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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Create and parse buffers containing CTF data. 28 */ 29 30 #if HAVE_NBTOOL_CONFIG_H 31 #include "nbtool_config.h" 32 #endif 33 34 #include <sys/types.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <strings.h> 38 #include <ctype.h> 39 #include <zlib.h> 40 #include <elf.h> 41 42 #include "ctf_headers.h" 43 #include "ctftools.h" 44 #include "strtab.h" 45 #include "memory.h" 46 47 /* 48 * Name of the file currently being read, used to print error messages. We 49 * assume that only one file will be read at a time, and thus make no attempt 50 * to allow curfile to be used simultaneously by multiple threads. 51 * 52 * The value is only valid during a call to ctf_load. 53 */ 54 char *curfile; 55 56 57 /* The number of types. */ 58 static int ntypes=0; 59 60 #define CTF_BUF_CHUNK_SIZE (64 * 1024) 61 #define RES_BUF_CHUNK_SIZE (64 * 1024) 62 63 struct ctf_buf { 64 strtab_t ctb_strtab; /* string table */ 65 caddr_t ctb_base; /* pointer to base of buffer */ 66 caddr_t ctb_end; /* pointer to end of buffer */ 67 caddr_t ctb_ptr; /* pointer to empty buffer space */ 68 size_t ctb_size; /* size of buffer */ 69 int nptent; /* number of processed types */ 70 int ntholes; /* number of type holes */ 71 }; 72 73 /*PRINTFLIKE1*/ 74 static void 75 parseterminate(const char *fmt, ...) 76 { 77 static char msgbuf[1024]; /* sigh */ 78 va_list ap; 79 80 va_start(ap, fmt); 81 vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap); 82 va_end(ap); 83 84 terminate("%s: %s\n", curfile, msgbuf); 85 } 86 87 static void 88 ctf_buf_grow(ctf_buf_t *b) 89 { 90 off_t ptroff = b->ctb_ptr - b->ctb_base; 91 92 b->ctb_size += CTF_BUF_CHUNK_SIZE; 93 b->ctb_base = xrealloc(b->ctb_base, b->ctb_size); 94 b->ctb_end = b->ctb_base + b->ctb_size; 95 b->ctb_ptr = b->ctb_base + ptroff; 96 } 97 98 static ctf_buf_t * 99 ctf_buf_new(void) 100 { 101 ctf_buf_t *b = xcalloc(sizeof (ctf_buf_t)); 102 103 strtab_create(&b->ctb_strtab); 104 ctf_buf_grow(b); 105 106 return (b); 107 } 108 109 static void 110 ctf_buf_free(ctf_buf_t *b) 111 { 112 strtab_destroy(&b->ctb_strtab); 113 free(b->ctb_base); 114 free(b); 115 } 116 117 static uint_t 118 ctf_buf_cur(ctf_buf_t *b) 119 { 120 return (b->ctb_ptr - b->ctb_base); 121 } 122 123 static void 124 ctf_buf_write(ctf_buf_t *b, void const *p, size_t n) 125 { 126 size_t len; 127 128 while (n != 0) { 129 if (b->ctb_ptr == b->ctb_end) 130 ctf_buf_grow(b); 131 132 len = MIN((size_t)(b->ctb_end - b->ctb_ptr), n); 133 bcopy(p, b->ctb_ptr, len); 134 b->ctb_ptr += len; 135 136 p = (char const *)p + len; 137 n -= len; 138 } 139 } 140 141 static int 142 write_label(void *arg1, void *arg2) 143 { 144 labelent_t *le = arg1; 145 ctf_buf_t *b = arg2; 146 ctf_lblent_t ctl; 147 148 ctl.ctl_label = strtab_insert(&b->ctb_strtab, le->le_name); 149 ctl.ctl_typeidx = le->le_idx; 150 151 ctf_buf_write(b, &ctl, sizeof (ctl)); 152 153 return (1); 154 } 155 156 static void 157 write_objects(iidesc_t *idp, ctf_buf_t *b) 158 { 159 ushort_t id = (idp ? idp->ii_dtype->t_id : 0); 160 161 ctf_buf_write(b, &id, sizeof (id)); 162 163 debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id); 164 } 165 166 static void 167 write_functions(iidesc_t *idp, ctf_buf_t *b) 168 { 169 ushort_t fdata[2]; 170 ushort_t id; 171 int nargs; 172 int i; 173 174 if (!idp) { 175 fdata[0] = 0; 176 ctf_buf_write(b, &fdata[0], sizeof (fdata[0])); 177 178 debug(3, "Wrote function (null)\n"); 179 return; 180 } 181 182 nargs = idp->ii_nargs + (idp->ii_vargs != 0); 183 184 if (nargs > CTF_MAX_VLEN) { 185 terminate("function %s has too many args: %d > %d\n", 186 idp->ii_name, nargs, CTF_MAX_VLEN); 187 } 188 189 fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs); 190 fdata[1] = idp->ii_dtype->t_id; 191 ctf_buf_write(b, fdata, sizeof (fdata)); 192 193 for (i = 0; i < idp->ii_nargs; i++) { 194 id = idp->ii_args[i]->t_id; 195 ctf_buf_write(b, &id, sizeof (id)); 196 } 197 198 if (idp->ii_vargs) { 199 id = 0; 200 ctf_buf_write(b, &id, sizeof (id)); 201 } 202 203 debug(3, "Wrote function %s (%d args)\n", idp->ii_name, nargs); 204 } 205 206 /* 207 * Depending on the size of the type being described, either a ctf_stype_t (for 208 * types with size < CTF_LSTRUCT_THRESH) or a ctf_type_t (all others) will be 209 * written. We isolate the determination here so the rest of the writer code 210 * doesn't need to care. 211 */ 212 static void 213 write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size) 214 { 215 if (size > CTF_MAX_SIZE) { 216 ctt->ctt_size = CTF_LSIZE_SENT; 217 ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size); 218 ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size); 219 ctf_buf_write(b, ctt, sizeof (*ctt)); 220 } else { 221 ctf_stype_t *cts = (ctf_stype_t *)ctt; 222 223 cts->ctt_size = (ushort_t)size; 224 ctf_buf_write(b, cts, sizeof (*cts)); 225 } 226 } 227 228 static void 229 write_unsized_type_rec(ctf_buf_t *b, ctf_type_t *ctt) 230 { 231 ctf_stype_t *cts = (ctf_stype_t *)ctt; 232 233 ctf_buf_write(b, cts, sizeof (*cts)); 234 } 235 236 static int 237 write_type(void *arg1, void *arg2) 238 { 239 tdesc_t *tp = arg1; 240 ctf_buf_t *b = arg2; 241 elist_t *ep; 242 mlist_t *mp; 243 intr_t *ip; 244 245 size_t offset; 246 uint_t encoding; 247 uint_t data; 248 int isroot = tp->t_flags & TDESC_F_ISROOT; 249 int i; 250 251 ctf_type_t ctt; 252 ctf_array_t cta; 253 ctf_member_t ctm; 254 ctf_lmember_t ctlm; 255 ctf_enum_t cte; 256 ushort_t id; 257 258 ctlm.ctlm_pad = 0; 259 260 /* 261 * There shouldn't be any holes in the type list (where a hole is 262 * defined as two consecutive tdescs without consecutive ids), but 263 * check for them just in case. If we do find holes, we need to make 264 * fake entries to fill the holes, or we won't be able to reconstruct 265 * the tree from the written data. 266 */ 267 if (++b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) { 268 debug(2, "genctf: type hole from %d < x < %d\n", 269 b->nptent - 1, CTF_TYPE_TO_INDEX(tp->t_id)); 270 271 ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, 0); 272 ctt.ctt_info = CTF_TYPE_INFO(0, 0, 0); 273 while (b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) { 274 write_sized_type_rec(b, &ctt, 0); 275 b->nptent++; 276 } 277 } 278 279 offset = strtab_insert(&b->ctb_strtab, tp->t_name); 280 ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); 281 282 switch (tp->t_type) { 283 case INTRINSIC: 284 ip = tp->t_intr; 285 if (ip->intr_type == INTR_INT) 286 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_INTEGER, 287 isroot, 1); 288 else 289 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FLOAT, isroot, 1); 290 write_sized_type_rec(b, &ctt, tp->t_size); 291 292 encoding = 0; 293 294 if (ip->intr_type == INTR_INT) { 295 if (ip->intr_signed) 296 encoding |= CTF_INT_SIGNED; 297 if (ip->intr_iformat == 'c') 298 encoding |= CTF_INT_CHAR; 299 else if (ip->intr_iformat == 'b') 300 encoding |= CTF_INT_BOOL; 301 else if (ip->intr_iformat == 'v') 302 encoding |= CTF_INT_VARARGS; 303 } else 304 encoding = ip->intr_fformat; 305 306 data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits); 307 ctf_buf_write(b, &data, sizeof (data)); 308 break; 309 310 case POINTER: 311 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_POINTER, isroot, 0); 312 ctt.ctt_type = tp->t_tdesc->t_id; 313 write_unsized_type_rec(b, &ctt); 314 break; 315 316 case ARRAY: 317 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, isroot, 1); 318 write_sized_type_rec(b, &ctt, tp->t_size); 319 320 cta.cta_contents = tp->t_ardef->ad_contents->t_id; 321 cta.cta_index = tp->t_ardef->ad_idxtype->t_id; 322 cta.cta_nelems = tp->t_ardef->ad_nelems; 323 ctf_buf_write(b, &cta, sizeof (cta)); 324 break; 325 326 case STRUCT: 327 case UNION: 328 for (i = 0, mp = tp->t_members; mp != NULL; mp = mp->ml_next) 329 i++; /* count up struct or union members */ 330 331 if (i > CTF_MAX_VLEN) { 332 terminate("sou %s has too many members: %d > %d\n", 333 tdesc_name(tp), i, CTF_MAX_VLEN); 334 } 335 336 if (tp->t_type == STRUCT) 337 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, isroot, i); 338 else 339 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, isroot, i); 340 341 write_sized_type_rec(b, &ctt, tp->t_size); 342 343 if (tp->t_size < CTF_LSTRUCT_THRESH) { 344 for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { 345 offset = strtab_insert(&b->ctb_strtab, 346 mp->ml_name); 347 348 ctm.ctm_name = CTF_TYPE_NAME(CTF_STRTAB_0, 349 offset); 350 ctm.ctm_type = mp->ml_type->t_id; 351 ctm.ctm_offset = mp->ml_offset; 352 ctf_buf_write(b, &ctm, sizeof (ctm)); 353 } 354 } else { 355 for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { 356 offset = strtab_insert(&b->ctb_strtab, 357 mp->ml_name); 358 359 ctlm.ctlm_name = CTF_TYPE_NAME(CTF_STRTAB_0, 360 offset); 361 ctlm.ctlm_type = mp->ml_type->t_id; 362 ctlm.ctlm_offsethi = 363 CTF_OFFSET_TO_LMEMHI(mp->ml_offset); 364 ctlm.ctlm_offsetlo = 365 CTF_OFFSET_TO_LMEMLO(mp->ml_offset); 366 ctf_buf_write(b, &ctlm, sizeof (ctlm)); 367 } 368 } 369 break; 370 371 case ENUM: 372 for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next) 373 i++; /* count up enum members */ 374 375 if (i > CTF_MAX_VLEN) { 376 printf("enum %s has too many values: %d > %d, truncating\n", 377 tdesc_name(tp), i, CTF_MAX_VLEN); 378 379 i = CTF_MAX_VLEN; 380 } 381 382 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i); 383 write_sized_type_rec(b, &ctt, tp->t_size); 384 385 for (ep = tp->t_emem; i && ep != NULL; ep = ep->el_next, i--) { 386 offset = strtab_insert(&b->ctb_strtab, ep->el_name); 387 cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); 388 cte.cte_value = ep->el_number; 389 ctf_buf_write(b, &cte, sizeof (cte)); 390 } 391 break; 392 393 case FORWARD: 394 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, isroot, 0); 395 ctt.ctt_type = 0; 396 write_unsized_type_rec(b, &ctt); 397 break; 398 399 case TYPEDEF: 400 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, isroot, 0); 401 ctt.ctt_type = tp->t_tdesc->t_id; 402 write_unsized_type_rec(b, &ctt); 403 break; 404 405 case VOLATILE: 406 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_VOLATILE, isroot, 0); 407 ctt.ctt_type = tp->t_tdesc->t_id; 408 write_unsized_type_rec(b, &ctt); 409 break; 410 411 case CONST: 412 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_CONST, isroot, 0); 413 ctt.ctt_type = tp->t_tdesc->t_id; 414 write_unsized_type_rec(b, &ctt); 415 break; 416 417 case FUNCTION: 418 i = tp->t_fndef->fn_nargs + tp->t_fndef->fn_vargs; 419 420 if (i > CTF_MAX_VLEN) { 421 terminate("function %s has too many args: %d > %d\n", 422 i, CTF_MAX_VLEN); 423 } 424 425 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, isroot, i); 426 ctt.ctt_type = tp->t_fndef->fn_ret->t_id; 427 write_unsized_type_rec(b, &ctt); 428 429 for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) { 430 id = tp->t_fndef->fn_args[i]->t_id; 431 ctf_buf_write(b, &id, sizeof (id)); 432 } 433 434 if (tp->t_fndef->fn_vargs) { 435 id = 0; 436 ctf_buf_write(b, &id, sizeof (id)); 437 i++; 438 } 439 440 if (i & 1) { 441 id = 0; 442 ctf_buf_write(b, &id, sizeof (id)); 443 } 444 break; 445 446 case RESTRICT: 447 ctt.ctt_info = CTF_TYPE_INFO(CTF_K_RESTRICT, isroot, 0); 448 ctt.ctt_type = tp->t_tdesc->t_id; 449 write_unsized_type_rec(b, &ctt); 450 break; 451 452 default: 453 warning("Can't write unknown type %d\n", tp->t_type); 454 } 455 456 debug(3, "Wrote type %d %s\n", tp->t_id, tdesc_name(tp)); 457 458 return (1); 459 } 460 461 typedef struct resbuf { 462 caddr_t rb_base; 463 caddr_t rb_ptr; 464 size_t rb_size; 465 z_stream rb_zstr; 466 } resbuf_t; 467 468 static void 469 rbzs_grow(resbuf_t *rb) 470 { 471 off_t ptroff = (caddr_t)rb->rb_zstr.next_out - rb->rb_base; 472 473 rb->rb_size += RES_BUF_CHUNK_SIZE; 474 rb->rb_base = xrealloc(rb->rb_base, rb->rb_size); 475 rb->rb_ptr = rb->rb_base + ptroff; 476 rb->rb_zstr.next_out = (Bytef *)(rb->rb_ptr); 477 rb->rb_zstr.avail_out += RES_BUF_CHUNK_SIZE; 478 } 479 480 static void 481 compress_start(resbuf_t *rb) 482 { 483 int rc; 484 485 rb->rb_zstr.zalloc = (alloc_func)0; 486 rb->rb_zstr.zfree = (free_func)0; 487 rb->rb_zstr.opaque = (voidpf)0; 488 489 if ((rc = deflateInit(&rb->rb_zstr, Z_BEST_COMPRESSION)) != Z_OK) 490 parseterminate("zlib start failed: %s", zError(rc)); 491 } 492 493 static ssize_t 494 compress_buffer(void *buf, size_t n, void *data) 495 { 496 resbuf_t *rb = (resbuf_t *)data; 497 int rc; 498 499 rb->rb_zstr.next_out = (Bytef *)rb->rb_ptr; 500 rb->rb_zstr.avail_out = rb->rb_size - (rb->rb_ptr - rb->rb_base); 501 rb->rb_zstr.next_in = buf; 502 rb->rb_zstr.avail_in = n; 503 504 while (rb->rb_zstr.avail_in) { 505 if (rb->rb_zstr.avail_out == 0) 506 rbzs_grow(rb); 507 508 if ((rc = deflate(&rb->rb_zstr, Z_NO_FLUSH)) != Z_OK) 509 parseterminate("zlib deflate failed: %s", zError(rc)); 510 } 511 rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out; 512 513 return (n); 514 } 515 516 static void 517 compress_flush(resbuf_t *rb, int type) 518 { 519 int rc; 520 521 for (;;) { 522 if (rb->rb_zstr.avail_out == 0) 523 rbzs_grow(rb); 524 525 rc = deflate(&rb->rb_zstr, type); 526 if ((type == Z_FULL_FLUSH && rc == Z_BUF_ERROR) || 527 (type == Z_FINISH && rc == Z_STREAM_END)) 528 break; 529 else if (rc != Z_OK) 530 parseterminate("zlib finish failed: %s", zError(rc)); 531 } 532 rb->rb_ptr = (caddr_t)rb->rb_zstr.next_out; 533 } 534 535 static void 536 compress_end(resbuf_t *rb) 537 { 538 int rc; 539 540 compress_flush(rb, Z_FINISH); 541 542 if ((rc = deflateEnd(&rb->rb_zstr)) != Z_OK) 543 parseterminate("zlib end failed: %s", zError(rc)); 544 } 545 546 /* 547 * Pad the buffer to a power-of-2 boundary 548 */ 549 static void 550 pad_buffer(ctf_buf_t *buf, int align) 551 { 552 uint_t cur = ctf_buf_cur(buf); 553 ssize_t topad = (align - (cur % align)) % align; 554 static const char pad[8] = { 0 }; 555 556 while (topad > 0) { 557 ctf_buf_write(buf, pad, (topad > 8 ? 8 : topad)); 558 topad -= 8; 559 } 560 } 561 562 static ssize_t 563 bcopy_data(void *buf, size_t n, void *data) 564 { 565 caddr_t *posp = (caddr_t *)data; 566 bcopy(buf, *posp, n); 567 *posp += n; 568 return (n); 569 } 570 571 static caddr_t 572 write_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp) 573 { 574 caddr_t outbuf; 575 caddr_t bufpos; 576 577 outbuf = xmalloc(sizeof (ctf_header_t) + (buf->ctb_ptr - buf->ctb_base) 578 + buf->ctb_strtab.str_size); 579 580 bufpos = outbuf; 581 (void) bcopy_data(h, sizeof (ctf_header_t), &bufpos); 582 (void) bcopy_data(buf->ctb_base, buf->ctb_ptr - buf->ctb_base, 583 &bufpos); 584 (void) strtab_write(&buf->ctb_strtab, bcopy_data, &bufpos); 585 *resszp = bufpos - outbuf; 586 return (outbuf); 587 } 588 589 /* 590 * Create the compression buffer, and fill it with the CTF and string 591 * table data. We flush the compression state between the two so the 592 * dictionary used for the string tables won't be polluted with values 593 * that made sense for the CTF data. 594 */ 595 static caddr_t 596 write_compressed_buffer(ctf_header_t *h, ctf_buf_t *buf, size_t *resszp) 597 { 598 resbuf_t resbuf; 599 resbuf.rb_size = RES_BUF_CHUNK_SIZE; 600 resbuf.rb_base = xmalloc(resbuf.rb_size); 601 bcopy(h, resbuf.rb_base, sizeof (ctf_header_t)); 602 resbuf.rb_ptr = resbuf.rb_base + sizeof (ctf_header_t); 603 604 compress_start(&resbuf); 605 (void) compress_buffer(buf->ctb_base, buf->ctb_ptr - buf->ctb_base, 606 &resbuf); 607 compress_flush(&resbuf, Z_FULL_FLUSH); 608 (void) strtab_write(&buf->ctb_strtab, compress_buffer, &resbuf); 609 compress_end(&resbuf); 610 611 *resszp = (resbuf.rb_ptr - resbuf.rb_base); 612 return (resbuf.rb_base); 613 } 614 615 caddr_t 616 ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress) 617 { 618 ctf_buf_t *buf = ctf_buf_new(); 619 ctf_header_t h; 620 caddr_t outbuf; 621 622 int i; 623 624 /* 625 * Prepare the header, and create the CTF output buffers. The data 626 * object section and function section are both lists of 2-byte 627 * integers; we pad these out to the next 4-byte boundary if needed. 628 */ 629 h.cth_magic = CTF_MAGIC; 630 h.cth_version = CTF_VERSION; 631 h.cth_flags = do_compress ? CTF_F_COMPRESS : 0; 632 h.cth_parlabel = strtab_insert(&buf->ctb_strtab, 633 iiburst->iib_td->td_parlabel); 634 h.cth_parname = strtab_insert(&buf->ctb_strtab, 635 iiburst->iib_td->td_parname); 636 637 h.cth_lbloff = 0; 638 (void) list_iter(iiburst->iib_td->td_labels, write_label, 639 buf); 640 641 pad_buffer(buf, 2); 642 h.cth_objtoff = ctf_buf_cur(buf); 643 for (i = 0; i < iiburst->iib_nobjts; i++) 644 write_objects(iiburst->iib_objts[i], buf); 645 646 pad_buffer(buf, 2); 647 h.cth_funcoff = ctf_buf_cur(buf); 648 for (i = 0; i < iiburst->iib_nfuncs; i++) 649 write_functions(iiburst->iib_funcs[i], buf); 650 651 pad_buffer(buf, 4); 652 h.cth_typeoff = ctf_buf_cur(buf); 653 (void) list_iter(iiburst->iib_types, write_type, buf); 654 655 debug(2, "CTF wrote %d types\n", list_count(iiburst->iib_types)); 656 657 h.cth_stroff = ctf_buf_cur(buf); 658 h.cth_strlen = strtab_size(&buf->ctb_strtab); 659 660 /* 661 * We only do compression for ctfmerge, as ctfconvert is only 662 * supposed to be used on intermediary build objects. This is 663 * significantly faster. 664 */ 665 if (do_compress) 666 outbuf = write_compressed_buffer(&h, buf, resszp); 667 else 668 outbuf = write_buffer(&h, buf, resszp); 669 670 ctf_buf_free(buf); 671 return (outbuf); 672 } 673 674 static void 675 get_ctt_size(ctf_type_t *ctt, size_t *sizep, size_t *incrementp) 676 { 677 if (ctt->ctt_size == CTF_LSIZE_SENT) { 678 *sizep = (size_t)CTF_TYPE_LSIZE(ctt); 679 *incrementp = sizeof (ctf_type_t); 680 } else { 681 *sizep = ctt->ctt_size; 682 *incrementp = sizeof (ctf_stype_t); 683 } 684 } 685 686 static int 687 count_types(ctf_header_t *h, caddr_t data) 688 { 689 caddr_t dptr = data + h->cth_typeoff; 690 int count = 0; 691 692 dptr = data + h->cth_typeoff; 693 while (dptr < data + h->cth_stroff) { 694 void *v = (void *) dptr; 695 ctf_type_t *ctt = v; 696 size_t vlen = CTF_INFO_VLEN(ctt->ctt_info); 697 size_t size, increment; 698 699 get_ctt_size(ctt, &size, &increment); 700 701 switch (CTF_INFO_KIND(ctt->ctt_info)) { 702 case CTF_K_INTEGER: 703 case CTF_K_FLOAT: 704 dptr += 4; 705 break; 706 case CTF_K_POINTER: 707 case CTF_K_FORWARD: 708 case CTF_K_TYPEDEF: 709 case CTF_K_VOLATILE: 710 case CTF_K_CONST: 711 case CTF_K_RESTRICT: 712 case CTF_K_FUNCTION: 713 dptr += sizeof (ushort_t) * (vlen + (vlen & 1)); 714 break; 715 case CTF_K_ARRAY: 716 dptr += sizeof (ctf_array_t); 717 break; 718 case CTF_K_STRUCT: 719 case CTF_K_UNION: 720 if (size < CTF_LSTRUCT_THRESH) 721 dptr += sizeof (ctf_member_t) * vlen; 722 else 723 dptr += sizeof (ctf_lmember_t) * vlen; 724 break; 725 case CTF_K_ENUM: 726 dptr += sizeof (ctf_enum_t) * vlen; 727 break; 728 case CTF_K_UNKNOWN: 729 break; 730 default: 731 parseterminate("Unknown CTF type %d (#%d) at %#x", 732 CTF_INFO_KIND(ctt->ctt_info), count, dptr - data); 733 } 734 735 dptr += increment; 736 count++; 737 } 738 739 debug(3, "CTF read %d types\n", count); 740 741 return (count); 742 } 743 744 /* 745 * Resurrect the labels stored in the CTF data, returning the index associated 746 * with a label provided by the caller. There are several cases, outlined 747 * below. Note that, given two labels, the one associated with the lesser type 748 * index is considered to be older than the other. 749 * 750 * 1. matchlbl == NULL - return the index of the most recent label. 751 * 2. matchlbl == "BASE" - return the index of the oldest label. 752 * 3. matchlbl != NULL, but doesn't match any labels in the section - warn 753 * the user, and proceed as if matchlbl == "BASE" (for safety). 754 * 4. matchlbl != NULL, and matches one of the labels in the section - return 755 * the type index associated with the label. 756 */ 757 static int 758 resurrect_labels(ctf_header_t *h, tdata_t *td, caddr_t ctfdata, char *matchlbl) 759 { 760 caddr_t buf = ctfdata + h->cth_lbloff; 761 caddr_t sbuf = ctfdata + h->cth_stroff; 762 size_t bufsz = h->cth_objtoff - h->cth_lbloff; 763 int lastidx = 0, baseidx = -1; 764 char *baselabel = NULL; 765 ctf_lblent_t *ctl; 766 void *v = (void *) buf; 767 768 for (ctl = v; (caddr_t)ctl < buf + bufsz; ctl++) { 769 char *label = sbuf + ctl->ctl_label; 770 771 lastidx = ctl->ctl_typeidx; 772 773 debug(3, "Resurrected label %s type idx %d\n", label, lastidx); 774 775 tdata_label_add(td, label, lastidx); 776 777 if (baseidx == -1) { 778 baseidx = lastidx; 779 baselabel = label; 780 if (matchlbl != NULL && streq(matchlbl, "BASE")) 781 return (lastidx); 782 } 783 784 if (matchlbl != NULL && streq(label, matchlbl)) 785 return (lastidx); 786 } 787 788 if (matchlbl != NULL) { 789 /* User provided a label that didn't match */ 790 warning("%s: Cannot find label `%s' - using base (%s)\n", 791 curfile, matchlbl, (baselabel ? baselabel : "NONE")); 792 793 tdata_label_free(td); 794 tdata_label_add(td, baselabel, baseidx); 795 796 return (baseidx); 797 } 798 799 return (lastidx); 800 } 801 802 static void 803 resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 804 caddr_t ctfdata, symit_data_t *si) 805 { 806 caddr_t buf = ctfdata + h->cth_objtoff; 807 size_t bufsz = h->cth_funcoff - h->cth_objtoff; 808 caddr_t dptr; 809 810 symit_reset(si); 811 for (dptr = buf; dptr < buf + bufsz; dptr += 2) { 812 void *v = (void *) dptr; 813 ushort_t id = *((ushort_t *)v); 814 iidesc_t *ii; 815 GElf_Sym *sym; 816 817 if (!(sym = symit_next(si, STT_OBJECT)) && id != 0) { 818 parseterminate( 819 "Unexpected end of object symbols at %x of %x", 820 dptr - buf, bufsz); 821 } 822 823 if (id == 0) { 824 debug(3, "Skipping null object\n"); 825 continue; 826 } else if (id >= tdsize) { 827 parseterminate("(1) Reference to invalid type %d", id); 828 } 829 830 ii = iidesc_new(symit_name(si)); 831 ii->ii_dtype = tdarr[id]; 832 if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { 833 ii->ii_type = II_SVAR; 834 ii->ii_owner = xstrdup(symit_curfile(si)); 835 } else 836 ii->ii_type = II_GVAR; 837 hash_add(td->td_iihash, ii); 838 839 debug(3, "Resurrected %s object %s (%d) from %s\n", 840 (ii->ii_type == II_GVAR ? "global" : "static"), 841 ii->ii_name, id, (ii->ii_owner ? ii->ii_owner : "(none)")); 842 } 843 } 844 845 static void 846 resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 847 caddr_t ctfdata, symit_data_t *si) 848 { 849 caddr_t buf = ctfdata + h->cth_funcoff; 850 size_t bufsz = h->cth_typeoff - h->cth_funcoff; 851 caddr_t dptr = buf; 852 iidesc_t *ii; 853 ushort_t info; 854 ushort_t retid; 855 GElf_Sym *sym; 856 int i; 857 858 symit_reset(si); 859 while (dptr < buf + bufsz) { 860 void *v = (void *) dptr; 861 info = *((ushort_t *)v); 862 dptr += 2; 863 864 if (!(sym = symit_next(si, STT_FUNC)) && info != 0) 865 parseterminate("Unexpected end of function symbols"); 866 867 if (info == 0) { 868 debug(3, "Skipping null function (%s)\n", 869 symit_name(si)); 870 continue; 871 } 872 873 v = (void *) dptr; 874 retid = *((ushort_t *)v); 875 dptr += 2; 876 877 if (retid >= tdsize) 878 parseterminate("(2) Reference to invalid type %d", retid); 879 880 ii = iidesc_new(symit_name(si)); 881 ii->ii_dtype = tdarr[retid]; 882 if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { 883 ii->ii_type = II_SFUN; 884 ii->ii_owner = xstrdup(symit_curfile(si)); 885 } else 886 ii->ii_type = II_GFUN; 887 ii->ii_nargs = CTF_INFO_VLEN(info); 888 if (ii->ii_nargs) 889 ii->ii_args = 890 xmalloc(sizeof (tdesc_t *) * ii->ii_nargs); 891 892 for (i = 0; i < ii->ii_nargs; i++, dptr += 2) { 893 v = (void *) dptr; 894 ushort_t id = *((ushort_t *)v); 895 if (id >= tdsize) 896 parseterminate("(3) Reference to invalid type %d (tdsize %d) ii_nargs %d %s", 897 id, tdsize, ii->ii_nargs, ii->ii_name); 898 ii->ii_args[i] = tdarr[id]; 899 } 900 901 if (ii->ii_nargs && ii->ii_args[ii->ii_nargs - 1] == NULL) { 902 ii->ii_nargs--; 903 ii->ii_vargs = 1; 904 } 905 906 hash_add(td->td_iihash, ii); 907 908 debug(3, "Resurrected %s function %s (%d, %d args)\n", 909 (ii->ii_type == II_GFUN ? "global" : "static"), 910 ii->ii_name, retid, ii->ii_nargs); 911 } 912 } 913 914 static void 915 resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, 916 caddr_t ctfdata, int maxid) 917 { 918 caddr_t buf = ctfdata + h->cth_typeoff; 919 size_t bufsz = h->cth_stroff - h->cth_typeoff; 920 caddr_t sbuf = ctfdata + h->cth_stroff; 921 caddr_t dptr = buf; 922 tdesc_t *tdp; 923 uint_t data; 924 uint_t encoding; 925 size_t size, increment; 926 int tcnt; 927 int iicnt = 0; 928 tid_t tid, argid; 929 int kind, vlen; 930 int i; 931 932 elist_t **epp; 933 mlist_t **mpp; 934 intr_t *ip; 935 936 ctf_type_t *ctt; 937 ctf_array_t *cta; 938 ctf_enum_t *cte; 939 940 /* 941 * A maxid of zero indicates a request to resurrect all types, so reset 942 * maxid to the maximum type id. 943 */ 944 if (maxid == 0) 945 maxid = CTF_MAX_TYPE; 946 947 for (dptr = buf, tcnt = 0, tid = 1; dptr < buf + bufsz; tcnt++, tid++) { 948 if (tid > maxid) 949 break; 950 951 if (tid >= tdsize) 952 parseterminate("(4) Reference to invalid type %d", tid); 953 954 void *v = (void *) dptr; 955 ctt = v; 956 957 get_ctt_size(ctt, &size, &increment); 958 dptr += increment; 959 960 tdp = tdarr[tid]; 961 962 if (CTF_NAME_STID(ctt->ctt_name) != CTF_STRTAB_0) 963 parseterminate( 964 "Unable to cope with non-zero strtab id"); 965 if (CTF_NAME_OFFSET(ctt->ctt_name) != 0) { 966 tdp->t_name = 967 xstrdup(sbuf + CTF_NAME_OFFSET(ctt->ctt_name)); 968 } else 969 tdp->t_name = NULL; 970 971 kind = CTF_INFO_KIND(ctt->ctt_info); 972 vlen = CTF_INFO_VLEN(ctt->ctt_info); 973 974 switch (kind) { 975 case CTF_K_INTEGER: 976 tdp->t_type = INTRINSIC; 977 tdp->t_size = size; 978 979 v = (void *) dptr; 980 data = *((uint_t *)v); 981 dptr += sizeof (uint_t); 982 encoding = CTF_INT_ENCODING(data); 983 984 ip = xmalloc(sizeof (intr_t)); 985 ip->intr_type = INTR_INT; 986 ip->intr_signed = (encoding & CTF_INT_SIGNED) ? 1 : 0; 987 988 if (encoding & CTF_INT_CHAR) 989 ip->intr_iformat = 'c'; 990 else if (encoding & CTF_INT_BOOL) 991 ip->intr_iformat = 'b'; 992 else if (encoding & CTF_INT_VARARGS) 993 ip->intr_iformat = 'v'; 994 else 995 ip->intr_iformat = '\0'; 996 997 ip->intr_offset = CTF_INT_OFFSET(data); 998 ip->intr_nbits = CTF_INT_BITS(data); 999 tdp->t_intr = ip; 1000 break; 1001 1002 case CTF_K_FLOAT: 1003 tdp->t_type = INTRINSIC; 1004 tdp->t_size = size; 1005 1006 v = (void *) dptr; 1007 data = *((uint_t *)v); 1008 dptr += sizeof (uint_t); 1009 1010 ip = xcalloc(sizeof (intr_t)); 1011 ip->intr_type = INTR_REAL; 1012 ip->intr_fformat = CTF_FP_ENCODING(data); 1013 ip->intr_offset = CTF_FP_OFFSET(data); 1014 ip->intr_nbits = CTF_FP_BITS(data); 1015 tdp->t_intr = ip; 1016 break; 1017 1018 case CTF_K_POINTER: 1019 tdp->t_type = POINTER; 1020 tdp->t_tdesc = tdarr[ctt->ctt_type]; 1021 break; 1022 1023 case CTF_K_ARRAY: 1024 tdp->t_type = ARRAY; 1025 tdp->t_size = size; 1026 1027 v = (void *) dptr; 1028 cta = v; 1029 dptr += sizeof (ctf_array_t); 1030 1031 tdp->t_ardef = xmalloc(sizeof (ardef_t)); 1032 tdp->t_ardef->ad_contents = tdarr[cta->cta_contents]; 1033 tdp->t_ardef->ad_idxtype = tdarr[cta->cta_index]; 1034 tdp->t_ardef->ad_nelems = cta->cta_nelems; 1035 break; 1036 1037 case CTF_K_STRUCT: 1038 case CTF_K_UNION: 1039 tdp->t_type = (kind == CTF_K_STRUCT ? STRUCT : UNION); 1040 tdp->t_size = size; 1041 1042 if (size < CTF_LSTRUCT_THRESH) { 1043 for (i = 0, mpp = &tdp->t_members; i < vlen; 1044 i++, mpp = &((*mpp)->ml_next)) { 1045 v = (void *) dptr; 1046 ctf_member_t *ctm = v; 1047 dptr += sizeof (ctf_member_t); 1048 1049 *mpp = xmalloc(sizeof (mlist_t)); 1050 (*mpp)->ml_name = xstrdup(sbuf + 1051 ctm->ctm_name); 1052 (*mpp)->ml_type = tdarr[ctm->ctm_type]; 1053 (*mpp)->ml_offset = ctm->ctm_offset; 1054 (*mpp)->ml_size = 0; 1055 if (ctm->ctm_type > ntypes) { 1056 parseterminate("Invalid member type ctm_type=%d", ctm->ctm_type); 1057 } 1058 } 1059 } else { 1060 for (i = 0, mpp = &tdp->t_members; i < vlen; 1061 i++, mpp = &((*mpp)->ml_next)) { 1062 v = (void *) dptr; 1063 ctf_lmember_t *ctlm = v; 1064 dptr += sizeof (ctf_lmember_t); 1065 1066 *mpp = xmalloc(sizeof (mlist_t)); 1067 (*mpp)->ml_name = xstrdup(sbuf + 1068 ctlm->ctlm_name); 1069 (*mpp)->ml_type = 1070 tdarr[ctlm->ctlm_type]; 1071 (*mpp)->ml_offset = 1072 (int)CTF_LMEM_OFFSET(ctlm); 1073 (*mpp)->ml_size = 0; 1074 if (ctlm->ctlm_type > ntypes) { 1075 parseterminate("Invalid lmember type ctlm_type=%d", ctlm->ctlm_type); 1076 } 1077 } 1078 } 1079 1080 *mpp = NULL; 1081 break; 1082 1083 case CTF_K_ENUM: 1084 tdp->t_type = ENUM; 1085 tdp->t_size = size; 1086 1087 for (i = 0, epp = &tdp->t_emem; i < vlen; 1088 i++, epp = &((*epp)->el_next)) { 1089 v = (void *) dptr; 1090 cte = v; 1091 dptr += sizeof (ctf_enum_t); 1092 1093 *epp = xmalloc(sizeof (elist_t)); 1094 (*epp)->el_name = xstrdup(sbuf + cte->cte_name); 1095 (*epp)->el_number = cte->cte_value; 1096 } 1097 *epp = NULL; 1098 break; 1099 1100 case CTF_K_FORWARD: 1101 tdp->t_type = FORWARD; 1102 list_add(&td->td_fwdlist, tdp); 1103 break; 1104 1105 case CTF_K_TYPEDEF: 1106 tdp->t_type = TYPEDEF; 1107 tdp->t_tdesc = tdarr[ctt->ctt_type]; 1108 break; 1109 1110 case CTF_K_VOLATILE: 1111 tdp->t_type = VOLATILE; 1112 tdp->t_tdesc = tdarr[ctt->ctt_type]; 1113 break; 1114 1115 case CTF_K_CONST: 1116 tdp->t_type = CONST; 1117 tdp->t_tdesc = tdarr[ctt->ctt_type]; 1118 break; 1119 1120 case CTF_K_FUNCTION: 1121 tdp->t_type = FUNCTION; 1122 tdp->t_fndef = xcalloc(sizeof (fndef_t)); 1123 tdp->t_fndef->fn_ret = tdarr[ctt->ctt_type]; 1124 1125 v = (void *) (dptr + (sizeof (ushort_t) * (vlen - 1))); 1126 if (vlen > 0 && *(ushort_t *)v == 0) 1127 tdp->t_fndef->fn_vargs = 1; 1128 1129 tdp->t_fndef->fn_nargs = vlen - tdp->t_fndef->fn_vargs; 1130 tdp->t_fndef->fn_args = xcalloc(sizeof (tdesc_t) * 1131 vlen - tdp->t_fndef->fn_vargs); 1132 1133 for (i = 0; i < vlen; i++) { 1134 v = (void *) dptr; 1135 argid = *(ushort_t *)v; 1136 dptr += sizeof (ushort_t); 1137 1138 if (argid != 0) 1139 tdp->t_fndef->fn_args[i] = tdarr[argid]; 1140 } 1141 1142 if (vlen & 1) 1143 dptr += sizeof (ushort_t); 1144 break; 1145 1146 case CTF_K_RESTRICT: 1147 tdp->t_type = RESTRICT; 1148 tdp->t_tdesc = tdarr[ctt->ctt_type]; 1149 break; 1150 1151 case CTF_K_UNKNOWN: 1152 break; 1153 1154 default: 1155 warning("Can't parse unknown CTF type %d\n", kind); 1156 } 1157 1158 if (CTF_INFO_ISROOT(ctt->ctt_info)) { 1159 iidesc_t *ii = iidesc_new(tdp->t_name); 1160 if (tdp->t_type == STRUCT || tdp->t_type == UNION || 1161 tdp->t_type == ENUM) 1162 ii->ii_type = II_SOU; 1163 else 1164 ii->ii_type = II_TYPE; 1165 ii->ii_dtype = tdp; 1166 hash_add(td->td_iihash, ii); 1167 1168 iicnt++; 1169 } 1170 1171 debug(3, "Resurrected %d %stype %s (%d)\n", tdp->t_type, 1172 (CTF_INFO_ISROOT(ctt->ctt_info) ? "root " : ""), 1173 tdesc_name(tdp), tdp->t_id); 1174 } 1175 1176 debug(3, "Resurrected %d types (%d were roots)\n", tcnt, iicnt); 1177 } 1178 1179 /* 1180 * For lack of other inspiration, we're going to take the boring route. We 1181 * count the number of types. This lets us malloc that many tdesc structs 1182 * before we start filling them in. This has the advantage of allowing us to 1183 * avoid a merge-esque remap step. 1184 */ 1185 static tdata_t * 1186 ctf_parse(ctf_header_t *h, caddr_t buf, symit_data_t *si, char *label) 1187 { 1188 tdata_t *td = tdata_new(); 1189 tdesc_t **tdarr; 1190 int idx, i; 1191 1192 ntypes = count_types(h, buf); 1193 1194 /* shudder */ 1195 tdarr = xcalloc(sizeof (tdesc_t *) * (ntypes + 1)); 1196 tdarr[0] = NULL; 1197 for (i = 1; i <= ntypes; i++) { 1198 tdarr[i] = xcalloc(sizeof (tdesc_t)); 1199 tdarr[i]->t_id = i; 1200 } 1201 1202 td->td_parlabel = xstrdup(buf + h->cth_stroff + h->cth_parlabel); 1203 1204 /* we have the technology - we can rebuild them */ 1205 idx = resurrect_labels(h, td, buf, label); 1206 1207 resurrect_objects(h, td, tdarr, ntypes + 1, buf, si); 1208 resurrect_functions(h, td, tdarr, ntypes + 1, buf, si); 1209 resurrect_types(h, td, tdarr, ntypes + 1, buf, idx); 1210 1211 free(tdarr); 1212 1213 td->td_nextid = ntypes + 1; 1214 1215 return (td); 1216 } 1217 1218 static size_t 1219 decompress_ctf(caddr_t cbuf, size_t cbufsz, caddr_t dbuf, size_t dbufsz) 1220 { 1221 z_stream zstr; 1222 int rc; 1223 1224 zstr.zalloc = (alloc_func)0; 1225 zstr.zfree = (free_func)0; 1226 zstr.opaque = (voidpf)0; 1227 1228 zstr.next_in = (Bytef *)cbuf; 1229 zstr.avail_in = cbufsz; 1230 zstr.next_out = (Bytef *)dbuf; 1231 zstr.avail_out = dbufsz; 1232 1233 if ((rc = inflateInit(&zstr)) != Z_OK || 1234 (rc = inflate(&zstr, Z_NO_FLUSH)) != Z_STREAM_END || 1235 (rc = inflateEnd(&zstr)) != Z_OK) { 1236 warning("CTF decompress zlib error %s\n", zError(rc)); 1237 return (0); 1238 } 1239 1240 debug(3, "reflated %lu bytes to %lu, pointer at %d\n", 1241 zstr.total_in, zstr.total_out, (caddr_t)zstr.next_in - cbuf); 1242 1243 return (zstr.total_out); 1244 } 1245 1246 /* 1247 * Reconstruct the type tree from a given buffer of CTF data. Only the types 1248 * up to the type associated with the provided label, inclusive, will be 1249 * reconstructed. If a NULL label is provided, all types will be reconstructed. 1250 * 1251 * This function won't work on files that have been uniquified. 1252 */ 1253 tdata_t * 1254 ctf_load(char *file, caddr_t buf, size_t bufsz, symit_data_t *si, char *label) 1255 { 1256 ctf_header_t *h; 1257 caddr_t ctfdata; 1258 size_t ctfdatasz; 1259 tdata_t *td; 1260 1261 curfile = file; 1262 1263 if (bufsz < sizeof (ctf_header_t)) 1264 parseterminate("Corrupt CTF - short header"); 1265 1266 void *v = (void *) buf; 1267 h = v; 1268 buf += sizeof (ctf_header_t); 1269 bufsz -= sizeof (ctf_header_t); 1270 1271 if (h->cth_magic != CTF_MAGIC) 1272 parseterminate("Corrupt CTF - bad magic 0x%x", h->cth_magic); 1273 1274 if (h->cth_version != CTF_VERSION) 1275 parseterminate("Unknown CTF version %d", h->cth_version); 1276 1277 ctfdatasz = h->cth_stroff + h->cth_strlen; 1278 if (h->cth_flags & CTF_F_COMPRESS) { 1279 size_t actual; 1280 1281 ctfdata = xmalloc(ctfdatasz); 1282 if ((actual = decompress_ctf(buf, bufsz, ctfdata, ctfdatasz)) != 1283 ctfdatasz) { 1284 parseterminate("Corrupt CTF - short decompression " 1285 "(was %d, expecting %d)", actual, ctfdatasz); 1286 } 1287 } else { 1288 ctfdata = buf; 1289 ctfdatasz = bufsz; 1290 } 1291 1292 td = ctf_parse(h, ctfdata, si, label); 1293 1294 if (h->cth_flags & CTF_F_COMPRESS) 1295 free(ctfdata); 1296 1297 curfile = NULL; 1298 1299 return (td); 1300 } 1301