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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <mdb/mdb_ctf.h> 30 #include <mdb/mdb_ctf_impl.h> 31 #include <mdb/mdb_err.h> 32 #include <mdb/mdb_modapi.h> 33 #include <mdb/mdb_string.h> 34 #include <mdb/mdb.h> 35 #include <mdb/mdb_debug.h> 36 37 #include <libctf.h> 38 #include <string.h> 39 40 typedef struct tnarg { 41 mdb_tgt_t *tn_tgt; /* target to use for lookup */ 42 const char *tn_name; /* query string to lookup */ 43 ctf_file_t *tn_fp; /* CTF container from match */ 44 ctf_id_t tn_id; /* CTF type ID from match */ 45 } tnarg_t; 46 47 typedef struct type_iter { 48 mdb_ctf_type_f *ti_cb; 49 void *ti_arg; 50 ctf_file_t *ti_fp; 51 } type_iter_t; 52 53 typedef struct member_iter { 54 mdb_ctf_member_f *mi_cb; 55 void *mi_arg; 56 ctf_file_t *mi_fp; 57 } member_iter_t; 58 59 typedef struct type_visit { 60 mdb_ctf_visit_f *tv_cb; 61 void *tv_arg; 62 ctf_file_t *tv_fp; 63 } type_visit_t; 64 65 typedef struct mbr_info { 66 const char *mbr_member; 67 ulong_t *mbr_offp; 68 mdb_ctf_id_t *mbr_typep; 69 } mbr_info_t; 70 71 static void 72 set_ctf_id(mdb_ctf_id_t *p, ctf_file_t *fp, ctf_id_t id) 73 { 74 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p; 75 76 mcip->mci_fp = fp; 77 mcip->mci_id = id; 78 } 79 80 /* 81 * Callback function for mdb_tgt_object_iter used from name_to_type, below, 82 * to search the CTF namespace for a given object file. 83 */ 84 /*ARGSUSED*/ 85 static int 86 obj_lookup(void *data, const mdb_map_t *mp, const char *name) 87 { 88 tnarg_t *tnp = data; 89 ctf_file_t *fp; 90 ctf_id_t id; 91 92 if ((fp = mdb_tgt_name_to_ctf(tnp->tn_tgt, name)) != NULL && 93 (id = ctf_lookup_by_name(fp, tnp->tn_name)) != CTF_ERR) { 94 tnp->tn_fp = fp; 95 tnp->tn_id = id; 96 97 /* 98 * We may have found a forward declaration. If we did, we'll 99 * note the ID and file pointer, but we'll keep searching in 100 * an attempt to find the real thing. If we found something 101 * real (i.e. not a forward), we stop the iteration. 102 */ 103 return (ctf_type_kind(fp, id) == CTF_K_FORWARD ? 0 : -1); 104 } 105 106 return (0); 107 } 108 109 /* 110 * Convert a string type name with an optional leading object specifier into 111 * the corresponding CTF file container and type ID. If an error occurs, we 112 * print an appropriate message and return NULL. 113 */ 114 static ctf_file_t * 115 name_to_type(mdb_tgt_t *t, const char *cname, ctf_id_t *idp) 116 { 117 const char *object = MDB_TGT_OBJ_EXEC; 118 ctf_file_t *fp = NULL; 119 ctf_id_t id; 120 tnarg_t arg; 121 char *p, *s; 122 char buf[MDB_SYM_NAMLEN]; 123 char *name = &buf[0]; 124 125 (void) mdb_snprintf(buf, sizeof (buf), "%s", cname); 126 127 if ((p = strrsplit(name, '`')) != NULL) { 128 /* 129 * We need to shuffle things around a little to support 130 * type names of the form "struct module`name". 131 */ 132 if ((s = strsplit(name, ' ')) != NULL) { 133 bcopy(cname + (s - name), name, (p - s) - 1); 134 name[(p - s) - 1] = '\0'; 135 bcopy(cname, name + (p - s), s - name); 136 p = name + (p - s); 137 } 138 if (*name != '\0') 139 object = name; 140 name = p; 141 } 142 143 /* 144 * Attempt to look up the name in the primary object file. If this 145 * fails and the name was unscoped, search all remaining object files. 146 */ 147 if (((fp = mdb_tgt_name_to_ctf(t, object)) == NULL || 148 (id = ctf_lookup_by_name(fp, name)) == CTF_ERR || 149 ctf_type_kind(fp, id) == CTF_K_FORWARD) && 150 object == MDB_TGT_OBJ_EXEC) { 151 152 arg.tn_tgt = t; 153 arg.tn_name = name; 154 arg.tn_fp = NULL; 155 arg.tn_id = CTF_ERR; 156 157 (void) mdb_tgt_object_iter(t, obj_lookup, &arg); 158 159 if (arg.tn_id != CTF_ERR) { 160 fp = arg.tn_fp; 161 id = arg.tn_id; 162 } 163 } 164 165 if (fp == NULL) 166 return (NULL); /* errno is set for us */ 167 168 if (id == CTF_ERR) { 169 (void) set_errno(ctf_to_errno(ctf_errno(fp))); 170 return (NULL); 171 } 172 173 *idp = id; 174 return (fp); 175 } 176 177 /* 178 * Check to see if there is ctf data in the given object. This is useful 179 * so that we don't enter some loop where every call to lookup fails. 180 */ 181 int 182 mdb_ctf_enabled_by_object(const char *object) 183 { 184 mdb_tgt_t *t = mdb.m_target; 185 186 return (mdb_tgt_name_to_ctf(t, object) != NULL); 187 } 188 189 int 190 mdb_ctf_lookup_by_name(const char *name, mdb_ctf_id_t *p) 191 { 192 ctf_file_t *fp = NULL; 193 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p; 194 mdb_tgt_t *t = mdb.m_target; 195 196 if (mcip == NULL) 197 return (set_errno(EINVAL)); 198 199 if ((fp = name_to_type(t, name, &mcip->mci_id)) == NULL) { 200 mdb_ctf_type_invalidate(p); 201 return (-1); /* errno is set for us */ 202 } 203 204 mcip->mci_fp = fp; 205 206 return (0); 207 } 208 209 int 210 mdb_ctf_lookup_by_symbol(const GElf_Sym *symp, const mdb_syminfo_t *sip, 211 mdb_ctf_id_t *p) 212 { 213 ctf_file_t *fp = NULL; 214 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p; 215 mdb_tgt_t *t = mdb.m_target; 216 217 if (mcip == NULL) 218 return (set_errno(EINVAL)); 219 220 if (symp == NULL || sip == NULL) { 221 mdb_ctf_type_invalidate(p); 222 return (set_errno(EINVAL)); 223 } 224 225 if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL) { 226 mdb_ctf_type_invalidate(p); 227 return (-1); /* errno is set for us */ 228 } 229 230 if ((mcip->mci_id = ctf_lookup_by_symbol(fp, sip->sym_id)) == CTF_ERR) { 231 mdb_ctf_type_invalidate(p); 232 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 233 } 234 235 mcip->mci_fp = fp; 236 237 return (0); 238 } 239 240 int 241 mdb_ctf_lookup_by_addr(uintptr_t addr, mdb_ctf_id_t *p) 242 { 243 GElf_Sym sym; 244 mdb_syminfo_t si; 245 char name[MDB_SYM_NAMLEN]; 246 const mdb_map_t *mp; 247 mdb_tgt_t *t = mdb.m_target; 248 const char *obj, *c; 249 250 if (p == NULL) 251 return (set_errno(EINVAL)); 252 253 if (mdb_tgt_lookup_by_addr(t, addr, MDB_TGT_SYM_EXACT, name, 254 sizeof (name), NULL, NULL) == -1) { 255 mdb_ctf_type_invalidate(p); 256 return (-1); /* errno is set for us */ 257 } 258 259 if ((c = strrsplit(name, '`')) != NULL) { 260 obj = name; 261 } else { 262 if ((mp = mdb_tgt_addr_to_map(t, addr)) == NULL) { 263 mdb_ctf_type_invalidate(p); 264 return (-1); /* errno is set for us */ 265 } 266 267 obj = mp->map_name; 268 c = name; 269 } 270 271 if (mdb_tgt_lookup_by_name(t, obj, c, &sym, &si) == -1) { 272 mdb_ctf_type_invalidate(p); 273 return (-1); /* errno is set for us */ 274 } 275 276 return (mdb_ctf_lookup_by_symbol(&sym, &si, p)); 277 } 278 279 int 280 mdb_ctf_module_lookup(const char *name, mdb_ctf_id_t *p) 281 { 282 ctf_file_t *fp; 283 ctf_id_t id; 284 mdb_module_t *mod; 285 286 if ((mod = mdb_get_module()) == NULL) 287 return (set_errno(EMDB_CTX)); 288 289 if ((fp = mod->mod_ctfp) == NULL) 290 return (set_errno(EMDB_NOCTF)); 291 292 if ((id = ctf_lookup_by_name(fp, name)) == CTF_ERR) 293 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 294 295 set_ctf_id(p, fp, id); 296 297 return (0); 298 } 299 300 /*ARGSUSED*/ 301 int 302 mdb_ctf_func_info(const GElf_Sym *symp, const mdb_syminfo_t *sip, 303 mdb_ctf_funcinfo_t *mfp) 304 { 305 ctf_file_t *fp = NULL; 306 ctf_funcinfo_t f; 307 mdb_tgt_t *t = mdb.m_target; 308 char name[MDB_SYM_NAMLEN]; 309 const mdb_map_t *mp; 310 mdb_syminfo_t si; 311 int err; 312 313 if (symp == NULL || mfp == NULL) 314 return (set_errno(EINVAL)); 315 316 /* 317 * In case the input symbol came from a merged or private symbol table, 318 * re-lookup the address as a symbol, and then perform a fully scoped 319 * lookup of that symbol name to get the mdb_syminfo_t for its CTF. 320 */ 321 if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL || 322 (mp = mdb_tgt_addr_to_map(t, symp->st_value)) == NULL || 323 mdb_tgt_lookup_by_addr(t, symp->st_value, MDB_TGT_SYM_FUZZY, 324 name, sizeof (name), NULL, NULL) != 0) 325 return (-1); /* errno is set for us */ 326 327 if (strchr(name, '`') != NULL) 328 err = mdb_tgt_lookup_by_scope(t, name, NULL, &si); 329 else 330 err = mdb_tgt_lookup_by_name(t, mp->map_name, name, NULL, &si); 331 332 if (err != 0) 333 return (-1); /* errno is set for us */ 334 335 if (ctf_func_info(fp, si.sym_id, &f) == CTF_ERR) 336 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 337 338 set_ctf_id(&mfp->mtf_return, fp, f.ctc_return); 339 mfp->mtf_argc = f.ctc_argc; 340 mfp->mtf_flags = f.ctc_flags; 341 mfp->mtf_symidx = si.sym_id; 342 343 return (0); 344 } 345 346 int 347 mdb_ctf_func_args(const mdb_ctf_funcinfo_t *funcp, uint_t len, 348 mdb_ctf_id_t *argv) 349 { 350 ctf_file_t *fp; 351 ctf_id_t cargv[32]; 352 int i; 353 354 if (len > (sizeof (cargv) / sizeof (cargv[0]))) 355 return (set_errno(EINVAL)); 356 357 if (funcp == NULL || argv == NULL) 358 return (set_errno(EINVAL)); 359 360 fp = mdb_ctf_type_file(funcp->mtf_return); 361 362 if (ctf_func_args(fp, funcp->mtf_symidx, len, cargv) == CTF_ERR) 363 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 364 365 for (i = MIN(len, funcp->mtf_argc) - 1; i >= 0; i--) { 366 set_ctf_id(&argv[i], fp, cargv[i]); 367 } 368 369 return (0); 370 } 371 372 void 373 mdb_ctf_type_invalidate(mdb_ctf_id_t *idp) 374 { 375 set_ctf_id(idp, NULL, CTF_ERR); 376 } 377 378 int 379 mdb_ctf_type_valid(mdb_ctf_id_t id) 380 { 381 return (((mdb_ctf_impl_t *)&id)->mci_id != CTF_ERR); 382 } 383 384 int 385 mdb_ctf_type_cmp(mdb_ctf_id_t aid, mdb_ctf_id_t bid) 386 { 387 mdb_ctf_impl_t *aidp = (mdb_ctf_impl_t *)&aid; 388 mdb_ctf_impl_t *bidp = (mdb_ctf_impl_t *)&bid; 389 390 return (ctf_type_cmp(aidp->mci_fp, aidp->mci_id, 391 bidp->mci_fp, bidp->mci_id)); 392 } 393 394 int 395 mdb_ctf_type_resolve(mdb_ctf_id_t mid, mdb_ctf_id_t *outp) 396 { 397 ctf_id_t id; 398 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)∣ 399 400 if ((id = ctf_type_resolve(idp->mci_fp, idp->mci_id)) == CTF_ERR) { 401 if (outp) 402 mdb_ctf_type_invalidate(outp); 403 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 404 } 405 406 if (outp != NULL) 407 set_ctf_id(outp, idp->mci_fp, id); 408 409 return (0); 410 } 411 412 char * 413 mdb_ctf_type_name(mdb_ctf_id_t id, char *buf, size_t len) 414 { 415 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 416 char *ret; 417 418 if (!mdb_ctf_type_valid(id)) { 419 (void) set_errno(EINVAL); 420 return (NULL); 421 } 422 423 ret = ctf_type_name(idp->mci_fp, idp->mci_id, buf, len); 424 if (ret == NULL) 425 (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))); 426 427 return (ret); 428 } 429 430 ssize_t 431 mdb_ctf_type_size(mdb_ctf_id_t id) 432 { 433 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 434 ssize_t ret; 435 436 if ((ret = ctf_type_size(idp->mci_fp, idp->mci_id)) == CTF_ERR) 437 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 438 439 return (ret); 440 } 441 442 int 443 mdb_ctf_type_kind(mdb_ctf_id_t id) 444 { 445 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 446 int ret; 447 448 if ((ret = ctf_type_kind(idp->mci_fp, idp->mci_id)) == CTF_ERR) 449 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 450 451 return (ret); 452 } 453 454 int 455 mdb_ctf_type_reference(mdb_ctf_id_t mid, mdb_ctf_id_t *outp) 456 { 457 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)∣ 458 ctf_id_t id; 459 460 if ((id = ctf_type_reference(idp->mci_fp, idp->mci_id)) == CTF_ERR) { 461 if (outp) 462 mdb_ctf_type_invalidate(outp); 463 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 464 } 465 466 if (outp != NULL) 467 set_ctf_id(outp, idp->mci_fp, id); 468 469 return (0); 470 } 471 472 473 int 474 mdb_ctf_type_encoding(mdb_ctf_id_t id, ctf_encoding_t *ep) 475 { 476 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 477 478 if (ctf_type_encoding(idp->mci_fp, idp->mci_id, ep) == CTF_ERR) 479 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 480 481 return (0); 482 } 483 484 /* 485 * callback proxy for mdb_ctf_type_visit 486 */ 487 static int 488 type_cb(const char *name, ctf_id_t type, ulong_t off, int depth, void *arg) 489 { 490 type_visit_t *tvp = arg; 491 mdb_ctf_id_t id; 492 493 set_ctf_id(&id, tvp->tv_fp, type); 494 495 return (tvp->tv_cb(name, id, off, depth, tvp->tv_arg)); 496 } 497 498 int 499 mdb_ctf_type_visit(mdb_ctf_id_t id, mdb_ctf_visit_f *func, void *arg) 500 { 501 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 502 type_visit_t tv; 503 int ret; 504 505 tv.tv_cb = func; 506 tv.tv_arg = arg; 507 tv.tv_fp = idp->mci_fp; 508 509 ret = ctf_type_visit(idp->mci_fp, idp->mci_id, type_cb, &tv); 510 511 if (ret == CTF_ERR) 512 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 513 514 return (ret); 515 } 516 517 int 518 mdb_ctf_array_info(mdb_ctf_id_t id, mdb_ctf_arinfo_t *arp) 519 { 520 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 521 ctf_arinfo_t car; 522 523 if (ctf_array_info(idp->mci_fp, idp->mci_id, &car) == CTF_ERR) 524 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 525 526 set_ctf_id(&arp->mta_contents, idp->mci_fp, car.ctr_contents); 527 set_ctf_id(&arp->mta_index, idp->mci_fp, car.ctr_index); 528 529 arp->mta_nelems = car.ctr_nelems; 530 531 return (0); 532 } 533 534 const char * 535 mdb_ctf_enum_name(mdb_ctf_id_t id, int value) 536 { 537 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 538 const char *ret; 539 540 if ((ret = ctf_enum_name(idp->mci_fp, idp->mci_id, value)) == NULL) 541 (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))); 542 543 return (ret); 544 } 545 546 /* 547 * callback proxy for mdb_ctf_member_iter 548 */ 549 static int 550 member_iter_cb(const char *name, ctf_id_t type, ulong_t off, void *data) 551 { 552 member_iter_t *mip = data; 553 mdb_ctf_id_t id; 554 555 set_ctf_id(&id, mip->mi_fp, type); 556 557 return (mip->mi_cb(name, id, off, mip->mi_arg)); 558 } 559 560 int 561 mdb_ctf_member_iter(mdb_ctf_id_t id, mdb_ctf_member_f *cb, void *data) 562 { 563 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 564 member_iter_t mi; 565 int ret; 566 567 mi.mi_cb = cb; 568 mi.mi_arg = data; 569 mi.mi_fp = idp->mci_fp; 570 571 ret = ctf_member_iter(idp->mci_fp, idp->mci_id, member_iter_cb, &mi); 572 573 if (ret == CTF_ERR) 574 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 575 576 return (ret); 577 } 578 579 int 580 mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data) 581 { 582 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 583 584 return (ctf_enum_iter(idp->mci_fp, idp->mci_id, cb, data)); 585 } 586 587 /* 588 * callback proxy for mdb_ctf_type_iter 589 */ 590 static int 591 type_iter_cb(ctf_id_t type, void *data) 592 { 593 type_iter_t *tip = data; 594 mdb_ctf_id_t id; 595 596 set_ctf_id(&id, tip->ti_fp, type); 597 598 return (tip->ti_cb(id, tip->ti_arg)); 599 } 600 601 int 602 mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data) 603 { 604 ctf_file_t *fp; 605 mdb_tgt_t *t = mdb.m_target; 606 int ret; 607 type_iter_t ti; 608 609 if ((fp = mdb_tgt_name_to_ctf(t, object)) == NULL) 610 return (-1); 611 612 ti.ti_cb = cb; 613 ti.ti_arg = data; 614 ti.ti_fp = fp; 615 616 if ((ret = ctf_type_iter(fp, type_iter_cb, &ti)) == CTF_ERR) 617 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 618 619 return (ret); 620 } 621 622 /* utility functions */ 623 624 ctf_id_t 625 mdb_ctf_type_id(mdb_ctf_id_t id) 626 { 627 return (((mdb_ctf_impl_t *)&id)->mci_id); 628 } 629 630 ctf_file_t * 631 mdb_ctf_type_file(mdb_ctf_id_t id) 632 { 633 return (((mdb_ctf_impl_t *)&id)->mci_fp); 634 } 635 636 static int 637 member_info_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data) 638 { 639 mbr_info_t *mbrp = data; 640 641 if (strcmp(name, mbrp->mbr_member) == 0) { 642 if (mbrp->mbr_offp != NULL) 643 *(mbrp->mbr_offp) = off; 644 if (mbrp->mbr_typep != NULL) 645 *(mbrp->mbr_typep) = id; 646 647 return (1); 648 } 649 650 return (0); 651 } 652 653 int 654 mdb_ctf_member_info(mdb_ctf_id_t id, const char *member, ulong_t *offp, 655 mdb_ctf_id_t *typep) 656 { 657 mbr_info_t mbr; 658 int rc; 659 660 mbr.mbr_member = member; 661 mbr.mbr_offp = offp; 662 mbr.mbr_typep = typep; 663 664 rc = mdb_ctf_member_iter(id, member_info_cb, &mbr); 665 666 /* couldn't get member list */ 667 if (rc == -1) 668 return (-1); /* errno is set for us */ 669 670 /* not a member */ 671 if (rc == 0) 672 return (set_errno(EMDB_CTFNOMEMB)); 673 674 return (0); 675 } 676 677 int 678 mdb_ctf_offsetof(mdb_ctf_id_t id, const char *member, ulong_t *retp) 679 { 680 return (mdb_ctf_member_info(id, member, retp, NULL)); 681 } 682 683 /*ARGSUSED*/ 684 static int 685 num_members_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data) 686 { 687 int *count = data; 688 *count = *count + 1; 689 return (0); 690 } 691 692 int 693 mdb_ctf_num_members(mdb_ctf_id_t id) 694 { 695 int count = 0; 696 697 if (mdb_ctf_member_iter(id, num_members_cb, &count) != 0) 698 return (-1); /* errno is set for us */ 699 700 return (count); 701 } 702 703 typedef struct mbr_contains { 704 char **mbc_bufp; 705 size_t *mbc_lenp; 706 ulong_t *mbc_offp; 707 mdb_ctf_id_t *mbc_idp; 708 ssize_t mbc_total; 709 } mbr_contains_t; 710 711 static int 712 offset_to_name_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data) 713 { 714 mbr_contains_t *mbc = data; 715 ulong_t size; 716 ctf_encoding_t e; 717 size_t n; 718 719 if (*mbc->mbc_offp < off) 720 return (0); 721 722 if (mdb_ctf_type_encoding(id, &e) == -1) 723 size = mdb_ctf_type_size(id) * NBBY; 724 else 725 size = e.cte_bits; 726 727 if (off + size <= *mbc->mbc_offp) 728 return (0); 729 730 n = mdb_snprintf(*mbc->mbc_bufp, *mbc->mbc_lenp, "%s", name); 731 mbc->mbc_total += n; 732 if (n > *mbc->mbc_lenp) 733 n = *mbc->mbc_lenp; 734 735 *mbc->mbc_lenp -= n; 736 *mbc->mbc_bufp += n; 737 738 *mbc->mbc_offp -= off; 739 *mbc->mbc_idp = id; 740 741 return (1); 742 } 743 744 ssize_t 745 mdb_ctf_offset_to_name(mdb_ctf_id_t id, ulong_t off, char *buf, size_t len, 746 int dot, mdb_ctf_id_t *midp, ulong_t *moffp) 747 { 748 size_t size; 749 size_t n; 750 mbr_contains_t mbc; 751 752 if (!mdb_ctf_type_valid(id)) 753 return (set_errno(EINVAL)); 754 755 /* 756 * Quick sanity check to make sure the given offset is within 757 * this scope of this type. 758 */ 759 if (mdb_ctf_type_size(id) * NBBY <= off) 760 return (set_errno(EINVAL)); 761 762 mbc.mbc_bufp = &buf; 763 mbc.mbc_lenp = &len; 764 mbc.mbc_offp = &off; 765 mbc.mbc_idp = &id; 766 mbc.mbc_total = 0; 767 768 *buf = '\0'; 769 770 for (;;) { 771 /* 772 * Check for an exact match. 773 */ 774 if (off == 0) 775 break; 776 777 (void) mdb_ctf_type_resolve(id, &id); 778 779 /* 780 * Find the member that contains this offset. 781 */ 782 switch (mdb_ctf_type_kind(id)) { 783 case CTF_K_ARRAY: { 784 mdb_ctf_arinfo_t ar; 785 uint_t index; 786 787 (void) mdb_ctf_array_info(id, &ar); 788 size = mdb_ctf_type_size(ar.mta_contents) * NBBY; 789 index = off / size; 790 791 id = ar.mta_contents; 792 off %= size; 793 794 n = mdb_snprintf(buf, len, "[%u]", index); 795 mbc.mbc_total += n; 796 if (n > len) 797 n = len; 798 799 buf += n; 800 len -= n; 801 break; 802 } 803 804 case CTF_K_STRUCT: { 805 int ret; 806 807 /* 808 * Find the member that contains this offset 809 * and continue. 810 */ 811 812 if (dot) { 813 mbc.mbc_total++; 814 if (len != 0) { 815 *buf++ = '.'; 816 *buf = '\0'; 817 len--; 818 } 819 } 820 821 ret = mdb_ctf_member_iter(id, offset_to_name_cb, &mbc); 822 if (ret == -1) 823 return (-1); /* errno is set for us */ 824 825 /* 826 * If we did not find a member containing this offset 827 * (due to holes in the structure), return EINVAL. 828 */ 829 if (ret == 0) 830 return (set_errno(EINVAL)); 831 832 break; 833 } 834 835 case CTF_K_UNION: 836 /* 837 * Treat unions like atomic entities since we can't 838 * do more than guess which member of the union 839 * might be the intended one. 840 */ 841 goto done; 842 843 case CTF_K_INTEGER: 844 case CTF_K_FLOAT: 845 case CTF_K_POINTER: 846 case CTF_K_ENUM: 847 goto done; 848 849 default: 850 return (set_errno(EINVAL)); 851 } 852 853 dot = 1; 854 } 855 done: 856 if (midp != NULL) 857 *midp = id; 858 if (moffp != NULL) 859 *moffp = off; 860 861 return (mbc.mbc_total); 862 } 863 864 /* 865 * Check if two types are structurally the same rather than logically 866 * the same. That is to say that two types are equal if they have the 867 * same logical structure rather than having the same ids in CTF-land. 868 */ 869 static int type_equals(mdb_ctf_id_t, mdb_ctf_id_t); 870 871 static int 872 type_equals_cb(const char *name, mdb_ctf_id_t amem, ulong_t aoff, void *data) 873 { 874 mdb_ctf_id_t b = *(mdb_ctf_id_t *)data; 875 ulong_t boff; 876 mdb_ctf_id_t bmem; 877 878 /* 879 * Look up the corresponding member in the other composite type. 880 */ 881 if (mdb_ctf_member_info(b, name, &boff, &bmem) != 0) 882 return (1); 883 884 /* 885 * We don't allow members to be shuffled around. 886 */ 887 if (aoff != boff) 888 return (1); 889 890 return (type_equals(amem, bmem) ? 0 : 1); 891 } 892 893 static int 894 type_equals(mdb_ctf_id_t a, mdb_ctf_id_t b) 895 { 896 size_t asz, bsz; 897 int akind, bkind; 898 mdb_ctf_arinfo_t aar, bar; 899 900 /* 901 * Resolve both types down to their fundamental types, and make 902 * sure their sizes and kinds match. 903 */ 904 if (mdb_ctf_type_resolve(a, &a) != 0 || 905 mdb_ctf_type_resolve(b, &b) != 0 || 906 (asz = mdb_ctf_type_size(a)) == -1UL || 907 (bsz = mdb_ctf_type_size(b)) == -1UL || 908 (akind = mdb_ctf_type_kind(a)) == -1 || 909 (bkind = mdb_ctf_type_kind(b)) == -1 || 910 asz != bsz || akind != bkind) { 911 return (0); 912 } 913 914 switch (akind) { 915 case CTF_K_INTEGER: 916 case CTF_K_FLOAT: 917 case CTF_K_POINTER: 918 /* 919 * For pointers we could be a little stricter and require 920 * both pointers to reference types which look vaguely 921 * similar (for example, we could insist that the two types 922 * have the same name). However, all we really care about 923 * here is that the structure of the two types are the same, 924 * and, in that regard, one pointer is as good as another. 925 */ 926 return (1); 927 928 case CTF_K_UNION: 929 case CTF_K_STRUCT: 930 /* 931 * The test for the number of members is only strictly 932 * necessary for unions since we'll find other problems with 933 * structs. However, the extra check will do no harm. 934 */ 935 return (mdb_ctf_num_members(a) == mdb_ctf_num_members(b) && 936 mdb_ctf_member_iter(a, type_equals_cb, &b) == 0); 937 938 case CTF_K_ARRAY: 939 return (mdb_ctf_array_info(a, &aar) == 0 && 940 mdb_ctf_array_info(b, &bar) == 0 && 941 aar.mta_nelems == bar.mta_nelems && 942 type_equals(aar.mta_index, bar.mta_index) && 943 type_equals(aar.mta_contents, bar.mta_contents)); 944 } 945 946 return (0); 947 } 948 949 950 typedef struct member { 951 char *m_modbuf; 952 char *m_tgtbuf; 953 mdb_ctf_id_t m_tgtid; 954 uint_t m_flags; 955 } member_t; 956 957 static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *, uint_t); 958 959 static int 960 member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data) 961 { 962 member_t *mp = data; 963 char *modbuf = mp->m_modbuf; 964 mdb_ctf_id_t tgtmid; 965 char *tgtbuf = mp->m_tgtbuf; 966 ulong_t tgtoff; 967 968 if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) { 969 if (mp->m_flags & MDB_CTF_VREAD_IGNORE_ABSENT) 970 return (0); 971 else 972 return (set_errno(EMDB_CTFNOMEMB)); 973 } 974 975 return (vread_helper(modmid, modbuf + modoff / NBBY, 976 tgtmid, tgtbuf + tgtoff / NBBY, mp->m_flags)); 977 } 978 979 980 static int 981 vread_helper(mdb_ctf_id_t modid, char *modbuf, 982 mdb_ctf_id_t tgtid, char *tgtbuf, uint_t flags) 983 { 984 size_t modsz, tgtsz; 985 int modkind, tgtkind; 986 member_t mbr; 987 int ret; 988 mdb_ctf_arinfo_t tar, mar; 989 int i; 990 991 /* 992 * Resolve the types to their canonical form. 993 */ 994 (void) mdb_ctf_type_resolve(modid, &modid); 995 (void) mdb_ctf_type_resolve(tgtid, &tgtid); 996 997 if ((modkind = mdb_ctf_type_kind(modid)) == -1) 998 return (-1); /* errno is set for us */ 999 if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) 1000 return (-1); /* errno is set for us */ 1001 1002 if (tgtkind != modkind) 1003 return (set_errno(EMDB_INCOMPAT)); 1004 1005 switch (modkind) { 1006 case CTF_K_INTEGER: 1007 case CTF_K_FLOAT: 1008 case CTF_K_POINTER: 1009 if ((modsz = mdb_ctf_type_size(modid)) == -1UL) 1010 return (-1); /* errno is set for us */ 1011 1012 if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) 1013 return (-1); /* errno is set for us */ 1014 1015 /* 1016 * If the sizes don't match we need to be tricky to make 1017 * sure that the caller gets the correct data. 1018 */ 1019 if (modsz < tgtsz) { 1020 if (!(flags & MDB_CTF_VREAD_IGNORE_GROW)) 1021 return (set_errno(EMDB_INCOMPAT)); 1022 #ifdef _BIG_ENDIAN 1023 bcopy(tgtbuf + tgtsz - modsz, modbuf, modsz); 1024 #else 1025 bcopy(tgtbuf, modbuf, modsz); 1026 #endif 1027 } else if (modsz > tgtsz) { 1028 bzero(modbuf, modsz); 1029 #ifdef _BIG_ENDIAN 1030 bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz); 1031 #else 1032 bcopy(tgtbuf, modbuf, tgtsz); 1033 #endif 1034 } else { 1035 bcopy(tgtbuf, modbuf, modsz); 1036 } 1037 1038 return (0); 1039 1040 case CTF_K_STRUCT: 1041 mbr.m_modbuf = modbuf; 1042 mbr.m_tgtbuf = tgtbuf; 1043 mbr.m_tgtid = tgtid; 1044 mbr.m_flags = flags; 1045 1046 return (mdb_ctf_member_iter(modid, member_cb, &mbr)); 1047 1048 case CTF_K_UNION: 1049 1050 /* 1051 * Unions are a little tricky. The only time it's truly 1052 * safe to read in a union is if no part of the union or 1053 * any of its component types have changed. We allow the 1054 * consumer to ignore unions. The correct use of this 1055 * feature is to read the containing structure, figure 1056 * out which component of the union is valid, compute 1057 * the location of that in the target and then read in 1058 * that part of the structure. 1059 */ 1060 if (flags & MDB_CTF_VREAD_IGNORE_UNIONS) 1061 return (0); 1062 1063 if (!type_equals(modid, tgtid)) 1064 return (set_errno(EMDB_INCOMPAT)); 1065 1066 modsz = mdb_ctf_type_size(modid); 1067 tgtsz = mdb_ctf_type_size(tgtid); 1068 1069 ASSERT(modsz == tgtsz); 1070 1071 bcopy(tgtbuf, modbuf, modsz); 1072 1073 return (0); 1074 1075 case CTF_K_ARRAY: 1076 if (mdb_ctf_array_info(tgtid, &tar) != 0) 1077 return (-1); /* errno is set for us */ 1078 if (mdb_ctf_array_info(modid, &mar) != 0) 1079 return (-1); /* errno is set for us */ 1080 1081 if (tar.mta_nelems != mar.mta_nelems) 1082 return (set_errno(EMDB_INCOMPAT)); 1083 1084 if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) 1085 return (-1); /* errno is set for us */ 1086 1087 if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) 1088 return (-1); /* errno is set for us */ 1089 1090 for (i = 0; i < tar.mta_nelems; i++) { 1091 ret = vread_helper(mar.mta_contents, modbuf + i * modsz, 1092 tar.mta_contents, tgtbuf + i * tgtsz, flags); 1093 1094 if (ret != 0) 1095 return (ret); 1096 } 1097 1098 return (0); 1099 } 1100 1101 return (set_errno(EMDB_INCOMPAT)); 1102 } 1103 1104 1105 int 1106 mdb_ctf_vread(void *modbuf, const char *typename, uintptr_t addr, uint_t flags) 1107 { 1108 ctf_file_t *mfp; 1109 ctf_id_t mid; 1110 void *tgtbuf; 1111 size_t size; 1112 mdb_ctf_id_t tgtid; 1113 mdb_ctf_id_t modid; 1114 mdb_module_t *mod; 1115 1116 if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) 1117 return (set_errno(EMDB_NOCTF)); 1118 1119 if ((mid = ctf_lookup_by_name(mfp, typename)) == CTF_ERR) { 1120 mdb_dprintf(MDB_DBG_CTF, "couldn't find module's ctf data\n"); 1121 return (set_errno(ctf_to_errno(ctf_errno(mfp)))); 1122 } 1123 1124 set_ctf_id(&modid, mfp, mid); 1125 1126 if (mdb_ctf_lookup_by_name(typename, &tgtid) != 0) { 1127 mdb_dprintf(MDB_DBG_CTF, "couldn't find target's ctf data\n"); 1128 return (set_errno(EMDB_NOCTF)); 1129 } 1130 1131 /* 1132 * Read the data out of the target's address space. 1133 */ 1134 if ((size = mdb_ctf_type_size(tgtid)) == -1UL) 1135 return (-1); /* errno is set for us */ 1136 1137 tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC); 1138 1139 if (mdb_vread(tgtbuf, size, addr) < 0) 1140 return (-1); /* errno is set for us */ 1141 1142 return (vread_helper(modid, modbuf, tgtid, tgtbuf, flags)); 1143 } 1144 1145 int 1146 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags) 1147 { 1148 GElf_Sym sym; 1149 1150 if (mdb_lookup_by_name(name, &sym) != 0) 1151 return (-1); /* errno is set for us */ 1152 1153 return (mdb_ctf_vread(buf, typename, sym.st_value, flags)); 1154 } 1155 1156 ctf_file_t * 1157 mdb_ctf_bufopen(const void *ctf_va, size_t ctf_size, const void *sym_va, 1158 Shdr *symhdr, const void *str_va, Shdr *strhdr, int *errp) 1159 { 1160 ctf_sect_t ctdata, symtab, strtab; 1161 1162 ctdata.cts_name = ".SUNW_ctf"; 1163 ctdata.cts_type = SHT_PROGBITS; 1164 ctdata.cts_flags = 0; 1165 ctdata.cts_data = ctf_va; 1166 ctdata.cts_size = ctf_size; 1167 ctdata.cts_entsize = 1; 1168 ctdata.cts_offset = 0; 1169 1170 symtab.cts_name = ".symtab"; 1171 symtab.cts_type = symhdr->sh_type; 1172 symtab.cts_flags = symhdr->sh_flags; 1173 symtab.cts_data = sym_va; 1174 symtab.cts_size = symhdr->sh_size; 1175 symtab.cts_entsize = symhdr->sh_entsize; 1176 symtab.cts_offset = symhdr->sh_offset; 1177 1178 strtab.cts_name = ".strtab"; 1179 strtab.cts_type = strhdr->sh_type; 1180 strtab.cts_flags = strhdr->sh_flags; 1181 strtab.cts_data = str_va; 1182 strtab.cts_size = strhdr->sh_size; 1183 strtab.cts_entsize = strhdr->sh_entsize; 1184 strtab.cts_offset = strhdr->sh_offset; 1185 1186 return (ctf_bufopen(&ctdata, &symtab, &strtab, errp)); 1187 } 1188