#include "gdbtypes.h"
#include "value.h"
#include "language.h"
+#include "c-lang.h"
#include "expression.h"
#include "gdbcore.h"
#include "gdbcmd.h"
#include "cli/cli-option.h"
#include "cli/cli-script.h"
#include "cli/cli-style.h"
-#include "common/format.h"
+#include "gdbsupport/format.h"
#include "source.h"
-#include "common/byte-vector.h"
-#include "common/gdb_optional.h"
+#include "gdbsupport/byte-vector.h"
+#include "gdbsupport/gdb_optional.h"
/* Last specified output format. */
/* Append the source filename and linenumber of the symbol when
printing a symbolic value as `<symbol at filename:linenum>' if set. */
-static int print_symbol_filename = 0;
+static bool print_symbol_filename = false;
static void
show_print_symbol_filename (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
struct gdbarch *gdbarch = get_type_arch (type);
unsigned int len = TYPE_LENGTH (type);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ enum bfd_endian byte_order = type_byte_order (type);
/* String printing should go through val_print_scalar_formatted. */
gdb_assert (options->format != 's');
/* Historically gdb has printed floats by first casting them to a
long, and then printing the long. PR cli/16242 suggests changing
- this to using C-style hex float format. */
- gdb::byte_vector converted_float_bytes;
- if (TYPE_CODE (type) == TYPE_CODE_FLT
- && (options->format == 'o'
- || options->format == 'x'
- || options->format == 't'
- || options->format == 'z'
- || options->format == 'd'
- || options->format == 'u'))
- {
- LONGEST val_long = unpack_long (type, valaddr);
- converted_float_bytes.resize (TYPE_LENGTH (type));
- store_signed_integer (converted_float_bytes.data (), TYPE_LENGTH (type),
- byte_order, val_long);
- valaddr = converted_float_bytes.data ();
+ this to using C-style hex float format.
+
+ Biased range types must also be unbiased here; the unbiasing is
+ done by unpack_long. */
+ gdb::byte_vector converted_bytes;
+ /* Some cases below will unpack the value again. In the biased
+ range case, we want to avoid this, so we store the unpacked value
+ here for possible use later. */
+ gdb::optional<LONGEST> val_long;
+ if ((TYPE_CODE (type) == TYPE_CODE_FLT
+ && (options->format == 'o'
+ || options->format == 'x'
+ || options->format == 't'
+ || options->format == 'z'
+ || options->format == 'd'
+ || options->format == 'u'))
+ || (TYPE_CODE (type) == TYPE_CODE_RANGE
+ && TYPE_RANGE_DATA (type)->bias != 0))
+ {
+ val_long.emplace (unpack_long (type, valaddr));
+ converted_bytes.resize (TYPE_LENGTH (type));
+ store_signed_integer (converted_bytes.data (), TYPE_LENGTH (type),
+ byte_order, *val_long);
+ valaddr = converted_bytes.data ();
}
/* Printing a non-float type as 'f' will interpret the data as if it were
{
struct value_print_options opts = *options;
- LONGEST val_long = unpack_long (type, valaddr);
+ if (!val_long.has_value ())
+ val_long.emplace (unpack_long (type, valaddr));
opts.format = 0;
if (TYPE_UNSIGNED (type))
else
type = builtin_type (gdbarch)->builtin_true_char;
- value_print (value_from_longest (type, val_long), stream, &opts);
+ value_print (value_from_longest (type, *val_long), stream, &opts);
}
break;
case 'a':
{
- CORE_ADDR addr = unpack_pointer (type, valaddr);
-
- print_address (gdbarch, addr, stream);
+ if (!val_long.has_value ())
+ val_long.emplace (unpack_long (type, valaddr));
+ print_address (gdbarch, *val_long, stream);
}
break;
int offset = 0;
int line = 0;
- if (build_address_symbolic (gdbarch, addr, do_demangle, &name, &offset,
- &filename, &line, &unmapped))
+ if (build_address_symbolic (gdbarch, addr, do_demangle, false, &name,
+ &offset, &filename, &line, &unmapped))
return 0;
fputs_filtered (leadin, stream);
fputs_filtered ("<", stream);
fputs_styled (name.c_str (), function_name_style.style (), stream);
if (offset != 0)
- fprintf_filtered (stream, "+%u", (unsigned int) offset);
+ fprintf_filtered (stream, "%+d", offset);
/* Append source filename and line number if desired. Give specific
line # of this addr, if we have it; else line # of the nearest symbol. */
int
build_address_symbolic (struct gdbarch *gdbarch,
CORE_ADDR addr, /* IN */
- int do_demangle, /* IN */
+ bool do_demangle, /* IN */
+ bool prefer_sym_over_minsym, /* IN */
std::string *name, /* OUT */
int *offset, /* OUT */
std::string *filename, /* OUT */
}
}
- /* First try to find the address in the symbol table, then
- in the minsyms. Take the closest one. */
+ /* Try to find the address in both the symbol table and the minsyms.
+ In most cases, we'll prefer to use the symbol instead of the
+ minsym. However, there are cases (see below) where we'll choose
+ to use the minsym instead. */
/* This is defective in the sense that it only finds text symbols. So
really this is kind of pointless--we should make sure that the
name_location = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (symbol));
if (do_demangle || asm_demangle)
- name_temp = SYMBOL_PRINT_NAME (symbol);
+ name_temp = symbol->print_name ();
else
- name_temp = SYMBOL_LINKAGE_NAME (symbol);
+ name_temp = symbol->linkage_name ();
}
if (msymbol.minsym != NULL
if (msymbol.minsym != NULL)
{
- if (BMSYMBOL_VALUE_ADDRESS (msymbol) > name_location || symbol == NULL)
+ /* Use the minsym if no symbol is found.
+
+ Additionally, use the minsym instead of a (found) symbol if
+ the following conditions all hold:
+ 1) The prefer_sym_over_minsym flag is false.
+ 2) The minsym address is identical to that of the address under
+ consideration.
+ 3) The symbol address is not identical to that of the address
+ under consideration. */
+ if (symbol == NULL ||
+ (!prefer_sym_over_minsym
+ && BMSYMBOL_VALUE_ADDRESS (msymbol) == addr
+ && name_location != addr))
{
/* If this is a function (i.e. a code address), strip out any
non-address bits. For instance, display a pointer to the
|| MSYMBOL_TYPE (msymbol.minsym) == mst_solib_trampoline)
addr = gdbarch_addr_bits_remove (gdbarch, addr);
- /* The msymbol is closer to the address than the symbol;
- use the msymbol instead. */
symbol = 0;
name_location = BMSYMBOL_VALUE_ADDRESS (msymbol);
if (do_demangle || asm_demangle)
- name_temp = MSYMBOL_PRINT_NAME (msymbol.minsym);
+ name_temp = msymbol.minsym->print_name ();
else
- name_temp = MSYMBOL_LINKAGE_NAME (msymbol.minsym);
+ name_temp = msymbol.minsym->linkage_name ();
}
}
if (symbol == NULL && msymbol.minsym == NULL)
&& name_location + max_symbolic_offset > name_location)
return 1;
- *offset = addr - name_location;
+ *offset = (LONGEST) addr - name_location;
*name = name_temp;
{
const char *exp = *expp;
+ /* opts->raw value might already have been set by 'set print raw-values'
+ or by using 'print -raw-values'.
+ So, do not set opts->raw to 0, only set it to 1 if /r is given. */
if (exp && *exp == '/')
{
format_data fmt;
last_format = fmt.format;
opts->format = fmt.format;
- opts->raw = fmt.raw;
+ opts->raw = opts->raw || fmt.raw;
}
else
{
opts->format = 0;
- opts->raw = 0;
}
*expp = exp;
offset = sect_addr - MSYMBOL_VALUE_ADDRESS (objfile, msymbol);
mapped = section_is_mapped (osect) ? _("mapped") : _("unmapped");
sec_name = osect->the_bfd_section->name;
- msym_name = MSYMBOL_PRINT_NAME (msymbol);
+ msym_name = msymbol->print_name ();
/* Don't print the offset if it is zero.
We assume there's no need to handle i18n of "sym + offset". */
gdb_assert (osect->objfile && objfile_name (osect->objfile));
obj_name = objfile_name (osect->objfile);
- if (MULTI_OBJFILE_P ())
+ if (current_program_space->multi_objfile_p ())
if (pc_in_unmapped_range (addr, osect))
if (section_is_overlay (osect))
printf_filtered (_("%s in load address range of "
}
printf_filtered ("Symbol \"");
- fprintf_symbol_filtered (gdb_stdout, SYMBOL_PRINT_NAME (sym),
+ fprintf_symbol_filtered (gdb_stdout, sym->print_name (),
current_language->la_language, DMGL_ANSI);
printf_filtered ("\" is ");
val = SYMBOL_VALUE (sym);
{
struct bound_minimal_symbol msym;
- msym = lookup_bound_minimal_symbol (SYMBOL_LINKAGE_NAME (sym));
+ msym = lookup_bound_minimal_symbol (sym->linkage_name ());
if (msym.minsym == NULL)
printf_filtered ("unresolved");
else
if (d->block)
{
if (d->pspace == current_program_space)
- within_current_scope = contained_in (get_selected_block (0), d->block);
+ within_current_scope = contained_in (get_selected_block (0), d->block,
+ true);
else
within_current_scope = 0;
}
}
catch (const gdb_exception_error &ex)
{
- fprintf_filtered (gdb_stdout, _("<error: %s>\n"),
- ex.what ());
+ fprintf_filtered (gdb_stdout, _("%p[<error: %s>%p]\n"),
+ metadata_style.style ().ptr (), ex.what (),
+ nullptr);
}
}
else
}
catch (const gdb_exception_error &ex)
{
- fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.what ());
+ fprintf_styled (gdb_stdout, metadata_style.style (),
+ _("<error: %s>"), ex.what ());
}
printf_filtered ("\n");
else if (d->format.format)
printf_filtered ("/%c ", d->format.format);
puts_filtered (d->exp_string);
- if (d->block && !contained_in (get_selected_block (0), d->block))
+ if (d->block && !contained_in (get_selected_block (0), d->block, true))
printf_filtered (_(" (cannot be evaluated in the current context)"));
printf_filtered ("\n");
}
d->enabled_p = *(int *) data;
}
-/* Implamentation of both the "disable display" and "enable display"
+/* Implementation of both the "disable display" and "enable display"
commands. ENABLE decides what to do. */
static void
{
if (!name)
- name = SYMBOL_PRINT_NAME (var);
+ name = var->print_name ();
- fputs_filtered (n_spaces (2 * indent), stream);
- fputs_styled (name, variable_name_style.style (), stream);
- fputs_filtered (" = ", stream);
+ fprintf_filtered (stream, "%s%ps = ", n_spaces (2 * indent),
+ styled_string (variable_name_style.style (), name));
try
{
}
catch (const gdb_exception_error &except)
{
- fprintf_filtered (stream, "<error reading variable %s (%s)>", name,
- except.what ());
+ fprintf_styled (stream, metadata_style.style (),
+ "<error reading variable %s (%s)>", name,
+ except.what ());
}
fprintf_filtered (stream, "\n");
/* Subroutine of ui_printf to simplify it.
Print VALUE to STREAM using FORMAT.
- VALUE is a C-style string on the target. */
+ VALUE is a C-style string either on the target or
+ in a GDB internal variable. */
static void
printf_c_string (struct ui_file *stream, const char *format,
struct value *value)
{
- gdb_byte *str;
- CORE_ADDR tem;
- int j;
+ const gdb_byte *str;
- tem = value_as_address (value);
- if (tem == 0)
+ if (VALUE_LVAL (value) == lval_internalvar
+ && c_is_string_type_p (value_type (value)))
{
- DIAGNOSTIC_PUSH
- DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
- fprintf_filtered (stream, format, "(null)");
- DIAGNOSTIC_POP
- return;
- }
+ size_t len = TYPE_LENGTH (value_type (value));
- /* This is a %s argument. Find the length of the string. */
- for (j = 0;; j++)
- {
- gdb_byte c;
+ /* Copy the internal var value to TEM_STR and append a terminating null
+ character. This protects against corrupted C-style strings that lack
+ the terminating null char. It also allows Ada-style strings (not
+ null terminated) to be printed without problems. */
+ gdb_byte *tem_str = (gdb_byte *) alloca (len + 1);
- QUIT;
- read_memory (tem + j, &c, 1);
- if (c == 0)
- break;
+ memcpy (tem_str, value_contents (value), len);
+ tem_str [len] = 0;
+ str = tem_str;
}
+ else
+ {
+ CORE_ADDR tem = value_as_address (value);;
+
+ if (tem == 0)
+ {
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+ fprintf_filtered (stream, format, "(null)");
+ DIAGNOSTIC_POP
+ return;
+ }
- /* Copy the string contents into a string inside GDB. */
- str = (gdb_byte *) alloca (j + 1);
- if (j != 0)
- read_memory (tem, str, j);
- str[j] = 0;
+ /* This is a %s argument. Find the length of the string. */
+ size_t len;
+
+ for (len = 0;; len++)
+ {
+ gdb_byte c;
+
+ QUIT;
+ read_memory (tem + len, &c, 1);
+ if (c == 0)
+ break;
+ }
+
+ /* Copy the string contents into a string inside GDB. */
+ gdb_byte *tem_str = (gdb_byte *) alloca (len + 1);
+
+ if (len != 0)
+ read_memory (tem, tem_str, len);
+ tem_str[len] = 0;
+ str = tem_str;
+ }
DIAGNOSTIC_PUSH
DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
/* Subroutine of ui_printf to simplify it.
Print VALUE to STREAM using FORMAT.
- VALUE is a wide C-style string on the target. */
+ VALUE is a wide C-style string on the target or
+ in a GDB internal variable. */
static void
printf_wide_c_string (struct ui_file *stream, const char *format,
struct value *value)
{
- gdb_byte *str;
- CORE_ADDR tem;
- int j;
+ const gdb_byte *str;
+ size_t len;
struct gdbarch *gdbarch = get_type_arch (value_type (value));
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct type *wctype = lookup_typename (current_language, gdbarch,
+ struct type *wctype = lookup_typename (current_language,
"wchar_t", NULL, 0);
int wcwidth = TYPE_LENGTH (wctype);
- gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
- tem = value_as_address (value);
- if (tem == 0)
+ if (VALUE_LVAL (value) == lval_internalvar
+ && c_is_string_type_p (value_type (value)))
{
- DIAGNOSTIC_PUSH
- DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
- fprintf_filtered (stream, format, "(null)");
- DIAGNOSTIC_POP
- return;
+ str = value_contents (value);
+ len = TYPE_LENGTH (value_type (value));
}
-
- /* This is a %s argument. Find the length of the string. */
- for (j = 0;; j += wcwidth)
+ else
{
- QUIT;
- read_memory (tem + j, buf, wcwidth);
- if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
- break;
- }
+ CORE_ADDR tem = value_as_address (value);
+
+ if (tem == 0)
+ {
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+ fprintf_filtered (stream, format, "(null)");
+ DIAGNOSTIC_POP
+ return;
+ }
+
+ /* This is a %s argument. Find the length of the string. */
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
+
+ for (len = 0;; len += wcwidth)
+ {
+ QUIT;
+ read_memory (tem + len, buf, wcwidth);
+ if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
+ break;
+ }
- /* Copy the string contents into a string inside GDB. */
- str = (gdb_byte *) alloca (j + wcwidth);
- if (j != 0)
- read_memory (tem, str, j);
- memset (&str[j], 0, wcwidth);
+ /* Copy the string contents into a string inside GDB. */
+ gdb_byte *tem_str = (gdb_byte *) alloca (len + wcwidth);
+
+ if (len != 0)
+ read_memory (tem, tem_str, len);
+ memset (&tem_str[len], 0, wcwidth);
+ str = tem_str;
+ }
auto_obstack output;
convert_between_encodings (target_wide_charset (gdbarch),
host_charset (),
- str, j, wcwidth,
+ str, len, wcwidth,
&output, translit_char);
obstack_grow_str0 (&output, "");
{
struct gdbarch *gdbarch
= get_type_arch (value_type (val_args[i]));
- struct type *wctype = lookup_typename (current_language, gdbarch,
+ struct type *wctype = lookup_typename (current_language,
"wchar_t", NULL, 0);
struct type *valtype;
const gdb_byte *bytes;
{
long val = value_as_long (val_args[i]);
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
+ fprintf_filtered (stream, current_substring, val);
+ DIAGNOSTIC_POP
+ break;
+ }
+ case size_t_arg:
+ {
+ size_t val = value_as_long (val_args[i]);
+
DIAGNOSTIC_PUSH
DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
fprintf_filtered (stream, current_substring, val);
This is useful in user-defined commands."));
add_prefix_cmd ("set", class_vars, set_command, _("\
-Evaluate expression EXP and assign result to variable VAR\n\
+Evaluate expression EXP and assign result to variable VAR.\n\
Usage: set VAR = EXP\n\
This uses assignment syntax appropriate for the current language\n\
(VAR = EXP or VAR := EXP for example).\n\
&setlist, "set ", 1, &cmdlist);
if (dbx_commands)
add_com ("assign", class_vars, set_command, _("\
-Evaluate expression EXP and assign result to variable VAR\n\
+Evaluate expression EXP and assign result to variable VAR.\n\
Usage: assign VAR = EXP\n\
This uses assignment syntax appropriate for the current language\n\
(VAR = EXP or VAR := EXP for example).\n\
set_cmd_completer_handle_brkchars (c, print_command_completer);
add_cmd ("variable", class_vars, set_command, _("\
-Evaluate expression EXP and assign result to variable VAR\n\
+Evaluate expression EXP and assign result to variable VAR.\n\
Usage: set variable VAR = EXP\n\
This uses assignment syntax appropriate for the current language\n\
(VAR = EXP or VAR := EXP for example).\n\
const auto print_opts = make_value_print_options_def_group (nullptr);
- static const std::string print_help = gdb::option::build_help (N_("\
+ static const std::string print_help = gdb::option::build_help (_("\
Print value of expression EXP.\n\
Usage: print [[OPTION]... --] [/FMT] [EXP]\n\
\n\
Options:\n\
-%OPTIONS%\
+%OPTIONS%\n\
+\n\
Note: because this command accepts arbitrary expressions, if you\n\
specify any command option, you must use a double dash (\"--\")\n\
to mark the end of option processing. E.g.: \"print -o -- myobj\".\n\