gdbsupport, gdb: give names to observers
[deliverable/binutils-gdb.git] / gdb / printcmd.c
index 9200e66db39a0859bcabdd0a46638b7ddafb320b..1c68d19cda1fb63861591033c689908f6627cfb2 100644 (file)
@@ -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;
@@ -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
@@ -1100,12 +1110,50 @@ 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 ())
+               {
+                 printf_filtered (_("<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);
       print_address (next_gdbarch, next_address, gdb_stdout);
@@ -1136,6 +1184,11 @@ 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");
     }
@@ -1208,6 +1261,26 @@ print_value (value *val, const value_print_options &opts)
   annotate_value_history_end ();
 }
 
+/* Returns true if memory tags should be validated.  False otherwise.  */
+
+static bool
+should_validate_memtags (struct value *value)
+{
+  if (target_supports_memory_tagging ()
+      && gdbarch_tagged_address_p (target_gdbarch (), value))
+    {
+      gdb_assert (value != nullptr && value_type (value) != nullptr);
+
+      enum type_code code = value_type (value)->code ();
+
+      return (code == TYPE_CODE_PTR
+             || code == TYPE_CODE_REF
+             || code == TYPE_CODE_METHODPTR
+             || code == TYPE_CODE_MEMBERPTR);
+    }
+  return false;
+}
+
 /* Helper for parsing arguments for print_command_1.  */
 
 static struct value *
@@ -1246,7 +1319,30 @@ 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 && 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);
+
+         printf_filtered (_("Logical tag (%s) does not match the "
+                            "allocation tag (%s).\n"),
+                          ltag.c_str (), atag.c_str ());
+       }
+      print_value (val, print_opts);
+    }
 }
 
 /* Called from command completion function to skip over /FMT
@@ -1741,6 +1837,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 +1894,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)
     {
@@ -2287,7 +2387,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.  */
@@ -3086,7 +3186,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\
This page took 0.025805 seconds and 4 git commands to generate.