lens_default.c revision d8286ed3496bcd69cd4796f57a5b5c04859d2378
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 126format_char(FILE *stream, struct value *value, struct value_dict *arguments) 127{ 128 long lc; 129 if (value_extract_word(value, &lc, arguments) < 0) 130 return -1; 131 int c = (int)lc; 132 133 const char *fmt; 134 switch (c) { 135 case -1: 136 fmt = "EOF"; 137 break; 138 case 0: 139 fmt = "\\0"; 140 break; 141 case '\a': 142 fmt = "\\a"; 143 break; 144 case '\b': 145 fmt = "\\b"; 146 break; 147 case '\t': 148 fmt = "\\t"; 149 break; 150 case '\n': 151 fmt = "\\n"; 152 break; 153 case '\v': 154 fmt = "\\v"; 155 break; 156 case '\f': 157 fmt = "\\f"; 158 break; 159 case '\r': 160 fmt = "\\r"; 161 break; 162 case '\\': 163 fmt = "\\\\"; 164 break; 165 default: 166 if (isprint(c) || c == ' ') 167 fmt = "%c"; 168 else 169 fmt = "\\%03o"; 170 } 171 172 return fprintf(stream, fmt, c); 173} 174 175static int 176format_naked_char(FILE *stream, struct value *value, 177 struct value_dict *arguments) 178{ 179 int written = 0; 180 if (acc_fprintf(&written, stream, "'") < 0 181 || account_output(&written, 182 format_char(stream, value, arguments)) < 0 183 || acc_fprintf(&written, stream, "'") < 0) 184 return -1; 185 186 return written; 187} 188 189static int 190format_double(FILE *stream, double value, enum int_fmt_t format) 191{ 192 if (format == INT_FMT_x) 193 return fprintf(stream, "%a", value); 194 else 195 return fprintf(stream, "%f", value); 196} 197 198static int 199format_floating(FILE *stream, struct value *value, struct value_dict *arguments, 200 enum int_fmt_t format) 201{ 202 switch (value->type->type) { 203 float f; 204 double d; 205 case ARGTYPE_FLOAT: 206 if (read_float(value, &f, arguments) < 0) 207 return -1; 208 return format_double(stream, f, format); 209 case ARGTYPE_DOUBLE: 210 if (read_double(value, &d, arguments) < 0) 211 return -1; 212 return format_double(stream, d, format); 213 default: 214 abort(); 215 } 216} 217 218struct format_argument_data 219{ 220 struct value *value; 221 struct value_dict *arguments; 222}; 223 224static int 225format_argument_cb(FILE *stream, void *ptr) 226{ 227 struct format_argument_data *data = ptr; 228 return format_argument(stream, data->value, data->arguments); 229} 230 231static int 232format_struct(FILE *stream, struct value *value, struct value_dict *arguments) 233{ 234 int written = 0; 235 if (acc_fprintf(&written, stream, "{ ") < 0) 236 return -1; 237 238 int need_delim = 0; 239 size_t i; 240 for (i = 0; i < type_struct_size(value->type); ++i) { 241 struct value element; 242 if (value_init_element(&element, value, i) < 0) 243 return -1; 244 245 struct format_argument_data data = { &element, arguments }; 246 int o = delim_output(stream, &need_delim, 247 format_argument_cb, &data); 248 value_destroy(&element); 249 if (o < 0) 250 return -1; 251 252 written += o; 253 } 254 if (acc_fprintf(&written, stream, " }") < 0) 255 return -1; 256 return written; 257} 258 259static const char null_message[] = "nil"; 260int 261format_pointer(FILE *stream, struct value *value, struct value_dict *arguments) 262{ 263 if (value_is_zero(value, arguments)) 264 return fprintf(stream, null_message); 265 266 /* The following is for detecting recursion. We keep track of 267 * the values that were already displayed. Each time a 268 * pointer should be dereferenced, we compare its value to the 269 * value of each of the pointers dereferenced so far. If one 270 * of them matches, instead of recursing, we just printf which 271 * superstructure this pointer recurses to. */ 272 static struct vect pointers = {}; 273 if (pointers.elt_size == 0) 274 VECT_INIT(&pointers, struct value *); 275 276 /* Trim number of expanded structures of the same type. Even 277 * for non-recursive structure, we don't want to expand all of 278 * it if it's huge. */ 279 size_t i; 280 size_t len = vect_size(&pointers); 281 assert(value->type->type == ARGTYPE_POINTER); 282 struct arg_type_info *pointee = value->type->u.ptr_info.info; 283 if (pointee->type == ARGTYPE_STRUCT) { 284 size_t depth = 0; 285 for (i = 0; i < len; ++i) { 286 struct value *old 287 = *VECT_ELEMENT(&pointers, struct value *, i); 288 assert(old->type->type == ARGTYPE_POINTER); 289 struct arg_type_info *old_pointee 290 = old->type->u.ptr_info.info; 291 if (old_pointee == pointee) 292 depth++; 293 } 294 if (depth >= options.arraylen) 295 return fprintf(stream, "..."); 296 } 297 298 for (i = len; i-- > 0 ;) { 299 struct value **old = VECT_ELEMENT(&pointers, struct value *, i); 300 int rc = value_equal(value, *old, arguments); 301 if (rc < 0) 302 return -1; 303 if (rc > 0) { 304 size_t reclevel = len - i - 1; 305 char buf[reclevel + 1]; 306 memset(buf, '^', sizeof buf); 307 buf[reclevel] = 0; 308 return fprintf(stream, "recurse%s", buf); 309 } 310 } 311 312 /* OK, not a recursion. Remember this value for tracking. */ 313 if (VECT_PUSHBACK(&pointers, &value) < 0) 314 return -1; 315 316 struct value element; 317 int o; 318 if (value_init_deref(&element, value) < 0) { 319 o = -1; 320 goto done; 321 } 322 o = format_argument(stream, &element, arguments); 323 value_destroy(&element); 324 325done: 326 VECT_POPBACK(&pointers, struct value *, NULL, NULL); 327 return o; 328} 329 330/* 331 * LENGTH is an expression whose evaluation will yield the actual 332 * length of the array. 333 * 334 * MAXLEN is the actual maximum length that we care about 335 * 336 * BEFORE if LENGTH>MAXLEN, we display ellipsis. We display it before 337 * the closing parenthesis if BEFORE, otherwise after it. 338 * 339 * OPEN, CLOSE, DELIM are opening and closing parenthesis and element 340 * delimiter. 341 */ 342int 343format_array(FILE *stream, struct value *value, struct value_dict *arguments, 344 struct expr_node *length, size_t maxlen, int before, 345 const char *open, const char *close, const char *delim) 346{ 347 /* We need "long" to be long enough to cover the whole address 348 * space. */ 349 (void)sizeof(char[1 - 2*(sizeof(long) < sizeof(void *))]); 350 long l; 351 if (expr_eval_word(length, value, arguments, &l) < 0) 352 return -1; 353 size_t len = (size_t)l; 354 355 int written = 0; 356 if (acc_fprintf(&written, stream, "%s", open) < 0) 357 return -1; 358 359 size_t i; 360 for (i = 0; i < len && i <= maxlen; ++i) { 361 if (i == maxlen) { 362 if (before && acc_fprintf(&written, stream, "...") < 0) 363 return -1; 364 break; 365 } 366 367 if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0) 368 return -1; 369 370 struct value element; 371 if (value_init_element(&element, value, i) < 0) 372 return -1; 373 int o = format_argument(stream, &element, arguments); 374 value_destroy(&element); 375 if (o < 0) 376 return -1; 377 written += o; 378 } 379 if (acc_fprintf(&written, stream, "%s", close) < 0) 380 return -1; 381 if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0) 382 return -1; 383 384 return written; 385} 386 387static int 388toplevel_format_lens(struct lens *lens, FILE *stream, 389 struct value *value, struct value_dict *arguments, 390 enum int_fmt_t int_fmt) 391{ 392 switch (value->type->type) { 393 case ARGTYPE_VOID: 394 return fprintf(stream, "<void>"); 395 396 case ARGTYPE_SHORT: 397 case ARGTYPE_INT: 398 case ARGTYPE_LONG: 399 return format_integer(stream, value, int_fmt, arguments); 400 401 case ARGTYPE_USHORT: 402 case ARGTYPE_UINT: 403 case ARGTYPE_ULONG: 404 if (int_fmt == INT_FMT_i || int_fmt == INT_FMT_default) 405 int_fmt = INT_FMT_u; 406 return format_integer(stream, value, int_fmt, arguments); 407 408 case ARGTYPE_CHAR: 409 if (int_fmt == INT_FMT_default) 410 return format_naked_char(stream, value, arguments); 411 return format_integer(stream, value, int_fmt, arguments); 412 413 case ARGTYPE_FLOAT: 414 case ARGTYPE_DOUBLE: 415 return format_floating(stream, value, arguments, int_fmt); 416 417 case ARGTYPE_STRUCT: 418 return format_struct(stream, value, arguments); 419 420 case ARGTYPE_POINTER: 421 if (value_is_zero(value, arguments)) 422 return fprintf(stream, null_message); 423 if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID) 424 return format_pointer(stream, value, arguments); 425 return format_integer(stream, value, INT_FMT_x, arguments); 426 427 case ARGTYPE_ARRAY: 428 return format_array(stream, value, arguments, 429 value->type->u.array_info.length, 430 options.arraylen, 1, "[ ", " ]", ", "); 431 } 432 abort(); 433} 434 435static int 436default_lens_format_cb(struct lens *lens, FILE *stream, 437 struct value *value, struct value_dict *arguments) 438{ 439 return toplevel_format_lens(lens, stream, value, arguments, 440 INT_FMT_default); 441} 442 443struct lens default_lens = { 444 .format_cb = default_lens_format_cb, 445}; 446 447 448static int 449blind_lens_format_cb(struct lens *lens, FILE *stream, 450 struct value *value, struct value_dict *arguments) 451{ 452 return 0; 453} 454 455struct lens blind_lens = { 456 .format_cb = blind_lens_format_cb, 457}; 458 459 460static int 461octal_lens_format_cb(struct lens *lens, FILE *stream, 462 struct value *value, struct value_dict *arguments) 463{ 464 return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_o); 465} 466 467struct lens octal_lens = { 468 .format_cb = octal_lens_format_cb, 469}; 470 471 472static int 473hex_lens_format_cb(struct lens *lens, FILE *stream, 474 struct value *value, struct value_dict *arguments) 475{ 476 return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_x); 477} 478 479struct lens hex_lens = { 480 .format_cb = hex_lens_format_cb, 481}; 482 483 484static int 485dec_lens_format_cb(struct lens *lens, FILE *stream, 486 struct value *value, struct value_dict *arguments) 487{ 488 return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_u); 489} 490 491struct lens dec_lens = { 492 .format_cb = dec_lens_format_cb, 493}; 494 495 496static int 497guess_lens_format_cb(struct lens *lens, FILE *stream, 498 struct value *value, struct value_dict *arguments) 499{ 500 return toplevel_format_lens(lens, stream, value, arguments, 501 INT_FMT_unknown); 502} 503 504struct lens guess_lens = { 505 .format_cb = guess_lens_format_cb, 506}; 507 508 509static int 510bool_lens_format_cb(struct lens *lens, FILE *stream, 511 struct value *value, struct value_dict *arguments) 512{ 513 switch (value->type->type) { 514 case ARGTYPE_VOID: 515 case ARGTYPE_FLOAT: 516 case ARGTYPE_DOUBLE: 517 case ARGTYPE_STRUCT: 518 case ARGTYPE_POINTER: 519 case ARGTYPE_ARRAY: 520 return toplevel_format_lens(lens, stream, value, 521 arguments, INT_FMT_default); 522 523 int zero; 524 case ARGTYPE_SHORT: 525 case ARGTYPE_INT: 526 case ARGTYPE_LONG: 527 case ARGTYPE_USHORT: 528 case ARGTYPE_UINT: 529 case ARGTYPE_ULONG: 530 case ARGTYPE_CHAR: 531 if ((zero = value_is_zero(value, arguments)) < 0) 532 return -1; 533 if (zero) 534 return fprintf(stream, "false"); 535 else 536 return fprintf(stream, "true"); 537 } 538 abort(); 539} 540 541struct lens bool_lens = { 542 .format_cb = bool_lens_format_cb, 543}; 544 545 546static int 547string_lens_format_cb(struct lens *lens, FILE *stream, 548 struct value *value, struct value_dict *arguments) 549{ 550 switch (value->type->type) { 551 case ARGTYPE_POINTER: 552 /* This should really be written as either "string", 553 * or, if lens, then string(array(char, zero)*). But 554 * I suspect people are so used to the char * C idiom, 555 * that string(char *) might actually turn up. So 556 * let's just support it. */ 557 if (value->type->u.ptr_info.info->type == ARGTYPE_CHAR) { 558 struct arg_type_info info[2]; 559 type_init_array(&info[1], 560 value->type->u.ptr_info.info, 0, 561 expr_node_zero(), 0); 562 type_init_pointer(&info[0], &info[1], 0); 563 info->lens = lens; 564 info->own_lens = 0; 565 struct value tmp; 566 if (value_clone(&tmp, value) < 0) 567 return -1; 568 value_set_type(&tmp, info, 0); 569 int ret = string_lens_format_cb(lens, stream, &tmp, 570 arguments); 571 type_destroy(&info[0]); 572 type_destroy(&info[1]); 573 value_destroy(&tmp); 574 return ret; 575 } 576 577 /* fall-through */ 578 case ARGTYPE_VOID: 579 case ARGTYPE_FLOAT: 580 case ARGTYPE_DOUBLE: 581 case ARGTYPE_STRUCT: 582 case ARGTYPE_SHORT: 583 case ARGTYPE_INT: 584 case ARGTYPE_LONG: 585 case ARGTYPE_USHORT: 586 case ARGTYPE_UINT: 587 case ARGTYPE_ULONG: 588 return toplevel_format_lens(lens, stream, value, 589 arguments, INT_FMT_default); 590 591 case ARGTYPE_CHAR: 592 return format_char(stream, value, arguments); 593 594 case ARGTYPE_ARRAY: 595 return format_array(stream, value, arguments, 596 value->type->u.array_info.length, 597 options.strlen, 0, "\"", "\"", ""); 598 } 599 abort(); 600} 601 602struct lens string_lens = { 603 .format_cb = string_lens_format_cb, 604}; 605 606static int 607out_bits(FILE *stream, size_t low, size_t high) 608{ 609 if (low == high) 610 return fprintf(stream, "%zd", low); 611 else 612 return fprintf(stream, "%zd-%zd", low, high); 613} 614 615static int 616bitvect_lens_format_cb(struct lens *lens, FILE *stream, 617 struct value *value, struct value_dict *arguments) 618{ 619 unsigned char *data = value_get_data(value, arguments); 620 if (data == NULL) 621 return -1; 622 size_t sz = type_sizeof(value->inferior, value->type); 623 if (sz == (size_t)-1) 624 return -1; 625 626 size_t i; 627 unsigned char buf[sz]; 628 switch ((int)value->type->type) { 629 union bitvect_integral_64 630 { 631 uint8_t u8; 632 uint16_t u16; 633 uint32_t u32; 634 uint64_t u64; 635 unsigned char buf[0]; 636 } bv; 637 638 case ARGTYPE_POINTER: 639 return format_pointer(stream, value, arguments); 640 641 case ARGTYPE_STRUCT: 642 case ARGTYPE_ARRAY: 643 break; 644 645 default: 646 assert(sz <= sizeof(bv)); 647 memmove(bv.buf, data, sz); 648 649 if (sz == 1) 650 bv.u64 = bv.u8; 651 else if (sz == 2) 652 bv.u64 = bv.u16; 653 else if (sz == 4) 654 bv.u64 = bv.u32; 655 656 for (i = 0; i < sz; ++i) { 657 buf[i] = bv.u64 & 0xff; 658 bv.u64 >>= 8; 659 } 660 data = buf; 661 } 662 663 size_t bits = 0; 664 for (i = 0; i < sz; ++i) 665 bits += bitcount(data[i]); 666 667 /* If there's more 1's than 0's, show inverse. */ 668 unsigned neg = bits > sz * 4 ? 0xff : 0x00; 669 670 int o = 0; 671 if (acc_fprintf(&o, stream, "%s<", &"~"[neg == 0x00]) < 0) 672 return -1; 673 674 size_t bitno = 0; 675 ssize_t low = -1; 676 for (i = 0; i < sz; ++i) { 677 unsigned char m; 678 unsigned char d = data[i] ^ neg; 679 for (m = 0x01; m != 0; m <<= 1) { 680 int bit = !!(m & d); 681 if (low < 0) { 682 if (bit) { 683 if (low == -2 684 && acc_fprintf(&o, stream, ",") < 0) 685 return -1; 686 low = bitno; 687 } 688 } else if (!bit) { 689 if (account_output(&o, out_bits(stream, low, 690 bitno-1)) < 0) 691 return -1; 692 low = -2; 693 } 694 bitno++; 695 } 696 } 697 if (low >= 0 && account_output(&o, out_bits(stream, low, bitno-1)) < 0) 698 return -1; 699 700 if (fputc('>', stream) < 0) 701 return -1; 702 o += 1; 703 704 return o; 705} 706 707struct lens bitvect_lens = { 708 .format_cb = bitvect_lens_format_cb, 709}; 710