gdb: Fix numerical field extraction for target description "flags"
The "val_print_type_code_flags ()" function is responsible for extraction of fields for "flags" data type. These data types are used when describing a custom register type in a target description XML. The logic used for the extraction though is not sound: unsigned field_len = TYPE_FIELD_BITSIZE (type, field); ULONGEST field_val = val >> (TYPE_FIELD_BITPOS (type, field) - field_len + 1); TYPE_FIELD_BITSIZE: The bit length of the field to be extracted. TYPE_FIELD_BITPOS: The starting position of the field; 0 is LSB. val: The register value. Imagine you have a field that starts at position 1 and its length is 4 bits. According to the third line of the code snippet the shifting right would become "val >> -2", or "val >> 0xfff...fe" to be precise. That will result in a "field_val" of 0. The correct extraction should be: ULONGEST field_val = val >> TYPE_FIELD_BITPOS (type, field); The rest of the algorithm that masks out the higher bits is OK. Co-Authored-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
parent
0264bf6fe3
commit
c9bd98593b
1 changed files with 34 additions and 2 deletions
|
@ -43,6 +43,8 @@
|
|||
#include "c-lang.h"
|
||||
#include "cp-abi.h"
|
||||
#include "inferior.h"
|
||||
#include "gdbsupport/selftest.h"
|
||||
#include "selftest-arch.h"
|
||||
|
||||
/* Maximum number of wchars returned from wchar_iterate. */
|
||||
#define MAX_WCHARS 4
|
||||
|
@ -1221,8 +1223,7 @@ val_print_type_code_flags (struct type *type, struct value *original_value,
|
|||
else
|
||||
{
|
||||
unsigned field_len = TYPE_FIELD_BITSIZE (type, field);
|
||||
ULONGEST field_val
|
||||
= val >> (TYPE_FIELD_BITPOS (type, field) - field_len + 1);
|
||||
ULONGEST field_val = val >> TYPE_FIELD_BITPOS (type, field);
|
||||
|
||||
if (field_len < sizeof (ULONGEST) * TARGET_CHAR_BIT)
|
||||
field_val &= ((ULONGEST) 1 << field_len) - 1;
|
||||
|
@ -3137,10 +3138,41 @@ make_value_print_options_def_group (value_print_options *opts)
|
|||
return {{value_print_option_defs}, opts};
|
||||
}
|
||||
|
||||
#if GDB_SELF_TEST
|
||||
|
||||
/* Test printing of TYPE_CODE_FLAGS values. */
|
||||
|
||||
static void
|
||||
test_print_flags (gdbarch *arch)
|
||||
{
|
||||
type *flags_type = arch_flags_type (arch, "test_type", 32);
|
||||
type *field_type = builtin_type (arch)->builtin_uint32;
|
||||
|
||||
/* Value: 1010 1010
|
||||
Fields: CCCB BAAA */
|
||||
append_flags_type_field (flags_type, 0, 3, field_type, "A");
|
||||
append_flags_type_field (flags_type, 3, 2, field_type, "B");
|
||||
append_flags_type_field (flags_type, 5, 3, field_type, "C");
|
||||
|
||||
value *val = allocate_value (flags_type);
|
||||
gdb_byte *contents = value_contents_writeable (val);
|
||||
store_unsigned_integer (contents, 4, gdbarch_byte_order (arch), 0xaa);
|
||||
|
||||
string_file out;
|
||||
val_print_type_code_flags (flags_type, val, 0, &out);
|
||||
SELF_CHECK (out.string () == "[ A=2 B=1 C=5 ]");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void _initialize_valprint ();
|
||||
void
|
||||
_initialize_valprint ()
|
||||
{
|
||||
#if GDB_SELF_TEST
|
||||
selftests::register_test_foreach_arch ("print-flags", test_print_flags);
|
||||
#endif
|
||||
|
||||
cmd_list_element *cmd;
|
||||
|
||||
cmd_list_element *set_print_cmd
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue