Adapt ASLR to ltrace
[platform/upstream/ltrace.git] / printf.c
1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
4  * Copyright (C) 1998,2004,2007,2008,2009 Juan Cespedes
5  * Copyright (C) 2006 Steve Fink
6  * Copyright (C) 2006 Ian Wienand
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 #include <assert.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "printf.h"
30 #include "type.h"
31 #include "value.h"
32 #include "expr.h"
33 #include "zero.h"
34 #include "param.h"
35 #include "lens_default.h"
36
37 struct param_enum {
38         struct value array;
39         int percent;
40         size_t *future_length;
41         char *format;
42         char const *ptr;
43         char const *end;
44         size_t width;
45 };
46
47 static struct param_enum *
48 param_printf_init(struct value *cb_args, size_t nargs,
49                   struct value_dict *arguments)
50 {
51         assert(nargs == 1);
52
53         struct process *proc = cb_args[0].inferior;
54         assert(proc != NULL);
55
56         /* We expect a pointer to array.  */
57         if (cb_args->type->type != ARGTYPE_POINTER
58             || cb_args->type->u.ptr_info.info->type != ARGTYPE_ARRAY)
59                 return NULL;
60
61         /* The element type should be either character (for narrow
62          * strings) or an integral type (for wide strings).  */
63         struct arg_type_info *et
64                 = cb_args->type->u.ptr_info.info->u.array_info.elt_type;
65         switch (et->type) {
66         case ARGTYPE_CHAR:
67         case ARGTYPE_SHORT:
68         case ARGTYPE_USHORT:
69         case ARGTYPE_INT:
70         case ARGTYPE_UINT:
71         case ARGTYPE_LONG:
72         case ARGTYPE_ULONG:
73                 break;
74         default:
75                 return NULL;
76         }
77
78         struct param_enum *self = malloc(sizeof(*self));
79         if (self == NULL) {
80         fail:
81                 free(self);
82                 return NULL;
83         }
84         self->width = type_sizeof(proc, et);
85         if (self->width == (size_t) -1)
86                 goto fail;
87
88         if (value_init_deref(&self->array, cb_args) < 0)
89                 goto fail;
90         assert(self->array.type->type == ARGTYPE_ARRAY);
91
92         self->format = (char *)value_get_data(&self->array, arguments);
93         if (self->format == NULL) {
94                 value_destroy(&self->array);
95                 goto fail;
96         }
97
98         size_t size = value_size(&self->array, arguments);
99         if (size == (size_t)-1) {
100                 value_destroy(&self->array);
101                 goto fail;
102         }
103
104         self->percent = 0;
105         self->ptr = self->format;
106         self->end = self->format + size;
107         self->future_length = NULL;
108         return self;
109 }
110
111 static void
112 drop_future_length(struct param_enum *self)
113 {
114         if (self->future_length != NULL) {
115                 free(self->future_length);
116                 self->future_length = NULL;
117         }
118 }
119
120 static int
121 form_next_param(struct param_enum *self,
122                 enum arg_type format_type, enum arg_type elt_type,
123                 unsigned hlf, unsigned lng, char *len_buf, size_t len_buf_len,
124                 struct arg_type_info *infop)
125 {
126         /* XXX note: Some types are wrong because we lack
127            ARGTYPE_LONGLONG, ARGTYPE_UCHAR and ARGTYPE_SCHAR.  */
128         assert(lng <= 2);
129         assert(hlf <= 2);
130         static enum arg_type ints[] =
131                 { ARGTYPE_CHAR, ARGTYPE_SHORT, ARGTYPE_INT,
132                   ARGTYPE_LONG, ARGTYPE_ULONG };
133         static enum arg_type uints[] =
134                 { ARGTYPE_CHAR, ARGTYPE_USHORT, ARGTYPE_UINT,
135                   ARGTYPE_ULONG, ARGTYPE_ULONG };
136
137         struct arg_type_info *elt_info = NULL;
138         if (format_type == ARGTYPE_ARRAY || format_type == ARGTYPE_POINTER)
139                 elt_info = type_get_simple(elt_type);
140         else if (format_type == ARGTYPE_INT)
141                 format_type = ints[2 + lng - hlf];
142         else if (format_type == ARGTYPE_UINT)
143                 format_type = uints[2 + lng - hlf];
144
145
146         if (format_type == ARGTYPE_ARRAY) {
147                 struct arg_type_info *array = malloc(sizeof(*array));
148                 if (array == NULL)
149                         return -1;
150
151                 struct expr_node *node = NULL;
152                 int own_node;
153                 if (len_buf_len != 0
154                     || self->future_length != NULL) {
155                         struct tmp {
156                                 struct expr_node node;
157                                 struct arg_type_info type;
158                         };
159                         struct tmp *len = malloc(sizeof(*len));
160                         if (len == NULL) {
161                         fail:
162                                 free(len);
163                                 free(array);
164                                 return -1;
165                         }
166
167                         len->type = *type_get_simple(ARGTYPE_LONG);
168
169                         long l;
170                         if (self->future_length != NULL) {
171                                 l = *self->future_length;
172                                 drop_future_length(self);
173                         } else {
174                                 l = atol(len_buf);
175                         }
176
177                         expr_init_const_word(&len->node, l, &len->type, 0);
178
179                         node = build_zero_w_arg(&len->node, 1);
180                         if (node == NULL)
181                                 goto fail;
182                         own_node = 1;
183
184                 } else {
185                         node = expr_node_zero();
186                         own_node = 0;
187                 }
188                 assert(node != NULL);
189
190                 type_init_array(array, elt_info, 0, node, own_node);
191                 type_init_pointer(infop, array, 1);
192
193         } else if (format_type == ARGTYPE_POINTER) {
194                 type_init_pointer(infop, elt_info, 0);
195
196         } else {
197                 *infop = *type_get_simple(format_type);
198         }
199
200         return 0;
201 }
202
203 static int
204 param_printf_next(struct param_enum *self, struct arg_type_info *infop,
205                   int *insert_stop)
206 {
207         unsigned hlf = 0;
208         unsigned lng = 0;
209         enum arg_type format_type = ARGTYPE_VOID;
210         enum arg_type elt_type = ARGTYPE_VOID;
211         char len_buf[25] = {};
212         size_t len_buf_len = 0;
213         struct lens *lens = NULL;
214
215         for (; self->ptr < self->end; self->ptr += self->width) {
216                 union {
217                         uint8_t u8;
218                         uint16_t u16;
219                         uint32_t u32;
220                         uint64_t u64;
221                         char buf[0];
222                 } u;
223                 memcpy(u.buf, self->ptr, self->width);
224                 switch (self->width) {
225                 case 1: u.u64 = u.u8; break;
226                 case 2: u.u64 = u.u16; break;
227                 case 4: u.u64 = u.u32; break;
228                 }
229                 uint64_t c = u.u64;
230
231                 if (!self->percent) {
232                         if (c == '%')
233                                 self->percent = 1;
234                         continue;
235                 }
236
237                 switch (c) {
238                 case '#': case ' ': case '-':
239                 case '+': case 'I': case '\'':
240                         /* These are only important for formatting,
241                          * not for interpreting the type.  */
242                         continue;
243
244                 case '*':
245                         /* Length parameter given in the next
246                          * argument.  */
247                         if (self->future_length == NULL)
248                                 /* This should really be an assert,
249                                  * but we can't just fail on invalid
250                                  * format string.  */
251                                 self->future_length
252                                         = malloc(sizeof(*self->future_length));
253
254                         if (self->future_length != NULL) {
255                                 self->ptr += self->width;
256                                 format_type = ARGTYPE_INT;
257                                 break;
258                         }
259
260                 case '0':
261                 case '1': case '2': case '3':
262                 case '4': case '5': case '6':
263                 case '7': case '8': case '9':
264                         /* Field length likewise, but we need to parse
265                          * this to attach the appropriate string
266                          * length expression.  */
267                         if (len_buf_len < sizeof(len_buf) - 1)
268                                 len_buf[len_buf_len++] = c;
269                         continue;
270
271                 case 'h':
272                         if (hlf < 2)
273                                 hlf++;
274                         continue;
275
276                 case 'l':
277                         if (lng < 2)
278                                 lng++;
279                         continue;
280
281                 case 'q':
282                         lng = 2;
283                         continue;
284
285                 case 'L': /* long double */
286                         lng = 1;
287                         continue;
288
289                 case 'j': /* intmax_t */
290                         /*   XXX ABI should know */
291                         lng = 2;
292                         continue;
293
294                 case 't': /* ptrdiff_t */
295                 case 'Z': case 'z': /* size_t */
296                         lng = 1; /* XXX ABI should tell */
297                         continue;
298
299                 case 'd':
300                 case 'i':
301                         format_type = ARGTYPE_INT;
302                         self->percent = 0;
303                         break;
304
305                 case 'o':
306                         lens = &octal_lens;
307                         goto uint;
308
309                 case 'x': case 'X':
310                         lens = &hex_lens;
311                         /* Fall through.  */
312                 case 'u':
313                 uint:
314                         format_type = ARGTYPE_UINT;
315                         self->percent = 0;
316                         break;
317
318                 case 'e': case 'E':
319                 case 'f': case 'F':
320                 case 'g': case 'G':
321                 case 'a': case 'A':
322                         format_type = ARGTYPE_DOUBLE;
323                         self->percent = 0;
324                         break;
325
326                 case 'C': /* like "lc" */
327                         if (lng == 0)
328                                 lng++;
329                 case 'c':
330                         /* XXX "lc" means wchar_t string.  */
331                         format_type = ARGTYPE_CHAR;
332                         self->percent = 0;
333                         break;
334
335                 case 'S': /* like "ls" */
336                         if (lng == 0)
337                                 lng++;
338                 case 's':
339                         format_type = ARGTYPE_ARRAY;
340                         elt_type = lng == 0 ? ARGTYPE_CHAR : ARGTYPE_INT;
341                         self->percent = 0;
342                         lens = &string_lens;
343                         break;
344
345                 case 'p':
346                 case 'n': /* int* where to store no. of printed chars.  */
347                         format_type = ARGTYPE_POINTER;
348                         elt_type = ARGTYPE_VOID;
349                         self->percent = 0;
350                         break;
351
352                 case 'm': /* (glibc) print argument of errno */
353                 case '%':
354                         lng = 0;
355                         hlf = 0;
356                         self->percent = 0;
357                         continue;
358
359                 default:
360                         continue;
361                 }
362
363                 /* If we got here, the type must have been set.  */
364                 assert(format_type != ARGTYPE_VOID);
365
366                 if (form_next_param(self, format_type, elt_type, hlf, lng,
367                                     len_buf, len_buf_len, infop) < 0)
368                         return -1;
369
370                 infop->lens = lens;
371                 infop->own_lens = 0;
372
373                 return 0;
374         }
375
376         *infop = *type_get_simple(ARGTYPE_VOID);
377         return 0;
378 }
379
380 static enum param_status
381 param_printf_stop(struct param_enum *self, struct value *value)
382 {
383         if (self->future_length != NULL
384             && value_extract_word(value, (long *)self->future_length, NULL) < 0)
385                 drop_future_length(self);
386
387         return PPCB_CONT;
388 }
389
390 static void
391 param_printf_done(struct param_enum *context)
392 {
393         value_destroy(&context->array);
394         free(context);
395 }
396
397 void
398 param_pack_init_printf(struct param *param, struct expr_node *arg, int own_arg)
399 {
400         param_init_pack(param, PARAM_PACK_VARARGS, arg, 1, own_arg,
401                         &param_printf_init, &param_printf_next,
402                         &param_printf_stop, &param_printf_done);
403 }