gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index 2fd2438e61dcd55555e81168cb7fe9f7d3838e15..aead882acd885b13694af3f90e5a6fe525b6c46c 100644 (file)
@@ -1,6 +1,6 @@
 /* Everything about breakpoints, for GDB.
 
-   Copyright (C) 1986-2019 Free Software Foundation, Inc.
+   Copyright (C) 1986-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -144,6 +144,10 @@ static void describe_other_breakpoints (struct gdbarch *,
 static int watchpoint_locations_match (struct bp_location *loc1,
                                       struct bp_location *loc2);
 
+static int breakpoint_locations_match (struct bp_location *loc1,
+                                      struct bp_location *loc2,
+                                      bool sw_hw_bps_match = false);
+
 static int breakpoint_location_address_match (struct bp_location *bl,
                                              const struct address_space *aspace,
                                              CORE_ADDR addr);
@@ -246,6 +250,9 @@ struct breakpoint_ops bkpt_breakpoint_ops;
 /* Breakpoints set on probes.  */
 static struct breakpoint_ops bkpt_probe_breakpoint_ops;
 
+/* Tracepoints set on probes.  */
+static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
+
 /* Dynamic printf class type.  */
 struct breakpoint_ops dprintf_breakpoint_ops;
 
@@ -386,7 +393,7 @@ breakpoints_should_be_inserted_now (void)
         no threads under GDB's control yet.  */
       return 1;
     }
-  else if (target_has_execution)
+  else
     {
       if (always_inserted_mode)
        {
@@ -395,8 +402,10 @@ breakpoints_should_be_inserted_now (void)
          return 1;
        }
 
-      if (threads_are_executing ())
-       return 1;
+      for (inferior *inf : all_inferiors ())
+       if (inf->has_execution ()
+           && threads_are_executing (inf->process_target ()))
+         return 1;
 
       /* Don't remove breakpoints yet if, even though all threads are
         stopped, we still have events to process.  */
@@ -519,7 +528,7 @@ bool target_exact_watchpoints = false;
 
 static struct breakpoint *breakpoint_chain;
 
-/* Array is sorted by bp_locations_compare - primarily by the ADDRESS.  */
+/* Array is sorted by bp_location_is_less_than - primarily by the ADDRESS.  */
 
 static struct bp_location **bp_locations;
 
@@ -773,7 +782,7 @@ show_condition_evaluation_mode (struct ui_file *file, int from_tty,
 
 /* A comparison function for bp_location AP and BP that is used by
    bsearch.  This comparison function only cares about addresses, unlike
-   the more general bp_locations_compare function.  */
+   the more general bp_location_is_less_than function.  */
 
 static int
 bp_locations_compare_addrs (const void *ap, const void *bp)
@@ -1801,8 +1810,8 @@ update_watchpoint (struct watchpoint *b, int reparse)
                 for it explicitly, never if they just happen to
                 appear in the middle of some value chain.  */
              if (v == result
-                 || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
-                     && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+                 || (vtype->code () != TYPE_CODE_STRUCT
+                     && vtype->code () != TYPE_CODE_ARRAY))
                {
                  CORE_ADDR addr;
                  enum target_hw_bp_type type;
@@ -2120,10 +2129,14 @@ build_target_condition_list (struct bp_location *bl)
     return;
 
   /* Do a first pass to check for locations with no assigned
-     conditions or conditions that fail to parse to a valid agent expression
-     bytecode.  If any of these happen, then it's no use to send conditions
-     to the target since this location will always trigger and generate a
-     response back to GDB.  */
+     conditions or conditions that fail to parse to a valid agent
+     expression bytecode.  If any of these happen, then it's no use to
+     send conditions to the target since this location will always
+     trigger and generate a response back to GDB.  Note we consider
+     all locations at the same address irrespective of type, i.e.,
+     even if the locations aren't considered duplicates (e.g.,
+     software breakpoint and hardware breakpoint at the same
+     address).  */
   ALL_BP_LOCATIONS_AT_ADDR (loc2p, locp, bl->address)
     {
       loc = (*loc2p);
@@ -2172,8 +2185,12 @@ build_target_condition_list (struct bp_location *bl)
        }
     }
 
-  /* No NULL conditions or failed bytecode generation.  Build a condition list
-     for this location's address.  */
+  /* No NULL conditions or failed bytecode generation.  Build a
+     condition list for this location's address.  If we have software
+     and hardware locations at the same address, they aren't
+     considered duplicates, but we still marge all the conditions
+     anyway, as it's simpler, and doesn't really make a practical
+     difference.  */
   ALL_BP_LOCATIONS_AT_ADDR (loc2p, locp, bl->address)
     {
       loc = (*loc2p);
@@ -2291,9 +2308,9 @@ build_target_command_list (struct bp_location *bl)
   if (dprintf_style != dprintf_style_agent)
     return;
 
-  /* For now, if we have any duplicate location that isn't a dprintf,
-     don't install the target-side commands, as that would make the
-     breakpoint not be reported to the core, and we'd lose
+  /* For now, if we have any location at the same address that isn't a
+     dprintf, don't install the target-side commands, as that would
+     make the breakpoint not be reported to the core, and we'd lose
      control.  */
   ALL_BP_LOCATIONS_AT_ADDR (loc2p, locp, bl->address)
     {
@@ -2355,12 +2372,19 @@ build_target_command_list (struct bp_location *bl)
        }
     }
 
-  /* No NULL commands or failed bytecode generation.  Build a command list
-     for this location's address.  */
+  /* No NULL commands or failed bytecode generation.  Build a command
+     list for all duplicate locations at this location's address.
+     Note that here we must care for whether the breakpoint location
+     types are considered duplicates, otherwise, say, if we have a
+     software and hardware location at the same address, the target
+     could end up running the commands twice.  For the moment, we only
+     support targets-side commands with dprintf, but it doesn't hurt
+     to be pedantically correct in case that changes.  */
   ALL_BP_LOCATIONS_AT_ADDR (loc2p, locp, bl->address)
     {
       loc = (*loc2p);
-      if (loc->owner->extra_string
+      if (breakpoint_locations_match (bl, loc)
+         && loc->owner->extra_string
          && is_breakpoint (loc->owner)
          && loc->pspace->num == bl->pspace->num
          && loc->owner->enable_state == bp_enabled
@@ -2446,72 +2470,31 @@ insert_bp_location (struct bp_location *bl,
       bl->needs_update = 0;
     }
 
+  /* If "set breakpoint auto-hw" is "on" and a software breakpoint was
+     set at a read-only address, then a breakpoint location will have
+     been changed to hardware breakpoint before we get here.  If it is
+     "off" however, error out before actually trying to insert the
+     breakpoint, with a nicer error message.  */
   if (bl->loc_type == bp_loc_software_breakpoint
-      || bl->loc_type == bp_loc_hardware_breakpoint)
+      && !automatic_hardware_breakpoints)
     {
-      if (bl->owner->type != bp_hardware_breakpoint)
-       {
-         /* If the explicitly specified breakpoint type
-            is not hardware breakpoint, check the memory map to see
-            if the breakpoint address is in read only memory or not.
-
-            Two important cases are:
-            - location type is not hardware breakpoint, memory
-            is readonly.  We change the type of the location to
-            hardware breakpoint.
-            - location type is hardware breakpoint, memory is
-            read-write.  This means we've previously made the
-            location hardware one, but then the memory map changed,
-            so we undo.
-            
-            When breakpoints are removed, remove_breakpoints will use
-            location types we've just set here, the only possible
-            problem is that memory map has changed during running
-            program, but it's not going to work anyway with current
-            gdb.  */
-         struct mem_region *mr 
-           = lookup_mem_region (bl->target_info.reqstd_address);
-         
-         if (mr)
-           {
-             if (automatic_hardware_breakpoints)
-               {
-                 enum bp_loc_type new_type;
-                 
-                 if (mr->attrib.mode != MEM_RW)
-                   new_type = bp_loc_hardware_breakpoint;
-                 else 
-                   new_type = bp_loc_software_breakpoint;
-                 
-                 if (new_type != bl->loc_type)
-                   {
-                     static int said = 0;
+      mem_region *mr = lookup_mem_region (bl->address);
 
-                     bl->loc_type = new_type;
-                     if (!said)
-                       {
-                         fprintf_filtered (gdb_stdout,
-                                           _("Note: automatically using "
-                                             "hardware breakpoints for "
-                                             "read-only addresses.\n"));
-                         said = 1;
-                       }
-                   }
-               }
-             else if (bl->loc_type == bp_loc_software_breakpoint
-                      && mr->attrib.mode != MEM_RW)
-               {
-                 fprintf_unfiltered (tmp_error_stream,
-                                     _("Cannot insert breakpoint %d.\n"
-                                       "Cannot set software breakpoint "
-                                       "at read-only address %s\n"),
-                                     bl->owner->number,
-                                     paddress (bl->gdbarch, bl->address));
-                 return 1;
-               }
-           }
+      if (mr != nullptr && mr->attrib.mode != MEM_RW)
+       {
+         fprintf_unfiltered (tmp_error_stream,
+                             _("Cannot insert breakpoint %d.\n"
+                               "Cannot set software breakpoint "
+                               "at read-only address %s\n"),
+                             bl->owner->number,
+                             paddress (bl->gdbarch, bl->address));
+         return 1;
        }
-        
+    }
+
+  if (bl->loc_type == bp_loc_software_breakpoint
+      || bl->loc_type == bp_loc_hardware_breakpoint)
+    {
       /* First check to see if we have to handle an overlay.  */
       if (overlay_debugging == ovly_off
          || bl->section == NULL
@@ -2825,7 +2808,11 @@ insert_breakpoints (void)
 
   /* Updating watchpoints creates new locations, so update the global
      location list.  Explicitly tell ugll to insert locations and
-     ignore breakpoints_always_inserted_mode.  */
+     ignore breakpoints_always_inserted_mode.  Also,
+     update_global_location_list tries to "upgrade" software
+     breakpoints to hardware breakpoints to handle "set breakpoint
+     auto-hw", so we need to call it even if we don't have new
+     locations.  */
   update_global_location_list (UGLL_INSERT);
 }
 
@@ -2884,7 +2871,7 @@ update_inserted_breakpoint_locations (void)
         if we aren't attached to any process yet, we should still
         insert breakpoints.  */
       if (!gdbarch_has_global_breakpoints (target_gdbarch ())
-         && inferior_ptid == null_ptid)
+         && (inferior_ptid == null_ptid || !target_has_execution))
        continue;
 
       val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
@@ -2940,7 +2927,7 @@ insert_breakpoint_locations (void)
         if we aren't attached to any process yet, we should still
         insert breakpoints.  */
       if (!gdbarch_has_global_breakpoints (target_gdbarch ())
-         && inferior_ptid == null_ptid)
+         && (inferior_ptid == null_ptid || !target_has_execution))
        continue;
 
       val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
@@ -3196,7 +3183,7 @@ create_overlay_event_breakpoint (void)
        }
 
       addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym);
-      b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
+      b = create_internal_breakpoint (objfile->arch (), addr,
                                       bp_overlay_event,
                                      &internal_breakpoint_ops);
       initialize_explicit_location (&explicit_loc);
@@ -3219,153 +3206,151 @@ create_overlay_event_breakpoint (void)
 static void
 create_longjmp_master_breakpoint (void)
 {
-  struct program_space *pspace;
-
   scoped_restore_current_program_space restore_pspace;
 
-  ALL_PSPACES (pspace)
-  {
-    set_current_program_space (pspace);
+  for (struct program_space *pspace : program_spaces)
+    {
+      set_current_program_space (pspace);
 
-    for (objfile *objfile : current_program_space->objfiles ())
-      {
-       int i;
-       struct gdbarch *gdbarch;
-       struct breakpoint_objfile_data *bp_objfile_data;
+      for (objfile *objfile : current_program_space->objfiles ())
+       {
+         int i;
+         struct gdbarch *gdbarch;
+         struct breakpoint_objfile_data *bp_objfile_data;
 
-       gdbarch = get_objfile_arch (objfile);
+         gdbarch = objfile->arch ();
 
-       bp_objfile_data = get_breakpoint_objfile_data (objfile);
+         bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
-       if (!bp_objfile_data->longjmp_searched)
-         {
-           std::vector<probe *> ret
-             = find_probes_in_objfile (objfile, "libc", "longjmp");
+         if (!bp_objfile_data->longjmp_searched)
+           {
+             std::vector<probe *> ret
+               = find_probes_in_objfile (objfile, "libc", "longjmp");
 
-           if (!ret.empty ())
-             {
-               /* We are only interested in checking one element.  */
-               probe *p = ret[0];
+             if (!ret.empty ())
+               {
+                 /* We are only interested in checking one element.  */
+                 probe *p = ret[0];
 
-               if (!p->can_evaluate_arguments ())
-                 {
-                   /* We cannot use the probe interface here, because it does
-                      not know how to evaluate arguments.  */
-                   ret.clear ();
-                 }
-             }
-           bp_objfile_data->longjmp_probes = ret;
-           bp_objfile_data->longjmp_searched = 1;
-         }
+                 if (!p->can_evaluate_arguments ())
+                   {
+                     /* We cannot use the probe interface here,
+                        because it does not know how to evaluate
+                        arguments.  */
+                     ret.clear ();
+                   }
+               }
+             bp_objfile_data->longjmp_probes = ret;
+             bp_objfile_data->longjmp_searched = 1;
+           }
 
-       if (!bp_objfile_data->longjmp_probes.empty ())
-         {
-           for (probe *p : bp_objfile_data->longjmp_probes)
-             {
-               struct breakpoint *b;
-
-               b = create_internal_breakpoint (gdbarch,
-                                               p->get_relocated_address (objfile),
-                                               bp_longjmp_master,
-                                               &internal_breakpoint_ops);
-               b->location = new_probe_location ("-probe-stap libc:longjmp");
-               b->enable_state = bp_disabled;
-             }
+         if (!bp_objfile_data->longjmp_probes.empty ())
+           {
+             for (probe *p : bp_objfile_data->longjmp_probes)
+               {
+                 struct breakpoint *b;
+
+                 b = create_internal_breakpoint (gdbarch,
+                                                 p->get_relocated_address (objfile),
+                                                 bp_longjmp_master,
+                                                 &internal_breakpoint_ops);
+                 b->location = new_probe_location ("-probe-stap libc:longjmp");
+                 b->enable_state = bp_disabled;
+               }
 
-           continue;
-         }
+             continue;
+           }
 
-       if (!gdbarch_get_longjmp_target_p (gdbarch))
-         continue;
+         if (!gdbarch_get_longjmp_target_p (gdbarch))
+           continue;
 
-       for (i = 0; i < NUM_LONGJMP_NAMES; i++)
-         {
-           struct breakpoint *b;
-           const char *func_name;
-           CORE_ADDR addr;
-           struct explicit_location explicit_loc;
+         for (i = 0; i < NUM_LONGJMP_NAMES; i++)
+           {
+             struct breakpoint *b;
+             const char *func_name;
+             CORE_ADDR addr;
+             struct explicit_location explicit_loc;
 
-           if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
-             continue;
+             if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
+               continue;
 
-           func_name = longjmp_names[i];
-           if (bp_objfile_data->longjmp_msym[i].minsym == NULL)
-             {
-               struct bound_minimal_symbol m;
+             func_name = longjmp_names[i];
+             if (bp_objfile_data->longjmp_msym[i].minsym == NULL)
+               {
+                 struct bound_minimal_symbol m;
 
-               m = lookup_minimal_symbol_text (func_name, objfile);
-               if (m.minsym == NULL)
-                 {
-                   /* Prevent future lookups in this objfile.  */
-                   bp_objfile_data->longjmp_msym[i].minsym = &msym_not_found;
-                   continue;
-                 }
-               bp_objfile_data->longjmp_msym[i] = m;
-             }
+                 m = lookup_minimal_symbol_text (func_name, objfile);
+                 if (m.minsym == NULL)
+                   {
+                     /* Prevent future lookups in this objfile.  */
+                     bp_objfile_data->longjmp_msym[i].minsym = &msym_not_found;
+                     continue;
+                   }
+                 bp_objfile_data->longjmp_msym[i] = m;
+               }
 
-           addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
-           b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
-                                           &internal_breakpoint_ops);
-           initialize_explicit_location (&explicit_loc);
-           explicit_loc.function_name = ASTRDUP (func_name);
-           b->location = new_explicit_location (&explicit_loc);
-           b->enable_state = bp_disabled;
-         }
-      }
-  }
+             addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
+             b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
+                                             &internal_breakpoint_ops);
+             initialize_explicit_location (&explicit_loc);
+             explicit_loc.function_name = ASTRDUP (func_name);
+             b->location = new_explicit_location (&explicit_loc);
+             b->enable_state = bp_disabled;
+           }
+       }
+    }
 }
 
 /* Create a master std::terminate breakpoint.  */
 static void
 create_std_terminate_master_breakpoint (void)
 {
-  struct program_space *pspace;
   const char *const func_name = "std::terminate()";
 
   scoped_restore_current_program_space restore_pspace;
 
-  ALL_PSPACES (pspace)
-  {
-    CORE_ADDR addr;
+  for (struct program_space *pspace : program_spaces)
+    {
+      CORE_ADDR addr;
 
-    set_current_program_space (pspace);
+      set_current_program_space (pspace);
 
-    for (objfile *objfile : current_program_space->objfiles ())
-      {
-       struct breakpoint *b;
-       struct breakpoint_objfile_data *bp_objfile_data;
-       struct explicit_location explicit_loc;
+      for (objfile *objfile : current_program_space->objfiles ())
+       {
+         struct breakpoint *b;
+         struct breakpoint_objfile_data *bp_objfile_data;
+         struct explicit_location explicit_loc;
 
-       bp_objfile_data = get_breakpoint_objfile_data (objfile);
+         bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
-       if (msym_not_found_p (bp_objfile_data->terminate_msym.minsym))
-         continue;
+         if (msym_not_found_p (bp_objfile_data->terminate_msym.minsym))
+           continue;
 
-       if (bp_objfile_data->terminate_msym.minsym == NULL)
-         {
-           struct bound_minimal_symbol m;
+         if (bp_objfile_data->terminate_msym.minsym == NULL)
+           {
+             struct bound_minimal_symbol m;
 
-           m = lookup_minimal_symbol (func_name, NULL, objfile);
-           if (m.minsym == NULL || (MSYMBOL_TYPE (m.minsym) != mst_text
-                                    && MSYMBOL_TYPE (m.minsym) != mst_file_text))
-             {
-               /* Prevent future lookups in this objfile.  */
-               bp_objfile_data->terminate_msym.minsym = &msym_not_found;
-               continue;
-             }
-           bp_objfile_data->terminate_msym = m;
-         }
+             m = lookup_minimal_symbol (func_name, NULL, objfile);
+             if (m.minsym == NULL || (MSYMBOL_TYPE (m.minsym) != mst_text
+                                      && MSYMBOL_TYPE (m.minsym) != mst_file_text))
+               {
+                 /* Prevent future lookups in this objfile.  */
+                 bp_objfile_data->terminate_msym.minsym = &msym_not_found;
+                 continue;
+               }
+             bp_objfile_data->terminate_msym = m;
+           }
 
-       addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym);
-       b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
-                                       bp_std_terminate_master,
-                                       &internal_breakpoint_ops);
-       initialize_explicit_location (&explicit_loc);
-       explicit_loc.function_name = ASTRDUP (func_name);
-       b->location = new_explicit_location (&explicit_loc);
-       b->enable_state = bp_disabled;
-      }
-  }
+         addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym);
+         b = create_internal_breakpoint (objfile->arch (), addr,
+                                         bp_std_terminate_master,
+                                         &internal_breakpoint_ops);
+         initialize_explicit_location (&explicit_loc);
+         explicit_loc.function_name = ASTRDUP (func_name);
+         b->location = new_explicit_location (&explicit_loc);
+         b->enable_state = bp_disabled;
+       }
+    }
 }
 
 /* Install a master breakpoint on the unwinder's debug hook.  */
@@ -3409,7 +3394,7 @@ create_exception_master_breakpoint (void)
 
       if (!bp_objfile_data->exception_probes.empty ())
        {
-         gdbarch = get_objfile_arch (objfile);
+         gdbarch = objfile->arch ();
 
          for (probe *p : bp_objfile_data->exception_probes)
            {
@@ -3429,7 +3414,7 @@ create_exception_master_breakpoint (void)
       if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
        continue;
 
-      gdbarch = get_objfile_arch (objfile);
+      gdbarch = objfile->arch ();
 
       if (bp_objfile_data->exception_msym.minsym == NULL)
        {
@@ -5818,7 +5803,7 @@ print_breakpoint_location (struct breakpoint *b,
       if (sym)
        {
          uiout->text ("in ");
-         uiout->field_string ("func", SYMBOL_PRINT_NAME (sym),
+         uiout->field_string ("func", sym->print_name (),
                               function_name_style.style ());
          uiout->text (" ");
          uiout->wrap_hint (wrap_indent_at_field (uiout, "what"));
@@ -6083,7 +6068,7 @@ print_one_breakpoint_location (struct breakpoint *b,
           there are several.  Always display for MI. */
        if (allflag
            || (!gdbarch_has_global_breakpoints (target_gdbarch ())
-               && (number_of_program_spaces () > 1
+               && (program_spaces.size () > 1
                    || number_of_inferiors () > 1)
                /* LOC is for existing B, it cannot be in
                   moribund_locations and thus having NULL OWNER.  */
@@ -6808,11 +6793,14 @@ tracepoint_locations_match (struct bp_location *loc1,
 
 /* Assuming LOC1 and LOC2's types' have meaningful target addresses
    (bl_address_is_meaningful), returns true if LOC1 and LOC2 represent
-   the same location.  */
+   the same location.  If SW_HW_BPS_MATCH is true, then software
+   breakpoint locations and hardware breakpoint locations match,
+   otherwise they don't.  */
 
 static int
-breakpoint_locations_match (struct bp_location *loc1, 
-                           struct bp_location *loc2)
+breakpoint_locations_match (struct bp_location *loc1,
+                           struct bp_location *loc2,
+                           bool sw_hw_bps_match)
 {
   int hw_point1, hw_point2;
 
@@ -6830,9 +6818,12 @@ breakpoint_locations_match (struct bp_location *loc1,
   else if (is_tracepoint (loc1->owner) || is_tracepoint (loc2->owner))
     return tracepoint_locations_match (loc1, loc2);
   else
-    /* We compare bp_location.length in order to cover ranged breakpoints.  */
+    /* We compare bp_location.length in order to cover ranged
+       breakpoints.  Keep this in sync with
+       bp_location_is_less_than.  */
     return (breakpoint_address_match (loc1->pspace->aspace, loc1->address,
                                     loc2->pspace->aspace, loc2->address)
+           && (loc1->loc_type == loc2->loc_type || sw_hw_bps_match)
            && loc1->length == loc2->length);
 }
 
@@ -7085,7 +7076,7 @@ set_breakpoint_location_function (struct bp_location *loc)
        {
          struct breakpoint *b = loc->owner;
 
-         function_name = MSYMBOL_LINKAGE_NAME (loc->msymbol);
+         function_name = loc->msymbol->linkage_name ();
 
          if (b->type == bp_breakpoint && b->loc == loc
              && loc->next == NULL && b->related_breakpoint == b)
@@ -7111,9 +7102,9 @@ struct gdbarch *
 get_sal_arch (struct symtab_and_line sal)
 {
   if (sal.section)
-    return get_objfile_arch (sal.section->objfile);
+    return sal.section->objfile->arch ();
   if (sal.symtab)
-    return get_objfile_arch (SYMTAB_OBJFILE (sal.symtab));
+    return SYMTAB_OBJFILE (sal.symtab)->arch ();
 
   return NULL;
 }
@@ -8510,7 +8501,62 @@ mention (struct breakpoint *b)
 }
 \f
 
-static int bp_loc_is_permanent (struct bp_location *loc);
+static bool bp_loc_is_permanent (struct bp_location *loc);
+
+/* Handle "set breakpoint auto-hw on".
+
+   If the explicitly specified breakpoint type is not hardware
+   breakpoint, check the memory map to see whether the breakpoint
+   address is in read-only memory.
+
+   - location type is not hardware breakpoint, memory is read-only.
+   We change the type of the location to hardware breakpoint.
+
+   - location type is hardware breakpoint, memory is read-write.  This
+   means we've previously made the location hardware one, but then the
+   memory map changed, so we undo.
+*/
+
+static void
+handle_automatic_hardware_breakpoints (bp_location *bl)
+{
+  if (automatic_hardware_breakpoints
+      && bl->owner->type != bp_hardware_breakpoint
+      && (bl->loc_type == bp_loc_software_breakpoint
+         || bl->loc_type == bp_loc_hardware_breakpoint))
+    {
+      /* When breakpoints are removed, remove_breakpoints will use
+        location types we've just set here, the only possible problem
+        is that memory map has changed during running program, but
+        it's not going to work anyway with current gdb.  */
+      mem_region *mr = lookup_mem_region (bl->address);
+
+      if (mr != nullptr)
+       {
+         enum bp_loc_type new_type;
+
+         if (mr->attrib.mode != MEM_RW)
+           new_type = bp_loc_hardware_breakpoint;
+         else
+           new_type = bp_loc_software_breakpoint;
+
+         if (new_type != bl->loc_type)
+           {
+             static bool said = false;
+
+             bl->loc_type = new_type;
+             if (!said)
+               {
+                 fprintf_filtered (gdb_stdout,
+                                   _("Note: automatically using "
+                                     "hardware breakpoints for "
+                                     "read-only addresses.\n"));
+                 said = true;
+               }
+           }
+       }
+    }
+}
 
 static struct bp_location *
 add_location_to_breakpoint (struct breakpoint *b,
@@ -8576,42 +8622,10 @@ add_location_to_breakpoint (struct breakpoint *b,
 }
 \f
 
-/* See breakpoint.h.  */
-
-int
-program_breakpoint_here_p (struct gdbarch *gdbarch, CORE_ADDR address)
-{
-  int len;
-  CORE_ADDR addr;
-  const gdb_byte *bpoint;
-  gdb_byte *target_mem;
+/* Return true if LOC is pointing to a permanent breakpoint,
+   return false otherwise.  */
 
-  addr = address;
-  bpoint = gdbarch_breakpoint_from_pc (gdbarch, &addr, &len);
-
-  /* Software breakpoints unsupported?  */
-  if (bpoint == NULL)
-    return 0;
-
-  target_mem = (gdb_byte *) alloca (len);
-
-  /* Enable the automatic memory restoration from breakpoints while
-     we read the memory.  Otherwise we could say about our temporary
-     breakpoints they are permanent.  */
-  scoped_restore restore_memory
-    = make_scoped_restore_show_memory_breakpoints (0);
-
-  if (target_read_memory (address, target_mem, len) == 0
-      && memcmp (target_mem, bpoint, len) == 0)
-    return 1;
-
-  return 0;
-}
-
-/* Return 1 if LOC is pointing to a permanent breakpoint,
-   return 0 otherwise.  */
-
-static int
+static bool
 bp_loc_is_permanent (struct bp_location *loc)
 {
   gdb_assert (loc != NULL);
@@ -8619,14 +8633,14 @@ bp_loc_is_permanent (struct bp_location *loc)
   /* If we have a non-breakpoint-backed catchpoint or a software
      watchpoint, just return 0.  We should not attempt to read from
      the addresses the locations of these breakpoint types point to.
-     program_breakpoint_here_p, below, will attempt to read
+     gdbarch_program_breakpoint_here_p, below, will attempt to read
      memory.  */
   if (!bl_address_is_meaningful (loc))
-    return 0;
+    return false;
 
   scoped_restore_current_pspace_and_thread restore_pspace_thread;
   switch_to_program_space_and_thread (loc->pspace);
-  return program_breakpoint_here_p (loc->gdbarch, loc->address);
+  return gdbarch_program_breakpoint_here_p (loc->gdbarch, loc->address);
 }
 
 /* Build a command list for the dprintf corresponding to the current
@@ -9163,6 +9177,41 @@ decode_static_tracepoint_spec (const char **arg_p)
   return sals;
 }
 
+/* Returns the breakpoint ops appropriate for use with with LOCATION_TYPE and
+   according to IS_TRACEPOINT.  */
+
+static const struct breakpoint_ops *
+breakpoint_ops_for_event_location_type (enum event_location_type location_type,
+                                       bool is_tracepoint)
+{
+  if (is_tracepoint)
+    {
+      if (location_type == PROBE_LOCATION)
+       return &tracepoint_probe_breakpoint_ops;
+      else
+       return &tracepoint_breakpoint_ops;
+    }
+  else
+    {
+      if (location_type == PROBE_LOCATION)
+       return &bkpt_probe_breakpoint_ops;
+      else
+       return &bkpt_breakpoint_ops;
+    }
+}
+
+/* See breakpoint.h.  */
+
+const struct breakpoint_ops *
+breakpoint_ops_for_event_location (const struct event_location *location,
+                                  bool is_tracepoint)
+{
+  if (location != nullptr)
+    return breakpoint_ops_for_event_location_type
+      (event_location_type (location), is_tracepoint);
+  return is_tracepoint ? &tracepoint_breakpoint_ops : &bkpt_breakpoint_ops;
+}
+
 /* See breakpoint.h.  */
 
 int
@@ -9344,16 +9393,10 @@ break_command_1 (const char *arg, int flag, int from_tty)
   enum bptype type_wanted = (flag & BP_HARDWAREFLAG
                             ? bp_hardware_breakpoint
                             : bp_breakpoint);
-  struct breakpoint_ops *ops;
 
   event_location_up location = string_to_event_location (&arg, current_language);
-
-  /* Matching breakpoints on probes.  */
-  if (location != NULL
-      && event_location_type (location.get ()) == PROBE_LOCATION)
-    ops = &bkpt_probe_breakpoint_ops;
-  else
-    ops = &bkpt_breakpoint_ops;
+  const struct breakpoint_ops *ops = breakpoint_ops_for_event_location
+    (location.get (), false /* is_tracepoint */);
 
   create_breakpoint (get_current_arch (),
                     location.get (),
@@ -10398,7 +10441,6 @@ static void
 print_recreate_masked_watchpoint (struct breakpoint *b, struct ui_file *fp)
 {
   struct watchpoint *w = (struct watchpoint *) b;
-  char tmp[40];
 
   switch (b->type)
     {
@@ -10416,8 +10458,8 @@ print_recreate_masked_watchpoint (struct breakpoint *b, struct ui_file *fp)
                      _("Invalid hardware watchpoint type."));
     }
 
-  sprintf_vma (tmp, w->hw_wp_mask);
-  fprintf_unfiltered (fp, " %s mask 0x%s", w->exp_string, tmp);
+  fprintf_unfiltered (fp, " %s mask 0x%s", w->exp_string,
+                     phex (w->hw_wp_mask, sizeof (CORE_ADDR)));
   print_recreate_thread (b, fp);
 }
 
@@ -10807,8 +10849,8 @@ can_use_hardware_watchpoint (const std::vector<value_ref_ptr> &vals)
                 explicitly, never if they just happen to appear in a
                 middle of some value chain.  */
              if (v == head
-                 || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
-                     && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+                 || (vtype->code () != TYPE_CODE_STRUCT
+                     && vtype->code () != TYPE_CODE_ARRAY))
                {
                  CORE_ADDR vaddr = value_address (v);
                  int len;
@@ -11213,19 +11255,8 @@ init_ada_exception_breakpoint (struct breakpoint *b,
   b->language = language_ada;
 }
 
-static void
-catch_command (const char *arg, int from_tty)
-{
-  error (_("Catch requires an event name."));
-}
 \f
 
-static void
-tcatch_command (const char *arg, int from_tty)
-{
-  error (_("Catch requires an event name."));
-}
-
 /* Compare two breakpoints and return a strcmp-like result.  */
 
 static int
@@ -11428,41 +11459,48 @@ breakpoint_auto_delete (bpstat bs)
 }
 
 /* A comparison function for bp_location AP and BP being interfaced to
-   qsort.  Sort elements primarily by their ADDRESS (no matter what
+   std::sort.  Sort elements primarily by their ADDRESS (no matter what
    bl_address_is_meaningful says), secondarily by ordering first
    permanent elements and terciarily just ensuring the array is sorted
-   stable way despite qsort being an unstable algorithm.  */
+   stable way despite std::sort being an unstable algorithm.  */
 
 static int
-bp_locations_compare (const void *ap, const void *bp)
+bp_location_is_less_than (const bp_location *a, const bp_location *b)
 {
-  const struct bp_location *a = *(const struct bp_location **) ap;
-  const struct bp_location *b = *(const struct bp_location **) bp;
-
   if (a->address != b->address)
-    return (a->address > b->address) - (a->address < b->address);
+    return a->address < b->address;
 
   /* Sort locations at the same address by their pspace number, keeping
      locations of the same inferior (in a multi-inferior environment)
      grouped.  */
 
   if (a->pspace->num != b->pspace->num)
-    return ((a->pspace->num > b->pspace->num)
-           - (a->pspace->num < b->pspace->num));
+    return a->pspace->num < b->pspace->num;
 
   /* Sort permanent breakpoints first.  */
   if (a->permanent != b->permanent)
-    return (a->permanent < b->permanent) - (a->permanent > b->permanent);
+    return a->permanent > b->permanent;
+
+  /* Sort by type in order to make duplicate determination easier.
+     See update_global_location_list.  This is kept in sync with
+     breakpoint_locations_match.  */
+  if (a->loc_type < b->loc_type)
+    return true;
+
+  /* Likewise, for range-breakpoints, sort by length.  */
+  if (a->loc_type == bp_loc_hardware_breakpoint
+      && b->loc_type == bp_loc_hardware_breakpoint
+      && a->length < b->length)
+    return true;
 
   /* Make the internal GDB representation stable across GDB runs
      where A and B memory inside GDB can differ.  Breakpoint locations of
      the same type at the same address can be sorted in arbitrary order.  */
 
   if (a->owner->number != b->owner->number)
-    return ((a->owner->number > b->owner->number)
-           - (a->owner->number < b->owner->number));
+    return a->owner->number < b->owner->number;
 
-  return (a > b) - (a < b);
+  return a < b;
 }
 
 /* Set bp_locations_placed_address_before_address_max and
@@ -11629,6 +11667,7 @@ force_breakpoint_reinsertion (struct bp_location *bl)
       loc->cond_bytecode.reset ();
     }
 }
+
 /* Called whether new breakpoints are created, or existing breakpoints
    deleted, to update the global location list and recompute which
    locations are duplicate of which.
@@ -11677,8 +11716,22 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
   ALL_BREAKPOINTS (b)
     for (loc = b->loc; loc; loc = loc->next)
       *locp++ = loc;
-  qsort (bp_locations, bp_locations_count, sizeof (*bp_locations),
-        bp_locations_compare);
+
+  /* See if we need to "upgrade" a software breakpoint to a hardware
+     breakpoint.  Do this before deciding whether locations are
+     duplicates.  Also do this before sorting because sorting order
+     depends on location type.  */
+  for (locp = bp_locations;
+       locp < bp_locations + bp_locations_count;
+       locp++)
+    {
+      loc = *locp;
+      if (!loc->inserted && should_be_inserted (loc))
+       handle_automatic_hardware_breakpoints (loc);
+    }
+
+  std::sort (bp_locations, bp_locations + bp_locations_count,
+            bp_location_is_less_than);
 
   bp_locations_target_extensions_update ();
 
@@ -11780,6 +11833,9 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
                    {
                      struct bp_location *loc2 = *loc2p;
 
+                     if (loc2 == old_loc)
+                       continue;
+
                      if (breakpoint_locations_match (loc2, old_loc))
                        {
                          /* Read watchpoint locations are switched to
@@ -11794,8 +11850,7 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
                          /* loc2 is a duplicated location. We need to check
                             if it should be inserted in case it will be
                             unduplicated.  */
-                         if (loc2 != old_loc
-                             && unduplicated_should_be_inserted (loc2))
+                         if (unduplicated_should_be_inserted (loc2))
                            {
                              swap_insertion (old_loc, loc2);
                              keep_in_target = 1;
@@ -11876,7 +11931,18 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
                 around.  We simply always ignore hardware watchpoint
                 traps we can no longer explain.  */
 
-             old_loc->events_till_retirement = 3 * (thread_count () + 1);
+             process_stratum_target *proc_target = nullptr;
+             for (inferior *inf : all_inferiors ())
+               if (inf->pspace == old_loc->pspace)
+                 {
+                   proc_target = inf->process_target ();
+                   break;
+                 }
+             if (proc_target != nullptr)
+               old_loc->events_till_retirement
+                 = 3 * (thread_count (proc_target) + 1);
+             else
+               old_loc->events_till_retirement = 1;
              old_loc->owner = NULL;
 
              moribund_locations.push_back (old_loc);
@@ -12807,8 +12873,7 @@ tracepoint_decode_location (struct breakpoint *b,
 
 struct breakpoint_ops tracepoint_breakpoint_ops;
 
-/* The breakpoint_ops structure to be use on tracepoints placed in a
-   static probe.  */
+/* Virtual table for tracepoints on static probes.  */
 
 static void
 tracepoint_probe_create_sals_from_location
@@ -12829,8 +12894,6 @@ tracepoint_probe_decode_location (struct breakpoint *b,
   return bkpt_probe_decode_location (b, location, search_pspace);
 }
 
-static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
-
 /* Dprintf breakpoint_ops methods.  */
 
 static void
@@ -13309,7 +13372,7 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
          uiout->text ("Now in ");
          if (sym)
            {
-             uiout->field_string ("func", SYMBOL_PRINT_NAME (sym),
+             uiout->field_string ("func", sym->print_name (),
                                   function_name_style.style ());
              uiout->text (" at ");
            }
@@ -13504,11 +13567,20 @@ update_breakpoint_locations (struct breakpoint *b,
            if (have_ambiguous_names)
              {
                for (; l; l = l->next)
-                 if (breakpoint_locations_match (e, l))
-                   {
-                     l->enabled = 0;
-                     break;
-                   }
+                 {
+                   /* Ignore software vs hardware location type at
+                      this point, because with "set breakpoint
+                      auto-hw", after a re-set, locations that were
+                      hardware can end up as software, or vice versa.
+                      As mentioned above, this is an heuristic and in
+                      practice should give the correct answer often
+                      enough.  */
+                   if (breakpoint_locations_match (e, l, true))
+                     {
+                       l->enabled = 0;
+                       break;
+                     }
+                 }
              }
            else
              {
@@ -14331,16 +14403,6 @@ enable_delete_command (const char *args, int from_tty)
      });
 }
 \f
-static void
-set_breakpoint_cmd (const char *args, int from_tty)
-{
-}
-
-static void
-show_breakpoint_cmd (const char *args, int from_tty)
-{
-}
-
 /* Invalidate last known value of any hardware watchpoint if
    the memory which that value represents has been written to by
    GDB itself.  */
@@ -14472,15 +14534,10 @@ set_tracepoint_count (int num)
 static void
 trace_command (const char *arg, int from_tty)
 {
-  struct breakpoint_ops *ops;
-
   event_location_up location = string_to_event_location (&arg,
                                                         current_language);
-  if (location != NULL
-      && event_location_type (location.get ()) == PROBE_LOCATION)
-    ops = &tracepoint_probe_breakpoint_ops;
-  else
-    ops = &tracepoint_breakpoint_ops;
+  const struct breakpoint_ops *ops = breakpoint_ops_for_event_location
+    (location.get (), true /* is_tracepoint */);
 
   create_breakpoint (get_current_arch (),
                     location.get (),
@@ -15119,14 +15176,6 @@ add_catch_command (const char *name, const char *docstring,
   set_cmd_completer (command, completer);
 }
 
-static void
-save_command (const char *arg, int from_tty)
-{
-  printf_unfiltered (_("\"save\" must be followed by "
-                      "the name of a save subcommand.\n"));
-  help_list (save_cmdlist, "save ", all_commands, gdb_stdout);
-}
-
 struct breakpoint *
 iterate_over_breakpoints (gdb::function_view<bool (breakpoint *)> callback)
 {
@@ -15377,8 +15426,9 @@ static struct cmd_list_element *enablebreaklist = NULL;
 
 cmd_list_element *commands_cmd_element = nullptr;
 
+void _initialize_breakpoint ();
 void
-_initialize_breakpoint (void)
+_initialize_breakpoint ()
 {
   struct cmd_list_element *c;
 
@@ -15509,7 +15559,7 @@ A disabled breakpoint is not forgotten, but has no effect until re-enabled."),
   add_com_alias ("dis", "disable", class_breakpoint, 1);
   add_com_alias ("disa", "disable", class_breakpoint, 1);
 
-  add_cmd ("breakpoints", class_alias, disable_command, _("\
+  add_cmd ("breakpoints", class_breakpoint, disable_command, _("\
 Disable all or some breakpoints.\n\
 Usage: disable breakpoints [BREAKPOINTNUM]...\n\
 Arguments are breakpoint numbers with spaces in between.\n\
@@ -15529,7 +15579,7 @@ Also a prefix command for deletion of other GDB objects."),
   add_com_alias ("d", "delete", class_breakpoint, 1);
   add_com_alias ("del", "delete", class_breakpoint, 1);
 
-  add_cmd ("breakpoints", class_alias, delete_command, _("\
+  add_cmd ("breakpoints", class_breakpoint, delete_command, _("\
 Delete all or some breakpoints or auto-display expressions.\n\
 Usage: delete breakpoints [BREAKPOINTNUM]...\n\
 Arguments are breakpoint numbers with spaces in between.\n\
@@ -15622,15 +15672,15 @@ Convenience variable \"$bpnum\" contains the number of the last\n\
 breakpoint set."),
           &maintenanceinfolist);
 
-  add_prefix_cmd ("catch", class_breakpoint, catch_command, _("\
+  add_basic_prefix_cmd ("catch", class_breakpoint, _("\
 Set catchpoints to catch events."),
-                 &catch_cmdlist, "catch ",
-                 0/*allow-unknown*/, &cmdlist);
+                       &catch_cmdlist, "catch ",
+                       0/*allow-unknown*/, &cmdlist);
 
-  add_prefix_cmd ("tcatch", class_breakpoint, tcatch_command, _("\
+  add_basic_prefix_cmd ("tcatch", class_breakpoint, _("\
 Set temporary catchpoints to catch events."),
-                 &tcatch_cmdlist, "tcatch ",
-                 0/*allow-unknown*/, &cmdlist);
+                       &tcatch_cmdlist, "tcatch ",
+                       0/*allow-unknown*/, &cmdlist);
 
   add_catch_command ("fork", _("Catch calls to fork."),
                     catch_fork_command_1,
@@ -15717,10 +15767,10 @@ BREAK_ARGS_HELP ("trace") "\n\
 Do \"help tracepoints\" for info on other tracepoint commands."));
   set_cmd_completer (c, location_completer);
 
-  add_com_alias ("tp", "trace", class_alias, 0);
-  add_com_alias ("tr", "trace", class_alias, 1);
-  add_com_alias ("tra", "trace", class_alias, 1);
-  add_com_alias ("trac", "trace", class_alias, 1);
+  add_com_alias ("tp", "trace", class_breakpoint, 0);
+  add_com_alias ("tr", "trace", class_breakpoint, 1);
+  add_com_alias ("tra", "trace", class_breakpoint, 1);
+  add_com_alias ("trac", "trace", class_breakpoint, 1);
 
   c = add_com ("ftrace", class_breakpoint, ftrace_command, _("\
 Set a fast tracepoint at specified location.\n\
@@ -15785,10 +15835,10 @@ The trace will end when the tracepoint has been passed 'count' times.\n\
 Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
 if TPNUM is omitted, passcount refers to the last tracepoint defined."));
 
-  add_prefix_cmd ("save", class_breakpoint, save_command,
-                 _("Save breakpoint definitions as a script."),
-                 &save_cmdlist, "save ",
-                 0/*allow-unknown*/, &cmdlist);
+  add_basic_prefix_cmd ("save", class_breakpoint,
+                       _("Save breakpoint definitions as a script."),
+                       &save_cmdlist, "save ",
+                       0/*allow-unknown*/, &cmdlist);
 
   c = add_cmd ("breakpoints", class_breakpoint, save_breakpoints_command, _("\
 Save current breakpoint definitions as a script.\n\
@@ -15807,18 +15857,18 @@ Use the 'source' command in another debug session to restore them."),
   c = add_com_alias ("save-tracepoints", "save tracepoints", class_trace, 0);
   deprecate_cmd (c, "save tracepoints");
 
-  add_prefix_cmd ("breakpoint", class_maintenance, set_breakpoint_cmd, _("\
+  add_basic_prefix_cmd ("breakpoint", class_maintenance, _("\
 Breakpoint specific settings.\n\
 Configure various breakpoint-specific variables such as\n\
 pending breakpoint behavior."),
-                 &breakpoint_set_cmdlist, "set breakpoint ",
-                 0/*allow-unknown*/, &setlist);
-  add_prefix_cmd ("breakpoint", class_maintenance, show_breakpoint_cmd, _("\
+                       &breakpoint_set_cmdlist, "set breakpoint ",
+                       0/*allow-unknown*/, &setlist);
+  add_show_prefix_cmd ("breakpoint", class_maintenance, _("\
 Breakpoint specific settings.\n\
 Configure various breakpoint-specific variables such as\n\
 pending breakpoint behavior."),
-                 &breakpoint_show_cmdlist, "show breakpoint ",
-                 0/*allow-unknown*/, &showlist);
+                      &breakpoint_show_cmdlist, "show breakpoint ",
+                      0/*allow-unknown*/, &showlist);
 
   add_setshow_auto_boolean_cmd ("pending", no_class,
                                &pending_break_support, _("\
This page took 0.090048 seconds and 4 git commands to generate.