1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/stat.h> 31*0Sstevel@tonic-gate #include <sys/mman.h> 32*0Sstevel@tonic-gate #include <ctf_impl.h> 33*0Sstevel@tonic-gate #include <unistd.h> 34*0Sstevel@tonic-gate #include <fcntl.h> 35*0Sstevel@tonic-gate #include <errno.h> 36*0Sstevel@tonic-gate #include <dlfcn.h> 37*0Sstevel@tonic-gate #include <gelf.h> 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate #ifdef _LP64 40*0Sstevel@tonic-gate static const char *_libctf_zlib = "/usr/lib/64/libz.so"; 41*0Sstevel@tonic-gate #else 42*0Sstevel@tonic-gate static const char *_libctf_zlib = "/usr/lib/libz.so"; 43*0Sstevel@tonic-gate #endif 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate static struct { 46*0Sstevel@tonic-gate int (*z_uncompress)(uchar_t *, ulong_t *, const uchar_t *, ulong_t); 47*0Sstevel@tonic-gate const char *(*z_error)(int); 48*0Sstevel@tonic-gate void *z_dlp; 49*0Sstevel@tonic-gate } zlib; 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate static size_t _PAGESIZE; 52*0Sstevel@tonic-gate static size_t _PAGEMASK; 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate #pragma init(_libctf_init) 55*0Sstevel@tonic-gate void 56*0Sstevel@tonic-gate _libctf_init(void) 57*0Sstevel@tonic-gate { 58*0Sstevel@tonic-gate const char *p = getenv("LIBCTF_DECOMPRESSOR"); 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate if (p != NULL) 61*0Sstevel@tonic-gate _libctf_zlib = p; /* use alternate decompression library */ 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate _libctf_debug = getenv("LIBCTF_DEBUG") != NULL; 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate _PAGESIZE = getpagesize(); 66*0Sstevel@tonic-gate _PAGEMASK = ~(_PAGESIZE - 1); 67*0Sstevel@tonic-gate } 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* 70*0Sstevel@tonic-gate * Attempt to dlopen the decompression library and locate the symbols of 71*0Sstevel@tonic-gate * interest that we will need to call. This information in cached so 72*0Sstevel@tonic-gate * that multiple calls to ctf_bufopen() do not need to reopen the library. 73*0Sstevel@tonic-gate */ 74*0Sstevel@tonic-gate void * 75*0Sstevel@tonic-gate ctf_zopen(int *errp) 76*0Sstevel@tonic-gate { 77*0Sstevel@tonic-gate ctf_dprintf("decompressing CTF data using %s\n", _libctf_zlib); 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate if (zlib.z_dlp != NULL) 80*0Sstevel@tonic-gate return (zlib.z_dlp); /* library is already loaded */ 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate if (access(_libctf_zlib, R_OK) == -1) 83*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_ZMISSING)); 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate if ((zlib.z_dlp = dlopen(_libctf_zlib, RTLD_LAZY | RTLD_LOCAL)) == NULL) 86*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_ZINIT)); 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate zlib.z_uncompress = (int (*)()) dlsym(zlib.z_dlp, "uncompress"); 89*0Sstevel@tonic-gate zlib.z_error = (const char *(*)()) dlsym(zlib.z_dlp, "zError"); 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate if (zlib.z_uncompress == NULL || zlib.z_error == NULL) { 92*0Sstevel@tonic-gate (void) dlclose(zlib.z_dlp); 93*0Sstevel@tonic-gate bzero(&zlib, sizeof (zlib)); 94*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_ZINIT)); 95*0Sstevel@tonic-gate } 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate return (zlib.z_dlp); 98*0Sstevel@tonic-gate } 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate /* 101*0Sstevel@tonic-gate * The ctf_bufopen() routine calls these subroutines, defined by <sys/zmod.h>, 102*0Sstevel@tonic-gate * which we then patch through to the functions in the decompression library. 103*0Sstevel@tonic-gate */ 104*0Sstevel@tonic-gate int 105*0Sstevel@tonic-gate z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 106*0Sstevel@tonic-gate { 107*0Sstevel@tonic-gate return (zlib.z_uncompress(dst, (ulong_t *)dstlen, src, srclen)); 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate const char * 111*0Sstevel@tonic-gate z_strerror(int err) 112*0Sstevel@tonic-gate { 113*0Sstevel@tonic-gate return (zlib.z_error(err)); 114*0Sstevel@tonic-gate } 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate /* 117*0Sstevel@tonic-gate * Convert a 32-bit ELF file header into GElf. 118*0Sstevel@tonic-gate */ 119*0Sstevel@tonic-gate static void 120*0Sstevel@tonic-gate ehdr_to_gelf(const Elf32_Ehdr *src, GElf_Ehdr *dst) 121*0Sstevel@tonic-gate { 122*0Sstevel@tonic-gate bcopy(src->e_ident, dst->e_ident, EI_NIDENT); 123*0Sstevel@tonic-gate dst->e_type = src->e_type; 124*0Sstevel@tonic-gate dst->e_machine = src->e_machine; 125*0Sstevel@tonic-gate dst->e_version = src->e_version; 126*0Sstevel@tonic-gate dst->e_entry = (Elf64_Addr)src->e_entry; 127*0Sstevel@tonic-gate dst->e_phoff = (Elf64_Off)src->e_phoff; 128*0Sstevel@tonic-gate dst->e_shoff = (Elf64_Off)src->e_shoff; 129*0Sstevel@tonic-gate dst->e_flags = src->e_flags; 130*0Sstevel@tonic-gate dst->e_ehsize = src->e_ehsize; 131*0Sstevel@tonic-gate dst->e_phentsize = src->e_phentsize; 132*0Sstevel@tonic-gate dst->e_phnum = src->e_phnum; 133*0Sstevel@tonic-gate dst->e_shentsize = src->e_shentsize; 134*0Sstevel@tonic-gate dst->e_shnum = src->e_shnum; 135*0Sstevel@tonic-gate dst->e_shstrndx = src->e_shstrndx; 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate /* 139*0Sstevel@tonic-gate * Convert a 32-bit ELF section header into GElf. 140*0Sstevel@tonic-gate */ 141*0Sstevel@tonic-gate static void 142*0Sstevel@tonic-gate shdr_to_gelf(const Elf32_Shdr *src, GElf_Shdr *dst) 143*0Sstevel@tonic-gate { 144*0Sstevel@tonic-gate dst->sh_name = src->sh_name; 145*0Sstevel@tonic-gate dst->sh_type = src->sh_type; 146*0Sstevel@tonic-gate dst->sh_flags = src->sh_flags; 147*0Sstevel@tonic-gate dst->sh_addr = src->sh_addr; 148*0Sstevel@tonic-gate dst->sh_offset = src->sh_offset; 149*0Sstevel@tonic-gate dst->sh_size = src->sh_size; 150*0Sstevel@tonic-gate dst->sh_link = src->sh_link; 151*0Sstevel@tonic-gate dst->sh_info = src->sh_info; 152*0Sstevel@tonic-gate dst->sh_addralign = src->sh_addralign; 153*0Sstevel@tonic-gate dst->sh_entsize = src->sh_entsize; 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate /* 157*0Sstevel@tonic-gate * In order to mmap a section from the ELF file, we must round down sh_offset 158*0Sstevel@tonic-gate * to the previous page boundary, and mmap the surrounding page. We store 159*0Sstevel@tonic-gate * the pointer to the start of the actual section data back into sp->cts_data. 160*0Sstevel@tonic-gate */ 161*0Sstevel@tonic-gate const void * 162*0Sstevel@tonic-gate ctf_sect_mmap(ctf_sect_t *sp, int fd) 163*0Sstevel@tonic-gate { 164*0Sstevel@tonic-gate size_t pageoff = sp->cts_offset & ~_PAGEMASK; 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate caddr_t base = mmap64(NULL, sp->cts_size + pageoff, PROT_READ, 167*0Sstevel@tonic-gate MAP_PRIVATE, fd, sp->cts_offset & _PAGEMASK); 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate if (base != MAP_FAILED) 170*0Sstevel@tonic-gate sp->cts_data = base + pageoff; 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate return (base); 173*0Sstevel@tonic-gate } 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate /* 176*0Sstevel@tonic-gate * Since sp->cts_data has the adjusted offset, we have to again round down 177*0Sstevel@tonic-gate * to get the actual mmap address and round up to get the size. 178*0Sstevel@tonic-gate */ 179*0Sstevel@tonic-gate void 180*0Sstevel@tonic-gate ctf_sect_munmap(const ctf_sect_t *sp) 181*0Sstevel@tonic-gate { 182*0Sstevel@tonic-gate uintptr_t addr = (uintptr_t)sp->cts_data; 183*0Sstevel@tonic-gate uintptr_t pageoff = addr & ~_PAGEMASK; 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate (void) munmap((void *)(addr - pageoff), sp->cts_size + pageoff); 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate /* 189*0Sstevel@tonic-gate * Open the specified file descriptor and return a pointer to a CTF container. 190*0Sstevel@tonic-gate * The file can be either an ELF file or raw CTF file. The caller is 191*0Sstevel@tonic-gate * responsible for closing the file descriptor when it is no longer needed. 192*0Sstevel@tonic-gate */ 193*0Sstevel@tonic-gate ctf_file_t * 194*0Sstevel@tonic-gate ctf_fdopen(int fd, int *errp) 195*0Sstevel@tonic-gate { 196*0Sstevel@tonic-gate ctf_sect_t ctfsect, symsect, strsect; 197*0Sstevel@tonic-gate ctf_file_t *fp = NULL; 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate struct stat64 st; 200*0Sstevel@tonic-gate ssize_t nbytes; 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate union { 203*0Sstevel@tonic-gate ctf_preamble_t ctf; 204*0Sstevel@tonic-gate Elf32_Ehdr e32; 205*0Sstevel@tonic-gate GElf_Ehdr e64; 206*0Sstevel@tonic-gate } hdr; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate bzero(&ctfsect, sizeof (ctf_sect_t)); 209*0Sstevel@tonic-gate bzero(&symsect, sizeof (ctf_sect_t)); 210*0Sstevel@tonic-gate bzero(&strsect, sizeof (ctf_sect_t)); 211*0Sstevel@tonic-gate bzero(&hdr.ctf, sizeof (hdr)); 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate if (fstat64(fd, &st) == -1) 214*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, errno)); 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate if ((nbytes = pread64(fd, &hdr.ctf, sizeof (hdr), 0)) <= 0) 217*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, nbytes < 0? errno : ECTF_FMT)); 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate /* 220*0Sstevel@tonic-gate * If we have read enough bytes to form a CTF header and the magic 221*0Sstevel@tonic-gate * string matches, attempt to interpret the file as raw CTF. 222*0Sstevel@tonic-gate */ 223*0Sstevel@tonic-gate if (nbytes >= sizeof (ctf_preamble_t) && 224*0Sstevel@tonic-gate hdr.ctf.ctp_magic == CTF_MAGIC) { 225*0Sstevel@tonic-gate if (hdr.ctf.ctp_version > CTF_VERSION) 226*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CTFVERS)); 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate ctfsect.cts_data = mmap64(NULL, st.st_size, PROT_READ, 229*0Sstevel@tonic-gate MAP_PRIVATE, fd, 0); 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate if (ctfsect.cts_data == MAP_FAILED) 232*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, errno)); 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate ctfsect.cts_name = _CTF_SECTION; 235*0Sstevel@tonic-gate ctfsect.cts_type = SHT_PROGBITS; 236*0Sstevel@tonic-gate ctfsect.cts_flags = SHF_ALLOC; 237*0Sstevel@tonic-gate ctfsect.cts_size = (size_t)st.st_size; 238*0Sstevel@tonic-gate ctfsect.cts_entsize = 1; 239*0Sstevel@tonic-gate ctfsect.cts_offset = 0; 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate if ((fp = ctf_bufopen(&ctfsect, NULL, NULL, errp)) == NULL) 242*0Sstevel@tonic-gate ctf_sect_munmap(&ctfsect); 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate return (fp); 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate /* 248*0Sstevel@tonic-gate * If we have read enough bytes to form an ELF header and the magic 249*0Sstevel@tonic-gate * string matches, attempt to interpret the file as an ELF file. We 250*0Sstevel@tonic-gate * do our own largefile ELF processing, and convert everything to 251*0Sstevel@tonic-gate * GElf structures so that clients can operate on any data model. 252*0Sstevel@tonic-gate */ 253*0Sstevel@tonic-gate if (nbytes >= sizeof (Elf32_Ehdr) && 254*0Sstevel@tonic-gate bcmp(&hdr.e32.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0) { 255*0Sstevel@tonic-gate #ifdef _BIG_ENDIAN 256*0Sstevel@tonic-gate uchar_t order = ELFDATA2MSB; 257*0Sstevel@tonic-gate #else 258*0Sstevel@tonic-gate uchar_t order = ELFDATA2LSB; 259*0Sstevel@tonic-gate #endif 260*0Sstevel@tonic-gate GElf_Half i, n; 261*0Sstevel@tonic-gate GElf_Shdr *sp; 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate void *strs_map; 264*0Sstevel@tonic-gate size_t strs_mapsz; 265*0Sstevel@tonic-gate const char *strs; 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate if (hdr.e32.e_ident[EI_DATA] != order) 268*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_ENDIAN)); 269*0Sstevel@tonic-gate if (hdr.e32.e_version != EV_CURRENT) 270*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_ELFVERS)); 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS64) { 273*0Sstevel@tonic-gate if (nbytes < sizeof (GElf_Ehdr)) 274*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_FMT)); 275*0Sstevel@tonic-gate } else { 276*0Sstevel@tonic-gate Elf32_Ehdr e32 = hdr.e32; 277*0Sstevel@tonic-gate ehdr_to_gelf(&e32, &hdr.e64); 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate if (hdr.e64.e_shstrndx >= hdr.e64.e_shnum) 281*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate n = hdr.e64.e_shnum; 284*0Sstevel@tonic-gate nbytes = sizeof (GElf_Shdr) * n; 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate if ((sp = malloc(nbytes)) == NULL) 287*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, errno)); 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate /* 290*0Sstevel@tonic-gate * Read in and convert to GElf the array of Shdr structures 291*0Sstevel@tonic-gate * from e_shoff so we can locate sections of interest. 292*0Sstevel@tonic-gate */ 293*0Sstevel@tonic-gate if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) { 294*0Sstevel@tonic-gate Elf32_Shdr *sp32; 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate nbytes = sizeof (Elf32_Shdr) * n; 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate if ((sp32 = malloc(nbytes)) == NULL || pread64(fd, 299*0Sstevel@tonic-gate sp32, nbytes, hdr.e64.e_shoff) != nbytes) { 300*0Sstevel@tonic-gate free(sp); 301*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, errno)); 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate for (i = 0; i < n; i++) 305*0Sstevel@tonic-gate shdr_to_gelf(&sp32[i], &sp[i]); 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate free(sp32); 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate } else if (pread64(fd, sp, nbytes, hdr.e64.e_shoff) != nbytes) { 310*0Sstevel@tonic-gate free(sp); 311*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, errno)); 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* 315*0Sstevel@tonic-gate * Now mmap the section header strings section so that we can 316*0Sstevel@tonic-gate * perform string comparison on the section names. 317*0Sstevel@tonic-gate */ 318*0Sstevel@tonic-gate strs_mapsz = sp[hdr.e64.e_shstrndx].sh_size + 319*0Sstevel@tonic-gate (sp[hdr.e64.e_shstrndx].sh_offset & ~_PAGEMASK); 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate strs_map = mmap64(NULL, strs_mapsz, PROT_READ, MAP_PRIVATE, 322*0Sstevel@tonic-gate fd, sp[hdr.e64.e_shstrndx].sh_offset & _PAGEMASK); 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate strs = (const char *)strs_map + 325*0Sstevel@tonic-gate (sp[hdr.e64.e_shstrndx].sh_offset & ~_PAGEMASK); 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate if (strs_map == MAP_FAILED) { 328*0Sstevel@tonic-gate free(sp); 329*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_MMAP)); 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate /* 333*0Sstevel@tonic-gate * Iterate over the section header array looking for the CTF 334*0Sstevel@tonic-gate * section and symbol table. The strtab is linked to symtab. 335*0Sstevel@tonic-gate */ 336*0Sstevel@tonic-gate for (i = 0; i < n; i++) { 337*0Sstevel@tonic-gate const GElf_Shdr *shp = &sp[i]; 338*0Sstevel@tonic-gate const GElf_Shdr *lhp = &sp[shp->sh_link]; 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate if (shp->sh_link >= hdr.e64.e_shnum) 341*0Sstevel@tonic-gate continue; /* corrupt sh_link field */ 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate if (shp->sh_name >= sp[hdr.e64.e_shstrndx].sh_size || 344*0Sstevel@tonic-gate lhp->sh_name >= sp[hdr.e64.e_shstrndx].sh_size) 345*0Sstevel@tonic-gate continue; /* corrupt sh_name field */ 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate if (shp->sh_type == SHT_PROGBITS && 348*0Sstevel@tonic-gate strcmp(strs + shp->sh_name, _CTF_SECTION) == 0) { 349*0Sstevel@tonic-gate ctfsect.cts_name = strs + shp->sh_name; 350*0Sstevel@tonic-gate ctfsect.cts_type = shp->sh_type; 351*0Sstevel@tonic-gate ctfsect.cts_flags = shp->sh_flags; 352*0Sstevel@tonic-gate ctfsect.cts_size = shp->sh_size; 353*0Sstevel@tonic-gate ctfsect.cts_entsize = shp->sh_entsize; 354*0Sstevel@tonic-gate ctfsect.cts_offset = (off64_t)shp->sh_offset; 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate } else if (shp->sh_type == SHT_SYMTAB) { 357*0Sstevel@tonic-gate symsect.cts_name = strs + shp->sh_name; 358*0Sstevel@tonic-gate symsect.cts_type = shp->sh_type; 359*0Sstevel@tonic-gate symsect.cts_flags = shp->sh_flags; 360*0Sstevel@tonic-gate symsect.cts_size = shp->sh_size; 361*0Sstevel@tonic-gate symsect.cts_entsize = shp->sh_entsize; 362*0Sstevel@tonic-gate symsect.cts_offset = (off64_t)shp->sh_offset; 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate strsect.cts_name = strs + lhp->sh_name; 365*0Sstevel@tonic-gate strsect.cts_type = lhp->sh_type; 366*0Sstevel@tonic-gate strsect.cts_flags = lhp->sh_flags; 367*0Sstevel@tonic-gate strsect.cts_size = lhp->sh_size; 368*0Sstevel@tonic-gate strsect.cts_entsize = lhp->sh_entsize; 369*0Sstevel@tonic-gate strsect.cts_offset = (off64_t)lhp->sh_offset; 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate free(sp); /* free section header array */ 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate if (ctfsect.cts_type == SHT_NULL) { 376*0Sstevel@tonic-gate (void) munmap(strs_map, strs_mapsz); 377*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_NOCTFDATA)); 378*0Sstevel@tonic-gate } 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate /* 381*0Sstevel@tonic-gate * Now mmap the CTF data, symtab, and strtab sections and 382*0Sstevel@tonic-gate * call ctf_bufopen() to do the rest of the work. 383*0Sstevel@tonic-gate */ 384*0Sstevel@tonic-gate if (ctf_sect_mmap(&ctfsect, fd) == MAP_FAILED) { 385*0Sstevel@tonic-gate (void) munmap(strs_map, strs_mapsz); 386*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_MMAP)); 387*0Sstevel@tonic-gate } 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate if (symsect.cts_type != SHT_NULL && 390*0Sstevel@tonic-gate strsect.cts_type != SHT_NULL) { 391*0Sstevel@tonic-gate if (ctf_sect_mmap(&symsect, fd) == MAP_FAILED || 392*0Sstevel@tonic-gate ctf_sect_mmap(&strsect, fd) == MAP_FAILED) { 393*0Sstevel@tonic-gate (void) ctf_set_open_errno(errp, ECTF_MMAP); 394*0Sstevel@tonic-gate goto bad; /* unmap all and abort */ 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate fp = ctf_bufopen(&ctfsect, &symsect, &strsect, errp); 397*0Sstevel@tonic-gate } else 398*0Sstevel@tonic-gate fp = ctf_bufopen(&ctfsect, NULL, NULL, errp); 399*0Sstevel@tonic-gate bad: 400*0Sstevel@tonic-gate if (fp == NULL) { 401*0Sstevel@tonic-gate ctf_sect_munmap(&ctfsect); 402*0Sstevel@tonic-gate ctf_sect_munmap(&symsect); 403*0Sstevel@tonic-gate ctf_sect_munmap(&strsect); 404*0Sstevel@tonic-gate } else 405*0Sstevel@tonic-gate fp->ctf_flags |= LCTF_MMAP; 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate (void) munmap(strs_map, strs_mapsz); 408*0Sstevel@tonic-gate return (fp); 409*0Sstevel@tonic-gate } 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate return (ctf_set_open_errno(errp, ECTF_FMT)); 412*0Sstevel@tonic-gate } 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* 415*0Sstevel@tonic-gate * Open the specified file and return a pointer to a CTF container. The file 416*0Sstevel@tonic-gate * can be either an ELF file or raw CTF file. This is just a convenient 417*0Sstevel@tonic-gate * wrapper around ctf_fdopen() for callers. 418*0Sstevel@tonic-gate */ 419*0Sstevel@tonic-gate ctf_file_t * 420*0Sstevel@tonic-gate ctf_open(const char *filename, int *errp) 421*0Sstevel@tonic-gate { 422*0Sstevel@tonic-gate ctf_file_t *fp; 423*0Sstevel@tonic-gate int fd; 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate if ((fd = open64(filename, O_RDONLY)) == -1) { 426*0Sstevel@tonic-gate if (errp != NULL) 427*0Sstevel@tonic-gate *errp = errno; 428*0Sstevel@tonic-gate return (NULL); 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate fp = ctf_fdopen(fd, errp); 432*0Sstevel@tonic-gate (void) close(fd); 433*0Sstevel@tonic-gate return (fp); 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate /* 437*0Sstevel@tonic-gate * Write the uncompressed CTF data stream to the specified file descriptor. 438*0Sstevel@tonic-gate * This is useful for saving the results of dynamic CTF containers. 439*0Sstevel@tonic-gate */ 440*0Sstevel@tonic-gate int 441*0Sstevel@tonic-gate ctf_write(ctf_file_t *fp, int fd) 442*0Sstevel@tonic-gate { 443*0Sstevel@tonic-gate const uchar_t *buf = fp->ctf_base; 444*0Sstevel@tonic-gate ssize_t resid = fp->ctf_size; 445*0Sstevel@tonic-gate ssize_t len; 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate while (resid != 0) { 448*0Sstevel@tonic-gate if ((len = write(fd, buf, resid)) <= 0) 449*0Sstevel@tonic-gate return (ctf_set_errno(fp, errno)); 450*0Sstevel@tonic-gate resid -= len; 451*0Sstevel@tonic-gate buf += len; 452*0Sstevel@tonic-gate } 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate return (0); 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate /* 458*0Sstevel@tonic-gate * Set the CTF library client version to the specified version. If version is 459*0Sstevel@tonic-gate * zero, we just return the default library version number. 460*0Sstevel@tonic-gate */ 461*0Sstevel@tonic-gate int 462*0Sstevel@tonic-gate ctf_version(int version) 463*0Sstevel@tonic-gate { 464*0Sstevel@tonic-gate if (version < 0) { 465*0Sstevel@tonic-gate errno = EINVAL; 466*0Sstevel@tonic-gate return (-1); 467*0Sstevel@tonic-gate } 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate if (version > 0) { 470*0Sstevel@tonic-gate if (version > CTF_VERSION) { 471*0Sstevel@tonic-gate errno = ENOTSUP; 472*0Sstevel@tonic-gate return (-1); 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate ctf_dprintf("ctf_version: client using version %d\n", version); 475*0Sstevel@tonic-gate _libctf_version = version; 476*0Sstevel@tonic-gate } 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate return (_libctf_version); 479*0Sstevel@tonic-gate } 480