Convert the unavailable vector to be bit, not byte, based.
https://sourceware.org/ml/gdb-patches/2013-12/msg00144.html The vector of unavailable parts of a value is currently byte based. Given that we can model a value down to the bit level, we can potentially loose information with the current implementation. After this patch we model the unavailable information in bits. gdb/ChangeLog * dwarf2loc.c (read_pieced_value): Mark bits, not bytes unavailable, use correct bit length. * value.c (struct value): Extend comment on unavailable to indicate that it is bit based. (value_bits_available): New function. (value_bytes_available): Call value_bits_available. (value_entirely_available): Check against the bit length, not byte length. (mark_value_bits_unavailable): New function. (mark_value_bytes_unavailable): Move contents to mark_value_bits_unavailable, call to same. (memcmp_with_bit_offsets): New function. (value_available_contents_bits_eq): New function, takes the functionality from value_available_contents_eq but uses memcmp_with_bit_offsets now, and is bit not byte based. (value_available_contents_eq): Move implementation into value_available_contents_bits_eq, call to same. (value_contents_copy_raw): Work on bits, not bytes. (unpack_value_bits_as_long_1): Check availability in bits, not bytes. * value.h (value_bits_available): Declare new function. (mark_value_bits_unavailable): Declare new function. gdb/testsuite/ChangeLog * gdb.trace/unavailable-dwarf-piece.c: New file. * gdb.trace/unavailable-dwarf-piece.exp: New file.
This commit is contained in:
parent
4a357820ad
commit
bdf2220615
@ -1,3 +1,28 @@
|
|||||||
|
2013-12-17 Andrew Burgess <aburgess@broadcom.com>
|
||||||
|
|
||||||
|
* dwarf2loc.c (read_pieced_value): Mark bits, not bytes
|
||||||
|
unavailable, use correct bit length.
|
||||||
|
* value.c (struct value): Extend comment on unavailable to
|
||||||
|
indicate that it is bit based.
|
||||||
|
(value_bits_available): New function.
|
||||||
|
(value_bytes_available): Call value_bits_available.
|
||||||
|
(value_entirely_available): Check against the bit length, not byte
|
||||||
|
length.
|
||||||
|
(mark_value_bits_unavailable): New function.
|
||||||
|
(mark_value_bytes_unavailable): Move contents to
|
||||||
|
mark_value_bits_unavailable, call to same.
|
||||||
|
(memcmp_with_bit_offsets): New function.
|
||||||
|
(value_available_contents_bits_eq): New function, takes the
|
||||||
|
functionality from value_available_contents_eq but uses
|
||||||
|
memcmp_with_bit_offsets now, and is bit not byte based.
|
||||||
|
(value_available_contents_eq): Move implementation into
|
||||||
|
value_available_contents_bits_eq, call to same.
|
||||||
|
(value_contents_copy_raw): Work on bits, not bytes.
|
||||||
|
(unpack_value_bits_as_long_1): Check availability in bits, not
|
||||||
|
bytes.
|
||||||
|
* value.h (value_bits_available): Declare new function.
|
||||||
|
(mark_value_bits_unavailable): Declare new function.
|
||||||
|
|
||||||
2013-12-16 Pierre Muller <muller@sourceware.org>
|
2013-12-16 Pierre Muller <muller@sourceware.org>
|
||||||
|
|
||||||
Fix compilation error for cygwin native build.
|
Fix compilation error for cygwin native build.
|
||||||
|
@ -1709,7 +1709,7 @@ read_pieced_value (struct value *v)
|
|||||||
if (optim)
|
if (optim)
|
||||||
set_value_optimized_out (v, 1);
|
set_value_optimized_out (v, 1);
|
||||||
if (unavail)
|
if (unavail)
|
||||||
mark_value_bytes_unavailable (v, offset, this_size);
|
mark_value_bits_unavailable (v, offset, this_size_bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2013-12-17 Andrew Burgess <aburgess@broadcom.com>
|
||||||
|
|
||||||
|
* gdb.trace/unavailable-dwarf-piece.c: New file.
|
||||||
|
* gdb.trace/unavailable-dwarf-piece.exp: New file.
|
||||||
|
|
||||||
2013-12-15 Yao Qi <yao@codesourcery.com>
|
2013-12-15 Yao Qi <yao@codesourcery.com>
|
||||||
|
|
||||||
* gdb.perf/skip-prologue.c: New.
|
* gdb.perf/skip-prologue.c: New.
|
||||||
|
86
gdb/testsuite/gdb.trace/unavailable-dwarf-piece.c
Normal file
86
gdb/testsuite/gdb.trace/unavailable-dwarf-piece.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
Copyright 2013 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
struct s
|
||||||
|
{
|
||||||
|
unsigned char a;
|
||||||
|
unsigned char b;
|
||||||
|
unsigned char c;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct t
|
||||||
|
{
|
||||||
|
/* First, a complete byte. */
|
||||||
|
unsigned char a;
|
||||||
|
/* Next, 8 single bits. */
|
||||||
|
unsigned char b : 1;
|
||||||
|
unsigned char c : 1;
|
||||||
|
unsigned char d : 1;
|
||||||
|
unsigned char e : 1;
|
||||||
|
unsigned char f : 1;
|
||||||
|
unsigned char g : 1;
|
||||||
|
unsigned char h : 1;
|
||||||
|
unsigned char i : 1;
|
||||||
|
/* Now another byte. */
|
||||||
|
unsigned char j;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
end (void)
|
||||||
|
{
|
||||||
|
/* Nothing. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dummy (void)
|
||||||
|
{
|
||||||
|
/* Nothing. */
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
foo (struct s x, struct s y, struct s z)
|
||||||
|
{
|
||||||
|
dummy ();
|
||||||
|
asm (".global foo_end_lbl\nfoo_end_lbl:");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bar (struct t x, struct t y, struct t z)
|
||||||
|
{
|
||||||
|
dummy ();
|
||||||
|
asm (".global bar_end_lbl\nbar_end_lbl:");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
struct s v = { 0, 1, 2 };
|
||||||
|
struct t w = { 5, 0, 1, 0, 1, 0, 1, 0, 1, 7 };
|
||||||
|
int ans;
|
||||||
|
|
||||||
|
ans = foo (v, v, v);
|
||||||
|
|
||||||
|
end ();
|
||||||
|
|
||||||
|
ans = bar (w, w, w);
|
||||||
|
|
||||||
|
end ();
|
||||||
|
|
||||||
|
return ans;
|
||||||
|
}
|
334
gdb/testsuite/gdb.trace/unavailable-dwarf-piece.exp
Normal file
334
gdb/testsuite/gdb.trace/unavailable-dwarf-piece.exp
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
# Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
load_lib "trace-support.exp"
|
||||||
|
load_lib dwarf.exp
|
||||||
|
|
||||||
|
if {![dwarf2_support]} {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
standard_testfile .c
|
||||||
|
|
||||||
|
set asm_file "${testfile}-dbg.s"
|
||||||
|
set opts {}
|
||||||
|
|
||||||
|
if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile}1.o \
|
||||||
|
object {nodebug}] != "" } {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
Dwarf::assemble $asm_file {
|
||||||
|
declare_labels uchar_label struct_s_label foo_label struct_t_label bar_label
|
||||||
|
|
||||||
|
cu {} {
|
||||||
|
compile_unit {{language @DW_LANG_C}} {
|
||||||
|
uchar_label: DW_TAG_base_type {
|
||||||
|
{name "unsigned char"}
|
||||||
|
{byte_size 1 DW_FORM_sdata}
|
||||||
|
{encoding @DW_ATE_unsigned_char}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct_s_label: DW_TAG_structure_type {
|
||||||
|
{name s}
|
||||||
|
{byte_size 3 DW_FORM_sdata}
|
||||||
|
{decl_file 1}
|
||||||
|
{decl_line 1}
|
||||||
|
} {
|
||||||
|
DW_TAG_member {
|
||||||
|
{name a}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 0
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name b}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name c}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 2
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct_t_label: DW_TAG_structure_type {
|
||||||
|
{name t}
|
||||||
|
{byte_size 3 DW_FORM_sdata}
|
||||||
|
{decl_file 1}
|
||||||
|
{decl_line 1}
|
||||||
|
} {
|
||||||
|
DW_TAG_member {
|
||||||
|
{name a}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 0
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name b}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{byte_size 1 DW_FORM_sdata}
|
||||||
|
{bit_size 1 DW_FORM_sdata}
|
||||||
|
{bit_offset 7 DW_FORM_sdata}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name c}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{byte_size 1 DW_FORM_sdata}
|
||||||
|
{bit_size 1 DW_FORM_sdata}
|
||||||
|
{bit_offset 6 DW_FORM_sdata}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name d}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{byte_size 1 DW_FORM_sdata}
|
||||||
|
{bit_size 1 DW_FORM_sdata}
|
||||||
|
{bit_offset 5 DW_FORM_sdata}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name e}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{byte_size 1 DW_FORM_sdata}
|
||||||
|
{bit_size 1 DW_FORM_sdata}
|
||||||
|
{bit_offset 4 DW_FORM_sdata}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name f}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{byte_size 1 DW_FORM_sdata}
|
||||||
|
{bit_size 1 DW_FORM_sdata}
|
||||||
|
{bit_offset 3 DW_FORM_sdata}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name g}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{byte_size 1 DW_FORM_sdata}
|
||||||
|
{bit_size 1 DW_FORM_sdata}
|
||||||
|
{bit_offset 2 DW_FORM_sdata}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name h}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{byte_size 1 DW_FORM_sdata}
|
||||||
|
{bit_size 1 DW_FORM_sdata}
|
||||||
|
{bit_offset 1 DW_FORM_sdata}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name i}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{byte_size 1 DW_FORM_sdata}
|
||||||
|
{bit_size 1 DW_FORM_sdata}
|
||||||
|
{bit_offset 0 DW_FORM_sdata}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_member {
|
||||||
|
{name j}
|
||||||
|
{type :$uchar_label}
|
||||||
|
{data_member_location {
|
||||||
|
DW_OP_plus_uconst 2
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DW_TAG_subprogram {
|
||||||
|
{name foo}
|
||||||
|
{decl_file 1}
|
||||||
|
{low_pc foo addr}
|
||||||
|
{high_pc foo_end_lbl addr}
|
||||||
|
} {
|
||||||
|
DW_TAG_formal_parameter {
|
||||||
|
{type :$struct_s_label}
|
||||||
|
{name x}
|
||||||
|
{location {
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_piece 2
|
||||||
|
DW_OP_reg0
|
||||||
|
DW_OP_piece 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_formal_parameter {
|
||||||
|
{type :$struct_s_label}
|
||||||
|
{name y}
|
||||||
|
{location {
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_piece 1
|
||||||
|
DW_OP_reg0
|
||||||
|
DW_OP_piece 1
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_piece 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_formal_parameter {
|
||||||
|
{type :$struct_s_label}
|
||||||
|
{name z}
|
||||||
|
{location {
|
||||||
|
DW_OP_reg0
|
||||||
|
DW_OP_piece 1
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_piece 2
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DW_TAG_subprogram {
|
||||||
|
{name bar}
|
||||||
|
{decl_file 1}
|
||||||
|
{low_pc bar addr}
|
||||||
|
{high_pc bar_end_lbl addr}
|
||||||
|
} {
|
||||||
|
DW_TAG_formal_parameter {
|
||||||
|
{type :$struct_t_label}
|
||||||
|
{name x}
|
||||||
|
{location {
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_piece 1
|
||||||
|
DW_OP_reg0
|
||||||
|
DW_OP_bit_piece 1 0
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_bit_piece 7 0
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_piece 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_formal_parameter {
|
||||||
|
{type :$struct_t_label}
|
||||||
|
{name y}
|
||||||
|
{location {
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_piece 1
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_bit_piece 3 0
|
||||||
|
DW_OP_reg0
|
||||||
|
DW_OP_bit_piece 1 0
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_bit_piece 4 0
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_piece 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
DW_TAG_formal_parameter {
|
||||||
|
{type :$struct_t_label}
|
||||||
|
{name z}
|
||||||
|
{location {
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_piece 1
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_bit_piece 7 0
|
||||||
|
DW_OP_reg0
|
||||||
|
DW_OP_bit_piece 1 0
|
||||||
|
DW_OP_lit0
|
||||||
|
DW_OP_stack_value
|
||||||
|
DW_OP_piece 1
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if { [gdb_compile ${asm_file} ${binfile}2.o object {nodebug}] != "" } {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if { [gdb_compile [list ${binfile}1.o ${binfile}2.o] ${binfile} \
|
||||||
|
executable {}] != "" } {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
clean_restart ${testfile}
|
||||||
|
|
||||||
|
if ![runto_main] {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ![gdb_target_supports_trace] {
|
||||||
|
unsupported "target does not support trace"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_breakpoint "end"
|
||||||
|
|
||||||
|
with_test_prefix "tracing foo" {
|
||||||
|
gdb_test "trace foo" ".*"
|
||||||
|
gdb_test_no_output "tstart"
|
||||||
|
gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*"
|
||||||
|
gdb_test_no_output "tstop"
|
||||||
|
|
||||||
|
gdb_test "tfind 0" "Found trace frame 0, tracepoint .*"
|
||||||
|
gdb_test "p/d x" "\\\$${decimal} = {a = 0, b = 0, c = <unavailable>}"
|
||||||
|
gdb_test "p/d y" "\\\$${decimal} = {a = 0, b = <unavailable>, c = 0}"
|
||||||
|
gdb_test "p/d z" "\\\$${decimal} = {a = <unavailable>, b = 0, c = 0}"
|
||||||
|
|
||||||
|
gdb_test "tfind none" "No longer looking at any trace frame.*"
|
||||||
|
}
|
||||||
|
|
||||||
|
with_test_prefix "tracing bar" {
|
||||||
|
gdb_test "trace bar" ".*"
|
||||||
|
gdb_test_no_output "tstart"
|
||||||
|
gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*"
|
||||||
|
gdb_test_no_output "tstop"
|
||||||
|
|
||||||
|
gdb_test "tfind 0" "Found trace frame 0, tracepoint .*"
|
||||||
|
gdb_test "p/d x" "\\\$${decimal} = {a = 0, b = <unavailable>, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0}"
|
||||||
|
gdb_test "p/d y" "\\\$${decimal} = {a = 0, b = 0, c = 0, d = 0, e = <unavailable>, f = 0, g = 0, h = 0, i = 0, j = 0}"
|
||||||
|
gdb_test "p/d z" "\\\$${decimal} = {a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = <unavailable>, j = 0}"
|
||||||
|
|
||||||
|
gdb_test "tfind none" "No longer looking at any trace frame.*"
|
||||||
|
}
|
181
gdb/value.c
181
gdb/value.c
@ -333,18 +333,27 @@ struct value
|
|||||||
|
|
||||||
/* Unavailable ranges in CONTENTS. We mark unavailable ranges,
|
/* Unavailable ranges in CONTENTS. We mark unavailable ranges,
|
||||||
rather than available, since the common and default case is for a
|
rather than available, since the common and default case is for a
|
||||||
value to be available. This is filled in at value read time. */
|
value to be available. This is filled in at value read time. The
|
||||||
|
unavailable ranges are tracked in bits. */
|
||||||
VEC(range_s) *unavailable;
|
VEC(range_s) *unavailable;
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
value_bytes_available (const struct value *value, int offset, int length)
|
value_bits_available (const struct value *value, int offset, int length)
|
||||||
{
|
{
|
||||||
gdb_assert (!value->lazy);
|
gdb_assert (!value->lazy);
|
||||||
|
|
||||||
return !ranges_contain (value->unavailable, offset, length);
|
return !ranges_contain (value->unavailable, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
value_bytes_available (const struct value *value, int offset, int length)
|
||||||
|
{
|
||||||
|
return value_bits_available (value,
|
||||||
|
offset * TARGET_CHAR_BIT,
|
||||||
|
length * TARGET_CHAR_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
value_entirely_available (struct value *value)
|
value_entirely_available (struct value *value)
|
||||||
{
|
{
|
||||||
@ -371,7 +380,8 @@ value_entirely_unavailable (struct value *value)
|
|||||||
struct range *t = VEC_index (range_s, value->unavailable, 0);
|
struct range *t = VEC_index (range_s, value->unavailable, 0);
|
||||||
|
|
||||||
if (t->offset == 0
|
if (t->offset == 0
|
||||||
&& t->length == TYPE_LENGTH (value_enclosing_type (value)))
|
&& t->length == (TARGET_CHAR_BIT *
|
||||||
|
TYPE_LENGTH (value_enclosing_type (value))))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +389,7 @@ value_entirely_unavailable (struct value *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mark_value_bytes_unavailable (struct value *value, int offset, int length)
|
mark_value_bits_unavailable (struct value *value, int offset, int length)
|
||||||
{
|
{
|
||||||
range_s newr;
|
range_s newr;
|
||||||
int i;
|
int i;
|
||||||
@ -543,6 +553,14 @@ mark_value_bytes_unavailable (struct value *value, int offset, int length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mark_value_bytes_unavailable (struct value *value, int offset, int length)
|
||||||
|
{
|
||||||
|
mark_value_bits_unavailable (value,
|
||||||
|
offset * TARGET_CHAR_BIT,
|
||||||
|
length * TARGET_CHAR_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the first range in RANGES that overlaps the range defined by
|
/* Find the first range in RANGES that overlaps the range defined by
|
||||||
OFFSET and LENGTH, starting at element POS in the RANGES vector,
|
OFFSET and LENGTH, starting at element POS in the RANGES vector,
|
||||||
Returns the index into RANGES where such overlapping range was
|
Returns the index into RANGES where such overlapping range was
|
||||||
@ -562,10 +580,118 @@ find_first_range_overlap (VEC(range_s) *ranges, int pos,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/* Compare LENGTH_BITS of memory at PTR1 + OFFSET1_BITS with the memory at
|
||||||
value_available_contents_eq (const struct value *val1, int offset1,
|
PTR2 + OFFSET2_BITS. Return 0 if the memory is the same, otherwise
|
||||||
const struct value *val2, int offset2,
|
return non-zero.
|
||||||
int length)
|
|
||||||
|
It must always be the case that:
|
||||||
|
OFFSET1_BITS % TARGET_CHAR_BIT == OFFSET2_BITS % TARGET_CHAR_BIT
|
||||||
|
|
||||||
|
It is assumed that memory can be accessed from:
|
||||||
|
PTR + (OFFSET_BITS / TARGET_CHAR_BIT)
|
||||||
|
to:
|
||||||
|
PTR + ((OFFSET_BITS + LENGTH_BITS + TARGET_CHAR_BIT - 1)
|
||||||
|
/ TARGET_CHAR_BIT) */
|
||||||
|
static int
|
||||||
|
memcmp_with_bit_offsets (const gdb_byte *ptr1, size_t offset1_bits,
|
||||||
|
const gdb_byte *ptr2, size_t offset2_bits,
|
||||||
|
size_t length_bits)
|
||||||
|
{
|
||||||
|
gdb_assert (offset1_bits % TARGET_CHAR_BIT
|
||||||
|
== offset2_bits % TARGET_CHAR_BIT);
|
||||||
|
|
||||||
|
if (offset1_bits % TARGET_CHAR_BIT != 0)
|
||||||
|
{
|
||||||
|
size_t bits;
|
||||||
|
gdb_byte mask, b1, b2;
|
||||||
|
|
||||||
|
/* The offset from the base pointers PTR1 and PTR2 is not a complete
|
||||||
|
number of bytes. A number of bits up to either the next exact
|
||||||
|
byte boundary, or LENGTH_BITS (which ever is sooner) will be
|
||||||
|
compared. */
|
||||||
|
bits = TARGET_CHAR_BIT - offset1_bits % TARGET_CHAR_BIT;
|
||||||
|
gdb_assert (bits < sizeof (mask) * TARGET_CHAR_BIT);
|
||||||
|
mask = (1 << bits) - 1;
|
||||||
|
|
||||||
|
if (length_bits < bits)
|
||||||
|
{
|
||||||
|
mask &= ~(gdb_byte) ((1 << (bits - length_bits)) - 1);
|
||||||
|
bits = length_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now load the two bytes and mask off the bits we care about. */
|
||||||
|
b1 = *(ptr1 + offset1_bits / TARGET_CHAR_BIT) & mask;
|
||||||
|
b2 = *(ptr2 + offset2_bits / TARGET_CHAR_BIT) & mask;
|
||||||
|
|
||||||
|
if (b1 != b2)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Now update the length and offsets to take account of the bits
|
||||||
|
we've just compared. */
|
||||||
|
length_bits -= bits;
|
||||||
|
offset1_bits += bits;
|
||||||
|
offset2_bits += bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length_bits % TARGET_CHAR_BIT != 0)
|
||||||
|
{
|
||||||
|
size_t bits;
|
||||||
|
size_t o1, o2;
|
||||||
|
gdb_byte mask, b1, b2;
|
||||||
|
|
||||||
|
/* The length is not an exact number of bytes. After the previous
|
||||||
|
IF.. block then the offsets are byte aligned, or the
|
||||||
|
length is zero (in which case this code is not reached). Compare
|
||||||
|
a number of bits at the end of the region, starting from an exact
|
||||||
|
byte boundary. */
|
||||||
|
bits = length_bits % TARGET_CHAR_BIT;
|
||||||
|
o1 = offset1_bits + length_bits - bits;
|
||||||
|
o2 = offset2_bits + length_bits - bits;
|
||||||
|
|
||||||
|
gdb_assert (bits < sizeof (mask) * TARGET_CHAR_BIT);
|
||||||
|
mask = ((1 << bits) - 1) << (TARGET_CHAR_BIT - bits);
|
||||||
|
|
||||||
|
gdb_assert (o1 % TARGET_CHAR_BIT == 0);
|
||||||
|
gdb_assert (o2 % TARGET_CHAR_BIT == 0);
|
||||||
|
|
||||||
|
b1 = *(ptr1 + o1 / TARGET_CHAR_BIT) & mask;
|
||||||
|
b2 = *(ptr2 + o2 / TARGET_CHAR_BIT) & mask;
|
||||||
|
|
||||||
|
if (b1 != b2)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
length_bits -= bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length_bits > 0)
|
||||||
|
{
|
||||||
|
/* We've now taken care of any stray "bits" at the start, or end of
|
||||||
|
the region to compare, the remainder can be covered with a simple
|
||||||
|
memcmp. */
|
||||||
|
gdb_assert (offset1_bits % TARGET_CHAR_BIT == 0);
|
||||||
|
gdb_assert (offset2_bits % TARGET_CHAR_BIT == 0);
|
||||||
|
gdb_assert (length_bits % TARGET_CHAR_BIT == 0);
|
||||||
|
|
||||||
|
return memcmp (ptr1 + offset1_bits / TARGET_CHAR_BIT,
|
||||||
|
ptr2 + offset2_bits / TARGET_CHAR_BIT,
|
||||||
|
length_bits / TARGET_CHAR_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Length is zero, regions match. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper function for value_available_contents_eq. The only difference is
|
||||||
|
that this function is bit rather than byte based.
|
||||||
|
|
||||||
|
Compare LENGTH bits of VAL1's contents starting at OFFSET1 bits with
|
||||||
|
LENGTH bits of VAL2's contents starting at OFFSET2 bits. Return true
|
||||||
|
if the available bits match. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
value_available_contents_bits_eq (const struct value *val1, int offset1,
|
||||||
|
const struct value *val2, int offset2,
|
||||||
|
int length)
|
||||||
{
|
{
|
||||||
int idx1 = 0, idx2 = 0;
|
int idx1 = 0, idx2 = 0;
|
||||||
|
|
||||||
@ -585,9 +711,9 @@ value_available_contents_eq (const struct value *val1, int offset1,
|
|||||||
|
|
||||||
/* The usual case is for both values to be completely available. */
|
/* The usual case is for both values to be completely available. */
|
||||||
if (idx1 == -1 && idx2 == -1)
|
if (idx1 == -1 && idx2 == -1)
|
||||||
return (memcmp (val1->contents + offset1,
|
return (memcmp_with_bit_offsets (val1->contents, offset1,
|
||||||
val2->contents + offset2,
|
val2->contents, offset2,
|
||||||
length) == 0);
|
length) == 0);
|
||||||
/* The contents only match equal if the available set matches as
|
/* The contents only match equal if the available set matches as
|
||||||
well. */
|
well. */
|
||||||
else if (idx1 == -1 || idx2 == -1)
|
else if (idx1 == -1 || idx2 == -1)
|
||||||
@ -620,9 +746,8 @@ value_available_contents_eq (const struct value *val1, int offset1,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Compare the _available_ contents. */
|
/* Compare the _available_ contents. */
|
||||||
if (memcmp (val1->contents + offset1,
|
if (memcmp_with_bit_offsets (val1->contents, offset1,
|
||||||
val2->contents + offset2,
|
val2->contents, offset2, l1) != 0)
|
||||||
l1) != 0)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
length -= h1;
|
length -= h1;
|
||||||
@ -633,6 +758,16 @@ value_available_contents_eq (const struct value *val1, int offset1,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
value_available_contents_eq (const struct value *val1, int offset1,
|
||||||
|
const struct value *val2, int offset2,
|
||||||
|
int length)
|
||||||
|
{
|
||||||
|
return value_available_contents_bits_eq (val1, offset1 * TARGET_CHAR_BIT,
|
||||||
|
val2, offset2 * TARGET_CHAR_BIT,
|
||||||
|
length * TARGET_CHAR_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Prototypes for local functions. */
|
/* Prototypes for local functions. */
|
||||||
|
|
||||||
static void show_values (char *, int);
|
static void show_values (char *, int);
|
||||||
@ -972,6 +1107,7 @@ value_contents_copy_raw (struct value *dst, int dst_offset,
|
|||||||
{
|
{
|
||||||
range_s *r;
|
range_s *r;
|
||||||
int i;
|
int i;
|
||||||
|
int src_bit_offset, dst_bit_offset, bit_length;
|
||||||
|
|
||||||
/* A lazy DST would make that this copy operation useless, since as
|
/* A lazy DST would make that this copy operation useless, since as
|
||||||
soon as DST's contents were un-lazied (by a later value_contents
|
soon as DST's contents were un-lazied (by a later value_contents
|
||||||
@ -990,17 +1126,20 @@ value_contents_copy_raw (struct value *dst, int dst_offset,
|
|||||||
length);
|
length);
|
||||||
|
|
||||||
/* Copy the meta-data, adjusted. */
|
/* Copy the meta-data, adjusted. */
|
||||||
|
src_bit_offset = src_offset * TARGET_CHAR_BIT;
|
||||||
|
dst_bit_offset = dst_offset * TARGET_CHAR_BIT;
|
||||||
|
bit_length = length * TARGET_CHAR_BIT;
|
||||||
for (i = 0; VEC_iterate (range_s, src->unavailable, i, r); i++)
|
for (i = 0; VEC_iterate (range_s, src->unavailable, i, r); i++)
|
||||||
{
|
{
|
||||||
ULONGEST h, l;
|
ULONGEST h, l;
|
||||||
|
|
||||||
l = max (r->offset, src_offset);
|
l = max (r->offset, src_bit_offset);
|
||||||
h = min (r->offset + r->length, src_offset + length);
|
h = min (r->offset + r->length, src_bit_offset + bit_length);
|
||||||
|
|
||||||
if (l < h)
|
if (l < h)
|
||||||
mark_value_bytes_unavailable (dst,
|
mark_value_bits_unavailable (dst,
|
||||||
dst_offset + (l - src_offset),
|
dst_bit_offset + (l - src_bit_offset),
|
||||||
h - l);
|
h - l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2884,8 +3023,8 @@ unpack_value_bits_as_long_1 (struct type *field_type, const gdb_byte *valaddr,
|
|||||||
read_offset = bitpos / 8;
|
read_offset = bitpos / 8;
|
||||||
|
|
||||||
if (original_value != NULL
|
if (original_value != NULL
|
||||||
&& !value_bytes_available (original_value, embedded_offset + read_offset,
|
&& !value_bits_available (original_value, embedded_offset + bitpos,
|
||||||
bytes_read))
|
bitsize))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
val = extract_unsigned_integer (valaddr + embedded_offset + read_offset,
|
val = extract_unsigned_integer (valaddr + embedded_offset + read_offset,
|
||||||
|
14
gdb/value.h
14
gdb/value.h
@ -436,6 +436,14 @@ extern int value_bits_synthetic_pointer (const struct value *value,
|
|||||||
extern int value_bytes_available (const struct value *value,
|
extern int value_bytes_available (const struct value *value,
|
||||||
int offset, int length);
|
int offset, int length);
|
||||||
|
|
||||||
|
/* Given a value, determine whether the contents bits starting at
|
||||||
|
OFFSET and extending for LENGTH bits are available. This returns
|
||||||
|
nonzero if all bits in the given range are available, zero if any
|
||||||
|
bit is unavailable. */
|
||||||
|
|
||||||
|
extern int value_bits_available (const struct value *value,
|
||||||
|
int offset, int length);
|
||||||
|
|
||||||
/* Like value_bytes_available, but return false if any byte in the
|
/* Like value_bytes_available, but return false if any byte in the
|
||||||
whole object is unavailable. */
|
whole object is unavailable. */
|
||||||
extern int value_entirely_available (struct value *value);
|
extern int value_entirely_available (struct value *value);
|
||||||
@ -450,6 +458,12 @@ extern int value_entirely_unavailable (struct value *value);
|
|||||||
extern void mark_value_bytes_unavailable (struct value *value,
|
extern void mark_value_bytes_unavailable (struct value *value,
|
||||||
int offset, int length);
|
int offset, int length);
|
||||||
|
|
||||||
|
/* Mark VALUE's content bits starting at OFFSET and extending for
|
||||||
|
LENGTH bits as unavailable. */
|
||||||
|
|
||||||
|
extern void mark_value_bits_unavailable (struct value *value,
|
||||||
|
int offset, int length);
|
||||||
|
|
||||||
/* Compare LENGTH bytes of VAL1's contents starting at OFFSET1 with
|
/* Compare LENGTH bytes of VAL1's contents starting at OFFSET1 with
|
||||||
LENGTH bytes of VAL2's contents starting at OFFSET2.
|
LENGTH bytes of VAL2's contents starting at OFFSET2.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user