• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA
19  */
20 
21 #include <string.h>
22 #include <assert.h>
23 #include <errno.h>
24 #include <stdlib.h>
25 
26 #include "expr.h"
27 
28 static void
expr_init_common(struct expr_node * node,enum expr_node_kind kind)29 expr_init_common(struct expr_node *node, enum expr_node_kind kind)
30 {
31 	node->kind = kind;
32 	node->lhs = NULL;
33 	node->own_lhs = 0;
34 	memset(&node->u, 0, sizeof(node->u));
35 }
36 
37 void
expr_init_self(struct expr_node * node)38 expr_init_self(struct expr_node *node)
39 {
40 	expr_init_common(node, EXPR_OP_SELF);
41 }
42 
43 void
expr_init_named(struct expr_node * node,const char * name,int own_name)44 expr_init_named(struct expr_node *node,
45 		const char *name, int own_name)
46 {
47 	expr_init_common(node, EXPR_OP_NAMED);
48 	node->u.name.s = name;
49 	node->u.name.own = own_name;
50 }
51 
52 void
expr_init_argno(struct expr_node * node,size_t num)53 expr_init_argno(struct expr_node *node, size_t num)
54 {
55 	expr_init_common(node, EXPR_OP_ARGNO);
56 	node->u.num = num;
57 }
58 
59 void
expr_init_const(struct expr_node * node,struct value * val)60 expr_init_const(struct expr_node *node, struct value *val)
61 {
62 	expr_init_common(node, EXPR_OP_CONST);
63 	node->u.value = *val;
64 }
65 
66 void
expr_init_const_word(struct expr_node * node,long l,struct arg_type_info * type,int own_type)67 expr_init_const_word(struct expr_node *node, long l,
68 		     struct arg_type_info *type, int own_type)
69 {
70 	struct value val;
71 	value_init_detached(&val, NULL, type, own_type);
72 	value_set_word(&val, l);
73 	expr_init_const(node, &val);
74 }
75 
76 void
expr_init_index(struct expr_node * node,struct expr_node * lhs,int own_lhs,struct expr_node * rhs,int own_rhs)77 expr_init_index(struct expr_node *node,
78 		struct expr_node *lhs, int own_lhs,
79 		struct expr_node *rhs, int own_rhs)
80 {
81 	expr_init_common(node, EXPR_OP_INDEX);
82 	node->lhs = lhs;
83 	node->own_lhs = own_lhs;
84 	node->u.node.n = rhs;
85 	node->u.node.own = own_rhs;
86 }
87 
88 void
expr_init_up(struct expr_node * node,struct expr_node * lhs,int own_lhs)89 expr_init_up(struct expr_node *node, struct expr_node *lhs, int own_lhs)
90 {
91 	assert(lhs != NULL);
92 	expr_init_common(node, EXPR_OP_UP);
93 	node->lhs = lhs;
94 	node->own_lhs = own_lhs;
95 }
96 
97 void
expr_init_cb1(struct expr_node * node,int (* cb)(struct value * ret_value,struct value * value,struct value_dict * arguments,void * data),struct expr_node * lhs,int own_lhs,void * data)98 expr_init_cb1(struct expr_node *node,
99 	      int (*cb)(struct value *ret_value, struct value *value,
100 			struct value_dict *arguments, void *data),
101 	      struct expr_node *lhs, int own_lhs, void *data)
102 {
103 	expr_init_common(node, EXPR_OP_CALL1);
104 	node->lhs = lhs;
105 	node->own_lhs = own_lhs;
106 	node->u.call.u.cb1 = cb;
107 	node->u.call.data = data;
108 }
109 
110 void
expr_init_cb2(struct expr_node * node,int (* cb)(struct value * ret_value,struct value * lhs,struct value * rhs,struct value_dict * arguments,void * data),struct expr_node * lhs,int own_lhs,struct expr_node * rhs,int own_rhs,void * data)111 expr_init_cb2(struct expr_node *node,
112 	      int (*cb)(struct value *ret_value,
113 			struct value *lhs, struct value *rhs,
114 			struct value_dict *arguments, void *data),
115 	      struct expr_node *lhs, int own_lhs,
116 	      struct expr_node *rhs, int own_rhs, void *data)
117 {
118 	expr_init_common(node, EXPR_OP_CALL2);
119 	node->lhs = lhs;
120 	node->own_lhs = own_lhs;
121 	node->u.call.rhs = rhs;
122 	node->u.call.own_rhs = own_rhs;
123 	node->u.call.u.cb2 = cb;
124 	node->u.call.data = data;
125 }
126 
127 static void
release_expr(struct expr_node * node,int own)128 release_expr(struct expr_node *node, int own)
129 {
130 	if (own) {
131 		expr_destroy(node);
132 		free(node);
133 	}
134 }
135 
136 void
expr_destroy(struct expr_node * node)137 expr_destroy(struct expr_node *node)
138 {
139 	if (node == NULL)
140 		return;
141 
142 	switch (node->kind) {
143 	case EXPR_OP_ARGNO:
144 	case EXPR_OP_SELF:
145 		return;
146 
147 	case EXPR_OP_CONST:
148 		value_destroy(&node->u.value);
149 		return;
150 
151 	case EXPR_OP_NAMED:
152 		if (node->u.name.own)
153 			free((char *)node->u.name.s);
154 		return;
155 
156 	case EXPR_OP_INDEX:
157 		release_expr(node->lhs, node->own_lhs);
158 		release_expr(node->u.node.n, node->u.node.own);
159 		return;
160 
161 	case EXPR_OP_CALL2:
162 		release_expr(node->u.call.rhs, node->u.call.own_rhs);
163 		/* Fall through.  */
164 	case EXPR_OP_UP:
165 	case EXPR_OP_CALL1:
166 		release_expr(node->lhs, node->own_lhs);
167 		return;
168 	}
169 
170 	assert(!"Invalid value of node kind");
171 	abort();
172 }
173 
174 static int
expr_alloc_and_clone(struct expr_node ** retpp,struct expr_node * node,int own)175 expr_alloc_and_clone(struct expr_node **retpp, struct expr_node *node, int own)
176 {
177 	*retpp = node;
178 	if (own) {
179 		*retpp = malloc(sizeof **retpp);
180 		if (*retpp == NULL || expr_clone(*retpp, node) < 0) {
181 			free(*retpp);
182 			return -1;
183 		}
184 	}
185 	return 0;
186 }
187 
188 int
expr_clone(struct expr_node * retp,const struct expr_node * node)189 expr_clone(struct expr_node *retp, const struct expr_node *node)
190 {
191 	*retp = *node;
192 
193 	switch (node->kind) {
194 		struct expr_node *nlhs;
195 		struct expr_node *nrhs;
196 
197 	case EXPR_OP_ARGNO:
198 	case EXPR_OP_SELF:
199 		return 0;
200 
201 	case EXPR_OP_CONST:
202 		return value_clone(&retp->u.value, &node->u.value);
203 
204 	case EXPR_OP_NAMED:
205 		if (node->u.name.own
206 		    && (retp->u.name.s = strdup(node->u.name.s)) == NULL)
207 			return -1;
208 		return 0;
209 
210 	case EXPR_OP_INDEX:
211 		if (expr_alloc_and_clone(&nlhs, node->lhs, node->own_lhs) < 0)
212 			return -1;
213 
214 		if (expr_alloc_and_clone(&nrhs, node->u.node.n,
215 					 node->u.node.own) < 0) {
216 			if (nlhs != node->lhs) {
217 				expr_destroy(nlhs);
218 				free(nlhs);
219 			}
220 			return -1;
221 		}
222 
223 		retp->lhs = nlhs;
224 		retp->u.node.n = nrhs;
225 		return 0;
226 
227 	case EXPR_OP_CALL2:
228 		if (expr_alloc_and_clone(&nrhs, node->u.call.rhs,
229 					 node->u.call.own_rhs) < 0)
230 			return -1;
231 		retp->u.call.rhs = nrhs;
232 		/* Fall through.  */
233 
234 	case EXPR_OP_UP:
235 	case EXPR_OP_CALL1:
236 		if (expr_alloc_and_clone(&nlhs, node->lhs, node->own_lhs) < 0) {
237 			if (node->kind == EXPR_OP_CALL2
238 			    && node->u.call.own_rhs) {
239 				expr_destroy(nrhs);
240 				free(nrhs);
241 				return -1;
242 			}
243 		}
244 
245 		retp->lhs = nlhs;
246 		return 0;
247 	}
248 
249 	assert(!"Invalid value of node kind");
250 	abort();
251 }
252 
253 int
expr_is_compile_constant(struct expr_node * node)254 expr_is_compile_constant(struct expr_node *node)
255 {
256 	return node->kind == EXPR_OP_CONST;
257 }
258 
259 static int
eval_up(struct expr_node * node,struct value * context,struct value_dict * arguments,struct value * ret_value)260 eval_up(struct expr_node *node, struct value *context,
261 	struct value_dict *arguments, struct value *ret_value)
262 {
263 	if (expr_eval(node->lhs, context, arguments, ret_value) < 0)
264 		return -1;
265 	struct value *parent = value_get_parental_struct(ret_value);
266 	if (parent == NULL) {
267 		value_destroy(ret_value);
268 		return -1;
269 	}
270 	*ret_value = *parent;
271 	return 0;
272 }
273 
274 static int
eval_cb1(struct expr_node * node,struct value * context,struct value_dict * arguments,struct value * ret_value)275 eval_cb1(struct expr_node *node, struct value *context,
276 	 struct value_dict *arguments, struct value *ret_value)
277 {
278 	struct value val;
279 	if (expr_eval(node->lhs, context, arguments, &val) < 0)
280 		return -1;
281 
282 	int ret = 0;
283 	if (node->u.call.u.cb1(ret_value, &val, arguments,
284 			       node->u.call.data) < 0)
285 		ret = -1;
286 
287 	/* N.B. the callback must return its own value, or somehow
288 	 * clone the incoming argument.  */
289 	value_destroy(&val);
290 	return ret;
291 }
292 
293 static int
eval_cb2(struct expr_node * node,struct value * context,struct value_dict * arguments,struct value * ret_value)294 eval_cb2(struct expr_node *node, struct value *context,
295 	 struct value_dict *arguments, struct value *ret_value)
296 {
297 	struct value lhs;
298 	if (expr_eval(node->lhs, context, arguments, &lhs) < 0)
299 		return -1;
300 
301 	struct value rhs;
302 	if (expr_eval(node->u.call.rhs, context, arguments, &rhs) < 0) {
303 		value_destroy(&lhs);
304 		return -1;
305 	}
306 
307 	int ret = 0;
308 	if (node->u.call.u.cb2(ret_value, &lhs, &rhs, arguments,
309 			       node->u.call.data) < 0)
310 		ret = -1;
311 
312 	/* N.B. the callback must return its own value, or somehow
313 	 * clone the incoming argument.  */
314 	value_destroy(&lhs);
315 	value_destroy(&rhs);
316 	return ret;
317 }
318 
319 int
eval_index(struct expr_node * node,struct value * context,struct value_dict * arguments,struct value * ret_value)320 eval_index(struct expr_node *node, struct value *context,
321 	   struct value_dict *arguments, struct value *ret_value)
322 {
323 	struct value lhs;
324 	if (expr_eval(node->lhs, context, arguments, &lhs) < 0)
325 		return -1;
326 
327 	long l;
328 	if (expr_eval_word(node->u.node.n, context, arguments, &l) < 0) {
329 	fail:
330 		value_destroy(&lhs);
331 		return -1;
332 	}
333 
334 	if (value_init_element(ret_value, &lhs, (size_t)l) < 0)
335 		goto fail;
336 	return 0;
337 }
338 
339 int
expr_eval(struct expr_node * node,struct value * context,struct value_dict * arguments,struct value * ret_value)340 expr_eval(struct expr_node *node, struct value *context,
341 	  struct value_dict *arguments, struct value *ret_value)
342 {
343 	switch (node->kind) {
344 		struct value *valp;
345 	case EXPR_OP_ARGNO:
346 		valp = val_dict_get_num(arguments, node->u.num);
347 		if (valp == NULL)
348 			return -1;
349 		*ret_value = *valp;
350 		return 0;
351 
352 	case EXPR_OP_NAMED:
353 		valp = val_dict_get_name(arguments, node->u.name.s);
354 		if (valp == NULL)
355 			return -1;
356 		*ret_value = *valp;
357 		return 0;
358 
359 	case EXPR_OP_SELF:
360 		*ret_value = *context;
361 		return 0;
362 
363 	case EXPR_OP_CONST:
364 		*ret_value = node->u.value;
365 		return 0;
366 
367 	case EXPR_OP_INDEX:
368 		return eval_index(node, context, arguments, ret_value);
369 
370 	case EXPR_OP_UP:
371 		return eval_up(node, context, arguments, ret_value);
372 
373 	case EXPR_OP_CALL1:
374 		return eval_cb1(node, context, arguments, ret_value);
375 
376 	case EXPR_OP_CALL2:
377 		return eval_cb2(node, context, arguments, ret_value);
378 	}
379 
380 	assert(!"Unknown node kind.");
381 	abort();
382 }
383 
384 int
expr_eval_word(struct expr_node * node,struct value * context,struct value_dict * arguments,long * ret_value)385 expr_eval_word(struct expr_node *node, struct value *context,
386 	       struct value_dict *arguments, long *ret_value)
387 {
388 	struct value val;
389 	if (expr_eval(node, context, arguments, &val) < 0)
390 		return -1;
391 	int ret = 0;
392 	if (value_extract_word(&val, ret_value, arguments) < 0)
393 		ret = -1;
394 	value_destroy(&val);
395 	return ret;
396 }
397 
398 int
expr_eval_constant(struct expr_node * node,long * valuep)399 expr_eval_constant(struct expr_node *node, long *valuep)
400 {
401 	assert(expr_is_compile_constant(node));
402 	return expr_eval_word(node, NULL, NULL, valuep);
403 }
404 
405 struct expr_node *
expr_self(void)406 expr_self(void)
407 {
408 	static struct expr_node *nodep = NULL;
409 	if (nodep == NULL) {
410 		static struct expr_node node;
411 		expr_init_self(&node);
412 		nodep = &node;
413 	}
414 	return nodep;
415 }
416