Bug Summary

File:src/usr.bin/ctfdump/ctfdump.c
Warning:line 169, column 2
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ctfdump.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/ctfdump/obj -resource-dir /usr/local/lib/clang/13.0.0 -D ZLIB -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused -fdebug-compilation-dir=/usr/src/usr.bin/ctfdump/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/ctfdump/ctfdump.c
1/* $OpenBSD: ctfdump.c,v 1.24 2019/09/03 10:32:15 mpi Exp $ */
2
3/*
4 * Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <sys/mman.h>
22#include <sys/ctf.h>
23
24#include <err.h>
25#include <fcntl.h>
26#include <gelf.h>
27#include <libelf.h>
28#include <locale.h>
29#include <stdio.h>
30#include <stdint.h>
31#include <stdlib.h>
32#include <string.h>
33#include <unistd.h>
34
35#ifdef ZLIB1
36#include <zlib.h>
37#endif /* ZLIB */
38
39#ifndef nitems
40#define nitems(_a)(sizeof((_a)) / sizeof((_a)[0])) (sizeof((_a)) / sizeof((_a)[0]))
41#endif
42
43#define DUMP_OBJECT(1 << 0) (1 << 0)
44#define DUMP_FUNCTION(1 << 1) (1 << 1)
45#define DUMP_HEADER(1 << 2) (1 << 2)
46#define DUMP_LABEL(1 << 3) (1 << 3)
47#define DUMP_STRTAB(1 << 4) (1 << 4)
48#define DUMP_STATISTIC(1 << 5) (1 << 5)
49#define DUMP_TYPE(1 << 6) (1 << 6)
50
51int dump(const char *, uint8_t);
52int isctf(const char *, size_t);
53__dead__attribute__((__noreturn__)) void usage(void);
54
55int ctf_dump(const char *, size_t, uint8_t);
56void ctf_dump_type(struct ctf_header *, const char *, off_t,
57 uint32_t, uint32_t *, uint32_t);
58const char *ctf_kind2name(uint16_t);
59const char *ctf_enc2name(uint16_t);
60const char *ctf_fpenc2name(uint16_t);
61const char *ctf_off2name(struct ctf_header *, const char *, off_t,
62 uint32_t);
63
64char *decompress(const char *, size_t, off_t);
65int elf_dump(uint8_t);
66const char *elf_idx2sym(size_t *, uint8_t);
67
68int
69main(int argc, char *argv[])
70{
71 const char *filename;
72 uint8_t flags = 0;
73 int ch, error = 0;
74
75 setlocale(LC_ALL0, "");
76
77 if (pledge("stdio rpath", NULL((void*)0)) == -1)
1
Assuming the condition is false
2
Taking false branch
78 err(1, "pledge");
79
80 while ((ch = getopt(argc, argv, "dfhlst")) != -1) {
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 105
81 switch (ch) {
82 case 'd':
83 flags |= DUMP_OBJECT(1 << 0);
84 break;
85 case 'f':
86 flags |= DUMP_FUNCTION(1 << 1);
87 break;
88 case 'h':
89 flags |= DUMP_HEADER(1 << 2);
90 break;
91 case 'l':
92 flags |= DUMP_LABEL(1 << 3);
93 break;
94 case 's':
95 flags |= DUMP_STRTAB(1 << 4);
96 break;
97 case 't':
98 flags |= DUMP_TYPE(1 << 6);
99 break;
100 default:
101 usage();
102 }
103 }
104
105 argc -= optind;
106 argv += optind;
107
108 if (argc <= 0)
5
Assuming 'argc' is > 0
6
Taking false branch
109 usage();
110
111 /* Dump everything by default */
112 if (flags
6.1
'flags' is equal to 0
== 0)
7
Taking true branch
113 flags = 0xff;
114
115 if (elf_version(EV_CURRENT1) == EV_NONE0)
8
Assuming the condition is false
9
Taking false branch
116 errx(1, "elf_version: %s", elf_errmsg(-1));
117
118 while ((filename = *argv++) != NULL((void*)0))
10
Assuming the condition is true
11
Loop condition is true. Entering loop body
119 error |= dump(filename, flags);
12
Calling 'dump'
120
121 return error;
122}
123
124Elf *e;
125Elf_Scn *scnsymtab;
126size_t strtabndx, strtabsz, nsymb;
127
128int
129dump(const char *path, uint8_t flags)
130{
131 struct stat st;
132 char *p;
133 int fd, error = 1;
134
135 fd = open(path, O_RDONLY0x0000);
136 if (fd == -1) {
13
Assuming the condition is false
14
Taking false branch
137 warn("open");
138 return 1;
139 }
140
141 if ((e = elf_begin(fd, ELF_C_READ, NULL((void*)0))) == NULL((void*)0)) {
15
Assuming the condition is false
16
Taking false branch
142 warnx("elf_begin: %s", elf_errmsg(-1));
143 goto done;
144 }
145
146 if (elf_kind(e) == ELF_K_ELF) {
17
Assuming the condition is false
18
Taking false branch
147 error = elf_dump(flags);
148 elf_end(e);
149 goto done;
150 }
151 elf_end(e);
152
153 if (fstat(fd, &st) == -1) {
19
Assuming the condition is false
20
Taking false branch
154 warn("fstat");
155 goto done;
156 }
157 if ((uintmax_t)st.st_size
20.1
Field 'st_size' is <= SIZE_MAX
> SIZE_MAX0xffffffffffffffffUL) {
21
Taking false branch
158 warnx("file too big to fit memory");
159 goto done;
160 }
161
162 p = mmap(NULL((void*)0), st.st_size, PROT_READ0x01, MAP_PRIVATE0x0002, fd, 0);
163 if (p == MAP_FAILED((void *)-1))
22
Assuming the condition is false
23
Taking false branch
164 err(1, "mmap");
165
166 if (isctf(p, st.st_size))
24
Taking true branch
167 error = ctf_dump(p, st.st_size, flags);
25
Calling 'ctf_dump'
47
Returning; memory was released via 1st parameter
168
169 munmap(p, st.st_size);
48
Use of memory after it is freed
170
171 done:
172 close(fd);
173 return error;
174}
175
176const char *
177elf_idx2sym(size_t *idx, uint8_t type)
178{
179 GElf_Sym sym;
180 Elf_Data *data;
181 char *name;
182 size_t i;
183
184 if (scnsymtab == NULL((void*)0) || strtabndx == 0)
185 return NULL((void*)0);
186
187 data = NULL((void*)0);
188 while ((data = elf_rawdata(scnsymtab, data)) != NULL((void*)0)) {
189 for (i = *idx + 1; i < nsymb; i++) {
190 if (gelf_getsym(data, i, &sym) != &sym)
191 continue;
192 if (GELF_ST_TYPE(sym.st_info)(((unsigned int) sym.st_info) & 0xf) != type)
193 continue;
194 if (sym.st_name >= strtabsz)
195 break;
196 if ((name = elf_strptr(e, strtabndx,
197 sym.st_name)) == NULL((void*)0))
198 continue;
199
200 *idx = i;
201 return name;
202 }
203 }
204
205 return NULL((void*)0);
206}
207
208int
209elf_dump(uint8_t flags)
210{
211 GElf_Shdr shdr;
212 Elf_Scn *scn, *scnctf;
213 Elf_Data *data;
214 char *name;
215 size_t shstrndx;
216 int error = 0;
217
218 if (elf_getshdrstrndx(e, &shstrndx) != 0) {
219 warnx("elf_getshdrstrndx: %s", elf_errmsg(-1));
220 return 1;
221 }
222
223 scn = scnctf = NULL((void*)0);
224 while ((scn = elf_nextscn(e, scn)) != NULL((void*)0)) {
225 if (gelf_getshdr(scn, &shdr) != &shdr) {
226 warnx("elf_getshdr: %s", elf_errmsg(-1));
227 return 1;
228 }
229
230 if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL((void*)0)) {
231 warnx("elf_strptr: %s", elf_errmsg(-1));
232 return 1;
233 }
234
235 if (strcmp(name, ELF_CTF".SUNW_ctf") == 0)
236 scnctf = scn;
237
238 if (strcmp(name, ELF_SYMTAB".symtab") == 0 &&
239 shdr.sh_type == SHT_SYMTAB2 && shdr.sh_entsize != 0) {
240 scnsymtab = scn;
241 nsymb = shdr.sh_size / shdr.sh_entsize;
242 }
243
244 if (strcmp(name, ELF_STRTAB".strtab") == 0 &&
245 shdr.sh_type == SHT_STRTAB3) {
246 strtabndx = elf_ndxscn(scn);
247 strtabsz = shdr.sh_size;
248 }
249 }
250
251 if (scnctf == NULL((void*)0)) {
252 warnx("%s section not found", ELF_CTF".SUNW_ctf");
253 return 1;
254 }
255
256 if (scnsymtab == NULL((void*)0))
257 warnx("symbol table not found");
258
259 data = NULL((void*)0);
260 while ((data = elf_rawdata(scnctf, data)) != NULL((void*)0)) {
261 if (data->d_buf == NULL((void*)0)) {
262 warnx("%s section size is zero", ELF_CTF".SUNW_ctf");
263 return 1;
264 }
265
266 if (isctf(data->d_buf, data->d_size))
267 error |= ctf_dump(data->d_buf, data->d_size, flags);
268 }
269
270 return error;
271}
272
273int
274isctf(const char *p, size_t filesize)
275{
276 struct ctf_header *cth = (struct ctf_header *)p;
277 off_t dlen;
278
279 if (filesize < sizeof(struct ctf_header)) {
280 warnx("file too small to be CTF");
281 return 0;
282 }
283
284 if (cth->cth_magic != CTF_MAGIC0xcff1 || cth->cth_version != CTF_VERSION2)
285 return 0;
286
287 dlen = (off_t)cth->cth_stroff + cth->cth_strlen;
288 if (dlen > (off_t)filesize && !(cth->cth_flags & CTF_F_COMPRESS(1 << 0))) {
289 warnx("bogus file size");
290 return 0;
291 }
292
293 if ((cth->cth_lbloff & 3) || (cth->cth_objtoff & 1) ||
294 (cth->cth_funcoff & 1) || (cth->cth_typeoff & 3)) {
295 warnx("wrongly aligned offset");
296 return 0;
297 }
298
299 if ((cth->cth_lbloff >= dlen) || (cth->cth_objtoff >= dlen) ||
300 (cth->cth_funcoff >= dlen) || (cth->cth_typeoff >= dlen)) {
301 warnx("truncated file");
302 return 0;
303 }
304
305 if ((cth->cth_lbloff > cth->cth_objtoff) ||
306 (cth->cth_objtoff > cth->cth_funcoff) ||
307 (cth->cth_funcoff > cth->cth_typeoff) ||
308 (cth->cth_typeoff > cth->cth_stroff)) {
309 warnx("corrupted file");
310 return 0;
311 }
312
313 return 1;
314}
315
316int
317ctf_dump(const char *p, size_t size, uint8_t flags)
318{
319 struct ctf_header *cth = (struct ctf_header *)p;
320 off_t dlen;
321 char *data;
322
323 dlen = (off_t)cth->cth_stroff + cth->cth_strlen;
324 if (cth->cth_flags & CTF_F_COMPRESS(1 << 0)) {
26
Assuming the condition is false
27
Taking false branch
325 data = decompress(p + sizeof(*cth), size - sizeof(*cth), dlen);
326 if (data == NULL((void*)0))
327 return 1;
328 } else {
329 data = (char *)p + sizeof(*cth);
330 }
331
332 if (flags & DUMP_HEADER(1 << 2)) {
28
Taking true branch
333 printf(" cth_magic = 0x%04x\n", cth->cth_magic);
334 printf(" cth_version = %u\n", cth->cth_version);
335 printf(" cth_flags = 0x%02x\n", cth->cth_flags);
336 printf(" cth_parlabel = %s\n",
337 ctf_off2name(cth, data, dlen, cth->cth_parlabel));
338 printf(" cth_parname = %s\n",
339 ctf_off2name(cth, data, dlen, cth->cth_parname));
340 printf(" cth_lbloff = %u\n", cth->cth_lbloff);
341 printf(" cth_objtoff = %u\n", cth->cth_objtoff);
342 printf(" cth_funcoff = %u\n", cth->cth_funcoff);
343 printf(" cth_typeoff = %u\n", cth->cth_typeoff);
344 printf(" cth_stroff = %u\n", cth->cth_stroff);
345 printf(" cth_strlen = %u\n", cth->cth_strlen);
346 printf("\n");
347 }
348
349 if (flags & DUMP_LABEL(1 << 3)) {
29
Taking true branch
350 uint32_t lbloff = cth->cth_lbloff;
351 struct ctf_lblent *ctl;
352
353 while (lbloff < cth->cth_objtoff) {
30
Assuming 'lbloff' is >= field 'cth_objtoff'
31
Loop condition is false. Execution continues on line 361
354 ctl = (struct ctf_lblent *)(data + lbloff);
355
356 printf(" %5u %s\n", ctl->ctl_typeidx,
357 ctf_off2name(cth, data, dlen, ctl->ctl_label));
358
359 lbloff += sizeof(*ctl);
360 }
361 printf("\n");
362 }
363
364 if (flags & DUMP_OBJECT(1 << 0)) {
32
Taking true branch
365 uint32_t objtoff = cth->cth_objtoff;
366 size_t idx = 0, i = 0;
367 uint16_t *dsp;
368 const char *s;
369 int l;
370
371 while (objtoff < cth->cth_funcoff) {
33
Assuming 'objtoff' is >= field 'cth_funcoff'
34
Loop condition is false. Execution continues on line 382
372 dsp = (uint16_t *)(data + objtoff);
373
374 l = printf(" [%zu] %u", i++, *dsp);
375 if ((s = elf_idx2sym(&idx, STT_OBJECT1)) != NULL((void*)0))
376 printf("%*s %s (%zu)\n", (14 - l), "", s, idx);
377 else
378 printf("\n");
379
380 objtoff += sizeof(*dsp);
381 }
382 printf("\n");
383 }
384
385 if (flags & DUMP_FUNCTION(1 << 1)) {
35
Taking true branch
386 uint16_t *fsp, kind, vlen;
387 uint16_t *fstart, *fend;
388 size_t idx = 0, i = -1;
389 const char *s;
390 int l;
391
392 fstart = (uint16_t *)(data + cth->cth_funcoff);
393 fend = (uint16_t *)(data + cth->cth_typeoff);
394
395 fsp = fstart;
396 while (fsp < fend) {
36
Assuming 'fsp' is >= 'fend'
37
Loop condition is false. Execution continues on line 414
397 kind = CTF_INFO_KIND(*fsp)(((*fsp) & 0xf800) >> 11);
398 vlen = CTF_INFO_VLEN(*fsp)(((*fsp) & 0x03ff));
399 s = elf_idx2sym(&idx, STT_FUNC2);
400 fsp++;
401 i++;
402
403 if (kind == CTF_K_UNKNOWN0 && vlen == 0)
404 continue;
405
406 l = printf(" [%zu] FUNC ", i);
407 if (s != NULL((void*)0))
408 printf("(%s) ", s);
409 printf("returns: %u args: (", *fsp++);
410 while (vlen-- > 0 && fsp < fend)
411 printf("%u%s", *fsp++, (vlen > 0) ? ", " : "");
412 printf(")\n");
413 }
414 printf("\n");
415 }
416
417 if (flags & DUMP_TYPE(1 << 6)) {
38
Taking true branch
418 uint32_t idx = 1, offset = cth->cth_typeoff;
419 uint32_t stroff = cth->cth_stroff;
420
421 while (offset < stroff) {
39
Assuming 'offset' is >= 'stroff'
40
Loop condition is false. Execution continues on line 424
422 ctf_dump_type(cth, data, dlen, stroff, &offset, idx++);
423 }
424 printf("\n");
425 }
426
427 if (flags & DUMP_STRTAB(1 << 4)) {
41
Taking true branch
428 uint32_t offset = 0;
429 const char *str;
430
431 while (offset < cth->cth_strlen) {
42
Assuming 'offset' is >= field 'cth_strlen'
43
Loop condition is false. Execution continues on line 442
432 str = ctf_off2name(cth, data, dlen, offset);
433
434 printf(" [%u] ", offset);
435 if (strcmp(str, "(anon)"))
436 offset += printf("%s\n", str);
437 else {
438 printf("\\0\n");
439 offset++;
440 }
441 }
442 printf("\n");
443 }
444
445 if (cth->cth_flags & CTF_F_COMPRESS(1 << 0))
44
Assuming the condition is true
45
Taking true branch
446 free(data);
46
Memory is released
447
448 return 0;
449}
450
451void
452ctf_dump_type(struct ctf_header *cth, const char *data, off_t dlen,
453 uint32_t stroff, uint32_t *offset, uint32_t idx)
454{
455 const char *p = data + *offset;
456 const struct ctf_type *ctt = (struct ctf_type *)p;
457 const struct ctf_array *cta;
458 uint16_t *argp, i, kind, vlen, root;
459 uint32_t eob, toff;
460 uint64_t size;
461 const char *name, *kname;
462
463 kind = CTF_INFO_KIND(ctt->ctt_info)(((ctt->_ctt_stype.cts_info) & 0xf800) >> 11);
464 vlen = CTF_INFO_VLEN(ctt->ctt_info)(((ctt->_ctt_stype.cts_info) & 0x03ff));
465 root = CTF_INFO_ISROOT(ctt->ctt_info)(((ctt->_ctt_stype.cts_info) & 0x0400) >> 10);
466 name = ctf_off2name(cth, data, dlen, ctt->ctt_name_ctt_stype.cts_name);
467
468 if (root)
469 printf(" <%u> ", idx);
470 else
471 printf(" [%u] ", idx);
472
473 if ((kname = ctf_kind2name(kind)) != NULL((void*)0))
474 printf("%s %s", kname, name);
475
476 if (ctt->ctt_size_ctt_stype._ST._size <= CTF_MAX_SIZE0xfffe) {
477 size = ctt->ctt_size_ctt_stype._ST._size;
478 toff = sizeof(struct ctf_stype);
479 } else {
480 size = CTF_TYPE_LSIZE(ctt)(((uint64_t)(ctt)->ctt_lsizehi) << 32 | (ctt)->ctt_lsizelo
)
;
481 toff = sizeof(struct ctf_type);
482 }
483
484 switch (kind) {
485 case CTF_K_UNKNOWN0:
486 case CTF_K_FORWARD9:
487 break;
488 case CTF_K_INTEGER1:
489 eob = *((uint32_t *)(p + toff));
490 toff += sizeof(uint32_t);
491 printf(" encoding=%s offset=%u bits=%u",
492 ctf_enc2name(CTF_INT_ENCODING(eob)(((eob) & 0xff000000) >> 24)), CTF_INT_OFFSET(eob)(((eob) & 0x00ff0000) >> 16),
493 CTF_INT_BITS(eob)(((eob) & 0x0000ffff)));
494 break;
495 case CTF_K_FLOAT2:
496 eob = *((uint32_t *)(p + toff));
497 toff += sizeof(uint32_t);
498 printf(" encoding=%s offset=%u bits=%u",
499 ctf_fpenc2name(CTF_FP_ENCODING(eob)(((eob) & 0xff000000) >> 24)), CTF_FP_OFFSET(eob)(((eob) & 0x00ff0000) >> 16),
500 CTF_FP_BITS(eob)(((eob) & 0x0000ffff)));
501 break;
502 case CTF_K_ARRAY4:
503 cta = (struct ctf_array *)(p + toff);
504 printf(" content: %u index: %u nelems: %u\n", cta->cta_contents,
505 cta->cta_index, cta->cta_nelems);
506 toff += sizeof(struct ctf_array);
507 break;
508 case CTF_K_FUNCTION5:
509 argp = (uint16_t *)(p + toff);
510 printf(" returns: %u args: (%u", ctt->ctt_type_ctt_stype._ST._type, *argp);
511 for (i = 1; i < vlen; i++) {
512 argp++;
513 if ((const char *)argp > data + dlen)
514 errx(1, "offset exceeds CTF section");
515
516 printf(", %u", *argp);
517 }
518 printf(")");
519 toff += (vlen + (vlen & 1)) * sizeof(uint16_t);
520 break;
521 case CTF_K_STRUCT6:
522 case CTF_K_UNION7:
523 printf(" (%llu bytes)\n", size);
524
525 if (size < CTF_LSTRUCT_THRESH8192) {
526 for (i = 0; i < vlen; i++) {
527 struct ctf_member *ctm;
528
529 if (p + toff > data + dlen)
530 errx(1, "offset exceeds CTF section");
531
532 if (toff > (stroff - sizeof(*ctm)))
533 break;
534
535 ctm = (struct ctf_member *)(p + toff);
536 toff += sizeof(struct ctf_member);
537
538 printf("\t%s type=%u off=%u\n",
539 ctf_off2name(cth, data, dlen,
540 ctm->ctm_name),
541 ctm->ctm_type, ctm->ctm_offset);
542 }
543 } else {
544 for (i = 0; i < vlen; i++) {
545 struct ctf_lmember *ctlm;
546
547 if (p + toff > data + dlen)
548 errx(1, "offset exceeds CTF section");
549
550 if (toff > (stroff - sizeof(*ctlm)))
551 break;
552
553 ctlm = (struct ctf_lmember *)(p + toff);
554 toff += sizeof(struct ctf_lmember);
555
556 printf("\t%s type=%u off=%llu\n",
557 ctf_off2name(cth, data, dlen,
558 ctlm->ctlm_name_ctlm_member.ctm_name),
559 ctlm->ctlm_type_ctlm_member.ctm_type, CTF_LMEM_OFFSET(ctlm)(((uint64_t)(ctlm)->ctlm_offsethi) << 32 | (ctlm)->
ctlm_offsetlo)
);
560 }
561 }
562 break;
563 case CTF_K_ENUM8:
564 printf("\n");
565 for (i = 0; i < vlen; i++) {
566 struct ctf_enum *cte;
567
568 if (p + toff > data + dlen)
569 errx(1, "offset exceeds CTF section");
570
571 if (toff > (stroff - sizeof(*cte)))
572 break;
573
574 cte = (struct ctf_enum *)(p + toff);
575 toff += sizeof(struct ctf_enum);
576
577 printf("\t%s = %d\n",
578 ctf_off2name(cth, data, dlen, cte->cte_name),
579 cte->cte_value);
580 }
581 break;
582 case CTF_K_POINTER3:
583 case CTF_K_TYPEDEF10:
584 case CTF_K_VOLATILE11:
585 case CTF_K_CONST12:
586 case CTF_K_RESTRICT13:
587 printf(" refers to %u", ctt->ctt_type_ctt_stype._ST._type);
588 break;
589 default:
590 errx(1, "incorrect type %u at offset %u", kind, *offset);
591 }
592
593 printf("\n");
594
595 *offset += toff;
596}
597
598const char *
599ctf_kind2name(uint16_t kind)
600{
601 static const char *kind_name[] = { NULL((void*)0), "INTEGER", "FLOAT", "POINTER",
602 "ARRAY", "FUNCTION", "STRUCT", "UNION", "ENUM", "FORWARD",
603 "TYPEDEF", "VOLATILE", "CONST", "RESTRICT" };
604
605 if (kind >= nitems(kind_name)(sizeof((kind_name)) / sizeof((kind_name)[0])))
606 return NULL((void*)0);
607
608 return kind_name[kind];
609}
610
611const char *
612ctf_enc2name(uint16_t enc)
613{
614 static const char *enc_name[] = { "SIGNED", "CHAR", "SIGNED CHAR",
615 "BOOL", "SIGNED BOOL" };
616 static char invalid[7];
617
618 if (enc == CTF_INT_VARARGS(1 << 3))
619 return "VARARGS";
620
621 if (enc > 0 && enc <= nitems(enc_name)(sizeof((enc_name)) / sizeof((enc_name)[0])))
622 return enc_name[enc - 1];
623
624 snprintf(invalid, sizeof(invalid), "0x%x", enc);
625 return invalid;
626}
627
628const char *
629ctf_fpenc2name(uint16_t enc)
630{
631 static const char *enc_name[] = { "SINGLE", "DOUBLE", NULL((void*)0), NULL((void*)0),
632 NULL((void*)0), "LDOUBLE" };
633 static char invalid[7];
634
635 if (enc > 0 && enc <= nitems(enc_name)(sizeof((enc_name)) / sizeof((enc_name)[0])) && enc_name[enc - 1] != NULL((void*)0))
636 return enc_name[enc - 1];
637
638 snprintf(invalid, sizeof(invalid), "0x%x", enc);
639 return invalid;
640}
641
642const char *
643ctf_off2name(struct ctf_header *cth, const char *data, off_t dlen,
644 uint32_t offset)
645{
646 const char *name;
647
648 if (CTF_NAME_STID(offset)((offset) >> 31) != CTF_STRTAB_00)
649 return "external";
650
651 if (CTF_NAME_OFFSET(offset)((offset) & 0x7fffffff) >= cth->cth_strlen)
652 return "exceeds strlab";
653
654 if (cth->cth_stroff + CTF_NAME_OFFSET(offset)((offset) & 0x7fffffff) >= dlen)
655 return "invalid";
656
657 name = data + cth->cth_stroff + CTF_NAME_OFFSET(offset)((offset) & 0x7fffffff);
658 if (*name == '\0')
659 return "(anon)";
660
661 return name;
662}
663
664char *
665decompress(const char *buf, size_t size, off_t len)
666{
667#ifdef ZLIB1
668 z_stream stream;
669 char *data;
670 int error;
671
672 data = malloc(len);
673 if (data == NULL((void*)0)) {
674 warn(NULL((void*)0));
675 return NULL((void*)0);
676 }
677
678 memset(&stream, 0, sizeof(stream));
679 stream.next_in = (void *)buf;
680 stream.avail_in = size;
681 stream.next_out = (uint8_t *)data;
682 stream.avail_out = len;
683
684 if ((error = inflateInit(&stream)inflateInit_((&stream), "1.2.11", (int)sizeof(z_stream))) != Z_OK0) {
685 warnx("zlib inflateInit failed: %s", zError(error));
686 goto exit;
687 }
688
689 if ((error = inflate(&stream, Z_FINISH4)) != Z_STREAM_END1) {
690 warnx("zlib inflate failed: %s", zError(error));
691 inflateEnd(&stream);
692 goto exit;
693 }
694
695 if ((error = inflateEnd(&stream)) != Z_OK0) {
696 warnx("zlib inflateEnd failed: %s", zError(error));
697 goto exit;
698 }
699
700 if (stream.total_out != len) {
701 warnx("decompression failed: %llu != %llu",
702 stream.total_out, len);
703 goto exit;
704 }
705
706 return data;
707
708exit:
709 free(data);
710#endif /* ZLIB */
711 return NULL((void*)0);
712}
713
714__dead__attribute__((__noreturn__)) void
715usage(void)
716{
717 fprintf(stderr(&__sF[2]), "usage: %s [-dfhlst] file ...\n",
718 getprogname());
719 exit(1);
720}