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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. 28 * Copyright (c) 2018, Joyent, Inc. 29 * Copyright 2022 Oxide Computer Company 30 */ 31 32 #include <stdlib.h> 33 #include <stdio.h> 34 #include <string.h> 35 #include <sys/types.h> 36 #include <unistd.h> 37 #include <sys/corectl.h> 38 #include <procfs.h> 39 #include <msg.h> 40 #include <_elfdump.h> 41 #include <struct_layout.h> 42 #include <conv.h> 43 #include <ctype.h> 44 #include <sys/sysmacros.h> 45 46 47 /* 48 * This module contains the code that displays data from the note 49 * sections found in illumos core files. The format of these 50 * note sections are described in the core(5) manpage. 51 */ 52 53 54 55 56 /* 57 * Much of the code in this file uses the "%*s" format to set 58 * the left margin indentation. This macro combines the indent 59 * integer argument and the NULL string that follows it. 60 */ 61 #define INDENT state->ns_indent, MSG_ORIG(MSG_STR_EMPTY) 62 63 /* 64 * Indent unit, used for each nesting 65 */ 66 #define INDENT_STEP 4 67 68 /* 69 * The PRINT_ macros are convenience wrappers on print_num(), 70 * print_subtype(), and print_strbuf(). They reduce code 71 * clutter by hiding the boilerplate arguments. 72 * 73 * Assumptions: 74 * - A variable named "layout" exists in the compilation 75 * environment, referencing the layout information for the 76 * current type. 77 * - The variable "state" references the current note state. 78 */ 79 #define PRINT_DEC(_title, _field) \ 80 print_num(state, _title, &layout->_field, SL_FMT_NUM_DEC) 81 #define PRINT_DEC_2UP(_title1, _field1, _title2, _field2) \ 82 print_num_2up(state, _title1, &layout->_field1, SL_FMT_NUM_DEC, \ 83 _title2, &layout->_field2, SL_FMT_NUM_DEC) 84 #define PRINT_HEX(_title, _field) \ 85 print_num(state, _title, &layout->_field, SL_FMT_NUM_HEX) 86 #define PRINT_HEX_2UP(_title1, _field1, _title2, _field2) \ 87 print_num_2up(state, _title1, &layout->_field1, SL_FMT_NUM_HEX, \ 88 _title2, &layout->_field2, SL_FMT_NUM_HEX) 89 #define PRINT_ZHEX(_title, _field) \ 90 print_num(state, _title, &layout->_field, SL_FMT_NUM_ZHEX) 91 #define PRINT_ZHEX_2UP(_title1, _field1, _title2, _field2) \ 92 print_num_2up(state, _title1, &layout->_field1, SL_FMT_NUM_ZHEX, \ 93 _title2, &layout->_field2, SL_FMT_NUM_ZHEX) 94 #define PRINT_SUBTYPE(_title, _field, _func) \ 95 print_subtype(state, _title, &layout->_field, _func) 96 #define PRINT_STRBUF(_title, _field) \ 97 print_strbuf(state, _title, &layout->_field) 98 99 100 /* 101 * Structure used to maintain state data for a core note, or a subregion 102 * (sub-struct) of a core note. These values would otherwise need to be 103 * passed to nearly every routine. 104 */ 105 typedef struct { 106 Half ns_mach; /* ELF machine type of core file */ 107 const sl_arch_layout_t *ns_arch; /* structure layout def for mach */ 108 int ns_swap; /* True if byte swapping is needed */ 109 int ns_indent; /* Left margin indentation */ 110 int ns_vcol; /* Column where value starts */ 111 int ns_t2col; /* Column where 2up title starts */ 112 int ns_v2col; /* Column where 2up value starts */ 113 const char *ns_data; /* Pointer to struct data area */ 114 Word ns_len; /* Length of struct data area */ 115 } note_state_t; 116 117 /* 118 * Standard signature for a dump function used to process a note 119 * or a sub-structure within a note. 120 */ 121 typedef void (* dump_func_t)(note_state_t *state, const char *title); 122 123 124 125 126 127 128 /* 129 * Some core notes contain string buffers of fixed size 130 * that are expected to contain NULL terminated strings. 131 * If the NULL is there, we can print these strings directly. 132 * However, the potential exists for a corrupt file to have 133 * a non-terminated buffer. This routine examines the given 134 * string, and if the string is terminated, the string itself 135 * is returned. Otherwise, it is copied to a static buffer, 136 * and a pointer to the buffer is returned. 137 */ 138 static const char * 139 safe_str(const char *str, size_t n) 140 { 141 static char buf[2048]; 142 size_t i, used; 143 144 if (n == 0) 145 return (MSG_ORIG(MSG_STR_EMPTY)); 146 147 /* 148 * If the string is terminated and doesn't need escaping, we can return 149 * it as is. 150 */ 151 for (i = 0; i < n; i++) { 152 if (str[i] == '\0') 153 return (str); 154 155 if (!isascii(str[i]) || !isprint(str[i])) { 156 break; 157 } 158 } 159 160 for (i = 0, used = 0; i < n; i++) { 161 if (str[i] == '\0') { 162 if (used + 1 > sizeof (buf)) 163 break; 164 buf[used++] = str[i]; 165 return (buf); 166 } else if (isascii(str[i]) && isprint(str[i])) { 167 if (used + 1 > sizeof (buf)) 168 break; 169 buf[used++] = str[i]; 170 } else { 171 size_t len = snprintf(NULL, 0, "\\x%02x", str[i]); 172 if (used + len > sizeof (buf)) 173 break; 174 (void) snprintf(buf + used, sizeof (buf) - used, 175 "\\x%02x", str[i]); 176 used += len; 177 } 178 } 179 180 if (i == n && used < sizeof (buf)) { 181 buf[used] = '\0'; 182 return (buf); 183 } 184 185 /* 186 * If we got here, we would have overflowed. Figure out where we need to 187 * start and truncate. 188 */ 189 used = MIN(used, sizeof (buf) - 4); 190 buf[used++] = '.'; 191 buf[used++] = '.'; 192 buf[used++] = '.'; 193 buf[used++] = '\0'; 194 return (buf); 195 } 196 197 /* 198 * Convenience wrappers on top of the corresponding sl_XXX() functions. 199 */ 200 static Word 201 extract_as_word(note_state_t *state, const sl_field_t *fdesc) 202 { 203 return (sl_extract_as_word(state->ns_data, state->ns_swap, fdesc)); 204 } 205 static Lword 206 extract_as_lword(note_state_t *state, const sl_field_t *fdesc) 207 { 208 return (sl_extract_as_lword(state->ns_data, state->ns_swap, fdesc)); 209 } 210 static int 211 extract_as_sword(note_state_t *state, const sl_field_t *fdesc) 212 { 213 return (sl_extract_as_sword(state->ns_data, state->ns_swap, fdesc)); 214 } 215 static const char * 216 fmt_num(note_state_t *state, const sl_field_t *fdesc, 217 sl_fmt_num_t fmt_type, sl_fmtbuf_t buf) 218 { 219 return (sl_fmt_num(state->ns_data, state->ns_swap, fdesc, 220 fmt_type, buf)); 221 } 222 223 224 /* 225 * Return true of the data for the specified field is available. 226 */ 227 inline static int 228 data_present(note_state_t *state, const sl_field_t *fdesc) 229 { 230 return ((fdesc->slf_offset + fdesc->slf_eltlen) <= state->ns_len); 231 } 232 233 /* 234 * indent_enter/exit are used to start/end output for a subitem. 235 * On entry, a title is output, and the indentation level is raised 236 * by one unit. On exit, the indentation level is restored to its 237 * previous value. 238 */ 239 static void 240 indent_enter(note_state_t *state, const char *title, 241 const sl_field_t *first_fdesc) 242 { 243 /* 244 * If the first field offset and extent fall past the end of the 245 * available data, then return without printing a title. That note 246 * is from an older core file that doesn't have all the fields 247 * that we know about. 248 */ 249 if (data_present(state, first_fdesc)) 250 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_TITLE), INDENT, title); 251 252 state->ns_indent += INDENT_STEP; 253 } 254 static void 255 indent_exit(note_state_t *state) 256 { 257 state->ns_indent -= INDENT_STEP; 258 } 259 260 261 /* 262 * print_num outputs a field on one line, in the format: 263 * 264 * title: value 265 */ 266 static void 267 print_num(note_state_t *state, const char *title, 268 const sl_field_t *fdesc, sl_fmt_num_t fmt_type) 269 { 270 sl_fmtbuf_t buf; 271 272 /* 273 * If the field offset and extent fall past the end of the 274 * available data, then return without doing anything. That note 275 * is from an older core file that doesn't have all the fields 276 * that we know about. 277 */ 278 if (!data_present(state, fdesc)) 279 return; 280 281 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE), INDENT, 282 state->ns_vcol - state->ns_indent, title, 283 fmt_num(state, fdesc, fmt_type, buf)); 284 } 285 286 /* 287 * print_num_2up outputs two fields on one line, in the format: 288 * 289 * title1: value1 title2: value2 290 */ 291 static void 292 print_num_2up(note_state_t *state, const char *title1, 293 const sl_field_t *fdesc1, sl_fmt_num_t fmt_type1, const char *title2, 294 const sl_field_t *fdesc2, sl_fmt_num_t fmt_type2) 295 { 296 sl_fmtbuf_t buf1, buf2; 297 298 /* 299 * If the field offset and extent fall past the end of the 300 * available data, then return without doing anything. That note 301 * is from an older core file that doesn't have all the fields 302 * that we know about. 303 */ 304 if (!(data_present(state, fdesc1) && 305 data_present(state, fdesc2))) 306 return; 307 308 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE_2UP), INDENT, 309 state->ns_vcol - state->ns_indent, title1, 310 state->ns_t2col - state->ns_vcol, 311 fmt_num(state, fdesc1, fmt_type1, buf1), 312 state->ns_v2col - state->ns_t2col, title2, 313 fmt_num(state, fdesc2, fmt_type2, buf2)); 314 } 315 316 /* 317 * print_strbuf outputs a fixed sized character buffer field 318 * on one line, in the format: 319 * 320 * title: value 321 */ 322 static void 323 print_strbuf(note_state_t *state, const char *title, 324 const sl_field_t *fdesc) 325 { 326 Word n; 327 328 /* 329 * If we are past the end of the data area, then return 330 * without doing anything. That note is from an older core 331 * file that doesn't have all the fields that we know about. 332 * 333 * Note that we are willing to accept a partial buffer, 334 * so we don't use data_present() for this test. 335 */ 336 if (fdesc->slf_offset >= state->ns_len) 337 return; 338 339 /* 340 * We expect the full buffer to be present, but if there 341 * is less than that, we will still proceed. The use of safe_str() 342 * protects us from the effect of printing garbage data. 343 */ 344 n = state->ns_len - fdesc->slf_offset; 345 if (n > fdesc->slf_nelts) 346 n = fdesc->slf_nelts; 347 348 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE), INDENT, 349 state->ns_vcol - state->ns_indent, 350 title, safe_str(fdesc->slf_offset + state->ns_data, n)); 351 } 352 353 /* 354 * print_str outputs an arbitrary string value item 355 * on one line, in the format: 356 * 357 * title: str 358 */ 359 static void 360 print_str(note_state_t *state, const char *title, const char *str) 361 { 362 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE), INDENT, 363 state->ns_vcol - state->ns_indent, title, str); 364 } 365 366 /* 367 * Used when one dump function needs to call another dump function 368 * in order to display a subitem. This routine constructs a state 369 * block for the sub-region, and then calls the dump function with it. 370 * This limits the amount of data visible to the sub-function to that 371 * for the sub-item. 372 */ 373 static void 374 print_subtype(note_state_t *state, const char *title, 375 const sl_field_t *fdesc, dump_func_t dump_func) 376 { 377 note_state_t sub_state; 378 379 /* 380 * If there is no data for the sub-item, return immediately. 381 * Partial data is left to the dump function to handle, 382 * as that can be a sign of an older core file with less data, 383 * which can still be interpreted. 384 */ 385 if (fdesc->slf_offset >= state->ns_len) 386 return; 387 388 /* 389 * Construct a state block that reflects the sub-item 390 */ 391 sub_state = *state; 392 sub_state.ns_data += fdesc->slf_offset; 393 sub_state.ns_len -= fdesc->slf_offset; 394 if (sub_state.ns_len > fdesc->slf_eltlen) 395 sub_state.ns_len = fdesc->slf_eltlen; 396 397 (* dump_func)(&sub_state, title); 398 } 399 400 401 /* 402 * Output a sequence of array elements, giving each 403 * element an index, in the format: 404 * 405 * [ndx] value 406 * 407 * entry: 408 * state - Current state 409 * base_desc - Field descriptor for 1st element of array 410 * nelts - # of array elements to display 411 * check_nelts - If True (1), nelts is clipped to fdesc->slf_nelts. 412 * If False (1), nelts is not clipped. 413 * title - Name of array 414 */ 415 static void 416 print_array(note_state_t *state, const sl_field_t *base_desc, 417 sl_fmt_num_t fmt_type, int nelts, int check_nelts, const char *title) 418 { 419 char index1[MAXNDXSIZE], index2[MAXNDXSIZE]; 420 int i; 421 sl_field_t fdesc1, fdesc2; 422 423 if (check_nelts && (check_nelts > base_desc->slf_nelts)) 424 nelts = base_desc->slf_nelts; 425 if (nelts == 0) 426 return; 427 428 indent_enter(state, title, base_desc); 429 430 fdesc1 = fdesc2 = *base_desc; 431 for (i = 0; i < nelts; ) { 432 if (i == (nelts - 1)) { 433 /* One final value is left */ 434 if (!data_present(state, &fdesc1)) 435 break; 436 (void) snprintf(index1, sizeof (index1), 437 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(i)); 438 print_num(state, index1, &fdesc1, fmt_type); 439 fdesc1.slf_offset += fdesc1.slf_eltlen; 440 i++; 441 continue; 442 } 443 444 /* There are at least 2 items left. Show 2 up. */ 445 fdesc2.slf_offset = fdesc1.slf_offset + fdesc1.slf_eltlen; 446 if (!(data_present(state, &fdesc1) && 447 data_present(state, &fdesc2))) 448 break; 449 (void) snprintf(index1, sizeof (index1), 450 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(i)); 451 (void) snprintf(index2, sizeof (index2), 452 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(i + 1)); 453 print_num_2up(state, index1, &fdesc1, fmt_type, 454 index2, &fdesc2, fmt_type); 455 fdesc1.slf_offset += 2 * fdesc1.slf_eltlen; 456 i += 2; 457 } 458 459 indent_exit(state); 460 } 461 462 463 /* 464 * Output information from auxv_t structure. 465 */ 466 static void 467 dump_auxv(note_state_t *state, const char *title) 468 { 469 const sl_auxv_layout_t *layout = state->ns_arch->auxv; 470 union { 471 Conv_cap_val_hw1_buf_t hw1; 472 Conv_cap_val_hw2_buf_t hw2; 473 Conv_cap_val_hw3_buf_t hw3; 474 Conv_cnote_auxv_af_buf_t auxv_af; 475 Conv_ehdr_flags_buf_t ehdr_flags; 476 Conv_secflags_buf_t secflags; 477 Conv_inv_buf_t inv; 478 } conv_buf; 479 sl_fmtbuf_t buf; 480 int ndx, ndx_start; 481 Word sizeof_auxv; 482 483 sizeof_auxv = layout->sizeof_struct.slf_eltlen; 484 485 indent_enter(state, title, &layout->sizeof_struct); 486 487 /* 488 * Immediate indent_exit() restores the indent level to 489 * that of the title. We include indentation as part of 490 * the index string, which is right justified, and don't 491 * want the usual indentation spacing. 492 */ 493 indent_exit(state); 494 495 ndx = 0; 496 while (state->ns_len > sizeof_auxv) { 497 char index[(MAXNDXSIZE * 2) + 1]; 498 sl_fmt_num_t num_fmt = SL_FMT_NUM_ZHEX; 499 const char *vstr = NULL; 500 Word w; 501 int type; 502 sl_field_t a_type_next; 503 504 type = extract_as_word(state, &layout->a_type); 505 ndx_start = ndx; 506 switch (type) { 507 case AT_NULL: 508 a_type_next = layout->a_type; 509 a_type_next.slf_offset += sizeof_auxv; 510 while ((state->ns_len - sizeof_auxv) >= sizeof_auxv) { 511 type = extract_as_word(state, &a_type_next); 512 if (type != AT_NULL) 513 break; 514 ndx++; 515 state->ns_data += sizeof_auxv; 516 state->ns_len -= sizeof_auxv; 517 } 518 num_fmt = SL_FMT_NUM_HEX; 519 break; 520 521 522 523 case AT_IGNORE: 524 case AT_SUN_IFLUSH: 525 num_fmt = SL_FMT_NUM_HEX; 526 break; 527 528 case AT_EXECFD: 529 case AT_PHENT: 530 case AT_PHNUM: 531 case AT_PAGESZ: 532 case AT_SUN_UID: 533 case AT_SUN_RUID: 534 case AT_SUN_GID: 535 case AT_SUN_RGID: 536 case AT_SUN_LPAGESZ: 537 case AT_SUN_FPSIZE: 538 case AT_SUN_FPTYPE: 539 num_fmt = SL_FMT_NUM_DEC; 540 break; 541 542 case AT_FLAGS: /* processor flags */ 543 w = extract_as_word(state, &layout->a_val); 544 vstr = conv_ehdr_flags(state->ns_mach, w, 545 0, &conv_buf.ehdr_flags); 546 break; 547 548 case AT_SUN_HWCAP: 549 w = extract_as_word(state, &layout->a_val); 550 vstr = conv_cap_val_hw1(w, state->ns_mach, 551 0, &conv_buf.hw1); 552 /* 553 * conv_cap_val_hw1() produces output like: 554 * 555 * 0xfff [ flg1 flg2 0xff] 556 * 557 * where the first hex value is the complete value, 558 * and the second is the leftover bits. We only 559 * want the part in brackets, and failing that, 560 * would rather fall back to formatting the full 561 * value ourselves. 562 */ 563 while ((*vstr != '\0') && (*vstr != '[')) 564 vstr++; 565 if (*vstr != '[') 566 vstr = NULL; 567 num_fmt = SL_FMT_NUM_HEX; 568 break; 569 case AT_SUN_HWCAP2: 570 w = extract_as_word(state, &layout->a_val); 571 vstr = conv_cap_val_hw2(w, state->ns_mach, 572 0, &conv_buf.hw2); 573 /* 574 * conv_cap_val_hw2() produces output like: 575 * 576 * 0xfff [ flg1 flg2 0xff] 577 * 578 * where the first hex value is the complete value, 579 * and the second is the leftover bits. We only 580 * want the part in brackets, and failing that, 581 * would rather fall back to formatting the full 582 * value ourselves. 583 */ 584 while ((*vstr != '\0') && (*vstr != '[')) 585 vstr++; 586 if (*vstr != '[') 587 vstr = NULL; 588 num_fmt = SL_FMT_NUM_HEX; 589 break; 590 case AT_SUN_HWCAP3: 591 w = extract_as_word(state, &layout->a_val); 592 vstr = conv_cap_val_hw3(w, state->ns_mach, 593 0, &conv_buf.hw3); 594 /* 595 * conv_cap_val_hw3() produces output like: 596 * 597 * 0xfff [ flg1 flg2 0xff] 598 * 599 * where the first hex value is the complete value, 600 * and the second is the leftover bits. We only 601 * want the part in brackets, and failing that, 602 * would rather fall back to formatting the full 603 * value ourselves. 604 */ 605 while ((*vstr != '\0') && (*vstr != '[')) 606 vstr++; 607 if (*vstr != '[') 608 vstr = NULL; 609 num_fmt = SL_FMT_NUM_HEX; 610 break; 611 612 case AT_SUN_AUXFLAGS: 613 w = extract_as_word(state, &layout->a_val); 614 vstr = conv_cnote_auxv_af(w, 0, &conv_buf.auxv_af); 615 num_fmt = SL_FMT_NUM_HEX; 616 break; 617 } 618 619 if (ndx == ndx_start) 620 (void) snprintf(index, sizeof (index), 621 MSG_ORIG(MSG_FMT_INDEX2), EC_WORD(ndx)); 622 else 623 (void) snprintf(index, sizeof (index), 624 MSG_ORIG(MSG_FMT_INDEXRNG), 625 EC_WORD(ndx_start), EC_WORD(ndx)); 626 627 if (vstr == NULL) 628 vstr = fmt_num(state, &layout->a_val, num_fmt, buf); 629 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_AUXVLINE), INDENT, index, 630 state->ns_vcol - state->ns_indent, 631 conv_cnote_auxv_type(type, CONV_FMT_DECIMAL, 632 &conv_buf.inv), vstr); 633 634 state->ns_data += sizeof_auxv; 635 state->ns_len -= sizeof_auxv; 636 ndx++; 637 } 638 } 639 640 641 /* 642 * Output information from fltset_t structure. 643 */ 644 static void 645 dump_fltset(note_state_t *state, const char *title) 646 { 647 #define NELTS 4 648 649 const sl_fltset_layout_t *layout = state->ns_arch->fltset; 650 Conv_cnote_fltset_buf_t buf; 651 sl_field_t fdesc; 652 uint32_t mask[NELTS]; 653 int i, nelts; 654 655 if (!data_present(state, &layout->sizeof_struct)) 656 return; 657 658 fdesc = layout->word; 659 nelts = fdesc.slf_nelts; 660 if (nelts > NELTS) /* Type has grown? Show what we understand */ 661 nelts = NELTS; 662 for (i = 0; i < nelts; i++) { 663 mask[i] = extract_as_word(state, &fdesc); 664 fdesc.slf_offset += fdesc.slf_eltlen; 665 } 666 667 print_str(state, title, conv_cnote_fltset(mask, nelts, 0, &buf)); 668 669 #undef NELTS 670 } 671 672 673 /* 674 * Output information from sigset_t structure. 675 */ 676 static void 677 dump_sigset(note_state_t *state, const char *title) 678 { 679 #define NELTS 4 680 681 const sl_sigset_layout_t *layout = state->ns_arch->sigset; 682 Conv_cnote_sigset_buf_t buf; 683 sl_field_t fdesc; 684 uint32_t mask[NELTS]; 685 int i, nelts; 686 687 if (!data_present(state, &layout->sizeof_struct)) 688 return; 689 690 fdesc = layout->sigbits; 691 nelts = fdesc.slf_nelts; 692 if (nelts > NELTS) /* Type has grown? Show what we understand */ 693 nelts = NELTS; 694 for (i = 0; i < nelts; i++) { 695 mask[i] = extract_as_word(state, &fdesc); 696 fdesc.slf_offset += fdesc.slf_eltlen; 697 } 698 699 print_str(state, title, conv_cnote_sigset(mask, nelts, 0, &buf)); 700 701 #undef NELTS 702 } 703 704 705 /* 706 * Output information from sigaction structure. 707 */ 708 static void 709 dump_sigaction(note_state_t *state, const char *title) 710 { 711 const sl_sigaction_layout_t *layout = state->ns_arch->sigaction; 712 Conv_cnote_sa_flags_buf_t conv_buf; 713 Word w; 714 715 indent_enter(state, title, &layout->sa_flags); 716 717 if (data_present(state, &layout->sa_flags)) { 718 w = extract_as_word(state, &layout->sa_flags); 719 print_str(state, MSG_ORIG(MSG_CNOTE_T_SA_FLAGS), 720 conv_cnote_sa_flags(w, 0, &conv_buf)); 721 } 722 723 PRINT_ZHEX_2UP(MSG_ORIG(MSG_CNOTE_T_SA_HANDLER), sa_hand, 724 MSG_ORIG(MSG_CNOTE_T_SA_SIGACTION), sa_sigact); 725 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_SA_MASK), sa_mask, dump_sigset); 726 727 indent_exit(state); 728 } 729 730 731 /* 732 * Output information from siginfo structure. 733 */ 734 static void 735 dump_siginfo(note_state_t *state, const char *title) 736 { 737 const sl_siginfo_layout_t *layout = state->ns_arch->siginfo; 738 Conv_inv_buf_t inv_buf; 739 Word w; 740 int v_si_code, v_si_signo; 741 742 if (!data_present(state, &layout->sizeof_struct)) 743 return; 744 745 indent_enter(state, title, &layout->f_si_signo); 746 747 v_si_signo = extract_as_sword(state, &layout->f_si_signo); 748 print_str(state, MSG_ORIG(MSG_CNOTE_T_SI_SIGNO), 749 conv_cnote_signal(v_si_signo, CONV_FMT_DECIMAL, &inv_buf)); 750 751 w = extract_as_word(state, &layout->f_si_errno); 752 print_str(state, MSG_ORIG(MSG_CNOTE_T_SI_ERRNO), 753 conv_cnote_errno(w, CONV_FMT_DECIMAL, &inv_buf)); 754 755 v_si_code = extract_as_sword(state, &layout->f_si_code); 756 print_str(state, MSG_ORIG(MSG_CNOTE_T_SI_CODE), 757 conv_cnote_si_code(state->ns_mach, v_si_signo, v_si_code, 758 CONV_FMT_DECIMAL, &inv_buf)); 759 760 if ((v_si_signo == 0) || (v_si_code == SI_NOINFO)) { 761 indent_exit(state); 762 return; 763 } 764 765 /* User generated signals have (si_code <= 0) */ 766 if (v_si_code <= 0) { 767 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_SI_PID), f_si_pid); 768 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_SI_UID), f_si_uid); 769 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_SI_CTID), f_si_ctid); 770 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_SI_ZONEID), f_si_zoneid); 771 switch (v_si_code) { 772 case SI_QUEUE: 773 case SI_TIMER: 774 case SI_ASYNCIO: 775 case SI_MESGQ: 776 indent_enter(state, MSG_ORIG(MSG_CNOTE_T_SI_VALUE), 777 &layout->f_si_value_int); 778 PRINT_ZHEX(MSG_ORIG(MSG_CNOTE_T_SIVAL_INT), 779 f_si_value_int); 780 PRINT_ZHEX(MSG_ORIG(MSG_CNOTE_T_SIVAL_PTR), 781 f_si_value_ptr); 782 indent_exit(state); 783 break; 784 } 785 indent_exit(state); 786 return; 787 } 788 789 /* 790 * Remaining cases are kernel generated signals. Output any 791 * signal or code specific information. 792 */ 793 if (v_si_code == SI_RCTL) 794 PRINT_HEX(MSG_ORIG(MSG_CNOTE_T_SI_ENTITY), f_si_entity); 795 switch (v_si_signo) { 796 case SIGILL: 797 case SIGFPE: 798 case SIGSEGV: 799 case SIGBUS: 800 PRINT_ZHEX(MSG_ORIG(MSG_CNOTE_T_SI_ADDR), f_si_addr); 801 break; 802 case SIGCHLD: 803 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_SI_PID), f_si_pid); 804 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_SI_STATUS), f_si_status); 805 break; 806 case SIGPOLL: 807 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_SI_BAND), f_si_band); 808 break; 809 } 810 811 indent_exit(state); 812 } 813 814 815 /* 816 * Output information from stack_t structure. 817 */ 818 static void 819 dump_stack(note_state_t *state, const char *title) 820 { 821 const sl_stack_layout_t *layout = state->ns_arch->stack; 822 Conv_cnote_ss_flags_buf_t conv_buf; 823 Word w; 824 825 indent_enter(state, title, &layout->ss_size); 826 827 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_SS_SP), &layout->ss_sp, 828 SL_FMT_NUM_ZHEX, MSG_ORIG(MSG_CNOTE_T_SS_SIZE), &layout->ss_size, 829 SL_FMT_NUM_HEX); 830 831 if (data_present(state, &layout->ss_flags)) { 832 w = extract_as_word(state, &layout->ss_flags); 833 print_str(state, MSG_ORIG(MSG_CNOTE_T_SS_FLAGS), 834 conv_cnote_ss_flags(w, 0, &conv_buf)); 835 } 836 837 indent_exit(state); 838 } 839 840 841 /* 842 * Output information from sysset_t structure. 843 */ 844 static void 845 dump_sysset(note_state_t *state, const char *title) 846 { 847 #define NELTS 16 848 849 const sl_sysset_layout_t *layout = state->ns_arch->sysset; 850 Conv_cnote_sysset_buf_t buf; 851 sl_field_t fdesc; 852 uint32_t mask[NELTS]; 853 int i, nelts; 854 855 if (!data_present(state, &layout->sizeof_struct)) 856 return; 857 858 fdesc = layout->word; 859 nelts = fdesc.slf_nelts; 860 if (nelts > NELTS) /* Type has grown? Show what we understand */ 861 nelts = NELTS; 862 for (i = 0; i < nelts; i++) { 863 mask[i] = extract_as_word(state, &fdesc); 864 fdesc.slf_offset += fdesc.slf_eltlen; 865 } 866 867 print_str(state, title, conv_cnote_sysset(mask, nelts, 0, &buf)); 868 869 #undef NELTS 870 } 871 872 873 /* 874 * Output information from timestruc_t structure. 875 */ 876 static void 877 dump_timestruc(note_state_t *state, const char *title) 878 { 879 const sl_timestruc_layout_t *layout = state->ns_arch->timestruc; 880 881 indent_enter(state, title, &layout->tv_sec); 882 883 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_TV_SEC), tv_sec, 884 MSG_ORIG(MSG_CNOTE_T_TV_NSEC), tv_nsec); 885 886 indent_exit(state); 887 } 888 889 /* 890 * Output information from prsecflags_t structure. 891 */ 892 static void 893 dump_secflags(note_state_t *state, const char *title) 894 { 895 const sl_prsecflags_layout_t *layout = state->ns_arch->prsecflags; 896 Conv_secflags_buf_t inv; 897 Lword lw; 898 Word w; 899 900 indent_enter(state, title, &layout->pr_version); 901 902 w = extract_as_word(state, &layout->pr_version); 903 904 if (w != PRSECFLAGS_VERSION_1) { 905 PRINT_DEC(MSG_INTL(MSG_NOTE_BAD_SECFLAGS_VER), pr_version); 906 dump_hex_bytes(state->ns_data, state->ns_len, state->ns_indent, 907 4, 3); 908 } else { 909 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_VERSION), pr_version); 910 lw = extract_as_lword(state, &layout->pr_effective); 911 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_EFFECTIVE), 912 conv_prsecflags(lw, 0, &inv)); 913 914 lw = extract_as_lword(state, &layout->pr_inherit); 915 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_INHERIT), 916 conv_prsecflags(lw, 0, &inv)); 917 918 lw = extract_as_lword(state, &layout->pr_lower); 919 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_LOWER), 920 conv_prsecflags(lw, 0, &inv)); 921 922 lw = extract_as_lword(state, &layout->pr_upper); 923 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_UPPER), 924 conv_prsecflags(lw, 0, &inv)); 925 } 926 927 indent_exit(state); 928 } 929 930 /* 931 * Output information from utsname structure. 932 */ 933 static void 934 dump_utsname(note_state_t *state, const char *title) 935 { 936 const sl_utsname_layout_t *layout = state->ns_arch->utsname; 937 938 indent_enter(state, title, &layout->sysname); 939 940 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_UTS_SYSNAME), sysname); 941 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_UTS_NODENAME), nodename); 942 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_UTS_RELEASE), release); 943 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_UTS_VERSION), version); 944 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_UTS_MACHINE), machine); 945 946 indent_exit(state); 947 } 948 949 950 /* 951 * Dump register contents 952 */ 953 static void 954 dump_prgregset(note_state_t *state, const char *title) 955 { 956 sl_field_t fdesc1, fdesc2; 957 sl_fmtbuf_t buf1, buf2; 958 Conv_inv_buf_t inv_buf1, inv_buf2; 959 Word w; 960 961 fdesc1 = fdesc2 = state->ns_arch->prgregset->elt0; 962 indent_enter(state, title, &fdesc1); 963 964 for (w = 0; w < fdesc1.slf_nelts; ) { 965 if (w == (fdesc1.slf_nelts - 1)) { 966 /* One last register is left */ 967 if (!data_present(state, &fdesc1)) 968 break; 969 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE), 970 INDENT, state->ns_vcol - state->ns_indent, 971 conv_cnote_pr_regname(state->ns_mach, w, 972 CONV_FMT_DECIMAL, &inv_buf1), 973 fmt_num(state, &fdesc1, SL_FMT_NUM_ZHEX, buf1)); 974 fdesc1.slf_offset += fdesc1.slf_eltlen; 975 w++; 976 continue; 977 } 978 979 /* There are at least 2 more registers left. Show 2 up */ 980 fdesc2.slf_offset = fdesc1.slf_offset + fdesc1.slf_eltlen; 981 if (!(data_present(state, &fdesc1) && 982 data_present(state, &fdesc2))) 983 break; 984 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE_2UP), INDENT, 985 state->ns_vcol - state->ns_indent, 986 conv_cnote_pr_regname(state->ns_mach, w, 987 CONV_FMT_DECIMAL, &inv_buf1), 988 state->ns_t2col - state->ns_vcol, 989 fmt_num(state, &fdesc1, SL_FMT_NUM_ZHEX, buf1), 990 state->ns_v2col - state->ns_t2col, 991 conv_cnote_pr_regname(state->ns_mach, w + 1, 992 CONV_FMT_DECIMAL, &inv_buf2), 993 fmt_num(state, &fdesc2, SL_FMT_NUM_ZHEX, buf2)); 994 fdesc1.slf_offset += 2 * fdesc1.slf_eltlen; 995 w += 2; 996 } 997 998 indent_exit(state); 999 } 1000 1001 /* 1002 * Output information from lwpstatus_t structure. 1003 */ 1004 static void 1005 dump_lwpstatus(note_state_t *state, const char *title) 1006 { 1007 const sl_lwpstatus_layout_t *layout = state->ns_arch->lwpstatus; 1008 Word w, w2; 1009 int32_t i; 1010 union { 1011 Conv_inv_buf_t inv; 1012 Conv_cnote_pr_flags_buf_t flags; 1013 } conv_buf; 1014 1015 indent_enter(state, title, &layout->pr_flags); 1016 1017 if (data_present(state, &layout->pr_flags)) { 1018 w = extract_as_word(state, &layout->pr_flags); 1019 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_FLAGS), 1020 conv_cnote_pr_flags(w, 0, &conv_buf.flags)); 1021 } 1022 1023 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_LWPID), pr_lwpid); 1024 1025 if (data_present(state, &layout->pr_why)) { 1026 w = extract_as_word(state, &layout->pr_why); 1027 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_WHY), 1028 conv_cnote_pr_why(w, 0, &conv_buf.inv)); 1029 1030 if (data_present(state, &layout->pr_what)) { 1031 w2 = extract_as_word(state, &layout->pr_what); 1032 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_WHAT), 1033 conv_cnote_pr_what(w, w2, 0, &conv_buf.inv)); 1034 } 1035 } 1036 1037 if (data_present(state, &layout->pr_cursig)) { 1038 w = extract_as_word(state, &layout->pr_cursig); 1039 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_CURSIG), 1040 conv_cnote_signal(w, CONV_FMT_DECIMAL, &conv_buf.inv)); 1041 } 1042 1043 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_INFO), pr_info, dump_siginfo); 1044 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_LWPPEND), pr_lwppend, 1045 dump_sigset); 1046 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_LWPHOLD), pr_lwphold, 1047 dump_sigset); 1048 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_ACTION), pr_action, 1049 dump_sigaction); 1050 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_ALTSTACK), pr_altstack, 1051 dump_stack); 1052 1053 PRINT_ZHEX(MSG_ORIG(MSG_CNOTE_T_PR_OLDCONTEXT), pr_oldcontext); 1054 1055 if (data_present(state, &layout->pr_syscall)) { 1056 w = extract_as_word(state, &layout->pr_syscall); 1057 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_SYSCALL), 1058 conv_cnote_syscall(w, CONV_FMT_DECIMAL, &conv_buf.inv)); 1059 } 1060 1061 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_NSYSARG), pr_nsysarg); 1062 1063 if (data_present(state, &layout->pr_errno)) { 1064 w = extract_as_word(state, &layout->pr_errno); 1065 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_ERRNO), 1066 conv_cnote_errno(w, CONV_FMT_DECIMAL, &conv_buf.inv)); 1067 } 1068 1069 if (data_present(state, &layout->pr_nsysarg)) { 1070 w2 = extract_as_word(state, &layout->pr_nsysarg); 1071 print_array(state, &layout->pr_sysarg, SL_FMT_NUM_ZHEX, w2, 1, 1072 MSG_ORIG(MSG_CNOTE_T_PR_SYSARG)); 1073 } 1074 1075 PRINT_HEX_2UP(MSG_ORIG(MSG_CNOTE_T_PR_RVAL1), pr_rval1, 1076 MSG_ORIG(MSG_CNOTE_T_PR_RVAL2), pr_rval2); 1077 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_CLNAME), pr_clname); 1078 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_TSTAMP), pr_tstamp, 1079 dump_timestruc); 1080 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_UTIME), pr_utime, dump_timestruc); 1081 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_STIME), pr_stime, dump_timestruc); 1082 1083 if (data_present(state, &layout->pr_errpriv)) { 1084 i = extract_as_sword(state, &layout->pr_errpriv); 1085 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_ERRPRIV), 1086 conv_cnote_priv(i, CONV_FMT_DECIMAL, &conv_buf.inv)); 1087 } 1088 1089 PRINT_ZHEX_2UP(MSG_ORIG(MSG_CNOTE_T_PR_USTACK), pr_ustack, 1090 MSG_ORIG(MSG_CNOTE_T_PR_INSTR), pr_instr); 1091 1092 /* 1093 * In order to line up all the values in a single column, 1094 * we would have to set vcol to a very high value, which results 1095 * in ugly looking output that runs off column 80. So, we use 1096 * two levels of vcol, one for the contents so far, and a 1097 * higher one for the pr_reg sub-struct. 1098 */ 1099 state->ns_vcol += 3; 1100 state->ns_t2col += 3; 1101 state->ns_v2col += 2; 1102 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_REG), pr_reg, dump_prgregset); 1103 state->ns_vcol -= 3; 1104 state->ns_t2col -= 3; 1105 state->ns_v2col -= 2; 1106 1107 /* 1108 * The floating point register state is complex, and highly 1109 * platform dependent. For now, we simply display it as 1110 * a hex dump. This can be replaced if better information 1111 * is required. 1112 */ 1113 if (data_present(state, &layout->pr_fpreg)) { 1114 indent_enter(state, MSG_ORIG(MSG_CNOTE_T_PR_FPREG), 1115 &layout->pr_fpreg); 1116 dump_hex_bytes(layout->pr_fpreg.slf_offset + state->ns_data, 1117 layout->pr_fpreg.slf_eltlen, state->ns_indent, 4, 3); 1118 indent_exit(state); 1119 } 1120 1121 indent_exit(state); 1122 } 1123 1124 1125 /* 1126 * Output information from pstatus_t structure. 1127 */ 1128 static void 1129 dump_pstatus(note_state_t *state, const char *title) 1130 { 1131 const sl_pstatus_layout_t *layout = state->ns_arch->pstatus; 1132 Word w; 1133 union { 1134 Conv_inv_buf_t inv; 1135 Conv_cnote_pr_flags_buf_t flags; 1136 } conv_buf; 1137 1138 indent_enter(state, title, &layout->pr_flags); 1139 1140 if (data_present(state, &layout->pr_flags)) { 1141 w = extract_as_word(state, &layout->pr_flags); 1142 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_FLAGS), 1143 conv_cnote_pr_flags(w, 0, &conv_buf.flags)); 1144 } 1145 1146 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_NLWP), pr_nlwp); 1147 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_PID), pr_pid, 1148 MSG_ORIG(MSG_CNOTE_T_PR_PPID), pr_ppid); 1149 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_PGID), pr_pgid, 1150 MSG_ORIG(MSG_CNOTE_T_PR_SID), pr_sid); 1151 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_ASLWPID), pr_aslwpid, 1152 MSG_ORIG(MSG_CNOTE_T_PR_AGENTID), pr_agentid); 1153 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_SIGPEND), pr_sigpend, 1154 dump_sigset); 1155 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_BRKBASE), 1156 &layout->pr_brkbase, SL_FMT_NUM_ZHEX, 1157 MSG_ORIG(MSG_CNOTE_T_PR_BRKSIZE), 1158 &layout->pr_brksize, SL_FMT_NUM_HEX); 1159 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_STKBASE), 1160 &layout->pr_stkbase, SL_FMT_NUM_ZHEX, 1161 MSG_ORIG(MSG_CNOTE_T_PR_STKSIZE), 1162 &layout->pr_stksize, SL_FMT_NUM_HEX); 1163 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_UTIME), pr_utime, dump_timestruc); 1164 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_STIME), pr_stime, dump_timestruc); 1165 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_CUTIME), pr_cutime, 1166 dump_timestruc); 1167 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_CSTIME), pr_cstime, 1168 dump_timestruc); 1169 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_SIGTRACE), pr_sigtrace, 1170 dump_sigset); 1171 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_FLTTRACE), pr_flttrace, 1172 dump_fltset); 1173 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_SYSENTRY), pr_sysentry, 1174 dump_sysset); 1175 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_SYSEXIT), pr_sysexit, 1176 dump_sysset); 1177 1178 if (data_present(state, &layout->pr_dmodel)) { 1179 w = extract_as_word(state, &layout->pr_dmodel); 1180 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_DMODEL), 1181 conv_cnote_pr_dmodel(w, 0, &conv_buf.inv)); 1182 } 1183 1184 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_TASKID), pr_taskid, 1185 MSG_ORIG(MSG_CNOTE_T_PR_PROJID), pr_projid); 1186 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_NZOMB), pr_nzomb, 1187 MSG_ORIG(MSG_CNOTE_T_PR_ZONEID), pr_zoneid); 1188 1189 /* 1190 * In order to line up all the values in a single column, 1191 * we would have to set vcol to a very high value, which results 1192 * in ugly looking output that runs off column 80. So, we use 1193 * two levels of vcol, one for the contents so far, and a 1194 * higher one for the pr_lwp sub-struct. 1195 */ 1196 state->ns_vcol += 5; 1197 state->ns_t2col += 5; 1198 state->ns_v2col += 5; 1199 1200 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_LWP), pr_lwp, dump_lwpstatus); 1201 state->ns_vcol -= 5; 1202 state->ns_t2col -= 5; 1203 state->ns_v2col -= 5; 1204 1205 indent_exit(state); 1206 } 1207 1208 1209 /* 1210 * Output information from prstatus_t (<sys/old_procfs.h>) structure. 1211 */ 1212 static void 1213 dump_prstatus(note_state_t *state, const char *title) 1214 { 1215 const sl_prstatus_layout_t *layout = state->ns_arch->prstatus; 1216 Word w, w2; 1217 int i; 1218 union { 1219 Conv_inv_buf_t inv; 1220 Conv_cnote_old_pr_flags_buf_t flags; 1221 } conv_buf; 1222 1223 indent_enter(state, title, &layout->pr_flags); 1224 1225 if (data_present(state, &layout->pr_flags)) { 1226 w = extract_as_word(state, &layout->pr_flags); 1227 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_FLAGS), 1228 conv_cnote_old_pr_flags(w, 0, &conv_buf.flags)); 1229 } 1230 1231 if (data_present(state, &layout->pr_why)) { 1232 w = extract_as_word(state, &layout->pr_why); 1233 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_WHY), 1234 conv_cnote_pr_why(w, 0, &conv_buf.inv)); 1235 1236 1237 if (data_present(state, &layout->pr_what)) { 1238 w2 = extract_as_word(state, &layout->pr_what); 1239 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_WHAT), 1240 conv_cnote_pr_what(w, w2, 0, &conv_buf.inv)); 1241 } 1242 } 1243 1244 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_INFO), pr_info, dump_siginfo); 1245 1246 if (data_present(state, &layout->pr_cursig)) { 1247 w = extract_as_word(state, &layout->pr_cursig); 1248 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_CURSIG), 1249 conv_cnote_signal(w, CONV_FMT_DECIMAL, &conv_buf.inv)); 1250 } 1251 1252 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_NLWP), pr_nlwp); 1253 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_SIGPEND), pr_sigpend, 1254 dump_sigset); 1255 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_SIGHOLD), pr_sighold, 1256 dump_sigset); 1257 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_ALTSTACK), pr_altstack, 1258 dump_stack); 1259 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_ACTION), pr_action, 1260 dump_sigaction); 1261 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_PID), pr_pid, 1262 MSG_ORIG(MSG_CNOTE_T_PR_PPID), pr_ppid); 1263 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_PGRP), pr_pgrp, 1264 MSG_ORIG(MSG_CNOTE_T_PR_SID), pr_sid); 1265 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_UTIME), pr_utime, dump_timestruc); 1266 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_STIME), pr_stime, dump_timestruc); 1267 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_CUTIME), pr_cutime, 1268 dump_timestruc); 1269 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_CSTIME), pr_cstime, 1270 dump_timestruc); 1271 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_CLNAME), pr_clname); 1272 1273 if (data_present(state, &layout->pr_syscall)) { 1274 w = extract_as_word(state, &layout->pr_syscall); 1275 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_SYSCALL), 1276 conv_cnote_syscall(w, CONV_FMT_DECIMAL, &conv_buf.inv)); 1277 } 1278 1279 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_NSYSARG), pr_nsysarg); 1280 1281 if (data_present(state, &layout->pr_nsysarg)) { 1282 w2 = extract_as_word(state, &layout->pr_nsysarg); 1283 print_array(state, &layout->pr_sysarg, SL_FMT_NUM_ZHEX, w2, 1, 1284 MSG_ORIG(MSG_CNOTE_T_PR_SYSARG)); 1285 } 1286 1287 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_WHO), pr_who); 1288 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_LWPPEND), pr_sigpend, 1289 dump_sigset); 1290 PRINT_ZHEX(MSG_ORIG(MSG_CNOTE_T_PR_OLDCONTEXT), pr_oldcontext); 1291 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_BRKBASE), 1292 &layout->pr_brkbase, SL_FMT_NUM_ZHEX, 1293 MSG_ORIG(MSG_CNOTE_T_PR_BRKSIZE), 1294 &layout->pr_brksize, SL_FMT_NUM_HEX); 1295 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_STKBASE), 1296 &layout->pr_stkbase, SL_FMT_NUM_ZHEX, 1297 MSG_ORIG(MSG_CNOTE_T_PR_STKSIZE), 1298 &layout->pr_stksize, SL_FMT_NUM_HEX); 1299 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_PROCESSOR), pr_processor); 1300 1301 if (data_present(state, &layout->pr_bind)) { 1302 i = extract_as_sword(state, &layout->pr_bind); 1303 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_BIND), 1304 conv_cnote_psetid(i, CONV_FMT_DECIMAL, &conv_buf.inv)); 1305 } 1306 1307 PRINT_ZHEX(MSG_ORIG(MSG_CNOTE_T_PR_INSTR), pr_instr); 1308 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_REG), pr_reg, dump_prgregset); 1309 1310 indent_exit(state); 1311 } 1312 1313 1314 static void 1315 dump_lwpname(note_state_t *state, const char *title) 1316 { 1317 const sl_prlwpname_layout_t *layout = state->ns_arch->prlwpname; 1318 1319 indent_enter(state, title, &layout->pr_lwpid); 1320 1321 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_LWPID), pr_lwpid); 1322 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_LWPNAME), pr_lwpname); 1323 1324 indent_exit(state); 1325 } 1326 1327 1328 /* 1329 * Print percent from 16-bit binary fraction [0 .. 1] 1330 * Round up .01 to .1 to indicate some small percentage (the 0x7000 below). 1331 * 1332 * Note: This routine was copied from ps(1) and then modified. 1333 */ 1334 static const char * 1335 prtpct_value(note_state_t *state, const sl_field_t *fdesc, 1336 sl_fmtbuf_t buf) 1337 { 1338 uint_t value; /* need 32 bits to compute with */ 1339 1340 value = extract_as_word(state, fdesc); 1341 value = ((value * 1000) + 0x7000) >> 15; /* [0 .. 1000] */ 1342 if (value >= 1000) 1343 value = 999; 1344 1345 (void) snprintf(buf, sizeof (sl_fmtbuf_t), 1346 MSG_ORIG(MSG_CNOTE_FMT_PRTPCT), value / 10, value % 10); 1347 1348 return (buf); 1349 } 1350 1351 1352 1353 /* 1354 * Version of prtpct() used for a 2-up display of two adjacent percentages. 1355 */ 1356 static void 1357 prtpct_2up(note_state_t *state, const sl_field_t *fdesc1, 1358 const char *title1, const sl_field_t *fdesc2, const char *title2) 1359 { 1360 sl_fmtbuf_t buf1, buf2; 1361 1362 if (!(data_present(state, fdesc1) && 1363 data_present(state, fdesc2))) 1364 return; 1365 1366 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE_2UP), INDENT, 1367 state->ns_vcol - state->ns_indent, title1, 1368 state->ns_t2col - state->ns_vcol, 1369 prtpct_value(state, fdesc1, buf1), 1370 state->ns_v2col - state->ns_t2col, title2, 1371 prtpct_value(state, fdesc2, buf2)); 1372 } 1373 1374 1375 /* 1376 * The psinfo_t and prpsinfo_t structs have pr_state and pr_sname 1377 * fields that we wish to print in a 2up format. The pr_state is 1378 * an integer, while pr_sname is a single character. 1379 */ 1380 static void 1381 print_state_sname_2up(note_state_t *state, 1382 const sl_field_t *state_fdesc, 1383 const sl_field_t *sname_fdesc) 1384 { 1385 sl_fmtbuf_t buf1, buf2; 1386 int sname; 1387 1388 /* 1389 * If the field slf_offset and extent fall past the end of the 1390 * available data, then return without doing anything. That note 1391 * is from an older core file that doesn't have all the fields 1392 * that we know about. 1393 */ 1394 if (!(data_present(state, state_fdesc) && 1395 data_present(state, sname_fdesc))) 1396 return; 1397 1398 sname = extract_as_sword(state, sname_fdesc); 1399 buf2[0] = sname; 1400 buf2[1] = '\0'; 1401 1402 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE_2UP), INDENT, 1403 state->ns_vcol - state->ns_indent, MSG_ORIG(MSG_CNOTE_T_PR_STATE), 1404 state->ns_t2col - state->ns_vcol, 1405 fmt_num(state, state_fdesc, SL_FMT_NUM_DEC, buf1), 1406 state->ns_v2col - state->ns_t2col, MSG_ORIG(MSG_CNOTE_T_PR_SNAME), 1407 buf2); 1408 } 1409 1410 /* 1411 * Output information from lwpsinfo_t structure. 1412 */ 1413 static void 1414 dump_lwpsinfo(note_state_t *state, const char *title) 1415 { 1416 const sl_lwpsinfo_layout_t *layout = state->ns_arch->lwpsinfo; 1417 Word w; 1418 int32_t i; 1419 union { 1420 Conv_cnote_proc_flag_buf_t proc_flag; 1421 Conv_inv_buf_t inv; 1422 } conv_buf; 1423 1424 indent_enter(state, title, &layout->pr_flag); 1425 1426 if (data_present(state, &layout->pr_flag)) { 1427 w = extract_as_word(state, &layout->pr_flag); 1428 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_FLAG), 1429 conv_cnote_proc_flag(w, 0, &conv_buf.proc_flag)); 1430 } 1431 1432 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_LWPID), &layout->pr_lwpid, 1433 SL_FMT_NUM_DEC, MSG_ORIG(MSG_CNOTE_T_PR_ADDR), &layout->pr_addr, 1434 SL_FMT_NUM_ZHEX); 1435 PRINT_HEX(MSG_ORIG(MSG_CNOTE_T_PR_WCHAN), pr_wchan); 1436 1437 if (data_present(state, &layout->pr_stype)) { 1438 w = extract_as_word(state, &layout->pr_stype); 1439 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_STYPE), 1440 conv_cnote_pr_stype(w, CONV_FMT_DECIMAL, &conv_buf.inv)); 1441 } 1442 1443 print_state_sname_2up(state, &layout->pr_state, &layout->pr_sname); 1444 1445 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_NICE), pr_nice); 1446 1447 if (data_present(state, &layout->pr_syscall)) { 1448 w = extract_as_word(state, &layout->pr_syscall); 1449 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_SYSCALL), 1450 conv_cnote_syscall(w, CONV_FMT_DECIMAL, &conv_buf.inv)); 1451 } 1452 1453 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_OLDPRI), pr_oldpri, 1454 MSG_ORIG(MSG_CNOTE_T_PR_CPU), pr_cpu); 1455 1456 if (data_present(state, &layout->pr_pri) && 1457 data_present(state, &layout->pr_pctcpu)) { 1458 sl_fmtbuf_t buf1, buf2; 1459 1460 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE_2UP), INDENT, 1461 state->ns_vcol - state->ns_indent, 1462 MSG_ORIG(MSG_CNOTE_T_PR_PRI), 1463 state->ns_t2col - state->ns_vcol, 1464 fmt_num(state, &layout->pr_pri, SL_FMT_NUM_DEC, buf1), 1465 state->ns_v2col - state->ns_t2col, 1466 MSG_ORIG(MSG_CNOTE_T_PR_PCTCPU), 1467 prtpct_value(state, &layout->pr_pctcpu, buf2)); 1468 } 1469 1470 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_START), pr_start, dump_timestruc); 1471 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_TIME), pr_time, dump_timestruc); 1472 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_CLNAME), pr_clname); 1473 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_NAME), pr_name); 1474 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_ONPRO), pr_onpro, 1475 MSG_ORIG(MSG_CNOTE_T_PR_BINDPRO), pr_bindpro); 1476 1477 if (data_present(state, &layout->pr_bindpset)) { 1478 i = extract_as_sword(state, &layout->pr_bindpset); 1479 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_BINDPSET), 1480 conv_cnote_psetid(i, CONV_FMT_DECIMAL, &conv_buf.inv)); 1481 } 1482 1483 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_LGRP), pr_lgrp); 1484 1485 indent_exit(state); 1486 } 1487 1488 1489 /* 1490 * Output information from psinfo_t structure. 1491 */ 1492 static void 1493 dump_psinfo(note_state_t *state, const char *title) 1494 { 1495 const sl_psinfo_layout_t *layout = state->ns_arch->psinfo; 1496 Word w; 1497 union { 1498 Conv_cnote_proc_flag_buf_t proc_flag; 1499 Conv_inv_buf_t inv; 1500 } conv_buf; 1501 1502 indent_enter(state, title, &layout->pr_flag); 1503 1504 if (data_present(state, &layout->pr_flag)) { 1505 w = extract_as_word(state, &layout->pr_flag); 1506 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_FLAG), 1507 conv_cnote_proc_flag(w, 0, &conv_buf.proc_flag)); 1508 } 1509 1510 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_NLWP), pr_nlwp); 1511 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_PID), pr_pid, 1512 MSG_ORIG(MSG_CNOTE_T_PR_PPID), pr_ppid); 1513 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_PGID), pr_pgid, 1514 MSG_ORIG(MSG_CNOTE_T_PR_SID), pr_sid); 1515 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_UID), pr_uid, 1516 MSG_ORIG(MSG_CNOTE_T_PR_EUID), pr_euid); 1517 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_GID), pr_gid, 1518 MSG_ORIG(MSG_CNOTE_T_PR_EGID), pr_egid); 1519 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_ADDR), &layout->pr_addr, 1520 SL_FMT_NUM_ZHEX, MSG_ORIG(MSG_CNOTE_T_PR_SIZE), &layout->pr_size, 1521 SL_FMT_NUM_HEX); 1522 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_RSSIZE), 1523 &layout->pr_rssize, SL_FMT_NUM_HEX, MSG_ORIG(MSG_CNOTE_T_PR_TTYDEV), 1524 &layout->pr_ttydev, SL_FMT_NUM_DEC); 1525 prtpct_2up(state, &layout->pr_pctcpu, MSG_ORIG(MSG_CNOTE_T_PR_PCTCPU), 1526 &layout->pr_pctmem, MSG_ORIG(MSG_CNOTE_T_PR_PCTMEM)); 1527 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_START), pr_start, dump_timestruc); 1528 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_TIME), pr_time, dump_timestruc); 1529 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_CTIME), pr_ctime, dump_timestruc); 1530 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_FNAME), pr_fname); 1531 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_PSARGS), pr_psargs); 1532 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_WSTAT), &layout->pr_wstat, 1533 SL_FMT_NUM_HEX, MSG_ORIG(MSG_CNOTE_T_PR_ARGC), &layout->pr_argc, 1534 SL_FMT_NUM_DEC); 1535 PRINT_ZHEX_2UP(MSG_ORIG(MSG_CNOTE_T_PR_ARGV), pr_argv, 1536 MSG_ORIG(MSG_CNOTE_T_PR_ENVP), pr_envp); 1537 1538 if (data_present(state, &layout->pr_dmodel)) { 1539 w = extract_as_word(state, &layout->pr_dmodel); 1540 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_DMODEL), 1541 conv_cnote_pr_dmodel(w, 0, &conv_buf.inv)); 1542 } 1543 1544 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_TASKID), pr_taskid, 1545 MSG_ORIG(MSG_CNOTE_T_PR_PROJID), pr_projid); 1546 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_NZOMB), pr_nzomb, 1547 MSG_ORIG(MSG_CNOTE_T_PR_POOLID), pr_poolid); 1548 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_ZONEID), pr_zoneid, 1549 MSG_ORIG(MSG_CNOTE_T_PR_CONTRACT), pr_contract); 1550 1551 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_LWP), pr_lwp, dump_lwpsinfo); 1552 1553 indent_exit(state); 1554 } 1555 1556 /* 1557 * Output information from prpsinfo_t structure. 1558 */ 1559 static void 1560 dump_prpsinfo(note_state_t *state, const char *title) 1561 { 1562 const sl_prpsinfo_layout_t *layout = state->ns_arch->prpsinfo; 1563 Word w; 1564 union { 1565 Conv_cnote_proc_flag_buf_t proc_flag; 1566 Conv_inv_buf_t inv; 1567 } conv_buf; 1568 1569 indent_enter(state, title, &layout->pr_state); 1570 1571 print_state_sname_2up(state, &layout->pr_state, &layout->pr_sname); 1572 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_ZOMB), pr_zomb, 1573 MSG_ORIG(MSG_CNOTE_T_PR_NICE), pr_nice); 1574 1575 if (data_present(state, &layout->pr_flag)) { 1576 w = extract_as_word(state, &layout->pr_flag); 1577 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_FLAG), 1578 conv_cnote_proc_flag(w, 0, &conv_buf.proc_flag)); 1579 } 1580 1581 1582 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_UID), pr_uid, 1583 MSG_ORIG(MSG_CNOTE_T_PR_GID), pr_gid); 1584 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_PID), pr_pid, 1585 MSG_ORIG(MSG_CNOTE_T_PR_PPID), pr_ppid); 1586 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_PGRP), pr_pgrp, 1587 MSG_ORIG(MSG_CNOTE_T_PR_SID), pr_sid); 1588 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_ADDR), &layout->pr_addr, 1589 SL_FMT_NUM_ZHEX, MSG_ORIG(MSG_CNOTE_T_PR_SIZE), &layout->pr_size, 1590 SL_FMT_NUM_HEX); 1591 PRINT_HEX_2UP(MSG_ORIG(MSG_CNOTE_T_PR_RSSIZE), pr_rssize, 1592 MSG_ORIG(MSG_CNOTE_T_PR_WCHAN), pr_wchan); 1593 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_START), pr_start, dump_timestruc); 1594 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_TIME), pr_time, dump_timestruc); 1595 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_PRI), pr_pri, 1596 MSG_ORIG(MSG_CNOTE_T_PR_OLDPRI), pr_oldpri); 1597 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_CPU), pr_cpu); 1598 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_OTTYDEV), pr_ottydev, 1599 MSG_ORIG(MSG_CNOTE_T_PR_LTTYDEV), pr_lttydev); 1600 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_CLNAME), pr_clname); 1601 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_FNAME), pr_fname); 1602 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_PSARGS), pr_psargs); 1603 1604 if (data_present(state, &layout->pr_syscall)) { 1605 w = extract_as_word(state, &layout->pr_syscall); 1606 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_SYSCALL), 1607 conv_cnote_syscall(w, CONV_FMT_DECIMAL, &conv_buf.inv)); 1608 } 1609 1610 PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_CTIME), pr_ctime, dump_timestruc); 1611 PRINT_HEX_2UP(MSG_ORIG(MSG_CNOTE_T_PR_BYSIZE), pr_bysize, 1612 MSG_ORIG(MSG_CNOTE_T_PR_BYRSSIZE), pr_byrssize); 1613 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_ARGC), &layout->pr_argc, 1614 SL_FMT_NUM_DEC, MSG_ORIG(MSG_CNOTE_T_PR_ARGV), &layout->pr_argv, 1615 SL_FMT_NUM_ZHEX); 1616 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PR_ENVP), &layout->pr_envp, 1617 SL_FMT_NUM_ZHEX, MSG_ORIG(MSG_CNOTE_T_PR_WSTAT), &layout->pr_wstat, 1618 SL_FMT_NUM_HEX); 1619 prtpct_2up(state, &layout->pr_pctcpu, MSG_ORIG(MSG_CNOTE_T_PR_PCTCPU), 1620 &layout->pr_pctmem, MSG_ORIG(MSG_CNOTE_T_PR_PCTMEM)); 1621 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_EUID), pr_euid, 1622 MSG_ORIG(MSG_CNOTE_T_PR_EGID), pr_egid); 1623 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_ASLWPID), pr_aslwpid); 1624 1625 if (data_present(state, &layout->pr_dmodel)) { 1626 w = extract_as_word(state, &layout->pr_dmodel); 1627 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_DMODEL), 1628 conv_cnote_pr_dmodel(w, 0, &conv_buf.inv)); 1629 } 1630 1631 indent_exit(state); 1632 } 1633 1634 1635 /* 1636 * Output information from prcred_t structure. 1637 */ 1638 static void 1639 dump_prcred(note_state_t *state, const char *title) 1640 { 1641 const sl_prcred_layout_t *layout = state->ns_arch->prcred; 1642 Word ngroups; 1643 1644 indent_enter(state, title, &layout->pr_euid); 1645 1646 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_EUID), pr_euid, 1647 MSG_ORIG(MSG_CNOTE_T_PR_RUID), pr_ruid); 1648 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_SUID), pr_suid, 1649 MSG_ORIG(MSG_CNOTE_T_PR_EGID), pr_egid); 1650 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_RGID), pr_rgid, 1651 MSG_ORIG(MSG_CNOTE_T_PR_SGID), pr_sgid); 1652 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_NGROUPS), pr_ngroups); 1653 1654 if (data_present(state, &layout->pr_ngroups)) { 1655 ngroups = extract_as_word(state, &layout->pr_ngroups); 1656 print_array(state, &layout->pr_groups, SL_FMT_NUM_DEC, ngroups, 1657 0, MSG_ORIG(MSG_CNOTE_T_PR_GROUPS)); 1658 } 1659 1660 indent_exit(state); 1661 } 1662 1663 1664 /* 1665 * Output information from prpriv_t structure. 1666 */ 1667 static void 1668 dump_prpriv(note_state_t *state, const char *title) 1669 { 1670 const sl_prpriv_layout_t *layout = state->ns_arch->prpriv; 1671 Word nsets; 1672 1673 indent_enter(state, title, &layout->pr_nsets); 1674 1675 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_NSETS), pr_nsets); 1676 PRINT_HEX(MSG_ORIG(MSG_CNOTE_T_PR_SETSIZE), pr_setsize); 1677 PRINT_HEX(MSG_ORIG(MSG_CNOTE_T_PR_INFOSIZE), pr_infosize); 1678 1679 if (data_present(state, &layout->pr_nsets)) { 1680 nsets = extract_as_word(state, &layout->pr_nsets); 1681 print_array(state, &layout->pr_sets, SL_FMT_NUM_ZHEX, nsets, 1682 0, MSG_ORIG(MSG_CNOTE_T_PR_SETS)); 1683 } 1684 1685 indent_exit(state); 1686 } 1687 1688 static void 1689 dump_prfdinfo(note_state_t *state, const char *title) 1690 { 1691 const sl_prfdinfo_layout_t *layout = state->ns_arch->prfdinfo; 1692 char buf[1024]; 1693 uint32_t fileflags, mode; 1694 1695 indent_enter(state, title, &layout->pr_fd); 1696 1697 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_FD), pr_fd); 1698 mode = extract_as_word(state, &layout->pr_mode); 1699 1700 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_MODE), 1701 conv_cnote_filemode(mode, 0, buf, sizeof (buf))); 1702 1703 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_UID), pr_uid, 1704 MSG_ORIG(MSG_CNOTE_T_PR_GID), pr_gid); 1705 1706 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_MAJOR), pr_major, 1707 MSG_ORIG(MSG_CNOTE_T_PR_MINOR), pr_minor); 1708 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_RMAJOR), pr_rmajor, 1709 MSG_ORIG(MSG_CNOTE_T_PR_RMINOR), pr_rminor); 1710 1711 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_INO), pr_ino); 1712 1713 PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_SIZE), pr_size, 1714 MSG_ORIG(MSG_CNOTE_T_PR_OFFSET), pr_offset); 1715 1716 fileflags = extract_as_word(state, &layout->pr_fileflags); 1717 1718 print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_FILEFLAGS), 1719 conv_cnote_fileflags(fileflags, 0, buf, sizeof (buf))); 1720 1721 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_FDFLAGS), pr_fdflags); 1722 1723 PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_PATH), pr_path); 1724 1725 indent_exit(state); 1726 } 1727 1728 /* 1729 * Output information from priv_impl_info_t structure. 1730 */ 1731 static void 1732 dump_priv_impl_info(note_state_t *state, const char *title) 1733 { 1734 const sl_priv_impl_info_layout_t *layout; 1735 1736 layout = state->ns_arch->priv_impl_info; 1737 indent_enter(state, title, &layout->priv_headersize); 1738 1739 PRINT_HEX_2UP(MSG_ORIG(MSG_CNOTE_T_PRIV_HEADERSIZE), priv_headersize, 1740 MSG_ORIG(MSG_CNOTE_T_PRIV_FLAGS), priv_flags); 1741 1742 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PRIV_NSETS), 1743 &layout->priv_nsets, SL_FMT_NUM_DEC, 1744 MSG_ORIG(MSG_CNOTE_T_PRIV_SETSIZE), &layout->priv_setsize, 1745 SL_FMT_NUM_HEX); 1746 print_num_2up(state, MSG_ORIG(MSG_CNOTE_T_PRIV_MAX), &layout->priv_max, 1747 SL_FMT_NUM_DEC, MSG_ORIG(MSG_CNOTE_T_PRIV_INFOSIZE), 1748 &layout->priv_infosize, SL_FMT_NUM_HEX); 1749 PRINT_HEX(MSG_ORIG(MSG_CNOTE_T_PRIV_GLOBALINFOSIZE), 1750 priv_globalinfosize); 1751 1752 indent_exit(state); 1753 } 1754 1755 1756 /* 1757 * Dump information from an asrset_t array. This data 1758 * structure is specific to sparcv9, and does not appear 1759 * on any other platform. 1760 * 1761 * asrset_t is a simple array, defined in <sys/regset.h> as 1762 * typedef int64_t asrset_t[16]; %asr16 - > %asr31 1763 * 1764 * As such, we do not make use of the struct_layout facilities 1765 * for this routine. 1766 */ 1767 static void 1768 dump_asrset(note_state_t *state, const char *title) 1769 { 1770 static const sl_field_t ftemplate = { 0, sizeof (int64_t), 16, 0 }; 1771 sl_field_t fdesc1, fdesc2; 1772 sl_fmtbuf_t buf1, buf2; 1773 char index1[MAXNDXSIZE * 2], index2[MAXNDXSIZE * 2]; 1774 Word w, nelts; 1775 1776 fdesc1 = fdesc2 = ftemplate; 1777 1778 /* We expect 16 values, but will print whatever is actually there */ 1779 nelts = state->ns_len / ftemplate.slf_eltlen; 1780 if (nelts == 0) 1781 return; 1782 1783 indent_enter(state, title, &fdesc1); 1784 1785 for (w = 0; w < nelts; ) { 1786 (void) snprintf(index1, sizeof (index1), 1787 MSG_ORIG(MSG_FMT_ASRINDEX), w + 16); 1788 1789 if (w == (nelts - 1)) { 1790 /* One last register is left */ 1791 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE), 1792 INDENT, state->ns_vcol - state->ns_indent, index1, 1793 fmt_num(state, &fdesc1, SL_FMT_NUM_ZHEX, buf1)); 1794 fdesc1.slf_offset += fdesc1.slf_eltlen; 1795 w++; 1796 continue; 1797 } 1798 1799 /* There are at least 2 more registers left. Show 2 up */ 1800 (void) snprintf(index2, sizeof (index2), 1801 MSG_ORIG(MSG_FMT_ASRINDEX), w + 17); 1802 1803 fdesc2.slf_offset = fdesc1.slf_offset + fdesc1.slf_eltlen; 1804 dbg_print(0, MSG_ORIG(MSG_CNOTE_FMT_LINE_2UP), INDENT, 1805 state->ns_vcol - state->ns_indent, index1, 1806 state->ns_t2col - state->ns_vcol, 1807 fmt_num(state, &fdesc1, SL_FMT_NUM_ZHEX, buf1), 1808 state->ns_v2col - state->ns_t2col, index2, 1809 fmt_num(state, &fdesc2, SL_FMT_NUM_ZHEX, buf2)); 1810 fdesc1.slf_offset += 2 * fdesc1.slf_eltlen; 1811 w += 2; 1812 } 1813 1814 indent_exit(state); 1815 } 1816 1817 static void 1818 dump_upanic(note_state_t *state, const char *title) 1819 { 1820 const sl_prupanic_layout_t *layout = state->ns_arch->prupanic; 1821 Conv_upanic_buf_t inv; 1822 Word w; 1823 1824 indent_enter(state, title, &layout->pru_version); 1825 w = extract_as_word(state, &layout->pru_version); 1826 if (w != PRUPANIC_VERSION_1) { 1827 PRINT_DEC(MSG_INTL(MSG_NOTE_BAD_UPANIC_VER), pru_version); 1828 dump_hex_bytes(state->ns_data, state->ns_len, state->ns_indent, 1829 4, 3); 1830 } else { 1831 PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PRU_VERSION), pru_version); 1832 w = extract_as_word(state, &layout->pru_flags); 1833 print_str(state, MSG_ORIG(MSG_CNOTE_T_PRU_FLAGS), 1834 conv_prupanic(w, 0, &inv)); 1835 1836 if ((w & PRUPANIC_FLAG_MSG_VALID) != 0) { 1837 /* 1838 * We have a message that is _probably_ a text string, 1839 * but the interface allows for arbitrary data. The only 1840 * guarantee is that someone using this is probably up 1841 * to no good. As a result, we basically try to print 1842 * this as a string, but in the face of certain types of 1843 * data, we hex escape it. 1844 */ 1845 print_strbuf(state, MSG_ORIG(MSG_CNOTE_T_PRU_DATA), 1846 &layout->pru_data); 1847 } 1848 } 1849 } 1850 1851 corenote_ret_t 1852 corenote(Half mach, int do_swap, Word type, 1853 const char *desc, Word descsz) 1854 { 1855 note_state_t state; 1856 1857 /* 1858 * Get the per-architecture layout definition 1859 */ 1860 state.ns_mach = mach; 1861 state.ns_arch = sl_mach(state.ns_mach); 1862 if (sl_mach(state.ns_mach) == NULL) 1863 return (CORENOTE_R_BADARCH); 1864 1865 state.ns_swap = do_swap; 1866 state.ns_indent = 4; 1867 state.ns_t2col = state.ns_v2col = 0; 1868 state.ns_data = desc; 1869 state.ns_len = descsz; 1870 1871 switch (type) { 1872 case NT_PRSTATUS: /* prstatus_t <sys/old_procfs.h> */ 1873 state.ns_vcol = 26; 1874 state.ns_t2col = 46; 1875 state.ns_v2col = 60; 1876 dump_prstatus(&state, MSG_ORIG(MSG_CNOTE_DESC_PRSTATUS_T)); 1877 return (CORENOTE_R_OK); 1878 1879 case NT_PRFPREG: /* prfpregset_t <sys/procfs_isa.h> */ 1880 return (CORENOTE_R_OK_DUMP); 1881 1882 case NT_PRPSINFO: /* prpsinfo_t <sys/old_procfs.h> */ 1883 state.ns_vcol = 20; 1884 state.ns_t2col = 41; 1885 state.ns_v2col = 54; 1886 dump_prpsinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_PRPSINFO_T)); 1887 return (CORENOTE_R_OK); 1888 1889 case NT_PRXREG: /* prxregset_t <sys/procfs_isa.h> */ 1890 return (CORENOTE_R_OK_DUMP); 1891 1892 case NT_PLATFORM: /* string from sysinfo(SI_PLATFORM) */ 1893 dbg_print(0, MSG_ORIG(MSG_NOTE_DESC)); 1894 dbg_print(0, MSG_ORIG(MSG_FMT_INDENT), safe_str(desc, descsz)); 1895 return (CORENOTE_R_OK); 1896 1897 case NT_AUXV: /* auxv_t array <sys/auxv.h> */ 1898 state.ns_vcol = 18; 1899 dump_auxv(&state, MSG_ORIG(MSG_CNOTE_DESC_AUXV_T)); 1900 return (CORENOTE_R_OK); 1901 1902 case NT_GWINDOWS: /* gwindows_t SPARC only */ 1903 return (CORENOTE_R_OK_DUMP); 1904 1905 case NT_ASRS: /* asrset_t <sys/regset> sparcv9 only */ 1906 state.ns_vcol = 18; 1907 state.ns_t2col = 38; 1908 state.ns_v2col = 46; 1909 dump_asrset(&state, MSG_ORIG(MSG_CNOTE_DESC_ASRSET_T)); 1910 return (CORENOTE_R_OK); 1911 1912 case NT_LDT: /* ssd array <sys/sysi86.h> IA32 only */ 1913 return (CORENOTE_R_OK_DUMP); 1914 1915 case NT_PSTATUS: /* pstatus_t <sys/procfs.h> */ 1916 state.ns_vcol = 22; 1917 state.ns_t2col = 42; 1918 state.ns_v2col = 54; 1919 dump_pstatus(&state, MSG_ORIG(MSG_CNOTE_DESC_PSTATUS_T)); 1920 return (CORENOTE_R_OK); 1921 1922 case NT_PSINFO: /* psinfo_t <sys/procfs.h> */ 1923 state.ns_vcol = 25; 1924 state.ns_t2col = 45; 1925 state.ns_v2col = 58; 1926 dump_psinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_PSINFO_T)); 1927 return (CORENOTE_R_OK); 1928 1929 case NT_PRCRED: /* prcred_t <sys/procfs.h> */ 1930 state.ns_vcol = 20; 1931 state.ns_t2col = 34; 1932 state.ns_v2col = 44; 1933 dump_prcred(&state, MSG_ORIG(MSG_CNOTE_DESC_PRCRED_T)); 1934 return (CORENOTE_R_OK); 1935 1936 case NT_UTSNAME: /* struct utsname <sys/utsname.h> */ 1937 state.ns_vcol = 18; 1938 dump_utsname(&state, MSG_ORIG(MSG_CNOTE_DESC_STRUCT_UTSNAME)); 1939 return (CORENOTE_R_OK); 1940 1941 case NT_LWPSTATUS: /* lwpstatus_t <sys/procfs.h> */ 1942 state.ns_vcol = 24; 1943 state.ns_t2col = 44; 1944 state.ns_v2col = 54; 1945 dump_lwpstatus(&state, MSG_ORIG(MSG_CNOTE_DESC_LWPSTATUS_T)); 1946 return (CORENOTE_R_OK); 1947 1948 case NT_LWPSINFO: /* lwpsinfo_t <sys/procfs.h> */ 1949 state.ns_vcol = 22; 1950 state.ns_t2col = 42; 1951 state.ns_v2col = 54; 1952 dump_lwpsinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_LWPSINFO_T)); 1953 return (CORENOTE_R_OK); 1954 1955 case NT_PRPRIV: /* prpriv_t <sys/procfs.h> */ 1956 state.ns_vcol = 21; 1957 state.ns_t2col = 34; 1958 state.ns_v2col = 38; 1959 dump_prpriv(&state, MSG_ORIG(MSG_CNOTE_DESC_PRPRIV_T)); 1960 return (CORENOTE_R_OK); 1961 1962 case NT_PRPRIVINFO: /* priv_impl_info_t <sys/priv.h> */ 1963 state.ns_vcol = 29; 1964 state.ns_t2col = 41; 1965 state.ns_v2col = 56; 1966 dump_priv_impl_info(&state, 1967 MSG_ORIG(MSG_CNOTE_DESC_PRIV_IMPL_INFO_T)); 1968 return (CORENOTE_R_OK); 1969 1970 case NT_CONTENT: /* core_content_t <sys/corectl.h> */ 1971 if (sizeof (core_content_t) > descsz) 1972 return (CORENOTE_R_BADDATA); 1973 { 1974 static sl_field_t fdesc = { 0, 8, 0, 0 }; 1975 Conv_cnote_cc_content_buf_t conv_buf; 1976 core_content_t content; 1977 1978 state.ns_vcol = 8; 1979 indent_enter(&state, 1980 MSG_ORIG(MSG_CNOTE_DESC_CORE_CONTENT_T), 1981 &fdesc); 1982 content = extract_as_lword(&state, &fdesc); 1983 print_str(&state, MSG_ORIG(MSG_STR_EMPTY), 1984 conv_cnote_cc_content(content, 0, &conv_buf)); 1985 indent_exit(&state); 1986 } 1987 return (CORENOTE_R_OK); 1988 1989 case NT_ZONENAME: /* string from getzonenamebyid(3C) */ 1990 dbg_print(0, MSG_ORIG(MSG_NOTE_DESC)); 1991 dbg_print(0, MSG_ORIG(MSG_FMT_INDENT), safe_str(desc, descsz)); 1992 return (CORENOTE_R_OK); 1993 1994 1995 case NT_FDINFO: 1996 state.ns_vcol = 22; 1997 state.ns_t2col = 41; 1998 state.ns_v2col = 54; 1999 dump_prfdinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_PRFDINFO_T)); 2000 return (CORENOTE_R_OK); 2001 2002 case NT_SPYMASTER: 2003 state.ns_vcol = 25; 2004 state.ns_t2col = 45; 2005 state.ns_v2col = 58; 2006 dump_psinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_PSINFO_T)); 2007 return (CORENOTE_R_OK); 2008 2009 case NT_SECFLAGS: 2010 state.ns_vcol = 23; 2011 state.ns_t2col = 41; 2012 state.ns_v2col = 54; 2013 dump_secflags(&state, MSG_ORIG(MSG_CNOTE_DESC_PRSECFLAGS_T)); 2014 return (CORENOTE_R_OK); 2015 2016 case NT_LWPNAME: 2017 state.ns_vcol = 20; 2018 dump_lwpname(&state, MSG_ORIG(MSG_CNOTE_DESC_PRLWPNAME_T)); 2019 return (CORENOTE_R_OK); 2020 2021 case NT_UPANIC: 2022 state.ns_vcol = 23; 2023 dump_upanic(&state, MSG_ORIG(MSG_CNOTE_DESC_PRUPANIC_T)); 2024 return (CORENOTE_R_OK); 2025 } 2026 2027 return (CORENOTE_R_BADTYPE); 2028 } 2029