1 /* $OpenBSD: db_ctf.c,v 1.35 2024/11/07 16:02:29 miod Exp $ */
2
3 /*
4 * Copyright (c) 2016-2017 Martin Pieuchot
5 * Copyright (c) 2016 Jasper Lievisse Adriaanse <jasper@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include <sys/param.h>
21 #include <sys/stdint.h>
22 #include <sys/systm.h>
23 #include <sys/exec.h>
24
25 #include <machine/db_machdep.h>
26
27 #include <ddb/db_extern.h>
28 #include <ddb/db_command.h>
29 #include <ddb/db_elf.h>
30 #include <ddb/db_lex.h>
31 #include <ddb/db_output.h>
32 #include <ddb/db_sym.h>
33 #include <ddb/db_access.h>
34
35 #include <sys/exec_elf.h>
36 #include <sys/ctf.h>
37 #include <sys/malloc.h>
38 #include <lib/libz/zlib.h>
39
40 extern db_symtab_t db_symtab;
41
42 struct ddb_ctf {
43 struct ctf_header *cth;
44 const char *rawctf; /* raw .SUNW_ctf section */
45 size_t rawctflen; /* raw .SUNW_ctf section size */
46 const char *data; /* decompressed CTF data */
47 size_t dlen; /* decompressed CTF data size */
48 const char *strtab; /* ELF string table */
49 uint32_t ctf_found;
50 };
51
52 struct ddb_ctf db_ctf;
53
54 static const char *db_ctf_off2name(uint32_t);
55 static Elf_Sym *db_ctf_idx2sym(size_t *, uint8_t);
56 static char *db_ctf_decompress(const char *, size_t, size_t);
57
58 uint32_t db_ctf_type_len(const struct ctf_type *);
59 size_t db_ctf_type_size(const struct ctf_type *);
60 const struct ctf_type *db_ctf_type_by_name(const char *, unsigned int);
61 const struct ctf_type *db_ctf_type_by_symbol(Elf_Sym *);
62 const struct ctf_type *db_ctf_type_by_index(uint16_t);
63 void db_ctf_pprint(const struct ctf_type *, vaddr_t);
64 void db_ctf_pprint_struct(const struct ctf_type *, vaddr_t);
65 void db_ctf_pprint_enum(const struct ctf_type *, vaddr_t);
66 void db_ctf_pprint_ptr(const struct ctf_type *, vaddr_t);
67
68 /*
69 * Entrypoint to verify CTF presence, initialize the header, decompress
70 * the data, etc.
71 */
72 void
db_ctf_init(void)73 db_ctf_init(void)
74 {
75 db_symtab_t *stab = &db_symtab;
76 size_t rawctflen;
77
78 /* Assume nothing was correct found until proven otherwise. */
79 db_ctf.ctf_found = 0;
80
81 if (stab->private == NULL)
82 return;
83
84 db_ctf.strtab = db_elf_find_strtab(stab);
85 if (db_ctf.strtab == NULL)
86 return;
87
88 db_ctf.rawctf = db_elf_find_section(stab, &rawctflen, ELF_CTF);
89 if (db_ctf.rawctf == NULL)
90 return;
91
92 db_ctf.rawctflen = rawctflen;
93 db_ctf.cth = (struct ctf_header *)db_ctf.rawctf;
94 db_ctf.dlen = db_ctf.cth->cth_stroff + db_ctf.cth->cth_strlen;
95
96 if ((db_ctf.cth->cth_flags & CTF_F_COMPRESS) == 0) {
97 db_printf("unsupported non-compressed CTF section\n");
98 return;
99 }
100
101 /* Now decompress the section, take into account to skip the header */
102 db_ctf.data = db_ctf_decompress(db_ctf.rawctf + sizeof(*db_ctf.cth),
103 db_ctf.rawctflen - sizeof(*db_ctf.cth), db_ctf.dlen);
104 if (db_ctf.data == NULL)
105 return;
106
107 /* We made it this far, everything seems fine. */
108 db_ctf.ctf_found = 1;
109 }
110
111 /*
112 * Convert an index to a symbol name while ensuring the type is matched.
113 * It must be noted this only works if the CTF table has the same order
114 * as the symbol table.
115 */
116 Elf_Sym *
db_ctf_idx2sym(size_t * idx,uint8_t type)117 db_ctf_idx2sym(size_t *idx, uint8_t type)
118 {
119 Elf_Sym *symp, *symtab_start, *symtab_end;
120 size_t i = *idx + 1;
121
122 symtab_start = STAB_TO_SYMSTART(&db_symtab);
123 symtab_end = STAB_TO_SYMEND(&db_symtab);
124
125 for (symp = &symtab_start[i]; symp < symtab_end; i++, symp++) {
126 if (ELF_ST_TYPE(symp->st_info) != type)
127 continue;
128
129 *idx = i;
130 return symp;
131 }
132
133 return NULL;
134 }
135
136 /*
137 * For a given function name, return the number of arguments.
138 */
139 int
db_ctf_func_numargs(Elf_Sym * st)140 db_ctf_func_numargs(Elf_Sym *st)
141 {
142 Elf_Sym *symp;
143 uint16_t *fstart, *fend;
144 uint16_t *fsp, kind, vlen;
145 size_t i, idx = 0;
146
147 if (!db_ctf.ctf_found || st == NULL)
148 return -1;
149
150 fstart = (uint16_t *)(db_ctf.data + db_ctf.cth->cth_funcoff);
151 fend = (uint16_t *)(db_ctf.data + db_ctf.cth->cth_typeoff);
152
153 fsp = fstart;
154 while (fsp < fend) {
155 symp = db_ctf_idx2sym(&idx, STT_FUNC);
156 if (symp == NULL)
157 break;
158
159 kind = CTF_INFO_KIND(*fsp);
160 vlen = CTF_INFO_VLEN(*fsp);
161 fsp++;
162
163 if (kind == CTF_K_UNKNOWN && vlen == 0)
164 continue;
165
166 /* Skip return type */
167 fsp++;
168
169 /* Skip argument types */
170 for (i = 0; i < vlen; i++)
171 fsp++;
172
173 if (symp == st)
174 return vlen;
175 }
176
177 return 0;
178 }
179
180 /*
181 * Return the length of the type record in the CTF section.
182 */
183 uint32_t
db_ctf_type_len(const struct ctf_type * ctt)184 db_ctf_type_len(const struct ctf_type *ctt)
185 {
186 uint16_t kind, vlen, i;
187 uint32_t tlen;
188 uint64_t size;
189
190 kind = CTF_INFO_KIND(ctt->ctt_info);
191 vlen = CTF_INFO_VLEN(ctt->ctt_info);
192
193 if (ctt->ctt_size <= CTF_MAX_SIZE) {
194 size = ctt->ctt_size;
195 tlen = sizeof(struct ctf_stype);
196 } else {
197 size = CTF_TYPE_LSIZE(ctt);
198 tlen = sizeof(struct ctf_type);
199 }
200
201 switch (kind) {
202 case CTF_K_UNKNOWN:
203 case CTF_K_FORWARD:
204 break;
205 case CTF_K_INTEGER:
206 tlen += sizeof(uint32_t);
207 break;
208 case CTF_K_FLOAT:
209 tlen += sizeof(uint32_t);
210 break;
211 case CTF_K_ARRAY:
212 tlen += sizeof(struct ctf_array);
213 break;
214 case CTF_K_FUNCTION:
215 tlen += (vlen + (vlen & 1)) * sizeof(uint16_t);
216 break;
217 case CTF_K_STRUCT:
218 case CTF_K_UNION:
219 if (size < CTF_LSTRUCT_THRESH) {
220 for (i = 0; i < vlen; i++) {
221 tlen += sizeof(struct ctf_member);
222 }
223 } else {
224 for (i = 0; i < vlen; i++) {
225 tlen += sizeof(struct ctf_lmember);
226 }
227 }
228 break;
229 case CTF_K_ENUM:
230 for (i = 0; i < vlen; i++) {
231 tlen += sizeof(struct ctf_enum);
232 }
233 break;
234 case CTF_K_POINTER:
235 case CTF_K_TYPEDEF:
236 case CTF_K_VOLATILE:
237 case CTF_K_CONST:
238 case CTF_K_RESTRICT:
239 break;
240 default:
241 return 0;
242 }
243
244 return tlen;
245 }
246
247 /*
248 * Return the size of the type.
249 */
250 size_t
db_ctf_type_size(const struct ctf_type * ctt)251 db_ctf_type_size(const struct ctf_type *ctt)
252 {
253 vaddr_t taddr = (vaddr_t)ctt;
254 const struct ctf_type *ref;
255 const struct ctf_array *arr;
256 size_t tlen = 0;
257 uint16_t kind;
258 uint32_t toff;
259 uint64_t size;
260
261 kind = CTF_INFO_KIND(ctt->ctt_info);
262
263 if (ctt->ctt_size <= CTF_MAX_SIZE) {
264 size = ctt->ctt_size;
265 toff = sizeof(struct ctf_stype);
266 } else {
267 size = CTF_TYPE_LSIZE(ctt);
268 toff = sizeof(struct ctf_type);
269 }
270
271 switch (kind) {
272 case CTF_K_UNKNOWN:
273 case CTF_K_FORWARD:
274 break;
275 case CTF_K_INTEGER:
276 case CTF_K_FLOAT:
277 tlen = size;
278 break;
279 case CTF_K_ARRAY:
280 arr = (struct ctf_array *)(taddr + toff);
281 ref = db_ctf_type_by_index(arr->cta_contents);
282 tlen = arr->cta_nelems * db_ctf_type_size(ref);
283 break;
284 case CTF_K_FUNCTION:
285 tlen = 0;
286 break;
287 case CTF_K_STRUCT:
288 case CTF_K_UNION:
289 case CTF_K_ENUM:
290 tlen = size;
291 break;
292 case CTF_K_POINTER:
293 tlen = sizeof(void *);
294 break;
295 case CTF_K_TYPEDEF:
296 case CTF_K_VOLATILE:
297 case CTF_K_CONST:
298 case CTF_K_RESTRICT:
299 ref = db_ctf_type_by_index(ctt->ctt_type);
300 tlen = db_ctf_type_size(ref);
301 break;
302 default:
303 return 0;
304 }
305
306 return tlen;
307 }
308
309 /*
310 * Return the CTF type associated to an ELF symbol.
311 */
312 const struct ctf_type *
db_ctf_type_by_symbol(Elf_Sym * st)313 db_ctf_type_by_symbol(Elf_Sym *st)
314 {
315 Elf_Sym *symp;
316 uint32_t objtoff;
317 uint16_t *dsp;
318 size_t idx = 0;
319
320 if (!db_ctf.ctf_found || st == NULL)
321 return NULL;
322
323 objtoff = db_ctf.cth->cth_objtoff;
324
325 while (objtoff < db_ctf.cth->cth_funcoff) {
326 dsp = (uint16_t *)(db_ctf.data + objtoff);
327
328 symp = db_ctf_idx2sym(&idx, STT_OBJECT);
329 if (symp == NULL)
330 break;
331 if (symp == st)
332 return db_ctf_type_by_index(*dsp);
333
334 objtoff += sizeof(*dsp);
335 }
336
337 return NULL;
338 }
339
340 const struct ctf_type *
db_ctf_type_by_name(const char * name,unsigned int kind)341 db_ctf_type_by_name(const char *name, unsigned int kind)
342 {
343 struct ctf_header *cth;
344 const struct ctf_type *ctt;
345 const char *tname;
346 uint32_t off, toff;
347
348 if (!db_ctf.ctf_found)
349 return (NULL);
350
351 cth = db_ctf.cth;
352
353 for (off = cth->cth_typeoff; off < cth->cth_stroff; off += toff) {
354 ctt = (struct ctf_type *)(db_ctf.data + off);
355 toff = db_ctf_type_len(ctt);
356 if (toff == 0) {
357 db_printf("incorrect type at offset %u", off);
358 break;
359 }
360
361 if (CTF_INFO_KIND(ctt->ctt_info) != kind)
362 continue;
363
364 tname = db_ctf_off2name(ctt->ctt_name);
365 if (tname == NULL)
366 continue;
367
368 if (strcmp(name, tname) == 0)
369 return (ctt);
370 }
371
372 return (NULL);
373 }
374
375 /*
376 * Return the CTF type corresponding to a given index in the type section.
377 */
378 const struct ctf_type *
db_ctf_type_by_index(uint16_t index)379 db_ctf_type_by_index(uint16_t index)
380 {
381 uint32_t offset = db_ctf.cth->cth_typeoff;
382 uint16_t idx = 1;
383
384 if (!db_ctf.ctf_found)
385 return NULL;
386
387 while (offset < db_ctf.cth->cth_stroff) {
388 const struct ctf_type *ctt;
389 uint32_t toff;
390
391 ctt = (struct ctf_type *)(db_ctf.data + offset);
392 if (idx == index)
393 return ctt;
394
395 toff = db_ctf_type_len(ctt);
396 if (toff == 0) {
397 db_printf("incorrect type at offset %u", offset);
398 break;
399 }
400 offset += toff;
401 idx++;
402 }
403
404 return NULL;
405 }
406
407 /*
408 * Pretty print `addr'.
409 */
410 void
db_ctf_pprint(const struct ctf_type * ctt,vaddr_t addr)411 db_ctf_pprint(const struct ctf_type *ctt, vaddr_t addr)
412 {
413 vaddr_t taddr = (vaddr_t)ctt;
414 const struct ctf_type *ref;
415 const struct ctf_array *arr;
416 uint16_t kind;
417 uint32_t eob, toff, i;
418 db_expr_t val;
419 size_t elm_size;
420
421 if (ctt == NULL)
422 return;
423
424 kind = CTF_INFO_KIND(ctt->ctt_info);
425 if (ctt->ctt_size <= CTF_MAX_SIZE)
426 toff = sizeof(struct ctf_stype);
427 else
428 toff = sizeof(struct ctf_type);
429
430 switch (kind) {
431 case CTF_K_ARRAY:
432 arr = (struct ctf_array *)(taddr + toff);
433 ref = db_ctf_type_by_index(arr->cta_contents);
434 elm_size = db_ctf_type_size(ref);
435 db_printf("[");
436 for (i = 0; i < arr->cta_nelems; i++) {
437 db_ctf_pprint(ref, addr + i * elm_size);
438 if (i + 1 < arr->cta_nelems)
439 db_printf(",");
440 }
441 db_printf("]");
442 break;
443 case CTF_K_ENUM:
444 db_ctf_pprint_enum(ctt, addr);
445 break;
446 case CTF_K_FLOAT:
447 case CTF_K_FUNCTION:
448 val = db_get_value(addr, sizeof(val), 0);
449 db_printf("%lx", (unsigned long)val);
450 break;
451 case CTF_K_INTEGER:
452 eob = db_get_value((taddr + toff), sizeof(eob), 0);
453 switch (CTF_INT_BITS(eob)) {
454 #ifndef __LP64__
455 case 64: {
456 uint64_t val64;
457 #if BYTE_ORDER == LITTLE_ENDIAN
458 val64 = db_get_value(addr + 4, CTF_INT_BITS(eob) / 8,
459 CTF_INT_ENCODING(eob) & CTF_INT_SIGNED);
460 val64 <<= 32;
461 val64 |= db_get_value(addr, CTF_INT_BITS(eob) / 8, 0);
462 #else
463 val64 = db_get_value(addr, CTF_INT_BITS(eob) / 8,
464 CTF_INT_ENCODING(eob) & CTF_INT_SIGNED);
465 val64 <<= 32;
466 val64 |= db_get_value(addr + 4, CTF_INT_BITS(eob) / 8,
467 0);
468 #endif
469 if (CTF_INT_ENCODING(eob) & CTF_INT_SIGNED)
470 db_printf("%lld", val64);
471 else
472 db_printf("%llu", val64);
473 break;
474 }
475 #endif
476 default:
477 val = db_get_value(addr, CTF_INT_BITS(eob) / 8,
478 CTF_INT_ENCODING(eob) & CTF_INT_SIGNED);
479 if (CTF_INT_ENCODING(eob) & CTF_INT_SIGNED)
480 db_printf("%ld", val);
481 else
482 db_printf("%lu", val);
483 break;
484 }
485 break;
486 case CTF_K_STRUCT:
487 case CTF_K_UNION:
488 db_ctf_pprint_struct(ctt, addr);
489 break;
490 case CTF_K_POINTER:
491 db_ctf_pprint_ptr(ctt, addr);
492 break;
493 case CTF_K_TYPEDEF:
494 case CTF_K_VOLATILE:
495 case CTF_K_CONST:
496 case CTF_K_RESTRICT:
497 ref = db_ctf_type_by_index(ctt->ctt_type);
498 db_ctf_pprint(ref, addr);
499 break;
500 case CTF_K_UNKNOWN:
501 case CTF_K_FORWARD:
502 default:
503 break;
504 }
505 }
506
507 void
db_ctf_pprint_struct(const struct ctf_type * ctt,vaddr_t addr)508 db_ctf_pprint_struct(const struct ctf_type *ctt, vaddr_t addr)
509 {
510 const char *name, *p = (const char *)ctt;
511 const struct ctf_type *ref;
512 uint32_t toff;
513 uint64_t size;
514 uint16_t i, vlen;
515
516 vlen = CTF_INFO_VLEN(ctt->ctt_info);
517
518 if (ctt->ctt_size <= CTF_MAX_SIZE) {
519 size = ctt->ctt_size;
520 toff = sizeof(struct ctf_stype);
521 } else {
522 size = CTF_TYPE_LSIZE(ctt);
523 toff = sizeof(struct ctf_type);
524 }
525
526 db_printf("{");
527 if (size < CTF_LSTRUCT_THRESH) {
528 for (i = 0; i < vlen; i++) {
529 struct ctf_member *ctm;
530
531 ctm = (struct ctf_member *)(p + toff);
532 toff += sizeof(struct ctf_member);
533
534 name = db_ctf_off2name(ctm->ctm_name);
535 if (name != NULL)
536 db_printf("%s = ", name);
537 ref = db_ctf_type_by_index(ctm->ctm_type);
538 db_ctf_pprint(ref, addr + ctm->ctm_offset / 8);
539 if (i < vlen - 1)
540 db_printf(", ");
541 }
542 } else {
543 for (i = 0; i < vlen; i++) {
544 struct ctf_lmember *ctlm;
545
546 ctlm = (struct ctf_lmember *)(p + toff);
547 toff += sizeof(struct ctf_lmember);
548
549 name = db_ctf_off2name(ctlm->ctlm_name);
550 if (name != NULL)
551 db_printf("%s = ", name);
552 ref = db_ctf_type_by_index(ctlm->ctlm_type);
553 db_ctf_pprint(ref, addr +
554 CTF_LMEM_OFFSET(ctlm) / 8);
555 if (i < vlen - 1)
556 db_printf(", ");
557 }
558 }
559 db_printf("}");
560 }
561
562 void
db_ctf_pprint_enum(const struct ctf_type * ctt,vaddr_t addr)563 db_ctf_pprint_enum(const struct ctf_type *ctt, vaddr_t addr)
564 {
565 const char *name = NULL, *p = (const char *)ctt;
566 struct ctf_enum *cte;
567 uint32_t toff;
568 int32_t val;
569 uint16_t i, vlen;
570
571 vlen = CTF_INFO_VLEN(ctt->ctt_info);
572 toff = sizeof(struct ctf_stype);
573
574 val = (int32_t)db_get_value(addr, sizeof(val), 1);
575 for (i = 0; i < vlen; i++) {
576 cte = (struct ctf_enum *)(p + toff);
577 toff += sizeof(*cte);
578
579 if (val == cte->cte_value) {
580 name = db_ctf_off2name(cte->cte_name);
581 break;
582 }
583 }
584
585 if (name != NULL)
586 db_printf("%s", name);
587 else
588 db_printf("#%d", val);
589 }
590
591 void
db_ctf_pprint_ptr(const struct ctf_type * ctt,vaddr_t addr)592 db_ctf_pprint_ptr(const struct ctf_type *ctt, vaddr_t addr)
593 {
594 const char *name, *modif = "";
595 const struct ctf_type *ref;
596 uint16_t kind;
597 unsigned long ptr;
598
599 ref = db_ctf_type_by_index(ctt->ctt_type);
600 kind = CTF_INFO_KIND(ref->ctt_info);
601
602 switch (kind) {
603 case CTF_K_VOLATILE:
604 modif = "volatile ";
605 ref = db_ctf_type_by_index(ref->ctt_type);
606 break;
607 case CTF_K_CONST:
608 modif = "const ";
609 ref = db_ctf_type_by_index(ref->ctt_type);
610 break;
611 case CTF_K_STRUCT:
612 modif = "struct ";
613 break;
614 case CTF_K_UNION:
615 modif = "union ";
616 break;
617 default:
618 break;
619 }
620
621 name = db_ctf_off2name(ref->ctt_name);
622 if (name != NULL)
623 db_printf("(%s%s *)", modif, name);
624
625 ptr = (unsigned long)db_get_value(addr, sizeof(ptr), 0);
626
627 db_printf("0x%lx", ptr);
628 }
629
630 static const char *
db_ctf_off2name(uint32_t offset)631 db_ctf_off2name(uint32_t offset)
632 {
633 const char *name;
634
635 if (!db_ctf.ctf_found)
636 return NULL;
637
638 if (CTF_NAME_STID(offset) != CTF_STRTAB_0)
639 return "external";
640
641 if (CTF_NAME_OFFSET(offset) >= db_ctf.cth->cth_strlen)
642 return "exceeds strlab";
643
644 if (db_ctf.cth->cth_stroff + CTF_NAME_OFFSET(offset) >= db_ctf.dlen)
645 return "invalid";
646
647 name = db_ctf.data + db_ctf.cth->cth_stroff + CTF_NAME_OFFSET(offset);
648 if (*name == '\0')
649 return NULL;
650
651 return name;
652 }
653
654 static char *
db_ctf_decompress(const char * buf,size_t size,size_t len)655 db_ctf_decompress(const char *buf, size_t size, size_t len)
656 {
657 z_stream stream;
658 char *data;
659 int error;
660
661 data = malloc(len, M_TEMP, M_WAITOK|M_ZERO|M_CANFAIL);
662 if (data == NULL)
663 return NULL;
664
665 memset(&stream, 0, sizeof(stream));
666 stream.next_in = (void *)buf;
667 stream.avail_in = size;
668 stream.next_out = data;
669 stream.avail_out = len;
670
671 if ((error = inflateInit(&stream)) != Z_OK) {
672 db_printf("zlib inflateInit failed: %s", zError(error));
673 goto exit;
674 }
675
676 if ((error = inflate(&stream, Z_FINISH)) != Z_STREAM_END) {
677 db_printf("zlib inflate failed: %s", zError(error));
678 inflateEnd(&stream);
679 goto exit;
680 }
681
682 if ((error = inflateEnd(&stream)) != Z_OK) {
683 db_printf("zlib inflateEnd failed: %s", zError(error));
684 goto exit;
685 }
686
687 if (stream.total_out != len) {
688 db_printf("decompression failed: %lu != %zu",
689 stream.total_out, len);
690 goto exit;
691 }
692
693 return data;
694
695 exit:
696 free(data, M_DEVBUF, len);
697 return NULL;
698 }
699
700 /*
701 * pprint <symbol name>
702 */
703 void
db_ctf_pprint_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)704 db_ctf_pprint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
705 {
706 Elf_Sym *st;
707 const struct ctf_type *ctt;
708 int t;
709
710 if (!db_ctf.ctf_found) {
711 db_printf("No CTF data found\n");
712 db_flush_lex();
713 return;
714 }
715
716 /*
717 * Read the struct name from the debugger input.
718 */
719 t = db_read_token();
720 if (t != tIDENT) {
721 db_printf("Bad symbol name\n");
722 db_flush_lex();
723 return;
724 }
725
726 if ((st = db_symbol_by_name(db_tok_string, &addr)) == NULL) {
727 db_printf("Symbol not found %s\n", db_tok_string);
728 db_flush_lex();
729 return;
730 }
731
732 if ((ctt = db_ctf_type_by_symbol(st)) == NULL) {
733 modif[0] = '\0';
734 db_print_cmd(addr, 0, 0, modif);
735 db_flush_lex();
736 return;
737 }
738
739 db_printf("%s:\t", db_tok_string);
740 db_ctf_pprint(ctt, addr);
741 db_printf("\n");
742 }
743
744 /*
745 * show struct <struct name> [addr]: displays the data starting at addr
746 * (`dot' if unspecified) as a struct of the given type.
747 */
748 void
db_ctf_show_struct(db_expr_t addr,int have_addr,db_expr_t count,char * modifiers)749 db_ctf_show_struct(db_expr_t addr, int have_addr, db_expr_t count,
750 char *modifiers)
751 {
752 const struct ctf_type *ctt;
753 const char *name;
754 uint64_t sz;
755 int t;
756
757 /*
758 * Read the struct name from the debugger input.
759 */
760 t = db_read_token();
761 if (t != tIDENT) {
762 db_printf("Bad struct name\n");
763 db_flush_lex();
764 return;
765 }
766 name = db_tok_string;
767
768 ctt = db_ctf_type_by_name(name, CTF_K_STRUCT);
769 if (ctt == NULL) {
770 db_printf("unknown struct %s\n", name);
771 db_flush_lex();
772 return;
773 }
774
775 /*
776 * Read the address, if any, from the debugger input.
777 * In that case, update `dot' value.
778 */
779 if (db_expression(&addr)) {
780 db_dot = (vaddr_t)addr;
781 db_last_addr = db_dot;
782 } else
783 addr = (db_expr_t)db_dot;
784
785 db_skip_to_eol();
786
787 /*
788 * Display the structure contents.
789 */
790 sz = (ctt->ctt_size <= CTF_MAX_SIZE) ?
791 ctt->ctt_size : CTF_TYPE_LSIZE(ctt);
792 db_printf("struct %s at %p (%llu bytes) ", name, (void *)addr, sz);
793 db_ctf_pprint_struct(ctt, addr);
794 }
795