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 * Copyright (c) 2013 by Delphix. All rights reserved. 27 */ 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 ulong_t tv_base_offset; /* used when recursing from type_cb() */ 64 int tv_base_depth; /* used when recursing from type_cb() */ 65 int tv_min_depth; 66 } type_visit_t; 67 68 typedef struct mbr_info { 69 const char *mbr_member; 70 ulong_t *mbr_offp; 71 mdb_ctf_id_t *mbr_typep; 72 } mbr_info_t; 73 74 static void 75 set_ctf_id(mdb_ctf_id_t *p, ctf_file_t *fp, ctf_id_t id) 76 { 77 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p; 78 79 mcip->mci_fp = fp; 80 mcip->mci_id = id; 81 } 82 83 /* 84 * Callback function for mdb_tgt_object_iter used from name_to_type, below, 85 * to search the CTF namespace of each object file for a particular name. 86 */ 87 /*ARGSUSED*/ 88 static int 89 obj_lookup(void *data, const mdb_map_t *mp, const char *name) 90 { 91 tnarg_t *tnp = data; 92 ctf_file_t *fp; 93 ctf_id_t id; 94 95 if ((fp = mdb_tgt_name_to_ctf(tnp->tn_tgt, name)) != NULL && 96 (id = ctf_lookup_by_name(fp, tnp->tn_name)) != CTF_ERR) { 97 tnp->tn_fp = fp; 98 tnp->tn_id = id; 99 100 /* 101 * We may have found a forward declaration. If we did, we'll 102 * note the ID and file pointer, but we'll keep searching in 103 * an attempt to find the real thing. If we found something 104 * real (i.e. not a forward), we stop the iteration. 105 */ 106 return (ctf_type_kind(fp, id) == CTF_K_FORWARD ? 0 : -1); 107 } 108 109 return (0); 110 } 111 112 /* 113 * Convert a string type name with an optional leading object specifier into 114 * the corresponding CTF file container and type ID. If an error occurs, we 115 * print an appropriate message and return NULL. 116 */ 117 static ctf_file_t * 118 name_to_type(mdb_tgt_t *t, const char *cname, ctf_id_t *idp) 119 { 120 const char *object = MDB_TGT_OBJ_EXEC; 121 ctf_file_t *fp = NULL; 122 ctf_id_t id; 123 tnarg_t arg; 124 char *p, *s; 125 char buf[MDB_SYM_NAMLEN]; 126 char *name = &buf[0]; 127 128 (void) mdb_snprintf(buf, sizeof (buf), "%s", cname); 129 130 if ((p = strrsplit(name, '`')) != NULL) { 131 /* 132 * We need to shuffle things around a little to support 133 * type names of the form "struct module`name". 134 */ 135 if ((s = strsplit(name, ' ')) != NULL) { 136 bcopy(cname + (s - name), name, (p - s) - 1); 137 name[(p - s) - 1] = '\0'; 138 bcopy(cname, name + (p - s), s - name); 139 p = name + (p - s); 140 } 141 if (*name != '\0') 142 object = name; 143 name = p; 144 } 145 146 /* 147 * Attempt to look up the name in the primary object file. If this 148 * fails and the name was unscoped, search all remaining object files. 149 */ 150 if (((fp = mdb_tgt_name_to_ctf(t, object)) == NULL || 151 (id = ctf_lookup_by_name(fp, name)) == CTF_ERR || 152 ctf_type_kind(fp, id) == CTF_K_FORWARD) && 153 object == MDB_TGT_OBJ_EXEC) { 154 155 arg.tn_tgt = t; 156 arg.tn_name = name; 157 arg.tn_fp = NULL; 158 arg.tn_id = CTF_ERR; 159 160 (void) mdb_tgt_object_iter(t, obj_lookup, &arg); 161 162 if (arg.tn_id != CTF_ERR) { 163 fp = arg.tn_fp; 164 id = arg.tn_id; 165 } 166 } 167 168 if (fp == NULL) 169 return (NULL); /* errno is set for us */ 170 171 if (id == CTF_ERR) { 172 (void) set_errno(ctf_to_errno(ctf_errno(fp))); 173 return (NULL); 174 } 175 176 *idp = id; 177 return (fp); 178 } 179 180 /* 181 * Check to see if there is ctf data in the given object. This is useful 182 * so that we don't enter some loop where every call to lookup fails. 183 */ 184 int 185 mdb_ctf_enabled_by_object(const char *object) 186 { 187 mdb_tgt_t *t = mdb.m_target; 188 189 return (mdb_tgt_name_to_ctf(t, object) != NULL); 190 } 191 192 int 193 mdb_ctf_lookup_by_name(const char *name, mdb_ctf_id_t *p) 194 { 195 ctf_file_t *fp = NULL; 196 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p; 197 mdb_tgt_t *t = mdb.m_target; 198 199 if (mcip == NULL) 200 return (set_errno(EINVAL)); 201 202 if ((fp = name_to_type(t, name, &mcip->mci_id)) == NULL) { 203 mdb_ctf_type_invalidate(p); 204 return (-1); /* errno is set for us */ 205 } 206 207 mcip->mci_fp = fp; 208 209 return (0); 210 } 211 212 int 213 mdb_ctf_lookup_by_symbol(const GElf_Sym *symp, const mdb_syminfo_t *sip, 214 mdb_ctf_id_t *p) 215 { 216 ctf_file_t *fp = NULL; 217 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p; 218 mdb_tgt_t *t = mdb.m_target; 219 220 if (mcip == NULL) 221 return (set_errno(EINVAL)); 222 223 if (symp == NULL || sip == NULL) { 224 mdb_ctf_type_invalidate(p); 225 return (set_errno(EINVAL)); 226 } 227 228 if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL) { 229 mdb_ctf_type_invalidate(p); 230 return (-1); /* errno is set for us */ 231 } 232 233 if ((mcip->mci_id = ctf_lookup_by_symbol(fp, sip->sym_id)) == CTF_ERR) { 234 mdb_ctf_type_invalidate(p); 235 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 236 } 237 238 mcip->mci_fp = fp; 239 240 return (0); 241 } 242 243 int 244 mdb_ctf_lookup_by_addr(uintptr_t addr, mdb_ctf_id_t *p) 245 { 246 GElf_Sym sym; 247 mdb_syminfo_t si; 248 char name[MDB_SYM_NAMLEN]; 249 const mdb_map_t *mp; 250 mdb_tgt_t *t = mdb.m_target; 251 const char *obj, *c; 252 253 if (p == NULL) 254 return (set_errno(EINVAL)); 255 256 if (mdb_tgt_lookup_by_addr(t, addr, MDB_TGT_SYM_EXACT, name, 257 sizeof (name), NULL, NULL) == -1) { 258 mdb_ctf_type_invalidate(p); 259 return (-1); /* errno is set for us */ 260 } 261 262 if ((c = strrsplit(name, '`')) != NULL) { 263 obj = name; 264 } else { 265 if ((mp = mdb_tgt_addr_to_map(t, addr)) == NULL) { 266 mdb_ctf_type_invalidate(p); 267 return (-1); /* errno is set for us */ 268 } 269 270 obj = mp->map_name; 271 c = name; 272 } 273 274 if (mdb_tgt_lookup_by_name(t, obj, c, &sym, &si) == -1) { 275 mdb_ctf_type_invalidate(p); 276 return (-1); /* errno is set for us */ 277 } 278 279 return (mdb_ctf_lookup_by_symbol(&sym, &si, p)); 280 } 281 282 int 283 mdb_ctf_module_lookup(const char *name, mdb_ctf_id_t *p) 284 { 285 ctf_file_t *fp; 286 ctf_id_t id; 287 mdb_module_t *mod; 288 289 if ((mod = mdb_get_module()) == NULL) 290 return (set_errno(EMDB_CTX)); 291 292 if ((fp = mod->mod_ctfp) == NULL) 293 return (set_errno(EMDB_NOCTF)); 294 295 if ((id = ctf_lookup_by_name(fp, name)) == CTF_ERR) 296 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 297 298 set_ctf_id(p, fp, id); 299 300 return (0); 301 } 302 303 /*ARGSUSED*/ 304 int 305 mdb_ctf_func_info(const GElf_Sym *symp, const mdb_syminfo_t *sip, 306 mdb_ctf_funcinfo_t *mfp) 307 { 308 ctf_file_t *fp = NULL; 309 ctf_funcinfo_t f; 310 mdb_tgt_t *t = mdb.m_target; 311 char name[MDB_SYM_NAMLEN]; 312 const mdb_map_t *mp; 313 mdb_syminfo_t si; 314 int err; 315 316 if (symp == NULL || mfp == NULL) 317 return (set_errno(EINVAL)); 318 319 /* 320 * In case the input symbol came from a merged or private symbol table, 321 * re-lookup the address as a symbol, and then perform a fully scoped 322 * lookup of that symbol name to get the mdb_syminfo_t for its CTF. 323 */ 324 if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL || 325 (mp = mdb_tgt_addr_to_map(t, symp->st_value)) == NULL || 326 mdb_tgt_lookup_by_addr(t, symp->st_value, MDB_TGT_SYM_FUZZY, 327 name, sizeof (name), NULL, NULL) != 0) 328 return (-1); /* errno is set for us */ 329 330 if (strchr(name, '`') != NULL) 331 err = mdb_tgt_lookup_by_scope(t, name, NULL, &si); 332 else 333 err = mdb_tgt_lookup_by_name(t, mp->map_name, name, NULL, &si); 334 335 if (err != 0) 336 return (-1); /* errno is set for us */ 337 338 if (ctf_func_info(fp, si.sym_id, &f) == CTF_ERR) 339 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 340 341 set_ctf_id(&mfp->mtf_return, fp, f.ctc_return); 342 mfp->mtf_argc = f.ctc_argc; 343 mfp->mtf_flags = f.ctc_flags; 344 mfp->mtf_symidx = si.sym_id; 345 346 return (0); 347 } 348 349 int 350 mdb_ctf_func_args(const mdb_ctf_funcinfo_t *funcp, uint_t len, 351 mdb_ctf_id_t *argv) 352 { 353 ctf_file_t *fp; 354 ctf_id_t cargv[32]; 355 int i; 356 357 if (len > (sizeof (cargv) / sizeof (cargv[0]))) 358 return (set_errno(EINVAL)); 359 360 if (funcp == NULL || argv == NULL) 361 return (set_errno(EINVAL)); 362 363 fp = mdb_ctf_type_file(funcp->mtf_return); 364 365 if (ctf_func_args(fp, funcp->mtf_symidx, len, cargv) == CTF_ERR) 366 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 367 368 for (i = MIN(len, funcp->mtf_argc) - 1; i >= 0; i--) { 369 set_ctf_id(&argv[i], fp, cargv[i]); 370 } 371 372 return (0); 373 } 374 375 void 376 mdb_ctf_type_invalidate(mdb_ctf_id_t *idp) 377 { 378 set_ctf_id(idp, NULL, CTF_ERR); 379 } 380 381 int 382 mdb_ctf_type_valid(mdb_ctf_id_t id) 383 { 384 return (((mdb_ctf_impl_t *)&id)->mci_id != CTF_ERR); 385 } 386 387 int 388 mdb_ctf_type_cmp(mdb_ctf_id_t aid, mdb_ctf_id_t bid) 389 { 390 mdb_ctf_impl_t *aidp = (mdb_ctf_impl_t *)&aid; 391 mdb_ctf_impl_t *bidp = (mdb_ctf_impl_t *)&bid; 392 393 return (ctf_type_cmp(aidp->mci_fp, aidp->mci_id, 394 bidp->mci_fp, bidp->mci_id)); 395 } 396 397 int 398 mdb_ctf_type_resolve(mdb_ctf_id_t mid, mdb_ctf_id_t *outp) 399 { 400 ctf_id_t id; 401 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)∣ 402 403 if ((id = ctf_type_resolve(idp->mci_fp, idp->mci_id)) == CTF_ERR) { 404 if (outp) 405 mdb_ctf_type_invalidate(outp); 406 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 407 } 408 409 if (ctf_type_kind(idp->mci_fp, id) == CTF_K_FORWARD) { 410 char name[MDB_SYM_NAMLEN]; 411 mdb_ctf_id_t lookup_id; 412 413 if (ctf_type_name(idp->mci_fp, id, name, sizeof (name)) != 414 NULL && 415 mdb_ctf_lookup_by_name(name, &lookup_id) == 0 && 416 outp != NULL) { 417 *outp = lookup_id; 418 return (0); 419 } 420 } 421 422 if (outp != NULL) 423 set_ctf_id(outp, idp->mci_fp, id); 424 425 return (0); 426 } 427 428 char * 429 mdb_ctf_type_name(mdb_ctf_id_t id, char *buf, size_t len) 430 { 431 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 432 char *ret; 433 434 if (!mdb_ctf_type_valid(id)) { 435 (void) set_errno(EINVAL); 436 return (NULL); 437 } 438 439 ret = ctf_type_name(idp->mci_fp, idp->mci_id, buf, len); 440 if (ret == NULL) 441 (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))); 442 443 return (ret); 444 } 445 446 ssize_t 447 mdb_ctf_type_size(mdb_ctf_id_t id) 448 { 449 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 450 ssize_t ret; 451 452 /* resolve the type in case there's a forward declaration */ 453 if ((ret = mdb_ctf_type_resolve(id, &id)) != 0) 454 return (ret); 455 456 if ((ret = ctf_type_size(idp->mci_fp, idp->mci_id)) == CTF_ERR) 457 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 458 459 return (ret); 460 } 461 462 int 463 mdb_ctf_type_kind(mdb_ctf_id_t id) 464 { 465 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 466 int ret; 467 468 if ((ret = ctf_type_kind(idp->mci_fp, idp->mci_id)) == CTF_ERR) 469 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 470 471 return (ret); 472 } 473 474 int 475 mdb_ctf_type_reference(mdb_ctf_id_t mid, mdb_ctf_id_t *outp) 476 { 477 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)∣ 478 ctf_id_t id; 479 480 if ((id = ctf_type_reference(idp->mci_fp, idp->mci_id)) == CTF_ERR) { 481 if (outp) 482 mdb_ctf_type_invalidate(outp); 483 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 484 } 485 486 if (outp != NULL) 487 set_ctf_id(outp, idp->mci_fp, id); 488 489 return (0); 490 } 491 492 493 int 494 mdb_ctf_type_encoding(mdb_ctf_id_t id, ctf_encoding_t *ep) 495 { 496 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 497 498 if (ctf_type_encoding(idp->mci_fp, idp->mci_id, ep) == CTF_ERR) 499 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 500 501 return (0); 502 } 503 504 /* 505 * callback proxy for mdb_ctf_type_visit 506 */ 507 static int 508 type_cb(const char *name, ctf_id_t type, ulong_t off, int depth, void *arg) 509 { 510 type_visit_t *tvp = arg; 511 mdb_ctf_id_t id; 512 mdb_ctf_id_t base; 513 mdb_ctf_impl_t *basep = (mdb_ctf_impl_t *)&base; 514 515 int ret; 516 517 if (depth < tvp->tv_min_depth) 518 return (0); 519 520 off += tvp->tv_base_offset; 521 depth += tvp->tv_base_depth; 522 523 set_ctf_id(&id, tvp->tv_fp, type); 524 525 (void) mdb_ctf_type_resolve(id, &base); 526 if ((ret = tvp->tv_cb(name, id, base, off, depth, tvp->tv_arg)) != 0) 527 return (ret); 528 529 /* 530 * If the type resolves to a type in a different file, we must have 531 * followed a forward declaration. We need to recurse into the 532 * new type. 533 */ 534 if (basep->mci_fp != tvp->tv_fp && mdb_ctf_type_valid(base)) { 535 type_visit_t tv; 536 537 tv.tv_cb = tvp->tv_cb; 538 tv.tv_arg = tvp->tv_arg; 539 tv.tv_fp = basep->mci_fp; 540 541 tv.tv_base_offset = off; 542 tv.tv_base_depth = depth; 543 tv.tv_min_depth = 1; /* depth = 0 has already been done */ 544 545 ret = ctf_type_visit(basep->mci_fp, basep->mci_id, 546 type_cb, &tv); 547 } 548 return (ret); 549 } 550 551 int 552 mdb_ctf_type_visit(mdb_ctf_id_t id, mdb_ctf_visit_f *func, void *arg) 553 { 554 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 555 type_visit_t tv; 556 int ret; 557 558 tv.tv_cb = func; 559 tv.tv_arg = arg; 560 tv.tv_fp = idp->mci_fp; 561 tv.tv_base_offset = 0; 562 tv.tv_base_depth = 0; 563 tv.tv_min_depth = 0; 564 565 ret = ctf_type_visit(idp->mci_fp, idp->mci_id, type_cb, &tv); 566 567 if (ret == CTF_ERR) 568 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 569 570 return (ret); 571 } 572 573 int 574 mdb_ctf_array_info(mdb_ctf_id_t id, mdb_ctf_arinfo_t *arp) 575 { 576 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 577 ctf_arinfo_t car; 578 579 if (ctf_array_info(idp->mci_fp, idp->mci_id, &car) == CTF_ERR) 580 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 581 582 set_ctf_id(&arp->mta_contents, idp->mci_fp, car.ctr_contents); 583 set_ctf_id(&arp->mta_index, idp->mci_fp, car.ctr_index); 584 585 arp->mta_nelems = car.ctr_nelems; 586 587 return (0); 588 } 589 590 const char * 591 mdb_ctf_enum_name(mdb_ctf_id_t id, int value) 592 { 593 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 594 const char *ret; 595 596 /* resolve the type in case there's a forward declaration */ 597 if (mdb_ctf_type_resolve(id, &id) != 0) 598 return (NULL); 599 600 if ((ret = ctf_enum_name(idp->mci_fp, idp->mci_id, value)) == NULL) 601 (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))); 602 603 return (ret); 604 } 605 606 /* 607 * callback proxy for mdb_ctf_member_iter 608 */ 609 static int 610 member_iter_cb(const char *name, ctf_id_t type, ulong_t off, void *data) 611 { 612 member_iter_t *mip = data; 613 mdb_ctf_id_t id; 614 615 set_ctf_id(&id, mip->mi_fp, type); 616 617 return (mip->mi_cb(name, id, off, mip->mi_arg)); 618 } 619 620 int 621 mdb_ctf_member_iter(mdb_ctf_id_t id, mdb_ctf_member_f *cb, void *data) 622 { 623 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 624 member_iter_t mi; 625 int ret; 626 627 /* resolve the type in case there's a forward declaration */ 628 if ((ret = mdb_ctf_type_resolve(id, &id)) != 0) 629 return (ret); 630 631 mi.mi_cb = cb; 632 mi.mi_arg = data; 633 mi.mi_fp = idp->mci_fp; 634 635 ret = ctf_member_iter(idp->mci_fp, idp->mci_id, member_iter_cb, &mi); 636 637 if (ret == CTF_ERR) 638 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); 639 640 return (ret); 641 } 642 643 int 644 mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data) 645 { 646 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; 647 int ret; 648 649 /* resolve the type in case there's a forward declaration */ 650 if ((ret = mdb_ctf_type_resolve(id, &id)) != 0) 651 return (ret); 652 653 return (ctf_enum_iter(idp->mci_fp, idp->mci_id, cb, data)); 654 } 655 656 /* 657 * callback proxy for mdb_ctf_type_iter 658 */ 659 static int 660 type_iter_cb(ctf_id_t type, void *data) 661 { 662 type_iter_t *tip = data; 663 mdb_ctf_id_t id; 664 665 set_ctf_id(&id, tip->ti_fp, type); 666 667 return (tip->ti_cb(id, tip->ti_arg)); 668 } 669 670 int 671 mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data) 672 { 673 ctf_file_t *fp; 674 mdb_tgt_t *t = mdb.m_target; 675 int ret; 676 type_iter_t ti; 677 678 if ((fp = mdb_tgt_name_to_ctf(t, object)) == NULL) 679 return (-1); 680 681 ti.ti_cb = cb; 682 ti.ti_arg = data; 683 ti.ti_fp = fp; 684 685 if ((ret = ctf_type_iter(fp, type_iter_cb, &ti)) == CTF_ERR) 686 return (set_errno(ctf_to_errno(ctf_errno(fp)))); 687 688 return (ret); 689 } 690 691 /* utility functions */ 692 693 ctf_id_t 694 mdb_ctf_type_id(mdb_ctf_id_t id) 695 { 696 return (((mdb_ctf_impl_t *)&id)->mci_id); 697 } 698 699 ctf_file_t * 700 mdb_ctf_type_file(mdb_ctf_id_t id) 701 { 702 return (((mdb_ctf_impl_t *)&id)->mci_fp); 703 } 704 705 static int 706 member_info_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data) 707 { 708 mbr_info_t *mbrp = data; 709 710 if (strcmp(name, mbrp->mbr_member) == 0) { 711 if (mbrp->mbr_offp != NULL) 712 *(mbrp->mbr_offp) = off; 713 if (mbrp->mbr_typep != NULL) 714 *(mbrp->mbr_typep) = id; 715 716 return (1); 717 } 718 719 return (0); 720 } 721 722 int 723 mdb_ctf_member_info(mdb_ctf_id_t id, const char *member, ulong_t *offp, 724 mdb_ctf_id_t *typep) 725 { 726 mbr_info_t mbr; 727 int rc; 728 729 mbr.mbr_member = member; 730 mbr.mbr_offp = offp; 731 mbr.mbr_typep = typep; 732 733 rc = mdb_ctf_member_iter(id, member_info_cb, &mbr); 734 735 /* couldn't get member list */ 736 if (rc == -1) 737 return (-1); /* errno is set for us */ 738 739 /* not a member */ 740 if (rc == 0) 741 return (set_errno(EMDB_CTFNOMEMB)); 742 743 return (0); 744 } 745 746 /* 747 * Returns offset in _bits_ in *retp. 748 */ 749 int 750 mdb_ctf_offsetof(mdb_ctf_id_t id, const char *member, ulong_t *retp) 751 { 752 return (mdb_ctf_member_info(id, member, retp, NULL)); 753 } 754 755 /* 756 * Returns offset in _bytes_, or -1 on failure. 757 */ 758 int 759 mdb_ctf_offsetof_by_name(const char *type, const char *member) 760 { 761 mdb_ctf_id_t id; 762 ulong_t off; 763 764 if (mdb_ctf_lookup_by_name(type, &id) == -1) { 765 mdb_warn("couldn't find type %s", type); 766 return (-1); 767 } 768 769 if (mdb_ctf_offsetof(id, member, &off) == -1) { 770 mdb_warn("couldn't find member %s of type %s", member, type); 771 return (-1); 772 } 773 if (off % 8 != 0) { 774 mdb_warn("member %s of type %s is an unsupported bitfield\n", 775 member, type); 776 return (-1); 777 } 778 off /= 8; 779 780 return (off); 781 } 782 783 784 /*ARGSUSED*/ 785 static int 786 num_members_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data) 787 { 788 int *count = data; 789 *count = *count + 1; 790 return (0); 791 } 792 793 int 794 mdb_ctf_num_members(mdb_ctf_id_t id) 795 { 796 int count = 0; 797 798 if (mdb_ctf_member_iter(id, num_members_cb, &count) != 0) 799 return (-1); /* errno is set for us */ 800 801 return (count); 802 } 803 804 typedef struct mbr_contains { 805 char **mbc_bufp; 806 size_t *mbc_lenp; 807 ulong_t *mbc_offp; 808 mdb_ctf_id_t *mbc_idp; 809 ssize_t mbc_total; 810 } mbr_contains_t; 811 812 static int 813 offset_to_name_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data) 814 { 815 mbr_contains_t *mbc = data; 816 ulong_t size; 817 ctf_encoding_t e; 818 size_t n; 819 820 if (*mbc->mbc_offp < off) 821 return (0); 822 823 if (mdb_ctf_type_encoding(id, &e) == -1) 824 size = mdb_ctf_type_size(id) * NBBY; 825 else 826 size = e.cte_bits; 827 828 if (off + size <= *mbc->mbc_offp) 829 return (0); 830 831 n = mdb_snprintf(*mbc->mbc_bufp, *mbc->mbc_lenp, "%s", name); 832 mbc->mbc_total += n; 833 if (n > *mbc->mbc_lenp) 834 n = *mbc->mbc_lenp; 835 836 *mbc->mbc_lenp -= n; 837 *mbc->mbc_bufp += n; 838 839 *mbc->mbc_offp -= off; 840 *mbc->mbc_idp = id; 841 842 return (1); 843 } 844 845 ssize_t 846 mdb_ctf_offset_to_name(mdb_ctf_id_t id, ulong_t off, char *buf, size_t len, 847 int dot, mdb_ctf_id_t *midp, ulong_t *moffp) 848 { 849 size_t size; 850 size_t n; 851 mbr_contains_t mbc; 852 853 if (!mdb_ctf_type_valid(id)) 854 return (set_errno(EINVAL)); 855 856 /* 857 * Quick sanity check to make sure the given offset is within 858 * this scope of this type. 859 */ 860 if (mdb_ctf_type_size(id) * NBBY <= off) 861 return (set_errno(EINVAL)); 862 863 mbc.mbc_bufp = &buf; 864 mbc.mbc_lenp = &len; 865 mbc.mbc_offp = &off; 866 mbc.mbc_idp = &id; 867 mbc.mbc_total = 0; 868 869 *buf = '\0'; 870 871 for (;;) { 872 /* 873 * Check for an exact match. 874 */ 875 if (off == 0) 876 break; 877 878 (void) mdb_ctf_type_resolve(id, &id); 879 880 /* 881 * Find the member that contains this offset. 882 */ 883 switch (mdb_ctf_type_kind(id)) { 884 case CTF_K_ARRAY: { 885 mdb_ctf_arinfo_t ar; 886 uint_t index; 887 888 (void) mdb_ctf_array_info(id, &ar); 889 size = mdb_ctf_type_size(ar.mta_contents) * NBBY; 890 index = off / size; 891 892 id = ar.mta_contents; 893 off %= size; 894 895 n = mdb_snprintf(buf, len, "[%u]", index); 896 mbc.mbc_total += n; 897 if (n > len) 898 n = len; 899 900 buf += n; 901 len -= n; 902 break; 903 } 904 905 case CTF_K_STRUCT: { 906 int ret; 907 908 /* 909 * Find the member that contains this offset 910 * and continue. 911 */ 912 913 if (dot) { 914 mbc.mbc_total++; 915 if (len != 0) { 916 *buf++ = '.'; 917 *buf = '\0'; 918 len--; 919 } 920 } 921 922 ret = mdb_ctf_member_iter(id, offset_to_name_cb, &mbc); 923 if (ret == -1) 924 return (-1); /* errno is set for us */ 925 926 /* 927 * If we did not find a member containing this offset 928 * (due to holes in the structure), return EINVAL. 929 */ 930 if (ret == 0) 931 return (set_errno(EINVAL)); 932 933 break; 934 } 935 936 case CTF_K_UNION: 937 /* 938 * Treat unions like atomic entities since we can't 939 * do more than guess which member of the union 940 * might be the intended one. 941 */ 942 goto done; 943 944 case CTF_K_INTEGER: 945 case CTF_K_FLOAT: 946 case CTF_K_POINTER: 947 case CTF_K_ENUM: 948 goto done; 949 950 default: 951 return (set_errno(EINVAL)); 952 } 953 954 dot = 1; 955 } 956 done: 957 if (midp != NULL) 958 *midp = id; 959 if (moffp != NULL) 960 *moffp = off; 961 962 return (mbc.mbc_total); 963 } 964 965 static void 966 mdb_ctf_warn(uint_t flags, const char *format, ...) 967 { 968 va_list alist; 969 970 if (flags & MDB_CTF_VREAD_QUIET) 971 return; 972 973 va_start(alist, format); 974 vwarn(format, alist); 975 va_end(alist); 976 } 977 978 /* 979 * Check if two types are structurally the same rather than logically 980 * the same. That is to say that two types are equal if they have the 981 * same logical structure rather than having the same ids in CTF-land. 982 */ 983 static int type_equals(mdb_ctf_id_t, mdb_ctf_id_t); 984 985 static int 986 type_equals_cb(const char *name, mdb_ctf_id_t amem, ulong_t aoff, void *data) 987 { 988 mdb_ctf_id_t b = *(mdb_ctf_id_t *)data; 989 ulong_t boff; 990 mdb_ctf_id_t bmem; 991 992 /* 993 * Look up the corresponding member in the other composite type. 994 */ 995 if (mdb_ctf_member_info(b, name, &boff, &bmem) != 0) 996 return (1); 997 998 /* 999 * We don't allow members to be shuffled around. 1000 */ 1001 if (aoff != boff) 1002 return (1); 1003 1004 return (type_equals(amem, bmem) ? 0 : 1); 1005 } 1006 1007 static int 1008 type_equals(mdb_ctf_id_t a, mdb_ctf_id_t b) 1009 { 1010 size_t asz, bsz; 1011 int akind, bkind; 1012 mdb_ctf_arinfo_t aar, bar; 1013 1014 /* 1015 * Resolve both types down to their fundamental types, and make 1016 * sure their sizes and kinds match. 1017 */ 1018 if (mdb_ctf_type_resolve(a, &a) != 0 || 1019 mdb_ctf_type_resolve(b, &b) != 0 || 1020 (asz = mdb_ctf_type_size(a)) == -1UL || 1021 (bsz = mdb_ctf_type_size(b)) == -1UL || 1022 (akind = mdb_ctf_type_kind(a)) == -1 || 1023 (bkind = mdb_ctf_type_kind(b)) == -1 || 1024 asz != bsz || akind != bkind) { 1025 return (0); 1026 } 1027 1028 switch (akind) { 1029 case CTF_K_INTEGER: 1030 case CTF_K_FLOAT: 1031 case CTF_K_POINTER: 1032 /* 1033 * For pointers we could be a little stricter and require 1034 * both pointers to reference types which look vaguely 1035 * similar (for example, we could insist that the two types 1036 * have the same name). However, all we really care about 1037 * here is that the structure of the two types are the same, 1038 * and, in that regard, one pointer is as good as another. 1039 */ 1040 return (1); 1041 1042 case CTF_K_UNION: 1043 case CTF_K_STRUCT: 1044 /* 1045 * The test for the number of members is only strictly 1046 * necessary for unions since we'll find other problems with 1047 * structs. However, the extra check will do no harm. 1048 */ 1049 return (mdb_ctf_num_members(a) == mdb_ctf_num_members(b) && 1050 mdb_ctf_member_iter(a, type_equals_cb, &b) == 0); 1051 1052 case CTF_K_ARRAY: 1053 return (mdb_ctf_array_info(a, &aar) == 0 && 1054 mdb_ctf_array_info(b, &bar) == 0 && 1055 aar.mta_nelems == bar.mta_nelems && 1056 type_equals(aar.mta_index, bar.mta_index) && 1057 type_equals(aar.mta_contents, bar.mta_contents)); 1058 } 1059 1060 return (0); 1061 } 1062 1063 1064 typedef struct member { 1065 char *m_modbuf; 1066 char *m_tgtbuf; 1067 const char *m_tgtname; 1068 mdb_ctf_id_t m_tgtid; 1069 uint_t m_flags; 1070 } member_t; 1071 1072 static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *, 1073 const char *, uint_t); 1074 1075 static int 1076 member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data) 1077 { 1078 member_t *mp = data; 1079 char *modbuf = mp->m_modbuf; 1080 mdb_ctf_id_t tgtmid; 1081 char *tgtbuf = mp->m_tgtbuf; 1082 ulong_t tgtoff; 1083 char tgtname[128]; 1084 1085 (void) mdb_snprintf(tgtname, sizeof (tgtname), 1086 "member %s of type %s", name, mp->m_tgtname); 1087 1088 if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) { 1089 mdb_ctf_warn(mp->m_flags, 1090 "could not find %s\n", tgtname); 1091 return (set_errno(EMDB_CTFNOMEMB)); 1092 } 1093 1094 return (vread_helper(modmid, modbuf + modoff / NBBY, 1095 tgtmid, tgtbuf + tgtoff / NBBY, tgtname, mp->m_flags)); 1096 } 1097 1098 typedef struct enum_value { 1099 int *ev_modbuf; 1100 const char *ev_name; 1101 } enum_value_t; 1102 1103 static int 1104 enum_cb(const char *name, int value, void *data) 1105 { 1106 enum_value_t *ev = data; 1107 1108 if (strcmp(name, ev->ev_name) == 0) { 1109 *ev->ev_modbuf = value; 1110 return (1); 1111 } 1112 return (0); 1113 } 1114 1115 static int 1116 vread_helper(mdb_ctf_id_t modid, char *modbuf, 1117 mdb_ctf_id_t tgtid, char *tgtbuf, const char *tgtname, uint_t flags) 1118 { 1119 size_t modsz, tgtsz; 1120 int modkind, tgtkind; 1121 member_t mbr; 1122 enum_value_t ev; 1123 int ret; 1124 mdb_ctf_arinfo_t tar, mar; 1125 int i; 1126 char typename[128]; 1127 char mdbtypename[128]; 1128 ctf_encoding_t tgt_encoding, mod_encoding; 1129 boolean_t signed_int = B_FALSE; 1130 1131 if (mdb_ctf_type_name(tgtid, typename, sizeof (typename)) == NULL) { 1132 (void) mdb_snprintf(typename, sizeof (typename), 1133 "#%ul", mdb_ctf_type_id(tgtid)); 1134 } 1135 if (mdb_ctf_type_name(modid, 1136 mdbtypename, sizeof (mdbtypename)) == NULL) { 1137 (void) mdb_snprintf(mdbtypename, sizeof (mdbtypename), 1138 "#%ul", mdb_ctf_type_id(modid)); 1139 } 1140 1141 if (tgtname == NULL) 1142 tgtname = ""; 1143 1144 /* 1145 * Resolve the types to their canonical form. 1146 */ 1147 (void) mdb_ctf_type_resolve(modid, &modid); 1148 (void) mdb_ctf_type_resolve(tgtid, &tgtid); 1149 1150 if ((modkind = mdb_ctf_type_kind(modid)) == -1) { 1151 mdb_ctf_warn(flags, 1152 "couldn't determine type kind of mdb module type %s\n", 1153 mdbtypename); 1154 return (-1); /* errno is set for us */ 1155 } 1156 if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) { 1157 mdb_ctf_warn(flags, 1158 "couldn't determine type kind of %s\n", typename); 1159 return (-1); /* errno is set for us */ 1160 } 1161 1162 if ((modsz = mdb_ctf_type_size(modid)) == -1UL) { 1163 mdb_ctf_warn(flags, "couldn't determine type size of " 1164 "mdb module type %s\n", mdbtypename); 1165 return (-1); /* errno is set for us */ 1166 } 1167 if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) { 1168 mdb_ctf_warn(flags, "couldn't determine size of %s (%s)\n", 1169 typename, tgtname); 1170 return (-1); /* errno is set for us */ 1171 } 1172 1173 if (tgtkind == CTF_K_POINTER && modkind == CTF_K_INTEGER && 1174 strcmp(mdbtypename, "uintptr_t") == 0) { 1175 /* allow them to convert a pointer to a uintptr_t */ 1176 ASSERT(modsz == tgtsz); 1177 } else if (tgtkind != modkind) { 1178 mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n", 1179 typename, tgtname); 1180 return (set_errno(EMDB_INCOMPAT)); 1181 } 1182 1183 switch (tgtkind) { 1184 case CTF_K_INTEGER: 1185 case CTF_K_FLOAT: 1186 /* 1187 * Must determine if the target and module types have the same 1188 * encoding before we can copy them. 1189 */ 1190 if (mdb_ctf_type_encoding(tgtid, &tgt_encoding) != 0) { 1191 mdb_ctf_warn(flags, 1192 "couldn't determine encoding of type %s (%s)\n", 1193 typename, tgtname); 1194 return (-1); /* errno is set for us */ 1195 } 1196 if (mdb_ctf_type_encoding(modid, &mod_encoding) != 0) { 1197 mdb_ctf_warn(flags, "couldn't determine encoding of " 1198 "mdb module type %s\n", mdbtypename); 1199 return (-1); /* errno is set for us */ 1200 } 1201 1202 if (modkind == CTF_K_INTEGER) { 1203 if ((tgt_encoding.cte_format & CTF_INT_SIGNED) != 1204 (mod_encoding.cte_format & CTF_INT_SIGNED)) { 1205 mdb_ctf_warn(flags, 1206 "signedness mismatch between type " 1207 "%s (%s) and mdb module type %s\n", 1208 typename, tgtname, mdbtypename); 1209 return (set_errno(EMDB_INCOMPAT)); 1210 } 1211 signed_int = 1212 ((tgt_encoding.cte_format & CTF_INT_SIGNED) != 0); 1213 } else if (tgt_encoding.cte_format != mod_encoding.cte_format) { 1214 mdb_ctf_warn(flags, 1215 "encoding mismatch (%#x != %#x) between type " 1216 "%s (%s) and mdb module type %s\n", 1217 tgt_encoding.cte_format, mod_encoding.cte_format, 1218 typename, tgtname, mdbtypename); 1219 return (set_errno(EMDB_INCOMPAT)); 1220 } 1221 /* FALLTHROUGH */ 1222 case CTF_K_POINTER: 1223 /* 1224 * If the sizes don't match we need to be tricky to make 1225 * sure that the caller gets the correct data. 1226 */ 1227 if (modsz < tgtsz) { 1228 mdb_ctf_warn(flags, "size of type %s (%s) is too " 1229 "large for mdb module type %s\n", 1230 typename, tgtname, mdbtypename); 1231 return (set_errno(EMDB_INCOMPAT)); 1232 } else if (modsz > tgtsz) { 1233 /* BEGIN CSTYLED */ 1234 /* 1235 * Fill modbuf with 1's for sign extension if target 1236 * buf is a signed integer and its value is negative. 1237 * 1238 * S = sign bit (in most-significant byte) 1239 * 1240 * BIG ENDIAN DATA 1241 * +--------+--------+--------+--------+ 1242 * |S | | | | 1243 * +--------+--------+--------+--------+ 1244 * 0 1 ... sz-1 sz 1245 * 1246 * LITTLE ENDIAN DATA 1247 * +--------+--------+--------+--------+ 1248 * | | | |S | 1249 * +--------+--------+--------+--------+ 1250 * 0 1 ... sz-1 sz 1251 */ 1252 /* END CSTYLED */ 1253 #ifdef _BIG_ENDIAN 1254 if (signed_int && (tgtbuf[0] & 0x80) != 0) 1255 #else 1256 if (signed_int && (tgtbuf[tgtsz - 1] & 0x80) != 0) 1257 #endif 1258 (void) memset(modbuf, 0xFF, modsz); 1259 else 1260 bzero(modbuf, modsz); 1261 #ifdef _BIG_ENDIAN 1262 bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz); 1263 #else 1264 bcopy(tgtbuf, modbuf, tgtsz); 1265 #endif 1266 } else { 1267 bcopy(tgtbuf, modbuf, modsz); 1268 } 1269 1270 return (0); 1271 1272 case CTF_K_ENUM: 1273 if (modsz != tgtsz || modsz != sizeof (int)) { 1274 mdb_ctf_warn(flags, "unexpected size of type %s (%s)\n", 1275 typename, tgtname); 1276 return (set_errno(EMDB_INCOMPAT)); 1277 } 1278 1279 /* 1280 * Default to the same value as in the target. 1281 */ 1282 bcopy(tgtbuf, modbuf, sizeof (int)); 1283 1284 /* LINTED */ 1285 i = *(int *)tgtbuf; 1286 1287 /* LINTED */ 1288 ev.ev_modbuf = (int *)modbuf; 1289 ev.ev_name = mdb_ctf_enum_name(tgtid, i); 1290 if (ev.ev_name == NULL) { 1291 mdb_ctf_warn(flags, 1292 "unexpected value %u of enum type %s (%s)\n", 1293 i, typename, tgtname); 1294 return (set_errno(EMDB_INCOMPAT)); 1295 } 1296 1297 ret = mdb_ctf_enum_iter(modid, enum_cb, &ev); 1298 if (ret == 0) { 1299 /* value not found */ 1300 mdb_ctf_warn(flags, 1301 "unexpected value %s (%u) of enum type %s (%s)\n", 1302 ev.ev_name, i, typename, tgtname); 1303 return (set_errno(EMDB_INCOMPAT)); 1304 } else if (ret == 1) { 1305 /* value found */ 1306 return (0); 1307 } else if (ret == -1) { 1308 mdb_ctf_warn(flags, "could not iterate enum %s (%s)\n", 1309 typename, tgtname); 1310 } 1311 return (ret); 1312 1313 case CTF_K_STRUCT: 1314 mbr.m_modbuf = modbuf; 1315 mbr.m_tgtbuf = tgtbuf; 1316 mbr.m_tgtid = tgtid; 1317 mbr.m_flags = flags; 1318 mbr.m_tgtname = typename; 1319 1320 return (mdb_ctf_member_iter(modid, member_cb, &mbr)); 1321 1322 case CTF_K_UNION: 1323 1324 /* 1325 * Unions are a little tricky. The only time it's truly 1326 * safe to read in a union is if no part of the union or 1327 * any of its component types have changed. The correct 1328 * use of this feature is to read the containing structure, 1329 * figure out which component of the union is valid, compute 1330 * the location of that in the target and then read in 1331 * that part of the structure. 1332 */ 1333 1334 if (!type_equals(modid, tgtid)) { 1335 mdb_ctf_warn(flags, "inexact match for union %s (%s)\n", 1336 typename, tgtname); 1337 return (set_errno(EMDB_INCOMPAT)); 1338 } 1339 1340 ASSERT(modsz == tgtsz); 1341 1342 bcopy(tgtbuf, modbuf, modsz); 1343 1344 return (0); 1345 1346 case CTF_K_ARRAY: 1347 if (mdb_ctf_array_info(tgtid, &tar) != 0) { 1348 mdb_ctf_warn(flags, 1349 "couldn't get array info for %s (%s)\n", 1350 typename, tgtname); 1351 return (-1); /* errno is set for us */ 1352 } 1353 if (mdb_ctf_array_info(modid, &mar) != 0) { 1354 mdb_ctf_warn(flags, 1355 "couldn't get array info for mdb module type %s\n", 1356 mdbtypename); 1357 return (-1); /* errno is set for us */ 1358 } 1359 1360 if (tar.mta_nelems != mar.mta_nelems) { 1361 mdb_ctf_warn(flags, 1362 "unexpected array size (%u) for type %s (%s)\n", 1363 tar.mta_nelems, typename, tgtname); 1364 return (set_errno(EMDB_INCOMPAT)); 1365 } 1366 1367 if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) { 1368 mdb_ctf_warn(flags, "couldn't determine type size of " 1369 "mdb module type %s\n", mdbtypename); 1370 return (-1); /* errno is set for us */ 1371 } 1372 if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) { 1373 mdb_ctf_warn(flags, 1374 "couldn't determine size of %s (%s)\n", 1375 typename, tgtname); 1376 return (-1); /* errno is set for us */ 1377 } 1378 1379 for (i = 0; i < tar.mta_nelems; i++) { 1380 ret = vread_helper(mar.mta_contents, modbuf + i * modsz, 1381 tar.mta_contents, tgtbuf + i * tgtsz, 1382 tgtname, flags); 1383 1384 if (ret != 0) 1385 return (ret); 1386 } 1387 1388 return (0); 1389 } 1390 1391 mdb_ctf_warn(flags, "unsupported kind %d for type %s (%s)\n", 1392 modkind, typename, tgtname); 1393 return (set_errno(EMDB_INCOMPAT)); 1394 } 1395 1396 /* 1397 * Like mdb_vread(), mdb_ctf_vread() is used to read from the target's 1398 * virtual address space. However, mdb_ctf_vread() can be used to safely 1399 * read a complex type (e.g. a struct) from the target, even if MDB was compiled 1400 * against a different definition of that type (e.g. when debugging a crash 1401 * dump from an older release). 1402 * 1403 * Callers can achieve this by defining their own type which corresponds to the 1404 * type in the target, but contains only the members that the caller requires. 1405 * Using the CTF type information embedded in the target, mdb_ctf_vread will 1406 * find the required members in the target and fill in the caller's structure. 1407 * The members are located by name, and their types are verified to be 1408 * compatible. 1409 * 1410 * By convention, the caller will declare a type with the name "mdb_<type>", 1411 * where <type> is the name of the type in the target (e.g. mdb_zio_t). This 1412 * type will contain the members that the caller is interested in. For example: 1413 * 1414 * typedef struct mdb_zio { 1415 * enum zio_type io_type; 1416 * void *io_waiter; 1417 * struct { 1418 * struct { 1419 * void *list_next; 1420 * } list_head; 1421 * } io_parent_list; 1422 * int io_error; 1423 * } mdb_zio_t; 1424 * 1425 * mdb_zio_t zio; 1426 * error = mdb_ctf_vread(&zio, "zio_t", "mdb_zio_t", zio_target_addr, 0); 1427 * 1428 * If a given MDB module has different dcmds or walkers that need to read 1429 * different members from the same struct, then different "mdb_" types 1430 * should be declared for each caller. By convention, these types should 1431 * be named "mdb_<dcmd or walker>_<type>", e.g. mdb_findstack_kthread_t 1432 * for ::findstack. If the MDB module is compiled from several source files, 1433 * one must be especially careful to not define different types with the 1434 * same name in different source files, because the compiler can not detect 1435 * this error. 1436 * 1437 * Enums will also be translated by name, so the mdb module will receive 1438 * the enum value it expects even if the target has renumbered the enum. 1439 * Warning: it will therefore only work with enums are only used to store 1440 * legitimate enum values (not several values or-ed together). 1441 * 1442 * By default, if mdb_ctf_vread() can not find any members or enum values, 1443 * it will print a descriptive message (with mdb_warn()) and fail. 1444 * Passing MDB_CTF_VREAD_QUIET in 'flags' will suppress the warning message. 1445 * Additional flags can be used to ignore specific types of translation 1446 * failure, but should be used with caution, because they will silently leave 1447 * the caller's buffer uninitialized. 1448 */ 1449 int 1450 mdb_ctf_vread(void *modbuf, const char *target_typename, 1451 const char *mdb_typename, uintptr_t addr, uint_t flags) 1452 { 1453 ctf_file_t *mfp; 1454 ctf_id_t mid; 1455 void *tgtbuf; 1456 size_t size; 1457 mdb_ctf_id_t tgtid; 1458 mdb_ctf_id_t modid; 1459 mdb_module_t *mod; 1460 1461 if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) { 1462 mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n", 1463 mod->mod_name); 1464 return (set_errno(EMDB_NOCTF)); 1465 } 1466 1467 if ((mid = ctf_lookup_by_name(mfp, mdb_typename)) == CTF_ERR) { 1468 mdb_ctf_warn(flags, "couldn't find ctf data for " 1469 "type %s in mdb module %s\n", 1470 mdb_typename, mod->mod_name); 1471 return (set_errno(ctf_to_errno(ctf_errno(mfp)))); 1472 } 1473 1474 set_ctf_id(&modid, mfp, mid); 1475 1476 if (mdb_ctf_lookup_by_name(target_typename, &tgtid) != 0) { 1477 mdb_ctf_warn(flags, 1478 "couldn't find type %s in target's ctf data\n", 1479 target_typename); 1480 return (set_errno(EMDB_NOCTF)); 1481 } 1482 1483 /* 1484 * Read the data out of the target's address space. 1485 */ 1486 if ((size = mdb_ctf_type_size(tgtid)) == -1UL) { 1487 mdb_ctf_warn(flags, "couldn't determine size of type %s\n", 1488 target_typename); 1489 return (-1); /* errno is set for us */ 1490 } 1491 1492 tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC); 1493 1494 if (mdb_vread(tgtbuf, size, addr) < 0) { 1495 mdb_ctf_warn(flags, "couldn't read %s from %p\n", 1496 target_typename, addr); 1497 return (-1); /* errno is set for us */ 1498 } 1499 1500 return (vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags)); 1501 } 1502 1503 /* 1504 * Note: mdb_ctf_readsym() doesn't take separate parameters for the name 1505 * of the target's type vs the mdb module's type. Use with complicated 1506 * types (e.g. structs) may result in unnecessary failure if a member of 1507 * the struct has been changed in the target, but is not actually needed 1508 * by the mdb module. Use mdb_lookup_by_name() + mdb_ctf_vread() to 1509 * avoid this problem. 1510 */ 1511 int 1512 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags) 1513 { 1514 GElf_Sym sym; 1515 1516 if (mdb_lookup_by_obj(MDB_TGT_OBJ_EVERY, name, &sym) != 0) { 1517 mdb_ctf_warn(flags, "couldn't find symbol %s\n", name); 1518 return (-1); /* errno is set for us */ 1519 } 1520 1521 return (mdb_ctf_vread(buf, typename, typename, sym.st_value, flags)); 1522 } 1523 1524 ctf_file_t * 1525 mdb_ctf_bufopen(const void *ctf_va, size_t ctf_size, const void *sym_va, 1526 Shdr *symhdr, const void *str_va, Shdr *strhdr, int *errp) 1527 { 1528 ctf_sect_t ctdata, symtab, strtab; 1529 1530 ctdata.cts_name = ".SUNW_ctf"; 1531 ctdata.cts_type = SHT_PROGBITS; 1532 ctdata.cts_flags = 0; 1533 ctdata.cts_data = ctf_va; 1534 ctdata.cts_size = ctf_size; 1535 ctdata.cts_entsize = 1; 1536 ctdata.cts_offset = 0; 1537 1538 symtab.cts_name = ".symtab"; 1539 symtab.cts_type = symhdr->sh_type; 1540 symtab.cts_flags = symhdr->sh_flags; 1541 symtab.cts_data = sym_va; 1542 symtab.cts_size = symhdr->sh_size; 1543 symtab.cts_entsize = symhdr->sh_entsize; 1544 symtab.cts_offset = symhdr->sh_offset; 1545 1546 strtab.cts_name = ".strtab"; 1547 strtab.cts_type = strhdr->sh_type; 1548 strtab.cts_flags = strhdr->sh_flags; 1549 strtab.cts_data = str_va; 1550 strtab.cts_size = strhdr->sh_size; 1551 strtab.cts_entsize = strhdr->sh_entsize; 1552 strtab.cts_offset = strhdr->sh_offset; 1553 1554 return (ctf_bufopen(&ctdata, &symtab, &strtab, errp)); 1555 } 1556