xref: /titanic_51/usr/src/lib/libctf/common/ctf_lib.c (revision 7fd791373689a6af05e27efec3b1ab556e02aa23)
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