/* Low level packing and unpacking of values for GDB, the GNU Debugger.
- Copyright (C) 1986-2019 Free Software Foundation, Inc.
+ Copyright (C) 1986-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "user-regs.h"
#include <algorithm>
#include "completer.h"
-#include "common/selftest.h"
-#include "common/array-view.h"
+#include "gdbsupport/selftest.h"
+#include "gdbsupport/array-view.h"
+#include "cli/cli-style.h"
/* Definition of a user function. */
struct internal_function
LONGEST bitsize = 0;
/* Only used for bitfields; position of start of field. For
- gdbarch_bits_big_endian=0 targets, it is the position of the LSB. For
- gdbarch_bits_big_endian=1 targets, it is the position of the MSB. */
+ little-endian targets, it is the position of the LSB. For
+ big-endian targets, it is the position of the MSB. */
LONGEST bitpos = 0;
/* The number of references to this value. When a value is created,
if (max_value_size > -1 && length > max_value_size)
{
- if (TYPE_NAME (type) != NULL)
+ if (type->name () != NULL)
error (_("value of type `%s' requires %u bytes, which is more "
- "than max-value-size"), TYPE_NAME (type), length);
+ "than max-value-size"), type->name (), length);
else
error (_("value requires %u bytes, which is more than "
"max-value-size"), length);
{
/* If result's target type is TYPE_CODE_STRUCT, proceed to
fetch its rtti type. */
- if ((TYPE_CODE (result) == TYPE_CODE_PTR || TYPE_IS_REFERENCE (result))
- && TYPE_CODE (check_typedef (TYPE_TARGET_TYPE (result)))
- == TYPE_CODE_STRUCT
+ if ((result->code () == TYPE_CODE_PTR || TYPE_IS_REFERENCE (result))
+ && (check_typedef (TYPE_TARGET_TYPE (result))->code ()
+ == TYPE_CODE_STRUCT)
&& !value_optimized_out (value))
{
struct type *real_type;
fetch it. */
if (value->optimized_out.empty () && value->lazy)
{
- TRY
+ try
{
value_fetch_lazy (value);
}
- CATCH (ex, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &ex)
{
/* Fall back to checking value->optimized_out. */
}
- END_CATCH
}
return !value->optimized_out.empty ();
intvar = expr->elts[2].internalvar;
/* Only evaluate the expression if the lvalue is void.
- This may still fail if the expresssion is invalid. */
+ This may still fail if the expression is invalid. */
if (intvar->kind == INTERNALVAR_VOID)
evaluate_expression (expr.get ());
}
for (var = internalvars; var; var = var->next)
if (strncmp (var->name, name, len) == 0)
- {
- gdb::unique_xmalloc_ptr<char> copy (xstrdup (var->name));
-
- tracker.add_completion (std::move (copy));
- }
+ tracker.add_completion (make_unique_xstrdup (var->name));
}
/* Create an internal variable with name NAME and with a void value.
{
struct internalvar *var = XNEW (struct internalvar);
- var->name = concat (name, (char *)NULL);
+ var->name = xstrdup (name);
var->kind = INTERNALVAR_VOID;
var->next = internalvars;
internalvars = var;
on this value go back to affect the original internal variable.
Do not do this for INTERNALVAR_MAKE_VALUE variables, as those have
- no underlying modifyable state in the internal variable.
+ no underlying modifiable state in the internal variable.
Likewise, if the variable's value is a computed lvalue, we want
references to it to produce another computed lvalue, where
{
struct type *type = check_typedef (value_type (var->u.value));
- if (TYPE_CODE (type) == TYPE_CODE_INT)
+ if (type->code () == TYPE_CODE_INT)
{
*result = value_as_long (var->u.value);
return 1;
error (_("Cannot overwrite convenience function %s"), var->name);
/* Prepare new contents. */
- switch (TYPE_CODE (check_typedef (value_type (val))))
+ switch (check_typedef (value_type (val))->code ())
{
case TYPE_CODE_VOID:
new_kind = INTERNALVAR_VOID;
when accessing the value.
If we keep it, we would still refer to the origin value.
Remove the location property in case it exist. */
- remove_dyn_prop (DYN_PROP_DATA_LOCATION, value_type (new_data.value));
+ value_type (new_data.value)->remove_dyn_prop (DYN_PROP_DATA_LOCATION);
break;
}
/* Do nothing. */
}
-/* Clean up if an internal function's command is destroyed. */
-static void
-function_destroyer (struct cmd_list_element *self, void *ignore)
+/* Helper function that does the work for add_internal_function. */
+
+static struct cmd_list_element *
+do_add_internal_function (const char *name, const char *doc,
+ internal_function_fn handler, void *cookie)
{
- xfree ((char *) self->name);
- xfree ((char *) self->doc);
+ struct internal_function *ifn;
+ struct internalvar *var = lookup_internalvar (name);
+
+ ifn = create_internal_function (name, handler, cookie);
+ set_internalvar_function (var, ifn);
+
+ return add_cmd (name, no_class, function_command, doc, &functionlist);
}
-/* Add a new internal function. NAME is the name of the function; DOC
- is a documentation string describing the function. HANDLER is
- called when the function is invoked. COOKIE is an arbitrary
- pointer which is passed to HANDLER and is intended for "user
- data". */
+/* See value.h. */
+
void
add_internal_function (const char *name, const char *doc,
internal_function_fn handler, void *cookie)
{
- struct cmd_list_element *cmd;
- struct internal_function *ifn;
- struct internalvar *var = lookup_internalvar (name);
+ do_add_internal_function (name, doc, handler, cookie);
+}
- ifn = create_internal_function (name, handler, cookie);
- set_internalvar_function (var, ifn);
+/* See value.h. */
- cmd = add_cmd (xstrdup (name), no_class, function_command, (char *) doc,
- &functionlist);
- cmd->destroyer = function_destroyer;
+void
+add_internal_function (gdb::unique_xmalloc_ptr<char> &&name,
+ gdb::unique_xmalloc_ptr<char> &&doc,
+ internal_function_fn handler, void *cookie)
+{
+ struct cmd_list_element *cmd
+ = do_add_internal_function (name.get (), doc.get (), handler, cookie);
+ doc.release ();
+ cmd->doc_allocated = 1;
+ name.release ();
+ cmd->name_allocated = 1;
}
/* Update VALUE before discarding OBJFILE. COPIED_TYPES is used to
}
printf_filtered (("$%s = "), var->name);
- TRY
+ try
{
struct value *val;
val = value_of_internalvar (gdbarch, var);
value_print (val, gdb_stdout, &opts);
}
- CATCH (ex, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &ex)
{
- fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.message);
+ fprintf_styled (gdb_stdout, metadata_style.style (),
+ _("<error: %s>"), ex.what ());
}
- END_CATCH
printf_filtered (("\n"));
}
struct type *
result_type_of_xmethod (struct value *method, gdb::array_view<value *> argv)
{
- gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD
+ gdb_assert (value_type (method)->code () == TYPE_CODE_XMETHOD
&& method->lval == lval_xcallable && !argv.empty ());
return method->location.xm_worker->get_result_type (argv[0], argv.slice (1));
struct value *
call_xmethod (struct value *method, gdb::array_view<value *> argv)
{
- gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD
+ gdb_assert (value_type (method)->code () == TYPE_CODE_XMETHOD
&& method->lval == lval_xcallable && !argv.empty ());
return method->location.xm_worker->invoke (argv[0], argv.slice (1));
The following shortcut avoids this whole mess. If VAL is a
function, just return its address directly. */
- if (TYPE_CODE (value_type (val)) == TYPE_CODE_FUNC
- || TYPE_CODE (value_type (val)) == TYPE_CODE_METHOD)
+ if (value_type (val)->code () == TYPE_CODE_FUNC
+ || value_type (val)->code () == TYPE_CODE_METHOD)
return value_address (val);
val = coerce_array (val);
converted to pointers; usually, the ABI doesn't either, but
ABI-specific code is a more reasonable place to handle it. */
- if (TYPE_CODE (value_type (val)) != TYPE_CODE_PTR
+ if (value_type (val)->code () != TYPE_CODE_PTR
&& !TYPE_IS_REFERENCE (value_type (val))
&& gdbarch_integer_to_address_p (gdbarch))
return gdbarch_integer_to_address (gdbarch, value_type (val),
LONGEST
unpack_long (struct type *type, const gdb_byte *valaddr)
{
- enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
- enum type_code code = TYPE_CODE (type);
+ enum bfd_endian byte_order = type_byte_order (type);
+ enum type_code code = type->code ();
int len = TYPE_LENGTH (type);
int nosign = TYPE_UNSIGNED (type);
case TYPE_CODE_CHAR:
case TYPE_CODE_RANGE:
case TYPE_CODE_MEMBERPTR:
- if (nosign)
- return extract_unsigned_integer (valaddr, len, byte_order);
- else
- return extract_signed_integer (valaddr, len, byte_order);
+ {
+ LONGEST result;
+ if (nosign)
+ result = extract_unsigned_integer (valaddr, len, byte_order);
+ else
+ result = extract_signed_integer (valaddr, len, byte_order);
+ if (code == TYPE_CODE_RANGE)
+ result += TYPE_RANGE_DATA (type)->bias;
+ return result;
+ }
case TYPE_CODE_FLT:
case TYPE_CODE_DECFLOAT:
switch (TYPE_FIELD_LOC_KIND (type, fieldno))
{
case FIELD_LOC_KIND_PHYSADDR:
- retval = value_at_lazy (TYPE_FIELD_TYPE (type, fieldno),
+ retval = value_at_lazy (type->field (fieldno).type (),
TYPE_FIELD_STATIC_PHYSADDR (type, fieldno));
break;
case FIELD_LOC_KIND_PHYSNAME:
reported as non-debuggable symbols. */
struct bound_minimal_symbol msym
= lookup_minimal_symbol (phys_name, NULL, NULL);
- struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
+ struct type *field_type = type->field (fieldno).type ();
if (!msym.minsym)
retval = allocate_optimized_out_value (field_type);
int unit_size = gdbarch_addressable_memory_unit_size (arch);
arg_type = check_typedef (arg_type);
- type = TYPE_FIELD_TYPE (arg_type, fieldno);
+ type = arg_type->field (fieldno).type ();
/* Call check_typedef on our type to make sure that, if TYPE
is a TYPE_CODE_TYPEDEF, its length is set to the length
/* The minimal symbol might point to a function descriptor;
resolve it to the actual code address instead. */
struct objfile *objfile = msym.objfile;
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct gdbarch *gdbarch = objfile->arch ();
set_value_address (v,
gdbarch_convert_from_func_ptr_addr
\f
-/* Unpack a bitfield of the specified FIELD_TYPE, from the object at
- VALADDR, and store the result in *RESULT.
- The bitfield starts at BITPOS bits and contains BITSIZE bits; if
- BITSIZE is zero, then the length is taken from FIELD_TYPE.
-
- Extracting bits depends on endianness of the machine. Compute the
- number of least significant bits to discard. For big endian machines,
- we compute the total number of bits in the anonymous object, subtract
- off the bit count from the MSB of the object to the MSB of the
- bitfield, then the size of the bitfield, which leaves the LSB discard
- count. For little endian machines, the discard count is simply the
- number of bits from the LSB of the anonymous object to the LSB of the
- bitfield.
-
- If the field is signed, we also do sign extension. */
+/* See value.h. */
-static LONGEST
+LONGEST
unpack_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
LONGEST bitpos, LONGEST bitsize)
{
- enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (field_type));
+ enum bfd_endian byte_order = type_byte_order (field_type);
ULONGEST val;
ULONGEST valmask;
int lsbcount;
/* Extract bits. See comment above. */
- if (gdbarch_bits_big_endian (get_type_arch (field_type)))
+ if (byte_order == BFD_ENDIAN_BIG)
lsbcount = (bytes_read * 8 - bitpos % 8 - bitsize);
else
lsbcount = (bitpos % 8);
{
int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
- struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
+ struct type *field_type = type->field (fieldno).type ();
int bit_offset;
gdb_assert (val != NULL);
{
int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
- struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
+ struct type *field_type = type->field (fieldno).type ();
return unpack_bits_as_long (field_type, valaddr, bitpos, bitsize);
}
int dst_bit_offset;
struct type *field_type = value_type (dest_val);
- byte_order = gdbarch_byte_order (get_type_arch (field_type));
+ byte_order = type_byte_order (field_type);
/* First, unpack and sign extend the bitfield as if it was wholly
valid. Optimized out/unavailable bits are read as zero, but
{
int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
- struct value *res_val = allocate_value (TYPE_FIELD_TYPE (type, fieldno));
+ struct value *res_val = allocate_value (type->field (fieldno).type ());
unpack_value_bitfield (res_val, bitpos, bitsize,
valaddr, embedded_offset, val);
modify_field (struct type *type, gdb_byte *addr,
LONGEST fieldval, LONGEST bitpos, LONGEST bitsize)
{
- enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
+ enum bfd_endian byte_order = type_byte_order (type);
ULONGEST oword;
ULONGEST mask = (ULONGEST) -1 >> (8 * sizeof (ULONGEST) - bitsize);
LONGEST bytesize;
oword = extract_unsigned_integer (addr, bytesize, byte_order);
/* Shifting for bit field depends on endianness of the target machine. */
- if (gdbarch_bits_big_endian (get_type_arch (type)))
+ if (byte_order == BFD_ENDIAN_BIG)
bitpos = bytesize * 8 - bitpos - bitsize;
oword &= ~(mask << bitpos);
void
pack_long (gdb_byte *buf, struct type *type, LONGEST num)
{
- enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
+ enum bfd_endian byte_order = type_byte_order (type);
LONGEST len;
type = check_typedef (type);
len = TYPE_LENGTH (type);
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
+ case TYPE_CODE_RANGE:
+ num -= TYPE_RANGE_DATA (type)->bias;
+ /* Fall through. */
case TYPE_CODE_INT:
case TYPE_CODE_CHAR:
case TYPE_CODE_ENUM:
case TYPE_CODE_FLAGS:
case TYPE_CODE_BOOL:
- case TYPE_CODE_RANGE:
case TYPE_CODE_MEMBERPTR:
store_signed_integer (buf, len, byte_order, num);
break;
default:
error (_("Unexpected type (%d) encountered for integer constant."),
- TYPE_CODE (type));
+ type->code ());
}
}
type = check_typedef (type);
len = TYPE_LENGTH (type);
- byte_order = gdbarch_byte_order (get_type_arch (type));
+ byte_order = type_byte_order (type);
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
case TYPE_CODE_INT:
case TYPE_CODE_CHAR:
default:
error (_("Unexpected type (%d) encountered "
"for unsigned integer constant."),
- TYPE_CODE (type));
+ type->code ());
}
}
return val;
}
+/* Create and return a value object of TYPE containing the value D. The
+ TYPE must be of TYPE_CODE_FLT, and must be large enough to hold D once
+ it is converted to target format. */
+
+struct value *
+value_from_host_double (struct type *type, double d)
+{
+ struct value *value = allocate_value (type);
+ gdb_assert (type->code () == TYPE_CODE_FLT);
+ target_float_from_host_double (value_contents_raw (value),
+ value_type (value), d);
+ return value;
+}
/* Create a value of type TYPE whose contents come from VALADDR, if it
is non-null, and whose memory address (in the inferior) is
const gdb_byte *valaddr,
CORE_ADDR address)
{
- struct type *resolved_type = resolve_dynamic_type (type, valaddr, address);
+ gdb::array_view<const gdb_byte> view;
+ if (valaddr != nullptr)
+ view = gdb::make_array_view (valaddr, TYPE_LENGTH (type));
+ struct type *resolved_type = resolve_dynamic_type (type, view, address);
struct type *resolved_type_no_typedef = check_typedef (resolved_type);
struct value *v;
arg = coerce_ref (arg);
type = check_typedef (value_type (arg));
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
case TYPE_CODE_ARRAY:
if (!TYPE_VECTOR (type) && current_language->c_style_arrays)
struct_return_convention (struct gdbarch *gdbarch,
struct value *function, struct type *value_type)
{
- enum type_code code = TYPE_CODE (value_type);
+ enum type_code code = value_type->code ();
if (code == TYPE_CODE_ERROR)
error (_("Function return type unknown."));
using_struct_return (struct gdbarch *gdbarch,
struct value *function, struct type *value_type)
{
- if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
+ if (value_type->code () == TYPE_CODE_VOID)
/* A void return value is never in memory. See also corresponding
code in "print_return_value". */
return 0;
if (argc != 1)
error (_("You must provide one argument for $_isvoid."));
- ret = TYPE_CODE (value_type (argv[0])) == TYPE_CODE_VOID;
+ ret = value_type (argv[0])->code () == TYPE_CODE_VOID;
return value_from_longest (builtin_type (gdbarch)->builtin_int, ret);
}
+/* Implementation of the convenience function $_creal. Extracts the
+ real part from a complex number. */
+
+static struct value *
+creal_internal_fn (struct gdbarch *gdbarch,
+ const struct language_defn *language,
+ void *cookie, int argc, struct value **argv)
+{
+ if (argc != 1)
+ error (_("You must provide one argument for $_creal."));
+
+ value *cval = argv[0];
+ type *ctype = check_typedef (value_type (cval));
+ if (ctype->code () != TYPE_CODE_COMPLEX)
+ error (_("expected a complex number"));
+ return value_real_part (cval);
+}
+
+/* Implementation of the convenience function $_cimag. Extracts the
+ imaginary part from a complex number. */
+
+static struct value *
+cimag_internal_fn (struct gdbarch *gdbarch,
+ const struct language_defn *language,
+ void *cookie, int argc,
+ struct value **argv)
+{
+ if (argc != 1)
+ error (_("You must provide one argument for $_cimag."));
+
+ value *cval = argv[0];
+ type *ctype = check_typedef (value_type (cval));
+ if (ctype->code () != TYPE_CODE_COMPLEX)
+ error (_("expected a complex number"));
+ return value_imaginary_part (cval);
+}
+
#if GDB_SELF_TEST
namespace selftests
{
} /* namespace selftests */
#endif /* GDB_SELF_TEST */
+void _initialize_values ();
void
-_initialize_values (void)
+_initialize_values ()
{
add_cmd ("convenience", no_class, show_convenience, _("\
Debugger convenience (\"$foo\") variables and functions.\n\
Return 1 if the expression is void, zero otherwise."),
isvoid_internal_fn, NULL);
+ add_internal_function ("_creal", _("\
+Extract the real part of a complex number.\n\
+Usage: $_creal (expression)\n\
+Return the real part of a complex number, the type depends on the\n\
+type of a complex number."),
+ creal_internal_fn, NULL);
+
+ add_internal_function ("_cimag", _("\
+Extract the imaginary part of a complex number.\n\
+Usage: $_cimag (expression)\n\
+Return the imaginary part of a complex number, the type depends on the\n\
+type of a complex number."),
+ cimag_internal_fn, NULL);
+
add_setshow_zuinteger_unlimited_cmd ("max-value-size",
class_support, &max_value_size, _("\
Set maximum sized value gdb will load from the inferior."), _("\
selftests::test_insert_into_bit_range_vector);
#endif
}
+
+/* See value.h. */
+
+void
+finalize_values ()
+{
+ all_values.clear ();
+}