aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2012-11-20 02:00:16 +0100
committerPetr Machata <pmachata@redhat.com>2012-11-20 02:36:18 +0100
commitec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207 (patch)
tree00e24322a2282dbb783dd72a37e514eb9e958ba9
parent3219c86c7fa6d5464fe4b14ce038002851d0d5cc (diff)
downloadltrace-ec4ab256e5c7fe1596dd90a3c8e8d4b052ca1207.tar.gz
Add lens "bitvec" for displaying objects as bit vectors
-rw-r--r--NEWS4
-rw-r--r--lens_default.c126
-rw-r--r--lens_default.h5
-rw-r--r--ltrace.conf.522
-rw-r--r--read_config_file.c1
-rw-r--r--testsuite/ltrace.main/parameters2.exp29
6 files changed, 185 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index 8e33596..fc07f31 100644
--- a/NEWS
+++ b/NEWS
@@ -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