lens_default.c revision ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207
1/*
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
24#include <ctype.h>
25#include <stdlib.h>
26#include <assert.h>
27#include <inttypes.h>
28#include <stdarg.h>
29#include <stdio.h>
30#include <string.h>
31
32#include "proc.h"
33#include "lens_default.h"
34#include "value.h"
35#include "expr.h"
36#include "type.h"
37#include "common.h"
38#include "zero.h"
39
40#define READER(NAME, TYPE)						\
41	static int							\
42	NAME(struct value *value, TYPE *ret, struct value_dict *arguments) \
43	{								\
44		union {							\
45			TYPE val;					\
46			unsigned char buf[0];				\
47		} u;							\
48		if (value_extract_buf(value, u.buf, arguments) < 0)	\
49			return -1;					\
50		*ret = u.val;						\
51		return 0;						\
52	}
53
54READER(read_float, float)
55READER(read_double, double)
56
57#undef READER
58
59#define HANDLE_WIDTH(BITS)						\
60	do {								\
61		long l;							\
62		if (value_extract_word(value, &l, arguments) < 0)	\
63			return -1;					\
64		int##BITS##_t i = l;					\
65		uint64_t v = (uint64_t)(uint##BITS##_t)i;		\
66		switch (format) {					\
67		case INT_FMT_unknown:					\
68			if (l < -10000 || l > 10000)			\
69		case INT_FMT_x:						\
70			return fprintf(stream, "%#"PRIx64, v);		\
71		case INT_FMT_i:						\
72		case INT_FMT_default:					\
73			return fprintf(stream, "%"PRIi##BITS, i);	\
74		case INT_FMT_u:						\
75			return fprintf(stream, "%"PRIu64, v);		\
76		case INT_FMT_o:						\
77			return fprintf(stream, "0%"PRIo64, v);		\
78		}							\
79	} while (0)
80
81enum int_fmt_t
82{
83	INT_FMT_i,
84	INT_FMT_u,
85	INT_FMT_o,
86	INT_FMT_x,
87	INT_FMT_unknown,
88	INT_FMT_default,
89};
90
91static int
92format_integer(FILE *stream, struct value *value, enum int_fmt_t format,
93	       struct value_dict *arguments)
94{
95	switch (type_sizeof(value->inferior, value->type)) {
96
97	case 1: HANDLE_WIDTH(8);
98	case 2: HANDLE_WIDTH(16);
99	case 4: HANDLE_WIDTH(32);
100	case 8: HANDLE_WIDTH(64);
101
102	default:
103		assert(!"unsupported integer width");
104		abort();
105
106	case -1:
107		return -1;
108	}
109}
110
111#undef HANDLE_WIDTH
112
113static int
114acc_fprintf(int *countp, FILE *stream, const char *format, ...)
115{
116	va_list pa;
117	va_start(pa, format);
118	int i = account_output(countp, vfprintf(stream, format, pa));
119	va_end(pa);
120
121	return i;
122}
123
124static int
125format_char(FILE *stream, struct value *value, struct value_dict *arguments)
126{
127	long lc;
128	if (value_extract_word(value, &lc, arguments) < 0)
129		return -1;
130	int c = (int)lc;
131
132	const char *fmt;
133	switch (c) {
134	case -1:
135		fmt = "EOF";
136		break;
137	case 0:
138		fmt = "\\0";
139		break;
140	case '\a':
141		fmt = "\\a";
142		break;
143	case '\b':
144		fmt = "\\b";
145		break;
146	case '\t':
147		fmt = "\\t";
148		break;
149	case '\n':
150		fmt = "\\n";
151		break;
152	case '\v':
153		fmt = "\\v";
154		break;
155	case '\f':
156		fmt = "\\f";
157		break;
158	case '\r':
159		fmt = "\\r";
160		break;
161	case '\\':
162		fmt = "\\\\";
163		break;
164	default:
165		if (isprint(c) || c == ' ')
166			fmt = "%c";
167		else
168			fmt = "\\%03o";
169	}
170
171	return fprintf(stream, fmt, c);
172}
173
174static int
175format_naked_char(FILE *stream, struct value *value,
176		  struct value_dict *arguments)
177{
178	int written = 0;
179	if (acc_fprintf(&written, stream, "'") < 0
180	    || account_output(&written,
181			      format_char(stream, value, arguments)) < 0
182	    || acc_fprintf(&written, stream, "'") < 0)
183		return -1;
184
185	return written;
186}
187
188static int
189format_floating(FILE *stream, struct value *value, struct value_dict *arguments)
190{
191	switch (value->type->type) {
192		float f;
193		double d;
194	case ARGTYPE_FLOAT:
195		if (read_float(value, &f, arguments) < 0)
196			return -1;
197		return fprintf(stream, "%f", (double)f);
198	case ARGTYPE_DOUBLE:
199		if (read_double(value, &d, arguments) < 0)
200			return -1;
201		return fprintf(stream, "%f", d);
202	default:
203		abort();
204	}
205}
206
207struct format_argument_data
208{
209	struct value *value;
210	struct value_dict *arguments;
211};
212
213static int
214format_argument_cb(FILE *stream, void *ptr)
215{
216	struct format_argument_data *data = ptr;
217	return format_argument(stream, data->value, data->arguments);
218}
219
220static int
221format_struct(FILE *stream, struct value *value, struct value_dict *arguments)
222{
223	int written = 0;
224	if (acc_fprintf(&written, stream, "{ ") < 0)
225		return -1;
226
227	int need_delim = 0;
228	size_t i;
229	for (i = 0; i < type_struct_size(value->type); ++i) {
230		struct value element;
231		if (value_init_element(&element, value, i) < 0)
232			return -1;
233
234		struct format_argument_data data = { &element, arguments };
235		int o = delim_output(stream, &need_delim,
236				     format_argument_cb, &data);
237		value_destroy(&element);
238		if (o < 0)
239			return -1;
240
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	if (value_is_zero(value, arguments))
252		return fprintf(stream, "nil");
253
254	/* The following is for detecting recursion.  We keep track of
255	 * the values that were already displayed.  Each time a
256	 * pointer should be dereferenced, we compare its value to the
257	 * value of each of the pointers dereferenced so far.  If one
258	 * of them matches, instead of recursing, we just printf which
259	 * superstructure this pointer recurses to.  */
260	static struct vect pointers = {};
261	if (pointers.elt_size == 0)
262		VECT_INIT(&pointers, struct value *);
263
264	/* Trim number of expanded structures of the same type.  Even
265	 * for non-recursive structure, we don't want to expand all of
266	 * it if it's huge.  */
267	size_t i;
268	size_t len = vect_size(&pointers);
269	assert(value->type->type == ARGTYPE_POINTER);
270	struct arg_type_info *pointee = value->type->u.ptr_info.info;
271	if (pointee->type == ARGTYPE_STRUCT) {
272		size_t depth = 0;
273		for (i = 0; i < len; ++i) {
274			struct value *old
275				= *VECT_ELEMENT(&pointers, struct value *, i);
276			assert(old->type->type == ARGTYPE_POINTER);
277			struct arg_type_info *old_pointee
278				= old->type->u.ptr_info.info;
279			if (old_pointee == pointee)
280				depth++;
281		}
282		if (depth >= options.arraylen)
283			return fprintf(stream, "...");
284	}
285
286	for (i = len; i-- > 0 ;) {
287		struct value **old = VECT_ELEMENT(&pointers, struct value *, i);
288		int rc = value_equal(value, *old, arguments);
289		if (rc < 0)
290			return -1;
291		if (rc > 0) {
292			size_t reclevel = len - i - 1;
293			char buf[reclevel + 1];
294			memset(buf, '^', sizeof buf);
295			buf[reclevel] = 0;
296			return fprintf(stream, "recurse%s", buf);
297		}
298	}
299
300	/* OK, not a recursion.  Remember this value for tracking.  */
301	if (VECT_PUSHBACK(&pointers, &value) < 0)
302		return -1;
303
304	struct value element;
305	int o;
306	if (value_init_deref(&element, value) < 0) {
307		o = -1;
308		goto done;
309	}
310	o = format_argument(stream, &element, arguments);
311	value_destroy(&element);
312
313done:
314	vect_popback(&pointers);
315	return o;
316}
317
318/*
319 * LENGTH is an expression whose evaluation will yield the actual
320 *    length of the array.
321 *
322 * MAXLEN is the actual maximum length that we care about
323 *
324 * BEFORE if LENGTH>MAXLEN, we display ellipsis.  We display it before
325 *    the closing parenthesis if BEFORE, otherwise after it.
326 *
327 * OPEN, CLOSE, DELIM are opening and closing parenthesis and element
328 *    delimiter.
329 */
330int
331format_array(FILE *stream, struct value *value, struct value_dict *arguments,
332	     struct expr_node *length, size_t maxlen, int before,
333	     const char *open, const char *close, const char *delim)
334{
335	/* We need "long" to be long enough to cover the whole address
336	 * space.  */
337	typedef char assert__long_enough_long[-(sizeof(long) < sizeof(void *))];
338	long l;
339	if (expr_eval_word(length, value, arguments, &l) < 0)
340		return -1;
341	size_t len = (size_t)l;
342
343	int written = 0;
344	if (acc_fprintf(&written, stream, "%s", open) < 0)
345		return -1;
346
347	size_t i;
348	for (i = 0; i < len && i <= maxlen; ++i) {
349		if (i == maxlen) {
350			if (before && acc_fprintf(&written, stream, "...") < 0)
351				return -1;
352			break;
353		}
354
355		if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0)
356			return -1;
357
358		struct value element;
359		if (value_init_element(&element, value, i) < 0)
360			return -1;
361		int o = format_argument(stream, &element, arguments);
362		value_destroy(&element);
363		if (o < 0)
364			return -1;
365		written += o;
366	}
367	if (acc_fprintf(&written, stream, "%s", close) < 0)
368		return -1;
369	if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0)
370		return -1;
371
372	return written;
373}
374
375static int
376toplevel_format_lens(struct lens *lens, FILE *stream,
377		     struct value *value, struct value_dict *arguments,
378		     enum int_fmt_t int_fmt)
379{
380	switch (value->type->type) {
381	case ARGTYPE_VOID:
382		return fprintf(stream, "<void>");
383
384	case ARGTYPE_SHORT:
385	case ARGTYPE_INT:
386	case ARGTYPE_LONG:
387		return format_integer(stream, value, int_fmt, arguments);
388
389	case ARGTYPE_USHORT:
390	case ARGTYPE_UINT:
391	case ARGTYPE_ULONG:
392		if (int_fmt == INT_FMT_i || int_fmt == INT_FMT_default)
393			int_fmt = INT_FMT_u;
394		return format_integer(stream, value, int_fmt, arguments);
395
396	case ARGTYPE_CHAR:
397		if (int_fmt == INT_FMT_default)
398			return format_naked_char(stream, value, arguments);
399		return format_integer(stream, value, int_fmt, arguments);
400
401	case ARGTYPE_FLOAT:
402	case ARGTYPE_DOUBLE:
403		return format_floating(stream, value, arguments);
404
405	case ARGTYPE_STRUCT:
406		return format_struct(stream, value, arguments);
407
408	case ARGTYPE_POINTER:
409		if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID)
410			return format_pointer(stream, value, arguments);
411		return format_integer(stream, value, INT_FMT_x, arguments);
412
413	case ARGTYPE_ARRAY:
414		return format_array(stream, value, arguments,
415				    value->type->u.array_info.length,
416				    options.arraylen, 1, "[ ", " ]", ", ");
417	}
418	abort();
419}
420
421static int
422default_lens_format_cb(struct lens *lens, FILE *stream,
423		       struct value *value, struct value_dict *arguments)
424{
425	return toplevel_format_lens(lens, stream, value, arguments,
426				    INT_FMT_default);
427}
428
429struct lens default_lens = {
430	.format_cb = default_lens_format_cb,
431};
432
433
434static int
435blind_lens_format_cb(struct lens *lens, FILE *stream,
436		     struct value *value, struct value_dict *arguments)
437{
438	return 0;
439}
440
441struct lens blind_lens = {
442	.format_cb = blind_lens_format_cb,
443};
444
445
446static int
447octal_lens_format_cb(struct lens *lens, FILE *stream,
448		     struct value *value, struct value_dict *arguments)
449{
450	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_o);
451}
452
453struct lens octal_lens = {
454	.format_cb = octal_lens_format_cb,
455};
456
457
458static int
459hex_lens_format_cb(struct lens *lens, FILE *stream,
460		   struct value *value, struct value_dict *arguments)
461{
462	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_x);
463}
464
465struct lens hex_lens = {
466	.format_cb = hex_lens_format_cb,
467};
468
469
470static int
471dec_lens_format_cb(struct lens *lens, FILE *stream,
472		   struct value *value, struct value_dict *arguments)
473{
474	return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_u);
475}
476
477struct lens dec_lens = {
478	.format_cb = dec_lens_format_cb,
479};
480
481
482static int
483guess_lens_format_cb(struct lens *lens, FILE *stream,
484		     struct value *value, struct value_dict *arguments)
485{
486	return toplevel_format_lens(lens, stream, value, arguments,
487				    INT_FMT_unknown);
488}
489
490struct lens guess_lens = {
491	.format_cb = guess_lens_format_cb,
492};
493
494
495static int
496bool_lens_format_cb(struct lens *lens, FILE *stream,
497		    struct value *value, struct value_dict *arguments)
498{
499	switch (value->type->type) {
500	case ARGTYPE_VOID:
501	case ARGTYPE_FLOAT:
502	case ARGTYPE_DOUBLE:
503	case ARGTYPE_STRUCT:
504	case ARGTYPE_POINTER:
505	case ARGTYPE_ARRAY:
506		return toplevel_format_lens(lens, stream, value,
507					    arguments, INT_FMT_default);
508
509		int zero;
510	case ARGTYPE_SHORT:
511	case ARGTYPE_INT:
512	case ARGTYPE_LONG:
513	case ARGTYPE_USHORT:
514	case ARGTYPE_UINT:
515	case ARGTYPE_ULONG:
516	case ARGTYPE_CHAR:
517		if ((zero = value_is_zero(value, arguments)) < 0)
518			return -1;
519		if (zero)
520			return fprintf(stream, "false");
521		else
522			return fprintf(stream, "true");
523	}
524	abort();
525}
526
527struct lens bool_lens = {
528	.format_cb = bool_lens_format_cb,
529};
530
531
532static int
533string_lens_format_cb(struct lens *lens, FILE *stream,
534		      struct value *value, struct value_dict *arguments)
535{
536	switch (value->type->type) {
537	case ARGTYPE_POINTER:
538		/* This should really be written as either "string",
539		 * or, if lens, then string(array(char, zero)*).  But
540		 * I suspect people are so used to the char * C idiom,
541		 * that string(char *) might actually turn up.  So
542		 * let's just support it.  */
543		if (value->type->u.ptr_info.info->type == ARGTYPE_CHAR) {
544			struct arg_type_info info[2];
545			type_init_array(&info[1],
546					value->type->u.ptr_info.info, 0,
547					expr_node_zero(), 0);
548			type_init_pointer(&info[0], &info[1], 0);
549			info->lens = lens;
550			info->own_lens = 0;
551			struct value tmp;
552			if (value_clone(&tmp, value) < 0)
553				return -1;
554			value_set_type(&tmp, info, 0);
555			int ret = string_lens_format_cb(lens, stream, &tmp,
556							arguments);
557			type_destroy(&info[0]);
558			type_destroy(&info[1]);
559			value_destroy(&tmp);
560			return ret;
561		}
562
563		/* fall-through */
564	case ARGTYPE_VOID:
565	case ARGTYPE_FLOAT:
566	case ARGTYPE_DOUBLE:
567	case ARGTYPE_STRUCT:
568	case ARGTYPE_SHORT:
569	case ARGTYPE_INT:
570	case ARGTYPE_LONG:
571	case ARGTYPE_USHORT:
572	case ARGTYPE_UINT:
573	case ARGTYPE_ULONG:
574		return toplevel_format_lens(lens, stream, value,
575					    arguments, INT_FMT_default);
576
577	case ARGTYPE_CHAR:
578		return format_char(stream, value, arguments);
579
580	case ARGTYPE_ARRAY:
581		return format_array(stream, value, arguments,
582				    value->type->u.array_info.length,
583				    options.strlen, 0, "\"", "\"", "");
584	}
585	abort();
586}
587
588struct lens string_lens = {
589	.format_cb = string_lens_format_cb,
590};
591
592static int
593out_bits(FILE *stream, size_t low, size_t high)
594{
595	if (low == high)
596		return fprintf(stream, "%zd", low);
597	else
598		return fprintf(stream, "%zd-%zd", low, high);
599}
600
601static unsigned
602bitcount(unsigned u)
603{
604	int c = 0;
605	for (; u > 0; u &= u - 1)
606		c++;
607	return c;
608}
609
610static int
611bitvect_lens_format_cb(struct lens *lens, FILE *stream,
612		       struct value *value, struct value_dict *arguments)
613{
614	unsigned char *data = value_get_data(value, arguments);
615	if (data == NULL)
616		return -1;
617	size_t sz = type_sizeof(value->inferior, value->type);
618	if (sz == (size_t)-1)
619		return -1;
620
621	size_t i;
622	unsigned char buf[sz];
623	switch ((int)value->type->type) {
624		union bitvect_integral_64
625		{
626			uint8_t u8;
627			uint16_t u16;
628			uint32_t u32;
629			uint64_t u64;
630			unsigned char buf[0];
631		} bv;
632
633	case ARGTYPE_POINTER:
634		return format_pointer(stream, value, arguments);
635
636	case ARGTYPE_STRUCT:
637	case ARGTYPE_ARRAY:
638		break;
639
640	default:
641		assert(sz <= sizeof(bv));
642		memmove(bv.buf, data, sz);
643
644		if (sz == 1)
645			bv.u64 = bv.u8;
646		else if (sz == 2)
647			bv.u64 = bv.u16;
648		else if (sz == 4)
649			bv.u64 = bv.u32;
650
651		for (i = 0; i < sz; ++i) {
652			buf[i] = bv.u64 & 0xff;
653			bv.u64 >>= 8;
654		}
655		data = buf;
656	}
657
658	size_t bits = 0;
659	for (i = 0; i < sz; ++i)
660		bits += bitcount(data[i]);
661
662	/* If there's more 1's than 0's, show inverse.  */
663	unsigned neg = bits > sz * 4 ? 0xff : 0x00;
664
665	int o = 0;
666	if (acc_fprintf(&o, stream, "%s<", "~" + (neg == 0x00)) < 0)
667		return -1;
668
669	size_t bitno = 0;
670	ssize_t low = -1;
671	for (i = 0; i < sz; ++i) {
672		unsigned char m;
673		unsigned char d = data[i] ^ neg;
674		for (m = 0x01; m != 0; m <<= 1) {
675			int bit = !!(m & d);
676			if (low < 0) {
677				if (bit) {
678					if (low == -2
679					    && acc_fprintf(&o, stream, ",") < 0)
680						return -1;
681					low = bitno;
682				}
683			} else if (!bit) {
684				if (account_output(&o, out_bits(stream, low,
685								bitno-1)) < 0)
686					return -1;
687				low = -2;
688			}
689			bitno++;
690		}
691	}
692	if (low >= 0 && account_output(&o, out_bits(stream, low, bitno-1)) < 0)
693		return -1;
694
695	if (fputc('>', stream) < 0)
696		return -1;
697	o += 1;
698
699	return o;
700}
701
702struct lens bitvect_lens = {
703	.format_cb = bitvect_lens_format_cb,
704};
705