2 * This file is part of ltrace.
3 * Copyright (C) 2011,2012,2013,2014 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
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.
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.
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
39 #include "prototype.h"
43 #include "lens_default.h"
44 #include "lens_enum.h"
46 /* Lifted from GCC: The ctype functions are often implemented as
47 * macros which do lookups in arrays using the parameter as the
48 * offset. If the ctype function parameter is a char, then gcc will
49 * (appropriately) warn that a "subscript has type char". Using a
50 * (signed) char as a subscript is bad because you may get negative
51 * offsets and thus it is not 8-bit safe. The CTYPE_CONV macro
52 * ensures that the parameter is cast to an unsigned char when a char
53 * is passed in. When an int is passed in, the parameter is left
54 * alone so we don't lose EOF. */
56 #define CTYPE_CONV(CH) \
57 (sizeof(CH) == sizeof(unsigned char) ? (int)(unsigned char)(CH) : (int)(CH))
65 static struct arg_type_info *parse_nonpointer_type(struct protolib *plib,
68 struct param **extra_param,
70 int *ownp, int *forwardp);
71 static struct arg_type_info *parse_type(struct protolib *plib,
73 char **str, struct param **extra_param,
74 size_t param_num, int *ownp,
76 static struct arg_type_info *parse_lens(struct protolib *plib,
78 char **str, struct param **extra_param,
79 size_t param_num, int *ownp,
81 static int parse_enum(struct protolib *plib, struct locus *loc,
82 char **str, struct arg_type_info **retp, int *ownp);
84 struct prototype *list_of_functions = NULL;
87 parse_arg_type(char **name, enum arg_type *ret)
90 enum arg_type candidate;
92 #define KEYWORD(KWD, TYPE) \
94 if (strncmp(*name, KWD, sizeof(KWD) - 1) == 0) { \
95 rest = *name + sizeof(KWD) - 1; \
101 KEYWORD("void", ARGTYPE_VOID);
102 KEYWORD("int", ARGTYPE_INT);
103 KEYWORD("uint", ARGTYPE_UINT);
104 KEYWORD("long", ARGTYPE_LONG);
105 KEYWORD("ulong", ARGTYPE_ULONG);
106 KEYWORD("char", ARGTYPE_CHAR);
107 KEYWORD("short", ARGTYPE_SHORT);
108 KEYWORD("ushort", ARGTYPE_USHORT);
109 KEYWORD("float", ARGTYPE_FLOAT);
110 KEYWORD("double", ARGTYPE_DOUBLE);
111 KEYWORD("array", ARGTYPE_ARRAY);
112 KEYWORD("struct", ARGTYPE_STRUCT);
114 /* Misspelling of int used in ltrace.conf that we used to
116 KEYWORD("itn", ARGTYPE_INT);
118 assert(rest == NULL);
124 if (isalnum(CTYPE_CONV(*rest)) || *rest == '_')
133 eat_spaces(char **str) {
134 while (**str == ' ') {
140 xstrndup(char *str, size_t len) {
141 char *ret = (char *) malloc(len + 1);
143 report_global_error("malloc: %s", strerror(errno));
146 strncpy(ret, str, len);
152 parse_ident(struct locus *loc, char **str)
156 if (!isalpha(CTYPE_CONV(**str)) && **str != '_') {
157 report_error(loc->filename, loc->line_no, "bad identifier");
161 while (**str && (isalnum(CTYPE_CONV(**str)) || **str == '_')) {
165 return xstrndup(ident, *str - ident);
169 parse_int(struct locus *loc, char **str, long *ret)
172 long n = strtol(*str, &end, 0);
174 report_error(loc->filename, loc->line_no, "bad number");
185 check_nonnegative(struct locus *loc, long l)
188 report_error(loc->filename, loc->line_no,
189 "expected non-negative value, got %ld", l);
196 check_int(struct locus *loc, long l)
200 report_error(loc->filename, loc->line_no,
201 "Number too large: %ld", l);
208 parse_char(struct locus *loc, char **str, char expected)
210 if (**str != expected) {
211 report_error(loc->filename, loc->line_no,
212 "expected '%c', got '%c'", expected, **str);
220 static struct expr_node *parse_argnum(struct locus *loc,
221 char **str, int *ownp, int zero);
223 static struct expr_node *
224 parse_zero(struct locus *loc, char **str, int *ownp)
230 struct expr_node *arg = parse_argnum(loc, str, &own, 0);
233 if (parse_char(loc, str, ')') < 0) {
240 struct expr_node *ret = build_zero_w_arg(arg, own);
248 return expr_node_zero();
253 wrap_in_zero(struct expr_node **nodep)
255 struct expr_node *n = build_zero_w_arg(*nodep, 1);
264 * argN : The value of argument #N, counting from 1
265 * eltN : The value of element #N of the containing structure
266 * retval : The return value
267 * N : The numeric value N
269 static struct expr_node *
270 parse_argnum(struct locus *loc, char **str, int *ownp, int zero)
272 struct expr_node *expr = malloc(sizeof(*expr));
276 if (isdigit(CTYPE_CONV(**str))) {
278 if (parse_int(loc, str, &l) < 0
279 || check_nonnegative(loc, l) < 0
280 || check_int(loc, l) < 0)
283 expr_init_const_word(expr, l, type_get_simple(ARGTYPE_LONG), 0);
285 if (zero && wrap_in_zero(&expr) < 0)
292 char *const name = parse_ident(loc, str);
299 int is_arg = strncmp(name, "arg", 3) == 0;
300 if (is_arg || strncmp(name, "elt", 3) == 0) {
302 char *num = name + 3;
303 if (parse_int(loc, &num, &l) < 0
304 || check_int(loc, l) < 0)
309 expr_init_named(expr, "retval", 0);
311 expr_init_argno(expr, l - 1);
313 struct expr_node *e_up = malloc(sizeof(*e_up));
314 struct expr_node *e_ix = malloc(sizeof(*e_ix));
315 if (e_up == NULL || e_ix == NULL) {
321 expr_init_up(e_up, expr_self(), 0);
322 struct arg_type_info *ti
323 = type_get_simple(ARGTYPE_LONG);
324 expr_init_const_word(e_ix, l - 1, ti, 0);
325 expr_init_index(expr, e_up, 1, e_ix, 1);
328 } else if (strcmp(name, "retval") == 0) {
329 expr_init_named(expr, "retval", 0);
331 } else if (strcmp(name, "zero") == 0) {
332 struct expr_node *ret
333 = parse_zero(loc, str, ownp);
341 report_error(loc->filename, loc->line_no,
342 "Unknown length specifier: '%s'", name);
346 if (zero && wrap_in_zero(&expr) < 0)
359 static struct arg_type_info *
360 parse_typedef_name(struct protolib *plib, char **str)
363 while (*end && (isalnum(CTYPE_CONV(*end)) || *end == '_'))
368 size_t len = end - *str;
370 memcpy(buf, *str, len);
374 struct named_type *nt = protolib_lookup_type(plib, buf, true);
381 parse_typedef(struct protolib *plib, struct locus *loc, char **str)
383 (*str) += strlen("typedef");
385 char *name = parse_ident(loc, str);
387 /* Look through the typedef list whether we already have a
388 * forward of this type. If we do, it must be forward
390 struct named_type *forward = protolib_lookup_type(plib, name, true);
392 && (forward->info->type != ARGTYPE_STRUCT
393 || !forward->forward)) {
394 report_error(loc->filename, loc->line_no,
395 "Redefinition of typedef '%s'", name);
403 if (parse_char(loc, str, '=') < 0)
409 struct arg_type_info *info
410 = parse_lens(plib, loc, str, NULL, 0, &own, &fwd);
414 struct named_type this_nt;
415 named_type_init(&this_nt, info, own);
416 this_nt.forward = fwd;
418 if (forward == NULL) {
419 if (protolib_add_named_type(plib, name, 1, &this_nt) < 0) {
420 named_type_destroy(&this_nt);
426 /* If we are defining a forward, make sure the definition is a
427 * structure as well. */
428 if (this_nt.info->type != ARGTYPE_STRUCT) {
429 report_error(loc->filename, loc->line_no,
430 "Definition of forward '%s' must be a structure.",
432 named_type_destroy(&this_nt);
436 /* Now move guts of the actual type over to the forward type.
437 * We can't just move pointers around, because references to
438 * forward must stay intact. */
439 assert(this_nt.own_type);
440 type_destroy(forward->info);
441 *forward->info = *this_nt.info;
442 forward->forward = 0;
448 /* Syntax: struct ( type,type,type,... ) */
450 parse_struct(struct protolib *plib, struct locus *loc,
451 char **str, struct arg_type_info *info,
457 if (forwardp == NULL) {
458 report_error(loc->filename, loc->line_no,
459 "Forward struct can be declared only "
460 "directly after a typedef.");
464 /* Forward declaration is currently handled as an
466 type_init_struct(info);
471 if (parse_char(loc, str, '(') < 0)
474 eat_spaces(str); // Empty arg list with whitespace inside
476 type_init_struct(info);
480 if (**str == 0 || **str == ')') {
481 parse_char(loc, str, ')');
485 /* Field delimiter. */
486 if (type_struct_size(info) > 0)
487 parse_char(loc, str, ',');
491 struct arg_type_info *field
492 = parse_lens(plib, loc, str, NULL, 0, &own, NULL);
493 if (field == NULL || type_struct_add(info, field, own)) {
500 /* Make a copy of INFO and set the *OWN bit if it's not already
503 unshare_type_info(struct locus *loc, struct arg_type_info **infop, int *ownp)
508 struct arg_type_info *ninfo = malloc(sizeof(*ninfo));
509 if (ninfo == NULL || type_clone(ninfo, *infop) < 0) {
510 report_error(loc->filename, loc->line_no,
511 "malloc: %s", strerror(errno));
521 parse_string(struct protolib *plib, struct locus *loc,
522 char **str, struct arg_type_info **retp, int *ownp)
524 struct arg_type_info *info = NULL;
525 struct expr_node *length;
528 if (isdigit(CTYPE_CONV(**str))) {
529 /* string0 is string[retval], length is zero(retval)
530 * stringN is string[argN], length is zero(argN) */
532 if (parse_int(loc, str, &l) < 0
533 || check_int(loc, l) < 0)
536 struct expr_node *length_arg = malloc(sizeof(*length_arg));
537 if (length_arg == NULL)
541 expr_init_named(length_arg, "retval", 0);
543 expr_init_argno(length_arg, l - 1);
545 length = build_zero_w_arg(length_arg, 1);
546 if (length == NULL) {
547 expr_destroy(length_arg);
559 length = parse_argnum(loc, str, &own_length, 1);
564 parse_char(loc, str, ']');
566 } else if (**str == '(') {
567 /* Usage of "string" as lens. */
571 info = parse_type(plib, loc, str, NULL, 0, ownp, NULL);
579 parse_char(loc, str, ')');
582 /* It was just a simple string after all. */
583 length = expr_node_zero();
588 /* String is a pointer to array of chars. */
590 struct arg_type_info *info1 = malloc(sizeof(*info1));
591 struct arg_type_info *info2 = malloc(sizeof(*info2));
592 if (info1 == NULL || info2 == NULL) {
597 assert(length != NULL);
598 expr_destroy(length);
603 type_init_array(info2, type_get_simple(ARGTYPE_CHAR), 0,
605 type_init_pointer(info1, info2, 1);
611 /* We'll need to set the lens, so unshare. */
612 if (unshare_type_info(loc, &info, ownp) < 0)
613 /* If unshare_type_info failed, it must have been as a
614 * result of cloning attempt because *OWNP was 0.
615 * Thus we don't need to destroy INFO. */
618 info->lens = &string_lens;
626 build_printf_pack(struct locus *loc, struct param **packp, size_t param_num)
629 report_error(loc->filename, loc->line_no,
630 "'format' type in unexpected context");
633 if (*packp != NULL) {
634 report_error(loc->filename, loc->line_no,
635 "only one 'format' type per function supported");
639 *packp = malloc(sizeof(**packp));
643 struct expr_node *node = malloc(sizeof(*node));
650 expr_init_argno(node, param_num);
652 param_pack_init_printf(*packp, node, 1);
657 /* Match and consume KWD if it's next in stream, and return 0.
658 * Otherwise return negative number. */
660 try_parse_kwd(char **str, const char *kwd)
662 size_t len = strlen(kwd);
663 if (strncmp(*str, kwd, len) == 0
664 && !isalnum(CTYPE_CONV((*str)[len]))
665 && (*str)[len] != '_') {
672 /* XXX EXTRA_PARAM and PARAM_NUM are a kludge to get in
673 * backward-compatible support for "format" parameter type. The
674 * latter is only valid if the former is non-NULL, which is only in
675 * top-level context. */
677 parse_alias(struct protolib *plib, struct locus *loc,
678 char **str, struct arg_type_info **retp, int *ownp,
679 struct param **extra_param, size_t param_num)
681 /* For backward compatibility, we need to support things like
682 * stringN (which is like string[argN], string[N], and also
683 * bare string. We might, in theory, replace this by
684 * preprocessing configure file sources with M4, but for now,
685 * "string" is syntax. */
686 if (strncmp(*str, "string", 6) == 0) {
688 return parse_string(plib, loc, str, retp, ownp);
690 } else if (try_parse_kwd(str, "format") >= 0
691 && extra_param != NULL) {
692 /* For backward compatibility, format is parsed as
693 * "string", but it smuggles to the parameter list of
694 * a function a "printf" argument pack with this
695 * parameter as argument. */
696 if (parse_string(plib, loc, str, retp, ownp) < 0)
699 return build_printf_pack(loc, extra_param, param_num);
701 } else if (try_parse_kwd(str, "enum") >=0) {
703 return parse_enum(plib, loc, str, retp, ownp);
711 /* Syntax: array ( type, N|argN ) */
713 parse_array(struct protolib *plib, struct locus *loc,
714 char **str, struct arg_type_info *info)
717 if (parse_char(loc, str, '(') < 0)
722 struct arg_type_info *elt_info
723 = parse_lens(plib, loc, str, NULL, 0, &own, NULL);
724 if (elt_info == NULL)
728 parse_char(loc, str, ',');
732 struct expr_node *length = parse_argnum(loc, str, &own_length, 0);
733 if (length == NULL) {
735 type_destroy(elt_info);
741 type_init_array(info, elt_info, own, length, own_length);
744 parse_char(loc, str, ')');
749 * enum (keyname[=value],keyname[=value],... )
750 * enum<type> (keyname[=value],keyname[=value],... )
753 parse_enum(struct protolib *plib, struct locus *loc, char **str,
754 struct arg_type_info **retp, int *ownp)
756 /* Optional type argument. */
759 parse_char(loc, str, '[');
761 *retp = parse_nonpointer_type(plib, loc, str, NULL, 0, ownp, 0);
765 if (!type_is_integral((*retp)->type)) {
766 report_error(loc->filename, loc->line_no,
767 "integral type required as enum argument");
770 /* This also releases associated lens
771 * if any was set so far. */
779 if (parse_char(loc, str, ']') < 0)
783 *retp = type_get_simple(ARGTYPE_INT);
787 /* We'll need to set the lens, so unshare. */
788 if (unshare_type_info(loc, retp, ownp) < 0)
792 if (parse_char(loc, str, '(') < 0)
795 struct enum_lens *lens = malloc(sizeof(*lens));
797 report_error(loc->filename, loc->line_no,
798 "malloc enum lens: %s", strerror(errno));
802 lens_init_enum(lens);
803 (*retp)->lens = &lens->super;
804 (*retp)->own_lens = 1;
809 if (**str == 0 || **str == ')') {
810 parse_char(loc, str, ')');
814 /* Field delimiter. XXX should we support the C
815 * syntax, where the enumeration can end in pending
817 if (lens_enum_size(lens) > 0)
818 parse_char(loc, str, ',');
821 char *key = parse_ident(loc, str);
831 if (parse_int(loc, str, &last_val) < 0)
835 struct value *value = malloc(sizeof(*value));
838 value_init_detached(value, NULL, *retp, 0);
839 value_set_word(value, last_val);
841 if (lens_enum_add(lens, key, 1, value, 1) < 0)
850 static struct arg_type_info *
851 parse_nonpointer_type(struct protolib *plib, struct locus *loc,
852 char **str, struct param **extra_param, size_t param_num,
853 int *ownp, int *forwardp)
855 const char *orig_str = *str;
857 if (parse_arg_type(str, &type) < 0) {
858 struct arg_type_info *type;
859 if (parse_alias(plib, loc, str, &type,
860 ownp, extra_param, param_num) < 0)
862 else if (type != NULL)
866 if ((type = parse_typedef_name(plib, str)) == NULL)
867 report_error(loc->filename, loc->line_no,
868 "unknown type around '%s'", orig_str);
872 /* For some types that's all we need. */
885 return type_get_simple(type);
891 case ARGTYPE_POINTER:
892 /* Pointer syntax is not based on keyword, so we
893 * should never get this type. */
894 assert(type != ARGTYPE_POINTER);
898 struct arg_type_info *info = malloc(sizeof(*info));
900 report_error(loc->filename, loc->line_no,
901 "malloc: %s", strerror(errno));
906 if (type == ARGTYPE_ARRAY) {
907 if (parse_array(plib, loc, str, info) < 0) {
913 assert(type == ARGTYPE_STRUCT);
914 if (parse_struct(plib, loc, str, info, forwardp) < 0)
921 static struct named_lens {
925 { "hide", &blind_lens },
926 { "octal", &octal_lens },
927 { "oct", &octal_lens },
928 { "bitvec", &bitvect_lens },
929 { "hex", &hex_lens },
930 { "bool", &bool_lens },
931 { "guess", &guess_lens },
935 name2lens(char **str, int *own_lensp)
938 for (i = 0; i < sizeof(lenses)/sizeof(*lenses); ++i)
939 if (try_parse_kwd(str, lenses[i].name) == 0) {
941 return lenses[i].lens;
947 static struct arg_type_info *
948 parse_type(struct protolib *plib, struct locus *loc, char **str,
949 struct param **extra_param, size_t param_num,
950 int *ownp, int *forwardp)
952 struct arg_type_info *info
953 = parse_nonpointer_type(plib, loc, str, extra_param,
954 param_num, ownp, forwardp);
961 struct arg_type_info *outer = malloc(sizeof(*outer));
967 report_error(loc->filename, loc->line_no,
968 "malloc: %s", strerror(errno));
971 type_init_pointer(outer, info, *ownp);
981 static struct arg_type_info *
982 parse_lens(struct protolib *plib, struct locus *loc,
983 char **str, struct param **extra_param,
984 size_t param_num, int *ownp, int *forwardp)
987 struct lens *lens = name2lens(str, &own_lens);
989 struct arg_type_info *info;
993 /* Octal lens gets special treatment, because of
994 * backward compatibility. */
995 if (lens == &octal_lens && **str != '(') {
997 info = type_get_simple(ARGTYPE_INT);
999 } else if (parse_char(loc, str, '(') < 0) {
1000 report_error(loc->filename, loc->line_no,
1001 "expected type argument after the lens");
1008 info = parse_type(plib, loc, str, extra_param, param_num,
1012 if (own_lens && lens != NULL)
1018 if (lens != NULL && has_args) {
1020 parse_char(loc, str, ')');
1023 /* We can't modify shared types. Make a copy if we have a
1025 if (lens != NULL && unshare_type_info(loc, &info, ownp) < 0)
1030 info->own_lens = own_lens;
1037 param_is_void(struct param *param)
1039 return param->flavor == PARAM_FLAVOR_TYPE
1040 && param->u.type.type->type == ARGTYPE_VOID;
1043 static struct arg_type_info *
1044 get_hidden_int(void)
1046 static struct arg_type_info info, *pinfo = NULL;
1050 info = *type_get_simple(ARGTYPE_INT);
1051 info.lens = &blind_lens;
1057 static enum callback_status
1058 void_to_hidden_int(struct prototype *proto, struct param *param, void *data)
1060 struct locus *loc = data;
1061 if (param_is_void(param)) {
1062 report_warning(loc->filename, loc->line_no,
1063 "void parameter assumed to be 'hide(int)'");
1065 static struct arg_type_info *type = NULL;
1067 type = get_hidden_int();
1068 param_destroy(param);
1069 param_init_type(param, type, 0);
1075 process_line(struct protolib *plib, struct locus *loc, char *buf)
1079 debug(3, "Reading line %d of `%s'", loc->line_no, loc->filename);
1082 /* A comment or empty line. */
1083 if (*str == ';' || *str == 0 || *str == '\n' || *str == '#')
1086 if (strncmp(str, "typedef", 7) == 0) {
1087 parse_typedef(plib, loc, &str);
1091 struct prototype fun;
1092 prototype_init(&fun);
1094 struct param *extra_param = NULL;
1095 char *proto_name = NULL;
1097 fun.return_info = parse_lens(plib, loc, &str, NULL, 0, &own, NULL);
1098 if (fun.return_info == NULL) {
1100 debug(3, " Skipping line %d", loc->line_no);
1102 if (extra_param != NULL) {
1103 param_destroy(extra_param);
1107 prototype_destroy(&fun);
1111 fun.own_return_info = own;
1112 debug(4, " return_type = %d", fun.return_info->type);
1115 proto_name = parse_ident(loc, &str);
1116 if (proto_name == NULL)
1120 if (parse_char(loc, &str, '(') < 0)
1122 debug(3, " name = %s", proto_name);
1131 if (str[0] == '+') {
1132 if (have_stop == 0) {
1134 param_init_stop(¶m);
1135 if (prototype_push_param(&fun, ¶m) < 0) {
1137 report_error(loc->filename,
1139 "%s", strerror(errno));
1148 size_t param_num = prototype_num_params(&fun) - have_stop;
1149 struct arg_type_info *type
1150 = parse_lens(plib, loc, &str, &extra_param,
1151 param_num, &own, NULL);
1153 report_error(loc->filename, loc->line_no,
1154 "unknown argument type");
1159 param_init_type(¶m, type, own);
1160 if (prototype_push_param(&fun, ¶m) < 0)
1167 } else if (*str == ')') {
1170 if (str[strlen(str) - 1] == '\n')
1171 str[strlen(str) - 1] = '\0';
1172 report_error(loc->filename, loc->line_no,
1173 "syntax error around \"%s\"", str);
1178 /* We used to allow void parameter as a synonym to an argument
1179 * that shouldn't be displayed. But backends really need to
1180 * know the exact type that they are dealing with. The proper
1181 * way to do this these days is to use the hide lens.
1183 * So if there are any voids in the parameter list, show a
1184 * warning and assume that they are ints. If there's a sole
1185 * void, assume the function doesn't take any arguments. The
1186 * latter is conservative, we can drop the argument
1187 * altogether, instead of fetching and then not showing it,
1188 * without breaking any observable behavior. */
1189 if (prototype_num_params(&fun) == 1
1190 && param_is_void(prototype_get_nth_param(&fun, 0))) {
1192 /* Don't show this warning. Pre-0.7.0
1193 * ltrace.conf often used this idiom. This
1194 * should be postponed until much later, when
1195 * extant uses are likely gone. */
1196 report_warning(loc->filename, loc->line_no,
1197 "sole void parameter ignored");
1198 prototype_destroy_nth_param(&fun, 0);
1200 prototype_each_param(&fun, NULL, void_to_hidden_int, loc);
1203 if (extra_param != NULL) {
1204 prototype_push_param(&fun, extra_param);
1209 if (protolib_add_prototype(plib, proto_name, 1, &fun) < 0) {
1210 report_error(loc->filename, loc->line_no,
1211 "couldn't add prototype: %s",
1220 read_config_file(FILE *stream, const char *path, struct protolib *plib)
1222 debug(DEBUG_FUNCTION, "Reading config file `%s'...", path);
1224 struct locus loc = { path, 0 };
1227 while (getline(&line, &len, stream) >= 0) {
1229 process_line(plib, &loc, line);