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