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 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 * 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 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 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 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 * 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 * 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 * 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 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 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 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 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 * 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 * 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 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 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