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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright (c) 2015, Joyent, Inc. 28 */ 29 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <sys/mman.h> 33 #include <ctf_impl.h> 34 #include <unistd.h> 35 #include <fcntl.h> 36 #include <errno.h> 37 #include <dlfcn.h> 38 #include <gelf.h> 39 #include <zlib.h> 40 #include <sys/debug.h> 41 42 #ifdef _LP64 43 static const char *_libctf_zlib = "/usr/lib/64/libz.so.1"; 44 #else 45 static const char *_libctf_zlib = "/usr/lib/libz.so.1"; 46 #endif 47 48 static struct { 49 int (*z_uncompress)(uchar_t *, ulong_t *, const uchar_t *, ulong_t); 50 int (*z_initcomp)(z_stream *, int, const char *, int); 51 int (*z_compress)(z_stream *, int); 52 int (*z_finicomp)(z_stream *); 53 const char *(*z_error)(int); 54 void *z_dlp; 55 } zlib; 56 57 static size_t _PAGESIZE; 58 static size_t _PAGEMASK; 59 60 static uint64_t ctf_phase = 0; 61 62 #define CTF_COMPRESS_CHUNK (64*1024) 63 64 typedef struct ctf_zdata { 65 void *czd_buf; 66 void *czd_next; 67 ctf_file_t *czd_ctfp; 68 size_t czd_allocsz; 69 z_stream czd_zstr; 70 } ctf_zdata_t; 71 72 #pragma init(_libctf_init) 73 void 74 _libctf_init(void) 75 { 76 const char *p = getenv("LIBCTF_DECOMPRESSOR"); 77 78 if (p != NULL) 79 _libctf_zlib = p; /* use alternate decompression library */ 80 81 _libctf_debug = getenv("LIBCTF_DEBUG") != NULL; 82 83 _PAGESIZE = getpagesize(); 84 _PAGEMASK = ~(_PAGESIZE - 1); 85 } 86 87 /* 88 * Attempt to dlopen the decompression library and locate the symbols of 89 * interest that we will need to call. This information in cached so 90 * that multiple calls to ctf_bufopen() do not need to reopen the library. 91 */ 92 void * 93 ctf_zopen(int *errp) 94 { 95 ctf_dprintf("decompressing CTF data using %s\n", _libctf_zlib); 96 97 if (zlib.z_dlp != NULL) 98 return (zlib.z_dlp); /* library is already loaded */ 99 100 if (access(_libctf_zlib, R_OK) == -1) 101 return (ctf_set_open_errno(errp, ECTF_ZMISSING)); 102 103 if ((zlib.z_dlp = dlopen(_libctf_zlib, RTLD_LAZY | RTLD_LOCAL)) == NULL) 104 return (ctf_set_open_errno(errp, ECTF_ZINIT)); 105 106 zlib.z_uncompress = (int (*)()) dlsym(zlib.z_dlp, "uncompress"); 107 zlib.z_initcomp = (int (*)()) dlsym(zlib.z_dlp, "deflateInit_"); 108 zlib.z_compress = (int (*)()) dlsym(zlib.z_dlp, "deflate"); 109 zlib.z_finicomp = (int (*)()) dlsym(zlib.z_dlp, "deflateEnd"); 110 zlib.z_error = (const char *(*)()) dlsym(zlib.z_dlp, "zError"); 111 112 if (zlib.z_uncompress == NULL || zlib.z_error == NULL || 113 zlib.z_initcomp == NULL|| zlib.z_compress == NULL || 114 zlib.z_finicomp == NULL) { 115 (void) dlclose(zlib.z_dlp); 116 bzero(&zlib, sizeof (zlib)); 117 return (ctf_set_open_errno(errp, ECTF_ZINIT)); 118 } 119 120 return (zlib.z_dlp); 121 } 122 123 /* 124 * The ctf_bufopen() routine calls these subroutines, defined by <sys/zmod.h>, 125 * which we then patch through to the functions in the decompression library. 126 */ 127 int 128 z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 129 { 130 return (zlib.z_uncompress(dst, (ulong_t *)dstlen, src, srclen)); 131 } 132 133 const char * 134 z_strerror(int err) 135 { 136 return (zlib.z_error(err)); 137 } 138 139 static int 140 ctf_zdata_init(ctf_zdata_t *czd, ctf_file_t *fp) 141 { 142 ctf_header_t *cthp; 143 144 bzero(czd, sizeof (ctf_zdata_t)); 145 146 czd->czd_allocsz = fp->ctf_size; 147 czd->czd_buf = ctf_data_alloc(czd->czd_allocsz); 148 if (czd->czd_buf == MAP_FAILED) 149 return (ctf_set_errno(fp, ENOMEM)); 150 151 bcopy(fp->ctf_base, czd->czd_buf, sizeof (ctf_header_t)); 152 czd->czd_ctfp = fp; 153 cthp = czd->czd_buf; 154 cthp->cth_flags |= CTF_F_COMPRESS; 155 czd->czd_next = (void *)((uintptr_t)czd->czd_buf + 156 sizeof (ctf_header_t)); 157 158 if (zlib.z_initcomp(&czd->czd_zstr, Z_BEST_COMPRESSION, 159 ZLIB_VERSION, sizeof (z_stream)) != Z_OK) 160 return (ctf_set_errno(fp, ECTF_ZLIB)); 161 162 return (0); 163 } 164 165 static int 166 ctf_zdata_grow(ctf_zdata_t *czd) 167 { 168 size_t off; 169 size_t newsz; 170 void *ndata; 171 172 off = (uintptr_t)czd->czd_next - (uintptr_t)czd->czd_buf; 173 newsz = czd->czd_allocsz + CTF_COMPRESS_CHUNK; 174 ndata = ctf_data_alloc(newsz); 175 if (ndata == MAP_FAILED) { 176 return (ctf_set_errno(czd->czd_ctfp, ENOMEM)); 177 } 178 179 bcopy(czd->czd_buf, ndata, off); 180 ctf_data_free(czd->czd_buf, czd->czd_allocsz); 181 czd->czd_allocsz = newsz; 182 czd->czd_buf = ndata; 183 czd->czd_next = (void *)((uintptr_t)ndata + off); 184 185 czd->czd_zstr.next_out = (Bytef *)czd->czd_next; 186 czd->czd_zstr.avail_out = CTF_COMPRESS_CHUNK; 187 return (0); 188 } 189 190 static int 191 ctf_zdata_compress_buffer(ctf_zdata_t *czd, const void *buf, size_t bufsize) 192 { 193 int err; 194 195 czd->czd_zstr.next_out = czd->czd_next; 196 czd->czd_zstr.avail_out = czd->czd_allocsz - 197 ((uintptr_t)czd->czd_next - (uintptr_t)czd->czd_buf); 198 czd->czd_zstr.next_in = (Bytef *)buf; 199 czd->czd_zstr.avail_in = bufsize; 200 201 while (czd->czd_zstr.avail_in != 0) { 202 if (czd->czd_zstr.avail_out == 0) { 203 czd->czd_next = czd->czd_zstr.next_out; 204 if ((err = ctf_zdata_grow(czd)) != 0) { 205 return (err); 206 } 207 } 208 209 if ((err = zlib.z_compress(&czd->czd_zstr, Z_NO_FLUSH)) != Z_OK) 210 return (ctf_set_errno(czd->czd_ctfp, ECTF_ZLIB)); 211 } 212 czd->czd_next = czd->czd_zstr.next_out; 213 214 return (0); 215 } 216 217 static int 218 ctf_zdata_flush(ctf_zdata_t *czd, boolean_t finish) 219 { 220 int err; 221 int flag = finish == B_TRUE ? Z_FINISH : Z_FULL_FLUSH; 222 int bret = finish == B_TRUE ? Z_STREAM_END : Z_BUF_ERROR; 223 224 for (;;) { 225 if (czd->czd_zstr.avail_out == 0) { 226 czd->czd_next = czd->czd_zstr.next_out; 227 if ((err = ctf_zdata_grow(czd)) != 0) { 228 return (err); 229 } 230 } 231 232 err = zlib.z_compress(&czd->czd_zstr, flag); 233 if (err == bret) { 234 break; 235 } 236 if (err != Z_OK) 237 return (ctf_set_errno(czd->czd_ctfp, ECTF_ZLIB)); 238 239 } 240 241 czd->czd_next = czd->czd_zstr.next_out; 242 243 return (0); 244 } 245 246 static int 247 ctf_zdata_end(ctf_zdata_t *czd) 248 { 249 int ret; 250 251 if ((ret = ctf_zdata_flush(czd, B_TRUE)) != 0) 252 return (ret); 253 254 if ((ret = zlib.z_finicomp(&czd->czd_zstr)) != 0) 255 return (ctf_set_errno(czd->czd_ctfp, ECTF_ZLIB)); 256 257 return (0); 258 } 259 260 static void 261 ctf_zdata_cleanup(ctf_zdata_t *czd) 262 { 263 ctf_data_free(czd->czd_buf, czd->czd_allocsz); 264 (void) zlib.z_finicomp(&czd->czd_zstr); 265 } 266 267 /* 268 * Compress our CTF data and return both the size of the compressed data and the 269 * size of the allocation. These may be different due to the nature of 270 * compression. 271 * 272 * In addition, we flush the compression between our two phases such that we 273 * maintain a different dictionary between the CTF data and the string section. 274 */ 275 int 276 ctf_compress(ctf_file_t *fp, void **buf, size_t *allocsz, size_t *elfsize) 277 { 278 int err; 279 ctf_zdata_t czd; 280 ctf_header_t *cthp = (ctf_header_t *)fp->ctf_base; 281 282 if ((err = ctf_zdata_init(&czd, fp)) != 0) 283 return (err); 284 285 if ((err = ctf_zdata_compress_buffer(&czd, fp->ctf_buf, 286 cthp->cth_stroff)) != 0) { 287 ctf_zdata_cleanup(&czd); 288 return (err); 289 } 290 291 if ((err = ctf_zdata_flush(&czd, B_FALSE)) != 0) { 292 ctf_zdata_cleanup(&czd); 293 return (err); 294 } 295 296 if ((err = ctf_zdata_compress_buffer(&czd, 297 fp->ctf_buf + cthp->cth_stroff, cthp->cth_strlen)) != 0) { 298 ctf_zdata_cleanup(&czd); 299 return (err); 300 } 301 302 if ((err = ctf_zdata_end(&czd)) != 0) { 303 ctf_zdata_cleanup(&czd); 304 return (err); 305 } 306 307 *buf = czd.czd_buf; 308 *allocsz = czd.czd_allocsz; 309 *elfsize = (uintptr_t)czd.czd_next - (uintptr_t)czd.czd_buf; 310 311 return (0); 312 } 313 314 int 315 z_compress(void *dst, size_t *dstlen, const void *src, size_t srclen) 316 { 317 z_stream zs; 318 int err; 319 320 bzero(&zs, sizeof (z_stream)); 321 zs.next_in = (uchar_t *)src; 322 zs.avail_in = srclen; 323 zs.next_out = dst; 324 zs.avail_out = *dstlen; 325 326 if ((err = zlib.z_initcomp(&zs, Z_BEST_COMPRESSION, ZLIB_VERSION, 327 sizeof (z_stream))) != Z_OK) 328 return (err); 329 330 if ((err = zlib.z_compress(&zs, Z_FINISH)) != Z_STREAM_END) { 331 (void) zlib.z_finicomp(&zs); 332 return (err == Z_OK ? Z_BUF_ERROR : err); 333 } 334 335 *dstlen = zs.total_out; 336 return (zlib.z_finicomp(&zs)); 337 } 338 339 /* 340 * Convert a 32-bit ELF file header into GElf. 341 */ 342 static void 343 ehdr_to_gelf(const Elf32_Ehdr *src, GElf_Ehdr *dst) 344 { 345 bcopy(src->e_ident, dst->e_ident, EI_NIDENT); 346 dst->e_type = src->e_type; 347 dst->e_machine = src->e_machine; 348 dst->e_version = src->e_version; 349 dst->e_entry = (Elf64_Addr)src->e_entry; 350 dst->e_phoff = (Elf64_Off)src->e_phoff; 351 dst->e_shoff = (Elf64_Off)src->e_shoff; 352 dst->e_flags = src->e_flags; 353 dst->e_ehsize = src->e_ehsize; 354 dst->e_phentsize = src->e_phentsize; 355 dst->e_phnum = src->e_phnum; 356 dst->e_shentsize = src->e_shentsize; 357 dst->e_shnum = src->e_shnum; 358 dst->e_shstrndx = src->e_shstrndx; 359 } 360 361 /* 362 * Convert a 32-bit ELF section header into GElf. 363 */ 364 static void 365 shdr_to_gelf(const Elf32_Shdr *src, GElf_Shdr *dst) 366 { 367 dst->sh_name = src->sh_name; 368 dst->sh_type = src->sh_type; 369 dst->sh_flags = src->sh_flags; 370 dst->sh_addr = src->sh_addr; 371 dst->sh_offset = src->sh_offset; 372 dst->sh_size = src->sh_size; 373 dst->sh_link = src->sh_link; 374 dst->sh_info = src->sh_info; 375 dst->sh_addralign = src->sh_addralign; 376 dst->sh_entsize = src->sh_entsize; 377 } 378 379 /* 380 * In order to mmap a section from the ELF file, we must round down sh_offset 381 * to the previous page boundary, and mmap the surrounding page. We store 382 * the pointer to the start of the actual section data back into sp->cts_data. 383 */ 384 const void * 385 ctf_sect_mmap(ctf_sect_t *sp, int fd) 386 { 387 size_t pageoff = sp->cts_offset & ~_PAGEMASK; 388 389 caddr_t base = mmap64(NULL, sp->cts_size + pageoff, PROT_READ, 390 MAP_PRIVATE, fd, sp->cts_offset & _PAGEMASK); 391 392 if (base != MAP_FAILED) 393 sp->cts_data = base + pageoff; 394 395 return (base); 396 } 397 398 /* 399 * Since sp->cts_data has the adjusted offset, we have to again round down 400 * to get the actual mmap address and round up to get the size. 401 */ 402 void 403 ctf_sect_munmap(const ctf_sect_t *sp) 404 { 405 uintptr_t addr = (uintptr_t)sp->cts_data; 406 uintptr_t pageoff = addr & ~_PAGEMASK; 407 408 (void) munmap((void *)(addr - pageoff), sp->cts_size + pageoff); 409 } 410 411 /* 412 * Open the specified file descriptor and return a pointer to a CTF container. 413 * The file can be either an ELF file or raw CTF file. The caller is 414 * responsible for closing the file descriptor when it is no longer needed. 415 */ 416 ctf_file_t * 417 ctf_fdcreate_int(int fd, int *errp, ctf_sect_t *ctfp) 418 { 419 ctf_sect_t ctfsect, symsect, strsect; 420 ctf_file_t *fp = NULL; 421 size_t shstrndx, shnum; 422 423 struct stat64 st; 424 ssize_t nbytes; 425 426 union { 427 ctf_preamble_t ctf; 428 Elf32_Ehdr e32; 429 GElf_Ehdr e64; 430 } hdr; 431 432 bzero(&ctfsect, sizeof (ctf_sect_t)); 433 bzero(&symsect, sizeof (ctf_sect_t)); 434 bzero(&strsect, sizeof (ctf_sect_t)); 435 bzero(&hdr.ctf, sizeof (hdr)); 436 437 if (fstat64(fd, &st) == -1) 438 return (ctf_set_open_errno(errp, errno)); 439 440 if ((nbytes = pread64(fd, &hdr.ctf, sizeof (hdr), 0)) <= 0) 441 return (ctf_set_open_errno(errp, nbytes < 0? errno : ECTF_FMT)); 442 443 /* 444 * If we have read enough bytes to form a CTF header and the magic 445 * string matches, attempt to interpret the file as raw CTF. 446 */ 447 if (nbytes >= sizeof (ctf_preamble_t) && 448 hdr.ctf.ctp_magic == CTF_MAGIC) { 449 if (ctfp != NULL) 450 return (ctf_set_open_errno(errp, EINVAL)); 451 452 if (hdr.ctf.ctp_version > CTF_VERSION) 453 return (ctf_set_open_errno(errp, ECTF_CTFVERS)); 454 455 ctfsect.cts_data = mmap64(NULL, st.st_size, PROT_READ, 456 MAP_PRIVATE, fd, 0); 457 458 if (ctfsect.cts_data == MAP_FAILED) 459 return (ctf_set_open_errno(errp, errno)); 460 461 ctfsect.cts_name = _CTF_SECTION; 462 ctfsect.cts_type = SHT_PROGBITS; 463 ctfsect.cts_flags = SHF_ALLOC; 464 ctfsect.cts_size = (size_t)st.st_size; 465 ctfsect.cts_entsize = 1; 466 ctfsect.cts_offset = 0; 467 468 if ((fp = ctf_bufopen(&ctfsect, NULL, NULL, errp)) == NULL) 469 ctf_sect_munmap(&ctfsect); 470 471 return (fp); 472 } 473 474 /* 475 * If we have read enough bytes to form an ELF header and the magic 476 * string matches, attempt to interpret the file as an ELF file. We 477 * do our own largefile ELF processing, and convert everything to 478 * GElf structures so that clients can operate on any data model. 479 */ 480 if (nbytes >= sizeof (Elf32_Ehdr) && 481 bcmp(&hdr.e32.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0) { 482 #ifdef _BIG_ENDIAN 483 uchar_t order = ELFDATA2MSB; 484 #else 485 uchar_t order = ELFDATA2LSB; 486 #endif 487 GElf_Shdr *sp; 488 489 void *strs_map; 490 size_t strs_mapsz, i; 491 const char *strs; 492 493 if (hdr.e32.e_ident[EI_DATA] != order) 494 return (ctf_set_open_errno(errp, ECTF_ENDIAN)); 495 if (hdr.e32.e_version != EV_CURRENT) 496 return (ctf_set_open_errno(errp, ECTF_ELFVERS)); 497 498 if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS64) { 499 if (nbytes < sizeof (GElf_Ehdr)) 500 return (ctf_set_open_errno(errp, ECTF_FMT)); 501 } else { 502 Elf32_Ehdr e32 = hdr.e32; 503 ehdr_to_gelf(&e32, &hdr.e64); 504 } 505 506 shnum = hdr.e64.e_shnum; 507 shstrndx = hdr.e64.e_shstrndx; 508 509 /* Extended ELF sections */ 510 if ((shstrndx == SHN_XINDEX) || (shnum == 0)) { 511 if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) { 512 Elf32_Shdr x32; 513 514 if (pread64(fd, &x32, sizeof (x32), 515 hdr.e64.e_shoff) != sizeof (x32)) 516 return (ctf_set_open_errno(errp, 517 errno)); 518 519 shnum = x32.sh_size; 520 shstrndx = x32.sh_link; 521 } else { 522 Elf64_Shdr x64; 523 524 if (pread64(fd, &x64, sizeof (x64), 525 hdr.e64.e_shoff) != sizeof (x64)) 526 return (ctf_set_open_errno(errp, 527 errno)); 528 529 shnum = x64.sh_size; 530 shstrndx = x64.sh_link; 531 } 532 } 533 534 if (shstrndx >= shnum) 535 return (ctf_set_open_errno(errp, ECTF_CORRUPT)); 536 537 nbytes = sizeof (GElf_Shdr) * shnum; 538 539 if ((sp = malloc(nbytes)) == NULL) 540 return (ctf_set_open_errno(errp, errno)); 541 542 /* 543 * Read in and convert to GElf the array of Shdr structures 544 * from e_shoff so we can locate sections of interest. 545 */ 546 if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) { 547 Elf32_Shdr *sp32; 548 549 nbytes = sizeof (Elf32_Shdr) * shnum; 550 551 if ((sp32 = malloc(nbytes)) == NULL || pread64(fd, 552 sp32, nbytes, hdr.e64.e_shoff) != nbytes) { 553 free(sp); 554 return (ctf_set_open_errno(errp, errno)); 555 } 556 557 for (i = 0; i < shnum; i++) 558 shdr_to_gelf(&sp32[i], &sp[i]); 559 560 free(sp32); 561 562 } else if (pread64(fd, sp, nbytes, hdr.e64.e_shoff) != nbytes) { 563 free(sp); 564 return (ctf_set_open_errno(errp, errno)); 565 } 566 567 /* 568 * Now mmap the section header strings section so that we can 569 * perform string comparison on the section names. 570 */ 571 strs_mapsz = sp[shstrndx].sh_size + 572 (sp[shstrndx].sh_offset & ~_PAGEMASK); 573 574 strs_map = mmap64(NULL, strs_mapsz, PROT_READ, MAP_PRIVATE, 575 fd, sp[shstrndx].sh_offset & _PAGEMASK); 576 577 strs = (const char *)strs_map + 578 (sp[shstrndx].sh_offset & ~_PAGEMASK); 579 580 if (strs_map == MAP_FAILED) { 581 free(sp); 582 return (ctf_set_open_errno(errp, ECTF_MMAP)); 583 } 584 585 /* 586 * Iterate over the section header array looking for the CTF 587 * section and symbol table. The strtab is linked to symtab. 588 */ 589 for (i = 0; i < shnum; i++) { 590 const GElf_Shdr *shp = &sp[i]; 591 const GElf_Shdr *lhp = &sp[shp->sh_link]; 592 593 if (shp->sh_link >= shnum) 594 continue; /* corrupt sh_link field */ 595 596 if (shp->sh_name >= sp[shstrndx].sh_size || 597 lhp->sh_name >= sp[shstrndx].sh_size) 598 continue; /* corrupt sh_name field */ 599 600 if (shp->sh_type == SHT_PROGBITS && 601 strcmp(strs + shp->sh_name, _CTF_SECTION) == 0 && 602 ctfp == NULL) { 603 ctfsect.cts_name = strs + shp->sh_name; 604 ctfsect.cts_type = shp->sh_type; 605 ctfsect.cts_flags = shp->sh_flags; 606 ctfsect.cts_size = shp->sh_size; 607 ctfsect.cts_entsize = shp->sh_entsize; 608 ctfsect.cts_offset = (off64_t)shp->sh_offset; 609 610 } else if (shp->sh_type == SHT_SYMTAB) { 611 symsect.cts_name = strs + shp->sh_name; 612 symsect.cts_type = shp->sh_type; 613 symsect.cts_flags = shp->sh_flags; 614 symsect.cts_size = shp->sh_size; 615 symsect.cts_entsize = shp->sh_entsize; 616 symsect.cts_offset = (off64_t)shp->sh_offset; 617 618 strsect.cts_name = strs + lhp->sh_name; 619 strsect.cts_type = lhp->sh_type; 620 strsect.cts_flags = lhp->sh_flags; 621 strsect.cts_size = lhp->sh_size; 622 strsect.cts_entsize = lhp->sh_entsize; 623 strsect.cts_offset = (off64_t)lhp->sh_offset; 624 } 625 } 626 627 free(sp); /* free section header array */ 628 629 if (ctfp == NULL) { 630 if (ctfsect.cts_type == SHT_NULL && ctfp == NULL) { 631 (void) munmap(strs_map, strs_mapsz); 632 return (ctf_set_open_errno(errp, 633 ECTF_NOCTFDATA)); 634 } 635 636 /* 637 * Now mmap the CTF data, symtab, and strtab sections 638 * and call ctf_bufopen() to do the rest of the work. 639 */ 640 if (ctf_sect_mmap(&ctfsect, fd) == MAP_FAILED) { 641 (void) munmap(strs_map, strs_mapsz); 642 return (ctf_set_open_errno(errp, ECTF_MMAP)); 643 } 644 ctfp = &ctfsect; 645 } 646 647 if (symsect.cts_type != SHT_NULL && 648 strsect.cts_type != SHT_NULL) { 649 if (ctf_sect_mmap(&symsect, fd) == MAP_FAILED || 650 ctf_sect_mmap(&strsect, fd) == MAP_FAILED) { 651 (void) ctf_set_open_errno(errp, ECTF_MMAP); 652 goto bad; /* unmap all and abort */ 653 } 654 fp = ctf_bufopen(ctfp, &symsect, &strsect, errp); 655 } else 656 fp = ctf_bufopen(ctfp, NULL, NULL, errp); 657 bad: 658 if (fp == NULL) { 659 if (ctfp == NULL) 660 ctf_sect_munmap(&ctfsect); 661 ctf_sect_munmap(&symsect); 662 ctf_sect_munmap(&strsect); 663 } else 664 fp->ctf_flags |= LCTF_MMAP; 665 666 (void) munmap(strs_map, strs_mapsz); 667 return (fp); 668 } 669 670 return (ctf_set_open_errno(errp, ECTF_FMT)); 671 } 672 673 ctf_file_t * 674 ctf_fdopen(int fd, int *errp) 675 { 676 return (ctf_fdcreate_int(fd, errp, NULL)); 677 } 678 679 /* 680 * Open the specified file and return a pointer to a CTF container. The file 681 * can be either an ELF file or raw CTF file. This is just a convenient 682 * wrapper around ctf_fdopen() for callers. 683 */ 684 ctf_file_t * 685 ctf_open(const char *filename, int *errp) 686 { 687 ctf_file_t *fp; 688 int fd; 689 690 if ((fd = open64(filename, O_RDONLY)) == -1) { 691 if (errp != NULL) 692 *errp = errno; 693 return (NULL); 694 } 695 696 fp = ctf_fdopen(fd, errp); 697 (void) close(fd); 698 return (fp); 699 } 700 701 /* 702 * Write the uncompressed CTF data stream to the specified file descriptor. 703 * This is useful for saving the results of dynamic CTF containers. 704 */ 705 int 706 ctf_write(ctf_file_t *fp, int fd) 707 { 708 const uchar_t *buf = fp->ctf_base; 709 ssize_t resid = fp->ctf_size; 710 ssize_t len; 711 712 while (resid != 0) { 713 if ((len = write(fd, buf, resid)) <= 0) 714 return (ctf_set_errno(fp, errno)); 715 resid -= len; 716 buf += len; 717 } 718 719 return (0); 720 } 721 722 /* 723 * Set the CTF library client version to the specified version. If version is 724 * zero, we just return the default library version number. 725 */ 726 int 727 ctf_version(int version) 728 { 729 if (version < 0) { 730 errno = EINVAL; 731 return (-1); 732 } 733 734 if (version > 0) { 735 if (version > CTF_VERSION) { 736 errno = ENOTSUP; 737 return (-1); 738 } 739 ctf_dprintf("ctf_version: client using version %d\n", version); 740 _libctf_version = version; 741 } 742 743 return (_libctf_version); 744 } 745 746 /* 747 * A utility function for folks debugging CTF conversion and merging. 748 */ 749 void 750 ctf_phase_dump(ctf_file_t *fp, const char *phase) 751 { 752 int fd; 753 static char *base; 754 char path[MAXPATHLEN]; 755 756 if (base == NULL && (base = getenv("LIBCTF_WRITE_PHASES")) == NULL) 757 return; 758 759 (void) snprintf(path, sizeof (path), "%s/libctf.%s.%d.ctf", base, 760 phase != NULL ? phase : "", 761 ctf_phase); 762 if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0777)) < 0) 763 return; 764 (void) ctf_write(fp, fd); 765 (void) close(fd); 766 } 767