From f93fca700f0fd70532132ae535f48c1a936abb0a Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Fri, 9 Oct 2015 14:12:51 -0700 Subject: [PATCH] [Ada] split data unpacking code out of ada_value_primitive_packed_val. This patch is just preparation work which splits the function ada_value_primitive_packed_val into two function: one which unpacks the data, and the other which now uses it to implement ada_value_primitive_packed_val. This simplifies a bit ada_value_primitive_packed_val, but will also allow us to use the new function to unpack data without actually creating a struct value as a result. gdb/ChangeLog: * ada-lang.c (ada_unpack_from_contents): New function, extracted from ada_value_primitive_packed_val. (ada_value_primitive_packed_val): Replace extracted out code by call to ada_unpack_from_contents. --- gdb/ChangeLog | 7 ++ gdb/ada-lang.c | 217 ++++++++++++++++++++++++++++--------------------- 2 files changed, 133 insertions(+), 91 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 968992e908c..a511592c5ec 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2015-10-09 Joel Brobecker + + * ada-lang.c (ada_unpack_from_contents): New function, + extracted from ada_value_primitive_packed_val. + (ada_value_primitive_packed_val): Replace extracted out code + by call to ada_unpack_from_contents. + 2015-10-09 Joel Brobecker * ada-lang.c (ada_value_primitive_packed_val): Reorder local diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 1dbbb077407..6947d76f819 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -2382,24 +2382,23 @@ has_negatives (struct type *type) } } +/* With SRC being a buffer containing BIT_SIZE bits of data at BIT_OFFSET, + unpack that data into UNPACKED. UNPACKED_LEN is the size in bytes of + the unpacked buffer. -/* Create a new value of type TYPE from the contents of OBJ starting - at byte OFFSET, and bit offset BIT_OFFSET within that byte, - proceeding for BIT_SIZE bits. If OBJ is an lval in memory, then - assigning through the result will set the field fetched from. - VALADDR is ignored unless OBJ is NULL, in which case, - VALADDR+OFFSET must address the start of storage containing the - packed value. The value returned in this case is never an lval. - Assumes 0 <= BIT_OFFSET < HOST_CHAR_BIT. */ + IS_BIG_ENDIAN is nonzero if the data is stored in big endian mode, + zero otherwise. -struct value * -ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, - long offset, int bit_offset, int bit_size, - struct type *type) -{ - struct value *v; + IS_SIGNED_TYPE is nonzero if the data corresponds to a signed type. - gdb_byte *src; /* First byte containing data to unpack */ + IS_SCALAR is nonzero if the data corresponds to a signed type. */ + +static void +ada_unpack_from_contents (const gdb_byte *src, int bit_offset, int bit_size, + gdb_byte *unpacked, int unpacked_len, + int is_big_endian, int is_signed_type, + int is_scalar) +{ int src_len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8; int src_idx; /* Index into the source area */ int src_bytes_left; /* Number of source bytes left to process. */ @@ -2407,7 +2406,6 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, int unusedLS; /* Number of bits in next significant byte of source that are unused */ - gdb_byte *unpacked; int unpacked_idx; /* Index into the unpacked buffer */ int unpacked_bytes_left; /* Number of bytes left to set in unpacked. */ @@ -2417,86 +2415,31 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, /* Transmit bytes from least to most significant; delta is the direction the indices move. */ - int delta = gdbarch_bits_big_endian (get_type_arch (type)) ? -1 : 1; - - type = ada_check_typedef (type); - - if (obj == NULL) - { - v = allocate_value (type); - src = (gdb_byte *) valaddr + offset; - } - else if (VALUE_LVAL (obj) == lval_memory && value_lazy (obj)) - { - v = value_at (type, value_address (obj) + offset); - type = value_type (v); - if (TYPE_LENGTH (type) * HOST_CHAR_BIT < bit_size) - { - /* This can happen in the case of an array of dynamic objects, - where the size of each element changes from element to element. - In that case, we're initially given the array stride, but - after resolving the element type, we find that its size is - less than this stride. In that case, adjust bit_size to - match TYPE's length, and recompute LEN accordingly. */ - bit_size = TYPE_LENGTH (type) * HOST_CHAR_BIT; - src_len = TYPE_LENGTH (type) + (bit_offset + HOST_CHAR_BIT - 1) / 8; - } - src = alloca (src_len); - read_memory (value_address (v), src, src_len); - } - else - { - v = allocate_value (type); - src = (gdb_byte *) value_contents (obj) + offset; - } - - if (obj != NULL) - { - long new_offset = offset; - - set_value_component_location (v, obj); - set_value_bitpos (v, bit_offset + value_bitpos (obj)); - set_value_bitsize (v, bit_size); - if (value_bitpos (v) >= HOST_CHAR_BIT) - { - ++new_offset; - set_value_bitpos (v, value_bitpos (v) - HOST_CHAR_BIT); - } - set_value_offset (v, new_offset); - - /* Also set the parent value. This is needed when trying to - assign a new value (in inferior memory). */ - set_value_parent (v, obj); - } - else - set_value_bitsize (v, bit_size); - unpacked = (gdb_byte *) value_contents (v); + int delta = is_big_endian ? -1 : 1; srcBitsLeft = bit_size; src_bytes_left = src_len; - unpacked_bytes_left = TYPE_LENGTH (type); + unpacked_bytes_left = unpacked_len; sign = 0; - if (bit_size == 0) - { - memset (unpacked, 0, TYPE_LENGTH (type)); - return v; - } - else if (gdbarch_bits_big_endian (get_type_arch (type))) + + if (is_big_endian) { src_idx = src_len - 1; - if (has_negatives (type) - && ((src[0] << bit_offset) & (1 << (HOST_CHAR_BIT - 1)))) + if (is_signed_type + && ((src[0] << bit_offset) & (1 << (HOST_CHAR_BIT - 1)))) sign = ~0; unusedLS = (HOST_CHAR_BIT - (bit_size + bit_offset) % HOST_CHAR_BIT) % HOST_CHAR_BIT; - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: - case TYPE_CODE_UNION: - case TYPE_CODE_STRUCT: + if (is_scalar) + { + accumSize = 0; + unpacked_idx = unpacked_len - 1; + } + else + { /* Non-scalar values must be aligned at a byte boundary... */ accumSize = (HOST_CHAR_BIT - bit_size % HOST_CHAR_BIT) % HOST_CHAR_BIT; @@ -2504,12 +2447,7 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, of the target. */ unpacked_idx = (bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT - 1; unpacked_bytes_left = unpacked_idx + 1; - break; - default: - accumSize = 0; - unpacked_idx = TYPE_LENGTH (type) - 1; - break; - } + } } else { @@ -2519,7 +2457,7 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, unusedLS = bit_offset; accumSize = 0; - if (has_negatives (type) && (src[src_len - 1] & (1 << sign_bit_offset))) + if (is_signed_type && (src[src_len - 1] & (1 << sign_bit_offset))) sign = ~0; } @@ -2561,6 +2499,103 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, unpacked_bytes_left -= 1; unpacked_idx += delta; } +} + +/* Create a new value of type TYPE from the contents of OBJ starting + at byte OFFSET, and bit offset BIT_OFFSET within that byte, + proceeding for BIT_SIZE bits. If OBJ is an lval in memory, then + assigning through the result will set the field fetched from. + VALADDR is ignored unless OBJ is NULL, in which case, + VALADDR+OFFSET must address the start of storage containing the + packed value. The value returned in this case is never an lval. + Assumes 0 <= BIT_OFFSET < HOST_CHAR_BIT. */ + +struct value * +ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, + long offset, int bit_offset, int bit_size, + struct type *type) +{ + struct value *v; + gdb_byte *src; /* First byte containing data to unpack */ + int src_len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8; + gdb_byte *unpacked; + int is_scalar; + + type = ada_check_typedef (type); + + if (obj == NULL) + { + v = allocate_value (type); + src = (gdb_byte *) valaddr + offset; + } + else if (VALUE_LVAL (obj) == lval_memory && value_lazy (obj)) + { + v = value_at (type, value_address (obj) + offset); + type = value_type (v); + if (TYPE_LENGTH (type) * HOST_CHAR_BIT < bit_size) + { + /* This can happen in the case of an array of dynamic objects, + where the size of each element changes from element to element. + In that case, we're initially given the array stride, but + after resolving the element type, we find that its size is + less than this stride. In that case, adjust bit_size to + match TYPE's length, and recompute LEN accordingly. */ + bit_size = TYPE_LENGTH (type) * HOST_CHAR_BIT; + src_len = TYPE_LENGTH (type) + (bit_offset + HOST_CHAR_BIT - 1) / 8; + } + src = alloca (src_len); + read_memory (value_address (v), src, src_len); + } + else + { + v = allocate_value (type); + src = (gdb_byte *) value_contents (obj) + offset; + } + + if (obj != NULL) + { + long new_offset = offset; + + set_value_component_location (v, obj); + set_value_bitpos (v, bit_offset + value_bitpos (obj)); + set_value_bitsize (v, bit_size); + if (value_bitpos (v) >= HOST_CHAR_BIT) + { + ++new_offset; + set_value_bitpos (v, value_bitpos (v) - HOST_CHAR_BIT); + } + set_value_offset (v, new_offset); + + /* Also set the parent value. This is needed when trying to + assign a new value (in inferior memory). */ + set_value_parent (v, obj); + } + else + set_value_bitsize (v, bit_size); + unpacked = (gdb_byte *) value_contents (v); + + if (bit_size == 0) + { + memset (unpacked, 0, TYPE_LENGTH (type)); + return v; + } + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + case TYPE_CODE_UNION: + case TYPE_CODE_STRUCT: + is_scalar = 0; + break; + default: + is_scalar = 1; + break; + } + + ada_unpack_from_contents (src, bit_offset, bit_size, + unpacked, TYPE_LENGTH (type), + gdbarch_bits_big_endian (get_type_arch (type)), + has_negatives (type), is_scalar); if (is_dynamic_type (value_type (v))) v = value_from_contents_and_address (value_type (v), value_contents (v), -- 2.30.2