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 #include <mdb/mdb_ctf.h> 27 #include <mdb/mdb_ctf_impl.h> 28 #include <mdb/mdb_err.h> 29 #include <mdb/mdb_modapi.h> 30 #include <mdb/mdb_string.h> 31 #include <mdb/mdb.h> 32 #include <mdb/mdb_debug.h> 33 34 #include <libctf.h> 35 #include <string.h> 36 37 typedef struct tnarg { 38 mdb_tgt_t *tn_tgt; /* target to use for lookup */ 39 const char *tn_name; /* query string to lookup */ 40 ctf_file_t *tn_fp; /* CTF container from match */ 41 ctf_id_t tn_id; /* CTF type ID from match */ 42 } tnarg_t; 43 44 typedef struct type_iter { 45 mdb_ctf_type_f *ti_cb; 46 void *ti_arg; 47 ctf_file_t *ti_fp; 48 } type_iter_t; 49 50 typedef struct member_iter { 51 mdb_ctf_member_f *mi_cb; 52 void *mi_arg; 53 ctf_file_t *mi_fp; 54 } member_iter_t; 55 56 typedef struct type_visit { 57 mdb_ctf_visit_f *tv_cb; 58 void *tv_arg; 59 ctf_file_t *tv_fp; 60 ulong_t tv_base_offset; /* used when recursing from type_cb() */ 61 int tv_base_depth; /* used when recursing from type_cb() */ 62 int tv_min_depth; 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 of each object file for a particular name. 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 (ctf_type_kind(idp->mci_fp, id) == CTF_K_FORWARD) { 407 char name[MDB_SYM_NAMLEN]; 408 mdb_ctf_id_t lookup_id; 409 410 if (ctf_type_name(idp->mci_fp, id, name, sizeof (name)) != 411 NULL && 412 mdb_ctf_lookup_by_name(name, &lookup_id) == 0 && 413 outp != NULL) { 414 *outp = lookup_id; 415 return (0); 416 } 417 } 418 419 if (outp != NULL) 420 set_ctf_id(outp, idp->mci_fp, id); 421 422 return (0); 423 } 424 425 char * 426 mdb_ctf_type_name(mdb_ctf_id_t id, char *buf, size_t len) 427 { 428 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 429 char *ret; 430 431 if (!mdb_ctf_type_valid(id)) { 432 (void) set_errno(EINVAL); 433 return (NULL); 434 } 435 436 ret = ctf_type_name(idp->mci_fp, idp->mci_id, buf, len); 437 if (ret == NULL) 438 (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))); 439 440 return (ret); 441 } 442 443 ssize_t 444 mdb_ctf_type_size(mdb_ctf_id_t id) 445 { 446 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 447 ssize_t ret; 448 449 if ((ret = ctf_type_size(idp->mci_fp, idp->mci_id)) == CTF_ERR) 450 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 451 452 return (ret); 453 } 454 455 int 456 mdb_ctf_type_kind(mdb_ctf_id_t id) 457 { 458 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 459 int ret; 460 461 if ((ret = ctf_type_kind(idp->mci_fp, idp->mci_id)) == CTF_ERR) 462 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 463 464 return (ret); 465 } 466 467 int 468 mdb_ctf_type_reference(mdb_ctf_id_t mid, mdb_ctf_id_t *outp) 469 { 470 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)∣ 471 ctf_id_t id; 472 473 if ((id = ctf_type_reference(idp->mci_fp, idp->mci_id)) == CTF_ERR) { 474 if (outp) 475 mdb_ctf_type_invalidate(outp); 476 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 477 } 478 479 if (outp != NULL) 480 set_ctf_id(outp, idp->mci_fp, id); 481 482 return (0); 483 } 484 485 486 int 487 mdb_ctf_type_encoding(mdb_ctf_id_t id, ctf_encoding_t *ep) 488 { 489 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 490 491 if (ctf_type_encoding(idp->mci_fp, idp->mci_id, ep) == CTF_ERR) 492 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 493 494 return (0); 495 } 496 497 /* 498 * callback proxy for mdb_ctf_type_visit 499 */ 500 static int 501 type_cb(const char *name, ctf_id_t type, ulong_t off, int depth, void *arg) 502 { 503 type_visit_t *tvp = arg; 504 mdb_ctf_id_t id; 505 mdb_ctf_id_t base; 506 mdb_ctf_impl_t *basep = (mdb_ctf_impl_t *)&base; 507 508 int ret; 509 510 if (depth < tvp->tv_min_depth) 511 return (0); 512 513 off += tvp->tv_base_offset; 514 depth += tvp->tv_base_depth; 515 516 set_ctf_id(&id, tvp->tv_fp, type); 517 518 (void) mdb_ctf_type_resolve(id, &base); 519 if ((ret = tvp->tv_cb(name, id, base, off, depth, tvp->tv_arg)) != 0) 520 return (ret); 521 522 /* 523 * If the type resolves to a type in a different file, we must have 524 * followed a forward declaration. We need to recurse into the 525 * new type. 526 */ 527 if (basep->mci_fp != tvp->tv_fp && mdb_ctf_type_valid(base)) { 528 type_visit_t tv; 529 530 tv.tv_cb = tvp->tv_cb; 531 tv.tv_arg = tvp->tv_arg; 532 tv.tv_fp = basep->mci_fp; 533 534 tv.tv_base_offset = off; 535 tv.tv_base_depth = depth; 536 tv.tv_min_depth = 1; /* depth = 0 has already been done */ 537 538 ret = ctf_type_visit(basep->mci_fp, basep->mci_id, 539 type_cb, &tv); 540 } 541 return (ret); 542 } 543 544 int 545 mdb_ctf_type_visit(mdb_ctf_id_t id, mdb_ctf_visit_f *func, void *arg) 546 { 547 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 548 type_visit_t tv; 549 int ret; 550 551 tv.tv_cb = func; 552 tv.tv_arg = arg; 553 tv.tv_fp = idp->mci_fp; 554 tv.tv_base_offset = 0; 555 tv.tv_base_depth = 0; 556 tv.tv_min_depth = 0; 557 558 ret = ctf_type_visit(idp->mci_fp, idp->mci_id, type_cb, &tv); 559 560 if (ret == CTF_ERR) 561 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 562 563 return (ret); 564 } 565 566 int 567 mdb_ctf_array_info(mdb_ctf_id_t id, mdb_ctf_arinfo_t *arp) 568 { 569 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 570 ctf_arinfo_t car; 571 572 if (ctf_array_info(idp->mci_fp, idp->mci_id, &car) == CTF_ERR) 573 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 574 575 set_ctf_id(&arp->mta_contents, idp->mci_fp, car.ctr_contents); 576 set_ctf_id(&arp->mta_index, idp->mci_fp, car.ctr_index); 577 578 arp->mta_nelems = car.ctr_nelems; 579 580 return (0); 581 } 582 583 const char * 584 mdb_ctf_enum_name(mdb_ctf_id_t id, int value) 585 { 586 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 587 const char *ret; 588 589 if ((ret = ctf_enum_name(idp->mci_fp, idp->mci_id, value)) == NULL) 590 (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))); 591 592 return (ret); 593 } 594 595 /* 596 * callback proxy for mdb_ctf_member_iter 597 */ 598 static int 599 member_iter_cb(const char *name, ctf_id_t type, ulong_t off, void *data) 600 { 601 member_iter_t *mip = data; 602 mdb_ctf_id_t id; 603 604 set_ctf_id(&id, mip->mi_fp, type); 605 606 return (mip->mi_cb(name, id, off, mip->mi_arg)); 607 } 608 609 int 610 mdb_ctf_member_iter(mdb_ctf_id_t id, mdb_ctf_member_f *cb, void *data) 611 { 612 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 613 member_iter_t mi; 614 int ret; 615 616 mi.mi_cb = cb; 617 mi.mi_arg = data; 618 mi.mi_fp = idp->mci_fp; 619 620 ret = ctf_member_iter(idp->mci_fp, idp->mci_id, member_iter_cb, &mi); 621 622 if (ret == CTF_ERR) 623 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 624 625 return (ret); 626 } 627 628 int 629 mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data) 630 { 631 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 632 633 return (ctf_enum_iter(idp->mci_fp, idp->mci_id, cb, data)); 634 } 635 636 /* 637 * callback proxy for mdb_ctf_type_iter 638 */ 639 static int 640 type_iter_cb(ctf_id_t type, void *data) 641 { 642 type_iter_t *tip = data; 643 mdb_ctf_id_t id; 644 645 set_ctf_id(&id, tip->ti_fp, type); 646 647 return (tip->ti_cb(id, tip->ti_arg)); 648 } 649 650 int 651 mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data) 652 { 653 ctf_file_t *fp; 654 mdb_tgt_t *t = mdb.m_target; 655 int ret; 656 type_iter_t ti; 657 658 if ((fp = mdb_tgt_name_to_ctf(t, object)) == NULL) 659 return (-1); 660 661 ti.ti_cb = cb; 662 ti.ti_arg = data; 663 ti.ti_fp = fp; 664 665 if ((ret = ctf_type_iter(fp, type_iter_cb, &ti)) == CTF_ERR) 666 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 667 668 return (ret); 669 } 670 671 /* utility functions */ 672 673 ctf_id_t 674 mdb_ctf_type_id(mdb_ctf_id_t id) 675 { 676 return (((mdb_ctf_impl_t *)&id)->mci_id); 677 } 678 679 ctf_file_t * 680 mdb_ctf_type_file(mdb_ctf_id_t id) 681 { 682 return (((mdb_ctf_impl_t *)&id)->mci_fp); 683 } 684 685 static int 686 member_info_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data) 687 { 688 mbr_info_t *mbrp = data; 689 690 if (strcmp(name, mbrp->mbr_member) == 0) { 691 if (mbrp->mbr_offp != NULL) 692 *(mbrp->mbr_offp) = off; 693 if (mbrp->mbr_typep != NULL) 694 *(mbrp->mbr_typep) = id; 695 696 return (1); 697 } 698 699 return (0); 700 } 701 702 int 703 mdb_ctf_member_info(mdb_ctf_id_t id, const char *member, ulong_t *offp, 704 mdb_ctf_id_t *typep) 705 { 706 mbr_info_t mbr; 707 int rc; 708 709 mbr.mbr_member = member; 710 mbr.mbr_offp = offp; 711 mbr.mbr_typep = typep; 712 713 rc = mdb_ctf_member_iter(id, member_info_cb, &mbr); 714 715 /* couldn't get member list */ 716 if (rc == -1) 717 return (-1); /* errno is set for us */ 718 719 /* not a member */ 720 if (rc == 0) 721 return (set_errno(EMDB_CTFNOMEMB)); 722 723 return (0); 724 } 725 726 int 727 mdb_ctf_offsetof(mdb_ctf_id_t id, const char *member, ulong_t *retp) 728 { 729 return (mdb_ctf_member_info(id, member, retp, NULL)); 730 } 731 732 /*ARGSUSED*/ 733 static int 734 num_members_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data) 735 { 736 int *count = data; 737 *count = *count + 1; 738 return (0); 739 } 740 741 int 742 mdb_ctf_num_members(mdb_ctf_id_t id) 743 { 744 int count = 0; 745 746 if (mdb_ctf_member_iter(id, num_members_cb, &count) != 0) 747 return (-1); /* errno is set for us */ 748 749 return (count); 750 } 751 752 typedef struct mbr_contains { 753 char **mbc_bufp; 754 size_t *mbc_lenp; 755 ulong_t *mbc_offp; 756 mdb_ctf_id_t *mbc_idp; 757 ssize_t mbc_total; 758 } mbr_contains_t; 759 760 static int 761 offset_to_name_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data) 762 { 763 mbr_contains_t *mbc = data; 764 ulong_t size; 765 ctf_encoding_t e; 766 size_t n; 767 768 if (*mbc->mbc_offp < off) 769 return (0); 770 771 if (mdb_ctf_type_encoding(id, &e) == -1) 772 size = mdb_ctf_type_size(id) * NBBY; 773 else 774 size = e.cte_bits; 775 776 if (off + size <= *mbc->mbc_offp) 777 return (0); 778 779 n = mdb_snprintf(*mbc->mbc_bufp, *mbc->mbc_lenp, "%s", name); 780 mbc->mbc_total += n; 781 if (n > *mbc->mbc_lenp) 782 n = *mbc->mbc_lenp; 783 784 *mbc->mbc_lenp -= n; 785 *mbc->mbc_bufp += n; 786 787 *mbc->mbc_offp -= off; 788 *mbc->mbc_idp = id; 789 790 return (1); 791 } 792 793 ssize_t 794 mdb_ctf_offset_to_name(mdb_ctf_id_t id, ulong_t off, char *buf, size_t len, 795 int dot, mdb_ctf_id_t *midp, ulong_t *moffp) 796 { 797 size_t size; 798 size_t n; 799 mbr_contains_t mbc; 800 801 if (!mdb_ctf_type_valid(id)) 802 return (set_errno(EINVAL)); 803 804 /* 805 * Quick sanity check to make sure the given offset is within 806 * this scope of this type. 807 */ 808 if (mdb_ctf_type_size(id) * NBBY <= off) 809 return (set_errno(EINVAL)); 810 811 mbc.mbc_bufp = &buf; 812 mbc.mbc_lenp = &len; 813 mbc.mbc_offp = &off; 814 mbc.mbc_idp = &id; 815 mbc.mbc_total = 0; 816 817 *buf = '\0'; 818 819 for (;;) { 820 /* 821 * Check for an exact match. 822 */ 823 if (off == 0) 824 break; 825 826 (void) mdb_ctf_type_resolve(id, &id); 827 828 /* 829 * Find the member that contains this offset. 830 */ 831 switch (mdb_ctf_type_kind(id)) { 832 case CTF_K_ARRAY: { 833 mdb_ctf_arinfo_t ar; 834 uint_t index; 835 836 (void) mdb_ctf_array_info(id, &ar); 837 size = mdb_ctf_type_size(ar.mta_contents) * NBBY; 838 index = off / size; 839 840 id = ar.mta_contents; 841 off %= size; 842 843 n = mdb_snprintf(buf, len, "[%u]", index); 844 mbc.mbc_total += n; 845 if (n > len) 846 n = len; 847 848 buf += n; 849 len -= n; 850 break; 851 } 852 853 case CTF_K_STRUCT: { 854 int ret; 855 856 /* 857 * Find the member that contains this offset 858 * and continue. 859 */ 860 861 if (dot) { 862 mbc.mbc_total++; 863 if (len != 0) { 864 *buf++ = '.'; 865 *buf = '\0'; 866 len--; 867 } 868 } 869 870 ret = mdb_ctf_member_iter(id, offset_to_name_cb, &mbc); 871 if (ret == -1) 872 return (-1); /* errno is set for us */ 873 874 /* 875 * If we did not find a member containing this offset 876 * (due to holes in the structure), return EINVAL. 877 */ 878 if (ret == 0) 879 return (set_errno(EINVAL)); 880 881 break; 882 } 883 884 case CTF_K_UNION: 885 /* 886 * Treat unions like atomic entities since we can't 887 * do more than guess which member of the union 888 * might be the intended one. 889 */ 890 goto done; 891 892 case CTF_K_INTEGER: 893 case CTF_K_FLOAT: 894 case CTF_K_POINTER: 895 case CTF_K_ENUM: 896 goto done; 897 898 default: 899 return (set_errno(EINVAL)); 900 } 901 902 dot = 1; 903 } 904 done: 905 if (midp != NULL) 906 *midp = id; 907 if (moffp != NULL) 908 *moffp = off; 909 910 return (mbc.mbc_total); 911 } 912 913 /* 914 * Check if two types are structurally the same rather than logically 915 * the same. That is to say that two types are equal if they have the 916 * same logical structure rather than having the same ids in CTF-land. 917 */ 918 static int type_equals(mdb_ctf_id_t, mdb_ctf_id_t); 919 920 static int 921 type_equals_cb(const char *name, mdb_ctf_id_t amem, ulong_t aoff, void *data) 922 { 923 mdb_ctf_id_t b = *(mdb_ctf_id_t *)data; 924 ulong_t boff; 925 mdb_ctf_id_t bmem; 926 927 /* 928 * Look up the corresponding member in the other composite type. 929 */ 930 if (mdb_ctf_member_info(b, name, &boff, &bmem) != 0) 931 return (1); 932 933 /* 934 * We don't allow members to be shuffled around. 935 */ 936 if (aoff != boff) 937 return (1); 938 939 return (type_equals(amem, bmem) ? 0 : 1); 940 } 941 942 static int 943 type_equals(mdb_ctf_id_t a, mdb_ctf_id_t b) 944 { 945 size_t asz, bsz; 946 int akind, bkind; 947 mdb_ctf_arinfo_t aar, bar; 948 949 /* 950 * Resolve both types down to their fundamental types, and make 951 * sure their sizes and kinds match. 952 */ 953 if (mdb_ctf_type_resolve(a, &a) != 0 || 954 mdb_ctf_type_resolve(b, &b) != 0 || 955 (asz = mdb_ctf_type_size(a)) == -1UL || 956 (bsz = mdb_ctf_type_size(b)) == -1UL || 957 (akind = mdb_ctf_type_kind(a)) == -1 || 958 (bkind = mdb_ctf_type_kind(b)) == -1 || 959 asz != bsz || akind != bkind) { 960 return (0); 961 } 962 963 switch (akind) { 964 case CTF_K_INTEGER: 965 case CTF_K_FLOAT: 966 case CTF_K_POINTER: 967 /* 968 * For pointers we could be a little stricter and require 969 * both pointers to reference types which look vaguely 970 * similar (for example, we could insist that the two types 971 * have the same name). However, all we really care about 972 * here is that the structure of the two types are the same, 973 * and, in that regard, one pointer is as good as another. 974 */ 975 return (1); 976 977 case CTF_K_UNION: 978 case CTF_K_STRUCT: 979 /* 980 * The test for the number of members is only strictly 981 * necessary for unions since we'll find other problems with 982 * structs. However, the extra check will do no harm. 983 */ 984 return (mdb_ctf_num_members(a) == mdb_ctf_num_members(b) && 985 mdb_ctf_member_iter(a, type_equals_cb, &b) == 0); 986 987 case CTF_K_ARRAY: 988 return (mdb_ctf_array_info(a, &aar) == 0 && 989 mdb_ctf_array_info(b, &bar) == 0 && 990 aar.mta_nelems == bar.mta_nelems && 991 type_equals(aar.mta_index, bar.mta_index) && 992 type_equals(aar.mta_contents, bar.mta_contents)); 993 } 994 995 return (0); 996 } 997 998 999 typedef struct member { 1000 char *m_modbuf; 1001 char *m_tgtbuf; 1002 mdb_ctf_id_t m_tgtid; 1003 uint_t m_flags; 1004 } member_t; 1005 1006 static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *, uint_t); 1007 1008 static int 1009 member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data) 1010 { 1011 member_t *mp = data; 1012 char *modbuf = mp->m_modbuf; 1013 mdb_ctf_id_t tgtmid; 1014 char *tgtbuf = mp->m_tgtbuf; 1015 ulong_t tgtoff; 1016 1017 if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) { 1018 if (mp->m_flags & MDB_CTF_VREAD_IGNORE_ABSENT) 1019 return (0); 1020 else 1021 return (set_errno(EMDB_CTFNOMEMB)); 1022 } 1023 1024 return (vread_helper(modmid, modbuf + modoff / NBBY, 1025 tgtmid, tgtbuf + tgtoff / NBBY, mp->m_flags)); 1026 } 1027 1028 1029 static int 1030 vread_helper(mdb_ctf_id_t modid, char *modbuf, 1031 mdb_ctf_id_t tgtid, char *tgtbuf, uint_t flags) 1032 { 1033 size_t modsz, tgtsz; 1034 int modkind, tgtkind; 1035 member_t mbr; 1036 int ret; 1037 mdb_ctf_arinfo_t tar, mar; 1038 int i; 1039 1040 /* 1041 * Resolve the types to their canonical form. 1042 */ 1043 (void) mdb_ctf_type_resolve(modid, &modid); 1044 (void) mdb_ctf_type_resolve(tgtid, &tgtid); 1045 1046 if ((modkind = mdb_ctf_type_kind(modid)) == -1) 1047 return (-1); /* errno is set for us */ 1048 if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) 1049 return (-1); /* errno is set for us */ 1050 1051 if (tgtkind != modkind) 1052 return (set_errno(EMDB_INCOMPAT)); 1053 1054 switch (modkind) { 1055 case CTF_K_INTEGER: 1056 case CTF_K_FLOAT: 1057 case CTF_K_POINTER: 1058 if ((modsz = mdb_ctf_type_size(modid)) == -1UL) 1059 return (-1); /* errno is set for us */ 1060 1061 if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) 1062 return (-1); /* errno is set for us */ 1063 1064 /* 1065 * If the sizes don't match we need to be tricky to make 1066 * sure that the caller gets the correct data. 1067 */ 1068 if (modsz < tgtsz) { 1069 if (!(flags & MDB_CTF_VREAD_IGNORE_GROW)) 1070 return (set_errno(EMDB_INCOMPAT)); 1071 #ifdef _BIG_ENDIAN 1072 bcopy(tgtbuf + tgtsz - modsz, modbuf, modsz); 1073 #else 1074 bcopy(tgtbuf, modbuf, modsz); 1075 #endif 1076 } else if (modsz > tgtsz) { 1077 bzero(modbuf, modsz); 1078 #ifdef _BIG_ENDIAN 1079 bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz); 1080 #else 1081 bcopy(tgtbuf, modbuf, tgtsz); 1082 #endif 1083 } else { 1084 bcopy(tgtbuf, modbuf, modsz); 1085 } 1086 1087 return (0); 1088 1089 case CTF_K_STRUCT: 1090 mbr.m_modbuf = modbuf; 1091 mbr.m_tgtbuf = tgtbuf; 1092 mbr.m_tgtid = tgtid; 1093 mbr.m_flags = flags; 1094 1095 return (mdb_ctf_member_iter(modid, member_cb, &mbr)); 1096 1097 case CTF_K_UNION: 1098 1099 /* 1100 * Unions are a little tricky. The only time it's truly 1101 * safe to read in a union is if no part of the union or 1102 * any of its component types have changed. We allow the 1103 * consumer to ignore unions. The correct use of this 1104 * feature is to read the containing structure, figure 1105 * out which component of the union is valid, compute 1106 * the location of that in the target and then read in 1107 * that part of the structure. 1108 */ 1109 if (flags & MDB_CTF_VREAD_IGNORE_UNIONS) 1110 return (0); 1111 1112 if (!type_equals(modid, tgtid)) 1113 return (set_errno(EMDB_INCOMPAT)); 1114 1115 modsz = mdb_ctf_type_size(modid); 1116 tgtsz = mdb_ctf_type_size(tgtid); 1117 1118 ASSERT(modsz == tgtsz); 1119 1120 bcopy(tgtbuf, modbuf, modsz); 1121 1122 return (0); 1123 1124 case CTF_K_ARRAY: 1125 if (mdb_ctf_array_info(tgtid, &tar) != 0) 1126 return (-1); /* errno is set for us */ 1127 if (mdb_ctf_array_info(modid, &mar) != 0) 1128 return (-1); /* errno is set for us */ 1129 1130 if (tar.mta_nelems != mar.mta_nelems) 1131 return (set_errno(EMDB_INCOMPAT)); 1132 1133 if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) 1134 return (-1); /* errno is set for us */ 1135 1136 if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) 1137 return (-1); /* errno is set for us */ 1138 1139 for (i = 0; i < tar.mta_nelems; i++) { 1140 ret = vread_helper(mar.mta_contents, modbuf + i * modsz, 1141 tar.mta_contents, tgtbuf + i * tgtsz, flags); 1142 1143 if (ret != 0) 1144 return (ret); 1145 } 1146 1147 return (0); 1148 } 1149 1150 return (set_errno(EMDB_INCOMPAT)); 1151 } 1152 1153 1154 int 1155 mdb_ctf_vread(void *modbuf, const char *typename, uintptr_t addr, uint_t flags) 1156 { 1157 ctf_file_t *mfp; 1158 ctf_id_t mid; 1159 void *tgtbuf; 1160 size_t size; 1161 mdb_ctf_id_t tgtid; 1162 mdb_ctf_id_t modid; 1163 mdb_module_t *mod; 1164 1165 if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) 1166 return (set_errno(EMDB_NOCTF)); 1167 1168 if ((mid = ctf_lookup_by_name(mfp, typename)) == CTF_ERR) { 1169 mdb_dprintf(MDB_DBG_CTF, "couldn't find module's ctf data\n"); 1170 return (set_errno(ctf_to_errno(ctf_errno(mfp)))); 1171 } 1172 1173 set_ctf_id(&modid, mfp, mid); 1174 1175 if (mdb_ctf_lookup_by_name(typename, &tgtid) != 0) { 1176 mdb_dprintf(MDB_DBG_CTF, "couldn't find target's ctf data\n"); 1177 return (set_errno(EMDB_NOCTF)); 1178 } 1179 1180 /* 1181 * Read the data out of the target's address space. 1182 */ 1183 if ((size = mdb_ctf_type_size(tgtid)) == -1UL) 1184 return (-1); /* errno is set for us */ 1185 1186 tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC); 1187 1188 if (mdb_vread(tgtbuf, size, addr) < 0) 1189 return (-1); /* errno is set for us */ 1190 1191 return (vread_helper(modid, modbuf, tgtid, tgtbuf, flags)); 1192 } 1193 1194 int 1195 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags) 1196 { 1197 GElf_Sym sym; 1198 1199 if (mdb_lookup_by_name(name, &sym) != 0) 1200 return (-1); /* errno is set for us */ 1201 1202 return (mdb_ctf_vread(buf, typename, sym.st_value, flags)); 1203 } 1204 1205 ctf_file_t * 1206 mdb_ctf_bufopen(const void *ctf_va, size_t ctf_size, const void *sym_va, 1207 Shdr *symhdr, const void *str_va, Shdr *strhdr, int *errp) 1208 { 1209 ctf_sect_t ctdata, symtab, strtab; 1210 1211 ctdata.cts_name = ".SUNW_ctf"; 1212 ctdata.cts_type = SHT_PROGBITS; 1213 ctdata.cts_flags = 0; 1214 ctdata.cts_data = ctf_va; 1215 ctdata.cts_size = ctf_size; 1216 ctdata.cts_entsize = 1; 1217 ctdata.cts_offset = 0; 1218 1219 symtab.cts_name = ".symtab"; 1220 symtab.cts_type = symhdr->sh_type; 1221 symtab.cts_flags = symhdr->sh_flags; 1222 symtab.cts_data = sym_va; 1223 symtab.cts_size = symhdr->sh_size; 1224 symtab.cts_entsize = symhdr->sh_entsize; 1225 symtab.cts_offset = symhdr->sh_offset; 1226 1227 strtab.cts_name = ".strtab"; 1228 strtab.cts_type = strhdr->sh_type; 1229 strtab.cts_flags = strhdr->sh_flags; 1230 strtab.cts_data = str_va; 1231 strtab.cts_size = strhdr->sh_size; 1232 strtab.cts_entsize = strhdr->sh_entsize; 1233 strtab.cts_offset = strhdr->sh_offset; 1234 1235 return (ctf_bufopen(&ctdata, &symtab, &strtab, errp)); 1236 } 1237