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.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctfdump.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/llvm16/lib/clang/16 -D ZLIB -internal-isystem /usr/local/llvm16/lib/clang/16/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 -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/ctfdump/ctfdump.c
1/* $OpenBSD: ctfdump.c,v 1.27 2022/08/14 15:01:18 millert 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 *, size_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 *, size_t,
62 uint32_t);
63
64char *decompress(const char *, size_t, size_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
12
Assuming the condition is true
13
Loop condition is true. Entering loop body
14
Assuming the condition is true
15
Loop condition is true. Entering loop body
119 error |= dump(filename, flags);
16
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) {
17
Assuming the condition is false
18
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)) {
19
Assuming the condition is false
20
Taking false branch
142 warnx("elf_begin: %s", elf_errmsg(-1));
143 goto done;
144 }
145
146 if (elf_kind(e) == ELF_K_ELF) {
21
Assuming the condition is false
22
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) {
23
Assuming the condition is false
24
Taking false branch
154 warn("fstat");
155 goto done;
156 }
157 if ((uintmax_t)st.st_size > SIZE_MAX0xffffffffffffffffUL) {
25
Assuming field 'st_size' is <= SIZE_MAX
26
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))
27
Assuming the condition is false
28
Taking false branch
164 err(1, "mmap");
165
166 if (isctf(p, st.st_size))
29
Taking true branch
167 error = ctf_dump(p, st.st_size, flags);
30
Calling 'ctf_dump'
54
Returning; memory was released via 1st parameter
168
169 munmap(p, st.st_size);
55
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;
277 size_t dlen;
278
279 if (filesize < sizeof(struct ctf_header)) {
280 warnx("file too small to be CTF");
281 return 0;
282 }
283
284 memcpy(&cth, p, sizeof(struct ctf_header));
285 if (cth.cth_magic != CTF_MAGIC0xcff1 || cth.cth_version != CTF_VERSION2)
286 return 0;
287
288 dlen = cth.cth_stroff + cth.cth_strlen;
289 if (dlen > filesize && !(cth.cth_flags & CTF_F_COMPRESS(1 << 0))) {
290 warnx("bogus file size");
291 return 0;
292 }
293
294 if ((cth.cth_lbloff & 3) || (cth.cth_objtoff & 1) ||
295 (cth.cth_funcoff & 1) || (cth.cth_typeoff & 3)) {
296 warnx("wrongly aligned offset");
297 return 0;
298 }
299
300 if ((cth.cth_lbloff >= dlen) || (cth.cth_objtoff >= dlen) ||
301 (cth.cth_funcoff >= dlen) || (cth.cth_typeoff >= dlen)) {
302 warnx("truncated file");
303 return 0;
304 }
305
306 if ((cth.cth_lbloff > cth.cth_objtoff) ||
307 (cth.cth_objtoff > cth.cth_funcoff) ||
308 (cth.cth_funcoff > cth.cth_typeoff) ||
309 (cth.cth_typeoff > cth.cth_stroff)) {
310 warnx("corrupted file");
311 return 0;
312 }
313
314 return 1;
315}
316
317int
318ctf_dump(const char *p, size_t size, uint8_t flags)
319{
320 struct ctf_header cth;
321 size_t dlen;
322 char *data;
323
324 memcpy(&cth, p, sizeof(struct ctf_header));
325 dlen = cth.cth_stroff + cth.cth_strlen;
326 if (cth.cth_flags & CTF_F_COMPRESS(1 << 0)) {
31
Assuming the condition is false
32
Taking false branch
327 data = decompress(p + sizeof(cth), size - sizeof(cth), dlen);
328 if (data == NULL((void *)0))
329 return 1;
330 } else {
331 data = (char *)p + sizeof(cth);
332 }
333
334 if (flags & DUMP_HEADER(1 << 2)) {
33
Taking true branch
335 printf(" cth_magic = 0x%04x\n", cth.cth_magic);
336 printf(" cth_version = %u\n", cth.cth_version);
337 printf(" cth_flags = 0x%02x\n", cth.cth_flags);
338 printf(" cth_parlabel = %s\n",
339 ctf_off2name(&cth, data, dlen, cth.cth_parlabel));
340 printf(" cth_parname = %s\n",
341 ctf_off2name(&cth, data, dlen, cth.cth_parname));
342 printf(" cth_lbloff = %u\n", cth.cth_lbloff);
343 printf(" cth_objtoff = %u\n", cth.cth_objtoff);
344 printf(" cth_funcoff = %u\n", cth.cth_funcoff);
345 printf(" cth_typeoff = %u\n", cth.cth_typeoff);
346 printf(" cth_stroff = %u\n", cth.cth_stroff);
347 printf(" cth_strlen = %u\n", cth.cth_strlen);
348 printf("\n");
349 }
350
351 if (flags & DUMP_LABEL(1 << 3)) {
34
Taking true branch
352 uint32_t lbloff = cth.cth_lbloff;
353 struct ctf_lblent *ctl;
354
355 while (lbloff < cth.cth_objtoff) {
35
Assuming 'lbloff' is >= field 'cth_objtoff'
36
Loop condition is false. Execution continues on line 363
356 ctl = (struct ctf_lblent *)(data + lbloff);
357
358 printf(" %5u %s\n", ctl->ctl_typeidx,
359 ctf_off2name(&cth, data, dlen, ctl->ctl_label));
360
361 lbloff += sizeof(*ctl);
362 }
363 printf("\n");
364 }
365
366 if (flags & DUMP_OBJECT(1 << 0)) {
37
Taking true branch
367 uint32_t objtoff = cth.cth_objtoff;
368 size_t idx = 0, i = 0;
369 uint16_t *dsp;
370 const char *s;
371 int l;
372
373 while (objtoff < cth.cth_funcoff) {
38
Assuming 'objtoff' is >= field 'cth_funcoff'
39
Loop condition is false. Execution continues on line 384
374 dsp = (uint16_t *)(data + objtoff);
375
376 l = printf(" [%zu] %u", i++, *dsp);
377 if ((s = elf_idx2sym(&idx, STT_OBJECT1)) != NULL((void *)0))
378 printf("%*s %s (%zu)\n", (14 - l), "", s, idx);
379 else
380 printf("\n");
381
382 objtoff += sizeof(*dsp);
383 }
384 printf("\n");
385 }
386
387 if (flags & DUMP_FUNCTION(1 << 1)) {
40
Taking true branch
388 uint16_t *fsp, kind, vlen;
389 uint16_t *fstart, *fend;
390 size_t idx = 0, i = -1;
391 const char *s;
392 int l;
393
394 fstart = (uint16_t *)(data + cth.cth_funcoff);
395 fend = (uint16_t *)(data + cth.cth_typeoff);
396
397 fsp = fstart;
398 while (fsp < fend) {
41
Assuming 'fsp' is >= 'fend'
42
Loop condition is false. Execution continues on line 416
399 kind = CTF_INFO_KIND(*fsp)(((*fsp) & 0xf800) >> 11);
400 vlen = CTF_INFO_VLEN(*fsp)(((*fsp) & 0x03ff));
401 s = elf_idx2sym(&idx, STT_FUNC2);
402 fsp++;
403 i++;
404
405 if (kind == CTF_K_UNKNOWN0 && vlen == 0)
406 continue;
407
408 l = printf(" [%zu] FUNC ", i);
409 if (s != NULL((void *)0))
410 printf("(%s) ", s);
411 printf("returns: %u args: (", *fsp++);
412 while (vlen-- > 0 && fsp < fend)
413 printf("%u%s", *fsp++, (vlen > 0) ? ", " : "");
414 printf(")\n");
415 }
416 printf("\n");
417 }
418
419 if (flags & DUMP_TYPE(1 << 6)) {
43
Taking true branch
420 uint32_t idx = 1, offset = cth.cth_typeoff;
421 uint32_t stroff = cth.cth_stroff;
422
423 while (offset < stroff) {
44
Assuming 'offset' is < 'stroff'
45
Loop condition is true. Entering loop body
46
Assuming 'offset' is >= 'stroff'
47
Loop condition is false. Execution continues on line 426
424 ctf_dump_type(&cth, data, dlen, stroff, &offset, idx++);
425 }
426 printf("\n");
427 }
428
429 if (flags & DUMP_STRTAB(1 << 4)) {
48
Taking true branch
430 uint32_t offset = 0;
431 const char *str;
432
433 while (offset < cth.cth_strlen) {
49
Assuming 'offset' is >= field 'cth_strlen'
50
Loop condition is false. Execution continues on line 444
434 str = ctf_off2name(&cth, data, dlen, offset);
435
436 printf(" [%u] ", offset);
437 if (strcmp(str, "(anon)"))
438 offset += printf("%s\n", str);
439 else {
440 printf("\\0\n");
441 offset++;
442 }
443 }
444 printf("\n");
445 }
446
447 if (cth.cth_flags & CTF_F_COMPRESS(1 << 0))
51
Assuming the condition is true
52
Taking true branch
448 free(data);
53
Memory is released
449
450 return 0;
451}
452
453void
454ctf_dump_type(struct ctf_header *cth, const char *data, size_t dlen,
455 uint32_t stroff, uint32_t *offset, uint32_t idx)
456{
457 const char *p = data + *offset;
458 const struct ctf_type *ctt = (struct ctf_type *)p;
459 const struct ctf_array *cta;
460 uint16_t *argp, i, kind, vlen, root;
461 uint32_t eob, toff;
462 uint64_t size;
463 const char *name, *kname;
464
465 kind = CTF_INFO_KIND(ctt->ctt_info)(((ctt->_ctt_stype.cts_info) & 0xf800) >> 11);
466 vlen = CTF_INFO_VLEN(ctt->ctt_info)(((ctt->_ctt_stype.cts_info) & 0x03ff));
467 root = CTF_INFO_ISROOT(ctt->ctt_info)(((ctt->_ctt_stype.cts_info) & 0x0400) >> 10);
468 name = ctf_off2name(cth, data, dlen, ctt->ctt_name_ctt_stype.cts_name);
469
470 if (root)
471 printf(" <%u> ", idx);
472 else
473 printf(" [%u] ", idx);
474
475 if ((kname = ctf_kind2name(kind)) != NULL((void *)0))
476 printf("%s %s", kname, name);
477
478 if (ctt->ctt_size_ctt_stype._ST._size <= CTF_MAX_SIZE0xfffe) {
479 size = ctt->ctt_size_ctt_stype._ST._size;
480 toff = sizeof(struct ctf_stype);
481 } else {
482 size = CTF_TYPE_LSIZE(ctt)(((uint64_t)(ctt)->ctt_lsizehi) << 32 | (ctt)->ctt_lsizelo
)
;
483 toff = sizeof(struct ctf_type);
484 }
485
486 switch (kind) {
487 case CTF_K_UNKNOWN0:
488 case CTF_K_FORWARD9:
489 break;
490 case CTF_K_INTEGER1:
491 eob = *((uint32_t *)(p + toff));
492 toff += sizeof(uint32_t);
493 printf(" encoding=%s offset=%u bits=%u",
494 ctf_enc2name(CTF_INT_ENCODING(eob)(((eob) & 0xff000000) >> 24)), CTF_INT_OFFSET(eob)(((eob) & 0x00ff0000) >> 16),
495 CTF_INT_BITS(eob)(((eob) & 0x0000ffff)));
496 break;
497 case CTF_K_FLOAT2:
498 eob = *((uint32_t *)(p + toff));
499 toff += sizeof(uint32_t);
500 printf(" encoding=%s offset=%u bits=%u",
501 ctf_fpenc2name(CTF_FP_ENCODING(eob)(((eob) & 0xff000000) >> 24)), CTF_FP_OFFSET(eob)(((eob) & 0x00ff0000) >> 16),
502 CTF_FP_BITS(eob)(((eob) & 0x0000ffff)));
503 break;
504 case CTF_K_ARRAY4:
505 cta = (struct ctf_array *)(p + toff);
506 printf(" content: %u index: %u nelems: %u\n", cta->cta_contents,
507 cta->cta_index, cta->cta_nelems);
508 toff += sizeof(struct ctf_array);
509 break;
510 case CTF_K_FUNCTION5:
511 argp = (uint16_t *)(p + toff);
512 printf(" returns: %u args: (%u", ctt->ctt_type_ctt_stype._ST._type, *argp);
513 for (i = 1; i < vlen; i++) {
514 argp++;
515 if ((const char *)argp > data + dlen)
516 errx(1, "offset exceeds CTF section");
517
518 printf(", %u", *argp);
519 }
520 printf(")");
521 toff += (vlen + (vlen & 1)) * sizeof(uint16_t);
522 break;
523 case CTF_K_STRUCT6:
524 case CTF_K_UNION7:
525 printf(" (%llu bytes)\n", size);
526
527 if (size < CTF_LSTRUCT_THRESH8192) {
528 for (i = 0; i < vlen; i++) {
529 struct ctf_member *ctm;
530
531 if (p + toff > data + dlen)
532 errx(1, "offset exceeds CTF section");
533
534 if (toff > (stroff - sizeof(*ctm)))
535 break;
536
537 ctm = (struct ctf_member *)(p + toff);
538 toff += sizeof(struct ctf_member);
539
540 printf("\t%s type=%u off=%u\n",
541 ctf_off2name(cth, data, dlen,
542 ctm->ctm_name),
543 ctm->ctm_type, ctm->ctm_offset);
544 }
545 } else {
546 for (i = 0; i < vlen; i++) {
547 struct ctf_lmember *ctlm;
548
549 if (p + toff > data + dlen)
550 errx(1, "offset exceeds CTF section");
551
552 if (toff > (stroff - sizeof(*ctlm)))
553 break;
554
555 ctlm = (struct ctf_lmember *)(p + toff);
556 toff += sizeof(struct ctf_lmember);
557
558 printf("\t%s type=%u off=%llu\n",
559 ctf_off2name(cth, data, dlen,
560 ctlm->ctlm_name_ctlm_member.ctm_name),
561 ctlm->ctlm_type_ctlm_member.ctm_type, CTF_LMEM_OFFSET(ctlm)(((uint64_t)(ctlm)->ctlm_offsethi) << 32 | (ctlm)->
ctlm_offsetlo)
);
562 }
563 }
564 break;
565 case CTF_K_ENUM8:
566 printf("\n");
567 for (i = 0; i < vlen; i++) {
568 struct ctf_enum *cte;
569
570 if (p + toff > data + dlen)
571 errx(1, "offset exceeds CTF section");
572
573 if (toff > (stroff - sizeof(*cte)))
574 break;
575
576 cte = (struct ctf_enum *)(p + toff);
577 toff += sizeof(struct ctf_enum);
578
579 printf("\t%s = %d\n",
580 ctf_off2name(cth, data, dlen, cte->cte_name),
581 cte->cte_value);
582 }
583 break;
584 case CTF_K_POINTER3:
585 case CTF_K_TYPEDEF10:
586 case CTF_K_VOLATILE11:
587 case CTF_K_CONST12:
588 case CTF_K_RESTRICT13:
589 printf(" refers to %u", ctt->ctt_type_ctt_stype._ST._type);
590 break;
591 default:
592 errx(1, "incorrect type %u at offset %u", kind, *offset);
593 }
594
595 printf("\n");
596
597 *offset += toff;
598}
599
600const char *
601ctf_kind2name(uint16_t kind)
602{
603 static const char *kind_name[] = { NULL((void *)0), "INTEGER", "FLOAT", "POINTER",
604 "ARRAY", "FUNCTION", "STRUCT", "UNION", "ENUM", "FORWARD",
605 "TYPEDEF", "VOLATILE", "CONST", "RESTRICT" };
606
607 if (kind >= nitems(kind_name)(sizeof((kind_name)) / sizeof((kind_name)[0])))
608 return NULL((void *)0);
609
610 return kind_name[kind];
611}
612
613const char *
614ctf_enc2name(uint16_t enc)
615{
616 static const char *enc_name[] = { "SIGNED", "CHAR", "SIGNED CHAR",
617 "BOOL", "SIGNED BOOL" };
618 static char invalid[7];
619
620 if (enc == CTF_INT_VARARGS(1 << 3))
621 return "VARARGS";
622
623 if (enc > 0 && enc <= nitems(enc_name)(sizeof((enc_name)) / sizeof((enc_name)[0])))
624 return enc_name[enc - 1];
625
626 snprintf(invalid, sizeof(invalid), "0x%x", enc);
627 return invalid;
628}
629
630const char *
631ctf_fpenc2name(uint16_t enc)
632{
633 static const char *enc_name[] = { "SINGLE", "DOUBLE", NULL((void *)0), NULL((void *)0),
634 NULL((void *)0), "LDOUBLE" };
635 static char invalid[7];
636
637 if (enc > 0 && enc <= nitems(enc_name)(sizeof((enc_name)) / sizeof((enc_name)[0])) && enc_name[enc - 1] != NULL((void *)0))
638 return enc_name[enc - 1];
639
640 snprintf(invalid, sizeof(invalid), "0x%x", enc);
641 return invalid;
642}
643
644const char *
645ctf_off2name(struct ctf_header *cth, const char *data, size_t dlen,
646 uint32_t offset)
647{
648 const char *name;
649
650 if (CTF_NAME_STID(offset)((offset) >> 31) != CTF_STRTAB_00)
651 return "external";
652
653 if (CTF_NAME_OFFSET(offset)((offset) & 0x7fffffff) >= cth->cth_strlen)
654 return "exceeds strlab";
655
656 if (cth->cth_stroff + CTF_NAME_OFFSET(offset)((offset) & 0x7fffffff) >= dlen)
657 return "invalid";
658
659 name = data + cth->cth_stroff + CTF_NAME_OFFSET(offset)((offset) & 0x7fffffff);
660 if (*name == '\0')
661 return "(anon)";
662
663 return name;
664}
665
666char *
667decompress(const char *buf, size_t size, size_t len)
668{
669#ifdef ZLIB1
670 z_stream stream;
671 char *data;
672 int error;
673
674 data = malloc(len);
675 if (data == NULL((void *)0)) {
676 warn(NULL((void *)0));
677 return NULL((void *)0);
678 }
679
680 memset(&stream, 0, sizeof(stream));
681 stream.next_in = (void *)buf;
682 stream.avail_in = size;
683 stream.next_out = (uint8_t *)data;
684 stream.avail_out = len;
685
686 if ((error = inflateInit(&stream)inflateInit_((&stream), "1.3.0.1-motley", (int)sizeof(z_stream
))
) != Z_OK0) {
687 warnx("zlib inflateInit failed: %s", zError(error));
688 goto exit;
689 }
690
691 if ((error = inflate(&stream, Z_FINISH4)) != Z_STREAM_END1) {
692 warnx("zlib inflate failed: %s", zError(error));
693 inflateEnd(&stream);
694 goto exit;
695 }
696
697 if ((error = inflateEnd(&stream)) != Z_OK0) {
698 warnx("zlib inflateEnd failed: %s", zError(error));
699 goto exit;
700 }
701
702 if (stream.total_out != len) {
703 warnx("decompression failed: %lu != %zu",
704 stream.total_out, len);
705 goto exit;
706 }
707
708 return data;
709
710exit:
711 free(data);
712#endif /* ZLIB */
713 return NULL((void *)0);
714}
715
716__dead__attribute__((__noreturn__)) void
717usage(void)
718{
719 fprintf(stderr(&__sF[2]), "usage: %s [-dfhlst] file ...\n",
720 getprogname());
721 exit(1);
722}