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