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
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
27 #define _POSIX_C_SOURCE 200809L
42 #include "prototype.h"
46 #include "lens_default.h"
47 #include "lens_enum.h"
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. */
59 #define CTYPE_CONV(CH) \
60 (sizeof(CH) == sizeof(unsigned char) ? (int)(unsigned char)(CH) : (int)(CH))
68 static struct arg_type_info *parse_nonpointer_type(struct protolib *plib,
71 struct param **extra_param,
73 int *ownp, int *forwardp);
74 static struct arg_type_info *parse_type(struct protolib *plib,
76 char **str, struct param **extra_param,
77 size_t param_num, int *ownp,
79 static struct arg_type_info *parse_lens(struct protolib *plib,
81 char **str, struct param **extra_param,
82 size_t param_num, int *ownp,
84 static int parse_enum(struct protolib *plib, struct locus *loc,
85 char **str, struct arg_type_info **retp, int *ownp);
87 struct prototype *list_of_functions = NULL;
90 parse_arg_type(char **name, enum arg_type *ret)
93 enum arg_type candidate;
95 #define KEYWORD(KWD, TYPE) \
97 if (strncmp(*name, KWD, sizeof(KWD) - 1) == 0) { \
98 rest = *name + sizeof(KWD) - 1; \
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);
117 /* Misspelling of int used in ltrace.conf that we used to
119 KEYWORD("itn", ARGTYPE_INT);
121 assert(rest == NULL);
127 if (isalnum(CTYPE_CONV(*rest)) || *rest == '_')
136 eat_spaces(char **str) {
137 while (**str == ' ') {
143 xstrndup(char *str, size_t len) {
144 char *ret = (char *) malloc(len + 1);
146 report_global_error("malloc: %s", strerror(errno));
149 strncpy(ret, str, len);
155 parse_ident(struct locus *loc, char **str)
159 if (!isalpha(CTYPE_CONV(**str)) && **str != '_') {
160 report_error(loc->filename, loc->line_no, "bad identifier");
164 while (**str && (isalnum(CTYPE_CONV(**str)) || **str == '_')) {
168 return xstrndup(ident, *str - ident);
172 parse_int(struct locus *loc, char **str, long *ret)
175 long n = strtol(*str, &end, 0);
177 report_error(loc->filename, loc->line_no, "bad number");
188 check_nonnegative(struct locus *loc, long l)
191 report_error(loc->filename, loc->line_no,
192 "expected non-negative value, got %ld", l);
199 check_int(struct locus *loc, long l)
203 report_error(loc->filename, loc->line_no,
204 "Number too large: %ld", l);
211 parse_char(struct locus *loc, char **str, char expected)
213 if (**str != expected) {
214 report_error(loc->filename, loc->line_no,
215 "expected '%c', got '%c'", expected, **str);
223 static struct expr_node *parse_argnum(struct locus *loc,
224 char **str, int *ownp, int zero);
226 static struct expr_node *
227 parse_zero(struct locus *loc, char **str, int *ownp)
233 struct expr_node *arg = parse_argnum(loc, str, &own, 0);
236 if (parse_char(loc, str, ')') < 0) {
243 struct expr_node *ret = build_zero_w_arg(arg, own);
251 return expr_node_zero();
256 wrap_in_zero(struct expr_node **nodep)
258 struct expr_node *n = build_zero_w_arg(*nodep, 1);
267 * argN : The value of argument #N, counting from 1
268 * eltN : The value of element #N of the containing structure
269 * retval : The return value
270 * N : The numeric value N
272 static struct expr_node *
273 parse_argnum(struct locus *loc, char **str, int *ownp, int zero)
275 struct expr_node *expr = malloc(sizeof(*expr));
279 if (isdigit(CTYPE_CONV(**str))) {
281 if (parse_int(loc, str, &l) < 0
282 || check_nonnegative(loc, l) < 0
283 || check_int(loc, l) < 0)
286 expr_init_const_word(expr, l, type_get_simple(ARGTYPE_LONG), 0);
288 if (zero && wrap_in_zero(&expr) < 0)
295 char *const name = parse_ident(loc, str);
302 int is_arg = strncmp(name, "arg", 3) == 0;
303 if (is_arg || strncmp(name, "elt", 3) == 0) {
305 char *num = name + 3;
306 if (parse_int(loc, &num, &l) < 0
307 || check_int(loc, l) < 0)
312 expr_init_named(expr, "retval", 0);
314 expr_init_argno(expr, l - 1);
316 struct expr_node *e_up = malloc(sizeof(*e_up));
317 struct expr_node *e_ix = malloc(sizeof(*e_ix));
318 if (e_up == NULL || e_ix == NULL) {
324 expr_init_up(e_up, expr_self(), 0);
325 struct arg_type_info *ti
326 = type_get_simple(ARGTYPE_LONG);
327 expr_init_const_word(e_ix, l - 1, ti, 0);
328 expr_init_index(expr, e_up, 1, e_ix, 1);
331 } else if (strcmp(name, "retval") == 0) {
332 expr_init_named(expr, "retval", 0);
334 } else if (strcmp(name, "zero") == 0) {
335 struct expr_node *ret
336 = parse_zero(loc, str, ownp);
344 report_error(loc->filename, loc->line_no,
345 "Unknown length specifier: '%s'", name);
349 if (zero && wrap_in_zero(&expr) < 0)
362 static struct arg_type_info *
363 parse_typedef_name(struct protolib *plib, char **str)
366 while (*end && (isalnum(CTYPE_CONV(*end)) || *end == '_'))
371 size_t len = end - *str;
373 memcpy(buf, *str, len);
377 struct named_type *nt = protolib_lookup_type(plib, buf, true);
384 parse_typedef(struct protolib *plib, struct locus *loc, char **str)
386 (*str) += strlen("typedef");
388 char *name = parse_ident(loc, str);
390 /* Look through the typedef list whether we already have a
391 * forward of this type. If we do, it must be forward
393 struct named_type *forward = protolib_lookup_type(plib, name, true);
395 && (forward->info->type != ARGTYPE_STRUCT
396 || !forward->forward)) {
397 report_error(loc->filename, loc->line_no,
398 "Redefinition of typedef '%s'", name);
406 if (parse_char(loc, str, '=') < 0)
412 struct arg_type_info *info
413 = parse_lens(plib, loc, str, NULL, 0, &own, &fwd);
417 struct named_type this_nt;
418 named_type_init(&this_nt, info, own);
419 this_nt.forward = fwd;
421 if (forward == NULL) {
422 if (protolib_add_named_type(plib, name, 1, &this_nt) < 0) {
423 named_type_destroy(&this_nt);
429 /* If we are defining a forward, make sure the definition is a
430 * structure as well. */
431 if (this_nt.info->type != ARGTYPE_STRUCT) {
432 report_error(loc->filename, loc->line_no,
433 "Definition of forward '%s' must be a structure.",
435 named_type_destroy(&this_nt);
439 /* Now move guts of the actual type over to the forward type.
440 * We can't just move pointers around, because references to
441 * forward must stay intact. */
442 assert(this_nt.own_type);
443 type_destroy(forward->info);
444 *forward->info = *this_nt.info;
445 forward->forward = 0;
451 /* Syntax: struct ( type,type,type,... ) */
453 parse_struct(struct protolib *plib, struct locus *loc,
454 char **str, struct arg_type_info *info,
460 if (forwardp == NULL) {
461 report_error(loc->filename, loc->line_no,
462 "Forward struct can be declared only "
463 "directly after a typedef.");
467 /* Forward declaration is currently handled as an
469 type_init_struct(info);
474 if (parse_char(loc, str, '(') < 0)
477 eat_spaces(str); // Empty arg list with whitespace inside
479 type_init_struct(info);
483 if (**str == 0 || **str == ')') {
484 parse_char(loc, str, ')');
488 /* Field delimiter. */
489 if (type_struct_size(info) > 0)
490 parse_char(loc, str, ',');
494 struct arg_type_info *field
495 = parse_lens(plib, loc, str, NULL, 0, &own, NULL);
496 if (field == NULL || type_struct_add(info, field, own)) {
503 /* Make a copy of INFO and set the *OWN bit if it's not already
506 unshare_type_info(struct locus *loc, struct arg_type_info **infop, int *ownp)
511 struct arg_type_info *ninfo = malloc(sizeof(*ninfo));
512 if (ninfo == NULL || type_clone(ninfo, *infop) < 0) {
513 report_error(loc->filename, loc->line_no,
514 "malloc: %s", strerror(errno));
524 parse_string(struct protolib *plib, struct locus *loc,
525 char **str, struct arg_type_info **retp, int *ownp)
527 struct arg_type_info *info = NULL;
528 struct expr_node *length;
531 if (isdigit(CTYPE_CONV(**str))) {
532 /* string0 is string[retval], length is zero(retval)
533 * stringN is string[argN], length is zero(argN) */
535 if (parse_int(loc, str, &l) < 0
536 || check_int(loc, l) < 0)
539 struct expr_node *length_arg = malloc(sizeof(*length_arg));
540 if (length_arg == NULL)
544 expr_init_named(length_arg, "retval", 0);
546 expr_init_argno(length_arg, l - 1);
548 length = build_zero_w_arg(length_arg, 1);
549 if (length == NULL) {
550 expr_destroy(length_arg);
562 length = parse_argnum(loc, str, &own_length, 1);
567 parse_char(loc, str, ']');
569 } else if (**str == '(') {
570 /* Usage of "string" as lens. */
574 info = parse_type(plib, loc, str, NULL, 0, ownp, NULL);
582 parse_char(loc, str, ')');
585 /* It was just a simple string after all. */
586 length = expr_node_zero();
591 /* String is a pointer to array of chars. */
593 struct arg_type_info *info1 = malloc(sizeof(*info1));
594 struct arg_type_info *info2 = malloc(sizeof(*info2));
595 if (info1 == NULL || info2 == NULL) {
600 assert(length != NULL);
601 expr_destroy(length);
606 type_init_array(info2, type_get_simple(ARGTYPE_CHAR), 0,
608 type_init_pointer(info1, info2, 1);
614 /* We'll need to set the lens, so unshare. */
615 if (unshare_type_info(loc, &info, ownp) < 0)
616 /* If unshare_type_info failed, it must have been as a
617 * result of cloning attempt because *OWNP was 0.
618 * Thus we don't need to destroy INFO. */
621 info->lens = &string_lens;
629 build_printf_pack(struct locus *loc, struct param **packp, size_t param_num)
632 report_error(loc->filename, loc->line_no,
633 "'format' type in unexpected context");
636 if (*packp != NULL) {
637 report_error(loc->filename, loc->line_no,
638 "only one 'format' type per function supported");
642 *packp = malloc(sizeof(**packp));
646 struct expr_node *node = malloc(sizeof(*node));
653 expr_init_argno(node, param_num);
655 param_pack_init_printf(*packp, node, 1);
660 /* Match and consume KWD if it's next in stream, and return 0.
661 * Otherwise return negative number. */
663 try_parse_kwd(char **str, const char *kwd)
665 size_t len = strlen(kwd);
666 if (strncmp(*str, kwd, len) == 0
667 && !isalnum(CTYPE_CONV((*str)[len]))
668 && (*str)[len] != '_') {
675 /* XXX EXTRA_PARAM and PARAM_NUM are a kludge to get in
676 * backward-compatible support for "format" parameter type. The
677 * latter is only valid if the former is non-NULL, which is only in
678 * top-level context. */
680 parse_alias(struct protolib *plib, struct locus *loc,
681 char **str, struct arg_type_info **retp, int *ownp,
682 struct param **extra_param, size_t param_num)
684 /* For backward compatibility, we need to support things like
685 * stringN (which is like string[argN], string[N], and also
686 * bare string. We might, in theory, replace this by
687 * preprocessing configure file sources with M4, but for now,
688 * "string" is syntax. */
689 if (strncmp(*str, "string", 6) == 0) {
691 return parse_string(plib, loc, str, retp, ownp);
693 } else if (try_parse_kwd(str, "format") >= 0
694 && extra_param != NULL) {
695 /* For backward compatibility, format is parsed as
696 * "string", but it smuggles to the parameter list of
697 * a function a "printf" argument pack with this
698 * parameter as argument. */
699 if (parse_string(plib, loc, str, retp, ownp) < 0)
702 return build_printf_pack(loc, extra_param, param_num);
704 } else if (try_parse_kwd(str, "enum") >=0) {
706 return parse_enum(plib, loc, str, retp, ownp);
714 /* Syntax: array ( type, N|argN ) */
716 parse_array(struct protolib *plib, struct locus *loc,
717 char **str, struct arg_type_info *info)
720 if (parse_char(loc, str, '(') < 0)
725 struct arg_type_info *elt_info
726 = parse_lens(plib, loc, str, NULL, 0, &own, NULL);
727 if (elt_info == NULL)
731 parse_char(loc, str, ',');
735 struct expr_node *length = parse_argnum(loc, str, &own_length, 0);
736 if (length == NULL) {
738 type_destroy(elt_info);
744 type_init_array(info, elt_info, own, length, own_length);
747 parse_char(loc, str, ')');
752 * enum (keyname[=value],keyname[=value],... )
753 * enum<type> (keyname[=value],keyname[=value],... )
756 parse_enum(struct protolib *plib, struct locus *loc, char **str,
757 struct arg_type_info **retp, int *ownp)
759 /* Optional type argument. */
762 parse_char(loc, str, '[');
764 *retp = parse_nonpointer_type(plib, loc, str, NULL, 0, ownp, 0);
768 if (!type_is_integral((*retp)->type)) {
769 report_error(loc->filename, loc->line_no,
770 "integral type required as enum argument");
773 /* This also releases associated lens
774 * if any was set so far. */
782 if (parse_char(loc, str, ']') < 0)
786 *retp = type_get_simple(ARGTYPE_INT);
790 /* We'll need to set the lens, so unshare. */
791 if (unshare_type_info(loc, retp, ownp) < 0)
795 if (parse_char(loc, str, '(') < 0)
798 struct enum_lens *lens = malloc(sizeof(*lens));
800 report_error(loc->filename, loc->line_no,
801 "malloc enum lens: %s", strerror(errno));
805 lens_init_enum(lens);
806 (*retp)->lens = &lens->super;
807 (*retp)->own_lens = 1;
812 if (**str == 0 || **str == ')') {
813 parse_char(loc, str, ')');
817 /* Field delimiter. XXX should we support the C
818 * syntax, where the enumeration can end in pending
820 if (lens_enum_size(lens) > 0)
821 parse_char(loc, str, ',');
824 char *key = parse_ident(loc, str);
834 if (parse_int(loc, str, &last_val) < 0)
838 struct value *value = malloc(sizeof(*value));
841 value_init_detached(value, NULL, *retp, 0);
842 value_set_word(value, last_val);
844 if (lens_enum_add(lens, key, 1, value, 1) < 0)
853 static struct arg_type_info *
854 parse_nonpointer_type(struct protolib *plib, struct locus *loc,
855 char **str, struct param **extra_param, size_t param_num,
856 int *ownp, int *forwardp)
858 const char *orig_str = *str;
860 if (parse_arg_type(str, &type) < 0) {
861 struct arg_type_info *type;
862 if (parse_alias(plib, loc, str, &type,
863 ownp, extra_param, param_num) < 0)
865 else if (type != NULL)
869 if ((type = parse_typedef_name(plib, str)) == NULL)
870 report_error(loc->filename, loc->line_no,
871 "unknown type around '%s'", orig_str);
875 /* For some types that's all we need. */
888 return type_get_simple(type);
894 case ARGTYPE_POINTER:
895 /* Pointer syntax is not based on keyword, so we
896 * should never get this type. */
897 assert(type != ARGTYPE_POINTER);
901 struct arg_type_info *info = malloc(sizeof(*info));
903 report_error(loc->filename, loc->line_no,
904 "malloc: %s", strerror(errno));
909 if (type == ARGTYPE_ARRAY) {
910 if (parse_array(plib, loc, str, info) < 0) {
916 assert(type == ARGTYPE_STRUCT);
917 if (parse_struct(plib, loc, str, info, forwardp) < 0)
924 static struct named_lens {
928 { "hide", &blind_lens },
929 { "octal", &octal_lens },
930 { "oct", &octal_lens },
931 { "bitvec", &bitvect_lens },
932 { "hex", &hex_lens },
933 { "bool", &bool_lens },
934 { "guess", &guess_lens },
938 name2lens(char **str, int *own_lensp)
941 for (i = 0; i < sizeof(lenses)/sizeof(*lenses); ++i)
942 if (try_parse_kwd(str, lenses[i].name) == 0) {
944 return lenses[i].lens;
950 static struct arg_type_info *
951 parse_type(struct protolib *plib, struct locus *loc, char **str,
952 struct param **extra_param, size_t param_num,
953 int *ownp, int *forwardp)
955 struct arg_type_info *info
956 = parse_nonpointer_type(plib, loc, str, extra_param,
957 param_num, ownp, forwardp);
964 struct arg_type_info *outer = malloc(sizeof(*outer));
970 report_error(loc->filename, loc->line_no,
971 "malloc: %s", strerror(errno));
974 type_init_pointer(outer, info, *ownp);
984 static struct arg_type_info *
985 parse_lens(struct protolib *plib, struct locus *loc,
986 char **str, struct param **extra_param,
987 size_t param_num, int *ownp, int *forwardp)
990 struct lens *lens = name2lens(str, &own_lens);
992 struct arg_type_info *info;
996 /* Octal lens gets special treatment, because of
997 * backward compatibility. */
998 if (lens == &octal_lens && **str != '(') {
1000 info = type_get_simple(ARGTYPE_INT);
1002 } else if (parse_char(loc, str, '(') < 0) {
1003 report_error(loc->filename, loc->line_no,
1004 "expected type argument after the lens");
1011 info = parse_type(plib, loc, str, extra_param, param_num,
1015 if (own_lens && lens != NULL)
1021 if (lens != NULL && has_args) {
1023 parse_char(loc, str, ')');
1026 /* We can't modify shared types. Make a copy if we have a
1028 if (lens != NULL && unshare_type_info(loc, &info, ownp) < 0)
1033 info->own_lens = own_lens;
1040 param_is_void(struct param *param)
1042 return param->flavor == PARAM_FLAVOR_TYPE
1043 && param->u.type.type->type == ARGTYPE_VOID;
1046 static struct arg_type_info *
1047 get_hidden_int(void)
1049 static struct arg_type_info info, *pinfo = NULL;
1053 info = *type_get_simple(ARGTYPE_INT);
1054 info.lens = &blind_lens;
1060 static enum callback_status
1061 void_to_hidden_int(struct prototype *proto, struct param *param, void *data)
1063 struct locus *loc = data;
1064 if (param_is_void(param)) {
1065 report_warning(loc->filename, loc->line_no,
1066 "void parameter assumed to be 'hide(int)'");
1068 static struct arg_type_info *type = NULL;
1070 type = get_hidden_int();
1071 param_destroy(param);
1072 param_init_type(param, type, 0);
1078 process_line(struct protolib *plib, struct locus *loc, char *buf)
1082 debug(3, "Reading line %d of `%s'", loc->line_no, loc->filename);
1085 /* A comment or empty line. */
1086 if (*str == ';' || *str == 0 || *str == '\n' || *str == '#')
1089 if (strncmp(str, "typedef", 7) == 0) {
1090 parse_typedef(plib, loc, &str);
1094 struct prototype fun;
1095 prototype_init(&fun);
1097 struct param *extra_param = NULL;
1098 char *proto_name = NULL;
1100 fun.return_info = parse_lens(plib, loc, &str, NULL, 0, &own, NULL);
1101 if (fun.return_info == NULL) {
1103 debug(3, " Skipping line %d", loc->line_no);
1105 if (extra_param != NULL) {
1106 param_destroy(extra_param);
1110 prototype_destroy(&fun);
1114 fun.own_return_info = own;
1115 debug(4, " return_type = %d", fun.return_info->type);
1118 proto_name = parse_ident(loc, &str);
1119 if (proto_name == NULL)
1123 if (parse_char(loc, &str, '(') < 0)
1125 debug(3, " name = %s", proto_name);
1134 if (str[0] == '+') {
1135 if (have_stop == 0) {
1137 param_init_stop(¶m);
1138 if (prototype_push_param(&fun, ¶m) < 0) {
1140 report_error(loc->filename,
1142 "%s", strerror(errno));
1151 size_t param_num = prototype_num_params(&fun) - have_stop;
1152 struct arg_type_info *type
1153 = parse_lens(plib, loc, &str, &extra_param,
1154 param_num, &own, NULL);
1156 report_error(loc->filename, loc->line_no,
1157 "unknown argument type");
1162 param_init_type(¶m, type, own);
1163 if (prototype_push_param(&fun, ¶m) < 0)
1170 } else if (*str == ')') {
1173 if (str[strlen(str) - 1] == '\n')
1174 str[strlen(str) - 1] = '\0';
1175 report_error(loc->filename, loc->line_no,
1176 "syntax error around \"%s\"", str);
1181 /* We used to allow void parameter as a synonym to an argument
1182 * that shouldn't be displayed. But backends really need to
1183 * know the exact type that they are dealing with. The proper
1184 * way to do this these days is to use the hide lens.
1186 * So if there are any voids in the parameter list, show a
1187 * warning and assume that they are ints. If there's a sole
1188 * void, assume the function doesn't take any arguments. The
1189 * latter is conservative, we can drop the argument
1190 * altogether, instead of fetching and then not showing it,
1191 * without breaking any observable behavior. */
1192 if (prototype_num_params(&fun) == 1
1193 && param_is_void(prototype_get_nth_param(&fun, 0))) {
1195 /* Don't show this warning. Pre-0.7.0
1196 * ltrace.conf often used this idiom. This
1197 * should be postponed until much later, when
1198 * extant uses are likely gone. */
1199 report_warning(loc->filename, loc->line_no,
1200 "sole void parameter ignored");
1201 prototype_destroy_nth_param(&fun, 0);
1203 prototype_each_param(&fun, NULL, void_to_hidden_int, loc);
1206 if (extra_param != NULL) {
1207 prototype_push_param(&fun, extra_param);
1212 if (protolib_add_prototype(plib, proto_name, 1, &fun) < 0) {
1213 report_error(loc->filename, loc->line_no,
1214 "couldn't add prototype: %s",
1223 read_config_file(FILE *stream, const char *path, struct protolib *plib)
1225 debug(DEBUG_FUNCTION, "Reading config file `%s'...", path);
1227 struct locus loc = { path, 0 };
1230 while (getline(&line, &len, stream) >= 0) {
1232 process_line(plib, &loc, line);