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