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