mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-21 02:24:17 +08:00
Add lval_funcs::is_optimized_out
This adds an is_optimized_out function pointer to lval_funcs, and changes value_optimized_out to call it. This new function lets gdb determine if a value is optimized out without necessarily fetching the value. This is needed for a subsequent patch, where an attempt to access a lazy value would fail due to the value size limit -- however, the access was only needed to determine the optimized-out state.
This commit is contained in:
@ -149,10 +149,13 @@ allocate_piece_closure (dwarf2_per_cu_data *per_cu,
|
|||||||
/* Read or write a pieced value V. If FROM != NULL, operate in "write
|
/* Read or write a pieced value V. If FROM != NULL, operate in "write
|
||||||
mode": copy FROM into the pieces comprising V. If FROM == NULL,
|
mode": copy FROM into the pieces comprising V. If FROM == NULL,
|
||||||
operate in "read mode": fetch the contents of the (lazy) value V by
|
operate in "read mode": fetch the contents of the (lazy) value V by
|
||||||
composing it from its pieces. */
|
composing it from its pieces. If CHECK_OPTIMIZED is true, then no
|
||||||
|
reading or writing is done; instead the return value of this
|
||||||
|
function is true if any piece is optimized out. When
|
||||||
|
CHECK_OPTIMIZED is true, FROM must be nullptr. */
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
rw_pieced_value (value *v, value *from)
|
rw_pieced_value (value *v, value *from, bool check_optimized)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
LONGEST offset = 0, max_offset;
|
LONGEST offset = 0, max_offset;
|
||||||
@ -163,6 +166,7 @@ rw_pieced_value (value *v, value *from)
|
|||||||
gdb::byte_vector buffer;
|
gdb::byte_vector buffer;
|
||||||
bool bits_big_endian = type_byte_order (value_type (v)) == BFD_ENDIAN_BIG;
|
bool bits_big_endian = type_byte_order (value_type (v)) == BFD_ENDIAN_BIG;
|
||||||
|
|
||||||
|
gdb_assert (!check_optimized || from == nullptr);
|
||||||
if (from != nullptr)
|
if (from != nullptr)
|
||||||
{
|
{
|
||||||
from_contents = value_contents (from);
|
from_contents = value_contents (from);
|
||||||
@ -174,7 +178,10 @@ rw_pieced_value (value *v, value *from)
|
|||||||
internal_error (__FILE__, __LINE__,
|
internal_error (__FILE__, __LINE__,
|
||||||
_("Should not be able to create a lazy value with "
|
_("Should not be able to create a lazy value with "
|
||||||
"an enclosing type"));
|
"an enclosing type"));
|
||||||
v_contents = value_contents_raw (v);
|
if (check_optimized)
|
||||||
|
v_contents = nullptr;
|
||||||
|
else
|
||||||
|
v_contents = value_contents_raw (v);
|
||||||
from_contents = nullptr;
|
from_contents = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,17 +247,22 @@ rw_pieced_value (value *v, value *from)
|
|||||||
buffer, &optim, &unavail))
|
buffer, &optim, &unavail))
|
||||||
{
|
{
|
||||||
if (optim)
|
if (optim)
|
||||||
mark_value_bits_optimized_out (v, offset,
|
{
|
||||||
this_size_bits);
|
if (check_optimized)
|
||||||
if (unavail)
|
return true;
|
||||||
|
mark_value_bits_optimized_out (v, offset,
|
||||||
|
this_size_bits);
|
||||||
|
}
|
||||||
|
if (unavail && !check_optimized)
|
||||||
mark_value_bits_unavailable (v, offset,
|
mark_value_bits_unavailable (v, offset,
|
||||||
this_size_bits);
|
this_size_bits);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_bitwise (v_contents, offset,
|
if (!check_optimized)
|
||||||
buffer.data (), bits_to_skip % 8,
|
copy_bitwise (v_contents, offset,
|
||||||
this_size_bits, bits_big_endian);
|
buffer.data (), bits_to_skip % 8,
|
||||||
|
this_size_bits, bits_big_endian);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -286,6 +298,9 @@ rw_pieced_value (value *v, value *from)
|
|||||||
|
|
||||||
case DWARF_VALUE_MEMORY:
|
case DWARF_VALUE_MEMORY:
|
||||||
{
|
{
|
||||||
|
if (check_optimized)
|
||||||
|
break;
|
||||||
|
|
||||||
bits_to_skip += p->offset;
|
bits_to_skip += p->offset;
|
||||||
|
|
||||||
CORE_ADDR start_addr = p->v.mem.addr + bits_to_skip / 8;
|
CORE_ADDR start_addr = p->v.mem.addr + bits_to_skip / 8;
|
||||||
@ -355,6 +370,9 @@ rw_pieced_value (value *v, value *from)
|
|||||||
|
|
||||||
case DWARF_VALUE_STACK:
|
case DWARF_VALUE_STACK:
|
||||||
{
|
{
|
||||||
|
if (check_optimized)
|
||||||
|
break;
|
||||||
|
|
||||||
if (from != nullptr)
|
if (from != nullptr)
|
||||||
{
|
{
|
||||||
mark_value_bits_optimized_out (v, offset, this_size_bits);
|
mark_value_bits_optimized_out (v, offset, this_size_bits);
|
||||||
@ -384,6 +402,9 @@ rw_pieced_value (value *v, value *from)
|
|||||||
|
|
||||||
case DWARF_VALUE_LITERAL:
|
case DWARF_VALUE_LITERAL:
|
||||||
{
|
{
|
||||||
|
if (check_optimized)
|
||||||
|
break;
|
||||||
|
|
||||||
if (from != nullptr)
|
if (from != nullptr)
|
||||||
{
|
{
|
||||||
mark_value_bits_optimized_out (v, offset, this_size_bits);
|
mark_value_bits_optimized_out (v, offset, this_size_bits);
|
||||||
@ -418,6 +439,8 @@ rw_pieced_value (value *v, value *from)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DWARF_VALUE_OPTIMIZED_OUT:
|
case DWARF_VALUE_OPTIMIZED_OUT:
|
||||||
|
if (check_optimized)
|
||||||
|
return true;
|
||||||
mark_value_bits_optimized_out (v, offset, this_size_bits);
|
mark_value_bits_optimized_out (v, offset, this_size_bits);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -428,18 +451,26 @@ rw_pieced_value (value *v, value *from)
|
|||||||
offset += this_size_bits;
|
offset += this_size_bits;
|
||||||
bits_to_skip = 0;
|
bits_to_skip = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
read_pieced_value (value *v)
|
read_pieced_value (value *v)
|
||||||
{
|
{
|
||||||
rw_pieced_value (v, nullptr);
|
rw_pieced_value (v, nullptr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_pieced_value (value *to, value *from)
|
write_pieced_value (value *to, value *from)
|
||||||
{
|
{
|
||||||
rw_pieced_value (to, from);
|
rw_pieced_value (to, from, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_optimized_out_pieced_value (value *v)
|
||||||
|
{
|
||||||
|
return rw_pieced_value (v, nullptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* An implementation of an lval_funcs method to see whether a value is
|
/* An implementation of an lval_funcs method to see whether a value is
|
||||||
@ -617,6 +648,7 @@ free_pieced_value_closure (value *v)
|
|||||||
static const struct lval_funcs pieced_value_funcs = {
|
static const struct lval_funcs pieced_value_funcs = {
|
||||||
read_pieced_value,
|
read_pieced_value,
|
||||||
write_pieced_value,
|
write_pieced_value,
|
||||||
|
is_optimized_out_pieced_value,
|
||||||
indirect_pieced_value,
|
indirect_pieced_value,
|
||||||
coerce_pieced_ref,
|
coerce_pieced_ref,
|
||||||
check_pieced_synthetic_pointer,
|
check_pieced_synthetic_pointer,
|
||||||
|
@ -1282,6 +1282,7 @@ static const struct lval_funcs entry_data_value_funcs =
|
|||||||
{
|
{
|
||||||
NULL, /* read */
|
NULL, /* read */
|
||||||
NULL, /* write */
|
NULL, /* write */
|
||||||
|
nullptr,
|
||||||
NULL, /* indirect */
|
NULL, /* indirect */
|
||||||
entry_data_value_coerce_ref,
|
entry_data_value_coerce_ref,
|
||||||
NULL, /* check_synthetic_pointer */
|
NULL, /* check_synthetic_pointer */
|
||||||
|
@ -254,6 +254,7 @@ static const struct lval_funcs opencl_value_funcs =
|
|||||||
{
|
{
|
||||||
lval_func_read,
|
lval_func_read,
|
||||||
lval_func_write,
|
lval_func_write,
|
||||||
|
nullptr,
|
||||||
NULL, /* indirect */
|
NULL, /* indirect */
|
||||||
NULL, /* coerce_ref */
|
NULL, /* coerce_ref */
|
||||||
lval_func_check_synthetic_pointer,
|
lval_func_check_synthetic_pointer,
|
||||||
|
17
gdb/value.c
17
gdb/value.c
@ -1407,10 +1407,21 @@ value_contents_writeable (struct value *value)
|
|||||||
int
|
int
|
||||||
value_optimized_out (struct value *value)
|
value_optimized_out (struct value *value)
|
||||||
{
|
{
|
||||||
/* We can only know if a value is optimized out once we have tried to
|
if (value->lazy)
|
||||||
fetch it. */
|
|
||||||
if (value->optimized_out.empty () && value->lazy)
|
|
||||||
{
|
{
|
||||||
|
/* See if we can compute the result without fetching the
|
||||||
|
value. */
|
||||||
|
if (VALUE_LVAL (value) == lval_memory)
|
||||||
|
return false;
|
||||||
|
else if (VALUE_LVAL (value) == lval_computed)
|
||||||
|
{
|
||||||
|
const struct lval_funcs *funcs = value->location.computed.funcs;
|
||||||
|
|
||||||
|
if (funcs->is_optimized_out != nullptr)
|
||||||
|
return funcs->is_optimized_out (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fall back to fetching. */
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
value_fetch_lazy (value);
|
value_fetch_lazy (value);
|
||||||
|
@ -264,6 +264,12 @@ struct lval_funcs
|
|||||||
TOVAL is not considered as an lvalue. */
|
TOVAL is not considered as an lvalue. */
|
||||||
void (*write) (struct value *toval, struct value *fromval);
|
void (*write) (struct value *toval, struct value *fromval);
|
||||||
|
|
||||||
|
/* Return true if any part of V is optimized out, false otherwise.
|
||||||
|
This will only be called for lazy values -- if the value has been
|
||||||
|
fetched, then the value's optimized-out bits are consulted
|
||||||
|
instead. */
|
||||||
|
bool (*is_optimized_out) (struct value *v);
|
||||||
|
|
||||||
/* If non-NULL, this is used to implement pointer indirection for
|
/* If non-NULL, this is used to implement pointer indirection for
|
||||||
this value. This method may return NULL, in which case value_ind
|
this value. This method may return NULL, in which case value_ind
|
||||||
will fall back to ordinary indirection. */
|
will fall back to ordinary indirection. */
|
||||||
|
Reference in New Issue
Block a user