lens_default.c revision c00837c2928da53a3515b107399b742ea157e78a
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc. 4 * Copyright (C) 1998,2004,2007,2008,2009 Juan Cespedes 5 * Copyright (C) 2006 Ian Wienand 6 * Copyright (C) 2006 Steve Fink 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of the 11 * License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 21 * 02110-1301 USA 22 */ 23 24#include <ctype.h> 25#include <stdlib.h> 26#include <assert.h> 27#include <inttypes.h> 28#include <stdarg.h> 29#include <stdio.h> 30#include <string.h> 31 32#include "bits.h" 33#include "proc.h" 34#include "lens_default.h" 35#include "value.h" 36#include "expr.h" 37#include "type.h" 38#include "common.h" 39#include "zero.h" 40 41#define READER(NAME, TYPE) \ 42 static int \ 43 NAME(struct value *value, TYPE *ret, struct value_dict *arguments) \ 44 { \ 45 union { \ 46 TYPE val; \ 47 unsigned char buf[0]; \ 48 } u; \ 49 if (value_extract_buf(value, u.buf, arguments) < 0) \ 50 return -1; \ 51 *ret = u.val; \ 52 return 0; \ 53 } 54 55READER(read_float, float) 56READER(read_double, double) 57 58#undef READER 59 60#define HANDLE_WIDTH(BITS) \ 61 do { \ 62 long l; \ 63 if (value_extract_word(value, &l, arguments) < 0) \ 64 return -1; \ 65 int##BITS##_t i = l; \ 66 uint64_t v = (uint64_t)(uint##BITS##_t)i; \ 67 switch (format) { \ 68 case INT_FMT_unknown: \ 69 if (l < -10000 || l > 10000) \ 70 case INT_FMT_x: \ 71 return fprintf(stream, "%#"PRIx64, v); \ 72 case INT_FMT_i: \ 73 case INT_FMT_default: \ 74 return fprintf(stream, "%"PRIi##BITS, i); \ 75 case INT_FMT_u: \ 76 return fprintf(stream, "%"PRIu64, v); \ 77 case INT_FMT_o: \ 78 return fprintf(stream, "0%"PRIo64, v); \ 79 } \ 80 } while (0) 81 82enum int_fmt_t 83{ 84 INT_FMT_i, 85 INT_FMT_u, 86 INT_FMT_o, 87 INT_FMT_x, 88 INT_FMT_unknown, 89 INT_FMT_default, 90}; 91 92static int 93format_integer(FILE *stream, struct value *value, enum int_fmt_t format, 94 struct value_dict *arguments) 95{ 96 switch (type_sizeof(value->inferior, value->type)) { 97 98 case 1: HANDLE_WIDTH(8); 99 case 2: HANDLE_WIDTH(16); 100 case 4: HANDLE_WIDTH(32); 101 case 8: HANDLE_WIDTH(64); 102 103 default: 104 assert(!"unsupported integer width"); 105 abort(); 106 107 case -1: 108 return -1; 109 } 110} 111 112#undef HANDLE_WIDTH 113 114static int 115acc_fprintf(int *countp, FILE *stream, const char *format, ...) 116{ 117 va_list pa; 118 va_start(pa, format); 119 int i = account_output(countp, vfprintf(stream, format, pa)); 120 va_end(pa); 121 122 return i; 123} 124 125static int 126print_char(FILE *stream, int c) 127{ 128 const char *fmt; 129 switch (c) { 130 case -1: 131 fmt = "EOF"; 132 break; 133 case 0: 134 fmt = "\\0"; 135 break; 136 case '\a': 137 fmt = "\\a"; 138 break; 139 case '\b': 140 fmt = "\\b"; 141 break; 142 case '\t': 143 fmt = "\\t"; 144 break; 145 case '\n': 146 fmt = "\\n"; 147 break; 148 case '\v': 149 fmt = "\\v"; 150 break; 151 case '\f': 152 fmt = "\\f"; 153 break; 154 case '\r': 155 fmt = "\\r"; 156 break; 157 case '\\': 158 fmt = "\\\\"; 159 break; 160 default: 161 if (isprint(c) || c == ' ') 162 fmt = "%c"; 163 else 164 fmt = "\\%03o"; 165 } 166 167 return fprintf(stream, fmt, c); 168} 169 170static int 171format_char(FILE *stream, struct value *value, struct value_dict *arguments) 172{ 173 long lc; 174 if (value_extract_word(value, &lc, arguments) < 0) 175 return -1; 176 return print_char(stream, (int) lc); 177} 178 179static int 180format_naked(FILE *stream, struct value *value, 181 struct value_dict *arguments, 182 int (*what)(FILE *, struct value *, struct value_dict *)) 183{ 184 int written = 0; 185 if (acc_fprintf(&written, stream, "'") < 0 186 || account_output(&written, 187 what(stream, value, arguments)) < 0 188 || acc_fprintf(&written, stream, "'") < 0) 189 return -1; 190 191 return written; 192} 193 194static int 195format_double(FILE *stream, double value, enum int_fmt_t format) 196{ 197 if (format == INT_FMT_x) 198 return fprintf(stream, "%a", value); 199 else 200 return fprintf(stream, "%f", value); 201} 202 203static int 204format_floating(FILE *stream, struct value *value, struct value_dict *arguments, 205 enum int_fmt_t format) 206{ 207 switch (value->type->type) { 208 float f; 209 double d; 210 case ARGTYPE_FLOAT: 211 if (read_float(value, &f, arguments) < 0) 212 return -1; 213 return format_double(stream, f, format); 214 case ARGTYPE_DOUBLE: 215 if (read_double(value, &d, arguments) < 0) 216 return -1; 217 return format_double(stream, d, format); 218 default: 219 abort(); 220 } 221} 222 223struct format_argument_data 224{ 225 struct value *value; 226 struct value_dict *arguments; 227}; 228 229static int 230format_argument_cb(FILE *stream, void *ptr) 231{ 232 struct format_argument_data *data = ptr; 233 return format_argument(stream, data->value, data->arguments); 234} 235 236static int 237format_struct(FILE *stream, struct value *value, struct value_dict *arguments) 238{ 239 int written = 0; 240 if (acc_fprintf(&written, stream, "{ ") < 0) 241 return -1; 242 243 int need_delim = 0; 244 size_t i; 245 for (i = 0; i < type_struct_size(value->type); ++i) { 246 struct value element; 247 if (value_init_element(&element, value, i) < 0) 248 return -1; 249 250 struct format_argument_data data = { &element, arguments }; 251 int o = delim_output(stream, &need_delim, 252 format_argument_cb, &data); 253 value_destroy(&element); 254 if (o < 0) 255 return -1; 256 257 written += o; 258 } 259 if (acc_fprintf(&written, stream, " }") < 0) 260 return -1; 261 return written; 262} 263 264static const char null_message[] = "nil"; 265int 266format_pointer(FILE *stream, struct value *value, struct value_dict *arguments) 267{ 268 if (value_is_zero(value, arguments)) 269 return fprintf(stream, null_message); 270 271 /* The following is for detecting recursion. We keep track of 272 * the values that were already displayed. Each time a 273 * pointer should be dereferenced, we compare its value to the 274 * value of each of the pointers dereferenced so far. If one 275 * of them matches, instead of recursing, we just printf which 276 * superstructure this pointer recurses to. */ 277 static struct vect pointers = {}; 278 if (pointers.elt_size == 0) 279 VECT_INIT(&pointers, struct value *); 280 281 /* Trim number of expanded structures of the same type. Even 282 * for non-recursive structure, we don't want to expand all of 283 * it if it's huge. */ 284 size_t i; 285 size_t len = vect_size(&pointers); 286 assert(value->type->type == ARGTYPE_POINTER); 287 struct arg_type_info *pointee = value->type->u.ptr_info.info; 288 if (pointee->type == ARGTYPE_STRUCT) { 289 size_t depth = 0; 290 for (i = 0; i < len; ++i) { 291 struct value *old 292 = *VECT_ELEMENT(&pointers, struct value *, i); 293 assert(old->type->type == ARGTYPE_POINTER); 294 struct arg_type_info *old_pointee 295 = old->type->u.ptr_info.info; 296 if (old_pointee == pointee) 297 depth++; 298 } 299 if (depth >= options.arraylen) 300 return fprintf(stream, "..."); 301 } 302 303 for (i = len; i-- > 0 ;) { 304 struct value **old = VECT_ELEMENT(&pointers, struct value *, i); 305 int rc = value_equal(value, *old, arguments); 306 if (rc < 0) 307 return -1; 308 if (rc > 0) { 309 size_t reclevel = len - i - 1; 310 char buf[reclevel + 1]; 311 memset(buf, '^', sizeof buf); 312 buf[reclevel] = 0; 313 return fprintf(stream, "recurse%s", buf); 314 } 315 } 316 317 /* OK, not a recursion. Remember this value for tracking. */ 318 if (VECT_PUSHBACK(&pointers, &value) < 0) 319 return -1; 320 321 struct value element; 322 int o; 323 if (value_init_deref(&element, value) < 0) { 324 o = -1; 325 goto done; 326 } 327 o = format_argument(stream, &element, arguments); 328 value_destroy(&element); 329 330done: 331 VECT_POPBACK(&pointers, struct value *, NULL, NULL); 332 return o; 333} 334 335/* 336 * LENGTH is an expression whose evaluation will yield the actual 337 * length of the array. 338 * 339 * MAXLEN is the actual maximum length that we care about 340 * 341 * BEFORE if LENGTH>MAXLEN, we display ellipsis. We display it before 342 * the closing parenthesis if BEFORE, otherwise after it. 343 * 344 * OPEN, CLOSE, DELIM are opening and closing parenthesis and element 345 * delimiter. 346 */ 347static int 348format_array(FILE *stream, struct value *value, struct value_dict *arguments, 349 struct expr_node *length, size_t maxlen, int before, 350 const char *open, const char *close, const char *delim) 351{ 352 /* We need "long" to be long enough to cover the whole address 353 * space. */ 354 (void)sizeof(char[1 - 2*(sizeof(long) < sizeof(void *))]); 355 long l; 356 if (expr_eval_word(length, value, arguments, &l) < 0) 357 return -1; 358 size_t len = (size_t)l; 359 360 int written = 0; 361 if (acc_fprintf(&written, stream, "%s", open) < 0) 362 return -1; 363 364 size_t i; 365 for (i = 0; i < len && i <= maxlen; ++i) { 366 if (i == maxlen) { 367 if (before && acc_fprintf(&written, stream, "...") < 0) 368 return -1; 369 break; 370 } 371 372 if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0) 373 return -1; 374 375 struct value element; 376 if (value_init_element(&element, value, i) < 0) 377 return -1; 378 int o = format_argument(stream, &element, arguments); 379 value_destroy(&element); 380 if (o < 0) 381 return -1; 382 written += o; 383 } 384 if (acc_fprintf(&written, stream, "%s", close) < 0) 385 return -1; 386 if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0) 387 return -1; 388 389 return written; 390} 391 392static int 393toplevel_format_lens(struct lens *lens, FILE *stream, 394 struct value *value, struct value_dict *arguments, 395 enum int_fmt_t int_fmt) 396{ 397 switch (value->type->type) { 398 case ARGTYPE_VOID: 399 return fprintf(stream, "<void>"); 400 401 case ARGTYPE_SHORT: 402 case ARGTYPE_INT: 403 case ARGTYPE_LONG: 404 return format_integer(stream, value, int_fmt, arguments); 405 406 case ARGTYPE_USHORT: 407 case ARGTYPE_UINT: 408 case ARGTYPE_ULONG: 409 if (int_fmt == INT_FMT_i || int_fmt == INT_FMT_default) 410 int_fmt = INT_FMT_u; 411 return format_integer(stream, value, int_fmt, arguments); 412 413 case ARGTYPE_CHAR: 414 if (int_fmt == INT_FMT_default) 415 return format_naked(stream, value, arguments, 416 &format_char); 417 return format_integer(stream, value, int_fmt, arguments); 418 419 case ARGTYPE_FLOAT: 420 case ARGTYPE_DOUBLE: 421 return format_floating(stream, value, arguments, int_fmt); 422 423 case ARGTYPE_STRUCT: 424 return format_struct(stream, value, arguments); 425 426 case ARGTYPE_POINTER: 427 if (value_is_zero(value, arguments)) 428 return fprintf(stream, null_message); 429 if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID) 430 return format_pointer(stream, value, arguments); 431 return format_integer(stream, value, INT_FMT_x, arguments); 432 433 case ARGTYPE_ARRAY: 434 return format_array(stream, value, arguments, 435 value->type->u.array_info.length, 436 options.arraylen, 1, "[ ", " ]", ", "); 437 } 438 abort(); 439} 440 441static int 442default_lens_format_cb(struct lens *lens, FILE *stream, 443 struct value *value, struct value_dict *arguments) 444{ 445 return toplevel_format_lens(lens, stream, value, arguments, 446 INT_FMT_default); 447} 448 449struct lens default_lens = { 450 .format_cb = default_lens_format_cb, 451}; 452 453 454static int 455blind_lens_format_cb(struct lens *lens, FILE *stream, 456 struct value *value, struct value_dict *arguments) 457{ 458 return 0; 459} 460 461struct lens blind_lens = { 462 .format_cb = blind_lens_format_cb, 463}; 464 465 466static int 467octal_lens_format_cb(struct lens *lens, FILE *stream, 468 struct value *value, struct value_dict *arguments) 469{ 470 return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_o); 471} 472 473struct lens octal_lens = { 474 .format_cb = octal_lens_format_cb, 475}; 476 477 478static int 479hex_lens_format_cb(struct lens *lens, FILE *stream, 480 struct value *value, struct value_dict *arguments) 481{ 482 return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_x); 483} 484 485struct lens hex_lens = { 486 .format_cb = hex_lens_format_cb, 487}; 488 489 490static int 491dec_lens_format_cb(struct lens *lens, FILE *stream, 492 struct value *value, struct value_dict *arguments) 493{ 494 return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_u); 495} 496 497struct lens dec_lens = { 498 .format_cb = dec_lens_format_cb, 499}; 500 501 502static int 503guess_lens_format_cb(struct lens *lens, FILE *stream, 504 struct value *value, struct value_dict *arguments) 505{ 506 return toplevel_format_lens(lens, stream, value, arguments, 507 INT_FMT_unknown); 508} 509 510struct lens guess_lens = { 511 .format_cb = guess_lens_format_cb, 512}; 513 514 515static int 516bool_lens_format_cb(struct lens *lens, FILE *stream, 517 struct value *value, struct value_dict *arguments) 518{ 519 switch (value->type->type) { 520 case ARGTYPE_VOID: 521 case ARGTYPE_FLOAT: 522 case ARGTYPE_DOUBLE: 523 case ARGTYPE_STRUCT: 524 case ARGTYPE_POINTER: 525 case ARGTYPE_ARRAY: 526 return toplevel_format_lens(lens, stream, value, 527 arguments, INT_FMT_default); 528 529 int zero; 530 case ARGTYPE_SHORT: 531 case ARGTYPE_INT: 532 case ARGTYPE_LONG: 533 case ARGTYPE_USHORT: 534 case ARGTYPE_UINT: 535 case ARGTYPE_ULONG: 536 case ARGTYPE_CHAR: 537 if ((zero = value_is_zero(value, arguments)) < 0) 538 return -1; 539 if (zero) 540 return fprintf(stream, "false"); 541 else 542 return fprintf(stream, "true"); 543 } 544 abort(); 545} 546 547struct lens bool_lens = { 548 .format_cb = bool_lens_format_cb, 549}; 550 551static int 552redispatch_as_array(struct lens *lens, FILE *stream, 553 struct value *value, struct value_dict *arguments, 554 int (*cb)(struct lens *, FILE *, 555 struct value *, struct value_dict *)) 556{ 557 struct arg_type_info info[2]; 558 type_init_array(&info[1], value->type->u.ptr_info.info, 0, 559 expr_node_zero(), 0); 560 type_init_pointer(&info[0], &info[1], 0); 561 info->lens = lens; 562 info->own_lens = 0; 563 struct value tmp; 564 if (value_clone(&tmp, value) < 0) 565 return -1; 566 value_set_type(&tmp, info, 0); 567 int ret = cb(lens, stream, &tmp, arguments); 568 type_destroy(&info[0]); 569 type_destroy(&info[1]); 570 value_destroy(&tmp); 571 return ret; 572} 573 574static int 575format_wchar(FILE *stream, struct value *value, struct value_dict *arguments) 576{ 577 long l; 578 if (value_extract_word(value, &l, arguments) < 0) 579 return -1; 580 wchar_t wc = (wchar_t) l; 581 char buf[MB_CUR_MAX + 1]; 582 583 int c = wctomb(buf, wc); 584 if (c < 0) 585 return -1; 586 if (c == 1) 587 return print_char(stream, buf[0]); 588 589 buf[c] = 0; 590 return fprintf(stream, "%s", buf) >= 0 ? 1 : -1; 591} 592 593static int 594string_lens_format_cb(struct lens *lens, FILE *stream, 595 struct value *value, struct value_dict *arguments) 596{ 597 switch (value->type->type) { 598 case ARGTYPE_POINTER: 599 /* This should really be written as either "string", 600 * or, if lens, then string(array(char, zero)*). But 601 * I suspect people are so used to the char * C idiom, 602 * that string(char *) might actually turn up. So 603 * let's just support it. */ 604 switch ((int) value->type->u.ptr_info.info->type) 605 case ARGTYPE_CHAR: 606 case ARGTYPE_SHORT: 607 case ARGTYPE_USHORT: 608 case ARGTYPE_INT: 609 case ARGTYPE_UINT: 610 case ARGTYPE_LONG: 611 case ARGTYPE_ULONG: 612 return redispatch_as_array(lens, stream, value, 613 arguments, 614 &string_lens_format_cb); 615 616 /* Otherwise dispatch to whatever the default for the 617 * pointee is--most likely this will again be us. */ 618 /* Fall through. */ 619 case ARGTYPE_VOID: 620 case ARGTYPE_FLOAT: 621 case ARGTYPE_DOUBLE: 622 case ARGTYPE_STRUCT: 623 return toplevel_format_lens(lens, stream, value, 624 arguments, INT_FMT_default); 625 626 case ARGTYPE_SHORT: 627 case ARGTYPE_INT: 628 case ARGTYPE_LONG: 629 case ARGTYPE_USHORT: 630 case ARGTYPE_UINT: 631 case ARGTYPE_ULONG: 632 if (value->parent != NULL && value->type->lens == NULL) 633 return format_wchar(stream, value, arguments); 634 else 635 return format_naked(stream, value, arguments, 636 &format_wchar); 637 638 case ARGTYPE_CHAR: 639 return format_char(stream, value, arguments); 640 641 case ARGTYPE_ARRAY: 642 return format_array(stream, value, arguments, 643 value->type->u.array_info.length, 644 options.strlen, 0, "\"", "\"", ""); 645 } 646 abort(); 647} 648 649struct lens string_lens = { 650 .format_cb = string_lens_format_cb, 651}; 652 653static int 654out_bits(FILE *stream, size_t low, size_t high) 655{ 656 if (low == high) 657 return fprintf(stream, "%zd", low); 658 else 659 return fprintf(stream, "%zd-%zd", low, high); 660} 661 662static int 663bitvect_lens_format_cb(struct lens *lens, FILE *stream, 664 struct value *value, struct value_dict *arguments) 665{ 666 unsigned char *data = value_get_data(value, arguments); 667 if (data == NULL) 668 return -1; 669 size_t sz = type_sizeof(value->inferior, value->type); 670 if (sz == (size_t)-1) 671 return -1; 672 673 size_t i; 674 unsigned char buf[sz]; 675 switch ((int)value->type->type) { 676 union bitvect_integral_64 677 { 678 uint8_t u8; 679 uint16_t u16; 680 uint32_t u32; 681 uint64_t u64; 682 unsigned char buf[0]; 683 } bv; 684 685 case ARGTYPE_POINTER: 686 return format_pointer(stream, value, arguments); 687 688 case ARGTYPE_STRUCT: 689 case ARGTYPE_ARRAY: 690 break; 691 692 default: 693 assert(sz <= sizeof(bv)); 694 memmove(bv.buf, data, sz); 695 696 if (sz == 1) 697 bv.u64 = bv.u8; 698 else if (sz == 2) 699 bv.u64 = bv.u16; 700 else if (sz == 4) 701 bv.u64 = bv.u32; 702 703 for (i = 0; i < sz; ++i) { 704 buf[i] = bv.u64 & 0xff; 705 bv.u64 >>= 8; 706 } 707 data = buf; 708 } 709 710 size_t bits = 0; 711 for (i = 0; i < sz; ++i) 712 bits += bitcount(data[i]); 713 714 /* If there's more 1's than 0's, show inverse. */ 715 unsigned neg = bits > sz * 4 ? 0xff : 0x00; 716 717 int o = 0; 718 if (acc_fprintf(&o, stream, "%s<", &"~"[neg == 0x00]) < 0) 719 return -1; 720 721 size_t bitno = 0; 722 ssize_t low = -1; 723 for (i = 0; i < sz; ++i) { 724 unsigned char m; 725 unsigned char d = data[i] ^ neg; 726 for (m = 0x01; m != 0; m <<= 1) { 727 int bit = !!(m & d); 728 if (low < 0) { 729 if (bit) { 730 if (low == -2 731 && acc_fprintf(&o, stream, ",") < 0) 732 return -1; 733 low = bitno; 734 } 735 } else if (!bit) { 736 if (account_output(&o, out_bits(stream, low, 737 bitno-1)) < 0) 738 return -1; 739 low = -2; 740 } 741 bitno++; 742 } 743 } 744 if (low >= 0 && account_output(&o, out_bits(stream, low, bitno-1)) < 0) 745 return -1; 746 747 if (fputc('>', stream) < 0) 748 return -1; 749 o += 1; 750 751 return o; 752} 753 754struct lens bitvect_lens = { 755 .format_cb = bitvect_lens_format_cb, 756}; 757