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
_libctf_init(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 *
ctf_zopen(int * errp)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
z_uncompress(void * dst,size_t * dstlen,const void * src,size_t srclen)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 *
z_strerror(int err)134 z_strerror(int err)
135 {
136 return (zlib.z_error(err));
137 }
138
139 static int
ctf_zdata_init(ctf_zdata_t * czd,ctf_file_t * fp)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
ctf_zdata_grow(ctf_zdata_t * czd)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
ctf_zdata_compress_buffer(ctf_zdata_t * czd,const void * buf,size_t bufsize)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
ctf_zdata_flush(ctf_zdata_t * czd,boolean_t finish)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
ctf_zdata_end(ctf_zdata_t * czd)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
ctf_zdata_cleanup(ctf_zdata_t * czd)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
ctf_compress(ctf_file_t * fp,void ** buf,size_t * allocsz,size_t * elfsize)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
z_compress(void * dst,size_t * dstlen,const void * src,size_t srclen)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
ehdr_to_gelf(const Elf32_Ehdr * src,GElf_Ehdr * dst)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
shdr_to_gelf(const Elf32_Shdr * src,GElf_Shdr * dst)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 *
ctf_sect_mmap(ctf_sect_t * sp,int fd)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
ctf_sect_munmap(const ctf_sect_t * sp)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 *
ctf_fdcreate_int(int fd,int * errp,ctf_sect_t * ctfp)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 *
ctf_fdopen(int fd,int * errp)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 *
ctf_open(const char * filename,int * errp)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
ctf_write(ctf_file_t * fp,int fd)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
ctf_version(int version)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
ctf_phase_dump(ctf_file_t * fp,const char * phase)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