read_config_file.c revision b17863f2dc7a0f2edbf6a2482028c829b91c2c09
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc. 4 * Copyright (C) 1998,1999,2003,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 "config.h" 25 26#include <string.h> 27#include <stdlib.h> 28#include <ctype.h> 29#include <errno.h> 30#include <error.h> 31#include <assert.h> 32 33#include "common.h" 34#include "output.h" 35#include "expr.h" 36#include "param.h" 37#include "printf.h" 38#include "zero.h" 39#include "type.h" 40#include "lens.h" 41#include "lens_default.h" 42#include "lens_enum.h" 43 44static int line_no; 45static char *filename; 46 47static struct arg_type_info *parse_nonpointer_type(char **str, 48 struct param **extra_param, 49 size_t param_num, int *ownp); 50static struct arg_type_info *parse_type(char **str, struct param **extra_param, 51 size_t param_num, int *ownp); 52static struct arg_type_info *parse_lens(char **str, struct param **extra_param, 53 size_t param_num, int *ownp); 54static int parse_enum(char **str, struct arg_type_info **retp, int *ownp); 55 56Function *list_of_functions = NULL; 57 58static int 59parse_arg_type(char **name, enum arg_type *ret) 60{ 61 char *rest = NULL; 62 enum arg_type candidate; 63 64#define KEYWORD(KWD, TYPE) \ 65 do { \ 66 if (strncmp(*name, KWD, sizeof(KWD) - 1) == 0) { \ 67 rest = *name + sizeof(KWD) - 1; \ 68 candidate = TYPE; \ 69 goto ok; \ 70 } \ 71 } while (0) 72 73 KEYWORD("void", ARGTYPE_VOID); 74 KEYWORD("int", ARGTYPE_INT); 75 KEYWORD("uint", ARGTYPE_UINT); 76 KEYWORD("long", ARGTYPE_LONG); 77 KEYWORD("ulong", ARGTYPE_ULONG); 78 KEYWORD("char", ARGTYPE_CHAR); 79 KEYWORD("short", ARGTYPE_SHORT); 80 KEYWORD("ushort", ARGTYPE_USHORT); 81 KEYWORD("float", ARGTYPE_FLOAT); 82 KEYWORD("double", ARGTYPE_DOUBLE); 83 KEYWORD("array", ARGTYPE_ARRAY); 84 KEYWORD("struct", ARGTYPE_STRUCT); 85 86 /* Misspelling of int used in ltrace.conf that we used to 87 * ship. */ 88 KEYWORD("itn", ARGTYPE_INT); 89 90 assert(rest == NULL); 91 return -1; 92 93#undef KEYWORD 94 95ok: 96 if (isalnum(*rest)) 97 return -1; 98 99 *name = rest; 100 *ret = candidate; 101 return 0; 102} 103 104static void 105eat_spaces(char **str) { 106 while (**str == ' ') { 107 (*str)++; 108 } 109} 110 111static char * 112xstrndup(char *str, size_t len) { 113 char *ret = (char *) malloc(len + 1); 114 if (ret == NULL) { 115 report_global_error("malloc: %s", strerror(errno)); 116 return NULL; 117 } 118 strncpy(ret, str, len); 119 ret[len] = 0; 120 return ret; 121} 122 123static char * 124parse_ident(char **str) { 125 char *ident = *str; 126 127 if (!isalpha(**str) && **str != '_') { 128 report_error(filename, line_no, "bad identifier"); 129 return NULL; 130 } 131 132 while (**str && (isalnum(**str) || **str == '_')) { 133 ++(*str); 134 } 135 136 return xstrndup(ident, *str - ident); 137} 138 139/* 140 Returns position in string at the left parenthesis which starts the 141 function's argument signature. Returns NULL on error. 142*/ 143static char * 144start_of_arg_sig(char *str) { 145 char *pos; 146 int stacked = 0; 147 148 if (!strlen(str)) 149 return NULL; 150 151 pos = &str[strlen(str)]; 152 do { 153 pos--; 154 if (pos < str) 155 return NULL; 156 while ((pos > str) && (*pos != ')') && (*pos != '(')) 157 pos--; 158 159 if (*pos == ')') 160 stacked++; 161 else if (*pos == '(') 162 stacked--; 163 else 164 return NULL; 165 166 } while (stacked > 0); 167 168 return (stacked == 0) ? pos : NULL; 169} 170 171static int 172parse_int(char **str, long *ret) 173{ 174 char *end; 175 long n = strtol(*str, &end, 0); 176 if (end == *str) { 177 report_error(filename, line_no, "bad number"); 178 return -1; 179 } 180 181 *str = end; 182 if (ret != NULL) 183 *ret = n; 184 return 0; 185} 186 187static int 188check_nonnegative(long l) 189{ 190 if (l < 0) { 191 report_error(filename, line_no, 192 "expected non-negative value, got %ld", l); 193 return -1; 194 } 195 return 0; 196} 197 198static int 199check_int(long l) 200{ 201 int i = l; 202 if ((long)i != l) { 203 report_error(filename, line_no, 204 "Number too large: %ld", l); 205 return -1; 206 } 207 return 0; 208} 209 210static int 211parse_char(char **str, char expected) 212{ 213 if (**str != expected) { 214 report_error(filename, line_no, 215 "expected '%c', got '%c'", expected, **str); 216 return -1; 217 } 218 219 ++*str; 220 return 0; 221} 222 223static struct expr_node *parse_argnum(char **str, int *ownp, int zero); 224 225static struct expr_node * 226parse_zero(char **str, struct expr_node *ret, int *ownp) 227{ 228 eat_spaces(str); 229 if (**str == '(') { 230 ++*str; 231 int own; 232 struct expr_node *arg = parse_argnum(str, &own, 0); 233 if (arg == NULL) 234 return NULL; 235 if (parse_char(str, ')') < 0) { 236 fail: 237 expr_destroy(arg); 238 free(arg); 239 return NULL; 240 } 241 242 struct expr_node *ret = build_zero_w_arg(arg, own); 243 if (ret == NULL) 244 goto fail; 245 *ownp = 1; 246 return ret; 247 248 } else { 249 free(ret); 250 *ownp = 0; 251 return expr_node_zero(); 252 } 253} 254 255static int 256wrap_in_zero(struct expr_node **nodep) 257{ 258 struct expr_node *n = build_zero_w_arg(*nodep, 1); 259 if (n == NULL) 260 return -1; 261 *nodep = n; 262 return 0; 263} 264 265/* 266 * Input: 267 * argN : The value of argument #N, counting from 1 268 * eltN : The value of element #N of the containing structure 269 * retval : The return value 270 * N : The numeric value N 271 */ 272static struct expr_node * 273parse_argnum(char **str, int *ownp, int zero) 274{ 275 struct expr_node *expr = malloc(sizeof(*expr)); 276 if (expr == NULL) 277 return NULL; 278 279 if (isdigit(**str)) { 280 long l; 281 if (parse_int(str, &l) < 0 282 || check_nonnegative(l) < 0 283 || check_int(l) < 0) 284 goto fail; 285 286 expr_init_const_word(expr, l, type_get_simple(ARGTYPE_LONG), 0); 287 288 if (zero && wrap_in_zero(&expr) < 0) 289 goto fail; 290 291 *ownp = 1; 292 return expr; 293 294 } else { 295 char *const name = parse_ident(str); 296 if (name == NULL) { 297 fail_ident: 298 free(name); 299 goto fail; 300 } 301 302 int is_arg = strncmp(name, "arg", 3) == 0; 303 if (is_arg || strncmp(name, "elt", 3) == 0) { 304 long l; 305 char *num = name + 3; 306 if (parse_int(&num, &l) < 0 || check_int(l) < 0) 307 goto fail_ident; 308 309 if (is_arg) { 310 if (l == 0) 311 expr_init_named(expr, "retval", 0); 312 else 313 expr_init_argno(expr, l - 1); 314 } else { 315 struct expr_node *e_up = malloc(sizeof(*e_up)); 316 struct expr_node *e_ix = malloc(sizeof(*e_ix)); 317 if (e_up == NULL || e_ix == NULL) { 318 free(e_up); 319 free(e_ix); 320 goto fail_ident; 321 } 322 323 expr_init_up(e_up, expr_self(), 0); 324 struct arg_type_info *ti 325 = type_get_simple(ARGTYPE_LONG); 326 expr_init_const_word(e_ix, l - 1, ti, 0); 327 expr_init_index(expr, e_up, 1, e_ix, 1); 328 } 329 330 } else if (strcmp(name, "retval") == 0) { 331 expr_init_named(expr, "retval", 0); 332 333 } else if (strcmp(name, "zero") == 0) { 334 struct expr_node *ret = parse_zero(str, expr, ownp); 335 if (ret == NULL) 336 goto fail_ident; 337 return ret; 338 339 } else { 340 report_error(filename, line_no, 341 "Unknown length specifier: '%s'", name); 342 goto fail_ident; 343 } 344 345 if (zero && wrap_in_zero(&expr) < 0) 346 goto fail_ident; 347 348 free(name); 349 *ownp = 1; 350 return expr; 351 } 352 353fail: 354 free(expr); 355 return NULL; 356} 357 358struct typedef_node_t { 359 char *name; 360 struct arg_type_info *info; 361 int own_type; 362 struct typedef_node_t *next; 363} *typedefs = NULL; 364 365static struct arg_type_info * 366lookup_typedef(const char *name) 367{ 368 struct typedef_node_t *node; 369 for (node = typedefs; node != NULL; node = node->next) 370 if (strcmp(name, node->name) == 0) 371 return node->info; 372 return NULL; 373} 374 375static struct arg_type_info * 376parse_typedef_name(char **str) 377{ 378 char *end = *str; 379 while (*end && (isalnum(*end) || *end == '_')) 380 ++end; 381 if (end == *str) 382 return NULL; 383 384 size_t len = end - *str; 385 char buf[len + 1]; 386 memcpy(buf, *str, len); 387 *str += len; 388 buf[len] = 0; 389 390 return lookup_typedef(buf); 391} 392 393static struct typedef_node_t * 394insert_typedef(char *name, struct arg_type_info *info, int own_type) 395{ 396 struct typedef_node_t *binding = malloc(sizeof(*binding)); 397 binding->name = name; 398 binding->info = info; 399 binding->own_type = own_type; 400 binding->next = typedefs; 401 typedefs = binding; 402 return binding; 403} 404 405static void 406parse_typedef(char **str) 407{ 408 (*str) += strlen("typedef"); 409 eat_spaces(str); 410 char *name = parse_ident(str); 411 412 struct arg_type_info *info = lookup_typedef(name); 413 if (info != NULL) { 414 report_error(filename, line_no, 415 "Redefinition of typedef '%s'\n", name); 416 return; 417 } 418 419 // Skip = sign 420 eat_spaces(str); 421 if (parse_char(str, '=') < 0) 422 return; 423 eat_spaces(str); 424 425 // Parse the type 426 int own; 427 info = parse_type(str, NULL, 0, &own); 428 429 insert_typedef(name, info, own); 430} 431 432static void 433destroy_fun(Function *fun) 434{ 435 size_t i; 436 if (fun == NULL) 437 return; 438 if (fun->own_return_info) { 439 type_destroy(fun->return_info); 440 free(fun->return_info); 441 } 442 for (i = 0; i < fun->num_params; ++i) 443 param_destroy(&fun->params[i]); 444 free(fun->params); 445} 446 447/* Syntax: struct ( type,type,type,... ) */ 448static int 449parse_struct(char **str, struct arg_type_info *info) 450{ 451 eat_spaces(str); 452 if (parse_char(str, '(') < 0) 453 return -1; 454 455 eat_spaces(str); // Empty arg list with whitespace inside 456 457 type_init_struct(info); 458 459 while (1) { 460 eat_spaces(str); 461 if (**str == 0 || **str == ')') { 462 parse_char(str, ')'); 463 return 0; 464 } 465 466 /* Field delimiter. */ 467 if (type_struct_size(info) > 0) 468 parse_char(str, ','); 469 470 eat_spaces(str); 471 int own; 472 struct arg_type_info *field = parse_lens(str, NULL, 0, &own); 473 if (field == NULL || type_struct_add(info, field, own)) { 474 type_destroy(info); 475 return -1; 476 } 477 } 478} 479 480static int 481parse_string(char **str, struct arg_type_info **retp, int *ownp) 482{ 483 struct arg_type_info *info = malloc(sizeof(*info) * 2); 484 if (info == NULL) { 485 fail: 486 free(info); 487 return -1; 488 } 489 490 struct expr_node *length; 491 int own_length; 492 int with_arg = 0; 493 494 if (isdigit(**str)) { 495 /* string0 is string[retval], length is zero(retval) 496 * stringN is string[argN], length is zero(argN) */ 497 long l; 498 if (parse_int(str, &l) < 0 499 || check_int(l) < 0) 500 goto fail; 501 502 struct expr_node *length_arg = malloc(sizeof(*length_arg)); 503 if (length_arg == NULL) 504 goto fail; 505 506 if (l == 0) 507 expr_init_named(length_arg, "retval", 0); 508 else 509 expr_init_argno(length_arg, l - 1); 510 511 length = build_zero_w_arg(length_arg, 1); 512 if (length == NULL) { 513 expr_destroy(length_arg); 514 free(length_arg); 515 goto fail; 516 } 517 own_length = 1; 518 519 } else { 520 eat_spaces(str); 521 if (**str == '[') { 522 (*str)++; 523 eat_spaces(str); 524 525 length = parse_argnum(str, &own_length, 1); 526 if (length == NULL) 527 goto fail; 528 529 eat_spaces(str); 530 parse_char(str, ']'); 531 532 } else if (**str == '(') { 533 /* Usage of "string" as lens. */ 534 ++*str; 535 536 free(info); 537 538 eat_spaces(str); 539 info = parse_type(str, NULL, 0, ownp); 540 if (info == NULL) 541 goto fail; 542 543 eat_spaces(str); 544 parse_char(str, ')'); 545 546 with_arg = 1; 547 548 } else { 549 /* It was just a simple string after all. */ 550 length = expr_node_zero(); 551 own_length = 0; 552 } 553 } 554 555 /* String is a pointer to array of chars. */ 556 if (!with_arg) { 557 type_init_array(&info[1], type_get_simple(ARGTYPE_CHAR), 0, 558 length, own_length); 559 560 type_init_pointer(&info[0], &info[1], 0); 561 *ownp = 1; 562 } 563 564 info->lens = &string_lens; 565 info->own_lens = 0; 566 567 *retp = info; 568 return 0; 569} 570 571static int 572build_printf_pack(struct param **packp, size_t param_num) 573{ 574 if (packp == NULL) { 575 report_error(filename, line_no, 576 "'format' type in unexpected context"); 577 return -1; 578 } 579 if (*packp != NULL) { 580 report_error(filename, line_no, 581 "only one 'format' type per function supported"); 582 return -1; 583 } 584 585 *packp = malloc(sizeof(**packp)); 586 if (*packp == NULL) 587 return -1; 588 589 struct expr_node *node = malloc(sizeof(*node)); 590 if (node == NULL) { 591 free(*packp); 592 return -1; 593 } 594 595 expr_init_argno(node, param_num); 596 597 param_pack_init_printf(*packp, node, 1); 598 599 return 0; 600} 601 602/* Match and consume KWD if it's next in stream, and return 0. 603 * Otherwise return negative number. */ 604static int 605try_parse_kwd(char **str, const char *kwd) 606{ 607 size_t len = strlen(kwd); 608 if (strncmp(*str, kwd, len) == 0 609 && !isalnum((*str)[len])) { 610 (*str) += len; 611 return 0; 612 } 613 return -1; 614} 615 616/* Make a copy of INFO and set the *OWN bit if it's not already 617 * owned. */ 618static int 619unshare_type_info(struct arg_type_info **infop, int *ownp) 620{ 621 if (*ownp) 622 return 0; 623 624 struct arg_type_info *ninfo = malloc(sizeof(*ninfo)); 625 if (ninfo == NULL) { 626 report_error(filename, line_no, 627 "malloc: %s", strerror(errno)); 628 return -1; 629 } 630 *ninfo = **infop; 631 *infop = ninfo; 632 *ownp = 1; 633 return 0; 634} 635 636/* XXX extra_param and param_num are a kludge to get in 637 * backward-compatible support for "format" parameter type. The 638 * latter is only valid if the former is non-NULL, which is only in 639 * top-level context. */ 640static int 641parse_alias(char **str, struct arg_type_info **retp, int *ownp, 642 struct param **extra_param, size_t param_num) 643{ 644 /* For backward compatibility, we need to support things like 645 * stringN (which is like string[argN], string[N], and also 646 * bare string. We might, in theory, replace this by 647 * preprocessing configure file sources with M4, but for now, 648 * "string" is syntax. */ 649 if (strncmp(*str, "string", 6) == 0) { 650 (*str) += 6; 651 return parse_string(str, retp, ownp); 652 653 } else if (try_parse_kwd(str, "format") >= 0 654 && extra_param != NULL) { 655 /* For backward compatibility, format is parsed as 656 * "string", but it smuggles to the parameter list of 657 * a function a "printf" argument pack with this 658 * parameter as argument. */ 659 if (parse_string(str, retp, ownp) < 0) 660 return -1; 661 662 return build_printf_pack(extra_param, param_num); 663 664 } else if (try_parse_kwd(str, "enum") >=0) { 665 666 return parse_enum(str, retp, ownp); 667 668 } else { 669 *retp = NULL; 670 return 0; 671 } 672} 673 674/* Syntax: array ( type, N|argN ) */ 675static int 676parse_array(char **str, struct arg_type_info *info) 677{ 678 eat_spaces(str); 679 if (parse_char(str, '(') < 0) 680 return -1; 681 682 eat_spaces(str); 683 int own; 684 struct arg_type_info *elt_info = parse_lens(str, NULL, 0, &own); 685 if (elt_info == NULL) 686 return -1; 687 688 eat_spaces(str); 689 parse_char(str, ','); 690 691 eat_spaces(str); 692 int own_length; 693 struct expr_node *length = parse_argnum(str, &own_length, 0); 694 if (length == NULL) { 695 if (own) { 696 type_destroy(elt_info); 697 free(elt_info); 698 } 699 return -1; 700 } 701 702 type_init_array(info, elt_info, own, length, own_length); 703 704 eat_spaces(str); 705 parse_char(str, ')'); 706 return 0; 707} 708 709/* Syntax: 710 * enum (keyname[=value],keyname[=value],... ) 711 * enum<type> (keyname[=value],keyname[=value],... ) 712 */ 713static int 714parse_enum(char **str, struct arg_type_info **retp, int *ownp) 715{ 716 /* Optional type argument. */ 717 eat_spaces(str); 718 if (**str == '[') { 719 parse_char(str, '['); 720 eat_spaces(str); 721 *retp = parse_nonpointer_type(str, NULL, 0, ownp); 722 if (*retp == NULL) 723 return -1; 724 725 if (!type_is_integral((*retp)->type)) { 726 report_error(filename, line_no, 727 "integral type required as enum argument"); 728 fail: 729 if (*ownp) { 730 /* This also releases associated lens 731 * if any was set so far. */ 732 type_destroy(*retp); 733 free(*retp); 734 } 735 return -1; 736 } 737 738 eat_spaces(str); 739 if (parse_char(str, ']') < 0) 740 goto fail; 741 742 } else { 743 *retp = type_get_simple(ARGTYPE_INT); 744 *ownp = 0; 745 } 746 747 /* We'll need to set the lens, so unshare. */ 748 if (unshare_type_info(retp, ownp) < 0) 749 goto fail; 750 751 eat_spaces(str); 752 if (parse_char(str, '(') < 0) 753 goto fail; 754 755 struct enum_lens *lens = malloc(sizeof(*lens)); 756 if (lens == NULL) { 757 report_error(filename, line_no, 758 "malloc enum lens: %s", strerror(errno)); 759 return -1; 760 } 761 762 lens_init_enum(lens); 763 (*retp)->lens = &lens->super; 764 (*retp)->own_lens = 1; 765 766 long last_val = 0; 767 while (1) { 768 eat_spaces(str); 769 if (**str == 0 || **str == ')') { 770 parse_char(str, ')'); 771 return 0; 772 } 773 774 /* Field delimiter. XXX should we support the C 775 * syntax, where the enumeration can end in pending 776 * comma? */ 777 if (lens_enum_size(lens) > 0) 778 parse_char(str, ','); 779 780 eat_spaces(str); 781 char *key = parse_ident(str); 782 if (key == NULL) { 783 err: 784 free(key); 785 goto fail; 786 } 787 788 if (**str == '=') { 789 ++*str; 790 eat_spaces(str); 791 if (parse_int(str, &last_val) < 0) 792 goto err; 793 } 794 795 struct value *value = malloc(sizeof(*value)); 796 if (value == NULL) 797 goto err; 798 value_init_detached(value, NULL, *retp, 0); 799 value_set_word(value, last_val); 800 801 if (lens_enum_add(lens, key, 1, value, 1) < 0) 802 goto err; 803 804 last_val++; 805 } 806 807 return 0; 808} 809 810static struct arg_type_info * 811parse_nonpointer_type(char **str, struct param **extra_param, size_t param_num, 812 int *ownp) 813{ 814 enum arg_type type; 815 if (parse_arg_type(str, &type) < 0) { 816 struct arg_type_info *simple; 817 if (parse_alias(str, &simple, ownp, extra_param, param_num) < 0) 818 return NULL; 819 if (simple == NULL) 820 simple = parse_typedef_name(str); 821 if (simple != NULL) { 822 *ownp = 0; 823 return simple; 824 } 825 826 report_error(filename, line_no, 827 "unknown type around '%s'", *str); 828 return NULL; 829 } 830 831 int (*parser) (char **, struct arg_type_info *) = NULL; 832 833 /* For some types that's all we need. */ 834 switch (type) { 835 case ARGTYPE_VOID: 836 case ARGTYPE_INT: 837 case ARGTYPE_UINT: 838 case ARGTYPE_LONG: 839 case ARGTYPE_ULONG: 840 case ARGTYPE_CHAR: 841 case ARGTYPE_SHORT: 842 case ARGTYPE_USHORT: 843 case ARGTYPE_FLOAT: 844 case ARGTYPE_DOUBLE: 845 *ownp = 0; 846 return type_get_simple(type); 847 848 case ARGTYPE_ARRAY: 849 parser = parse_array; 850 break; 851 852 case ARGTYPE_STRUCT: 853 parser = parse_struct; 854 break; 855 856 case ARGTYPE_POINTER: 857 /* Pointer syntax is not based on keyword, so we 858 * should never get this type. */ 859 assert(type != ARGTYPE_POINTER); 860 abort(); 861 } 862 863 struct arg_type_info *info = malloc(sizeof(*info)); 864 if (info == NULL) { 865 report_error(filename, line_no, 866 "malloc: %s", strerror(errno)); 867 return NULL; 868 } 869 *ownp = 1; 870 871 if (parser(str, info) < 0) { 872 free(info); 873 return NULL; 874 } 875 876 return info; 877} 878 879static struct named_lens { 880 const char *name; 881 struct lens *lens; 882} lenses[] = { 883 { "hide", &blind_lens }, 884 { "octal", &octal_lens }, 885 { "hex", &hex_lens }, 886 { "bool", &bool_lens }, 887 { "guess", &guess_lens }, 888}; 889 890static struct lens * 891name2lens(char **str, int *own_lensp) 892{ 893 size_t i; 894 for (i = 0; i < sizeof(lenses)/sizeof(*lenses); ++i) 895 if (try_parse_kwd(str, lenses[i].name) == 0) { 896 *own_lensp = 0; 897 return lenses[i].lens; 898 } 899 900 return NULL; 901} 902 903static struct arg_type_info * 904parse_type(char **str, struct param **extra_param, size_t param_num, int *ownp) 905{ 906 struct arg_type_info *info 907 = parse_nonpointer_type(str, extra_param, param_num, ownp); 908 if (info == NULL) 909 return NULL; 910 911 while (1) { 912 eat_spaces(str); 913 if (**str == '*') { 914 struct arg_type_info *outer = malloc(sizeof(*outer)); 915 if (outer == NULL) { 916 if (*ownp) { 917 type_destroy(info); 918 free(info); 919 } 920 report_error(filename, line_no, 921 "malloc: %s", strerror(errno)); 922 return NULL; 923 } 924 type_init_pointer(outer, info, *ownp); 925 *ownp = 1; 926 (*str)++; 927 info = outer; 928 } else 929 break; 930 } 931 return info; 932} 933 934static struct arg_type_info * 935parse_lens(char **str, struct param **extra_param, size_t param_num, int *ownp) 936{ 937 int own_lens; 938 struct lens *lens = name2lens(str, &own_lens); 939 int has_args = 1; 940 struct arg_type_info *info; 941 if (lens != NULL) { 942 eat_spaces(str); 943 944 /* Octal lens gets special treatment, because of 945 * backward compatibility. */ 946 if (lens == &octal_lens && **str != '(') { 947 has_args = 0; 948 info = type_get_simple(ARGTYPE_INT); 949 *ownp = 0; 950 } else if (parse_char(str, '(') < 0) { 951 report_error(filename, line_no, 952 "expected type argument after the lens"); 953 return NULL; 954 } 955 } 956 957 if (has_args) { 958 eat_spaces(str); 959 info = parse_type(str, extra_param, param_num, ownp); 960 if (info == NULL) { 961 fail: 962 if (own_lens && lens != NULL) 963 lens_destroy(lens); 964 return NULL; 965 } 966 } 967 968 if (lens != NULL && has_args) { 969 eat_spaces(str); 970 parse_char(str, ')'); 971 } 972 973 /* We can't modify shared types. Make a copy if we have a 974 * lens. */ 975 if (lens != NULL && unshare_type_info(&info, ownp) < 0) 976 goto fail; 977 978 if (lens != NULL) { 979 info->lens = lens; 980 info->own_lens = own_lens; 981 } 982 983 return info; 984} 985 986static int 987add_param(Function *fun, size_t *allocdp) 988{ 989 size_t allocd = *allocdp; 990 /* XXX +1 is for the extra_param handling hack. */ 991 if ((fun->num_params + 1) >= allocd) { 992 allocd = allocd > 0 ? 2 * allocd : 8; 993 void *na = realloc(fun->params, sizeof(*fun->params) * allocd); 994 if (na == NULL) 995 return -1; 996 997 fun->params = na; 998 *allocdp = allocd; 999 } 1000 return 0; 1001} 1002 1003static int 1004param_is_void(struct param *param) 1005{ 1006 return param->flavor == PARAM_FLAVOR_TYPE 1007 && param->u.type.type->type == ARGTYPE_VOID; 1008} 1009 1010static struct arg_type_info * 1011get_hidden_int(void) 1012{ 1013 char *str = strdup("hide(int)"); 1014 char *ptr = str; 1015 assert(str != NULL); 1016 int own; 1017 struct arg_type_info *info = parse_lens(&ptr, NULL, 0, &own); 1018 assert(info != NULL); 1019 free(str); 1020 return info; 1021} 1022 1023static Function * 1024process_line(char *buf) { 1025 char *str = buf; 1026 char *tmp; 1027 1028 line_no++; 1029 debug(3, "Reading line %d of `%s'", line_no, filename); 1030 eat_spaces(&str); 1031 1032 /* A comment or empty line. */ 1033 if (*str == ';' || *str == 0 || *str == '\n') 1034 return NULL; 1035 1036 if (strncmp(str, "typedef", 7) == 0) { 1037 parse_typedef(&str); 1038 return NULL; 1039 } 1040 1041 Function *fun = calloc(1, sizeof(*fun)); 1042 if (fun == NULL) { 1043 report_error(filename, line_no, 1044 "alloc function: %s", strerror(errno)); 1045 return NULL; 1046 } 1047 1048 fun->return_info = parse_lens(&str, NULL, 0, &fun->own_return_info); 1049 if (fun->return_info == NULL) { 1050 err: 1051 debug(3, " Skipping line %d", line_no); 1052 destroy_fun(fun); 1053 return NULL; 1054 } 1055 debug(4, " return_type = %d", fun->return_info->type); 1056 1057 eat_spaces(&str); 1058 tmp = start_of_arg_sig(str); 1059 if (tmp == NULL) { 1060 report_error(filename, line_no, "syntax error"); 1061 goto err; 1062 } 1063 *tmp = '\0'; 1064 fun->name = strdup(str); 1065 str = tmp + 1; 1066 debug(3, " name = %s", fun->name); 1067 1068 size_t allocd = 0; 1069 struct param *extra_param = NULL; 1070 1071 int have_stop = 0; 1072 1073 while (1) { 1074 eat_spaces(&str); 1075 if (*str == ')') 1076 break; 1077 1078 if (str[0] == '+') { 1079 if (have_stop == 0) { 1080 if (add_param(fun, &allocd) < 0) 1081 goto add_err; 1082 param_init_stop 1083 (&fun->params[fun->num_params++]); 1084 have_stop = 1; 1085 } 1086 str++; 1087 } 1088 1089 if (add_param(fun, &allocd) < 0) { 1090 add_err: 1091 report_error(filename, line_no, "(re)alloc params: %s", 1092 strerror(errno)); 1093 goto err; 1094 } 1095 1096 int own; 1097 struct arg_type_info *type 1098 = parse_lens(&str, &extra_param, 1099 fun->num_params - have_stop, &own); 1100 if (type == NULL) { 1101 report_error(filename, line_no, 1102 "unknown argument type"); 1103 goto err; 1104 } 1105 1106 param_init_type(&fun->params[fun->num_params++], type, own); 1107 1108 eat_spaces(&str); 1109 if (*str == ',') { 1110 str++; 1111 continue; 1112 } else if (*str == ')') { 1113 continue; 1114 } else { 1115 if (str[strlen(str) - 1] == '\n') 1116 str[strlen(str) - 1] = '\0'; 1117 report_error(filename, line_no, 1118 "syntax error around \"%s\"", str); 1119 goto err; 1120 } 1121 } 1122 1123 /* We used to allow void parameter as a synonym to an argument 1124 * that shouldn't be displayed. But backends really need to 1125 * know the exact type that they are dealing with. The proper 1126 * way to do this these days is to use the hide lens. 1127 * 1128 * So if there are any voids in the parameter list, show a 1129 * warning and assume that they are ints. If there's a sole 1130 * void, assume the function doesn't take any arguments. The 1131 * latter is conservative, we can drop the argument 1132 * altogether, instead of fetching and then not showing it, 1133 * without breaking any observable behavior. */ 1134 if (fun->num_params == 1 && param_is_void(&fun->params[0])) { 1135 if (0) 1136 /* Don't show this warning. Pre-0.7.0 1137 * ltrace.conf often used this idiom. This 1138 * should be postponed until much later, when 1139 * extant uses are likely gone. */ 1140 report_warning(filename, line_no, 1141 "sole void parameter ignored"); 1142 param_destroy(&fun->params[0]); 1143 fun->num_params = 0; 1144 } else { 1145 size_t i; 1146 for (i = 0; i < fun->num_params; ++i) { 1147 if (param_is_void(&fun->params[i])) { 1148 report_warning 1149 (filename, line_no, 1150 "void parameter assumed to be " 1151 "'hide(int)'"); 1152 1153 static struct arg_type_info *type = NULL; 1154 if (type == NULL) 1155 type = get_hidden_int(); 1156 param_destroy(&fun->params[i]); 1157 param_init_type(&fun->params[i], type, 0); 1158 } 1159 } 1160 } 1161 1162 if (extra_param != NULL) { 1163 assert(fun->num_params < allocd); 1164 memcpy(&fun->params[fun->num_params++], extra_param, 1165 sizeof(*extra_param)); 1166 free(extra_param); 1167 } 1168 1169 return fun; 1170} 1171 1172void 1173init_global_config(void) 1174{ 1175 struct arg_type_info *info = malloc(2 * sizeof(*info)); 1176 if (info == NULL) 1177 error(1, errno, "malloc in init_global_config"); 1178 1179 memset(info, 0, 2 * sizeof(*info)); 1180 info[0].type = ARGTYPE_POINTER; 1181 info[0].u.ptr_info.info = &info[1]; 1182 info[1].type = ARGTYPE_VOID; 1183 1184 insert_typedef(strdup("addr"), info, 0); 1185 insert_typedef(strdup("file"), info, 1); 1186} 1187 1188void 1189read_config_file(char *file) { 1190 FILE *stream; 1191 char buf[1024]; 1192 1193 filename = file; 1194 stream = fopen(filename, "r"); 1195 if (!stream) { 1196 return; 1197 } 1198 1199 debug(1, "Reading config file `%s'...", filename); 1200 1201 line_no = 0; 1202 while (fgets(buf, 1024, stream)) { 1203 Function *tmp; 1204 1205 tmp = process_line(buf); 1206 1207 if (tmp) { 1208 debug(2, "New function: `%s'", tmp->name); 1209 tmp->next = list_of_functions; 1210 list_of_functions = tmp; 1211 } 1212 } 1213 fclose(stream); 1214} 1215