blob: daa368301c0d2607ada911a68e00b7b15699a068 [file] [log] [blame]
Petr Machata940ec062012-01-06 22:43:51 +01001/*
2 * This file is part of ltrace.
Petr Machata0441baf2013-01-09 16:22:14 +01003 * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
Petr Machata940ec062012-01-06 22:43:51 +01004 * 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>
Petr Machatac00837c2013-11-11 02:24:42 +010025#include <stdint.h>
Petr Machata940ec062012-01-06 22:43:51 +010026#include <stdlib.h>
Petr Machatac00837c2013-11-11 02:24:42 +010027#include <string.h>
Petr Machata940ec062012-01-06 22:43:51 +010028
29#include "printf.h"
30#include "type.h"
31#include "value.h"
32#include "expr.h"
33#include "zero.h"
34#include "param.h"
Petr Machatae3f4a982012-01-09 04:27:26 +010035#include "lens_default.h"
Petr Machata940ec062012-01-06 22:43:51 +010036
37struct 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;
Petr Machatac00837c2013-11-11 02:24:42 +010044 size_t width;
Petr Machata940ec062012-01-06 22:43:51 +010045};
46
47static struct param_enum *
48param_printf_init(struct value *cb_args, size_t nargs,
49 struct value_dict *arguments)
50{
51 assert(nargs == 1);
52
Petr Machatac00837c2013-11-11 02:24:42 +010053 struct process *proc = cb_args[0].inferior;
54 assert(proc != NULL);
55
56 /* We expect a pointer to array. */
Petr Machatae3f4a982012-01-09 04:27:26 +010057 if (cb_args->type->type != ARGTYPE_POINTER
Petr Machatac00837c2013-11-11 02:24:42 +010058 || cb_args->type->u.ptr_info.info->type != ARGTYPE_ARRAY)
Petr Machata940ec062012-01-06 22:43:51 +010059 return NULL;
60
Petr Machatac00837c2013-11-11 02:24:42 +010061 /* 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
Petr Machata940ec062012-01-06 22:43:51 +010078 struct param_enum *self = malloc(sizeof(*self));
79 if (self == NULL) {
80 fail:
81 free(self);
82 return NULL;
83 }
Petr Machatac00837c2013-11-11 02:24:42 +010084 self->width = type_sizeof(proc, et);
85 if (self->width == (size_t) -1)
86 goto fail;
Petr Machata940ec062012-01-06 22:43:51 +010087
Petr Machatae3f4a982012-01-09 04:27:26 +010088 if (value_init_deref(&self->array, cb_args) < 0)
Petr Machata940ec062012-01-06 22:43:51 +010089 goto fail;
Petr Machata940ec062012-01-06 22:43:51 +010090 assert(self->array.type->type == ARGTYPE_ARRAY);
91
92 self->format = (char *)value_get_data(&self->array, arguments);
Petr Machata43417842012-10-29 17:59:17 +010093 if (self->format == NULL) {
94 value_destroy(&self->array);
Petr Machata940ec062012-01-06 22:43:51 +010095 goto fail;
Petr Machata43417842012-10-29 17:59:17 +010096 }
Petr Machata940ec062012-01-06 22:43:51 +010097
98 size_t size = value_size(&self->array, arguments);
Petr Machata43417842012-10-29 17:59:17 +010099 if (size == (size_t)-1) {
100 value_destroy(&self->array);
Petr Machata940ec062012-01-06 22:43:51 +0100101 goto fail;
Petr Machata43417842012-10-29 17:59:17 +0100102 }
Petr Machata940ec062012-01-06 22:43:51 +0100103
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
111static void
112drop_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
120static int
121form_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;
Petr Machatab7819162012-01-09 04:26:15 +0100138 if (format_type == ARGTYPE_ARRAY || format_type == ARGTYPE_POINTER)
Petr Machata940ec062012-01-06 22:43:51 +0100139 elt_info = type_get_simple(elt_type);
Petr Machatab7819162012-01-09 04:26:15 +0100140 else if (format_type == ARGTYPE_INT)
Petr Machata940ec062012-01-06 22:43:51 +0100141 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) {
Petr Machata84c86d72012-10-30 00:28:44 +0100147 struct arg_type_info *array = malloc(sizeof(*array));
148 if (array == NULL)
149 return -1;
150
Petr Machata940ec062012-01-06 22:43:51 +0100151 struct expr_node *node = NULL;
Petr Machata58e75f52012-10-30 00:22:46 +0100152 int own_node;
Petr Machata940ec062012-01-06 22:43:51 +0100153 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);
Petr Machata84c86d72012-10-30 00:28:44 +0100163 free(array);
Petr Machata940ec062012-01-06 22:43:51 +0100164 return -1;
165 }
166
Petr Machata16804482012-10-30 00:19:36 +0100167 len->type = *type_get_simple(ARGTYPE_LONG);
Petr Machata940ec062012-01-06 22:43:51 +0100168
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;
Petr Machata58e75f52012-10-30 00:22:46 +0100182 own_node = 1;
Petr Machata940ec062012-01-06 22:43:51 +0100183
184 } else {
185 node = expr_node_zero();
Petr Machata58e75f52012-10-30 00:22:46 +0100186 own_node = 0;
Petr Machata940ec062012-01-06 22:43:51 +0100187 }
Petr Machata940ec062012-01-06 22:43:51 +0100188 assert(node != NULL);
Petr Machata940ec062012-01-06 22:43:51 +0100189
Petr Machata84c86d72012-10-30 00:28:44 +0100190 type_init_array(array, elt_info, 0, node, own_node);
191 type_init_pointer(infop, array, 1);
192
Petr Machata940ec062012-01-06 22:43:51 +0100193 } else if (format_type == ARGTYPE_POINTER) {
Peter Wucae76962013-09-26 00:55:57 +0200194 type_init_pointer(infop, elt_info, 0);
Petr Machata940ec062012-01-06 22:43:51 +0100195
196 } else {
197 *infop = *type_get_simple(format_type);
198 }
199
200 return 0;
201}
202
203static int
204param_printf_next(struct param_enum *self, struct arg_type_info *infop,
205 int *insert_stop)
206{
207 unsigned hlf = 0;
208 unsigned lng = 0;
Petr Machatab7819162012-01-09 04:26:15 +0100209 enum arg_type format_type = ARGTYPE_VOID;
210 enum arg_type elt_type = ARGTYPE_VOID;
Petr Machata940ec062012-01-06 22:43:51 +0100211 char len_buf[25] = {};
212 size_t len_buf_len = 0;
Petr Machata31af32c2012-01-08 02:36:50 +0100213 struct lens *lens = NULL;
Petr Machata940ec062012-01-06 22:43:51 +0100214
Petr Machatac00837c2013-11-11 02:24:42 +0100215 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
Petr Machata940ec062012-01-06 22:43:51 +0100231 if (!self->percent) {
Petr Machatac00837c2013-11-11 02:24:42 +0100232 if (c == '%')
Petr Machata940ec062012-01-06 22:43:51 +0100233 self->percent = 1;
234 continue;
235 }
236
Petr Machatac00837c2013-11-11 02:24:42 +0100237 switch (c) {
Petr Machata940ec062012-01-06 22:43:51 +0100238 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) {
Petr Machatac00837c2013-11-11 02:24:42 +0100255 self->ptr += self->width;
Petr Machata940ec062012-01-06 22:43:51 +0100256 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)
Petr Machatac00837c2013-11-11 02:24:42 +0100268 len_buf[len_buf_len++] = c;
Petr Machata940ec062012-01-06 22:43:51 +0100269 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
Petr Machata940ec062012-01-06 22:43:51 +0100305 case 'o':
Petr Machatac70b1952012-04-27 21:00:26 +0200306 lens = &octal_lens;
307 goto uint;
308
Petr Machata940ec062012-01-06 22:43:51 +0100309 case 'x': case 'X':
Petr Machatac70b1952012-04-27 21:00:26 +0200310 lens = &hex_lens;
Petr Machata0441baf2013-01-09 16:22:14 +0100311 /* Fall through. */
Petr Machatac70b1952012-04-27 21:00:26 +0200312 case 'u':
313 uint:
Petr Machata940ec062012-01-06 22:43:51 +0100314 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;
Petr Machatac00837c2013-11-11 02:24:42 +0100340 elt_type = lng == 0 ? ARGTYPE_CHAR : ARGTYPE_INT;
Petr Machata940ec062012-01-06 22:43:51 +0100341 self->percent = 0;
Petr Machatae3f4a982012-01-09 04:27:26 +0100342 lens = &string_lens;
Petr Machata940ec062012-01-06 22:43:51 +0100343 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. */
Petr Machatab7819162012-01-09 04:26:15 +0100364 assert(format_type != ARGTYPE_VOID);
Petr Machata940ec062012-01-06 22:43:51 +0100365
366 if (form_next_param(self, format_type, elt_type, hlf, lng,
367 len_buf, len_buf_len, infop) < 0)
368 return -1;
369
Petr Machata31af32c2012-01-08 02:36:50 +0100370 infop->lens = lens;
371 infop->own_lens = 0;
372
Petr Machata940ec062012-01-06 22:43:51 +0100373 return 0;
374 }
375
Petr Machata16804482012-10-30 00:19:36 +0100376 *infop = *type_get_simple(ARGTYPE_VOID);
Petr Machata940ec062012-01-06 22:43:51 +0100377 return 0;
378}
379
380static enum param_status
381param_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
390static void
391param_printf_done(struct param_enum *context)
392{
Petr Machata43417842012-10-29 17:59:17 +0100393 value_destroy(&context->array);
Petr Machata940ec062012-01-06 22:43:51 +0100394 free(context);
395}
396
397void
398param_pack_init_printf(struct param *param, struct expr_node *arg, int own_arg)
399{
Petr Machatae36298a2012-09-13 17:12:41 +0200400 param_init_pack(param, PARAM_PACK_VARARGS, arg, 1, own_arg,
Petr Machata940ec062012-01-06 22:43:51 +0100401 &param_printf_init, &param_printf_next,
402 &param_printf_stop, &param_printf_done);
403}