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
parse_arg_type(char ** name,enum arg_type * ret)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
eat_spaces(char ** str)136 eat_spaces(char **str) {
137 	while (**str == ' ') {
138 		(*str)++;
139 	}
140 }
141 
142 static char *
xstrndup(char * str,size_t len)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 *
parse_ident(struct locus * loc,char ** str)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 *
start_of_arg_sig(char * str)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
parse_int(struct locus * loc,char ** str,long * ret)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
check_nonnegative(struct locus * loc,long l)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
check_int(struct locus * loc,long l)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
parse_char(struct locus * loc,char ** str,char expected)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 *
parse_zero(struct locus * loc,char ** str,int * ownp)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
wrap_in_zero(struct expr_node ** nodep)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 *
parse_argnum(struct locus * loc,char ** str,int * ownp,int zero)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 *
parse_typedef_name(struct protolib * plib,char ** str)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
parse_typedef(struct protolib * plib,struct locus * loc,char ** str)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
parse_struct(struct protolib * plib,struct locus * loc,char ** str,struct arg_type_info * info,int * forwardp)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
unshare_type_info(struct locus * loc,struct arg_type_info ** infop,int * ownp)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
parse_string(struct protolib * plib,struct locus * loc,char ** str,struct arg_type_info ** retp,int * ownp)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
build_printf_pack(struct locus * loc,struct param ** packp,size_t param_num)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
try_parse_kwd(char ** str,const char * kwd)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
parse_alias(struct protolib * plib,struct locus * loc,char ** str,struct arg_type_info ** retp,int * ownp,struct param ** extra_param,size_t param_num)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
parse_array(struct protolib * plib,struct locus * loc,char ** str,struct arg_type_info * info)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
parse_enum(struct protolib * plib,struct locus * loc,char ** str,struct arg_type_info ** retp,int * ownp)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 *
parse_nonpointer_type(struct protolib * plib,struct locus * loc,char ** str,struct param ** extra_param,size_t param_num,int * ownp,int * forwardp)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 *
name2lens(char ** str,int * own_lensp)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 *
parse_type(struct protolib * plib,struct locus * loc,char ** str,struct param ** extra_param,size_t param_num,int * ownp,int * forwardp)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 *
parse_lens(struct protolib * plib,struct locus * loc,char ** str,struct param ** extra_param,size_t param_num,int * ownp,int * forwardp)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
param_is_void(struct param * param)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 *
get_hidden_int(void)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
void_to_hidden_int(struct prototype * proto,struct param * param,void * data)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
process_line(struct protolib * plib,struct locus * loc,char * buf)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(&param);
1180 				if (prototype_push_param(&fun, &param) < 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(&param, type, own);
1200 		if (prototype_push_param(&fun, &param) < 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
read_config_file(FILE * stream,const char * path,struct protolib * plib)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