diff options
author | Petr Machata <pmachata@redhat.com> | 2012-11-20 02:00:16 +0100 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2012-11-20 02:36:18 +0100 |
commit | ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207 (patch) | |
tree | 00e24322a2282dbb783dd72a37e514eb9e958ba9 | |
parent | 3219c86c7fa6d5464fe4b14ce038002851d0d5cc (diff) | |
download | ltrace-ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207.tar.gz |
Add lens "bitvec" for displaying objects as bit vectors
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | lens_default.c | 126 | ||||
-rw-r--r-- | lens_default.h | 5 | ||||
-rw-r--r-- | ltrace.conf.5 | 22 | ||||
-rw-r--r-- | read_config_file.c | 1 | ||||
-rw-r--r-- | testsuite/ltrace.main/parameters2.exp | 29 |
6 files changed, 185 insertions, 2 deletions
@@ -29,6 +29,10 @@ Please read ltrace.conf(5) man page, chapter "recursive structures", to learn about this new feature. +*** New lens "bitvec" is available + This allows displaying various data types as bit vectors. Please + read ltrace.conf(5) to learn more. + * Version 0.7.0 ** Tracing *** Full support for tracing multi-threaded processes diff --git a/lens_default.c b/lens_default.c index 7ad2ee4..093b803 100644 --- a/lens_default.c +++ b/lens_default.c @@ -468,6 +468,18 @@ struct lens hex_lens = { static int +dec_lens_format_cb(struct lens *lens, FILE *stream, + struct value *value, struct value_dict *arguments) +{ + return toplevel_format_lens(lens, stream, value, arguments, INT_FMT_u); +} + +struct lens dec_lens = { + .format_cb = dec_lens_format_cb, +}; + + +static int guess_lens_format_cb(struct lens *lens, FILE *stream, struct value *value, struct value_dict *arguments) { @@ -576,3 +588,117 @@ string_lens_format_cb(struct lens *lens, FILE *stream, struct lens string_lens = { .format_cb = string_lens_format_cb, }; + +static int +out_bits(FILE *stream, size_t low, size_t high) +{ + if (low == high) + return fprintf(stream, "%zd", low); + else + return fprintf(stream, "%zd-%zd", low, high); +} + +static unsigned +bitcount(unsigned u) +{ + int c = 0; + for (; u > 0; u &= u - 1) + c++; + return c; +} + +static int +bitvect_lens_format_cb(struct lens *lens, FILE *stream, + struct value *value, struct value_dict *arguments) +{ + unsigned char *data = value_get_data(value, arguments); + if (data == NULL) + return -1; + size_t sz = type_sizeof(value->inferior, value->type); + if (sz == (size_t)-1) + return -1; + + size_t i; + unsigned char buf[sz]; + switch ((int)value->type->type) { + union bitvect_integral_64 + { + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + unsigned char buf[0]; + } bv; + + case ARGTYPE_POINTER: + return format_pointer(stream, value, arguments); + + case ARGTYPE_STRUCT: + case ARGTYPE_ARRAY: + break; + + default: + assert(sz <= sizeof(bv)); + memmove(bv.buf, data, sz); + + if (sz == 1) + bv.u64 = bv.u8; + else if (sz == 2) + bv.u64 = bv.u16; + else if (sz == 4) + bv.u64 = bv.u32; + + for (i = 0; i < sz; ++i) { + buf[i] = bv.u64 & 0xff; + bv.u64 >>= 8; + } + data = buf; + } + + size_t bits = 0; + for (i = 0; i < sz; ++i) + bits += bitcount(data[i]); + + /* If there's more 1's than 0's, show inverse. */ + unsigned neg = bits > sz * 4 ? 0xff : 0x00; + + int o = 0; + if (acc_fprintf(&o, stream, "%s<", "~" + (neg == 0x00)) < 0) + return -1; + + size_t bitno = 0; + ssize_t low = -1; + for (i = 0; i < sz; ++i) { + unsigned char m; + unsigned char d = data[i] ^ neg; + for (m = 0x01; m != 0; m <<= 1) { + int bit = !!(m & d); + if (low < 0) { + if (bit) { + if (low == -2 + && acc_fprintf(&o, stream, ",") < 0) + return -1; + low = bitno; + } + } else if (!bit) { + if (account_output(&o, out_bits(stream, low, + bitno-1)) < 0) + return -1; + low = -2; + } + bitno++; + } + } + if (low >= 0 && account_output(&o, out_bits(stream, low, bitno-1)) < 0) + return -1; + + if (fputc('>', stream) < 0) + return -1; + o += 1; + + return o; +} + +struct lens bitvect_lens = { + .format_cb = bitvect_lens_format_cb, +}; diff --git a/lens_default.h b/lens_default.h index 9a9d0c6..1206ffc 100644 --- a/lens_default.h +++ b/lens_default.h @@ -1,6 +1,6 @@ /* * This file is part of ltrace. - * Copyright (C) 2011 Petr Machata, Red Hat Inc. + * Copyright (C) 2011, 2012 Petr Machata, Red Hat Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -46,4 +46,7 @@ extern struct lens guess_lens; /* A lens for strings. */ extern struct lens string_lens; +/* A lens for bit vector. */ +extern struct lens bitvect_lens; + #endif /* LENS_DEFAULT_H */ diff --git a/ltrace.conf.5 b/ltrace.conf.5 index 2b166fb..5d3b472 100644 --- a/ltrace.conf.5 +++ b/ltrace.conf.5 @@ -139,6 +139,28 @@ The argument is not shown in argument list. Arguments with zero value are shown as "false", other are shown as "true". +.TP +.B bitvec(\fITYPE\fB) +Underlying argument is interpreted as a bit vector and a summary of +bits set in the vector is displayed. For example if bits 3,4,5 and 7 +of the bit vector are set, ltrace shows <3-5,7>. Empty bit vector is +displayed as <>. If there are more bits set than unset, inverse is +shown instead: e.g. ~<0> when a number 0xfffffffe is displayed. Full +set is thus displayed ~<>. + +If the underlying type is integral, then bits are shown in their +natural little-endian order, with LSB being bit 0. +E.g. \fBbitvec(ushort)\fR with value 0x0102 would be displayed as +<1,8>, irrespective of underlying byte order. + +For other data types (notably structures and arrays), the underlying +data is interpreted byte after byte. Bit 0 of first byte has number +0, bit 0 of second byte number 8, and so on. Thus +\fBbitvec(struct(int))\fR is endian sensitive, and will show bytes +comprising the integer in their memory order. Pointers are first +dereferenced, thus \fBbitvec(array(char, \fR32\fB)*)\fR is actually a +pointer to 256-bit bit vector. + .PP .B string(\fITYPE\fB) .br diff --git a/read_config_file.c b/read_config_file.c index 58a4a14..724d99e 100644 --- a/read_config_file.c +++ b/read_config_file.c @@ -954,6 +954,7 @@ static struct named_lens { } lenses[] = { { "hide", &blind_lens }, { "octal", &octal_lens }, + { "bitvec", &bitvect_lens }, { "hex", &hex_lens }, { "bool", &bool_lens }, { "guess", &guess_lens }, diff --git a/testsuite/ltrace.main/parameters2.exp b/testsuite/ltrace.main/parameters2.exp index e13f9b3..ff61d21 100644 --- a/testsuite/ltrace.main/parameters2.exp +++ b/testsuite/ltrace.main/parameters2.exp @@ -126,7 +126,7 @@ proc ltraceParamTest {conf cdecl libcode maincode match} { } ltraceParamTest { - typedef hexptr = hex(uint); + typedef hexptr = hex(uint*); void fun(hexptr); } { void fun(unsigned *arg); @@ -139,4 +139,31 @@ ltraceParamTest { {{fun\(0x123\) *= <void>} == 1} } +ltraceParamTest { + void fun(bitvec(uint)); + void fun2(bitvec(array(char, 32)*)); +} { + void fun(unsigned i); + void fun2(unsigned char *arr); +} { + void fun(unsigned i) {} + void fun2(unsigned char *arr) {} +} { + fun(0); + fun(0x123); + fun(0xfffffffe); + fun(0xffffffff); + + unsigned char bytes[32] = {0x00}; + bytes[1] = 0xff; + bytes[31] = 0x80; + fun2(bytes); +} { + {{fun\(<>\) *= <void>} == 1} + {{fun\(<0-1,5,8>\) *= <void>} == 1} + {{fun\(~<0>\) *= <void>} == 1} + {{fun\(~<>\) *= <void>} == 1} + {{fun2\(<8-15,255>\) *= <void>} == 1} +} + ltraceDone |