gdb/testsuite: some additional tests in gdb.tui/scroll.exp
[binutils-gdb.git] / gdb / printcmd.c
index 9200e66db39a0859bcabdd0a46638b7ddafb320b..3c78edf7cce0dfd5a426e949b860ed62b9f35422 100644 (file)
@@ -1,6 +1,6 @@
 /* Print values for GNU debugger GDB.
 
-   Copyright (C) 1986-2021 Free Software Foundation, Inc.
+   Copyright (C) 1986-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -72,6 +72,10 @@ static char last_size = 'w';
 
 static int last_count;
 
+/* Last specified tag-printing option.  */
+
+static bool last_print_tags = false;
+
 /* Default address to examine next, and associated architecture.  */
 
 static struct gdbarch *next_gdbarch;
@@ -98,10 +102,10 @@ static void
 show_max_symbolic_offset (struct ui_file *file, int from_tty,
                          struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file,
-                   _("The largest offset that will be "
-                     "printed in <symbol+1234> form is %s.\n"),
-                   value);
+  gdb_printf (file,
+             _("The largest offset that will be "
+               "printed in <symbol+1234> form is %s.\n"),
+             value);
 }
 
 /* Append the source filename and linenumber of the symbol when
@@ -111,9 +115,9 @@ static void
 show_print_symbol_filename (struct ui_file *file, int from_tty,
                            struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("Printing of source filename and "
-                           "line number with <symbol> is %s.\n"),
-                   value);
+  gdb_printf (file, _("Printing of source filename and "
+                     "line number with <symbol> is %s.\n"),
+             value);
 }
 
 /* Number of auto-display expression currently being displayed.
@@ -193,6 +197,7 @@ decode_format (const char **string_ptr, int oformat, int osize)
   val.size = '?';
   val.count = 1;
   val.raw = 0;
+  val.print_tags = false;
 
   if (*p == '-')
     {
@@ -215,6 +220,11 @@ decode_format (const char **string_ptr, int oformat, int osize)
          val.raw = 1;
          p++;
        }
+      else if (*p == 'm')
+       {
+         val.print_tags = true;
+         p++;
+       }
       else if (*p >= 'a' && *p <= 'z')
        val.format = *p++;
       else
@@ -307,7 +317,7 @@ print_formatted (struct value *val, int size,
 
        case 'i':
          /* We often wrap here if there are long symbolic names.  */
-         wrap_here ("    ");
+         stream->wrap_here (4);
          next_address = (value_address (val)
                          + gdb_print_insn (type->arch (),
                                            value_address (val), stream,
@@ -416,19 +426,14 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
       len = newlen;
     }
 
-  /* 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.
-
-     Biased range types and sub-word scalar types must also be handled
+  /* Biased range types and sub-word scalar types must be handled
      here; the value is correctly computed 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_CODE_FLT
-       || is_fixed_point_type (type))
+  if ((is_fixed_point_type (type)
        && (options->format == 'o'
           || options->format == 'x'
           || options->format == 't'
@@ -498,7 +503,7 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
        opts.format = 0;
        if (type->is_unsigned ())
          type = builtin_type (gdbarch)->builtin_true_unsigned_char;
-       else
+       else
          type = builtin_type (gdbarch)->builtin_true_char;
 
        value_print (value_from_longest (type, *val_long), stream, &opts);
@@ -557,28 +562,28 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
                              &offset, &filename, &line, &unmapped))
     return 0;
 
-  fputs_filtered (leadin, stream);
+  gdb_puts (leadin, stream);
   if (unmapped)
-    fputs_filtered ("<*", stream);
+    gdb_puts ("<*", stream);
   else
-    fputs_filtered ("<", stream);
+    gdb_puts ("<", stream);
   fputs_styled (name.c_str (), function_name_style.style (), stream);
   if (offset != 0)
-    fprintf_filtered (stream, "%+d", offset);
+    gdb_printf (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.  */
   if (print_symbol_filename && !filename.empty ())
     {
-      fputs_filtered (line == -1 ? " in " : " at ", stream);
+      gdb_puts (line == -1 ? " in " : " at ", stream);
       fputs_styled (filename.c_str (), file_name_style.style (), stream);
       if (line != -1)
-       fprintf_filtered (stream, ":%d", line);
+       gdb_printf (stream, ":%d", line);
     }
   if (unmapped)
-    fputs_filtered ("*>", stream);
+    gdb_puts ("*>", stream);
   else
-    fputs_filtered (">", stream);
+    gdb_puts (">", stream);
 
   return 1;
 }
@@ -814,11 +819,11 @@ find_instruction_backward (struct gdbarch *gdbarch, CORE_ADDR addr,
          /* We reach here when line info is not available.  In this case,
             we print a message and just exit the loop.  The return value
             is calculated after the loop.  */
-         printf_filtered (_("No line number information available "
-                            "for address "));
-         wrap_here ("  ");
+         gdb_printf (_("No line number information available "
+                       "for address "));
+         gdb_stdout->wrap_here (2);
          print_address (gdbarch, loop_start - 1, gdb_stdout);
-         printf_filtered ("\n");
+         gdb_printf ("\n");
          break;
        }
 
@@ -900,8 +905,8 @@ read_memory_backward (struct gdbarch *gdbarch,
          if (errcode != 0)
            {
              /* The read was unsuccessful, so exit the loop.  */
-             printf_filtered (_("Cannot access memory at address %s\n"),
-                              paddress (gdbarch, memaddr));
+             gdb_printf (_("Cannot access memory at address %s\n"),
+                         paddress (gdbarch, memaddr));
              break;
            }
        }
@@ -1100,21 +1105,59 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
       need_to_update_next_address = 1;
     }
 
+  /* Whether we need to print the memory tag information for the current
+     address range.  */
+  bool print_range_tag = true;
+  uint32_t gsize = gdbarch_memtag_granule_size (gdbarch);
+
   /* Print as many objects as specified in COUNT, at most maxelts per line,
      with the address of the next one at the start of each line.  */
 
   while (count > 0)
     {
       QUIT;
+
+      CORE_ADDR tag_laddr = 0, tag_haddr = 0;
+
+      /* Print the memory tag information if requested.  */
+      if (fmt.print_tags && print_range_tag
+         && target_supports_memory_tagging ())
+       {
+         tag_laddr = align_down (next_address, gsize);
+         tag_haddr = align_down (next_address + gsize, gsize);
+
+         struct value *v_addr
+           = value_from_ulongest (builtin_type (gdbarch)->builtin_data_ptr,
+                                  tag_laddr);
+
+         if (gdbarch_tagged_address_p (target_gdbarch (), v_addr))
+           {
+             /* Fetch the allocation tag.  */
+             struct value *tag
+               = gdbarch_get_memtag (gdbarch, v_addr, memtag_type::allocation);
+             std::string atag
+               = gdbarch_memtag_to_string (gdbarch, tag);
+
+             if (!atag.empty ())
+               {
+                 gdb_printf (_("<Allocation Tag %s for range [%s,%s)>\n"),
+                             atag.c_str (),
+                             paddress (gdbarch, tag_laddr),
+                             paddress (gdbarch, tag_haddr));
+               }
+           }
+         print_range_tag = false;
+       }
+
       if (format == 'i')
-       fputs_filtered (pc_prefix (next_address), gdb_stdout);
+       gdb_puts (pc_prefix (next_address));
       print_address (next_gdbarch, next_address, gdb_stdout);
-      printf_filtered (":");
+      gdb_printf (":");
       for (i = maxelts;
           i > 0 && count > 0;
           i--, count--)
        {
-         printf_filtered ("\t");
+         gdb_printf ("\t");
          /* Note that print_formatted sets next_address for the next
             object.  */
          last_examine_address = next_address;
@@ -1136,8 +1179,13 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
          /* Display any branch delay slots following the final insn.  */
          if (format == 'i' && count == 1)
            count += branch_delay_insns;
+
+         /* Update the tag range based on the current address being
+            processed.  */
+         if (tag_haddr <= next_address)
+             print_range_tag = true;
        }
-      printf_filtered ("\n");
+      gdb_printf ("\n");
     }
 
   if (need_to_update_next_address)
@@ -1198,16 +1246,43 @@ print_value (value *val, const value_print_options &opts)
 
   annotate_value_history_begin (histindex, value_type (val));
 
-  printf_filtered ("$%d = ", histindex);
+  gdb_printf ("$%d = ", histindex);
 
   annotate_value_history_value ();
 
   print_formatted (val, 0, &opts, gdb_stdout);
-  printf_filtered ("\n");
+  gdb_printf ("\n");
 
   annotate_value_history_end ();
 }
 
+/* Returns true if memory tags should be validated.  False otherwise.  */
+
+static bool
+should_validate_memtags (struct value *value)
+{
+  gdb_assert (value != nullptr && value_type (value) != nullptr);
+
+  if (!target_supports_memory_tagging ())
+    return false;
+
+  enum type_code code = value_type (value)->code ();
+
+  /* Skip non-address values.  */
+  if (code != TYPE_CODE_PTR
+      && !TYPE_IS_REFERENCE (value_type (value)))
+    return false;
+
+  /* OK, we have an address value.  Check we have a complete value we
+     can extract.  */
+  if (value_optimized_out (value)
+      || !value_entirely_available (value))
+    return false;
+
+  /* We do.  Check whether it includes any tags.  */
+  return gdbarch_tagged_address_p (target_gdbarch (), value);
+}
+
 /* Helper for parsing arguments for print_command_1.  */
 
 static struct value *
@@ -1246,7 +1321,46 @@ print_command_1 (const char *args, int voidprint)
 
   if (voidprint || (val && value_type (val) &&
                    value_type (val)->code () != TYPE_CODE_VOID))
-    print_value (val, print_opts);
+    {
+      /* If memory tagging validation is on, check if the tag is valid.  */
+      if (print_opts.memory_tag_violations)
+       {
+         try
+           {
+             if (should_validate_memtags (val)
+                 && !gdbarch_memtag_matches_p (target_gdbarch (), val))
+               {
+                 /* Fetch the logical tag.  */
+                 struct value *tag
+                   = gdbarch_get_memtag (target_gdbarch (), val,
+                                         memtag_type::logical);
+                 std::string ltag
+                   = gdbarch_memtag_to_string (target_gdbarch (), tag);
+
+                 /* Fetch the allocation tag.  */
+                 tag = gdbarch_get_memtag (target_gdbarch (), val,
+                                           memtag_type::allocation);
+                 std::string atag
+                   = gdbarch_memtag_to_string (target_gdbarch (), tag);
+
+                 gdb_printf (_("Logical tag (%s) does not match the "
+                               "allocation tag (%s).\n"),
+                             ltag.c_str (), atag.c_str ());
+               }
+           }
+         catch (gdb_exception_error &ex)
+           {
+             if (ex.error == TARGET_CLOSE_ERROR)
+               throw;
+
+             gdb_printf (gdb_stderr,
+                         _("Could not validate memory tag: %s\n"),
+                         ex.message->c_str ());
+           }
+       }
+
+      print_value (val, print_opts);
+    }
 }
 
 /* Called from command completion function to skip over /FMT
@@ -1379,7 +1493,6 @@ output_command (const char *exp, int from_tty)
 
   annotate_value_end ();
 
-  wrap_here ("");
   gdb_flush (gdb_stdout);
 }
 
@@ -1429,8 +1542,7 @@ info_symbol_command (const char *arg, int from_tty)
 
        sect_addr = overlay_mapped_address (addr, osect);
 
-       if (obj_section_addr (osect) <= sect_addr
-           && sect_addr < obj_section_endaddr (osect)
+       if (osect->addr () <= sect_addr && sect_addr < osect->endaddr ()
            && (msymbol
                = lookup_minimal_symbol_by_pc_section (sect_addr,
                                                       osect).minsym))
@@ -1461,41 +1573,41 @@ info_symbol_command (const char *arg, int from_tty)
            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 "
-                                    "%s overlay section %s of %s\n"),
-                                  loc_string, mapped, sec_name, obj_name);
+                 gdb_printf (_("%s in load address range of "
+                               "%s overlay section %s of %s\n"),
+                             loc_string, mapped, sec_name, obj_name);
                else
-                 printf_filtered (_("%s in load address range of "
-                                    "section %s of %s\n"),
-                                  loc_string, sec_name, obj_name);
+                 gdb_printf (_("%s in load address range of "
+                               "section %s of %s\n"),
+                             loc_string, sec_name, obj_name);
              else
                if (section_is_overlay (osect))
-                 printf_filtered (_("%s in %s overlay section %s of %s\n"),
-                                  loc_string, mapped, sec_name, obj_name);
+                 gdb_printf (_("%s in %s overlay section %s of %s\n"),
+                             loc_string, mapped, sec_name, obj_name);
                else
-                 printf_filtered (_("%s in section %s of %s\n"),
-                                  loc_string, sec_name, obj_name);
+                 gdb_printf (_("%s in section %s of %s\n"),
+                             loc_string, sec_name, obj_name);
            else
              if (pc_in_unmapped_range (addr, osect))
                if (section_is_overlay (osect))
-                 printf_filtered (_("%s in load address range of %s overlay "
-                                    "section %s\n"),
-                                  loc_string, mapped, sec_name);
+                 gdb_printf (_("%s in load address range of %s overlay "
+                               "section %s\n"),
+                             loc_string, mapped, sec_name);
                else
-                 printf_filtered
+                 gdb_printf
                    (_("%s in load address range of section %s\n"),
                     loc_string, sec_name);
              else
                if (section_is_overlay (osect))
-                 printf_filtered (_("%s in %s overlay section %s\n"),
-                                  loc_string, mapped, sec_name);
+                 gdb_printf (_("%s in %s overlay section %s\n"),
+                             loc_string, mapped, sec_name);
                else
-                 printf_filtered (_("%s in section %s\n"),
-                                  loc_string, sec_name);
+                 gdb_printf (_("%s in section %s\n"),
+                             loc_string, sec_name);
          }
       }
   if (matches == 0)
-    printf_filtered (_("No symbol matches %s.\n"), arg);
+    gdb_printf (_("No symbol matches %s.\n"), arg);
 }
 
 static void
@@ -1519,14 +1631,14 @@ info_address_command (const char *exp, int from_tty)
     {
       if (is_a_field_of_this.type != NULL)
        {
-         printf_filtered ("Symbol \"");
-         fprintf_symbol_filtered (gdb_stdout, exp,
-                                  current_language->la_language, DMGL_ANSI);
-         printf_filtered ("\" is a field of the local class variable ");
+         gdb_printf ("Symbol \"");
+         fprintf_symbol (gdb_stdout, exp,
+                         current_language->la_language, DMGL_ANSI);
+         gdb_printf ("\" is a field of the local class variable ");
          if (current_language->la_language == language_objc)
-           printf_filtered ("`self'\n");       /* ObjC equivalent of "this" */
+           gdb_printf ("`self'\n");    /* ObjC equivalent of "this" */
          else
-           printf_filtered ("`this'\n");
+           gdb_printf ("`this'\n");
          return;
        }
 
@@ -1539,37 +1651,36 @@ info_address_command (const char *exp, int from_tty)
          gdbarch = objfile->arch ();
          load_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
 
-         printf_filtered ("Symbol \"");
-         fprintf_symbol_filtered (gdb_stdout, exp,
-                                  current_language->la_language, DMGL_ANSI);
-         printf_filtered ("\" is at ");
+         gdb_printf ("Symbol \"");
+         fprintf_symbol (gdb_stdout, exp,
+                         current_language->la_language, DMGL_ANSI);
+         gdb_printf ("\" is at ");
          fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
                        gdb_stdout);
-         printf_filtered (" in a file compiled without debugging");
+         gdb_printf (" in a file compiled without debugging");
          section = msymbol.minsym->obj_section (objfile);
          if (section_is_overlay (section))
            {
              load_addr = overlay_unmapped_address (load_addr, section);
-             printf_filtered (",\n -- loaded at ");
+             gdb_printf (",\n -- loaded at ");
              fputs_styled (paddress (gdbarch, load_addr),
                            address_style.style (),
                            gdb_stdout);
-             printf_filtered (" in overlay section %s",
-                              section->the_bfd_section->name);
+             gdb_printf (" in overlay section %s",
+                         section->the_bfd_section->name);
            }
-         printf_filtered (".\n");
+         gdb_printf (".\n");
        }
       else
        error (_("No symbol \"%s\" in current context."), exp);
       return;
     }
 
-  printf_filtered ("Symbol \"");
-  fprintf_symbol_filtered (gdb_stdout, sym->print_name (),
-                          current_language->la_language, DMGL_ANSI);
-  printf_filtered ("\" is ");
+  gdb_printf ("Symbol \"");
+  gdb_puts (sym->print_name ());
+  gdb_printf ("\" is ");
   val = SYMBOL_VALUE (sym);
-  if (SYMBOL_OBJFILE_OWNED (sym))
+  if (sym->is_objfile_owned ())
     section = sym->obj_section (symbol_objfile (sym));
   else
     section = NULL;
@@ -1579,35 +1690,35 @@ info_address_command (const char *exp, int from_tty)
     {
       SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, context_pc,
                                                    gdb_stdout);
-      printf_filtered (".\n");
+      gdb_printf (".\n");
       return;
     }
 
-  switch (SYMBOL_CLASS (sym))
+  switch (sym->aclass ())
     {
     case LOC_CONST:
     case LOC_CONST_BYTES:
-      printf_filtered ("constant");
+      gdb_printf ("constant");
       break;
 
     case LOC_LABEL:
-      printf_filtered ("a label at address ");
+      gdb_printf ("a label at address ");
       load_addr = SYMBOL_VALUE_ADDRESS (sym);
       fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
                    gdb_stdout);
       if (section_is_overlay (section))
        {
          load_addr = overlay_unmapped_address (load_addr, section);
-         printf_filtered (",\n -- loaded at ");
+         gdb_printf (",\n -- loaded at ");
          fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
                        gdb_stdout);
-         printf_filtered (" in overlay section %s",
-                          section->the_bfd_section->name);
+         gdb_printf (" in overlay section %s",
+                     section->the_bfd_section->name);
        }
       break;
 
     case LOC_COMPUTED:
-      gdb_assert_not_reached (_("LOC_COMPUTED variable missing a method"));
+      gdb_assert_not_reached ("LOC_COMPUTED variable missing a method");
 
     case LOC_REGISTER:
       /* GDBARCH is the architecture associated with the objfile the symbol
@@ -1618,66 +1729,66 @@ info_address_command (const char *exp, int from_tty)
         in that objfile.  */
       regno = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch);
 
-      if (SYMBOL_IS_ARGUMENT (sym))
-       printf_filtered (_("an argument in register %s"),
-                        gdbarch_register_name (gdbarch, regno));
+      if (sym->is_argument ())
+       gdb_printf (_("an argument in register %s"),
+                   gdbarch_register_name (gdbarch, regno));
       else
-       printf_filtered (_("a variable in register %s"),
-                        gdbarch_register_name (gdbarch, regno));
+       gdb_printf (_("a variable in register %s"),
+                   gdbarch_register_name (gdbarch, regno));
       break;
 
     case LOC_STATIC:
-      printf_filtered (_("static storage at address "));
+      gdb_printf (_("static storage at address "));
       load_addr = SYMBOL_VALUE_ADDRESS (sym);
       fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
                    gdb_stdout);
       if (section_is_overlay (section))
        {
          load_addr = overlay_unmapped_address (load_addr, section);
-         printf_filtered (_(",\n -- loaded at "));
+         gdb_printf (_(",\n -- loaded at "));
          fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
                        gdb_stdout);
-         printf_filtered (_(" in overlay section %s"),
-                          section->the_bfd_section->name);
+         gdb_printf (_(" in overlay section %s"),
+                     section->the_bfd_section->name);
        }
       break;
 
     case LOC_REGPARM_ADDR:
       /* Note comment at LOC_REGISTER.  */
       regno = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch);
-      printf_filtered (_("address of an argument in register %s"),
-                      gdbarch_register_name (gdbarch, regno));
+      gdb_printf (_("address of an argument in register %s"),
+                 gdbarch_register_name (gdbarch, regno));
       break;
 
     case LOC_ARG:
-      printf_filtered (_("an argument at offset %ld"), val);
+      gdb_printf (_("an argument at offset %ld"), val);
       break;
 
     case LOC_LOCAL:
-      printf_filtered (_("a local variable at frame offset %ld"), val);
+      gdb_printf (_("a local variable at frame offset %ld"), val);
       break;
 
     case LOC_REF_ARG:
-      printf_filtered (_("a reference argument at offset %ld"), val);
+      gdb_printf (_("a reference argument at offset %ld"), val);
       break;
 
     case LOC_TYPEDEF:
-      printf_filtered (_("a typedef"));
+      gdb_printf (_("a typedef"));
       break;
 
     case LOC_BLOCK:
-      printf_filtered (_("a function at address "));
+      gdb_printf (_("a function at address "));
       load_addr = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
       fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
                    gdb_stdout);
       if (section_is_overlay (section))
        {
          load_addr = overlay_unmapped_address (load_addr, section);
-         printf_filtered (_(",\n -- loaded at "));
+         gdb_printf (_(",\n -- loaded at "));
          fputs_styled (paddress (gdbarch, load_addr), address_style.style (),
                        gdb_stdout);
-         printf_filtered (_(" in overlay section %s"),
-                          section->the_bfd_section->name);
+         gdb_printf (_(" in overlay section %s"),
+                     section->the_bfd_section->name);
        }
       break;
 
@@ -1687,7 +1798,7 @@ info_address_command (const char *exp, int from_tty)
 
        msym = lookup_bound_minimal_symbol (sym->linkage_name ());
        if (msym.minsym == NULL)
-         printf_filtered ("unresolved");
+         gdb_printf ("unresolved");
        else
          {
            section = msym.obj_section ();
@@ -1696,26 +1807,26 @@ info_address_command (const char *exp, int from_tty)
                && (section->the_bfd_section->flags & SEC_THREAD_LOCAL) != 0)
              {
                load_addr = MSYMBOL_VALUE_RAW_ADDRESS (msym.minsym);
-               printf_filtered (_("a thread-local variable at offset %s "
-                                  "in the thread-local storage for `%s'"),
-                                paddress (gdbarch, load_addr),
-                                objfile_name (section->objfile));
+               gdb_printf (_("a thread-local variable at offset %s "
+                             "in the thread-local storage for `%s'"),
+                           paddress (gdbarch, load_addr),
+                           objfile_name (section->objfile));
              }
            else
              {
                load_addr = BMSYMBOL_VALUE_ADDRESS (msym);
-               printf_filtered (_("static storage at address "));
+               gdb_printf (_("static storage at address "));
                fputs_styled (paddress (gdbarch, load_addr),
                              address_style.style (), gdb_stdout);
                if (section_is_overlay (section))
                  {
                    load_addr = overlay_unmapped_address (load_addr, section);
-                   printf_filtered (_(",\n -- loaded at "));
+                   gdb_printf (_(",\n -- loaded at "));
                    fputs_styled (paddress (gdbarch, load_addr),
                                  address_style.style (),
                                  gdb_stdout);
-                   printf_filtered (_(" in overlay section %s"),
-                                    section->the_bfd_section->name);
+                   gdb_printf (_(" in overlay section %s"),
+                               section->the_bfd_section->name);
                  }
              }
          }
@@ -1723,14 +1834,14 @@ info_address_command (const char *exp, int from_tty)
       break;
 
     case LOC_OPTIMIZED_OUT:
-      printf_filtered (_("optimized out"));
+      gdb_printf (_("optimized out"));
       break;
 
     default:
-      printf_filtered (_("of unknown (botched) type"));
+      gdb_printf (_("of unknown (botched) type"));
       break;
     }
-  printf_filtered (".\n");
+  gdb_printf (".\n");
 }
 \f
 
@@ -1741,6 +1852,7 @@ x_command (const char *exp, int from_tty)
   struct value *val;
 
   fmt.format = last_format ? last_format : 'x';
+  fmt.print_tags = last_print_tags;
   fmt.size = last_size;
   fmt.count = 1;
   fmt.raw = 0;
@@ -1797,6 +1909,9 @@ x_command (const char *exp, int from_tty)
     last_size = fmt.size;
   last_format = fmt.format;
 
+  /* Remember tag-printing setting.  */
+  last_print_tags = fmt.print_tags;
+
   /* Set a couple of internal variables if appropriate.  */
   if (last_examine_value != nullptr)
     {
@@ -1937,7 +2052,7 @@ map_display_numbers (const char *args,
                                      return item->number == num;
                                    });
          if (iter == all_displays.end ())
-           printf_unfiltered (_("No display number %d.\n"), num);
+           gdb_printf (_("No display number %d.\n"), num);
          else
            function (iter->get ());
        }
@@ -2022,31 +2137,31 @@ do_one_display (struct display *d)
     = make_scoped_restore (&current_display_number, d->number);
 
   annotate_display_begin ();
-  printf_filtered ("%d", d->number);
+  gdb_printf ("%d", d->number);
   annotate_display_number_end ();
-  printf_filtered (": ");
+  gdb_printf (": ");
   if (d->format.size)
     {
 
       annotate_display_format ();
 
-      printf_filtered ("x/");
+      gdb_printf ("x/");
       if (d->format.count != 1)
-       printf_filtered ("%d", d->format.count);
-      printf_filtered ("%c", d->format.format);
+       gdb_printf ("%d", d->format.count);
+      gdb_printf ("%c", d->format.format);
       if (d->format.format != 'i' && d->format.format != 's')
-       printf_filtered ("%c", d->format.size);
-      printf_filtered (" ");
+       gdb_printf ("%c", d->format.size);
+      gdb_printf (" ");
 
       annotate_display_expression ();
 
-      puts_filtered (d->exp_string.c_str ());
+      gdb_puts (d->exp_string.c_str ());
       annotate_display_expression_end ();
 
       if (d->format.count != 1 || d->format.format == 'i')
-       printf_filtered ("\n");
+       gdb_printf ("\n");
       else
-       printf_filtered ("  ");
+       gdb_printf ("  ");
 
       annotate_display_value ();
 
@@ -2063,9 +2178,9 @@ do_one_display (struct display *d)
        }
       catch (const gdb_exception_error &ex)
        {
-         fprintf_filtered (gdb_stdout, _("%p[<error: %s>%p]\n"),
-                           metadata_style.style ().ptr (), ex.what (),
-                           nullptr);
+         gdb_printf (_("%p[<error: %s>%p]\n"),
+                     metadata_style.style ().ptr (), ex.what (),
+                     nullptr);
        }
     }
   else
@@ -2075,14 +2190,14 @@ do_one_display (struct display *d)
       annotate_display_format ();
 
       if (d->format.format)
-       printf_filtered ("/%c ", d->format.format);
+       gdb_printf ("/%c ", d->format.format);
 
       annotate_display_expression ();
 
-      puts_filtered (d->exp_string.c_str ());
+      gdb_puts (d->exp_string.c_str ());
       annotate_display_expression_end ();
 
-      printf_filtered (" = ");
+      gdb_printf (" = ");
 
       annotate_display_expression ();
 
@@ -2102,7 +2217,7 @@ do_one_display (struct display *d)
                          _("<error: %s>"), ex.what ());
        }
 
-      printf_filtered ("\n");
+      gdb_printf ("\n");
     }
 
   annotate_display_end ();
@@ -2132,7 +2247,7 @@ disable_display (int num)
        d->enabled_p = false;
        return;
       }
-  printf_unfiltered (_("No display number %d.\n"), num);
+  gdb_printf (_("No display number %d.\n"), num);
 }
 
 void
@@ -2141,10 +2256,10 @@ disable_current_display (void)
   if (current_display_number >= 0)
     {
       disable_display (current_display_number);
-      fprintf_unfiltered (gdb_stderr,
-                         _("Disabling display %d to "
-                           "avoid infinite recursion.\n"),
-                         current_display_number);
+      gdb_printf (gdb_stderr,
+                 _("Disabling display %d to "
+                   "avoid infinite recursion.\n"),
+                 current_display_number);
     }
   current_display_number = -1;
 }
@@ -2153,23 +2268,23 @@ static void
 info_display_command (const char *ignore, int from_tty)
 {
   if (all_displays.empty ())
-    printf_unfiltered (_("There are no auto-display expressions now.\n"));
+    gdb_printf (_("There are no auto-display expressions now.\n"));
   else
-    printf_filtered (_("Auto-display expressions now in effect:\n\
+    gdb_printf (_("Auto-display expressions now in effect:\n\
 Num Enb Expression\n"));
 
   for (auto &d : all_displays)
     {
-      printf_filtered ("%d:   %c  ", d->number, "ny"[(int) d->enabled_p]);
+      gdb_printf ("%d:   %c  ", d->number, "ny"[(int) d->enabled_p]);
       if (d->format.size)
-       printf_filtered ("/%d%c%c ", d->format.count, d->format.size,
-                        d->format.format);
+       gdb_printf ("/%d%c%c ", d->format.count, d->format.size,
+                   d->format.format);
       else if (d->format.format)
-       printf_filtered ("/%c ", d->format.format);
-      puts_filtered (d->exp_string.c_str ());
+       gdb_printf ("/%c ", d->format.format);
+      gdb_puts (d->exp_string.c_str ());
       if (d->block && !contained_in (get_selected_block (0), d->block, true))
-       printf_filtered (_(" (cannot be evaluated in the current context)"));
-      printf_filtered ("\n");
+       gdb_printf (_(" (cannot be evaluated in the current context)"));
+      gdb_printf ("\n");
     }
 }
 
@@ -2272,8 +2387,8 @@ print_variable_and_value (const char *name, struct symbol *var,
   if (!name)
     name = var->print_name ();
 
-  fprintf_filtered (stream, "%*s%ps = ", 2 * indent, "",
-                   styled_string (variable_name_style.style (), name));
+  gdb_printf (stream, "%*s%ps = ", 2 * indent, "",
+             styled_string (variable_name_style.style (), name));
 
   try
     {
@@ -2287,7 +2402,7 @@ print_variable_and_value (const char *name, struct symbol *var,
       val = read_var_value (var, NULL, frame);
       get_user_print_options (&opts);
       opts.deref_ref = 1;
-      common_val_print (val, stream, indent, &opts, current_language);
+      common_val_print_checked (val, stream, indent, &opts, current_language);
 
       /* common_val_print invalidates FRAME when a pretty printer calls inferior
         function.  */
@@ -2300,7 +2415,7 @@ print_variable_and_value (const char *name, struct symbol *var,
                      except.what ());
     }
 
-  fprintf_filtered (stream, "\n");
+  gdb_printf (stream, "\n");
 }
 
 /* Subroutine of ui_printf to simplify it.
@@ -2326,7 +2441,7 @@ printf_c_string (struct ui_file *stream, const char *format,
         null terminated) to be printed without problems.  */
       gdb_byte *tem_str = (gdb_byte *) alloca (len + 1);
 
-      memcpy (tem_str, value_contents (value), len);
+      memcpy (tem_str, value_contents (value).data (), len);
       tem_str [len] = 0;
       str = tem_str;
     }
@@ -2338,7 +2453,7 @@ printf_c_string (struct ui_file *stream, const char *format,
        {
          DIAGNOSTIC_PUSH
          DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-         fprintf_filtered (stream, format, "(null)");
+           gdb_printf (stream, format, "(null)");
          DIAGNOSTIC_POP
          return;
        }
@@ -2367,7 +2482,7 @@ printf_c_string (struct ui_file *stream, const char *format,
 
   DIAGNOSTIC_PUSH
   DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-  fprintf_filtered (stream, format, (char *) str);
+    gdb_printf (stream, format, (char *) str);
   DIAGNOSTIC_POP
 }
 
@@ -2390,7 +2505,7 @@ printf_wide_c_string (struct ui_file *stream, const char *format,
   if (VALUE_LVAL (value) == lval_internalvar
       && c_is_string_type_p (value_type (value)))
     {
-      str = value_contents (value);
+      str = value_contents (value).data ();
       len = TYPE_LENGTH (value_type (value));
     }
   else
@@ -2401,7 +2516,7 @@ printf_wide_c_string (struct ui_file *stream, const char *format,
        {
          DIAGNOSTIC_PUSH
          DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-         fprintf_filtered (stream, format, "(null)");
+           gdb_printf (stream, format, "(null)");
          DIAGNOSTIC_POP
          return;
        }
@@ -2437,7 +2552,7 @@ printf_wide_c_string (struct ui_file *stream, const char *format,
 
   DIAGNOSTIC_PUSH
   DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-  fprintf_filtered (stream, format, obstack_base (&output));
+    gdb_printf (stream, format, obstack_base (&output));
   DIAGNOSTIC_POP
 }
 
@@ -2499,15 +2614,16 @@ printf_floating (struct ui_file *stream, const char *format,
     {
       param_type = float_type_from_length (param_type);
       if (param_type != value_type (value))
-       value = value_from_contents (param_type, value_contents (value));
+       value = value_from_contents (param_type,
+                                    value_contents (value).data ());
     }
 
   value = value_cast (fmt_type, value);
 
   /* Convert the value to a string and print it.  */
   std::string str
-    = target_float_to_string (value_contents (value), fmt_type, format);
-  fputs_filtered (str.c_str (), stream);
+    = target_float_to_string (value_contents (value).data (), fmt_type, format);
+  gdb_puts (str.c_str (), stream);
 }
 
 /* Subroutine of ui_printf to simplify it.
@@ -2568,7 +2684,7 @@ printf_pointer (struct ui_file *stream, const char *format,
       *fmt_p++ = '\0';
       DIAGNOSTIC_PUSH
       DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-      fprintf_filtered (stream, fmt, val);
+       gdb_printf (stream, fmt, val);
       DIAGNOSTIC_POP
     }
   else
@@ -2577,7 +2693,7 @@ printf_pointer (struct ui_file *stream, const char *format,
       *fmt_p++ = '\0';
       DIAGNOSTIC_PUSH
       DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-      fprintf_filtered (stream, fmt, "(nil)");
+       gdb_printf (stream, fmt, "(nil)");
       DIAGNOSTIC_POP
     }
 }
@@ -2667,7 +2783,7 @@ ui_printf (const char *arg, struct ui_file *stream)
                  || valtype->code () != TYPE_CODE_INT)
                error (_("expected wchar_t argument for %%lc"));
 
-             bytes = value_contents (val_args[i]);
+             bytes = value_contents (val_args[i]).data ();
 
              auto_obstack output;
 
@@ -2680,8 +2796,8 @@ ui_printf (const char *arg, struct ui_file *stream)
 
              DIAGNOSTIC_PUSH
              DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-             fprintf_filtered (stream, current_substring,
-                               obstack_base (&output));
+               gdb_printf (stream, current_substring,
+                           obstack_base (&output));
              DIAGNOSTIC_POP
            }
            break;
@@ -2692,7 +2808,7 @@ ui_printf (const char *arg, struct ui_file *stream)
 
              DIAGNOSTIC_PUSH
              DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-             fprintf_filtered (stream, current_substring, val);
+               gdb_printf (stream, current_substring, val);
              DIAGNOSTIC_POP
              break;
            }
@@ -2705,7 +2821,7 @@ ui_printf (const char *arg, struct ui_file *stream)
 
              DIAGNOSTIC_PUSH
              DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-             fprintf_filtered (stream, current_substring, val);
+               gdb_printf (stream, current_substring, val);
              DIAGNOSTIC_POP
              break;
            }
@@ -2715,7 +2831,7 @@ ui_printf (const char *arg, struct ui_file *stream)
 
              DIAGNOSTIC_PUSH
              DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-             fprintf_filtered (stream, current_substring, val);
+               gdb_printf (stream, current_substring, val);
              DIAGNOSTIC_POP
              break;
            }
@@ -2725,7 +2841,7 @@ ui_printf (const char *arg, struct ui_file *stream)
 
              DIAGNOSTIC_PUSH
              DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-             fprintf_filtered (stream, current_substring, val);
+               gdb_printf (stream, current_substring, val);
              DIAGNOSTIC_POP
              break;
            }
@@ -2745,14 +2861,14 @@ ui_printf (const char *arg, struct ui_file *stream)
            /* Print a portion of the format string that has no
               directives.  Note that this will not include any
               ordinary %-specs, but it might include "%%".  That is
-              why we use printf_filtered and not puts_filtered here.
+              why we use gdb_printf and not gdb_puts here.
               Also, we pass a dummy argument because some platforms
               have modified GCC to include -Wformat-security by
               default, which will warn here if there is no
               argument.  */
            DIAGNOSTIC_PUSH
            DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
-           fprintf_filtered (stream, current_substring, 0);
+             gdb_printf (stream, current_substring, 0);
            DIAGNOSTIC_POP
            break;
          default:
@@ -2772,8 +2888,8 @@ static void
 printf_command (const char *arg, int from_tty)
 {
   ui_printf (arg, gdb_stdout);
-  reset_terminal_style (gdb_stdout);
-  wrap_here ("");
+  gdb_stdout->reset_style ();
+  gdb_stdout->wrap_here (0);
   gdb_stdout->flush ();
 }
 
@@ -2844,9 +2960,9 @@ memory_tag_print_tag_command (const char *args, enum memtag_type tag_type)
   std::string tag = gdbarch_memtag_to_string (target_gdbarch (), tag_value);
 
   if (tag.empty ())
-    printf_filtered (_("%s tag unavailable.\n"),
-                    tag_type
-                      == memtag_type::logical? "Logical" : "Allocation");
+    gdb_printf (_("%s tag unavailable.\n"),
+               tag_type
+               == memtag_type::logical? "Logical" : "Allocation");
 
   struct value *v_tag = process_print_command_args (tag.c_str (),
                                                    &print_opts,
@@ -2942,7 +3058,7 @@ memory_tag_with_logical_tag_command (const char *args, int from_tty)
   /* Length doesn't matter for a logical tag.  Pass 0.  */
   if (!gdbarch_set_memtags (target_gdbarch (), val, 0, tags,
                            memtag_type::logical))
-    printf_filtered (_("Could not update the logical tag data.\n"));
+    gdb_printf (_("Could not update the logical tag data.\n"));
   else
     {
       /* Always print it in hex format.  */
@@ -3019,9 +3135,9 @@ memory_tag_set_allocation_tag_command (const char *args, int from_tty)
 
   if (!gdbarch_set_memtags (target_gdbarch (), val, length, tags,
                            memtag_type::allocation))
-    printf_filtered (_("Could not update the allocation tag(s).\n"));
+    gdb_printf (_("Could not update the allocation tag(s).\n"));
   else
-    printf_filtered (_("Allocation tag(s) updated successfully.\n"));
+    gdb_printf (_("Allocation tag(s) updated successfully.\n"));
 }
 
 /* Implement the "memory-tag check" command.  */
@@ -3061,10 +3177,10 @@ memory_tag_check_command (const char *args, int from_tty)
       std::string atag
        = gdbarch_memtag_to_string (target_gdbarch (), tag);
 
-      printf_filtered (_("Logical tag (%s) does not match"
-                        " the allocation tag (%s) for address %s.\n"),
-                      ltag.c_str (), atag.c_str (),
-                      paddress (target_gdbarch (), addr));
+      gdb_printf (_("Logical tag (%s) does not match"
+                   " the allocation tag (%s) for address %s.\n"),
+                 ltag.c_str (), atag.c_str (),
+                 paddress (target_gdbarch (), addr));
     }
   else
     {
@@ -3073,8 +3189,8 @@ memory_tag_check_command (const char *args, int from_tty)
       std::string ltag
        = gdbarch_memtag_to_string (target_gdbarch (), tag);
 
-      printf_filtered (_("Memory tags for address %s match (%s).\n"),
-                      paddress (target_gdbarch (), addr), ltag.c_str ());
+      gdb_printf (_("Memory tags for address %s match (%s).\n"),
+                 paddress (target_gdbarch (), addr), ltag.c_str ());
     }
 }
 
@@ -3086,7 +3202,8 @@ _initialize_printcmd ()
 
   current_display_number = -1;
 
-  gdb::observers::free_objfile.attach (clear_dangling_display_expressions);
+  gdb::observers::free_objfile.attach (clear_dangling_display_expressions,
+                                      "printcmd");
 
   add_info ("address", info_address_command,
            _("Describe where symbol SYM is stored.\n\
@@ -3180,19 +3297,7 @@ Use \"set variable\" for variables with names identical to set subcommands.\n\
 \n\
 With a subcommand, this command modifies parts of the gdb environment.\n\
 You can see these environment settings with the \"show\" command."),
-                 &setlist, "set ", 1, &cmdlist);
-  if (dbx_commands)
-    add_com ("assign", class_vars, set_command, _("\
-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\
-VAR may be a debugger \"convenience\" variable (names starting\n\
-with $), a register (a few standard names starting with $), or an actual\n\
-variable in the program being debugged.  EXP is any valid expression.\n\
-Use \"set variable\" for variables with names identical to set subcommands.\n\
-\nWith a subcommand, this command modifies parts of the gdb environment.\n\
-You can see these environment settings with the \"show\" command."));
+                 &setlist, 1, &cmdlist);
 
   /* "call" is the same as "set", but handy for dbx users to call fns.  */
   c = add_com ("call", class_vars, call_command, _("\
@@ -3203,7 +3308,8 @@ current working language.  The result is printed and saved in the value\n\
 history, if it is not void."));
   set_cmd_completer_handle_brkchars (c, print_command_completer);
 
-  add_cmd ("variable", class_vars, set_command, _("\
+  cmd_list_element *set_variable_cmd
+    = add_cmd ("variable", class_vars, set_command, _("\
 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\
@@ -3212,8 +3318,8 @@ VAR may be a debugger \"convenience\" variable (names starting\n\
 with $), a register (a few standard names starting with $), or an actual\n\
 variable in the program being debugged.  EXP is any valid expression.\n\
 This may usually be abbreviated to simply \"set\"."),
-          &setlist);
-  add_alias_cmd ("var", "variable", class_vars, 0, &setlist);
+              &setlist);
+  add_alias_cmd ("var", set_variable_cmd, class_vars, 0, &setlist);
 
   const auto print_opts = make_value_print_options_def_group (nullptr);
 
@@ -3250,10 +3356,11 @@ EXP may be preceded with /FMT, where FMT is a format letter\n\
 but no count or size letter (see \"x\" command)."),
                                              print_opts);
 
-  c = add_com ("print", class_vars, print_command, print_help.c_str ());
-  set_cmd_completer_handle_brkchars (c, print_command_completer);
-  add_com_alias ("p", "print", class_vars, 1);
-  add_com_alias ("inspect", "print", class_vars, 1);
+  cmd_list_element *print_cmd
+    = add_com ("print", class_vars, print_command, print_help.c_str ());
+  set_cmd_completer_handle_brkchars (print_cmd, print_command_completer);
+  add_com_alias ("p", print_cmd, class_vars, 1);
+  add_com_alias ("inspect", print_cmd, class_vars, 1);
 
   add_setshow_uinteger_cmd ("max-symbolic-offset", no_class,
                            &max_symbolic_offset, _("\
@@ -3284,7 +3391,7 @@ treat this string as a command line, and evaluate it."));
   /* Memory tagging commands.  */
   add_prefix_cmd ("memory-tag", class_vars, memory_tag_command, _("\
 Generic command for printing and manipulating memory tag properties."),
-                 &memory_tag_list, "memory-tag ", 0, &cmdlist);
+                 &memory_tag_list, 0, &cmdlist);
   add_cmd ("print-logical-tag", class_vars,
           memory_tag_print_logical_tag_command,
           ("Print the logical tag from POINTER.\n\