Imported Upstream version 0.7.2
[platform/upstream/ltrace.git] / lens_default.c
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
54 READER(read_float, float)
55 READER(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
81 enum 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
91 static int
92 format_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
113 static int
114 acc_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
124 static int
125 format_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
174 static int
175 format_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
188 static int
189 format_double(FILE *stream, double value, enum int_fmt_t format)
190 {
191         if (format == INT_FMT_x)
192                 return fprintf(stream, "%a", value);
193         else
194                 return fprintf(stream, "%f", value);
195 }
196
197 static int
198 format_floating(FILE *stream, struct value *value, struct value_dict *arguments,
199                 enum int_fmt_t format)
200 {
201         switch (value->type->type) {
202                 float f;
203                 double d;
204         case ARGTYPE_FLOAT:
205                 if (read_float(value, &f, arguments) < 0)
206                         return -1;
207                 return format_double(stream, f, format);
208         case ARGTYPE_DOUBLE:
209                 if (read_double(value, &d, arguments) < 0)
210                         return -1;
211                 return format_double(stream, d, format);
212         default:
213                 abort();
214         }
215 }
216
217 struct format_argument_data
218 {
219         struct value *value;
220         struct value_dict *arguments;
221 };
222
223 static int
224 format_argument_cb(FILE *stream, void *ptr)
225 {
226         struct format_argument_data *data = ptr;
227         return format_argument(stream, data->value, data->arguments);
228 }
229
230 static int
231 format_struct(FILE *stream, struct value *value, struct value_dict *arguments)
232 {
233         int written = 0;
234         if (acc_fprintf(&written, stream, "{ ") < 0)
235                 return -1;
236
237         int need_delim = 0;
238         size_t i;
239         for (i = 0; i < type_struct_size(value->type); ++i) {
240                 struct value element;
241                 if (value_init_element(&element, value, i) < 0)
242                         return -1;
243
244                 struct format_argument_data data = { &element, arguments };
245                 int o = delim_output(stream, &need_delim,
246                                      format_argument_cb, &data);
247                 value_destroy(&element);
248                 if (o < 0)
249                         return -1;
250
251                 written += o;
252         }
253         if (acc_fprintf(&written, stream, " }") < 0)
254                 return -1;
255         return written;
256 }
257
258 int
259 format_pointer(FILE *stream, struct value *value, struct value_dict *arguments)
260 {
261         if (value_is_zero(value, arguments))
262                 return fprintf(stream, "nil");
263
264         /* The following is for detecting recursion.  We keep track of
265          * the values that were already displayed.  Each time a
266          * pointer should be dereferenced, we compare its value to the
267          * value of each of the pointers dereferenced so far.  If one
268          * of them matches, instead of recursing, we just printf which
269          * superstructure this pointer recurses to.  */
270         static struct vect pointers = {};
271         if (pointers.elt_size == 0)
272                 VECT_INIT(&pointers, struct value *);
273
274         /* Trim number of expanded structures of the same type.  Even
275          * for non-recursive structure, we don't want to expand all of
276          * it if it's huge.  */
277         size_t i;
278         size_t len = vect_size(&pointers);
279         assert(value->type->type == ARGTYPE_POINTER);
280         struct arg_type_info *pointee = value->type->u.ptr_info.info;
281         if (pointee->type == ARGTYPE_STRUCT) {
282                 size_t depth = 0;
283                 for (i = 0; i < len; ++i) {
284                         struct value *old
285                                 = *VECT_ELEMENT(&pointers, struct value *, i);
286                         assert(old->type->type == ARGTYPE_POINTER);
287                         struct arg_type_info *old_pointee
288                                 = old->type->u.ptr_info.info;
289                         if (old_pointee == pointee)
290                                 depth++;
291                 }
292                 if (depth >= options.arraylen)
293                         return fprintf(stream, "...");
294         }
295
296         for (i = len; i-- > 0 ;) {
297                 struct value **old = VECT_ELEMENT(&pointers, struct value *, i);
298                 int rc = value_equal(value, *old, arguments);
299                 if (rc < 0)
300                         return -1;
301                 if (rc > 0) {
302                         size_t reclevel = len - i - 1;
303                         char buf[reclevel + 1];
304                         memset(buf, '^', sizeof buf);
305                         buf[reclevel] = 0;
306                         return fprintf(stream, "recurse%s", buf);
307                 }
308         }
309
310         /* OK, not a recursion.  Remember this value for tracking.  */
311         if (VECT_PUSHBACK(&pointers, &value) < 0)
312                 return -1;
313
314         struct value element;
315         int o;
316         if (value_init_deref(&element, value) < 0) {
317                 o = -1;
318                 goto done;
319         }
320         o = format_argument(stream, &element, arguments);
321         value_destroy(&element);
322
323 done:
324         vect_popback(&pointers);
325         return o;
326 }
327
328 /*
329  * LENGTH is an expression whose evaluation will yield the actual
330  *    length of the array.
331  *
332  * MAXLEN is the actual maximum length that we care about
333  *
334  * BEFORE if LENGTH>MAXLEN, we display ellipsis.  We display it before
335  *    the closing parenthesis if BEFORE, otherwise after it.
336  *
337  * OPEN, CLOSE, DELIM are opening and closing parenthesis and element
338  *    delimiter.
339  */
340 int
341 format_array(FILE *stream, struct value *value, struct value_dict *arguments,
342              struct expr_node *length, size_t maxlen, int before,
343              const char *open, const char *close, const char *delim)
344 {
345         /* We need "long" to be long enough to cover the whole address
346          * space.  */
347         typedef char assert__long_enough_long[-(sizeof(long) < sizeof(void *))];
348         long l;
349         if (expr_eval_word(length, value, arguments, &l) < 0)
350                 return -1;
351         size_t len = (size_t)l;
352
353         int written = 0;
354         if (acc_fprintf(&written, stream, "%s", open) < 0)
355                 return -1;
356
357         size_t i;
358         for (i = 0; i < len && i <= maxlen; ++i) {
359                 if (i == maxlen) {
360                         if (before && acc_fprintf(&written, stream, "...") < 0)
361                                 return -1;
362                         break;
363                 }
364
365                 if (i > 0 && acc_fprintf(&written, stream, "%s", delim) < 0)
366                         return -1;
367
368                 struct value element;
369                 if (value_init_element(&element, value, i) < 0)
370                         return -1;
371                 int o = format_argument(stream, &element, arguments);
372                 value_destroy(&element);
373                 if (o < 0)
374                         return -1;
375                 written += o;
376         }
377         if (acc_fprintf(&written, stream, "%s", close) < 0)
378                 return -1;
379         if (i == maxlen && !before && acc_fprintf(&written, stream, "...") < 0)
380                 return -1;
381
382         return written;
383 }
384
385 static int
386 toplevel_format_lens(struct lens *lens, FILE *stream,
387                      struct value *value, struct value_dict *arguments,
388                      enum int_fmt_t int_fmt)
389 {
390         switch (value->type->type) {
391         case ARGTYPE_VOID:
392                 return fprintf(stream, "<void>");
393
394         case ARGTYPE_SHORT:
395         case ARGTYPE_INT:
396         case ARGTYPE_LONG:
397                 return format_integer(stream, value, int_fmt, arguments);
398
399         case ARGTYPE_USHORT:
400         case ARGTYPE_UINT:
401         case ARGTYPE_ULONG:
402                 if (int_fmt == INT_FMT_i || int_fmt == INT_FMT_default)
403                         int_fmt = INT_FMT_u;
404                 return format_integer(stream, value, int_fmt, arguments);
405
406         case ARGTYPE_CHAR:
407                 if (int_fmt == INT_FMT_default)
408                         return format_naked_char(stream, value, arguments);
409                 return format_integer(stream, value, int_fmt, arguments);
410
411         case ARGTYPE_FLOAT:
412         case ARGTYPE_DOUBLE:
413                 return format_floating(stream, value, arguments, int_fmt);
414
415         case ARGTYPE_STRUCT:
416                 return format_struct(stream, value, arguments);
417
418         case ARGTYPE_POINTER:
419                 if (value->type->u.array_info.elt_type->type != ARGTYPE_VOID)
420                         return format_pointer(stream, value, arguments);
421                 return format_integer(stream, value, INT_FMT_x, arguments);
422
423         case ARGTYPE_ARRAY:
424                 return format_array(stream, value, arguments,
425                                     value->type->u.array_info.length,
426                                     options.arraylen, 1, "[ ", " ]", ", ");
427         }
428         abort();
429 }
430
431 static int
432 default_lens_format_cb(struct lens *lens, FILE *stream,
433                        struct value *value, struct value_dict *arguments)
434 {
435         return toplevel_format_lens(lens, stream, value, arguments,
436                                     INT_FMT_default);
437 }
438
439 struct lens default_lens = {
440         .format_cb = default_lens_format_cb,
441 };
442
443
444 static int
445 blind_lens_format_cb(struct lens *lens, FILE *stream,
446                      struct value *value, struct value_dict *arguments)
447 {
448         return 0;
449 }
450
451 struct lens blind_lens = {
452         .format_cb = blind_lens_format_cb,
453 };
454
455
456 static int
457 octal_lens_format_cb(struct lens *lens, FILE *stream,
458                      struct value *value, struct value_dict *arguments)
459 {
460         return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_o);
461 }
462
463 struct lens octal_lens = {
464         .format_cb = octal_lens_format_cb,
465 };
466
467
468 static int
469 hex_lens_format_cb(struct lens *lens, FILE *stream,
470                    struct value *value, struct value_dict *arguments)
471 {
472         return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_x);
473 }
474
475 struct lens hex_lens = {
476         .format_cb = hex_lens_format_cb,
477 };
478
479
480 static int
481 dec_lens_format_cb(struct lens *lens, FILE *stream,
482                    struct value *value, struct value_dict *arguments)
483 {
484         return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_u);
485 }
486
487 struct lens dec_lens = {
488         .format_cb = dec_lens_format_cb,
489 };
490
491
492 static int
493 guess_lens_format_cb(struct lens *lens, FILE *stream,
494                      struct value *value, struct value_dict *arguments)
495 {
496         return toplevel_format_lens(lens, stream, value, arguments,
497                                     INT_FMT_unknown);
498 }
499
500 struct lens guess_lens = {
501         .format_cb = guess_lens_format_cb,
502 };
503
504
505 static int
506 bool_lens_format_cb(struct lens *lens, FILE *stream,
507                     struct value *value, struct value_dict *arguments)
508 {
509         switch (value->type->type) {
510         case ARGTYPE_VOID:
511         case ARGTYPE_FLOAT:
512         case ARGTYPE_DOUBLE:
513         case ARGTYPE_STRUCT:
514         case ARGTYPE_POINTER:
515         case ARGTYPE_ARRAY:
516                 return toplevel_format_lens(lens, stream, value,
517                                             arguments, INT_FMT_default);
518
519                 int zero;
520         case ARGTYPE_SHORT:
521         case ARGTYPE_INT:
522         case ARGTYPE_LONG:
523         case ARGTYPE_USHORT:
524         case ARGTYPE_UINT:
525         case ARGTYPE_ULONG:
526         case ARGTYPE_CHAR:
527                 if ((zero = value_is_zero(value, arguments)) < 0)
528                         return -1;
529                 if (zero)
530                         return fprintf(stream, "false");
531                 else
532                         return fprintf(stream, "true");
533         }
534         abort();
535 }
536
537 struct lens bool_lens = {
538         .format_cb = bool_lens_format_cb,
539 };
540
541
542 static int
543 string_lens_format_cb(struct lens *lens, FILE *stream,
544                       struct value *value, struct value_dict *arguments)
545 {
546         switch (value->type->type) {
547         case ARGTYPE_POINTER:
548                 /* This should really be written as either "string",
549                  * or, if lens, then string(array(char, zero)*).  But
550                  * I suspect people are so used to the char * C idiom,
551                  * that string(char *) might actually turn up.  So
552                  * let's just support it.  */
553                 if (value->type->u.ptr_info.info->type == ARGTYPE_CHAR) {
554                         struct arg_type_info info[2];
555                         type_init_array(&info[1],
556                                         value->type->u.ptr_info.info, 0,
557                                         expr_node_zero(), 0);
558                         type_init_pointer(&info[0], &info[1], 0);
559                         info->lens = lens;
560                         info->own_lens = 0;
561                         struct value tmp;
562                         if (value_clone(&tmp, value) < 0)
563                                 return -1;
564                         value_set_type(&tmp, info, 0);
565                         int ret = string_lens_format_cb(lens, stream, &tmp,
566                                                         arguments);
567                         type_destroy(&info[0]);
568                         type_destroy(&info[1]);
569                         value_destroy(&tmp);
570                         return ret;
571                 }
572
573                 /* fall-through */
574         case ARGTYPE_VOID:
575         case ARGTYPE_FLOAT:
576         case ARGTYPE_DOUBLE:
577         case ARGTYPE_STRUCT:
578         case ARGTYPE_SHORT:
579         case ARGTYPE_INT:
580         case ARGTYPE_LONG:
581         case ARGTYPE_USHORT:
582         case ARGTYPE_UINT:
583         case ARGTYPE_ULONG:
584                 return toplevel_format_lens(lens, stream, value,
585                                             arguments, INT_FMT_default);
586
587         case ARGTYPE_CHAR:
588                 return format_char(stream, value, arguments);
589
590         case ARGTYPE_ARRAY:
591                 return format_array(stream, value, arguments,
592                                     value->type->u.array_info.length,
593                                     options.strlen, 0, "\"", "\"", "");
594         }
595         abort();
596 }
597
598 struct lens string_lens = {
599         .format_cb = string_lens_format_cb,
600 };
601
602 static int
603 out_bits(FILE *stream, size_t low, size_t high)
604 {
605         if (low == high)
606                 return fprintf(stream, "%zd", low);
607         else
608                 return fprintf(stream, "%zd-%zd", low, high);
609 }
610
611 static unsigned
612 bitcount(unsigned u)
613 {
614         int c = 0;
615         for (; u > 0; u &= u - 1)
616                 c++;
617         return c;
618 }
619
620 static int
621 bitvect_lens_format_cb(struct lens *lens, FILE *stream,
622                        struct value *value, struct value_dict *arguments)
623 {
624         unsigned char *data = value_get_data(value, arguments);
625         if (data == NULL)
626                 return -1;
627         size_t sz = type_sizeof(value->inferior, value->type);
628         if (sz == (size_t)-1)
629                 return -1;
630
631         size_t i;
632         unsigned char buf[sz];
633         switch ((int)value->type->type) {
634                 union bitvect_integral_64
635                 {
636                         uint8_t u8;
637                         uint16_t u16;
638                         uint32_t u32;
639                         uint64_t u64;
640                         unsigned char buf[0];
641                 } bv;
642
643         case ARGTYPE_POINTER:
644                 return format_pointer(stream, value, arguments);
645
646         case ARGTYPE_STRUCT:
647         case ARGTYPE_ARRAY:
648                 break;
649
650         default:
651                 assert(sz <= sizeof(bv));
652                 memmove(bv.buf, data, sz);
653
654                 if (sz == 1)
655                         bv.u64 = bv.u8;
656                 else if (sz == 2)
657                         bv.u64 = bv.u16;
658                 else if (sz == 4)
659                         bv.u64 = bv.u32;
660
661                 for (i = 0; i < sz; ++i) {
662                         buf[i] = bv.u64 & 0xff;
663                         bv.u64 >>= 8;
664                 }
665                 data = buf;
666         }
667
668         size_t bits = 0;
669         for (i = 0; i < sz; ++i)
670                 bits += bitcount(data[i]);
671
672         /* If there's more 1's than 0's, show inverse.  */
673         unsigned neg = bits > sz * 4 ? 0xff : 0x00;
674
675         int o = 0;
676         if (acc_fprintf(&o, stream, "%s<", "~" + (neg == 0x00)) < 0)
677                 return -1;
678
679         size_t bitno = 0;
680         ssize_t low = -1;
681         for (i = 0; i < sz; ++i) {
682                 unsigned char m;
683                 unsigned char d = data[i] ^ neg;
684                 for (m = 0x01; m != 0; m <<= 1) {
685                         int bit = !!(m & d);
686                         if (low < 0) {
687                                 if (bit) {
688                                         if (low == -2
689                                             && acc_fprintf(&o, stream, ",") < 0)
690                                                 return -1;
691                                         low = bitno;
692                                 }
693                         } else if (!bit) {
694                                 if (account_output(&o, out_bits(stream, low,
695                                                                 bitno-1)) < 0)
696                                         return -1;
697                                 low = -2;
698                         }
699                         bitno++;
700                 }
701         }
702         if (low >= 0 && account_output(&o, out_bits(stream, low, bitno-1)) < 0)
703                 return -1;
704
705         if (fputc('>', stream) < 0)
706                 return -1;
707         o += 1;
708
709         return o;
710 }
711
712 struct lens bitvect_lens = {
713         .format_cb = bitvect_lens_format_cb,
714 };