blob: 8848b35100a0b164dcd9ceb330fb9ace95f80790 [file] [log] [blame]
Petr Machata94078ec2012-01-05 18:07:02 +01001/*
2 * This file is part of ltrace.
3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
4 * Copyright (C) 1998,2004,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
Steve Fink7bafff02006-08-07 04:50:42 +020024#include <ctype.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010025#include <stdlib.h>
Petr Machata94078ec2012-01-05 18:07:02 +010026#include <assert.h>
27#include <inttypes.h>
28#include <stdarg.h>
29#include <stdio.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +010030
Juan Cespedesf7281232009-06-25 16:11:21 +020031#include "common.h"
Petr Machata366c2f42012-02-09 19:34:36 +010032#include "proc.h"
Petr Machata94078ec2012-01-05 18:07:02 +010033#include "value.h"
34#include "expr.h"
Petr Machata000e3112012-01-03 17:03:39 +010035#include "type.h"
Petr Machata94078ec2012-01-05 18:07:02 +010036#include "common.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010037
Petr Machata94078ec2012-01-05 18:07:02 +010038static int format_argument_2(FILE *stream, struct value *value,
39 struct value_dict *arguments);
Juan Cespedes5e01f651998-03-08 22:31:44 +010040
Petr Machata94078ec2012-01-05 18:07:02 +010041#define READER(NAME, TYPE) \
42 static int \
43 NAME(struct value *value, TYPE *ret, struct value_dict *arguments) \
44 { \
45 union { \
46 TYPE val; \
47 unsigned char buf[0]; \
48 } u; \
49 if (value_extract_buf(value, u.buf, arguments) < 0) \
50 return -1; \
51 *ret = u.val; \
52 return 0; \
Juan Cespedesa413e5b2007-09-04 17:34:53 +020053 }
Steve Fink65b53df2006-09-25 02:27:08 +020054
Petr Machata94078ec2012-01-05 18:07:02 +010055READER(read_float, float)
56READER(read_double, double)
57
58#undef READER
59
60#define HANDLE_WIDTH(BITS) \
61 do { \
62 long l; \
63 if (value_extract_word(value, &l, arguments) < 0) \
64 return -1; \
65 int##BITS##_t i = l; \
66 switch (format) { \
67 case INT_FMT_unknown: \
68 if (i < -10000 || i > 10000) \
69 case INT_FMT_x: \
70 return fprintf(stream, "%#"PRIx##BITS, i); \
71 case INT_FMT_i: \
72 return fprintf(stream, "%"PRIi##BITS, i); \
73 case INT_FMT_u: \
74 return fprintf(stream, "%"PRIu##BITS, i); \
75 case INT_FMT_o: \
76 return fprintf(stream, "%"PRIo##BITS, i); \
77 } \
78 } while (0)
79
80enum int_fmt_t
81{
82 INT_FMT_i,
83 INT_FMT_u,
84 INT_FMT_o,
85 INT_FMT_x,
86 INT_FMT_unknown,
87};
88
89static int
90format_integer(FILE *stream, struct value *value, enum int_fmt_t format,
91 struct value_dict *arguments)
92{
93 switch (type_sizeof(value->inferior, value->type)) {
94
95 case 1: HANDLE_WIDTH(8);
96 case 2: HANDLE_WIDTH(16);
97 case 4: HANDLE_WIDTH(32);
98 case 8: HANDLE_WIDTH(64);
99
100 default:
101 assert(!"unsupported integer width");
102 abort();
103
104 case -1:
105 return -1;
106 }
107}
108
109#undef HANDLE_WIDTH
110
111static int
112format_enum(FILE *stream, struct value *value, struct value_dict *arguments)
113{
114 long l;
115 if (value_extract_word(value, &l, arguments) < 0)
116 return -1;
117
118 const char *name = type_enum_get(value->type, l);
119 if (name != NULL)
120 return fprintf(stream, "%s", name);
121
122 return format_integer(stream, value, INT_FMT_i, arguments);
Steve Fink6a48a6d2006-08-07 04:29:06 +0200123}
124
Juan Cespedesf1350522008-12-16 18:19:58 +0100125static int
Petr Machata94078ec2012-01-05 18:07:02 +0100126acc_fprintf(int *countp, FILE *stream, const char *format, ...)
127{
128 va_list pa;
129 va_start(pa, format);
130 int i = vfprintf(stream, format, pa);
131 va_end(pa);
132
133 if (i >= 0)
134 *countp += i;
135 return i;
136}
137
138static int
139format_char(FILE *stream, struct value *value, struct value_dict *arguments)
140{
141 long lc;
142 if (value_extract_word(value, &lc, arguments) < 0)
143 return -1;
144 int c = (int)lc;
145
146 /* If this value is not wrapped in array, then this is not a
147 * string, and we need to display quotes. */
148 int quote = !(value->parent != NULL
149 && (value->parent->type->type == ARGTYPE_ARRAY
150 || value->parent->type->type == ARGTYPE_STRING
151 || value->parent->type->type == ARGTYPE_STRING_N));
152 int written = 0;
153 if (quote && acc_fprintf(&written, stream, "'") < 0)
154 return -1;
155
156 const char *fmt;
157 switch (c) {
158 case -1:
159 fmt = "EOF";
160 break;
161 case 0:
162 fmt = "\\0";
163 break;
164 case '\a':
165 fmt = "\\a";
166 break;
167 case '\b':
168 fmt = "\\b";
169 break;
170 case '\t':
171 fmt = "\\t";
172 break;
173 case '\n':
174 fmt = "\\n";
175 break;
176 case '\v':
177 fmt = "\\v";
178 break;
179 case '\f':
180 fmt = "\\f";
181 break;
182 case '\r':
183 fmt = "\\r";
184 break;
185 case '\\':
186 fmt = "\\\\";
187 break;
188 default:
189 if (isprint(c) || c == ' ')
190 fmt = "%c";
191 else if (acc_fprintf(&written, stream, "\\%03o",
192 (unsigned char)c) < 0)
193 return -1;
194 else
195 fmt = NULL;
196 }
197
198 if (fmt != NULL && acc_fprintf(&written, stream, fmt, c) < 0)
199 return -1;
200 if (quote && acc_fprintf(&written, stream, "'") < 0)
201 return -1;
202 return written;
203}
204
205static int
206format_floating(FILE *stream, struct value *value, struct value_dict *arguments)
207{
208 switch (value->type->type) {
209 float f;
210 double d;
211 case ARGTYPE_FLOAT:
212 if (read_float(value, &f, arguments) < 0)
213 return -1;
214 return fprintf(stream, "%f", (double)f);
215 case ARGTYPE_DOUBLE:
216 if (read_double(value, &d, arguments) < 0)
217 return -1;
218 return fprintf(stream, "%f", d);
219 default:
220 abort();
221 }
222}
223
224static int
225format_struct(FILE *stream, struct value *value, struct value_dict *arguments)
226{
227 int written = 0;
228 if (acc_fprintf(&written, stream, "{ ") < 0)
229 return -1;
230 size_t i;
231 for (i = 0; i < type_struct_size(value->type); ++i) {
232 if (i > 0 && acc_fprintf(&written, stream, ", ") < 0)
233 return -1;
234
235 struct value element;
236 if (value_init_element(&element, value, i) < 0)
237 return -1;
238 int o = format_argument_2(stream, &element, arguments);
239 if (o < 0)
240 return -1;
241 written += o;
242 }
243 if (acc_fprintf(&written, stream, " }") < 0)
244 return -1;
245 return written;
246}
247
248int
249format_pointer(FILE *stream, struct value *value, struct value_dict *arguments)
250{
251 struct value element;
252 if (value_init_deref(&element, value) < 0)
253 return -1;
254 return format_argument_2(stream, &element, arguments);
Steve Fink1150bc42006-08-07 06:04:43 +0200255}
256
257/*
Petr Machata94078ec2012-01-05 18:07:02 +0100258 * LENGTH is an expression whose evaluation will yield the actual
259 * length of the array.
Steve Fink1150bc42006-08-07 06:04:43 +0200260 *
Petr Machata94078ec2012-01-05 18:07:02 +0100261 * MAXLEN is the actual maximum length that we care about
262 *
263 * BEFORE if LENGTH>MAXLEN, we display ellipsis. We display it before
264 * the closing parenthesis if BEFORE, otherwise after it.
265 *
266 * OPEN, CLOSE, DELIM are opening and closing parenthesis and element
267 * delimiter.
Steve Fink1150bc42006-08-07 06:04:43 +0200268 */
Juan Cespedesf1350522008-12-16 18:19:58 +0100269int
Petr Machata94078ec2012-01-05 18:07:02 +0100270format_array(FILE *stream, struct value *value, struct value_dict *arguments,
271 struct expr_node *length, size_t maxlen, int before,
272 const char *open, const char *close, const char *delim)
Petr Machata000e3112012-01-03 17:03:39 +0100273{
Petr Machata94078ec2012-01-05 18:07:02 +0100274 /* We need "long" to be long enough to cover the whole address
275 * space. */
276 typedef char assert__long_enough_long[-(sizeof(long) < sizeof(void *))];
277 long l = options.strlen;
278 if (length != NULL) /* XXX emulate node ZERO before it lands */
279 if (expr_eval_word(length, value, arguments, &l) < 0)
280 return -1;
281 size_t len = (size_t)l;
Steve Fink7bafff02006-08-07 04:50:42 +0200282
Petr Machata94078ec2012-01-05 18:07:02 +0100283 int written = 0;
284 if (acc_fprintf(&written, stream, "%s", open) < 0)
285 return -1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100286
Zachary T Welchba6aca22010-12-08 18:55:09 -0800287 size_t i;
Petr Machata94078ec2012-01-05 18:07:02 +0100288 for (i = 0; i < len && i <= maxlen; ++i) {
289 if (i == maxlen) {
290 if (before && acc_fprintf(&written, stream, "...") < 0)
291 return -1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100292 break;
293 }
Petr Machata94078ec2012-01-05 18:07:02 +0100294
295 if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0)
296 return -1;
297
298 struct value element;
299 if (value_init_element(&element, value, i) < 0)
300 return -1;
301 if (value_is_zero(&element, arguments)) /* XXX emulate ZERO */
302 break;
303 int o = format_argument_2(stream, &element, arguments);
304 if (o < 0)
305 return -1;
306 written += o;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100307 }
Petr Machata94078ec2012-01-05 18:07:02 +0100308 if (acc_fprintf(&written, stream, "%s", close) < 0)
309 return -1;
310 if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0)
311 return -1;
312
313 return written;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100314}
315
Juan Cespedesf1350522008-12-16 18:19:58 +0100316static int
Petr Machata94078ec2012-01-05 18:07:02 +0100317format_argument_2(FILE *stream, struct value *value,
318 struct value_dict *arguments)
319{
320 struct expr_node *length = NULL;
321 switch (value->type->type) {
322 case ARGTYPE_VOID:
323 return fprintf(stream, "<void>");
324
325 case ARGTYPE_UNKNOWN:
326 return format_integer(stream, value, INT_FMT_unknown,
327 arguments);
328
329 case ARGTYPE_SHORT:
330 case ARGTYPE_INT:
331 case ARGTYPE_LONG:
332 return format_integer(stream, value, INT_FMT_i, arguments);
333
334 case ARGTYPE_USHORT:
335 case ARGTYPE_UINT:
336 case ARGTYPE_ULONG:
337 return format_integer(stream, value, INT_FMT_u, arguments);
338
339 case ARGTYPE_OCTAL:
340 return format_integer(stream, value, INT_FMT_o, arguments);
341
342 case ARGTYPE_CHAR:
343 return format_char(stream, value, arguments);
344
345 case ARGTYPE_FLOAT:
346 case ARGTYPE_DOUBLE:
347 return format_floating(stream, value, arguments);
348
349 case ARGTYPE_STRUCT:
350 return format_struct(stream, value, arguments);
351
352 case ARGTYPE_POINTER:
353 if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID)
354 return format_pointer(stream, value, arguments);
355 case ARGTYPE_ADDR:
356 case ARGTYPE_FILE:
357 return format_integer(stream, value, INT_FMT_x, arguments);
358
359 case ARGTYPE_ARRAY:
360 if (value->type->u.array_info.elt_type->type != ARGTYPE_CHAR)
361 return format_array(stream, value, arguments,
362 value->type->u.array_info.length,
363 options.arraylen, 1,
364 "[ ", " ]", ", ");
365
366 return format_array(stream, value, arguments,
367 value->type->u.array_info.length,
368 options.strlen, 0, "\"", "\"", "");
369
370 case ARGTYPE_STRING_N:
371 length = value->type->u.string_n_info.length;
372 /* fall-through */
373 case ARGTYPE_FORMAT:
374 case ARGTYPE_STRING: {
375 /* Strings are in fact char pointers. Smuggle in the
376 * pointer here. */
377
378 struct arg_type_info info[2];
379 type_init_array(&info[1], type_get_simple(ARGTYPE_CHAR), 0,
380 length, 0);
381 type_init_pointer(&info[0], &info[1], 0);
382
383 struct value tmp;
384 value_clone(&tmp, value);
385 value_set_type(&tmp, info, 0);
386
387 int ret = format_argument_2(stream, &tmp, arguments);
388
389 value_destroy(&tmp);
390 type_destroy(&info[0]);
391 type_destroy(&info[1]);
392 return ret;
393 }
394
395 case ARGTYPE_ENUM:
396 return format_enum(stream, value, arguments);
397
398 case ARGTYPE_COUNT:
399 abort();
400 }
401 abort();
402}
403
404int
405format_argument(FILE *stream, struct value *value, struct value_dict *arguments)
406{
407 /* Arrays decay into pointers for purposes of argument
408 * passing. Before the proper support for this lands, wrap
409 * top-level arrays in pointers here. */
410 if (value->type->type == ARGTYPE_ARRAY) {
411
412 struct arg_type_info info;
413 type_init_pointer(&info, value->type, 0);
414
415 struct value tmp;
416 value_clone(&tmp, value);
417 value_set_type(&tmp, &info, 0);
418
419 int ret = format_argument_2(stream, &tmp, arguments);
420
421 value_destroy(&tmp);
422 type_destroy(&info);
423
424 return ret;
425
Juan Cespedes5e01f651998-03-08 22:31:44 +0100426 } else {
Petr Machata94078ec2012-01-05 18:07:02 +0100427 return format_argument_2(stream, value, arguments);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100428 }
429}