aboutsummaryrefslogtreecommitdiffstats
path: root/util.c
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2013-11-09 20:40:31 +0100
committerDenys Vlasenko <dvlasenk@redhat.com>2013-11-09 20:40:31 +0100
commitb338f2d65ea9d911a0fead3229ba336bc30e6214 (patch)
tree8a37a1bd344653fdd4d684418556db3b3d578b6a /util.c
parent1297a513dad3ce3bc6f8472ed592a865aea18fac (diff)
downloadandroid_external_strace-b338f2d65ea9d911a0fead3229ba336bc30e6214.tar.gz
android_external_strace-b338f2d65ea9d911a0fead3229ba336bc30e6214.tar.bz2
android_external_strace-b338f2d65ea9d911a0fead3229ba336bc30e6214.zip
Fix select decoding on e.g. 32-bit ppc process by 64-bit strace.
Added next_set_bit() function which finds the next set bit, properly taking into account word size of the traced process. Use it in decode_select() instead of fd_isset(). Also, properly round fdsize up to word size of traced process, not to strace's word size. Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'util.c')
-rw-r--r--util.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/util.c b/util.c
index 30a7f195..47c8734f 100644
--- a/util.c
+++ b/util.c
@@ -160,6 +160,53 @@ stpcpy(char *dst, const char *src)
}
#endif
+/* Find a next bit which is set.
+ * Starts testing at cur_bit.
+ * Returns -1 if no more bits are set.
+ *
+ * We never touch bytes we don't need to.
+ * On big-endian, array is assumed to consist of
+ * current_wordsize wide words: for example, is current_wordsize is 4,
+ * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
+ * On little-endian machines, word size is immaterial.
+ */
+int
+next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
+{
+ const unsigned endian = 1;
+ int little_endian = *(char*)&endian;
+
+ const uint8_t *array = bit_array;
+ unsigned pos = cur_bit / 8;
+ unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
+
+ for (;;) {
+ uint8_t bitmask;
+ uint8_t cur_byte;
+
+ if (cur_bit >= size_bits)
+ return -1;
+ cur_byte = array[pos ^ pos_xor_mask];
+ if (cur_byte == 0) {
+ cur_bit = (cur_bit + 8) & (-8);
+ pos++;
+ continue;
+ }
+ bitmask = 1 << (cur_bit & 7);
+ for (;;) {
+ if (cur_byte & bitmask)
+ return cur_bit;
+ cur_bit++;
+ if (cur_bit >= size_bits)
+ return -1;
+ bitmask <<= 1;
+ /* This check *can't be* optimized out: */
+ if (bitmask == 0)
+ break;
+ }
+ pos++;
+ }
+}
/*
* Print entry in struct xlat table, if there.
*/