public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/gdb] gdb-17.2-rebase-f44: - archer-jankratochvil-fedora12 commit:
@ 2026-06-27 23:54 Jan Kratochvil
  0 siblings, 0 replies; 5+ messages in thread
From: Jan Kratochvil @ 2026-06-27 23:54 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/gdb
            Branch : gdb-17.2-rebase-f44
            Commit : 594e04b937607ec98c71e04859eb5255bc0e708d
            Author : Jan Kratochvil <jkratoch@fedoraproject.org>
            Date   : 2009-09-01T13:19:03+00:00
            Stats  : +1380/-374 in 3 file(s)
            URL    : https://src.fedoraproject.org/rpms/gdb/c/594e04b937607ec98c71e04859eb5255bc0e708d?branch=gdb-17.2-rebase-f44

            Log:
            - archer-jankratochvil-fedora12 commit:
    d25596676e8811b03f8c9aba6bbd04ebaa9ff5db
- [call-frame-cfa] Fix parsing CFA-relative frames (BZ 516627, Tom Tromey).
- [vla] variable length Fortran strings for -O -g code (part of BZ 508406,
    me).
- [python] varobj + general fixes (Tom Tromey).

---
diff --git a/gdb-archer.patch b/gdb-archer.patch
index bd472e0..52e6af4 100644
--- a/gdb-archer.patch
+++ b/gdb-archer.patch
@@ -2,7 +2,7 @@ http://sourceware.org/gdb/wiki/ProjectArcher
 http://sourceware.org/gdb/wiki/ArcherBranchManagement
 
 GIT snapshot:
-commit 2ba2bc451eb832182ef84c3934115de7a329da7c
+commit d25596676e8811b03f8c9aba6bbd04ebaa9ff5db
 
 branch `archer' - the merge of branches:
 archer-tromey-call-frame-cfa
@@ -3458,7 +3458,7 @@ index 4984f31..fcf1b5d 100644
  This observer is used for internal testing.  Do not use.  
  See testsuite/gdb.gdb/observer.exp.
 diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
-index 427f58f..fc70309 100644
+index 427f58f..392a1b4 100644
 --- a/gdb/dwarf2-frame.c
 +++ b/gdb/dwarf2-frame.c
 @@ -38,6 +38,7 @@
@@ -3501,7 +3501,7 @@ index 427f58f..fc70309 100644
  
    do_cleanups (old_chain);
  
-@@ -1250,6 +1260,14 @@ dwarf2_frame_base_sniffer (struct frame_info *this_frame)
+@@ -1250,6 +1260,16 @@ dwarf2_frame_base_sniffer (struct frame_info *this_frame)
  
    return NULL;
  }
@@ -3509,6 +3509,8 @@ index 427f58f..fc70309 100644
 +CORE_ADDR
 +dwarf2_frame_cfa (struct frame_info *this_frame)
 +{
++  while (get_frame_type (this_frame) == INLINE_FRAME)
++    this_frame = get_prev_frame (this_frame);
 +  if (! frame_unwinder_is (this_frame, &dwarf2_frame_unwind))
 +    error (_("can't compute CFA for this frame"));
 +  return get_frame_base (this_frame);
@@ -3516,7 +3518,7 @@ index 427f58f..fc70309 100644
  \f
  const struct objfile_data *dwarf2_frame_objfile_data;
  
-@@ -1539,6 +1557,14 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
+@@ -1539,6 +1559,14 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
        CORE_ADDR offset;
        CORE_ADDR seek_pc;
  
@@ -3834,7 +3836,7 @@ index 2306e49..597c2de 100644
    /* The length of the piece, in bytes.  */
    ULONGEST size;
 diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
-index 1df6a9f..c101371 100644
+index 1df6a9f..939f7a2 100644
 --- a/gdb/dwarf2loc.c
 +++ b/gdb/dwarf2loc.c
 @@ -36,6 +36,7 @@
@@ -3875,7 +3877,7 @@ index 1df6a9f..c101371 100644
 +      gdb_assert (symbaton != NULL);
 +      *start = symbaton->data;
 +      *length = symbaton->size;
-+    }
+     }
 +  else if (SYMBOL_COMPUTED_OPS (framefunc) == &dwarf2_missing_funcs)
 +    {
 +      struct dwarf2_locexpr_baton *symbaton;
@@ -3884,7 +3886,7 @@ index 1df6a9f..c101371 100644
 +      gdb_assert (symbaton == NULL);
 +      *start = NULL;
 +      *length = 0;	/* unused */
-     }
++    }
 +  else
 +    internal_error (__FILE__, __LINE__,
 +		    _("Unsupported SYMBOL_COMPUTED_OPS %p for \"%s\""),
@@ -3905,7 +3907,7 @@ index 1df6a9f..c101371 100644
  }
  
  /* Using the objfile specified in BATON, find the address for the
-@@ -204,6 +226,118 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
+@@ -204,6 +226,129 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
    return target_translate_tls_address (debaton->objfile, offset);
  }
  
@@ -4016,6 +4018,17 @@ index 1df6a9f..c101371 100644
 +
 +  retval = dwarf_expr_fetch (ctx, 0);
 +
++  if (ctx->location == DWARF_VALUE_REGISTER)
++    {
++      /* Inlined dwarf_expr_read_reg as we no longer have the baton. */
++
++      int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (ctx->gdbarch, retval);
++      struct type *type = builtin_type (ctx->gdbarch)->builtin_data_ptr;
++      struct frame_info *frame = get_selected_frame (NULL);
++
++      retval = address_from_register (type, gdb_regnum, frame);
++    }
++
 +  do_cleanups (back_to);
 +
 +  return retval;
@@ -4024,7 +4037,7 @@ index 1df6a9f..c101371 100644
  /* Evaluate a location description, starting at DATA and with length
     SIZE, to find the current location of variable VAR in the context
     of FRAME.  */
-@@ -213,9 +347,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
+@@ -213,9 +358,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
  			  struct dwarf2_per_cu_data *per_cu)
  {
    struct value *retval;
@@ -4035,7 +4048,7 @@ index 1df6a9f..c101371 100644
  
    if (size == 0)
      {
-@@ -225,21 +358,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
+@@ -225,21 +369,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
        return retval;
      }
  
@@ -4044,7 +4057,8 @@ index 1df6a9f..c101371 100644
 -
 -  ctx = new_dwarf_expr_context ();
 -  old_chain = make_cleanup_free_dwarf_expr_context (ctx);
--
++  ctx = dwarf_expr_prep_ctx (frame, data, size, per_cu);
+ 
 -  ctx->gdbarch = get_objfile_arch (baton.objfile);
 -  ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
 -  ctx->baton = &baton;
@@ -4052,13 +4066,12 @@ index 1df6a9f..c101371 100644
 -  ctx->read_mem = dwarf_expr_read_mem;
 -  ctx->get_frame_base = dwarf_expr_frame_base;
 -  ctx->get_tls_address = dwarf_expr_tls_address;
-+  ctx = dwarf_expr_prep_ctx (frame, data, size, per_cu);
- 
+-
 -  dwarf_expr_eval (ctx, data, size);
    if (ctx->num_pieces > 0)
      {
        int i;
-@@ -251,36 +371,115 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
+@@ -251,36 +382,115 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
        for (i = 0; i < ctx->num_pieces; i++)
  	{
  	  struct dwarf_expr_piece *p = &ctx->pieces[i];
@@ -4197,7 +4210,7 @@ index 1df6a9f..c101371 100644
      }
  
    set_value_initialized (retval, ctx->initialized);
-@@ -330,6 +529,15 @@ needs_frame_frame_base (void *baton, gdb_byte **start, size_t * length)
+@@ -330,6 +540,15 @@ needs_frame_frame_base (void *baton, gdb_byte **start, size_t * length)
    nf_baton->needs_frame = 1;
  }
  
@@ -4213,7 +4226,7 @@ index 1df6a9f..c101371 100644
  /* Thread-local accesses do require a frame.  */
  static CORE_ADDR
  needs_frame_tls_address (void *baton, CORE_ADDR offset)
-@@ -362,11 +570,12 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
+@@ -362,11 +581,12 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
    ctx->read_reg = needs_frame_read_reg;
    ctx->read_mem = needs_frame_read_mem;
    ctx->get_frame_base = needs_frame_frame_base;
@@ -4227,7 +4240,7 @@ index 1df6a9f..c101371 100644
  
    if (ctx->num_pieces > 0)
      {
-@@ -375,7 +584,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
+@@ -375,7 +595,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
        /* If the location has several pieces, and any of them are in
           registers, then we will need a frame to fetch them from.  */
        for (i = 0; i < ctx->num_pieces; i++)
@@ -4236,7 +4249,7 @@ index 1df6a9f..c101371 100644
            in_reg = 1;
      }
  
-@@ -607,7 +816,7 @@ static int
+@@ -607,7 +827,7 @@ static int
  loclist_describe_location (struct symbol *symbol, struct ui_file *stream)
  {
    /* FIXME: Could print the entire list of locations.  */
@@ -4245,7 +4258,7 @@ index 1df6a9f..c101371 100644
    return 1;
  }
  
-@@ -623,16 +832,56 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
+@@ -623,16 +843,56 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
  
    data = find_location_expression (dlbaton, &size, ax->scope);
    if (data == NULL)
@@ -4322,7 +4335,7 @@ index 0bfcfca..01018d6 100644
  
  #endif /* dwarf2loc.h */
 diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
-index 445bab8..2e0a4bc 100644
+index 445bab8..42039ea 100644
 --- a/gdb/dwarf2read.c
 +++ b/gdb/dwarf2read.c
 @@ -1,8 +1,7 @@
@@ -5862,16 +5875,16 @@ index 445bab8..2e0a4bc 100644
  {
 -  struct die_info *child_die = die->child;
 +  struct type *type;
- 
--  /* FIXME: Support the separate Fortran module namespaces.  */
++
 +  type = read_module_type (die, cu);
- 
++
 +  if (type)
 +    new_symbol (die, type, cu);
 +}
-+
+ 
+-  /* FIXME: Support the separate Fortran module namespaces.  */
 +/* Read a Fortran module as type.
-+
+ 
 +   Modules present only as declarations - being used only for DW_AT_import of
 +   DW_TAG_imported_module - are ignored here.  They are read in only in form of
 +   the module name by read_fortran_imported_module.  */
@@ -6008,7 +6021,7 @@ index 445bab8..2e0a4bc 100644
  }
  
  /* Return the name of the namespace represented by DIE.  Set
-@@ -5705,29 +6159,93 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
+@@ -5705,29 +6159,114 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
    struct gdbarch *gdbarch = get_objfile_arch (objfile);
    struct type *type, *range_type, *index_type, *char_type;
    struct attribute *attr;
@@ -6039,37 +6052,58 @@ index 445bab8..2e0a4bc 100644
 +	 its value.  */
 +      else
 +	{
-+	  struct dwarf2_locexpr_baton *length_baton;
-+	  struct attribute *size_attr;
-+
-+	  length_baton = obstack_alloc (&cu->comp_unit_obstack,
-+					sizeof (*length_baton));
-+	  length_baton->per_cu = cu->per_cu;
-+	  length_baton->data = obstack_alloc (&cu->comp_unit_obstack,
-+					      DW_BLOCK (attr)->size + 2);
-+	  memcpy (length_baton->data, DW_BLOCK (attr)->data,
-+		  DW_BLOCK (attr)->size);
-+
-+	  /* DW_AT_BYTE_SIZE existing together with DW_AT_STRING_LENGTH
-+	     specifies the size of an integer to fetch.  */
-+
-+	  size_attr = dwarf2_attr (die, DW_AT_byte_size, cu);
-+	  if (size_attr)
++	  struct dwarf2_locexpr_baton *length_baton = NULL;
++	  struct dwarf_block *blk = DW_BLOCK (attr);
++
++	  /* Turn any single DW_OP_reg* into DW_OP_breg*(0) but clearing
++	     DW_OP_deref* in such case.  */
++
++	  if (blk->size == 1 && blk->data[0] >= DW_OP_reg0
++	      && blk->data[0] <= DW_OP_reg31)
++	    length_baton = dwarf2_attr_to_locexpr_baton (attr, cu);
++	  else if (blk->size > 1 && blk->data[0] == DW_OP_regx)
 +	    {
-+	      length_baton->size = DW_BLOCK (attr)->size + 2;
-+	      length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref_size;
-+	      length_baton->data[DW_BLOCK (attr)->size + 1]
-+							 = DW_UNSND (size_attr);
-+	      if (length_baton->data[DW_BLOCK (attr)->size + 1]
-+		  != DW_UNSND (size_attr))
-+		complaint (&symfile_complaints,
-+			   _("DW_AT_string_length's DW_AT_byte_size integer "
-+			     "exceeds the byte size storage"));
++	      ULONGEST ulongest;
++	      gdb_byte *end;
++
++	      end = read_uleb128 (&blk->data[1], &blk->data[blk->size],
++				  &ulongest);
++	      if (end == &blk->data[blk->size])
++		length_baton = dwarf2_attr_to_locexpr_baton (attr, cu);
 +	    }
-+	  else
++
++	  if (length_baton == NULL)
 +	    {
-+	      length_baton->size = DW_BLOCK (attr)->size + 1;
-+	      length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref;
++	      struct attribute *size_attr;
++
++	      length_baton = obstack_alloc (&cu->comp_unit_obstack,
++					    sizeof (*length_baton));
++	      length_baton->per_cu = cu->per_cu;
++	      length_baton->size = DW_BLOCK (attr)->size + 2;
++	      length_baton->data = obstack_alloc (&cu->comp_unit_obstack,
++						  length_baton->size);
++	      memcpy (length_baton->data, DW_BLOCK (attr)->data,
++		      DW_BLOCK (attr)->size);
++
++	      /* DW_AT_BYTE_SIZE existing together with DW_AT_STRING_LENGTH
++		 specifies the size of an integer to fetch.  */
++	      size_attr = dwarf2_attr (die, DW_AT_byte_size, cu);
++	      if (size_attr)
++		{
++		  length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref_size;
++		  length_baton->data[DW_BLOCK (attr)->size + 1] =
++							   DW_UNSND (size_attr);
++		  if (length_baton->data[DW_BLOCK (attr)->size + 1]
++		      != DW_UNSND (size_attr))
++		    complaint (&symfile_complaints,
++			       _("DW_AT_string_length's DW_AT_byte_size "
++				 "integer exceeds the byte size storage"));
++		}
++	      else
++		{
++		  length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref;
++		  length_baton->data[DW_BLOCK (attr)->size + 1] = DW_OP_nop;
++		}
 +	    }
 +
 +	  TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 1);
@@ -6116,7 +6150,7 @@ index 445bab8..2e0a4bc 100644
    char_type = language_string_char_type (cu->language_defn, gdbarch);
    type = create_string_type (NULL, char_type, range_type);
  
-@@ -5822,7 +6340,6 @@ static struct type *
+@@ -5822,7 +6361,6 @@ static struct type *
  read_typedef (struct die_info *die, struct dwarf2_cu *cu)
  {
    struct objfile *objfile = cu->objfile;
@@ -6124,7 +6158,7 @@ index 445bab8..2e0a4bc 100644
    const char *name = NULL;
    struct type *this_type;
  
-@@ -5930,8 +6447,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
+@@ -5930,8 +6468,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
    struct type *base_type;
    struct type *range_type;
    struct attribute *attr;
@@ -6134,7 +6168,7 @@ index 445bab8..2e0a4bc 100644
    char *name;
    
    base_type = die_type (die, cu);
-@@ -5944,42 +6460,91 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
+@@ -5944,42 +6481,91 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
  		     0, NULL, cu->objfile);
      }
  
@@ -6255,7 +6289,7 @@ index 445bab8..2e0a4bc 100644
  
    name = dwarf2_name (die, cu);
    if (name)
-@@ -6450,6 +7015,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
+@@ -6450,6 +7036,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
  	  && abbrev->tag != DW_TAG_lexical_block
  	  && abbrev->tag != DW_TAG_variable
  	  && abbrev->tag != DW_TAG_namespace
@@ -6263,7 +6297,7 @@ index 445bab8..2e0a4bc 100644
  	  && abbrev->tag != DW_TAG_member)
  	{
  	  /* Otherwise we skip to the next sibling, if any.  */
-@@ -6670,9 +7236,6 @@ read_partial_die (struct partial_die_info *part_die,
+@@ -6670,9 +7257,6 @@ read_partial_die (struct partial_die_info *part_die,
  	  if (part_die->dirname == NULL)
  	    part_die->dirname = DW_STRING (&attr);
  	  break;
@@ -6273,7 +6307,7 @@ index 445bab8..2e0a4bc 100644
  	case DW_AT_low_pc:
  	  has_low_pc_attr = 1;
  	  part_die->lowpc = DW_ADDR (&attr);
-@@ -6744,10 +7307,10 @@ read_partial_die (struct partial_die_info *part_die,
+@@ -6744,10 +7328,10 @@ read_partial_die (struct partial_die_info *part_die,
  	  else
  	    part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr);
  	  break;
@@ -6288,7 +6322,7 @@ index 445bab8..2e0a4bc 100644
          case DW_AT_byte_size:
            part_die->has_byte_size = 1;
            break;
-@@ -6789,13 +7352,6 @@ read_partial_die (struct partial_die_info *part_die,
+@@ -6789,13 +7373,6 @@ read_partial_die (struct partial_die_info *part_die,
  	  || dwarf2_per_objfile->has_section_at_zero))
      part_die->has_pc_info = 1;
  
@@ -6302,7 +6336,7 @@ index 445bab8..2e0a4bc 100644
    return info_ptr;
  }
  
-@@ -6904,7 +7460,8 @@ fixup_partial_die (struct partial_die_info *part_die,
+@@ -6904,7 +7481,8 @@ fixup_partial_die (struct partial_die_info *part_die,
    /* If we found a reference attribute and the DIE has no name, try
       to find a name in the referred to DIE.  */
  
@@ -6312,7 +6346,7 @@ index 445bab8..2e0a4bc 100644
      {
        struct partial_die_info *spec_die;
  
-@@ -8244,10 +8801,12 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
+@@ -8244,10 +8822,12 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
       (i.e. when the value of a register or memory location is
       referenced, or a thread-local block, etc.).  Then again, it might
       not be worthwhile.  I'm assuming that it isn't unless performance
@@ -6327,7 +6361,7 @@ index 445bab8..2e0a4bc 100644
  }
  
  /* Given a pointer to a DWARF information entry, figure out if we need
-@@ -8269,21 +8828,30 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
+@@ -8269,21 +8849,30 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
  
    baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
  
@@ -6365,7 +6399,7 @@ index 445bab8..2e0a4bc 100644
  
        /* Default assumptions.
           Use the passed type or decode it from the die.  */
-@@ -8381,9 +8949,28 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
+@@ -8381,9 +8970,28 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
  	  if (attr)
  	    {
  	      var_decode_location (attr, sym, cu);
@@ -6395,7 +6429,7 @@ index 445bab8..2e0a4bc 100644
  	      else
  		add_symbol_to_list (sym, cu->list_in_scope);
  	    }
-@@ -8513,7 +9100,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
+@@ -8513,7 +9121,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
  	  add_symbol_to_list (sym, cu->list_in_scope);
  	  break;
  	case DW_TAG_enumerator:
@@ -6404,7 +6438,7 @@ index 445bab8..2e0a4bc 100644
  	  attr = dwarf2_attr (die, DW_AT_const_value, cu);
  	  if (attr)
  	    {
-@@ -8537,6 +9124,16 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
+@@ -8537,6 +9145,16 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
  	  SYMBOL_CLASS (sym) = LOC_TYPEDEF;
  	  add_symbol_to_list (sym, &global_symbols);
  	  break;
@@ -6421,7 +6455,7 @@ index 445bab8..2e0a4bc 100644
  	default:
  	  /* Not a tag we recognize.  Hopefully we aren't processing
  	     trash data, but since we must specifically ignore things
-@@ -8550,8 +9147,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
+@@ -8550,8 +9168,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
        /* For the benefit of old versions of GCC, check for anonymous
  	 namespaces based on the demangled name.  */
        if (!processing_has_namespace_info
@@ -6431,7 +6465,7 @@ index 445bab8..2e0a4bc 100644
  	cp_scan_for_anonymous_namespaces (sym);
      }
    return (sym);
-@@ -8802,12 +9398,18 @@ read_type_die (struct die_info *die, struct dwarf2_cu *cu)
+@@ -8802,12 +9419,18 @@ read_type_die (struct die_info *die, struct dwarf2_cu *cu)
      case DW_TAG_namespace:
        this_type = read_namespace_type (die, cu);
        break;
@@ -6450,7 +6484,7 @@ index 445bab8..2e0a4bc 100644
    return this_type;
  }
  
-@@ -8889,10 +9491,97 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
+@@ -8889,10 +9512,97 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
  	     So it does not need a prefix.  */
  	  return "";
        default:
@@ -6549,7 +6583,7 @@ index 445bab8..2e0a4bc 100644
  /* Return a newly-allocated string formed by concatenating PREFIX and
     SUFFIX with appropriate separator.  If PREFIX or SUFFIX is NULL or empty, then
     simply copy the SUFFIX or PREFIX, respectively.  If OBS is non-null,
-@@ -8948,14 +9637,108 @@ static char *
+@@ -8948,14 +9658,108 @@ static char *
  dwarf2_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
  {
    struct attribute *attr;
@@ -6561,11 +6595,7 @@ index 445bab8..2e0a4bc 100644
 +  if (cu->language != language_cplus
 +      && cu->language != language_java)
 +    return name;
- 
--  attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
--  if (attr && DW_STRING (attr))
--    return DW_STRING (attr);
--  return dwarf2_name (die, cu);
++
 +  if (die_needs_namespace (die, cu))
 +    {
 +      long length;
@@ -6589,7 +6619,11 @@ index 445bab8..2e0a4bc 100644
 +	  && die->tag == DW_TAG_subprogram)
 +	{
 +	  struct type *type = read_type_die (die, cu);
-+
+ 
+-  attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
+-  if (attr && DW_STRING (attr))
+-    return DW_STRING (attr);
+-  return dwarf2_name (die, cu);
 +	  c_type_print_args (type, buf, 0, cu->language);
 +
 +	  if (cu->language == language_java)
@@ -6663,7 +6697,7 @@ index 445bab8..2e0a4bc 100644
  
  static char *
  dwarf2_canonicalize_name (char *name, struct dwarf2_cu *cu,
-@@ -10181,11 +10964,12 @@ dwarf2_get_ref_die_offset (struct attribute *attr)
+@@ -10181,11 +10985,12 @@ dwarf2_get_ref_die_offset (struct attribute *attr)
    return 0;
  }
  
@@ -6679,7 +6713,7 @@ index 445bab8..2e0a4bc 100644
  {
    if (attr->form == DW_FORM_sdata)
      return DW_SND (attr);
-@@ -10195,6 +10979,8 @@ dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
+@@ -10195,6 +11000,8 @@ dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
             || attr->form == DW_FORM_data4
             || attr->form == DW_FORM_data8)
      return DW_UNSND (attr);
@@ -6688,7 +6722,7 @@ index 445bab8..2e0a4bc 100644
    else
      {
        complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"),
-@@ -10990,8 +11776,6 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
+@@ -10990,8 +11797,6 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
  {
    gdb_byte *mac_ptr, *mac_end;
    struct macro_source_file *current_file = 0;
@@ -6697,7 +6731,7 @@ index 445bab8..2e0a4bc 100644
  
    if (dwarf2_per_objfile->macinfo.buffer == NULL)
      {
-@@ -10999,29 +11783,19 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
+@@ -10999,29 +11804,19 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
        return;
      }
  
@@ -6732,7 +6766,7 @@ index 445bab8..2e0a4bc 100644
          }
  
        macinfo_type = read_1_byte (abfd, mac_ptr);
-@@ -11032,92 +11806,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
+@@ -11032,92 +11827,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
            /* A zero macinfo type indicates the end of the macro
               information.  */
          case 0:
@@ -6826,7 +6860,7 @@ index 445bab8..2e0a4bc 100644
  
          case DW_MACINFO_define:
          case DW_MACINFO_undef:
-@@ -11132,31 +11821,19 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
+@@ -11132,31 +11842,19 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
              mac_ptr += bytes_read;
  
              if (! current_file)
@@ -6869,7 +6903,7 @@ index 445bab8..2e0a4bc 100644
            }
            break;
  
-@@ -11170,22 +11847,9 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
+@@ -11170,22 +11868,9 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
              file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
              mac_ptr += bytes_read;
  
@@ -6895,7 +6929,7 @@ index 445bab8..2e0a4bc 100644
            }
            break;
  
-@@ -11239,7 +11903,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
+@@ -11239,7 +11924,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
            }
            break;
          }
@@ -6904,7 +6938,7 @@ index 445bab8..2e0a4bc 100644
  }
  
  /* Check if the attribute's form is a DW_FORM_block*
-@@ -11299,6 +11963,34 @@ attr_form_is_constant (struct attribute *attr)
+@@ -11299,6 +11984,34 @@ attr_form_is_constant (struct attribute *attr)
      }
  }
  
@@ -6939,7 +6973,7 @@ index 445bab8..2e0a4bc 100644
  static void
  dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
  			     struct dwarf2_cu *cu)
-@@ -11328,35 +12020,25 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+@@ -11328,35 +12041,25 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
        SYMBOL_COMPUTED_OPS (sym) = &dwarf2_loclist_funcs;
        SYMBOL_LOCATION_BATON (sym) = baton;
      }
@@ -6990,7 +7024,7 @@ index 445bab8..2e0a4bc 100644
      }
  }
  
-@@ -11644,6 +12326,31 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs)
+@@ -11644,6 +12347,31 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs)
    return ofs_lhs->offset == ofs_rhs->offset;
  }
  
@@ -7022,7 +7056,7 @@ index 445bab8..2e0a4bc 100644
  /* Set the type associated with DIE to TYPE.  Save it in CU's hash
     table if necessary.  For convenience, return TYPE.  */
  
-@@ -11652,6 +12359,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
+@@ -11652,6 +12380,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
  {
    struct dwarf2_offset_and_type **slot, ofs;
  
@@ -7031,7 +7065,7 @@ index 445bab8..2e0a4bc 100644
    if (cu->type_hash == NULL)
      {
        gdb_assert (cu->per_cu != NULL);
-@@ -11794,23 +12503,13 @@ show_dwarf2_cmd (char *args, int from_tty)
+@@ -11794,23 +12524,13 @@ show_dwarf2_cmd (char *args, int from_tty)
    cmd_show_list (show_dwarf2_cmdlist, from_tty, "");
  }
  
@@ -7059,7 +7093,7 @@ index 445bab8..2e0a4bc 100644
  }
  
  /* munmap debug sections for OBJFILE, if necessary.  */
-@@ -11819,15 +12518,15 @@ static void
+@@ -11819,15 +12539,15 @@ static void
  dwarf2_per_objfile_cleanup (struct objfile *objfile, void *d)
  {
    struct dwarf2_per_objfile *data = d;
@@ -7084,7 +7118,7 @@ index 445bab8..2e0a4bc 100644
  }
  
  void _initialize_dwarf2_read (void);
-@@ -11835,6 +12534,7 @@ void _initialize_dwarf2_read (void);
+@@ -11835,6 +12555,7 @@ void _initialize_dwarf2_read (void);
  void
  _initialize_dwarf2_read (void)
  {
@@ -11319,7 +11353,7 @@ index aac82e9..626292c 100644
    TYPE_CPLUS_SPECIFIC (t) = (struct cplus_struct_type *) &cplus_struct_default;
    return t;
 diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c
-index 0cf03d9..d6a85d9 100644
+index 0cf03d9..e4ca621 100644
 --- a/gdb/mi/mi-cmd-var.c
 +++ b/gdb/mi/mi-cmd-var.c
 @@ -41,7 +41,7 @@ static void varobj_update_one (struct varobj *var,
@@ -11346,7 +11380,16 @@ index 0cf03d9..d6a85d9 100644
  
    type = varobj_get_type (var);
    if (type != NULL)
-@@ -223,6 +227,7 @@ mi_cmd_var_set_format (char *command, char **argv, int argc)
+@@ -138,6 +142,8 @@ mi_cmd_var_create (char *command, char **argv, int argc)
+ 
+   print_varobj (var, PRINT_ALL_VALUES, 0 /* don't print expression */);
+ 
++  ui_out_field_int (uiout, "has_more", varobj_has_more (var, 0));
++
+   do_cleanups (old_cleanups);
+ }
+ 
+@@ -223,6 +229,7 @@ mi_cmd_var_set_format (char *command, char **argv, int argc)
  {
    enum varobj_display_formats format;
    struct varobj *var;
@@ -11354,7 +11397,7 @@ index 0cf03d9..d6a85d9 100644
  
    if (argc != 2)
      error (_("mi_cmd_var_set_format: Usage: NAME FORMAT."));
-@@ -239,7 +244,9 @@ mi_cmd_var_set_format (char *command, char **argv, int argc)
+@@ -239,7 +246,9 @@ mi_cmd_var_set_format (char *command, char **argv, int argc)
    ui_out_field_string (uiout, "format", varobj_format_string[(int) format]);
   
    /* Report the value in the new format */
@@ -11365,7 +11408,7 @@ index 0cf03d9..d6a85d9 100644
  }
  
  void
-@@ -337,11 +344,12 @@ Must be: 0 or \"%s\", 1 or \"%s\", 2 or \"%s\""),
+@@ -337,11 +346,12 @@ Must be: 0 or \"%s\", 1 or \"%s\", 2 or \"%s\""),
  }
  
  /* Return 1 if given the argument PRINT_VALUES we should display
@@ -11380,7 +11423,7 @@ index 0cf03d9..d6a85d9 100644
  
    if (print_values == PRINT_NO_VALUES)
      return 0;
-@@ -349,6 +357,10 @@ mi_print_value_p (struct type *type, enum print_values print_values)
+@@ -349,6 +359,10 @@ mi_print_value_p (struct type *type, enum print_values print_values)
    if (print_values == PRINT_ALL_VALUES)
      return 1;
  
@@ -11391,7 +11434,7 @@ index 0cf03d9..d6a85d9 100644
    if (type == NULL)
      return 1;
    else
-@@ -369,24 +381,35 @@ mi_cmd_var_list_children (char *command, char **argv, int argc)
+@@ -369,24 +383,35 @@ mi_cmd_var_list_children (char *command, char **argv, int argc)
    struct varobj *var;  
    VEC(varobj_p) *children;
    struct varobj *child;
@@ -11415,6 +11458,8 @@ index 0cf03d9..d6a85d9 100644
      var = varobj_get_handle (argv[1]);
  
 -  children = varobj_list_children (var);
+-  ui_out_field_int (uiout, "numchild", VEC_length (varobj_p, children));
+-  if (argc == 2)
 +  if (argc > 2)
 +    {
 +      from = atoi (argv[argc - 2]);
@@ -11427,13 +11472,12 @@ index 0cf03d9..d6a85d9 100644
 +    }
 +
 +  children = varobj_list_children (var, &from, &to);
-   ui_out_field_int (uiout, "numchild", VEC_length (varobj_p, children));
--  if (argc == 2)
++  ui_out_field_int (uiout, "numchild", to - from);
 +  if (argc == 2 || argc == 4)
      print_values = mi_parse_values_option (argv[0]);
    else
      print_values = PRINT_NO_VALUES;
-@@ -398,21 +421,28 @@ mi_cmd_var_list_children (char *command, char **argv, int argc)
+@@ -398,21 +423,28 @@ mi_cmd_var_list_children (char *command, char **argv, int argc)
        xfree (display_hint);
      }
  
@@ -11475,7 +11519,7 @@ index 0cf03d9..d6a85d9 100644
  }
  
  void
-@@ -538,16 +568,24 @@ mi_cmd_var_evaluate_expression (char *command, char **argv, int argc)
+@@ -538,16 +570,24 @@ mi_cmd_var_evaluate_expression (char *command, char **argv, int argc)
    var = varobj_get_handle (argv[optind]);
     
    if (formatFound)
@@ -11503,7 +11547,7 @@ index 0cf03d9..d6a85d9 100644
  
    if (argc != 2)
      error (_("mi_cmd_var_assign: Usage: NAME EXPRESSION."));
-@@ -563,7 +601,9 @@ mi_cmd_var_assign (char *command, char **argv, int argc)
+@@ -563,7 +603,9 @@ mi_cmd_var_assign (char *command, char **argv, int argc)
    if (!varobj_set_value (var, expression))
      error (_("mi_cmd_var_assign: Could not assign expression to variable object"));
  
@@ -11514,7 +11558,7 @@ index 0cf03d9..d6a85d9 100644
  }
  
  /* Type used for parameters passing to mi_cmd_var_update_iter.  */
-@@ -644,7 +684,6 @@ mi_cmd_var_update (char *command, char **argv, int argc)
+@@ -644,7 +686,6 @@ mi_cmd_var_update (char *command, char **argv, int argc)
      }
    else
      {
@@ -11522,7 +11566,15 @@ index 0cf03d9..d6a85d9 100644
        struct varobj *var = varobj_get_handle (name);
  
        varobj_update_one (var, print_values, 1 /* explicit */);
-@@ -678,8 +717,12 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
+@@ -670,6 +711,7 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
+   for (i = 0; VEC_iterate (varobj_update_result, changes, i, r); ++i)
+     {
+       char *display_hint;
++      int from, to;
+ 
+       if (mi_version (uiout) > 1)
+         cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+@@ -678,8 +720,12 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
        switch (r->status)
  	{
  	case VAROBJ_IN_SCOPE:
@@ -11537,7 +11589,7 @@ index 0cf03d9..d6a85d9 100644
  	  ui_out_field_string (uiout, "in_scope", "true");
  	  break;
          case VAROBJ_NOT_IN_SCOPE:
-@@ -699,11 +742,11 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
+@@ -699,11 +745,11 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
  	}
  
        if (r->type_changed)
@@ -11554,19 +11606,19 @@ index 0cf03d9..d6a85d9 100644
  
        display_hint = varobj_get_display_hint (var);
        if (display_hint)
-@@ -714,26 +757,58 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
+@@ -712,28 +758,56 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
+ 	  xfree (display_hint);
+ 	}
  
-       if (r->children_changed)
- 	{
+-      if (r->children_changed)
+-	{
 -	  int ix;
 -	  struct varobj *child;
 -	  struct cleanup *cleanup =
 -	    make_cleanup_ui_out_list_begin_end (uiout, "children");
-+	  int from, to;
-+	  varobj_get_child_range (r->varobj, &from, &to);
-+	  ui_out_field_int (uiout, "has_more",
-+			    varobj_has_more (r->varobj, to));
-+	}
++      varobj_get_child_range (r->varobj, &from, &to);
++      ui_out_field_int (uiout, "has_more",
++			varobj_has_more (r->varobj, to));
  
 -	  VEC (varobj_p)* children = varobj_list_children (r->varobj);
 +      if (r->new)
@@ -17702,7 +17754,7 @@ index 49c0437..84a476e 100644
 +  return 1;
 +}
 diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
-index c4217d5..f1da660 100644
+index c4217d5..b993515 100644
 --- a/gdb/python/python-value.c
 +++ b/gdb/python/python-value.c
 @@ -25,6 +25,7 @@
@@ -17724,7 +17776,37 @@ index c4217d5..f1da660 100644
  #define builtin_type_pybool \
    language_bool_type (python_language, python_gdbarch)
  
-@@ -883,7 +888,34 @@ convert_value_from_python (PyObject *obj)
+@@ -693,7 +698,10 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
+     {
+       value_other = convert_value_from_python (other);
+       if (value_other == NULL)
+-	return NULL;
++	{
++	  result = -1;
++	  break;
++	}
+ 
+       switch (op) {
+         case Py_LT:
+@@ -720,11 +728,16 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
+ 	  /* Can't happen.  */
+ 	  PyErr_SetString (PyExc_NotImplementedError,
+ 			   "Invalid operation on gdb.Value.");
+-	  return NULL;
++	  result = -1;
++	  break;
+       }
+     }
+   GDB_PY_HANDLE_EXCEPTION (except);
+ 
++  /* In this case, the Python exception has already been set.  */
++  if (result < 0)
++    return NULL;
++
+   if (result == 1)
+     Py_RETURN_TRUE;
+ 
+@@ -883,7 +896,34 @@ convert_value_from_python (PyObject *obj)
  	{
  	  LONGEST l = PyLong_AsLongLong (obj);
  
@@ -17760,7 +17842,7 @@ index c4217d5..f1da660 100644
  	    value = value_from_longest (builtin_type_pylong, l);
  	}
        else if (PyFloat_Check (obj))
-@@ -942,6 +974,25 @@ gdbpy_history (PyObject *self, PyObject *args)
+@@ -942,6 +982,25 @@ gdbpy_history (PyObject *self, PyObject *args)
    return value_to_value_object (res_val);
  }
  
@@ -17786,7 +17868,7 @@ index c4217d5..f1da660 100644
  void
  gdbpy_initialize_values (void)
  {
-@@ -952,6 +1003,8 @@ gdbpy_initialize_values (void)
+@@ -952,6 +1011,8 @@ gdbpy_initialize_values (void)
    PyModule_AddObject (gdb_module, "Value", (PyObject *) &value_object_type);
  
    values_in_python = NULL;
@@ -20806,6 +20888,215 @@ index 750fd23..dfdb929 100644
  gdb_test "set input-radix 1" \
      "Nonsense input radix ``decimal 1''; input radix unchanged\\." \
      "Reject input-radix 1"
+diff --git a/gdb/testsuite/gdb.base/solib-overlap-lib.c b/gdb/testsuite/gdb.base/solib-overlap-lib.c
+new file mode 100644
+index 0000000..d4aec0d
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/solib-overlap-lib.c
+@@ -0,0 +1,27 @@
++/* Copyright 2009 Free Software Foundation, Inc.
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++   Contributed by Jan Kratochvil <jan.kratochvil@redhat.com>.  */
++
++void
++libsym (void)
++{
++}
++
++#ifdef SYMB
++void
++libsymb (void)
++{
++}
++#endif
+diff --git a/gdb/testsuite/gdb.base/solib-overlap-main.c b/gdb/testsuite/gdb.base/solib-overlap-main.c
+new file mode 100644
+index 0000000..1e91dd2
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/solib-overlap-main.c
+@@ -0,0 +1,25 @@
++/* Copyright 2009 Free Software Foundation, Inc.
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++   Contributed by Jan Kratochvil <jan.kratochvil@redhat.com>.  */
++
++#include <unistd.h>
++
++int
++main (void)
++{
++  sleep (60);
++
++  return 1;
++}
+diff --git a/gdb/testsuite/gdb.base/solib-overlap.exp b/gdb/testsuite/gdb.base/solib-overlap.exp
+new file mode 100644
+index 0000000..d644d9b
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/solib-overlap.exp
+@@ -0,0 +1,139 @@
++# Copyright 2009 Free Software Foundation, Inc.
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++#
++# Contributed by Jan Kratochvil <jan.kratochvil@redhat.com>.
++
++# Test GDB can cope with two libraries loaded with overlapping VMA ranges.
++# Prelink libraries first so they can be loaded and their native address.
++# In such case `struct linkmap'.l_addr will be zero.  Provide different
++# unprelinked library files on the disk which have zero-based VMAs.  These
++# different files should have their .dynamic section at a different offset in
++# page size so that we get for
++#   warning: .dynamic section for "..." is not at the expected address
++# the reason
++#   (wrong library or version mismatch?)
++# and not:
++#   difference appears to be caused by prelink, adjusting expectations
++# In such case both disk libraries will be loaded at VMAs starting at zero.
++
++if [skip_shlib_tests] {
++    return 0
++}
++
++# Are we on a target board?  It is required for attaching to a process.
++if [is_remote target] {
++    return 0
++}
++
++if [get_compiler_info binfile-unused] {
++    return -1;
++}
++
++# Library file.
++set libname "solib-overlap-lib"
++set srcfile_lib ${srcdir}/${subdir}/${libname}.c
++# Binary file.
++set testfile "solib-overlap-main"
++set srcfile ${srcdir}/${subdir}/${testfile}.c
++
++# Base addresses for `prelink -r' which should be compatible with both -m32 and
++# -m64 targets.  If it clashes with system prelinked libraries it would give
++# false PASS.
++# Prelink first lib1 at 0x40000000 and lib2 at 0x41000000.
++# During second pass try lib1 at 0x50000000 and lib2 at 0x51000000.
++foreach prelink_lib1 {0x40000000 0x50000000} {
++    set prelink_lib2 [format "0x%x" [expr $prelink_lib1 + 0x01000000]]
++
++    set old_prefix $pf_prefix
++    lappend pf_prefix "$prelink_lib1:"
++
++    # Library file.
++    set binfile_lib1 ${objdir}/${subdir}/${libname}1-${prelink_lib1}.so
++    set binfile_lib2 ${objdir}/${subdir}/${libname}2-${prelink_lib1}.so
++    set lib_flags {debug}
++    # Binary file.
++    set binfile_base ${testfile}-${prelink_lib1}
++    set binfile ${objdir}/${subdir}/${binfile_base}
++    set bin_flags [list debug shlib=${binfile_lib1} shlib=${binfile_lib2}]
++    set escapedbinfile  [string_to_regexp ${binfile}]
++
++    if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib1} $lib_flags] != ""
++	 || [gdb_compile_shlib ${srcfile_lib} ${binfile_lib2} $lib_flags] != ""
++	 || [gdb_compile ${srcfile} ${binfile} executable $bin_flags] != "" } {
++	untested "Could not compile ${binfile_lib1}, ${binfile_lib2} or ${binfile}."
++	return -1
++    }
++
++    if {[catch "system \"prelink -N -r ${prelink_lib1} ${binfile_lib1}\""] != 0
++	|| [catch "system \"prelink -N -r ${prelink_lib2} ${binfile_lib2}\""] != 0} {
++	# Maybe we don't have prelink.
++	untested "Could not prelink ${binfile_lib1} or ${binfile_lib2}."
++	return -1
++    }
++
++    # Start the program running and then wait for a bit, to be sure
++    # that it can be attached to.
++
++    set testpid [eval exec $binfile &]
++    sleep 2
++    if { [istarget "*-*-cygwin*"] } {
++	# testpid is the Cygwin PID, GDB uses the Windows PID, which might be
++	# different due to the way fork/exec works.
++	set testpid [ exec ps -e | gawk "{ if (\$1 == $testpid) print \$4; }" ]
++    }
++
++    remote_exec build "mv -f ${binfile_lib1} ${binfile_lib1}-running"
++    remote_exec build "mv -f ${binfile_lib2} ${binfile_lib2}-running"
++
++    # Provide another exported function name to cause different sizes of sections.
++    lappend lib_flags additional_flags=-DSYMB
++
++    if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib1} $lib_flags] != ""
++	 || [gdb_compile_shlib ${srcfile_lib} ${binfile_lib2} $lib_flags] != ""} {
++	untested "Could not recompile ${binfile_lib1} or ${binfile_lib2}."
++	remote_exec build "kill -9 ${testpid}"
++	return -1
++    }
++
++    clean_restart ${binfile_base}
++    # This testcase currently does not support remote targets.
++    # gdb_load_shlibs ${binfile_lib1} ${binfile_lib2}
++
++    # Here we should get:
++    # warning: .dynamic section for ".../solib-overlap-lib1.so" is not at the expected address (wrong library or version mismatch?)
++    # warning: .dynamic section for ".../solib-overlap-lib2.so" is not at the expected address (wrong library or version mismatch?)
++
++    set test attach
++    gdb_test_multiple "attach $testpid" $test {
++	-re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" {
++	    pass $test
++	}
++	-re "Attaching to program.*`?$escapedbinfile\.exe'?, process $testpid.*\[Switching to thread $testpid\..*\].*$gdb_prompt $" {
++	    # Response expected on Cygwin
++	    pass $test
++	}
++    }
++
++    # Detach the process.
++
++    gdb_test "detach" "Detaching from program: .*$escapedbinfile, process $testpid"
++
++    # Wait a bit for gdb to finish detaching
++
++    sleep 5
++
++    remote_exec build "kill -9 ${testpid}"
++
++    set pf_prefix $old_prefix
++}
 diff --git a/gdb/testsuite/gdb.base/valgrind-attach.c b/gdb/testsuite/gdb.base/valgrind-attach.c
 new file mode 100644
 index 0000000..84b57db
@@ -24670,6 +24961,345 @@ index d4acdc2..244c731 100644
      "list children of fooPtr.$i"
  }
  
+diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp
+index 619727d..8d06c0e 100644
+--- a/gdb/testsuite/gdb.mi/mi-break.exp
++++ b/gdb/testsuite/gdb.mi/mi-break.exp
+@@ -175,7 +175,7 @@ proc test_error {} {
+     # containing function call, the internal breakpoint created to handle
+     # function call would be reported, messing up MI output.
+     mi_gdb_test "-var-create V * return_1()" \
+-        "\\^done,name=\"V\",numchild=\"0\",value=\"1\",type=\"int\"" \
++        "\\^done,name=\"V\",numchild=\"0\",value=\"1\",type=\"int\",has_more=\"0\"" \
+         "create varobj for function call"
+ 
+     mi_gdb_test "-var-update *" \
+diff --git a/gdb/testsuite/gdb.mi/mi-var-block.exp b/gdb/testsuite/gdb.mi/mi-var-block.exp
+index 8806848..93ded26 100644
+--- a/gdb/testsuite/gdb.mi/mi-var-block.exp
++++ b/gdb/testsuite/gdb.mi/mi-var-block.exp
+@@ -74,7 +74,7 @@ mi_step_to "do_block_tests" "" "var-cmd.c" \
+ # Test: c_variable-3.4
+ # Desc: check foo, cb changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: cb foo changed"
+ 
+ # step to "foo = 321;"
+diff --git a/gdb/testsuite/gdb.mi/mi-var-child.exp b/gdb/testsuite/gdb.mi/mi-var-child.exp
+index 1f4bdc6..eb6c456 100644
+--- a/gdb/testsuite/gdb.mi/mi-var-child.exp
++++ b/gdb/testsuite/gdb.mi/mi-var-child.exp
+@@ -680,7 +680,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.2
+ # Desc: check that integer changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.integer"
+ 
+ # Step over:
+@@ -693,7 +693,7 @@ mi_execute_to "exec-step 3" "end-stepping-range" do_children_tests {} ".*${srcfi
+ # Test: c_variable-5.3
+ # Desc: check that char_ptr changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.char_ptr"
+ 
+ # Step over "struct_declarations.int_ptr_ptr = &foo;"
+@@ -703,7 +703,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.4
+ # Desc: check that int_ptr_ptr and children changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars int_ptr_ptr and children changed"
+ 
+ # Step over "weird->long_array[0] = 1234;"
+@@ -713,7 +713,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.5
+ # Desc: check that long_array[0] changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.long_array.0 changed"
+ 
+ # Step over "struct_declarations.long_array[1] = 2345;"
+@@ -723,7 +723,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.6
+ # Desc: check that long_array[1] changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.long_array.1 changed"
+ 
+ # Step over "weird->long_array[2] = 3456;"
+@@ -733,7 +733,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.7
+ # Desc: check that long_array[2] changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.long_array.2 changed"
+ 
+ # Step over:
+@@ -752,7 +752,7 @@ mi_execute_to "exec-step 7" "end-stepping-range" do_children_tests {} ".*${srcfi
+ # Test: c_variable-5.8
+ # Desc: check that long_array[3-9] changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.long_array.3-9 changed"
+ 
+ 
+@@ -763,7 +763,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.9
+ # Desc: check that func_ptr changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.func_ptr changed"
+ 
+ # Step over "struct_declarations.long_array[10] = 3456";
+@@ -771,7 +771,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+     [expr $line_dct_nothing + 2] "step \$line_dct_nothing + 2"
+ 
+ mi_gdb_test "-var-update --no-values *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.10\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.10\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+  "update all vars struct_declarations.long_array.10 changed, don't print values."
+ 
+ # Step over "struct_declarations.long_array[11] = 5678";
+@@ -780,7 +780,7 @@ mi_step_to  do_children_tests {} ".*${srcfile}" \
+     $line_dct_a0_0 "step \$line_dct_a0_0"
+ 
+ mi_gdb_test "-var-update --all-values *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.11\",value=\"5678\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.11\",value=\"5678\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+  "update all vars struct_declarations.long_array.11 changed, print values."
+ 
+ mi_list_varobj_children {struct_declarations.long_array --all-values} {
+@@ -1121,7 +1121,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.47
+ # Desc: check that psnp->char_ptr (and [0].char_ptr) changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->char_ptr (and 0.char_ptr) changed"
+ 
+ #  Step over "snp1.char_ptr = &c3;"
+@@ -1131,7 +1131,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.48
+ # Desc: check that psnp->next->char_ptr (and [1].char_ptr) changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->next->char_ptr (and 1.char_ptr) changed"
+ 
+ 
+@@ -1142,7 +1142,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.49
+ # Desc: check that psnp->next->next->char_ptr (and [2].char_ptr) changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->next->next->char_ptr (and 2.char_ptr) changed"
+ 
+ 
+@@ -1153,7 +1153,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.50
+ # Desc: check that psnp->long_ptr (and [0].long_ptr) changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->long_ptr (and 0.long_ptr) changed"
+ 
+ 
+@@ -1181,7 +1181,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
+ # Test: c_variable-5.52
+ # Desc: check that psnp->next->next->long_ptr (and [2].long_ptr) changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->next->next->long_ptr (and 2.long_ptr) changed"
+ 
+ mi_prepare_inline_tests $srcfile
+diff --git a/gdb/testsuite/gdb.mi/mi-var-cmd.exp b/gdb/testsuite/gdb.mi/mi-var-cmd.exp
+index ad2e55c..6efb333 100644
+--- a/gdb/testsuite/gdb.mi/mi-var-cmd.exp
++++ b/gdb/testsuite/gdb.mi/mi-var-cmd.exp
+@@ -146,7 +146,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" $line_dlt_linteger "step at do_local
+ # Test: c_variable-2.2
+ # Desc: check whether only linteger changed values
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: linteger changed"
+ 
+ # Step over "lpinteger = &linteger;"
+@@ -155,7 +155,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 1] "step
+ # Test: c_variable-2.3
+ # Desc: check whether only lpinteger changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: lpinteger changed"
+ 
+ # Step over "lcharacter = 'a';"
+@@ -164,7 +164,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 2] "step
+ # Test: c_variable-2.4
+ # Desc: check whether only lcharacter changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: lcharacter changed"
+ 
+ # Step over "lpcharacter = &lcharacter;"
+@@ -173,7 +173,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 3] "step
+ # Test: c_variable-2.5
+ # Desc: check whether only lpcharacter changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: lpcharacter changed"
+ 
+ 
+@@ -195,7 +195,7 @@ mi_execute_to "exec-step 9" "end-stepping-range" "do_locals_tests" "" \
+ # Desc: check whether llong, lplong, lfloat, lpfloat, ldouble, lpdouble, lsimple.integer,
+ #       lsimple.unsigned_character lsimple.integer lsimple.character changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: many changed"
+ 
+ # Step over:
+@@ -212,7 +212,7 @@ mi_execute_to "exec-step 4" "end-stepping-range" "do_locals_tests" "" \
+ # Test: c_variable-2.7
+ # Desc: check whether (lsimple.signed_character, lsimple.char_ptr) lpsimple, func changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: func and lpsimple changed"
+ 
+ # Step over
+@@ -234,7 +234,7 @@ mi_execute_to "exec-step 8" "end-stepping-range" "do_locals_tests" "" \
+ # Note: this test also checks that lpsimple->integer and lsimple.integer have
+ #       changed (they are the same)
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: lsimple and others changed"
+ 
+ 
+@@ -257,7 +257,7 @@ mi_gdb_test "-var-assign linteger 3333" \
+ # change.
+ set lpchar_update "\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\},"
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: linteger changed after assign"
+ 
+ mi_gdb_test "-var-assign linteger 3333" \
+@@ -277,7 +277,7 @@ mi_gdb_test "-var-assign lpinteger \"&linteger + 3\"" \
+ 	"assign to lpinteger"
+ 
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: lpinteger changed after assign"
+ 
+ mi_gdb_test "-var-update *" \
+@@ -377,7 +377,7 @@ mi_gdb_test "-var-update *" \
+ 	"assign same value to func (update)"
+ 
+ mi_gdb_test "-var-create array_ptr * array_ptr" \
+-	"\\^done,name=\"array_ptr\",numchild=\"1\",value=\"$hex\",type=\"int \\*\"" \
++	"\\^done,name=\"array_ptr\",numchild=\"1\",value=\"$hex\",type=\"int \\*\",has_more=\"0\"" \
+ 	"create global variable array_ptr"
+ 
+ mi_gdb_test "-var-assign array_ptr array2" \
+@@ -385,7 +385,7 @@ mi_gdb_test "-var-assign array_ptr array2" \
+ 	"assign array to pointer"
+ 
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"array_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"array_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"assign array to pointer (update)"
+ 
+ mi_gdb_test "-var-assign array_ptr array2" \
+@@ -439,7 +439,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\
+ # Test: c_variable-2.13
+ # Desc: change subroutine1 local i
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: i changed"
+ 
+ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\}" \
+@@ -448,7 +448,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\
+ # Test: c_variable-2.14
+ # Desc: change do_locals_tests local llong
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: llong changed"
+ 
+ set line_dlt_call_subroutine1 [gdb_get_line_number "subroutine1 (linteger, &llong);"]
+@@ -458,7 +458,7 @@ mi_next_to "do_locals_tests" ""	"var-cmd.c" \
+ # Test: c_variable-2.15
+ # Desc: check for out of scope subroutine1 locals
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\",has_more=\"0\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: all now out of scope"
+ 
+ # Done with locals/globals tests. Erase all variables
+@@ -550,14 +550,14 @@ mi_gdb_test "-var-create selected_a @ a" \
+ mi_continue_to incr_a
+ 
+ mi_gdb_test "-var-update selected_a" \
+-	"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\",has_more=\"0\"\}\\\]" \
+ 	"update selected_a in incr_a"
+ 
+ mi_next "step a line in incr_a"
+ mi_next "return from incr_a to do_special_tests"
+ 
+ mi_gdb_test "-var-update selected_a" \
+-	"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\",has_more=\"0\"\}\\\]" \
+ 	"update selected_a in do_special_tests"
+ 
+ mi_gdb_test "-file-exec-and-symbols ${binfile}" "\\^done" \
+@@ -596,7 +596,7 @@ mi_check_varobj_value F 7 "check F inside callee"
+ # A varobj we fail to read during -var-update should be considered
+ # out of scope.
+ mi_gdb_test "-var-create null_ptr * **0" \
+-    {\^done,name="null_ptr",numchild="0",value=".*",type="int"} \
++    {\^done,name="null_ptr",numchild="0",value=".*",type="int",has_more="0"} \
+     "create null_ptr"
+ 
+ # Allow this to succeed, if address zero is readable, although it
+@@ -644,7 +644,7 @@ mi_check_varobj_value "L" "{...}" "in-and-out-of-scope: check initial value"
+ mi_runto main
+ 
+ mi_gdb_test "-var-update L" \
+-    {\^done,changelist=\[{name="L",in_scope="false",type_changed="false"}\]} \
++    {\^done,changelist=\[{name="L",in_scope="false",type_changed="false",has_more="0"}\]} \
+     "in-and-out-of-scope: out of scope now"
+ 
+ mi_gdb_test "-var-update L" \
+@@ -654,7 +654,7 @@ mi_gdb_test "-var-update L" \
+ mi_continue_to do_locals_tests
+ 
+ mi_gdb_test "-var-update L" \
+-    {\^done,changelist=\[{name="L",in_scope="true",type_changed="false"}\]} \
++    {\^done,changelist=\[{name="L",in_scope="true",type_changed="false",has_more="0"}\]} \
+     "in-and-out-of-scope: in scope now"
+ 
+ mi_gdb_test "-var-update L" \
 diff --git a/gdb/testsuite/gdb.mi/mi-var-display.exp b/gdb/testsuite/gdb.mi/mi-var-display.exp
 index 4b02e50..faa9172 100644
 --- a/gdb/testsuite/gdb.mi/mi-var-display.exp
@@ -24692,6 +25322,284 @@ index 4b02e50..faa9172 100644
  	"get children of anone"
  
  
+diff --git a/gdb/testsuite/gdb.mi/mi2-var-block.exp b/gdb/testsuite/gdb.mi/mi2-var-block.exp
+index 6bcfea3..9b3d08f 100644
+--- a/gdb/testsuite/gdb.mi/mi2-var-block.exp
++++ b/gdb/testsuite/gdb.mi/mi2-var-block.exp
+@@ -74,7 +74,7 @@ mi_step_to "do_block_tests" "" "var-cmd.c" \
+ # Test: c_variable-3.4
+ # Desc: check foo, cb changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: cb foo changed"
+ 
+ # step to "foo = 321;"
+diff --git a/gdb/testsuite/gdb.mi/mi2-var-child.exp b/gdb/testsuite/gdb.mi/mi2-var-child.exp
+index 161b34f..0f9b4d4 100644
+--- a/gdb/testsuite/gdb.mi/mi2-var-child.exp
++++ b/gdb/testsuite/gdb.mi/mi2-var-child.exp
+@@ -1,4 +1,4 @@
+-# Copyright 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
++# Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2009 Free Software Foundation
+ 
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+@@ -680,7 +680,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.2
+ # Desc: check that integer changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.integer"
+ 
+ # Step over:
+@@ -693,7 +693,7 @@ mi_execute_to "exec-step 3" "end-stepping-range" do_children_tests {} {.*var-cmd
+ # Test: c_variable-5.3
+ # Desc: check that char_ptr changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.char_ptr"
+ 
+ # Step over "struct_declarations.int_ptr_ptr = &foo;"
+@@ -703,7 +703,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.4
+ # Desc: check that int_ptr_ptr and children changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars int_ptr_ptr and children changed"
+ 
+ # Step over "weird->long_array[0] = 1234;"
+@@ -713,7 +713,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.5
+ # Desc: check that long_array[0] changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.long_array.0 changed"
+ 
+ # Step over "struct_declarations.long_array[1] = 2345;"
+@@ -723,7 +723,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.6
+ # Desc: check that long_array[1] changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.long_array.1 changed"
+ 
+ # Step over "weird->long_array[2] = 3456;"
+@@ -733,7 +733,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.7
+ # Desc: check that long_array[2] changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.long_array.2 changed"
+ 
+ # Step over:
+@@ -752,7 +752,7 @@ mi_execute_to "exec-step 7" "end-stepping-range" do_children_tests {} {.*var-cmd
+ # Test: c_variable-5.8
+ # Desc: check that long_array[3-9] changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.long_array.3-9 changed"
+ 
+ 
+@@ -764,7 +764,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.9
+ # Desc: check that func_ptr changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars struct_declarations.func_ptr changed"
+ 
+ # Delete all variables
+@@ -1075,7 +1075,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.47
+ # Desc: check that psnp->char_ptr (and [0].char_ptr) changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->char_ptr (and 0.char_ptr) changed"
+ 
+ #  Step over "snp1.char_ptr = &c3;"
+@@ -1085,7 +1085,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.48
+ # Desc: check that psnp->next->char_ptr (and [1].char_ptr) changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->next->char_ptr (and 1.char_ptr) changed"
+ 
+ 
+@@ -1096,7 +1096,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.49
+ # Desc: check that psnp->next->next->char_ptr (and [2].char_ptr) changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->next->next->char_ptr (and 2.char_ptr) changed"
+ 
+ 
+@@ -1107,7 +1107,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.50
+ # Desc: check that psnp->long_ptr (and [0].long_ptr) changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->long_ptr (and 0.long_ptr) changed"
+ 
+ 
+@@ -1120,7 +1120,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Why does this have a FIXME?
+ setup_xfail *-*-*
+ mi_gdb_test "-var-update *" \
+-	"FIXME\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"FIXME\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->next->long_ptr (and 1.long_ptr) changed"
+ clear_xfail *-*-*
+ 
+@@ -1135,7 +1135,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
+ # Test: c_variable-5.52
+ # Desc: check that psnp->next->next->long_ptr (and [2].long_ptr) changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars psnp->next->next->long_ptr (and 2.long_ptr) changed"
+ 
+ 
+diff --git a/gdb/testsuite/gdb.mi/mi2-var-cmd.exp b/gdb/testsuite/gdb.mi/mi2-var-cmd.exp
+index 96d42a1..e900d14 100644
+--- a/gdb/testsuite/gdb.mi/mi2-var-cmd.exp
++++ b/gdb/testsuite/gdb.mi/mi2-var-cmd.exp
+@@ -146,7 +146,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" $line_dlt_linteger "step at do_local
+ # Test: c_variable-2.2
+ # Desc: check whether only linteger changed values
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: linteger changed"
+ 
+ # Step over "lpinteger = &linteger;"
+@@ -155,7 +155,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 1] "step
+ # Test: c_variable-2.3
+ # Desc: check whether only lpinteger changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: lpinteger changed"
+ 
+ # Step over "lcharacter = 'a';"
+@@ -164,7 +164,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 2] "step
+ # Test: c_variable-2.4
+ # Desc: check whether only lcharacter changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: lcharacter changed"
+ 
+ # Step over "lpcharacter = &lcharacter;"
+@@ -173,7 +173,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 3] "step
+ # Test: c_variable-2.5
+ # Desc: check whether only lpcharacter changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: lpcharacter changed"
+ 
+ 
+@@ -195,7 +195,7 @@ mi_execute_to "exec-step 9" "end-stepping-range" "do_locals_tests" "" \
+ # Desc: check whether llong, lplong, lfloat, lpfloat, ldouble, lpdouble, lsimple.integer,
+ #       lsimple.unsigned_character lsimple.integer lsimple.character changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: many changed"
+ 
+ # Step over:
+@@ -212,7 +212,7 @@ mi_execute_to "exec-step 4" "end-stepping-range" "do_locals_tests" "" \
+ # Test: c_variable-2.7
+ # Desc: check whether (lsimple.signed_character, lsimple.char_ptr) lpsimple, func changed
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: func and lpsimple changed"
+ 
+ # Step over
+@@ -234,7 +234,7 @@ mi_execute_to "exec-step 8" "end-stepping-range" "do_locals_tests" "" \
+ # Note: this test also checks that lpsimple->integer and lsimple.integer have
+ #       changed (they are the same)
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: lsimple and others changed"
+ 
+ 
+@@ -257,7 +257,7 @@ mi_gdb_test "-var-assign linteger 3333" \
+ # change.
+ set lpchar_update "\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\},"
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: linteger changed after assign"
+ 
+ mi_gdb_test "-var-assign linteger 3333" \
+@@ -277,7 +277,7 @@ mi_gdb_test "-var-assign lpinteger \"&linteger + 3\"" \
+ 	"assign to lpinteger"
+ 
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: lpinteger changed after assign"
+ 
+ mi_gdb_test "-var-update *" \
+@@ -402,7 +402,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\
+ # Test: c_variable-2.13
+ # Desc: change subroutine1 local i
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: i changed"
+ 
+ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\}" \
+@@ -411,7 +411,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\
+ # Test: c_variable-2.14
+ # Desc: change do_locals_tests local llong
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: llong changed"
+ 
+ set line_dlt_call_subroutine1 [gdb_get_line_number "subroutine1 (linteger, &llong);"]
+@@ -421,7 +421,7 @@ mi_next_to "do_locals_tests" ""	"var-cmd.c" \
+ # Test: c_variable-2.15
+ # Desc: check for out of scope subroutine1 locals
+ mi_gdb_test "-var-update *" \
+-	"\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\",has_more=\"0\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
+ 	"update all vars: all now out of scope"
+ 
+ # Done with locals/globals tests. Erase all variables
+@@ -513,14 +513,14 @@ mi_gdb_test "-var-create selected_a @ a" \
+ mi_continue_to incr_a
+ 
+ mi_gdb_test "-var-update selected_a" \
+-	"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\"\,has_more=\"0\"}\\\]" \
+ 	"update selected_a in incr_a"
+ 
+ mi_next "step a line in incr_a"
+ mi_next "return from incr_a to do_special_tests"
+ 
+ mi_gdb_test "-var-update selected_a" \
+-	"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\",has_more=\"0\"\}\\\]" \
+ 	"update selected_a in do_special_tests"
+ 
+ mi_gdb_test "-file-exec-and-symbols ${binfile}" "\\^done" \
 diff --git a/gdb/testsuite/gdb.mi/mi2-var-display.exp b/gdb/testsuite/gdb.mi/mi2-var-display.exp
 index d6ce673..17e208a 100644
 --- a/gdb/testsuite/gdb.mi/mi2-var-display.exp
@@ -24815,6 +25723,87 @@ index 0000000..f2de718
 +# Seen regression:
 +# Address requested for identifier "arr" which is in register $rdi
 +gdb_test "p arr\[0\]" "\\$\[0-9\]+ = 42"
+diff --git a/gdb/testsuite/gdb.opt/fortran-string.exp b/gdb/testsuite/gdb.opt/fortran-string.exp
+new file mode 100644
+index 0000000..f997eec
+--- /dev/null
++++ b/gdb/testsuite/gdb.opt/fortran-string.exp
+@@ -0,0 +1,41 @@
++# Copyright 2009 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++# 
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++# 
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
++
++# This file was written by Jan Kratochvil <jan.kratochvil@redhat.com>.
++
++# Test GDB can cope with Fortran strings having their length present in a CPU
++# register.  With -O0 the string length is passed on the stack.  To make this
++# test meaningful the follow assertion should pass.  It is not being checked
++# here as the "_s" symbol is compiler dependent:
++#   (gdb) info address _s
++#   Symbol "_s" is a variable in register XX.
++
++set test fortran-string
++set srcfile ${test}.f90
++if { [prepare_for_testing ${test}.exp ${test} ${srcfile} {debug f77 additional_flags=-O2}] } {
++    return -1
++}
++
++if ![runto MAIN__] then {
++    perror "couldn't run to breakpoint MAIN__"
++    continue
++}
++
++gdb_breakpoint [gdb_get_line_number "s = s"]
++gdb_continue_to_breakpoint "s = s"
++gdb_test "frame" ".*s='foo'.*"
++gdb_test "ptype s" "type = character\\*3"
++gdb_test "p s" "\\$\[0-9\]* = 'foo'"
+diff --git a/gdb/testsuite/gdb.opt/fortran-string.f90 b/gdb/testsuite/gdb.opt/fortran-string.f90
+new file mode 100644
+index 0000000..e48d520
+--- /dev/null
++++ b/gdb/testsuite/gdb.opt/fortran-string.f90
+@@ -0,0 +1,28 @@
++! Copyright 2009 Free Software Foundation, Inc.
++!
++! This program is free software; you can redistribute it and/or modify
++! it under the terms of the GNU General Public License as published by
++! the Free Software Foundation; either version 2 of the License, or
++! (at your option) any later version.
++!
++! This program is distributed in the hope that it will be useful,
++! but WITHOUT ANY WARRANTY; without even the implied warranty of
++! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++! GNU General Public License for more details.
++!
++! You should have received a copy of the GNU General Public License
++! along with this program; if not, write to the Free Software
++! Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++!
++! Ihis file is the Fortran source file for dynamic.exp.
++! Original file written by Jakub Jelinek <jakub@redhat.com>.
++! Modified for the GDB testcase by Jan Kratochvil <jan.kratochvil@redhat.com>.
++
++  subroutine f(s)
++  character*(*) s
++  s = s
++  end
++
++  program main
++  call f ('foo')
++  end
 diff --git a/gdb/testsuite/gdb.python/Makefile.in b/gdb/testsuite/gdb.python/Makefile.in
 index 79be9e7..c49f713 100644
 --- a/gdb/testsuite/gdb.python/Makefile.in
@@ -25353,7 +26342,7 @@ index 0000000..d444554
 +gdb_test "python print t0" "\\<gdb.InferiorThread object at 0x\[\[:xdigit:\]\]+>" "verify InferiorThread object"
 +gdb_test "python print 'result =', t0.num" " = \[0-9\]+" "test Inferior.num"
 diff --git a/gdb/testsuite/gdb.python/python-mi.exp b/gdb/testsuite/gdb.python/python-mi.exp
-index 3258810..095ee78 100644
+index 3258810..018c6a2 100644
 --- a/gdb/testsuite/gdb.python/python-mi.exp
 +++ b/gdb/testsuite/gdb.python/python-mi.exp
 @@ -48,23 +48,42 @@ mi_gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" ""
@@ -25361,7 +26350,7 @@ index 3258810..095ee78 100644
    "step to breakpoint"
  
 -mi_create_floating_varobj container c "create container varobj"
-+mi_create_floating_varobj container c \
++mi_create_dynamic_varobj container c \
 +  "create container varobj, no pretty-printing"
 +
 +mi_list_varobj_children container {
@@ -25374,7 +26363,7 @@ index 3258810..095ee78 100644
 +
 +mi_gdb_test "-enable-pretty-printing" ""
 +
-+mi_create_floating_varobj container c \
++mi_create_dynamic_varobj container c \
 +  "create container varobj"
  
  mi_list_varobj_children container {
@@ -25407,7 +26396,7 @@ index 3258810..095ee78 100644
  
  mi_gdb_test "-var-set-visualizer container None" \
    "\\^done" \
-@@ -78,19 +97,68 @@ mi_gdb_test "-var-set-visualizer container gdb.default_visualizer" \
+@@ -78,19 +97,88 @@ mi_gdb_test "-var-set-visualizer container gdb.default_visualizer" \
    "\\^done" \
    "choose default visualizer"
  
@@ -25470,20 +26459,40 @@ index 3258810..095ee78 100644
 +
 +mi_next "next over update 4"
 +
++
++# Regression test: examine an object that has no children, then update
++# it to ensure that we don't print the children.
++mi_create_dynamic_varobj container2 c2 \
++  "create second container varobj"
++
++mi_gdb_test "-var-update container2" \
++  "\\^done,changelist=.." \
++  "update varobj, no children requested"
++
++mi_next "next over update 5"
++
++# Now container2 has an element -- and an update should mention that
++# it has_more.  But, because we did not request children, we still
++# should not actually see them.
++mi_varobj_update_dynamic container2 \
++    "update varobj 2, no children requested" {
++	type_changed false has_more 1
++    } {} {}
++
 +# This should only show the first child, because the update range has
 +# been set.
 +mi_varobj_update_dynamic container \
 +  "update after next with restricted range" {
 +      type_changed false new_num_children 1 has_more 1
 +  } {
-+      { name {container.\[0\]} in_scope true type_changed false }
++      { name {container.\[0\]} in_scope true type_changed false has_more 0 }
 +  } {
 +  }
  
  mi_continue_to_line \
      [gdb_get_line_number {Another MI breakpoint} ${testfile}.c] \
 diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c
-index 3cafc48..6bbbf1d 100644
+index 3cafc48..5fbd534 100644
 --- a/gdb/testsuite/gdb.python/python-prettyprint.c
 +++ b/gdb/testsuite/gdb.python/python-prettyprint.c
 @@ -15,6 +15,8 @@
@@ -25507,9 +26516,11 @@ index 3cafc48..6bbbf1d 100644
  int
  main ()
  {
-@@ -156,10 +163,13 @@ main ()
+@@ -155,11 +162,15 @@ main ()
+   struct ss  ssa[2];
    string x = make_string ("this is x");
    zzz_type c = make_container ("container");
++  zzz_type c2 = make_container ("container2");
    const struct string_repr cstring = { { "const string" } };
 +  /* Clearing by being `static' could invoke an other GDB C++ bug.  */
 +  struct nullstr nullstr;
@@ -25521,13 +26532,15 @@ index 3cafc48..6bbbf1d 100644
  
    struct ns  ns;
    ns.null_str = "embedded\0null\0string";
-@@ -193,6 +203,9 @@ main ()
+@@ -193,6 +204,11 @@ main ()
    add_item (&c, 72);
  
  #ifdef MI
 +  add_item (&c, 1011);
 +  c.elements[0] = 1023;
 +
++  add_item (&c2, 2222);
++  add_item (&c2, 3333);
    do_nothing ();
  #endif
  
@@ -26832,10 +27845,17 @@ index 0c93a73..d0c3493 100644
  global GDB
  
 diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
-index e691232..64bc28e 100644
+index e691232..167a02c 100644
 --- a/gdb/testsuite/lib/mi-support.exp
 +++ b/gdb/testsuite/lib/mi-support.exp
-@@ -1201,7 +1201,7 @@ proc mi_create_varobj { name expression testname } {
+@@ -1195,13 +1195,13 @@ proc mi_list_breakpoints { expected test } {
+ # Name cannot be "-".
+ proc mi_create_varobj { name expression testname } {
+     mi_gdb_test "-var-create $name * $expression" \
+-        "\\^done,name=\"$name\",numchild=\"\[0-9\]+\",value=\".*\",type=.*" \
++        "\\^done,name=\"$name\",numchild=\"\[0-9\]+\",value=\".*\",type=.*,has_more=\"0\"" \
+         $testname
+ }
  
  proc mi_create_floating_varobj { name expression testname } {
      mi_gdb_test "-var-create $name @ $expression" \
@@ -26844,7 +27864,38 @@ index e691232..64bc28e 100644
          $testname
  }
  
-@@ -1250,16 +1250,64 @@ proc mi_varobj_update_with_type_change { name new_type new_children testname } {
+@@ -1214,6 +1214,14 @@ proc mi_create_varobj_checked { name expression type testname } {
+         $testname
+ }
+ 
++# Same as mi_create_floating_varobj, but assumes the test is creating
++# a dynamic varobj that has children, so the value must be "{...}".
++proc mi_create_dynamic_varobj {name expression testname} {
++    mi_gdb_test "-var-create $name @ $expression" \
++        "\\^done,name=\"$name\",numchild=\"\(-1\|\[0-9\]+\)\",value=\"{\\.\\.\\.}\",type=.*" \
++        $testname
++}
++
+ # Deletes the specified NAME. 
+ proc mi_delete_varobj { name testname } {
+     mi_gdb_test "-var-delete $name" \
+@@ -1229,7 +1237,7 @@ proc mi_varobj_update { name expected testname } {
+     set er "\\^done,changelist=\\\["
+     set first 1
+     foreach item $expected {
+-        set v "{name=\"$item\",in_scope=\"true\",type_changed=\"false\"}"
++        set v "{name=\"$item\",in_scope=\"true\",type_changed=\"false\",has_more=\".\"}"
+         if {$first == 1} {
+             set er "$er$v"
+             set first 0
+@@ -1244,22 +1252,70 @@ proc mi_varobj_update { name expected testname } {
+ }
+ 
+ proc mi_varobj_update_with_type_change { name new_type new_children testname } {
+-    set v "{name=\"$name\",in_scope=\"true\",type_changed=\"true\",new_type=\"$new_type\",new_num_children=\"$new_children\"}"
++    set v "{name=\"$name\",in_scope=\"true\",type_changed=\"true\",new_type=\"$new_type\",new_num_children=\"$new_children\",has_more=\".\"}"
+     set er "\\^done,changelist=\\\[$v\\\]"
+     verbose -log "Expecting: $er"
      mi_gdb_test "-var-update $name" $er $testname
  }
  
@@ -26871,13 +27922,15 @@ index e691232..64bc28e 100644
 +    }
 +    return $rx
 +}
-+
+ 
+-    set er "\\^done,changelist=\\\["
 +# A helper for mi_varobj_update_dynamic that computes a match
 +# expression given a child list.
 +proc mi_varobj_update_dynamic_helper {children} {
 +    set crx ""
  
--    set er "\\^done,changelist=\\\["
+-    append er "{name=\"$name\",in_scope=\"true\",type_changed=\"false\""
+-    append er ",children=\\\[$children_exp_j.*\\\]}\\\]"
 +    set first 1
 +    foreach child $children {
 +	if {!$first} {
@@ -26905,9 +27958,7 @@ index e691232..64bc28e 100644
 +    }
 +    set selfrx [mi_varobj_update_kv_helper $self]
 +    set crx [mi_varobj_update_dynamic_helper $children]
- 
--    append er "{name=\"$name\",in_scope=\"true\",type_changed=\"false\""
--    append er ",children=\\\[$children_exp_j.*\\\]}\\\]"
++
 +    set er "\\^done,changelist=\\\[\{name=\"$name\",in_scope=\"true\""
 +    append er ",$selfrx\}"
 +    if {"$crx" != ""} {
@@ -26917,7 +27968,7 @@ index e691232..64bc28e 100644
  
      verbose -log "Expecting: $er"
      mi_gdb_test "-var-update $name" $er $testname
-@@ -1329,14 +1377,13 @@ proc mi_child_regexp {children add_child} {
+@@ -1329,14 +1385,13 @@ proc mi_child_regexp {children add_child} {
  # have no value.
  #
  proc mi_list_varobj_children { varname children testname } {
@@ -26936,7 +27987,7 @@ index e691232..64bc28e 100644
      set options ""
      if {[llength $varname] == 2} {
          set options [lindex $varname 1]
-@@ -1352,9 +1399,18 @@ proc mi_list_varobj_children_range {varname numchildren children testname} {
+@@ -1352,9 +1407,18 @@ proc mi_list_varobj_children_range {varname numchildren children testname} {
          set expected "\\^done,numchild=\"0\""
      }
  
@@ -27711,10 +28762,18 @@ index 5e5c4ed..7aedbfd 100644
  					TYPE_TARGET_TYPE (range_type),
  					lowbound, 
 diff --git a/gdb/valprint.c b/gdb/valprint.c
-index cbb5d94..cf35bf0 100644
+index cbb5d94..f9634ea 100644
 --- a/gdb/valprint.c
 +++ b/gdb/valprint.c
-@@ -1153,6 +1153,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr,
+@@ -236,7 +236,6 @@ scalar_type_p (struct type *type)
+     case TYPE_CODE_STRUCT:
+     case TYPE_CODE_UNION:
+     case TYPE_CODE_SET:
+-    case TYPE_CODE_STRING:
+     case TYPE_CODE_BITSTRING:
+       return 0;
+     default:
+@@ -1153,6 +1152,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr,
  
    for (; i < len && things_printed < options->print_max; i++)
      {
@@ -27722,7 +28781,7 @@ index cbb5d94..cf35bf0 100644
        if (i != 0)
  	{
  	  if (options->prettyprint_arrays)
-@@ -1172,7 +1173,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr,
+@@ -1172,7 +1172,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr,
        rep1 = i + 1;
        reps = 1;
        while ((rep1 < len) &&
@@ -28057,7 +29116,7 @@ index 6f6b756..b9ca650 100644
  /* User function handler.  */
  
 diff --git a/gdb/varobj.c b/gdb/varobj.c
-index fbe8ff8..1bfc5e4 100644
+index fbe8ff8..a730095 100644
 --- a/gdb/varobj.c
 +++ b/gdb/varobj.c
 @@ -26,9 +26,12 @@
@@ -28200,14 +29259,14 @@ index fbe8ff8..1bfc5e4 100644
 +{
 +  if (VEC_length (varobj_p, var->children) > to)
 +    return 1;
-+  return (VEC_length (varobj_p, var->children) == to
++  return ((to == -1 || VEC_length (varobj_p, var->children) == to)
 +	  && var->saved_item != NULL);
 +}
 +
  /* If the variable object is bound to a specific thread, that
     is its evaluation can always be done in context of a frame
     inside that thread, returns GDB id of the thread -- which
-@@ -835,22 +880,73 @@ varobj_get_frozen (struct varobj *var)
+@@ -835,22 +880,90 @@ varobj_get_frozen (struct varobj *var)
    return var->frozen;
  }
  
@@ -28266,6 +29325,23 @@ index fbe8ff8..1bfc5e4 100644
 +    }
 +}
 +
++#if HAVE_PYTHON
++
++static int
++dynamic_varobj_has_child_method (struct varobj *var)
++{
++  struct cleanup *back_to;
++  PyObject *printer = var->pretty_printer;
++  int result;
++
++  back_to = varobj_ensure_python_env (var);
++  result = PyObject_HasAttr (printer, gdbpy_children_cst);
++  do_cleanups (back_to);
++  return result;
++}
++
++#endif
++
  static int
  update_dynamic_varobj_children (struct varobj *var,
  				VEC (varobj_p) **changed,
@@ -28289,7 +29365,7 @@ index fbe8ff8..1bfc5e4 100644
    PyObject *printer = var->pretty_printer;
  
    back_to = varobj_ensure_python_env (var);
-@@ -862,87 +958,103 @@ update_dynamic_varobj_children (struct varobj *var,
+@@ -862,87 +975,103 @@ update_dynamic_varobj_children (struct varobj *var,
        return 0;
      }
  
@@ -28450,17 +29526,30 @@ index fbe8ff8..1bfc5e4 100644
    return 1;
  #else
    gdb_assert (0 && "should never be called if Python is not enabled");
-@@ -955,8 +1067,7 @@ varobj_get_num_children (struct varobj *var)
+@@ -954,20 +1083,26 @@ varobj_get_num_children (struct varobj *var)
+ {
    if (var->num_children == -1)
      {
-       int changed;
+-      int changed;
 -      if (!var->pretty_printer
 -	  || !update_dynamic_varobj_children (var, NULL, NULL, &changed))
-+      if (!var->pretty_printer)
++      if (var->pretty_printer)
++	{
++	  int dummy;
++
++	  /* If we have a dynamic varobj, don't report -1 children.
++	     So, try to fetch some children first.  */
++	  update_dynamic_varobj_children (var, NULL, NULL, &dummy, 0, 0);
++	}
++      else
  	var->num_children = number_of_children (var);
      }
  
-@@ -967,7 +1078,7 @@ varobj_get_num_children (struct varobj *var)
+-  return var->num_children;
++  return var->num_children >= 0 ? var->num_children : 0;
+ }
+ 
+ /* Creates a list of the immediate children of a variable object;
     the return code is the number of such children or -1 on error */
  
  VEC (varobj_p)*
@@ -28469,7 +29558,7 @@ index fbe8ff8..1bfc5e4 100644
  {
    struct varobj *child;
    char *name;
-@@ -975,12 +1086,16 @@ varobj_list_children (struct varobj *var)
+@@ -975,12 +1110,16 @@ varobj_list_children (struct varobj *var)
  
    var->children_requested = 1;
  
@@ -28489,7 +29578,7 @@ index fbe8ff8..1bfc5e4 100644
  
    if (var->num_children == -1)
      var->num_children = number_of_children (var);
-@@ -1006,10 +1121,10 @@ varobj_list_children (struct varobj *var)
+@@ -1006,10 +1145,10 @@ varobj_list_children (struct varobj *var)
  	  name = name_of_child (var, i);
  	  existing = create_child (var, i, name);
  	  VEC_replace (varobj_p, var->children, i, existing);
@@ -28501,7 +29590,7 @@ index fbe8ff8..1bfc5e4 100644
    return var->children;
  }
  
-@@ -1020,7 +1135,6 @@ varobj_add_child (struct varobj *var, const char *name, struct value *value)
+@@ -1020,7 +1159,6 @@ varobj_add_child (struct varobj *var, const char *name, struct value *value)
  					VEC_length (varobj_p, var->children), 
  					name, value);
    VEC_safe_push (varobj_p, var->children, v);
@@ -28509,7 +29598,7 @@ index fbe8ff8..1bfc5e4 100644
    return v;
  }
  
-@@ -1082,6 +1196,12 @@ varobj_get_attributes (struct varobj *var)
+@@ -1082,6 +1220,12 @@ varobj_get_attributes (struct varobj *var)
    return attributes;
  }
  
@@ -28522,7 +29611,7 @@ index fbe8ff8..1bfc5e4 100644
  char *
  varobj_get_formatted_value (struct varobj *var,
  			    enum varobj_display_formats format)
-@@ -1159,6 +1279,115 @@ varobj_set_value (struct varobj *var, char *expression)
+@@ -1159,6 +1303,116 @@ varobj_set_value (struct varobj *var, char *expression)
    return 1;
  }
  
@@ -28615,8 +29704,9 @@ index fbe8ff8..1bfc5e4 100644
 +install_new_value_visualizer (struct varobj *var)
 +{
 +#if HAVE_PYTHON
-+  /* If the constructor is None, then we want the raw value.  */
-+  if (var->constructor != Py_None)
++  /* If the constructor is None, then we want the raw value.  If VAR
++     does not have a value, just skip this.  */
++  if (var->constructor != Py_None && var->value)
 +    {
 +      struct cleanup *cleanup;
 +      PyObject *pretty_printer = NULL;
@@ -28638,7 +29728,7 @@ index fbe8ff8..1bfc5e4 100644
  /* Assign a new value to a variable object.  If INITIAL is non-zero,
     this is the first assignement after the variable object was just
     created, or changed type.  In that case, just assign the value 
-@@ -1199,10 +1428,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
+@@ -1199,10 +1453,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
       that in C++ a reference is not rebindable, it cannot
       meaningfully change.  So, get hold of the real value.  */
    if (value)
@@ -28650,7 +29740,7 @@ index fbe8ff8..1bfc5e4 100644
  
    if (var->type && TYPE_CODE (var->type) == TYPE_CODE_UNION)
      /* For unions, we need to fetch the value implicitly because
-@@ -1249,7 +1475,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
+@@ -1249,7 +1500,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
       values.  Don't get string rendering if the value is
       lazy -- if it is, the code above has decided that the value
       should not be fetched.  */
@@ -28659,7 +29749,7 @@ index fbe8ff8..1bfc5e4 100644
      print_value = value_get_print_value (value, var->format, var);
  
    /* If the type is changeable, compare the old and the new values.
-@@ -1265,7 +1491,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
+@@ -1265,7 +1516,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
  	{
  	  changed = 1;
  	}
@@ -28668,7 +29758,7 @@ index fbe8ff8..1bfc5e4 100644
  	{
  	  /* Try to compare the values.  That requires that both
  	     values are non-lazy.  */
-@@ -1310,6 +1536,8 @@ install_new_value (struct varobj *var, struct value *value, int initial)
+@@ -1310,6 +1561,8 @@ install_new_value (struct varobj *var, struct value *value, int initial)
    if (var->value != NULL && var->value != value)
      value_free (var->value);
    var->value = value;
@@ -28677,7 +29767,7 @@ index fbe8ff8..1bfc5e4 100644
    if (var->print_value)
      xfree (var->print_value);
    var->print_value = print_value;
-@@ -1319,65 +1547,32 @@ install_new_value (struct varobj *var, struct value *value, int initial)
+@@ -1319,65 +1572,32 @@ install_new_value (struct varobj *var, struct value *value, int initial)
      var->not_fetched = 0;
    var->updated = 0;
  
@@ -28760,7 +29850,7 @@ index fbe8ff8..1bfc5e4 100644
  }
  
  void 
-@@ -1395,31 +1590,19 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer)
+@@ -1395,31 +1615,19 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer)
    make_cleanup_py_decref (globals);
  
    constructor = PyRun_String (visualizer, Py_eval_input, globals, globals);
@@ -28798,8 +29888,13 @@ index fbe8ff8..1bfc5e4 100644
  
    do_cleanups (back_to);
  #else
-@@ -1534,7 +1717,7 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
- 	 UI, so we need not bother getting it.  */
+@@ -1530,44 +1738,60 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
+ 
+       /* We probably should not get children of a varobj that has a
+ 	 pretty-printer, but for which -var-list-children was never
+-	 invoked.  Presumably, such varobj is not yet expanded in the
+-	 UI, so we need not bother getting it.  */
++	 invoked.    */
        if (v->pretty_printer)
  	{
 -	  VEC (varobj_p) *changed = 0, *new_and_unchanged = 0;
@@ -28807,8 +29902,32 @@ index fbe8ff8..1bfc5e4 100644
  	  int i, children_changed;
  	  varobj_p tmp;
  
-@@ -1546,28 +1729,28 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
+-	  if (!v->children_requested)
+-	    continue;
+-
+ 	  if (v->frozen)
+ 	    continue;
  
++	  if (!v->children_requested)
++	    {
++	      int dummy;
++
++	      /* If we initially did not have potential children, but
++		 now we do, consider the varobj as changed.
++		 Otherwise, if children were never requested, consider
++		 it as unchanged -- presumably, such varobj is not yet
++		 expanded in the UI, so we need not bother getting
++		 it.  */
++	      if (varobj_has_more (v, 0))
++		continue;
++
++	      update_dynamic_varobj_children (v, NULL, NULL, &dummy, 0, 0);
++	      if (varobj_has_more (v, 0))
++		VEC_safe_push (varobj_update_result, result, &r);
++
++	      continue;
++	    }
++
  	  /* If update_dynamic_varobj_children returns 0, then we have
  	     a non-conforming pretty-printer, so we skip it.  */
 -	  if (update_dynamic_varobj_children (v, &changed, &new_and_unchanged,
@@ -28848,7 +29967,7 @@ index fbe8ff8..1bfc5e4 100644
  	      continue;
  	    }
  	}
-@@ -1855,7 +2038,12 @@ new_variable (void)
+@@ -1855,7 +2079,12 @@ new_variable (void)
    var->frozen = 0;
    var->not_fetched = 0;
    var->children_requested = 0;
@@ -28861,7 +29980,7 @@ index fbe8ff8..1bfc5e4 100644
  
    return var;
  }
-@@ -1885,7 +2073,10 @@ free_variable (struct varobj *var)
+@@ -1885,7 +2114,10 @@ free_variable (struct varobj *var)
    if (var->pretty_printer)
      {
        struct cleanup *cleanup = varobj_ensure_python_env (var);
@@ -28873,7 +29992,7 @@ index fbe8ff8..1bfc5e4 100644
        do_cleanups (cleanup);
      }
  #endif
-@@ -1918,6 +2109,18 @@ make_cleanup_free_variable (struct varobj *var)
+@@ -1918,6 +2150,18 @@ make_cleanup_free_variable (struct varobj *var)
    return make_cleanup (do_free_variable_cleanup, var);
  }
  
@@ -28892,7 +30011,7 @@ index fbe8ff8..1bfc5e4 100644
  /* This returns the type of the variable. It also skips past typedefs
     to return the real type of the variable.
  
-@@ -2132,6 +2335,8 @@ value_of_root (struct varobj **var_handle, int *type_changed)
+@@ -2132,6 +2376,8 @@ value_of_root (struct varobj **var_handle, int *type_changed)
        else
  	{
  	  tmp_var->obj_name = xstrdup (var->obj_name);
@@ -28901,7 +30020,7 @@ index fbe8ff8..1bfc5e4 100644
  	  varobj_delete (var, NULL, 0);
  
  	  install_variable (tmp_var);
-@@ -2166,7 +2371,11 @@ static char *
+@@ -2166,7 +2412,11 @@ static char *
  my_value_of_variable (struct varobj *var, enum varobj_display_formats format)
  {
    if (var->root->is_valid)
@@ -28914,7 +30033,90 @@ index fbe8ff8..1bfc5e4 100644
    else
      return NULL;
  }
-@@ -2954,10 +3163,7 @@ cplus_describe_child (struct varobj *parent, int index,
+@@ -2189,43 +2439,51 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
+     struct cleanup *back_to = varobj_ensure_python_env (var);
+     PyObject *value_formatter = var->pretty_printer;
+ 
+-    if (value_formatter && PyObject_HasAttr (value_formatter,
+-					     gdbpy_to_string_cst))
++    if (value_formatter)
+       {
+-	char *hint;
+-	struct value *replacement;
+-	int string_print = 0;
+-	PyObject *output = NULL;
++	/* First check to see if we have any children at all.  If so,
++	   we simply return {...}.  */
++	if (dynamic_varobj_has_child_method (var))
++	  return xstrdup ("{...}");
+ 
+-	hint = gdbpy_get_display_hint (value_formatter);
+-	if (hint)
++	if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst))
+ 	  {
+-	    if (!strcmp (hint, "string"))
+-	      string_print = 1;
+-	    xfree (hint);
+-	  }
++	    char *hint;
++	    struct value *replacement;
++	    int string_print = 0;
++	    PyObject *output = NULL;
++
++	    hint = gdbpy_get_display_hint (value_formatter);
++	    if (hint)
++	      {
++		if (!strcmp (hint, "string"))
++		  string_print = 1;
++		xfree (hint);
++	      }
+ 
+-	output = apply_varobj_pretty_printer (value_formatter,
+-					      &replacement);
+- 	if (output)
+-  	  {
+- 	    PyObject *py_str = python_string_to_target_python_string (output);
+- 	    if (py_str)
+- 	      {
+- 		char *s = PyString_AsString (py_str);
+- 		len = PyString_Size (py_str);
+-		thevalue = xmemdup (s, len + 1, len + 1);
+- 		Py_DECREF (py_str);
++	    output = apply_varobj_pretty_printer (value_formatter,
++						  &replacement);
++	    if (output)
++	      {
++		PyObject *py_str
++		  = python_string_to_target_python_string (output);
++		if (py_str)
++		  {
++		    char *s = PyString_AsString (py_str);
++		    len = PyString_Size (py_str);
++		    thevalue = xmemdup (s, len + 1, len + 1);
++		    Py_DECREF (py_str);
++		  }
++		Py_DECREF (output);
+ 	      }
+- 	    Py_DECREF (output);
+-	  }
+-	if (thevalue && !string_print)
+-	  {
+-	    do_cleanups (back_to);
+-	    return thevalue;
++	    if (thevalue && !string_print)
++	      {
++		do_cleanups (back_to);
++		return thevalue;
++	      }
++	    if (replacement)
++	      value = replacement;
+ 	  }
+-	if (replacement)
+-	  value = replacement;
+       }
+     do_cleanups (back_to);
+   }
+@@ -2954,10 +3212,7 @@ cplus_describe_child (struct varobj *parent, int index,
  	    *cname = xstrdup (TYPE_FIELD_NAME (type, index));
  
  	  if (cvalue && value)
@@ -28926,7 +30128,7 @@ index fbe8ff8..1bfc5e4 100644
  
  	  if (ctype)
  	    {
-@@ -3163,6 +3369,19 @@ java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
+@@ -3163,6 +3418,19 @@ java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
    return cplus_value_of_variable (var, format);
  }
  
@@ -28946,7 +30148,7 @@ index fbe8ff8..1bfc5e4 100644
  /* Iterate all the existing _root_ VAROBJs and call the FUNC callback for them
     with an arbitrary caller supplied DATA pointer.  */
  
-@@ -3180,6 +3399,43 @@ all_root_varobjs (void (*func) (struct varobj *var, void *data), void *data)
+@@ -3180,6 +3448,43 @@ all_root_varobjs (void (*func) (struct varobj *var, void *data), void *data)
        (*func) (var_root->rootvar, data);
      }
  }

diff --git a/gdb-bz515434-qsort_cmp.patch b/gdb-bz515434-qsort_cmp.patch
index 20974f0..b1f4264 100644
--- a/gdb-bz515434-qsort_cmp.patch
+++ b/gdb-bz515434-qsort_cmp.patch
@@ -227,205 +227,3 @@ diff -p -u -r1.93 objfiles.c
  
    *pmap = map;
    *pmap_size = map_size;
-
-2009-08-25  Jan Kratochvil  <jan.kratochvil@redhat.com>
-
-	* gdb.base/solib-overlap.exp, gdb.base/solib-overlap-lib.c,
-	gdb.base/solib-overlap-main.c: New.
-
---- /dev/null
-+++ b/gdb/testsuite/gdb.base/solib-overlap-lib.c
-@@ -0,0 +1,27 @@
-+/* Copyright 2009 Free Software Foundation, Inc.
-+   This program is free software; you can redistribute it and/or modify
-+   it under the terms of the GNU General Public License as published by
-+   the Free Software Foundation; either version 3 of the License, or
-+   (at your option) any later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-+
-+   Contributed by Jan Kratochvil <jan.kratochvil@redhat.com>.  */
-+
-+void
-+libsym (void)
-+{
-+}
-+
-+#ifdef SYMB
-+void
-+libsymb (void)
-+{
-+}
-+#endif
---- /dev/null
-+++ b/gdb/testsuite/gdb.base/solib-overlap-main.c
-@@ -0,0 +1,25 @@
-+/* Copyright 2009 Free Software Foundation, Inc.
-+   This program is free software; you can redistribute it and/or modify
-+   it under the terms of the GNU General Public License as published by
-+   the Free Software Foundation; either version 3 of the License, or
-+   (at your option) any later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-+
-+   Contributed by Jan Kratochvil <jan.kratochvil@redhat.com>.  */
-+
-+#include <unistd.h>
-+
-+int
-+main (void)
-+{
-+  sleep (60);
-+
-+  return 1;
-+}
---- /dev/null
-+++ b/gdb/testsuite/gdb.base/solib-overlap.exp
-@@ -0,0 +1,135 @@
-+# Copyright 2009 Free Software Foundation, Inc.
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 3 of the License, or
-+# (at your option) any later version.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-+#
-+# Contributed by Jan Kratochvil <jan.kratochvil@redhat.com>.
-+
-+# Test GDB can cope with two libraries loaded with overlapping VMA ranges.
-+# Prelink libraries first so they can be loaded and their native address.
-+# In such case `struct linkmap'.l_addr will be zero.  Provide different
-+# unprelinked library files on the disk which have zero-based VMAs.  These
-+# different files should have their .dynamic section at a different offset in
-+# page size so that we get for
-+#   warning: .dynamic section for "..." is not at the expected address
-+# the reason
-+#   (wrong library or version mismatch?)
-+# and not:
-+#   difference appears to be caused by prelink, adjusting expectations
-+# In such case both disk libraries will be loaded at VMAs starting at zero.
-+
-+if [skip_shlib_tests] {
-+    return 0
-+}
-+
-+# Are we on a target board?  It is required for attaching to a process.
-+if [is_remote target] {
-+    return 0
-+}
-+
-+# Library file.
-+set libname "solib-overlap-lib"
-+set srcfile_lib ${srcdir}/${subdir}/${libname}.c
-+# Binary file.
-+set testfile "solib-overlap-main"
-+set srcfile ${srcdir}/${subdir}/${testfile}.c
-+
-+# Base addresses for `prelink -r' which should be compatible with both -m32 and
-+# -m64 targets.  If it clashes with system prelinked libraries it would give
-+# false PASS.
-+# Prelink first lib1 at 0x40000000 and lib2 at 0x41000000.
-+# During second pass try lib1 at 0x50000000 and lib2 at 0x51000000.
-+foreach prelink_lib1 {0x40000000 0x50000000} {
-+    set prelink_lib2 [format "0x%x" [expr $prelink_lib1 + 0x01000000]]
-+
-+    set old_prefix $pf_prefix
-+    lappend pf_prefix "$prelink_lib1:"
-+
-+    # Library file.
-+    set binfile_lib1 ${objdir}/${subdir}/${libname}1-${prelink_lib1}.so
-+    set binfile_lib2 ${objdir}/${subdir}/${libname}2-${prelink_lib1}.so
-+    set lib_flags {debug}
-+    # Binary file.
-+    set binfile_base ${testfile}-${prelink_lib1}
-+    set binfile ${objdir}/${subdir}/${binfile_base}
-+    set bin_flags [list debug shlib=${binfile_lib1} shlib=${binfile_lib2}]
-+    set escapedbinfile  [string_to_regexp ${binfile}]
-+
-+    if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib1} $lib_flags] != ""
-+	 || [gdb_compile_shlib ${srcfile_lib} ${binfile_lib2} $lib_flags] != ""
-+	 || [gdb_compile ${srcfile} ${binfile} executable $bin_flags] != "" } {
-+	untested "Could not compile ${binfile_lib1}, ${binfile_lib2} or ${binfile}."
-+	return -1
-+    }
-+
-+    if {[catch "system \"prelink -N -r ${prelink_lib1} ${binfile_lib1}\""] != 0
-+	|| [catch "system \"prelink -N -r ${prelink_lib2} ${binfile_lib2}\""] != 0} {
-+	# Maybe we don't have prelink.
-+	untested "Could not prelink ${binfile_lib1} or ${binfile_lib2}."
-+	return -1
-+    }
-+
-+    # Start the program running and then wait for a bit, to be sure
-+    # that it can be attached to.
-+
-+    set testpid [eval exec $binfile &]
-+    sleep 2
-+    if { [istarget "*-*-cygwin*"] } {
-+	# testpid is the Cygwin PID, GDB uses the Windows PID, which might be
-+	# different due to the way fork/exec works.
-+	set testpid [ exec ps -e | gawk "{ if (\$1 == $testpid) print \$4; }" ]
-+    }
-+
-+    remote_exec build "mv -f ${binfile_lib1} ${binfile_lib1}-running"
-+    remote_exec build "mv -f ${binfile_lib2} ${binfile_lib2}-running"
-+
-+    # Provide another exported function name to cause different sizes of sections.
-+    lappend lib_flags additional_flags=-DSYMB
-+
-+    if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib1} $lib_flags] != ""
-+	 || [gdb_compile_shlib ${srcfile_lib} ${binfile_lib2} $lib_flags] != ""} {
-+	untested "Could not recompile ${binfile_lib1} or ${binfile_lib2}."
-+	remote_exec build "kill -9 ${testpid}"
-+	return -1
-+    }
-+
-+    clean_restart ${binfile_base}
-+    # This testcase currently does not support remote targets.
-+    # gdb_load_shlibs ${binfile_lib1} ${binfile_lib2}
-+
-+    # Here we should get:
-+    # warning: .dynamic section for ".../solib-overlap-lib1.so" is not at the expected address (wrong library or version mismatch?)
-+    # warning: .dynamic section for ".../solib-overlap-lib2.so" is not at the expected address (wrong library or version mismatch?)
-+
-+    set test attach
-+    gdb_test_multiple "attach $testpid" $test {
-+	-re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*$gdb_prompt $" {
-+	    pass $test
-+	}
-+	-re "Attaching to program.*`?$escapedbinfile\.exe'?, process $testpid.*\[Switching to thread $testpid\..*\].*$gdb_prompt $" {
-+	    # Response expected on Cygwin
-+	    pass $test
-+	}
-+    }
-+
-+    # Detach the process.
-+
-+    gdb_test "detach" "Detaching from program: .*$escapedbinfile, process $testpid"
-+
-+    # Wait a bit for gdb to finish detaching
-+
-+    sleep 5
-+
-+    remote_exec build "kill -9 ${testpid}"
-+
-+    set pf_prefix $old_prefix
-+}

diff --git a/gdb.spec b/gdb.spec
index 3c2026c..3d6d104 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -14,7 +14,7 @@ Version: 6.8.50.20090818
 
 # The release always contains a leading reserved number, start it at 1.
 # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
-Release: 6%{?_with_upstream:.upstream}%{?dist}
+Release: 7%{?_with_upstream:.upstream}%{?dist}
 
 License: GPLv3+
 Group: Development/Debuggers
@@ -829,6 +829,12 @@ fi
 %endif
 
 %changelog
+* Tue Sep  1 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20090818-7
+- archer-jankratochvil-fedora12 commit: d25596676e8811b03f8c9aba6bbd04ebaa9ff5db
+  - [call-frame-cfa] Fix parsing CFA-relative frames (BZ 516627, Tom Tromey).
+  - [vla] variable length Fortran strings for -O -g code (part of BZ 508406, me).
+  - [python] varobj + general fixes (Tom Tromey).
+
 * Fri Aug 28 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20090818-6
 - Real upstream fixup of qsort_cmp (BZ 515434).
 - Revert bitfields regression (BZ 520129).

^ permalink raw reply related	[flat|nested] 5+ messages in thread
* [rpms/gdb] gdb-17.2-rebase-f44: - archer-jankratochvil-fedora12 commit:
@ 2026-06-27 23:54 Jan Kratochvil
  0 siblings, 0 replies; 5+ messages in thread
From: Jan Kratochvil @ 2026-06-27 23:54 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/gdb
            Branch : gdb-17.2-rebase-f44
            Commit : 2164cdaf2aee1d5e56a8729836a6f076f567d435
            Author : Jan Kratochvil <jkratoch@fedoraproject.org>
            Date   : 2009-09-03T19:45:38+00:00
            Stats  : +301/-68 in 2 file(s)
            URL    : https://src.fedoraproject.org/rpms/gdb/c/2164cdaf2aee1d5e56a8729836a6f076f567d435?branch=gdb-17.2-rebase-f44

            Log:
            - archer-jankratochvil-fedora12 commit:
    a081d2f12945e9468edd5f4341d3e945bd0fefe9
- [expr] Fix too slow lookups in large C++ programs (Sami Wagiaalla).
- [python] Fix varobj changed values reporting (GDB PR 10584, Tom Tromey).

---
diff --git a/gdb-archer.patch b/gdb-archer.patch
index 52e6af4..d31855b 100644
--- a/gdb-archer.patch
+++ b/gdb-archer.patch
@@ -2,7 +2,7 @@ http://sourceware.org/gdb/wiki/ProjectArcher
 http://sourceware.org/gdb/wiki/ArcherBranchManagement
 
 GIT snapshot:
-commit d25596676e8811b03f8c9aba6bbd04ebaa9ff5db
+commit a081d2f12945e9468edd5f4341d3e945bd0fefe9
 
 branch `archer' - the merge of branches:
 archer-tromey-call-frame-cfa
@@ -1934,7 +1934,7 @@ index 62800b8..97d587b 100644
  			{ $$ = $1.comp;
  			  if ($2) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2); }
 diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
-index d2d8f2e..5805a30 100644
+index d2d8f2e..7672b2e 100644
 --- a/gdb/cp-namespace.c
 +++ b/gdb/cp-namespace.c
 @@ -36,14 +36,17 @@ static struct using_direct *cp_copy_usings (struct using_direct *using,
@@ -2081,7 +2081,7 @@ index d2d8f2e..5805a30 100644
 +  /* Search for name in namespaces imported to this and parent blocks.  */
 +  while (block != NULL)
 +    {
-+      sym = cp_lookup_symbol_imports(scope,name, block, domain,0);
++      sym = cp_lookup_symbol_imports(scope,name, block, domain,0,1);
 +
 +      if (sym)
 +        return sym;
@@ -2114,7 +2114,7 @@ index d2d8f2e..5805a30 100644
        if (sym != NULL)
  	return sym;
      }
-@@ -320,25 +377,55 @@ lookup_namespace_scope (const char *name,
+@@ -320,25 +377,81 @@ lookup_namespace_scope (const char *name,
    namespace = alloca (scope_len + 1);
    strncpy (namespace, scope, scope_len);
    namespace[scope_len] = '\0';
@@ -2152,7 +2152,29 @@ index d2d8f2e..5805a30 100644
 +}
 +
 +/* Search for NAME by applying all import statements belonging
-+   to BLOCK which are applicable in SCOPE.  */
++   to BLOCK which are applicable in SCOPE. If DECLARATION_ONLY the search
++   is restricted to using declarations.
++   Example:
++
++     namespace A{
++       int x;
++     }
++     using A::x;
++
++   If SEARCH_PARENTS the search will include imports which are applicable in
++   parents of scopes.
++   Example:
++
++     namespace A{
++       using namespace X;
++       namespace B{
++         using namespace Y;
++       }
++     }
++
++   If SCOPE is "A::B" and SEARCH_PARENTS is true the imports of namespaces X
++   and Y will be considered. If SEARCH_PARENTS is false only the import of Y
++   is considered.  */
 +
  struct symbol *
 -cp_lookup_symbol_namespace (const char *namespace,
@@ -2164,17 +2186,21 @@ index d2d8f2e..5805a30 100644
 +                            const char *name,
 +                            const struct block *block,
 +                            const domain_enum domain,
-+                            int declaration_only)
++                            int declaration_only,
++                            int search_parents)
  {
 -  const struct using_direct *current;
 -  struct symbol *sym;
 +  struct using_direct *current;
 +  struct symbol *sym = NULL;
++  int directive_match;
++  int current_line = find_pc_line (get_frame_pc (get_current_frame ()), 0).line;
  
 -  /* First, go through the using directives.  If any of them add new
 +  if(!declaration_only)
-+  /* First, try to find the symbol in the given namespace.  */
-+  sym = cp_lookup_symbol_in_namespace (scope, name, block, domain);
++    /* First, try to find the symbol in the given namespace.  */
++    sym = cp_lookup_symbol_in_namespace (scope, name, block, domain);
++
 +  if ( sym != NULL)
 +    return sym;
 +
@@ -2182,17 +2208,20 @@ index d2d8f2e..5805a30 100644
       names to the namespace we're searching in, see if we can find a
       match by applying them.  */
  
-@@ -346,39 +433,70 @@ cp_lookup_symbol_namespace (const char *namespace,
+@@ -346,39 +459,74 @@ cp_lookup_symbol_namespace (const char *namespace,
         current != NULL;
         current = current->next)
      {
 -      if (strcmp (namespace, current->import_dest) == 0)
-+      int current_line = find_pc_line (get_frame_pc (get_current_frame ()), 0).line;
 +  
 +      /* If the import destination is the current scope or one of its ancestors then
 +         it is applicable.  */
-+      if (strncmp (scope, current->import_dest,
-+          strlen(current->import_dest)) == 0 &&
++      directive_match = search_parents ?
++                        strncmp (scope, current->import_dest,
++                                 strlen(current->import_dest)) == 0 :
++                        strcmp (scope, current->import_dest) == 0;
++
++      if (directive_match &&
 +          current->line_number < current_line &&
 +          !current->searched)
  	{
@@ -2244,6 +2273,7 @@ index d2d8f2e..5805a30 100644
 +		                                name,
 +		                                block,
 +		                                domain,
++		                                0,
 +		                                0);
 +	    }
 +
@@ -2281,7 +2311,7 @@ index d2d8f2e..5805a30 100644
  }
  
  /* Look up NAME in BLOCK's static block and in global blocks.  If
-@@ -388,17 +506,15 @@ cp_lookup_symbol_namespace (const char *namespace,
+@@ -388,17 +536,15 @@ cp_lookup_symbol_namespace (const char *namespace,
  
  static struct symbol *
  lookup_symbol_file (const char *name,
@@ -2300,7 +2330,7 @@ index d2d8f2e..5805a30 100644
    if (anonymous_namespace)
      {
        /* Symbols defined in anonymous namespaces have external linkage
-@@ -408,12 +524,11 @@ lookup_symbol_file (const char *name,
+@@ -408,12 +554,11 @@ lookup_symbol_file (const char *name,
        const struct block *global_block = block_global_block (block);
        
        if (global_block != NULL)
@@ -2315,7 +2345,7 @@ index d2d8f2e..5805a30 100644
      }
  
    if (sym != NULL)
-@@ -434,6 +549,7 @@ lookup_symbol_file (const char *name,
+@@ -434,6 +579,7 @@ lookup_symbol_file (const char *name,
        sym = lookup_possible_namespace_symbol (name);
        if (sym != NULL)
  	return sym;
@@ -2323,7 +2353,7 @@ index d2d8f2e..5805a30 100644
      }
  
    return NULL;
-@@ -461,9 +577,8 @@ cp_lookup_nested_type (struct type *parent_type,
+@@ -461,9 +607,8 @@ cp_lookup_nested_type (struct type *parent_type,
  	   lookup_symbol_namespace works when looking them up.  */
  
  	const char *parent_name = TYPE_TAG_NAME (parent_type);
@@ -2334,7 +2364,7 @@ index d2d8f2e..5805a30 100644
  							 block,
  							 VAR_DOMAIN);
  	if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
-@@ -709,7 +824,7 @@ check_one_possible_namespace_symbol (const char *name, int len,
+@@ -709,7 +854,7 @@ check_one_possible_namespace_symbol (const char *name, int len,
  
    memcpy (name_copy, name, len);
    name_copy[len] = '\0';
@@ -2343,7 +2373,7 @@ index d2d8f2e..5805a30 100644
  
    if (sym == NULL)
      {
-@@ -749,7 +864,7 @@ lookup_possible_namespace_symbol (const char *name)
+@@ -749,7 +894,7 @@ lookup_possible_namespace_symbol (const char *name)
        struct symbol *sym;
  
        sym = lookup_block_symbol (get_possible_namespace_block (objfile),
@@ -2474,7 +2504,7 @@ index f12d785..ca10007 100644
  _initialize_cp_support (void)
  {
 diff --git a/gdb/cp-support.h b/gdb/cp-support.h
-index b5a5c5f..022f102 100644
+index b5a5c5f..3f48f98 100644
 --- a/gdb/cp-support.h
 +++ b/gdb/cp-support.h
 @@ -38,15 +38,33 @@ struct demangle_component;
@@ -2547,7 +2577,7 @@ index b5a5c5f..022f102 100644
  					  struct using_direct *next);
  
  extern void cp_initialize_namespace (void);
-@@ -97,15 +124,19 @@ extern void cp_set_block_scope (const struct symbol *symbol,
+@@ -97,15 +124,20 @@ extern void cp_set_block_scope (const struct symbol *symbol,
  extern void cp_scan_for_anonymous_namespaces (const struct symbol *symbol);
  
  extern struct symbol *cp_lookup_symbol_nonlocal (const char *name,
@@ -2559,7 +2589,8 @@ index b5a5c5f..022f102 100644
 +                                         const char *name,
 +                                         const struct block *block,
 +                                         const domain_enum domain,
-+                                         int declaration_only);
++                                         int declaration_only,
++                                         int search_parents);
 +
  extern struct symbol *cp_lookup_symbol_namespace (const char *namespace,
 -						  const char *name,
@@ -3458,7 +3489,7 @@ index 4984f31..fcf1b5d 100644
  This observer is used for internal testing.  Do not use.  
  See testsuite/gdb.gdb/observer.exp.
 diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
-index 427f58f..392a1b4 100644
+index 427f58f..e66f007 100644
 --- a/gdb/dwarf2-frame.c
 +++ b/gdb/dwarf2-frame.c
 @@ -38,6 +38,7 @@
@@ -3483,7 +3514,7 @@ index 427f58f..392a1b4 100644
  no_get_tls_address (void *baton, CORE_ADDR offset)
  {
    internal_error (__FILE__, __LINE__,
-@@ -363,14 +371,16 @@ execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size,
+@@ -363,14 +371,22 @@ execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size,
    ctx->read_reg = read_reg;
    ctx->read_mem = read_mem;
    ctx->get_frame_base = no_get_frame_base;
@@ -3497,11 +3528,17 @@ index 427f58f..392a1b4 100644
 -  if (ctx->in_reg)
 +  if (ctx->location == DWARF_VALUE_REGISTER)
      result = read_reg (this_frame, result);
-+  /* FIXME */
++  else if (ctx->location != DWARF_VALUE_MEMORY)
++    {
++      /* This is actually invalid DWARF, but if we ever do run across
++	 it somehow, we might as well support it.  So, instead, report
++	 it as unimplemented.  */
++      error (_("Not implemented: computing unwound register using explicit value operator"));
++    }
  
    do_cleanups (old_chain);
  
-@@ -1250,6 +1260,16 @@ dwarf2_frame_base_sniffer (struct frame_info *this_frame)
+@@ -1250,6 +1266,16 @@ dwarf2_frame_base_sniffer (struct frame_info *this_frame)
  
    return NULL;
  }
@@ -3518,7 +3555,7 @@ index 427f58f..392a1b4 100644
  \f
  const struct objfile_data *dwarf2_frame_objfile_data;
  
-@@ -1539,6 +1559,14 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
+@@ -1539,6 +1565,14 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
        CORE_ADDR offset;
        CORE_ADDR seek_pc;
  
@@ -3547,7 +3584,7 @@ index b203661..dd03d59 100644
 +
  #endif /* dwarf2-frame.h */
 diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
-index 2721065..228eae7 100644
+index 2721065..0644b46 100644
 --- a/gdb/dwarf2expr.c
 +++ b/gdb/dwarf2expr.c
 @@ -125,8 +125,7 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
@@ -3578,7 +3615,7 @@ index 2721065..228eae7 100644
  }
  
  /* Evaluate the expression at ADDR (LEN bytes long) using the context
-@@ -287,6 +292,21 @@ signed_address_type (struct gdbarch *gdbarch, int addr_size)
+@@ -287,6 +292,23 @@ signed_address_type (struct gdbarch *gdbarch, int addr_size)
      }
  }
  \f
@@ -3589,7 +3626,9 @@ index 2721065..228eae7 100644
 +static void
 +require_composition (gdb_byte *op_ptr, gdb_byte *op_end, const char *op_name)
 +{
-+  /* FIXME: DW_OP_GNU_uninit?  */
++  /* It seems like DW_OP_GNU_uninit should be handled here.  However,
++     it doesn't seem to make sense for DW_OP_*_value, and it was not
++     checked at the other place that this function is called.  */
 +  if (op_ptr != op_end && *op_ptr != DW_OP_piece && *op_ptr != DW_OP_bit_piece)
 +    error (_("DWARF-2 expression error: `%s' operations must be "
 +	     "used either alone or in conjuction with DW_OP_piece "
@@ -3600,7 +3639,7 @@ index 2721065..228eae7 100644
  /* The engine for the expression evaluator.  Using the context in CTX,
     evaluate the expression between OP_PTR and OP_END.  */
  
-@@ -295,8 +315,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -295,8 +317,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  		  gdb_byte *op_ptr, gdb_byte *op_end)
  {
    enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
@@ -3610,7 +3649,7 @@ index 2721065..228eae7 100644
    ctx->initialized = 1;  /* Default is initialized.  */
  
    if (ctx->recursion_depth > ctx->max_recursion_depth)
-@@ -436,20 +455,36 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -436,20 +457,36 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  		   "used either alone or in conjuction with DW_OP_piece."));
  
  	  result = op - DW_OP_reg0;
@@ -3635,7 +3674,7 @@ index 2721065..228eae7 100644
 +	  {
 +	    ULONGEST len;
 +	    op_ptr = read_uleb128 (op_ptr, op_end, &len);
-+	    if (op_ptr + len >= op_end)
++	    if (op_ptr + len > op_end)
 +	      error (_("DW_OP_implicit_value: too few bytes available."));
 +	    ctx->len = len;
 +	    ctx->data = op_ptr;
@@ -3653,14 +3692,17 @@ index 2721065..228eae7 100644
  	case DW_OP_breg0:
  	case DW_OP_breg1:
  	case DW_OP_breg2:
-@@ -514,11 +549,12 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -513,12 +550,15 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+                specific this_base method.  */
  	    (ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
  	    dwarf_expr_eval (ctx, datastart, datalen);
++	    if (ctx->location == DWARF_VALUE_LITERAL
++		|| ctx->location == DWARF_VALUE_STACK)
++	      error (_("Not implemented: computing frame base using explicit value operator"));
  	    result = dwarf_expr_fetch (ctx, 0);
 -	    if (ctx->in_reg)
 +	    if (ctx->location == DWARF_VALUE_REGISTER)
  	      result = (ctx->read_reg) (ctx->baton, result);
-+	    /* FIXME: other DWARF_VALUE_*?? */
  	    result = result + offset;
  	    ctx->stack_len = before_stack_len;
 -	    ctx->in_reg = 0;
@@ -3668,7 +3710,7 @@ index 2721065..228eae7 100644
  	  }
  	  break;
  	case DW_OP_dup:
-@@ -716,6 +752,10 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -716,6 +756,10 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  	  }
  	  break;
  
@@ -3679,7 +3721,7 @@ index 2721065..228eae7 100644
  	case DW_OP_GNU_push_tls_address:
  	  /* Variable is at a constant offset in the thread-local
  	  storage block into the objfile for the current thread and
-@@ -754,12 +794,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -754,12 +798,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  
              /* Record the piece.  */
              op_ptr = read_uleb128 (op_ptr, op_end, &size);
@@ -3698,7 +3740,7 @@ index 2721065..228eae7 100644
            }
            goto no_push;
  
-@@ -771,6 +812,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -771,6 +816,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  	  ctx->initialized = 0;
  	  goto no_push;
  
@@ -18820,7 +18862,7 @@ index eb35369..dfd8c8c 100644
  	  {
  	    printf_filtered ("Global symbol `");
 diff --git a/gdb/symtab.c b/gdb/symtab.c
-index c88156a..9c102c0 100644
+index c88156a..75b907f 100644
 --- a/gdb/symtab.c
 +++ b/gdb/symtab.c
 @@ -42,6 +42,7 @@
@@ -19128,7 +19170,7 @@ index c88156a..9c102c0 100644
 +      if (language == language_cplus )
 +        {
 +          sym = cp_lookup_symbol_imports (block_scope (block_iterator), name,
-+                                          block_iterator, domain, 1);
++                                          block_iterator, domain, 1, 1);
 +
 +          if (sym != NULL)
 +            return sym;
@@ -22507,6 +22549,129 @@ index 0000000..ebc898f
 +
 +gdb_test "print xx" "= 999"
 +
+diff --git a/gdb/testsuite/gdb.cp/namespace-stress.cc b/gdb/testsuite/gdb.cp/namespace-stress.cc
+new file mode 100644
+index 0000000..f34083e
+--- /dev/null
++++ b/gdb/testsuite/gdb.cp/namespace-stress.cc
+@@ -0,0 +1,60 @@
++
++namespace A{ int x; }
++namespace B{ int x; }
++namespace C{ int x; }
++namespace D{ int x; }
++namespace E{ int x; }
++namespace F{ int x; }
++namespace G{ int x; }
++namespace H{ int x; }
++namespace I{ int x; }
++namespace J{ int x; }
++namespace K{ int x; }
++namespace L{ int x; }
++namespace M{ int x; }
++namespace N{ int x; }
++namespace O{ int x; }
++namespace P{ int x; }
++namespace Q{ int x; }
++namespace R{ int x; }
++namespace S{ int x; }
++namespace T{ int x; }
++namespace U{ int x; }
++namespace V{ int x; }
++namespace W{ int x; }
++namespace X{ int x; }
++namespace Y{ int x; }
++namespace Z{ int x; }
++
++
++int main(){
++
++  using namespace A;
++  using namespace B;
++  using namespace C;
++  using namespace D;
++  using namespace E;
++  using namespace F;
++  using namespace G;
++  using namespace H;
++  using namespace I;
++  using namespace J;
++  using namespace K;
++  using namespace L;
++  using namespace M;
++  using namespace N;
++  using namespace O;
++  using namespace P;
++  using namespace Q;
++  using namespace R;
++  using namespace S;
++  using namespace T;
++  using namespace U;
++  using namespace V;
++  using namespace W;
++  using namespace X;
++  using namespace Y;
++  using namespace Z;
++
++  return 0;
++}
+\ No newline at end of file
+diff --git a/gdb/testsuite/gdb.cp/namespace-stress.exp b/gdb/testsuite/gdb.cp/namespace-stress.exp
+new file mode 100644
+index 0000000..1806523
+--- /dev/null
++++ b/gdb/testsuite/gdb.cp/namespace-stress.exp
+@@ -0,0 +1,50 @@
++# Copyright 2008 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++if $tracelevel then {
++    strace $tracelevel
++}
++
++set prms_id 0
++set bug_id 0
++
++set testfile namespace-stress
++set srcfile ${testfile}.cc
++set binfile ${objdir}/${subdir}/${testfile}
++if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
++    untested "Couldn't compile test program"
++    return -1
++}
++
++if [get_compiler_info ${binfile}] {
++    return -1;
++}
++
++# Get things started.
++
++gdb_exit
++gdb_start
++gdb_reinitialize_dir $srcdir/$subdir
++gdb_load ${binfile}
++
++if ![runto_main] then {
++    perror "couldn't run to breakpoint main"
++    continue
++}
++
++############################################
++# Test that the search can fail efficiently 
++
++gdb_test "print y" "No symbol \"y\" in current context."
 diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc
 index 4786fd5..8ff5622 100644
 --- a/gdb/testsuite/gdb.cp/namespace-using.cc
@@ -25322,6 +25487,37 @@ index 4b02e50..faa9172 100644
  	"get children of anone"
  
  
+diff --git a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
+index 05d46fa..4b95674 100644
+--- a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
++++ b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
+@@ -72,7 +72,7 @@ mi_runto main
+ 
+ # Check local variable is "invalid".
+ mi_gdb_test "-var-update linteger" \
+-	"\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\",has_more=\"0\"\}\\\]" \
+ 	"linteger not anymore in scope due to binary changes"
+ 
+ mi_gdb_test "-var-info-type linteger" \
+@@ -97,7 +97,7 @@ mi_delete_breakpoints
+ mi_gdb_load ${binfile2}
+ # Check local variable are "invalid"
+ mi_gdb_test "-var-update linteger" \
+-	"\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\",has_more=\"0\"\}\\\]" \
+ 	"linteger not valid anymore due to binary changes"
+ 
+ mi_gdb_test "-var-info-type linteger" \
+@@ -106,7 +106,7 @@ mi_gdb_test "-var-info-type linteger" \
+ 
+ # Check global variable are still correct.
+ mi_gdb_test "-var-update global_simple" \
+-	"\\^done,changelist=\\\[\{name=\"global_simple\",in_scope=\"invalid\"\}\\\]" \
++	"\\^done,changelist=\\\[\{name=\"global_simple\",in_scope=\"invalid\",has_more=\"0\"\}\\\]" \
+ 	"global_simple not anymore in scope due to binary changes"
+ 
+ mi_gdb_test "-var-info-type global_simple" \
 diff --git a/gdb/testsuite/gdb.mi/mi2-var-block.exp b/gdb/testsuite/gdb.mi/mi2-var-block.exp
 index 6bcfea3..9b3d08f 100644
 --- a/gdb/testsuite/gdb.mi/mi2-var-block.exp
@@ -26342,10 +26538,10 @@ index 0000000..d444554
 +gdb_test "python print t0" "\\<gdb.InferiorThread object at 0x\[\[:xdigit:\]\]+>" "verify InferiorThread object"
 +gdb_test "python print 'result =', t0.num" " = \[0-9\]+" "test Inferior.num"
 diff --git a/gdb/testsuite/gdb.python/python-mi.exp b/gdb/testsuite/gdb.python/python-mi.exp
-index 3258810..018c6a2 100644
+index 3258810..7791775 100644
 --- a/gdb/testsuite/gdb.python/python-mi.exp
 +++ b/gdb/testsuite/gdb.python/python-mi.exp
-@@ -48,23 +48,42 @@ mi_gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" ""
+@@ -48,23 +48,53 @@ mi_gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" ""
  mi_continue_to_line [gdb_get_line_number {MI breakpoint here} ${testfile}.c] \
    "step to breakpoint"
  
@@ -26363,6 +26559,17 @@ index 3258810..018c6a2 100644
 +
 +mi_gdb_test "-enable-pretty-printing" ""
 +
++mi_create_varobj_checked string string_1 \
++    "struct string_repr" \
++    "create string_1 varobj"
++
++mi_gdb_test "-data-evaluate-expression \"string_1 = string_2\"" ".*" \
++    "assign string_1 from string_2"
++
++mi_gdb_test "-var-update string" \
++    "\\^done,changelist=\\\[{name=\"string\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"}\\\]" \
++    "update string varobj after assignment"
++
 +mi_create_dynamic_varobj container c \
 +  "create container varobj"
  
@@ -26396,7 +26603,7 @@ index 3258810..018c6a2 100644
  
  mi_gdb_test "-var-set-visualizer container None" \
    "\\^done" \
-@@ -78,19 +97,88 @@ mi_gdb_test "-var-set-visualizer container gdb.default_visualizer" \
+@@ -78,19 +108,88 @@ mi_gdb_test "-var-set-visualizer container gdb.default_visualizer" \
    "\\^done" \
    "choose default visualizer"
  
@@ -26492,7 +26699,7 @@ index 3258810..018c6a2 100644
  mi_continue_to_line \
      [gdb_get_line_number {Another MI breakpoint} ${testfile}.c] \
 diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c
-index 3cafc48..5fbd534 100644
+index 3cafc48..adf66b5 100644
 --- a/gdb/testsuite/gdb.python/python-prettyprint.c
 +++ b/gdb/testsuite/gdb.python/python-prettyprint.c
 @@ -15,6 +15,8 @@
@@ -26504,7 +26711,7 @@ index 3cafc48..5fbd534 100644
  struct s
  {
    int a;
-@@ -148,6 +150,11 @@ void do_nothing(void)
+@@ -148,6 +150,14 @@ void do_nothing(void)
    c = 23;			/* Another MI breakpoint */
  }
  
@@ -26513,10 +26720,13 @@ index 3cafc48..5fbd534 100644
 +  char *s;
 +};
 +
++struct string_repr string_1 = { { "one" } };
++struct string_repr string_2 = { { "two" } };
++
  int
  main ()
  {
-@@ -155,11 +162,15 @@ main ()
+@@ -155,11 +165,15 @@ main ()
    struct ss  ssa[2];
    string x = make_string ("this is x");
    zzz_type c = make_container ("container");
@@ -26532,7 +26742,7 @@ index 3cafc48..5fbd534 100644
  
    struct ns  ns;
    ns.null_str = "embedded\0null\0string";
-@@ -193,6 +204,11 @@ main ()
+@@ -193,6 +207,11 @@ main ()
    add_item (&c, 72);
  
  #ifdef MI
@@ -29116,7 +29326,7 @@ index 6f6b756..b9ca650 100644
  /* User function handler.  */
  
 diff --git a/gdb/varobj.c b/gdb/varobj.c
-index fbe8ff8..a730095 100644
+index fbe8ff8..490ca33 100644
 --- a/gdb/varobj.c
 +++ b/gdb/varobj.c
 @@ -26,9 +26,12 @@
@@ -29758,21 +29968,36 @@ index fbe8ff8..a730095 100644
  	{
  	  /* Try to compare the values.  That requires that both
  	     values are non-lazy.  */
-@@ -1310,6 +1561,8 @@ install_new_value (struct varobj *var, struct value *value, int initial)
+@@ -1310,74 +1561,53 @@ install_new_value (struct varobj *var, struct value *value, int initial)
    if (var->value != NULL && var->value != value)
      value_free (var->value);
    var->value = value;
+-  if (var->print_value)
+-    xfree (var->print_value);
+-  var->print_value = print_value;
 +  if (value != NULL)
 +    value_incref (value);
-   if (var->print_value)
-     xfree (var->print_value);
-   var->print_value = print_value;
-@@ -1319,65 +1572,32 @@ install_new_value (struct varobj *var, struct value *value, int initial)
+   if (value && value_lazy (value) && intentionally_not_fetched)
+     var->not_fetched = 1;
+   else
      var->not_fetched = 0;
    var->updated = 0;
  
 +  install_new_value_visualizer (var);
 +
++  /* If we installed a pretty-printer, re-compare the printed version
++     to see if the variable changed.  */
++  if (var->pretty_printer)
++    {
++      xfree (print_value);
++      print_value = value_get_print_value (var->value, var->format, var);
++      if (!var->print_value || strcmp (var->print_value, print_value) != 0)
++	changed = 1;
++    }
++  if (var->print_value)
++    xfree (var->print_value);
++  var->print_value = print_value;
++
    gdb_assert (!var->value || value_type (var->value));
  
    return changed;
@@ -29850,7 +30075,7 @@ index fbe8ff8..a730095 100644
  }
  
  void 
-@@ -1395,31 +1615,19 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer)
+@@ -1395,31 +1625,19 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer)
    make_cleanup_py_decref (globals);
  
    constructor = PyRun_String (visualizer, Py_eval_input, globals, globals);
@@ -29888,7 +30113,7 @@ index fbe8ff8..a730095 100644
  
    do_cleanups (back_to);
  #else
-@@ -1530,44 +1738,60 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
+@@ -1530,44 +1748,63 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
  
        /* We probably should not get children of a varobj that has a
  	 pretty-printer, but for which -var-list-children was never
@@ -29918,11 +30143,14 @@ index fbe8ff8..a730095 100644
 +		 it as unchanged -- presumably, such varobj is not yet
 +		 expanded in the UI, so we need not bother getting
 +		 it.  */
-+	      if (varobj_has_more (v, 0))
-+		continue;
++	      if (!varobj_has_more (v, 0))
++		{
++		  update_dynamic_varobj_children (v, NULL, NULL, &dummy, 0, 0);
++		  if (varobj_has_more (v, 0))
++		    r.changed = 1;
++		}
 +
-+	      update_dynamic_varobj_children (v, NULL, NULL, &dummy, 0, 0);
-+	      if (varobj_has_more (v, 0))
++	      if (r.changed)
 +		VEC_safe_push (varobj_update_result, result, &r);
 +
 +	      continue;
@@ -29967,7 +30195,7 @@ index fbe8ff8..a730095 100644
  	      continue;
  	    }
  	}
-@@ -1855,7 +2079,12 @@ new_variable (void)
+@@ -1855,7 +2092,12 @@ new_variable (void)
    var->frozen = 0;
    var->not_fetched = 0;
    var->children_requested = 0;
@@ -29980,7 +30208,7 @@ index fbe8ff8..a730095 100644
  
    return var;
  }
-@@ -1885,7 +2114,10 @@ free_variable (struct varobj *var)
+@@ -1885,7 +2127,10 @@ free_variable (struct varobj *var)
    if (var->pretty_printer)
      {
        struct cleanup *cleanup = varobj_ensure_python_env (var);
@@ -29992,7 +30220,7 @@ index fbe8ff8..a730095 100644
        do_cleanups (cleanup);
      }
  #endif
-@@ -1918,6 +2150,18 @@ make_cleanup_free_variable (struct varobj *var)
+@@ -1918,6 +2163,18 @@ make_cleanup_free_variable (struct varobj *var)
    return make_cleanup (do_free_variable_cleanup, var);
  }
  
@@ -30011,7 +30239,7 @@ index fbe8ff8..a730095 100644
  /* This returns the type of the variable. It also skips past typedefs
     to return the real type of the variable.
  
-@@ -2132,6 +2376,8 @@ value_of_root (struct varobj **var_handle, int *type_changed)
+@@ -2132,6 +2389,8 @@ value_of_root (struct varobj **var_handle, int *type_changed)
        else
  	{
  	  tmp_var->obj_name = xstrdup (var->obj_name);
@@ -30020,7 +30248,7 @@ index fbe8ff8..a730095 100644
  	  varobj_delete (var, NULL, 0);
  
  	  install_variable (tmp_var);
-@@ -2166,7 +2412,11 @@ static char *
+@@ -2166,7 +2425,11 @@ static char *
  my_value_of_variable (struct varobj *var, enum varobj_display_formats format)
  {
    if (var->root->is_valid)
@@ -30033,7 +30261,7 @@ index fbe8ff8..a730095 100644
    else
      return NULL;
  }
-@@ -2189,43 +2439,51 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
+@@ -2189,43 +2452,51 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
      struct cleanup *back_to = varobj_ensure_python_env (var);
      PyObject *value_formatter = var->pretty_printer;
  
@@ -30116,7 +30344,7 @@ index fbe8ff8..a730095 100644
        }
      do_cleanups (back_to);
    }
-@@ -2954,10 +3212,7 @@ cplus_describe_child (struct varobj *parent, int index,
+@@ -2954,10 +3225,7 @@ cplus_describe_child (struct varobj *parent, int index,
  	    *cname = xstrdup (TYPE_FIELD_NAME (type, index));
  
  	  if (cvalue && value)
@@ -30128,7 +30356,7 @@ index fbe8ff8..a730095 100644
  
  	  if (ctype)
  	    {
-@@ -3163,6 +3418,19 @@ java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
+@@ -3163,6 +3431,19 @@ java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
    return cplus_value_of_variable (var, format);
  }
  
@@ -30148,7 +30376,7 @@ index fbe8ff8..a730095 100644
  /* Iterate all the existing _root_ VAROBJs and call the FUNC callback for them
     with an arbitrary caller supplied DATA pointer.  */
  
-@@ -3180,6 +3448,43 @@ all_root_varobjs (void (*func) (struct varobj *var, void *data), void *data)
+@@ -3180,6 +3461,43 @@ all_root_varobjs (void (*func) (struct varobj *var, void *data), void *data)
        (*func) (var_root->rootvar, data);
      }
  }

diff --git a/gdb.spec b/gdb.spec
index 3d6d104..0ebb2ce 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -14,7 +14,7 @@ Version: 6.8.50.20090818
 
 # The release always contains a leading reserved number, start it at 1.
 # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
-Release: 7%{?_with_upstream:.upstream}%{?dist}
+Release: 8%{?_with_upstream:.upstream}%{?dist}
 
 License: GPLv3+
 Group: Development/Debuggers
@@ -829,6 +829,11 @@ fi
 %endif
 
 %changelog
+* Thu Sep  3 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20090818-8
+- archer-jankratochvil-fedora12 commit: a081d2f12945e9468edd5f4341d3e945bd0fefe9
+  - [expr] Fix too slow lookups in large C++ programs (Sami Wagiaalla).
+  - [python] Fix varobj changed values reporting (GDB PR 10584, Tom Tromey).
+
 * Tue Sep  1 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20090818-7
 - archer-jankratochvil-fedora12 commit: d25596676e8811b03f8c9aba6bbd04ebaa9ff5db
   - [call-frame-cfa] Fix parsing CFA-relative frames (BZ 516627, Tom Tromey).

^ permalink raw reply related	[flat|nested] 5+ messages in thread
* [rpms/gdb] gdb-17.2-rebase-f44: - archer-jankratochvil-fedora12 commit:
@ 2026-06-27 23:54 Jan Kratochvil
  0 siblings, 0 replies; 5+ messages in thread
From: Jan Kratochvil @ 2026-06-27 23:54 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/gdb
            Branch : gdb-17.2-rebase-f44
            Commit : 6370c17fdf8f9ed891910ec6e90bdf99e7215f72
            Author : Jan Kratochvil <jkratoch@fedoraproject.org>
            Date   : 2009-08-18T19:37:35+00:00
            Stats  : +1853/-16 in 2 file(s)
            URL    : https://src.fedoraproject.org/rpms/gdb/c/6370c17fdf8f9ed891910ec6e90bdf99e7215f72?branch=gdb-17.2-rebase-f44

            Log:
            - archer-jankratochvil-fedora12 commit:
    850e3cb38a25cb7fdfa4cef667626ffbde51bcac
- Fix the hardware watchpoints.

---
diff --git a/gdb-archer.patch b/gdb-archer.patch
index 15cd7ed..08ca4ed 100644
--- a/gdb-archer.patch
+++ b/gdb-archer.patch
@@ -2,7 +2,7 @@ http://sourceware.org/gdb/wiki/ProjectArcher
 http://sourceware.org/gdb/wiki/ArcherBranchManagement
 
 GIT snapshot:
-commit 5e0d1cc74f119391a2c3ae25ef5749fc28674f06
+commit 850e3cb38a25cb7fdfa4cef667626ffbde51bcac
 
 branch `archer' - the merge of branches:
 archer-tromey-call-frame-cfa
@@ -290,6 +290,102 @@ index 9b5d2c6..61676a9 100644
    ada_op_name,
    ada_dump_subexp_body,
    ada_evaluate_subexp
+diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
+index 7d8461c..a6d35d7 100644
+--- a/gdb/amd64-linux-nat.c
++++ b/gdb/amd64-linux-nat.c
+@@ -270,6 +270,8 @@ amd64_linux_dr_get (ptid_t ptid, int regnum)
+   return value;
+ }
+ 
++/* Set debug register REGNUM to VALUE in only the one LWP of PTID.  */
++
+ static void
+ amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
+ {
+@@ -286,6 +288,8 @@ amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
+     perror_with_name (_("Couldn't write debug register"));
+ }
+ 
++/* Set DR_CONTROL to ADDR in all LWPs of LWP_LIST.  */
++
+ static void
+ amd64_linux_dr_set_control (unsigned long control)
+ {
+@@ -297,6 +301,8 @@ amd64_linux_dr_set_control (unsigned long control)
+     amd64_linux_dr_set (ptid, DR_CONTROL, control);
+ }
+ 
++/* Set address REGNUM (zero based) to ADDR in all LWPs of LWP_LIST.  */
++
+ static void
+ amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
+ {
+@@ -310,18 +316,55 @@ amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
+     amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
+ }
+ 
++/* Set address REGNUM (zero based) to zero in all LWPs of LWP_LIST.  */
++
+ static void
+ amd64_linux_dr_reset_addr (int regnum)
+ {
+   amd64_linux_dr_set_addr (regnum, 0);
+ }
+ 
++/* Get DR_STATUS from only the one LWP of INFERIOR_PTID.  */
++
+ static unsigned long
+ amd64_linux_dr_get_status (void)
+ {
+   return amd64_linux_dr_get (inferior_ptid, DR_STATUS);
+ }
+ 
++/* Unset VALUE bits in DR_STATUS in all LWPs of LWP_LIST.  */
++
++static void
++amd64_linux_dr_unset_status (unsigned long mask)
++{
++  struct lwp_info *lp;
++  ptid_t ptid;
++
++  ALL_LWPS (lp, ptid)
++    {
++      unsigned long value;
++      
++      value = amd64_linux_dr_get (ptid, DR_STATUS);
++      value &= ~mask;
++      amd64_linux_dr_set (ptid, DR_STATUS, value);
++    }
++}
++
++/* See i386_dr_low_type.detach.  Do not use wrappers amd64_linux_dr_set_control
++   or amd64_linux_dr_reset_addr as they would modify the register cache
++   (amd64_linux_dr).  */
++
++static void
++amd64_linux_dr_detach (void)
++{
++  int regnum;
++
++  amd64_linux_dr_set (inferior_ptid, DR_CONTROL, 0);
++  amd64_linux_dr_unset_status (~0UL);
++  for (regnum = DR_FIRSTADDR; regnum <= DR_LASTADDR; regnum++)
++    amd64_linux_dr_set (inferior_ptid, regnum, 0);
++}
++
+ static void
+ amd64_linux_new_thread (ptid_t ptid)
+ {
+@@ -672,6 +715,8 @@ _initialize_amd64_linux_nat (void)
+   i386_dr_low.set_addr = amd64_linux_dr_set_addr;
+   i386_dr_low.reset_addr = amd64_linux_dr_reset_addr;
+   i386_dr_low.get_status = amd64_linux_dr_get_status;
++  i386_dr_low.unset_status = amd64_linux_dr_unset_status;
++  i386_dr_low.detach = amd64_linux_dr_detach;
+   i386_set_debug_register_length (8);
+ 
+   /* Override the GNU/Linux inferior startup hook.  */
 diff --git a/gdb/block.c b/gdb/block.c
 index 1889ecd..37fa342 100644
 --- a/gdb/block.c
@@ -368,7 +464,7 @@ index 53e7371..d373f8a 100644
 +
  #endif /* BLOCK_H */
 diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
-index f3940e1..70222a4 100644
+index f3940e1..2349fbc 100644
 --- a/gdb/breakpoint.c
 +++ b/gdb/breakpoint.c
 @@ -59,6 +59,7 @@
@@ -477,7 +573,97 @@ index f3940e1..70222a4 100644
  	return;
        }
  
-@@ -8843,6 +8856,22 @@ all_tracepoints ()
+@@ -1690,6 +1703,7 @@ detach_breakpoints (int pid)
+     if (b->inserted)
+       val |= remove_breakpoint (b, mark_inserted);
+   }
++  val |= target_detach_watchpoints ();
+   do_cleanups (old_chain);
+   return val;
+ }
+@@ -1782,12 +1796,14 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is)
+ 	return val;
+       b->inserted = (is == mark_inserted);
+     }
+-  else if (b->loc_type == bp_loc_hardware_watchpoint)
++  /* bp_loc_hardware_watchpoint with mark_inserted is being handled by
++     target_detach_watchpoints.  */
++  else if (b->loc_type == bp_loc_hardware_watchpoint && is == mark_uninserted)
+     {
+       struct value *v;
+       struct value *n;
+ 
+-      b->inserted = (is == mark_inserted);
++      b->inserted = 0;
+       val = target_remove_watchpoint (b->address, b->length, 
+ 				      b->watchpoint_type);
+ 
+@@ -2961,8 +2977,12 @@ bpstat_check_location (const struct bp_location *bl, CORE_ADDR bp_addr)
+ 
+ /* If BS refers to a watchpoint, determine if the watched values
+    has actually changed, and we should stop.  If not, set BS->stop
+-   to 0.  */
+-static void
++   to 0.
++   Return 0 for watchpoints which could not be the cause of this trap.
++   In such case PRINT_IT will be print_it_noop and STOP will be 0.
++   Otherwise return 1 but in such case it is not guaranteed whether this
++   breakpoint did or did not trigger this trap.  */
++static int
+ bpstat_check_watchpoint (bpstat bs)
+ {
+   const struct bp_location *bl = bs->breakpoint_at;
+@@ -3051,8 +3071,10 @@ bpstat_check_watchpoint (bpstat bs)
+ 	     anything for this watchpoint.  */
+ 	  bs->print_it = print_it_noop;
+ 	  bs->stop = 0;
++	  return 0;
+ 	}
+     }
++  return 1;
+ }
+ 
+ 
+@@ -3156,6 +3178,8 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
+ 
+   ALL_BP_LOCATIONS (bl)
+   {
++    bpstat bs_prev = bs;
++
+     b = bl->owner;
+     gdb_assert (b);
+     if (!breakpoint_enabled (b) && b->enable_state != bp_permanent)
+@@ -3176,6 +3200,7 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
+     /* Come here if it's a watchpoint, or if the break address matches */
+ 
+     bs = bpstat_alloc (bl, bs);	/* Alloc a bpstat to explain stop */
++    gdb_assert (bs_prev->next == bs);
+ 
+     /* Assume we stop.  Should we find watchpoint that is not actually
+        triggered, or if condition of breakpoint is false, we'll reset
+@@ -3183,9 +3208,18 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
+     bs->stop = 1;
+     bs->print = 1;
+ 
+-    bpstat_check_watchpoint (bs);
+-    if (!bs->stop)
+-      continue;
++    if (!bpstat_check_watchpoint (bs))
++      {
++	/* Ensure bpstat_explains_signal stays false if this BL could not be
++	   the cause of this trap.  */
++
++	gdb_assert (bs->print_it == print_it_noop);
++	gdb_assert (!bs->stop);
++	xfree (bs);
++	bs = bs_prev;
++	bs->next = NULL;
++	continue;
++      }
+ 
+     if (b->type == bp_thread_event || b->type == bp_overlay_event
+ 	|| b->type == bp_longjmp_master)
+@@ -8843,6 +8877,22 @@ all_tracepoints ()
    return tp_vec;
  }
  
@@ -500,7 +686,7 @@ index f3940e1..70222a4 100644
  \f
  /* This help string is used for the break, hbreak, tbreak and thbreak commands.
     It is defined as a macro to prevent duplication.
-@@ -9345,4 +9374,5 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
+@@ -9345,4 +9395,5 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
    automatic_hardware_breakpoints = 1;
  
    observer_attach_about_to_proceed (breakpoint_about_to_proceed);
@@ -10362,6 +10548,274 @@ index 5e55573..5439aba 100644
  # This Makefile.in is free software; the Free Software Foundation
  # gives unlimited permission to copy and/or distribute it,
  # with or without modifications, as long as this notice is preserved.
+diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
+index 991b27f..411b41b 100644
+--- a/gdb/i386-linux-nat.c
++++ b/gdb/i386-linux-nat.c
+@@ -586,6 +586,8 @@ i386_linux_store_inferior_registers (struct target_ops *ops,
+ 
+ static unsigned long i386_linux_dr[DR_CONTROL + 1];
+ 
++/* Get debug register REGNUM value from only the one LWP of PTID.  */
++
+ static unsigned long
+ i386_linux_dr_get (ptid_t ptid, int regnum)
+ {
+@@ -614,6 +616,8 @@ i386_linux_dr_get (ptid_t ptid, int regnum)
+   return value;
+ }
+ 
++/* Set debug register REGNUM to VALUE in only the one LWP of PTID.  */
++
+ static void
+ i386_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
+ {
+@@ -630,6 +634,8 @@ i386_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
+     perror_with_name (_("Couldn't write debug register"));
+ }
+ 
++/* Set DR_CONTROL to ADDR in all LWPs of LWP_LIST.  */
++
+ static void
+ i386_linux_dr_set_control (unsigned long control)
+ {
+@@ -641,6 +647,8 @@ i386_linux_dr_set_control (unsigned long control)
+     i386_linux_dr_set (ptid, DR_CONTROL, control);
+ }
+ 
++/* Set address REGNUM (zero based) to ADDR in all LWPs of LWP_LIST.  */
++
+ static void
+ i386_linux_dr_set_addr (int regnum, CORE_ADDR addr)
+ {
+@@ -654,18 +662,55 @@ i386_linux_dr_set_addr (int regnum, CORE_ADDR addr)
+     i386_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
+ }
+ 
++/* Set address REGNUM (zero based) to zero in all LWPs of LWP_LIST.  */
++
+ static void
+ i386_linux_dr_reset_addr (int regnum)
+ {
+   i386_linux_dr_set_addr (regnum, 0);
+ }
+ 
++/* Get DR_STATUS from only the one LWP of INFERIOR_PTID.  */
++
+ static unsigned long
+ i386_linux_dr_get_status (void)
+ {
+   return i386_linux_dr_get (inferior_ptid, DR_STATUS);
+ }
+ 
++/* Unset VALUE bits in DR_STATUS in all LWPs of LWP_LIST.  */
++
++static void
++i386_linux_dr_unset_status (unsigned long mask)
++{
++  struct lwp_info *lp;
++  ptid_t ptid;
++
++  ALL_LWPS (lp, ptid)
++    {
++      unsigned long value;
++      
++      value = i386_linux_dr_get (ptid, DR_STATUS);
++      value &= ~mask;
++      i386_linux_dr_set (ptid, DR_STATUS, value);
++    }
++}
++
++/* See i386_dr_low_type.detach.  Do not use wrappers i386_linux_dr_set_control
++   or i386_linux_dr_reset_addr as they would modify the register cache
++   (i386_linux_dr).  */
++
++static void
++i386_linux_dr_detach (void)
++{
++  int regnum;
++
++  i386_linux_dr_set (inferior_ptid, DR_CONTROL, 0);
++  i386_linux_dr_unset_status (~0UL);
++  for (regnum = DR_FIRSTADDR; regnum <= DR_LASTADDR; regnum++)
++    i386_linux_dr_set (inferior_ptid, regnum, 0);
++}
++
+ static void
+ i386_linux_new_thread (ptid_t ptid)
+ {
+@@ -832,6 +877,8 @@ _initialize_i386_linux_nat (void)
+   i386_dr_low.set_addr = i386_linux_dr_set_addr;
+   i386_dr_low.reset_addr = i386_linux_dr_reset_addr;
+   i386_dr_low.get_status = i386_linux_dr_get_status;
++  i386_dr_low.unset_status = i386_linux_dr_unset_status;
++  i386_dr_low.detach = i386_linux_dr_detach;
+   i386_set_debug_register_length (4);
+ 
+   /* Override the default ptrace resume method.  */
+diff --git a/gdb/i386-nat.c b/gdb/i386-nat.c
+index ab1bd8a..ee330b8 100644
+--- a/gdb/i386-nat.c
++++ b/gdb/i386-nat.c
+@@ -137,8 +137,11 @@ struct i386_dr_low_type i386_dr_low;
+ #define I386_DR_GET_RW_LEN(i) \
+   ((dr_control_mirror >> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f)
+ 
++/* Mask that this I'th watchpoint has triggered.  */
++#define I386_DR_WATCH_MASK(i)	(1 << (i))
++
+ /* Did the watchpoint whose address is in the I'th register break?  */
+-#define I386_DR_WATCH_HIT(i)	(dr_status_mirror & (1 << (i)))
++#define I386_DR_WATCH_HIT(i)	(dr_status_mirror & I386_DR_WATCH_MASK (i))
+ 
+ /* A macro to loop over all debug registers.  */
+ #define ALL_DEBUG_REGISTERS(i)	for (i = 0; i < DR_NADDR; i++)
+@@ -358,6 +361,10 @@ i386_insert_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
+   i386_dr_low.set_addr (i, addr);
+   i386_dr_low.set_control (dr_control_mirror);
+ 
++  /* Only a sanity check for leftover bits (set possibly only by inferior).  */
++  if (i386_dr_low.unset_status)
++    i386_dr_low.unset_status (I386_DR_WATCH_MASK (i));
++
+   return 0;
+ }
+ 
+@@ -387,6 +394,11 @@ i386_remove_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
+ 	      i386_dr_low.set_control (dr_control_mirror);
+ 	      if (i386_dr_low.reset_addr)
+ 		i386_dr_low.reset_addr (i);
++
++	      /* Status must be already queried for each LWP.  Otherwise it will
++	         be lost in all-stop mode + breakpoint always-inserted off.  */
++	      if (i386_dr_low.unset_status)
++		i386_dr_low.unset_status (I386_DR_WATCH_MASK (i));
+ 	    }
+ 	  retval = 0;
+ 	}
+@@ -520,6 +532,17 @@ i386_remove_watchpoint (CORE_ADDR addr, int len, int type)
+   return retval;
+ }
+ 
++/* See target_detach_watchpoints.  */
++
++static int
++i386_detach_watchpoints (void)
++{
++  if (i386_dr_low.detach)
++    i386_dr_low.detach ();
++
++  return 0;
++}
++
+ /* Return non-zero if we can watch a memory region that starts at
+    address ADDR and whose length is LEN bytes.  */
+ 
+@@ -575,28 +598,7 @@ static int
+ i386_stopped_by_watchpoint (void)
+ {
+   CORE_ADDR addr = 0;
+-  return i386_stopped_data_address (&current_target, &addr);
+-}
+-
+-/* Return non-zero if the inferior has some break/watchpoint that
+-   triggered.  */
+-
+-static int
+-i386_stopped_by_hwbp (void)
+-{
+-  int i;
+-
+-  dr_status_mirror = i386_dr_low.get_status ();
+-  if (maint_show_dr)
+-    i386_show_dr ("stopped_by_hwbp", 0, 0, hw_execute);
+-
+-  ALL_DEBUG_REGISTERS(i)
+-    {
+-      if (I386_DR_WATCH_HIT (i))
+-	return 1;
+-    }
+-
+-  return 0;
++  return target_stopped_data_address (&current_target, &addr);
+ }
+ 
+ /* Insert a hardware-assisted breakpoint at BP_TGT->placed_address.
+@@ -690,6 +692,7 @@ i386_use_watchpoints (struct target_ops *t)
+   t->to_stopped_data_address = i386_stopped_data_address;
+   t->to_insert_watchpoint = i386_insert_watchpoint;
+   t->to_remove_watchpoint = i386_remove_watchpoint;
++  t->to_detach_watchpoints = i386_detach_watchpoints;
+   t->to_insert_hw_breakpoint = i386_insert_hw_breakpoint;
+   t->to_remove_hw_breakpoint = i386_remove_hw_breakpoint;
+ }
+diff --git a/gdb/i386-nat.h b/gdb/i386-nat.h
+index f49b9f6..cd31958 100644
+--- a/gdb/i386-nat.h
++++ b/gdb/i386-nat.h
+@@ -49,16 +49,23 @@ extern void i386_use_watchpoints (struct target_ops *);
+    functions are:
+ 
+       set_control              -- set the debug control (DR7)
+-				  register to a given value
++				  register to a given value for all LWPs
+ 
+       set_addr                 -- put an address into one debug
+-				  register
++				  register for all LWPs
+ 
+       reset_addr               -- reset the address stored in
+-				  one debug register
++				  one debug register for all LWPs
+ 
+       get_status               -- return the value of the debug
+-				  status (DR6) register.
++				  status (DR6) register for current LWP
++
++      unset_status             -- unset the specified bits of the debug
++				  status (DR6) register for all LWPs
++
++      detach                   -- clear all debug registers of only the
++				  INFERIOR_PTID task without affecting any
++				  register caches.
+ 
+    Additionally, the native file should set the debug_register_length
+    field to 4 or 8 depending on the number of bytes used for
+@@ -70,6 +77,8 @@ struct i386_dr_low_type
+     void (*set_addr) (int, CORE_ADDR);
+     void (*reset_addr) (int);
+     unsigned long (*get_status) (void);
++    void (*unset_status) (unsigned long);
++    void (*detach) (void);
+     int debug_register_length;
+   };
+ 
+diff --git a/gdb/infrun.c b/gdb/infrun.c
+index e3eddce..8917ac9 100644
+--- a/gdb/infrun.c
++++ b/gdb/infrun.c
+@@ -2630,6 +2630,10 @@ handle_inferior_event (struct execution_control_state *ecs)
+ 
+       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+ 
++      /* Clear WATCHPOINT_TRIGGERED values from previous stop which could
++	 confuse bpstat_stop_status and bpstat_explains_signal.  */
++      watchpoints_triggered (&ecs->ws);
++
+       ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+ 
+       ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
+@@ -2667,6 +2671,10 @@ handle_inferior_event (struct execution_control_state *ecs)
+ 
+       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+ 
++      /* Clear WATCHPOINT_TRIGGERED values from previous stop which could
++	 confuse bpstat_stop_status and bpstat_explains_signal.  */
++      watchpoints_triggered (&ecs->ws);
++
+       /* This causes the eventpoints and symbol table to be reset.
+          Must do this now, before trying to determine whether to
+          stop.  */
 diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
 index 6b68e7d..5095180 100644
 --- a/gdb/jv-lang.c
@@ -10507,6 +10961,158 @@ index 3e943a1..3b8956c 100644
  	    build_canonical_line_spec (values.sals, copy, canonical);
  	}
        return values;
+diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
+index 1308844..e6fad24 100644
+--- a/gdb/linux-nat.c
++++ b/gdb/linux-nat.c
+@@ -1629,6 +1629,7 @@ resume_callback (struct lwp_info *lp, void *data)
+       lp->stopped = 0;
+       lp->step = 0;
+       memset (&lp->siginfo, 0, sizeof (lp->siginfo));
++      lp->watchpoint_hit_set = 0;
+     }
+   else if (lp->stopped && debug_linux_nat)
+     fprintf_unfiltered (gdb_stdlog, "RC: Not resuming sibling %s (has pending)\n",
+@@ -1766,6 +1767,7 @@ linux_nat_resume (struct target_ops *ops,
+ 
+   linux_ops->to_resume (linux_ops, ptid, step, signo);
+   memset (&lp->siginfo, 0, sizeof (lp->siginfo));
++  lp->watchpoint_hit_set = 0;
+ 
+   if (debug_linux_nat)
+     fprintf_unfiltered (gdb_stdlog,
+@@ -2164,6 +2166,78 @@ maybe_clear_ignore_sigint (struct lwp_info *lp)
+     }
+ }
+ 
++/* Fetch the possible triggered data watchpoint info and store it to LP.
++   The hardware data watchpoint trigger gets cleared during this fetch.  */
++
++static void
++save_sigtrap (struct lwp_info *lp)
++{
++  struct cleanup *old_chain;
++
++  /* linux_nat_stopped_data_address is not even installed in this case.  */
++  if (linux_ops->to_stopped_data_address == NULL)
++    return;
++
++  old_chain = save_inferior_ptid ();
++  inferior_ptid = lp->ptid;
++
++  lp->watchpoint_hit_set =
++    linux_ops->to_stopped_data_address (&current_target, &lp->watchpoint_hit);
++
++  do_cleanups (old_chain);
++}
++
++/* Wrap target_stopped_data_address where the GNU/Linux native target may be
++   directed by the watchpoint/debug register number.  Base the reported value
++   on the triggered data address instead.  During inferior stop the assignment
++   of watchpoint/debug registers may change making the register number specific
++   trigger info stale.  */
++
++static int
++linux_nat_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
++{
++  struct lwp_info *lp = find_lwp_pid (inferior_ptid);
++
++  gdb_assert (lp != NULL);
++
++  *addr_p = lp->watchpoint_hit;
++
++  return lp->watchpoint_hit_set;
++}
++
++/* In `set follow-fork-mode child' with multithreaded parent we need to detach
++   watchpoints from all the LWPs.  In such case INFERIOR_PTID will be the
++   non-threaded new child while LWP_LIST will still contain all the threads of
++   the parent being detached.  */
++
++static int
++linux_nat_detach_watchpoints (void)
++{
++  struct lwp_info *lp;
++  int found = 0, retval = 0;
++  ptid_t filter = pid_to_ptid (ptid_get_pid (inferior_ptid));
++  struct cleanup *old_chain = save_inferior_ptid ();
++
++  for (lp = lwp_list; lp; lp = lp->next)
++    if (ptid_match (lp->ptid, filter))
++      {
++	inferior_ptid = lp->ptid;
++	retval |= linux_ops->to_detach_watchpoints ();
++	found = 1;
++      }
++
++  do_cleanups (old_chain);
++
++  if (!found)
++    {
++      gdb_assert (!is_lwp (inferior_ptid));
++
++      retval |= linux_ops->to_detach_watchpoints ();
++    }
++
++  return retval;
++}
++
+ /* Wait until LP is stopped.  */
+ 
+ static int
+@@ -2215,6 +2289,8 @@ stop_wait_callback (struct lwp_info *lp, void *data)
+ 	      /* Save the trap's siginfo in case we need it later.  */
+ 	      save_siginfo (lp);
+ 
++	      save_sigtrap (lp);
++
+ 	      /* Now resume this LWP and get the SIGSTOP event. */
+ 	      errno = 0;
+ 	      ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
+@@ -2579,9 +2655,13 @@ linux_nat_filter_event (int lwpid, int status, int options)
+       add_thread (lp->ptid);
+     }
+ 
+-  /* Save the trap's siginfo in case we need it later.  */
+   if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
+-    save_siginfo (lp);
++    {
++      /* Save the trap's siginfo in case we need it later.  */
++      save_siginfo (lp);
++
++      save_sigtrap (lp);
++    }
+ 
+   /* Handle GNU/Linux's extended waitstatus for trace events.  */
+   if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
+@@ -4871,6 +4951,10 @@ linux_nat_add_target (struct target_ops *t)
+   t->to_thread_alive = linux_nat_thread_alive;
+   t->to_pid_to_str = linux_nat_pid_to_str;
+   t->to_has_thread_control = tc_schedlock;
++  if (linux_ops->to_stopped_data_address)
++    t->to_stopped_data_address = linux_nat_stopped_data_address;
++  if (linux_ops->to_detach_watchpoints)
++    t->to_detach_watchpoints = linux_nat_detach_watchpoints;
+ 
+   t->to_can_async_p = linux_nat_can_async_p;
+   t->to_is_async_p = linux_nat_is_async_p;
+diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h
+index d1ed6fc..faf68bb 100644
+--- a/gdb/linux-nat.h
++++ b/gdb/linux-nat.h
+@@ -62,6 +62,12 @@ struct lwp_info
+      be the address of a hardware watchpoint.  */
+   struct siginfo siginfo;
+ 
++  /* WATCHPOINT_HIT_SET is non-zero if this LWP stopped with a trap and a data
++     watchpoint has been found as triggered.  In such case WATCHPOINT_HIT
++     contains data address of the triggered data watchpoint.  */
++  unsigned watchpoint_hit_set : 1;
++  CORE_ADDR watchpoint_hit;
++
+   /* Non-zero if we expect a duplicated SIGINT.  */
+   int ignore_sigint;
+ 
 diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
 index 88c7e5e..2d0b3ca 100644
 --- a/gdb/m2-lang.c
@@ -11406,6 +12012,43 @@ index cbda9c3..a07e6f2 100644
 +extern void exp_types_mark_used (struct expression *exp);
 +
  #endif /* PARSER_DEFS_H */
+diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
+index 47b74ad..22fb2fc 100644
+--- a/gdb/ppc-linux-nat.c
++++ b/gdb/ppc-linux-nat.c
+@@ -1391,6 +1391,24 @@ ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw)
+   return 0;
+ }
+ 
++/* See target_detach_watchpoints.  Do not use wrapper
++   ppc_linux_remove_watchpoint as it would modify the register cache
++   (saved_dabr_value).  */
++
++static int
++ppc_linux_detach_watchpoints (void)
++{
++  pid_t tid;
++
++  tid = TIDGET (inferior_ptid);
++  if (tid == 0)
++    tid = PIDGET (inferior_ptid);
++
++  if (ptrace (PTRACE_SET_DEBUGREG, tid, NULL, NULL) < 0)
++    return -1;
++  return 0;
++}
++
+ static void
+ ppc_linux_new_thread (ptid_t ptid)
+ {
+@@ -1648,6 +1666,7 @@ _initialize_ppc_linux_nat (void)
+   t->to_region_ok_for_hw_watchpoint = ppc_linux_region_ok_for_hw_watchpoint;
+   t->to_insert_watchpoint = ppc_linux_insert_watchpoint;
+   t->to_remove_watchpoint = ppc_linux_remove_watchpoint;
++  t->to_detach_watchpoints = ppc_linux_detach_watchpoints;
+   t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint;
+   t->to_stopped_data_address = ppc_linux_stopped_data_address;
+   t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range;
 diff --git a/gdb/printcmd.c b/gdb/printcmd.c
 index 5d8b936..fb0a455 100644
 --- a/gdb/printcmd.c
@@ -18928,11 +19571,94 @@ index 740d4e0..461ff95 100644
  						  const domain_enum domain);
  
  extern struct symtabs_and_lines
+diff --git a/gdb/target.c b/gdb/target.c
+index 7ee444f..631e5f8 100644
+--- a/gdb/target.c
++++ b/gdb/target.c
+@@ -124,6 +124,8 @@ static int debug_to_insert_watchpoint (CORE_ADDR, int, int);
+ 
+ static int debug_to_remove_watchpoint (CORE_ADDR, int, int);
+ 
++static int debug_to_detach_watchpoints (void);
++
+ static int debug_to_stopped_by_watchpoint (void);
+ 
+ static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *);
+@@ -584,6 +586,7 @@ update_current_target (void)
+       INHERIT (to_remove_hw_breakpoint, t);
+       INHERIT (to_insert_watchpoint, t);
+       INHERIT (to_remove_watchpoint, t);
++      INHERIT (to_detach_watchpoints, t);
+       INHERIT (to_stopped_data_address, t);
+       INHERIT (to_have_steppable_watchpoint, t);
+       INHERIT (to_have_continuable_watchpoint, t);
+@@ -694,6 +697,9 @@ update_current_target (void)
+   de_fault (to_remove_watchpoint,
+ 	    (int (*) (CORE_ADDR, int, int))
+ 	    return_minus_one);
++  de_fault (to_detach_watchpoints,
++	    (int (*) (void))
++	    return_zero);
+   de_fault (to_stopped_by_watchpoint,
+ 	    (int (*) (void))
+ 	    return_zero);
+@@ -3095,6 +3101,19 @@ debug_to_remove_watchpoint (CORE_ADDR addr, int len, int type)
+   return retval;
+ }
+ 
++static int
++debug_to_detach_watchpoints (void)
++{
++  int retval;
++
++  retval = debug_target.to_detach_watchpoints ();
++
++  fprintf_unfiltered (gdb_stdlog,
++		      "target_detach_watchpoints () = %ld\n",
++		      (unsigned long) retval);
++  return retval;
++}
++
+ static void
+ debug_to_terminal_init (void)
+ {
+@@ -3342,6 +3361,7 @@ setup_target_debug (void)
+   current_target.to_remove_hw_breakpoint = debug_to_remove_hw_breakpoint;
+   current_target.to_insert_watchpoint = debug_to_insert_watchpoint;
+   current_target.to_remove_watchpoint = debug_to_remove_watchpoint;
++  current_target.to_detach_watchpoints = debug_to_detach_watchpoints;
+   current_target.to_stopped_by_watchpoint = debug_to_stopped_by_watchpoint;
+   current_target.to_stopped_data_address = debug_to_stopped_data_address;
+   current_target.to_watchpoint_addr_within_range = debug_to_watchpoint_addr_within_range;
 diff --git a/gdb/target.h b/gdb/target.h
-index 2c743e9..ef29610 100644
+index 2c743e9..dbbce12 100644
 --- a/gdb/target.h
 +++ b/gdb/target.h
-@@ -1157,6 +1157,20 @@ extern int target_search_memory (CORE_ADDR start_addr,
+@@ -376,6 +376,7 @@ struct target_ops
+     int (*to_remove_hw_breakpoint) (struct gdbarch *, struct bp_target_info *);
+     int (*to_remove_watchpoint) (CORE_ADDR, int, int);
+     int (*to_insert_watchpoint) (CORE_ADDR, int, int);
++    int (*to_detach_watchpoints) (void);
+     int (*to_stopped_by_watchpoint) (void);
+     int to_have_steppable_watchpoint;
+     int to_have_continuable_watchpoint;
+@@ -1120,6 +1121,15 @@ extern char *normal_pid_to_str (ptid_t ptid);
+ #define	target_remove_watchpoint(addr, len, type)	\
+      (*current_target.to_remove_watchpoint) (addr, len, type)
+ 
++/* Clear all debug registers without affecting any register caches.  Function
++   acts on INFERIOR_PTID which should be the forked-off process, either the
++   non-threaded child one or the threaded parent one, depending on `set
++   follow-fork-mode'.  Both watchpoints and hardware breakpoints get removed.
++   Return 0 on success, -1 on failure.  */
++
++#define	target_detach_watchpoints()	\
++     (*current_target.to_detach_watchpoints) ()
++
+ #define target_insert_hw_breakpoint(gdbarch, bp_tgt) \
+      (*current_target.to_insert_hw_breakpoint) (gdbarch, bp_tgt)
+ 
+@@ -1157,6 +1167,20 @@ extern int target_search_memory (CORE_ADDR start_addr,
                                   ULONGEST pattern_len,
                                   CORE_ADDR *found_addrp);
  
@@ -18953,7 +19679,7 @@ index 2c743e9..ef29610 100644
  /* Command logging facility.  */
  
  #define target_log_command(p)						\
-@@ -1276,6 +1290,14 @@ extern struct target_ops *find_target_beneath (struct target_ops *);
+@@ -1276,6 +1300,14 @@ extern struct target_ops *find_target_beneath (struct target_ops *);
  
  extern char *target_get_osdata (const char *type);
  
@@ -20519,15 +21245,100 @@ index 0000000..5da7378
 +gdb_test "p temp1" " = '1' <repeats 78 times>" "second: print temp1"
 +gdb_test "p temp2" " = '2' <repeats 78 times>" "second: print temp2"
 +gdb_test "p temp3" " = '3' <repeats 48 times>" "second: print temp3"
-diff --git a/gdb/testsuite/gdb.cp/cp-relocate.exp b/gdb/testsuite/gdb.cp/cp-relocate.exp
-index 4095ccf..03c07d5 100644
---- a/gdb/testsuite/gdb.cp/cp-relocate.exp
-+++ b/gdb/testsuite/gdb.cp/cp-relocate.exp
-@@ -30,7 +30,7 @@ proc get_func_address { func } {
-     global gdb_prompt hex
+diff --git a/gdb/testsuite/gdb.base/watchpoint-hw.c b/gdb/testsuite/gdb.base/watchpoint-hw.c
+index 8da9af5..e2de53a 100644
+--- a/gdb/testsuite/gdb.base/watchpoint-hw.c
++++ b/gdb/testsuite/gdb.base/watchpoint-hw.c
+@@ -20,5 +20,11 @@ int watchee;
+ int
+ main (void)
+ {
++  volatile int dummy;
++
++  dummy = watchee;
++  dummy = 1;
++  dummy = 2;	/* break-at-exit */
++
+   return 0;
+ }
+diff --git a/gdb/testsuite/gdb.base/watchpoint-hw.exp b/gdb/testsuite/gdb.base/watchpoint-hw.exp
+index a2bb731..d74d6c7 100644
+--- a/gdb/testsuite/gdb.base/watchpoint-hw.exp
++++ b/gdb/testsuite/gdb.base/watchpoint-hw.exp
+@@ -21,19 +21,12 @@ if {(![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"]
+     return
+ }
  
-     set rfunc [string_to_regexp $func]
--    gdb_test_multiple "print '${func}'" "get address of ${func}" {
+-set testfile watchpoint-hw
+-set srcfile ${testfile}.c
+-set binfile ${objdir}/${subdir}/${testfile}
+-if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+-    untested "Couldn't compile test program"
++set test watchpoint-hw
++set srcfile ${test}.c
++if { [prepare_for_testing ${test}.exp ${test} ${srcfile}] } {
+     return -1
+ }
+ 
+-gdb_exit
+-gdb_start
+-gdb_reinitialize_dir $srcdir/$subdir
+-gdb_load ${binfile}
+-
+ # Create the watchpoint before the inferior gets started.  Now the native CPU
+ # target is still not active and its `to_can_use_hw_breakpoint' is not
+ # installed, therefore only a software watchpoint gets created.
+@@ -43,10 +36,40 @@ gdb_test "watch watchee" "atchpoint 1: watchee"
+ # `runto_main' or `runto main' would delete the watchpoint created above.
+ 
+ if { [gdb_start_cmd] < 0 } {
+-    untested start
++    untested ${test}.exp
+     return -1
+ }
+ gdb_test "" "main .* at .*" "start"
+ 
+ # Check it is really a `hw'-watchpoint.
+ gdb_test "info watchpoints" "1 *hw watchpoint .* watchee"
++
++# Before the inferior gets started we would get:
++# 	Target does not support this type of hardware watchpoint.
++gdb_test "delete 1"
++gdb_test "rwatch watchee"
++
++set breakline [gdb_get_line_number "break-at-exit"]
++gdb_breakpoint $breakline
++
++gdb_test "continue" "Continuing.\r\nHardware read watchpoint 3: watchee\r\n\r\nValue = 0\r\n.*"
++
++# Here should be no repeated notification of the read watchpoint.
++gdb_test "continue" \
++	 "Continuing\\.\[ \r\n\]+Breakpoint \[0-9\]+, .*break-at-exit.*" \
++	 "continue to break-at-exit after rwatch"
++
++clean_restart ${test}
++
++if ![runto_main] {
++    untested ${test}.exp
++    return -1
++}
++
++gdb_test "hbreak ${srcfile}:${breakline}" \
++	 "Hardware assisted breakpoint 2 at 0x\[0-9a-f\]+: file .*${srcfile}, line ${breakline}\\." \
++	 "hbreak"
++
++gdb_test "continue" \
++	 "Continuing\\.\[ \r\n\]+Breakpoint \[0-9\]+, .*break-at-exit.*" \
++	 "continue to break-at-exit after hbreak"
+diff --git a/gdb/testsuite/gdb.cp/cp-relocate.exp b/gdb/testsuite/gdb.cp/cp-relocate.exp
+index 4095ccf..03c07d5 100644
+--- a/gdb/testsuite/gdb.cp/cp-relocate.exp
++++ b/gdb/testsuite/gdb.cp/cp-relocate.exp
+@@ -30,7 +30,7 @@ proc get_func_address { func } {
+     global gdb_prompt hex
+ 
+     set rfunc [string_to_regexp $func]
+-    gdb_test_multiple "print '${func}'" "get address of ${func}" {
 +    gdb_test_multiple "print ${func}" "get address of ${func}" {
  	-re "\\\$\[0-9\]+ = \\{.*\\} (0|($hex) <${rfunc}>)\[\r\n\]+${gdb_prompt} $" {
  	    # $1 = {int ()} 0x24 <function_bar>
@@ -24965,6 +25776,1028 @@ index 5223fc8..03e1eab 100644
  }
  
  gdb_py_test_multiple "multi-line python command" \
+diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c b/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c
+new file mode 100644
+index 0000000..4dc308b
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c
+@@ -0,0 +1,175 @@
++/* Test case for forgotten hw-watchpoints after fork()-off of a process.
++
++   Copyright 2008, 2009 Free Software Foundation, Inc.
++
++   This file is part of GDB.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.  */
++
++#include <string.h>
++#include <errno.h>
++
++static void
++delay (void)
++{
++  int i = usleep (1000000 / 100);
++  assert (i == 0 || errno == EINTR);
++}
++
++#if defined FOLLOW_PARENT
++
++static void
++forkoff (int nr)
++{
++  pid_t child, pid_got;
++  int exit_code = 42 + nr;
++  int status, i;
++
++  child = fork ();
++  switch (child)
++    {
++    case -1:
++      assert (0);
++    case 0:
++      printf ("child%d: %d\n", nr, (int) getpid ());
++      /* Delay to get both the "child%d" and "parent%d" message printed without
++	 a race breaking expect by its endless wait on `$gdb_prompt$':
++	 Breakpoint 3, breakpoint () at ../../../gdb/testsuite/gdb.threads/watchpoint-fork.c:33
++	 33      }
++	 (gdb) parent2: 14223  */
++      i = sleep (1);
++      assert (i == 0);
++
++      /* We must not get caught here (against a forgotten breakpoint).  */
++      var++;
++      breakpoint ();
++
++      _exit (exit_code);
++    default:
++      printf ("parent%d: %d\n", nr, (int) child);
++      /* Delay to get both the "child%d" and "parent%d" message printed, see
++	 above.  */
++      i = sleep (1);
++      assert (i == 0);
++
++      pid_got = wait (&status);
++      assert (pid_got == child);
++      assert (WIFEXITED (status));
++      assert (WEXITSTATUS (status) == exit_code);
++
++      /* We must get caught here (against a false watchpoint removal).  */
++      breakpoint ();
++    }
++}
++
++#elif defined FOLLOW_CHILD
++
++static volatile int usr1_got;
++
++static void
++handler_usr1 (int signo)
++{
++  usr1_got++;
++}
++
++static void
++forkoff (int nr)
++{
++  pid_t child;
++  int i, loop;
++  struct sigaction act, oldact;
++#ifdef THREAD
++  void *thread_result;
++#endif
++
++  memset (&act, 0, sizeof act);
++  act.sa_flags = SA_RESTART;
++  act.sa_handler = handler_usr1;
++  sigemptyset (&act.sa_mask);
++  i = sigaction (SIGUSR1, &act, &oldact);
++  assert (i == 0);
++
++  child = fork ();
++  switch (child)
++    {
++    case -1:
++      assert (0);
++    default:
++      printf ("parent%d: %d\n", nr, (int) child);
++
++      /* Sleep for a while to possibly get incorrectly ATTACH_THREADed by GDB
++	 tracing the child fork with no longer valid thread/lwp entries of the
++	 parent.  */
++
++      i = sleep (2);
++      assert (i == 0);
++
++      /* We must not get caught here (against a forgotten breakpoint).  */
++
++      var++;
++      breakpoint ();
++
++#ifdef THREAD
++      /* And neither got caught our thread.  */
++
++      step = 99;
++      i = pthread_join (thread, &thread_result);
++      assert (i == 0);
++      assert (thread_result == (void *) 99UL);
++#endif
++
++      /* Be sure our child knows we did not get caught above.  */
++
++      i = kill (child, SIGUSR1);
++      assert (i == 0);
++
++      /* Sleep for a while to check GDB's `info threads' no longer tracks us in
++	 the child fork.  */
++
++      i = sleep (2);
++      assert (i == 0);
++
++      _exit (0);
++    case 0:
++      printf ("child%d: %d\n", nr, (int) getpid ());
++
++      /* Let the parent signal us about its success.  Be careful of races.  */
++
++      for (loop = 0; loop < 1000; loop++)
++	{
++	  /* Parent either died (and USR1_GOT is zero) or it succeeded.  */
++	  if (kill (getppid (), 0) != 0)
++	    break;
++	  /* Parent succeeded?  */
++	  if (usr1_got)
++	    break;
++
++	  delay ();
++	}
++      assert (usr1_got);
++
++      /* We must get caught here (against a false watchpoint removal).  */
++
++      breakpoint ();
++    }
++
++  i = sigaction (SIGUSR1, &oldact, NULL);
++  assert (i == 0);
++}
++
++#else
++# error "!FOLLOW_PARENT && !FOLLOW_CHILD"
++#endif
+diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c b/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
+new file mode 100644
+index 0000000..edacfc0
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
+@@ -0,0 +1,157 @@
++/* Test case for forgotten hw-watchpoints after fork()-off of a process.
++
++   Copyright 2008, 2009 Free Software Foundation, Inc.
++
++   This file is part of GDB.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.  */
++
++#include <assert.h>
++#include <unistd.h>
++#include <sys/wait.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <pthread.h>
++
++#include <asm/unistd.h>
++#include <unistd.h>
++#define gettid() syscall (__NR_gettid)
++
++/* Non-atomic `var++' should not hurt as we synchronize the threads by the STEP
++   variable.  Hit-comments need to be duplicite there to catch both at-stops
++   and behind-stops, depending on the target.  */
++
++static volatile int var;
++
++static void
++dummy (void)
++{
++}
++
++static void
++breakpoint (void)
++{
++}
++
++/* Include here the functions:
++   static void forkoff (int nr);
++   static void delay (void);  */
++
++static pthread_t thread;
++static volatile int step;
++#define THREAD
++
++#include "watchpoint-fork-forkoff.c"
++
++static void *
++start (void *arg)
++{
++  if (step >= 3)
++    goto step_3;
++
++  while (step != 1)
++    delay ();
++
++  var++;	/* validity-thread-B */
++  dummy ();	/* validity-thread-B */
++  step = 2;
++  while (step != 3)
++    {
++      if (step == 99)
++	goto step_99;
++      delay ();
++    }
++
++step_3:
++  if (step >= 5)
++    goto step_5;
++
++  var++;	/* after-fork1-B */
++  dummy ();	/* after-fork1-B */
++  step = 4;
++  while (step != 5)
++    {
++      if (step == 99)
++	goto step_99;
++      delay ();
++    }
++
++step_5:
++  var++;	/* after-fork2-B */
++  dummy ();	/* after-fork2-B */
++  return (void *) 5UL;
++
++step_99:
++  /* We must not get caught here (against a forgotten breakpoint).  */
++  var++;
++  breakpoint ();
++  return (void *) 99UL;
++}
++
++int
++main (void)
++{
++  int i;
++  void *thread_result;
++
++  setbuf (stdout, NULL);
++  printf ("main: %d\n", (int) gettid ());
++
++  /* General watchpoints validity.  */
++  var++;	/* validity-first */
++  dummy ();	/* validity-first */
++
++  i = pthread_create (&thread, NULL, start, NULL);
++  assert (i == 0);
++
++  var++;	/* validity-thread-A */
++  dummy ();	/* validity-thread-A */
++  step = 1;
++  while (step != 2)
++    delay ();
++
++  /* Hardware watchpoints got disarmed here.  */
++  forkoff (1);
++
++  var++;	/* after-fork1-A */
++  dummy ();	/* after-fork1-A */
++  step = 3;
++#ifdef FOLLOW_CHILD
++  /* Spawn new thread as it was deleted in the child of FORK.  */
++  i = pthread_create (&thread, NULL, start, NULL);
++  assert (i == 0);
++#endif
++  while (step != 4)
++    delay ();
++
++  /* A sanity check for double hardware watchpoints removal.  */
++  forkoff (2);
++
++  var++;	/* after-fork2-A */
++  dummy ();	/* after-fork2-A */
++  step = 5;
++#ifdef FOLLOW_CHILD
++  /* Spawn new thread as it was deleted in the child of FORK.  */
++  i = pthread_create (&thread, NULL, start, NULL);
++  assert (i == 0);
++#endif
++
++  i = pthread_join (thread, &thread_result);
++  assert (i == 0);
++  assert (thread_result == (void *) 5UL);
++
++  return 0;
++}
+diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork.c b/gdb/testsuite/gdb.threads/watchpoint-fork.c
+new file mode 100644
+index 0000000..5f62e7f
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchpoint-fork.c
+@@ -0,0 +1,57 @@
++/* Test case for forgotten hw-watchpoints after fork()-off of a process.
++
++   Copyright 2008, 2009 Free Software Foundation, Inc.
++
++   This file is part of GDB.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.  */
++
++#include <assert.h>
++#include <unistd.h>
++#include <sys/wait.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++static volatile int var;
++
++static void
++breakpoint (void)
++{
++}
++
++/* Include here the function:
++   static void forkoff (int nr);  */
++
++#include "watchpoint-fork-forkoff.c"
++
++int
++main (void)
++{
++  setbuf (stdout, NULL);
++  printf ("main: %d\n", (int) getpid ());
++
++  /* General watchpoints validity.  */
++  var++;
++  /* Hardware watchpoints got disarmed here.  */
++  forkoff (1);
++  /* This watchpoint got lost before.  */
++  var++;
++  /* A sanity check for double hardware watchpoints removal.  */
++  forkoff (2);
++  var++;
++
++  return 0;
++}
+diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork.exp b/gdb/testsuite/gdb.threads/watchpoint-fork.exp
+new file mode 100644
+index 0000000..1dc93ab
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchpoint-fork.exp
+@@ -0,0 +1,130 @@
++# Copyright 2008, 2009 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++# Test case for forgotten hw-watchpoints after fork()-off of a process.
++
++proc test {type symbol} {
++    global objdir subdir srcdir
++
++    set test watchpoint-fork
++
++    global pf_prefix
++    set prefix_test $pf_prefix
++    lappend pf_prefix "$type:"
++    set prefix_mt $pf_prefix
++
++    # no threads
++
++    set pf_prefix $prefix_mt
++    lappend pf_prefix "singlethreaded:"
++
++    set executable ${test}-${type}
++    if { [gdb_compile ${srcdir}/${subdir}/${test}.c ${objdir}/${subdir}/${executable} executable [list debug additional_flags=-D$symbol]] != "" } {
++	untested ${test}.exp
++	return -1
++    }
++    clean_restart $executable
++
++    gdb_test "show detach-on-fork" "Whether gdb will detach the child of a fork is on."
++    gdb_test "set follow-fork-mode $type"
++    gdb_test "show follow-fork-mode" "Debugger response to a program call of fork or vfork is \"$type\"."
++    # Testcase uses it for the `follow-fork-mode child' type.
++    gdb_test "handle SIGUSR1 nostop noprint pass"
++
++    if { ![runto_main] } then {
++	gdb_suppress_tests
++	return
++    }
++
++    # Install the watchpoint only after getting into MAIN - workaround some PPC
++    # problem.
++    gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint"
++
++    # It is never hit but it should not be left over in the fork()ed-off child.
++    gdb_breakpoint "breakpoint"
++
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 0.*New value = 1.*forkoff *\\(1\\).*" "watchpoints work"
++    gdb_test "continue" \
++	     "reakpoint 3, breakpoint.*" "breakpoint after the first fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 1.*New value = 2.*forkoff *\\(2\\).*" "watchpoint after the first fork"
++    gdb_test "continue" \
++	     "reakpoint 3, breakpoint.*" "breakpoint after the second fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 2.*New value = 3.*return *0;" "watchpoint after the second fork"
++    gdb_test "continue" "Continuing..*Program exited normally." "finish"
++
++
++    # threads
++
++    set pf_prefix $prefix_mt
++    lappend pf_prefix "multithreaded:"
++
++    set executable ${test}-mt-${type}
++    if { [gdb_compile_pthreads ${srcdir}/${subdir}/${test}-mt.c ${objdir}/${subdir}/${executable} executable [list debug additional_flags=-D$symbol]] != "" } {
++	untested ${test}.exp
++	return -1
++    }
++    clean_restart $executable
++
++    gdb_test "set follow-fork-mode $type"
++    # Testcase uses it for the `follow-fork-mode child' type.
++    gdb_test "handle SIGUSR1 nostop noprint pass"
++
++    if { ![runto_main] } then {
++	gdb_suppress_tests
++	return
++    }
++
++    # Install the watchpoint only after getting into MAIN - workaround some PPC
++    # problem.
++    gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint"
++
++    # It is never hit but it should not be left over in the fork()ed-off child.
++    gdb_breakpoint "breakpoint"
++
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 0.*New value = 1.*validity-first.*" "singlethread watchpoints work"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 1.*New value = 2.*validity-thread-A.*" "multithreaded watchpoints work at A"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 2.*New value = 3.*validity-thread-B.*" "multithreaded watchpoints work at B"
++    gdb_test "continue" \
++	     "reakpoint 3, breakpoint.*" "breakpoint (A) after the first fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 3.*New value = 4.*after-fork1-A.*" "watchpoint A after the first fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 4.*New value = 5.*after-fork1-B.*" "watchpoint B after the first fork"
++    gdb_test "continue" \
++	     "reakpoint 3, breakpoint.*" "breakpoint (A) after the second fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 5.*New value = 6.*after-fork2-A.*" "watchpoint A after the second fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 6.*New value = 7.*after-fork2-B.*" "watchpoint B after the second fork"
++    gdb_test "continue" "Continuing..*Program exited normally." "finish"
++
++
++    # cleanup
++
++    set pf_prefix $prefix_test
++}
++
++test parent FOLLOW_PARENT
++
++# Only GNU/Linux is known to support `set follow-fork-mode child'.
++if {[istarget "*-*-linux*"]} {
++    test child FOLLOW_CHILD
++}
+diff --git a/gdb/testsuite/gdb.threads/watchthreads-reorder.c b/gdb/testsuite/gdb.threads/watchthreads-reorder.c
+new file mode 100644
+index 0000000..14f42d6
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchthreads-reorder.c
+@@ -0,0 +1,366 @@
++/* This testcase is part of GDB, the GNU debugger.
++
++   Copyright 2009 Free Software Foundation, Inc.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
++
++#define _GNU_SOURCE
++#include <pthread.h>
++#include <stdio.h>
++#include <limits.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <string.h>
++#include <assert.h>
++#include <sys/types.h>
++#include <signal.h>
++#include <unistd.h>
++#include <asm/unistd.h>
++
++#define gettid() syscall (__NR_gettid)
++
++/* Terminate always in the main task, it can lock up with SIGSTOPped GDB
++   otherwise.  */
++#define TIMEOUT (gettid () == getpid() ? 10 : 15)
++
++static pthread_mutex_t gdbstop_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
++
++static pid_t thread1_tid;
++static pthread_cond_t thread1_tid_cond = PTHREAD_COND_INITIALIZER;
++static pthread_mutex_t thread1_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
++
++static pid_t thread2_tid;
++static pthread_cond_t thread2_tid_cond = PTHREAD_COND_INITIALIZER;
++static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
++
++static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
++
++static volatile int thread1_rwatch;
++static volatile int thread2_rwatch;
++
++static int unused1_rwatch;
++static int unused2_rwatch;
++
++/* Do not use alarm as it would create a ptrace event which would hang up us if
++ * we are being traced by GDB which we stopped ourselves.  */
++
++static void timed_mutex_lock (pthread_mutex_t *mutex)
++{
++  int i;
++  struct timespec start, now;
++
++  i = clock_gettime (CLOCK_MONOTONIC, &start);
++  assert (i == 0);
++
++  do
++    {
++      i = pthread_mutex_trylock (mutex);
++      if (i == 0)
++	return;
++      assert (i == EBUSY);
++
++      i = clock_gettime (CLOCK_MONOTONIC, &now);
++      assert (i == 0);
++      assert (now.tv_sec >= start.tv_sec);
++    }
++  while (now.tv_sec - start.tv_sec < TIMEOUT);
++
++  fprintf (stderr, "Timed out waiting for internal lock!\n");
++  exit (EXIT_FAILURE);
++}
++
++static void *
++thread1_func (void *unused)
++{
++  int i;
++  volatile int rwatch_store;
++
++  thread1_tid = gettid ();
++  i = pthread_cond_signal (&thread1_tid_cond);
++  assert (i == 0);
++
++  /* Be sure GDB is already stopped before continuing.  */
++  timed_mutex_lock (&gdbstop_mutex);
++  i = pthread_mutex_unlock (&gdbstop_mutex);
++  assert (i == 0);
++
++  rwatch_store = thread1_rwatch;
++
++  /* Be sure the "T (tracing stop)" test can proceed for both threads.  */
++  timed_mutex_lock (&terminate_mutex);
++  i = pthread_mutex_unlock (&terminate_mutex);
++  assert (i == 0);
++
++  return NULL;
++}
++
++static void *
++thread2_func (void *unused)
++{
++  int i;
++  volatile int rwatch_store;
++
++  thread2_tid = gettid ();
++  i = pthread_cond_signal (&thread2_tid_cond);
++  assert (i == 0);
++
++  /* Be sure GDB is already stopped before continuing.  */
++  timed_mutex_lock (&gdbstop_mutex);
++  i = pthread_mutex_unlock (&gdbstop_mutex);
++  assert (i == 0);
++
++  rwatch_store = thread2_rwatch;
++
++  /* Be sure the "T (tracing stop)" test can proceed for both threads.  */
++  timed_mutex_lock (&terminate_mutex);
++  i = pthread_mutex_unlock (&terminate_mutex);
++  assert (i == 0);
++
++  return NULL;
++}
++
++static const char *
++proc_string (const char *filename, const char *line)
++{
++  FILE *f;
++  static char buf[LINE_MAX];
++  size_t line_len = strlen (line);
++
++  f = fopen (filename, "r");
++  if (f == NULL)
++    {
++      fprintf (stderr, "fopen (\"%s\") for \"%s\": %s\n", filename, line,
++	       strerror (errno));
++      exit (EXIT_FAILURE);
++    }
++  while (errno = 0, fgets (buf, sizeof (buf), f))
++    {
++      char *s;
++
++      s = strchr (buf, '\n');
++      assert (s != NULL);
++      *s = 0;
++
++      if (strncmp (buf, line, line_len) != 0)
++	continue;
++
++      if (fclose (f))
++	{
++	  fprintf (stderr, "fclose (\"%s\") for \"%s\": %s\n", filename, line,
++		   strerror (errno));
++	  exit (EXIT_FAILURE);
++	}
++
++      return &buf[line_len];
++    }
++  if (errno != 0)
++    {
++      fprintf (stderr, "fgets (\"%s\": %s\n", filename, strerror (errno));
++      exit (EXIT_FAILURE);
++    }
++  fprintf (stderr, "\"%s\": No line \"%s\" found.\n", filename, line);
++  exit (EXIT_FAILURE);
++}
++
++static unsigned long
++proc_ulong (const char *filename, const char *line)
++{
++  const char *s = proc_string (filename, line);
++  long retval;
++  char *end;
++
++  errno = 0;
++  retval = strtol (s, &end, 10);
++  if (retval < 0 || retval >= LONG_MAX || (end && *end))
++    {
++      fprintf (stderr, "\"%s\":\"%s\": %ld, %s\n", filename, line, retval,
++	       strerror (errno));
++      exit (EXIT_FAILURE);
++    }
++  return retval;
++}
++
++static void
++state_wait (pid_t process, const char *wanted)
++{
++  char *filename;
++  int i;
++  struct timespec start, now;
++  const char *state;
++
++  i = asprintf (&filename, "/proc/%lu/status", (unsigned long) process);
++  assert (i > 0);
++
++  i = clock_gettime (CLOCK_MONOTONIC, &start);
++  assert (i == 0);
++
++  do
++    {
++      state = proc_string (filename, "State:\t");
++      if (strcmp (state, wanted) == 0)
++	{
++	  free (filename);
++	  return;
++	}
++
++      if (sched_yield ())
++	{
++	  perror ("sched_yield()");
++	  exit (EXIT_FAILURE);
++	}
++
++      i = clock_gettime (CLOCK_MONOTONIC, &now);
++      assert (i == 0);
++      assert (now.tv_sec >= start.tv_sec);
++    }
++  while (now.tv_sec - start.tv_sec < TIMEOUT);
++
++  fprintf (stderr, "Timed out waiting for PID %lu \"%s\" (now it is \"%s\")!\n",
++	   (unsigned long) process, wanted, state);
++  exit (EXIT_FAILURE);
++}
++
++static volatile pid_t tracer = 0;
++static pthread_t thread1, thread2;
++
++static void
++cleanup (void)
++{
++  printf ("Resuming GDB PID %lu.\n", (unsigned long) tracer);
++
++  if (tracer)
++    {
++      int i;
++      int tracer_save = tracer;
++
++      tracer = 0;
++
++      i = kill (tracer_save, SIGCONT);
++      assert (i == 0);
++    }
++}
++
++int
++main (int argc, char **argv)
++{
++  int i;
++  int standalone = 0;
++
++  if (argc == 2 && strcmp (argv[1], "-s") == 0)
++    standalone = 1;
++  else
++    assert (argc == 1);
++
++  setbuf (stdout, NULL);
++
++  timed_mutex_lock (&gdbstop_mutex);
++
++  timed_mutex_lock (&terminate_mutex);
++
++  i = pthread_create (&thread1, NULL, thread1_func, NULL);
++  assert (i == 0);
++
++  i = pthread_create (&thread2, NULL, thread2_func, NULL);
++  assert (i == 0);
++
++  if (!standalone)
++    {
++      tracer = proc_ulong ("/proc/self/status", "TracerPid:\t");
++      if (tracer == 0)
++	{
++	  fprintf (stderr, "The testcase must be run by GDB!\n");
++	  exit (EXIT_FAILURE);
++	}
++      if (tracer != getppid ())
++	{
++	  fprintf (stderr, "The testcase parent must be our GDB tracer!\n");
++	  exit (EXIT_FAILURE);
++	}
++    }
++
++  /* SIGCONT our debugger in the case of our crash as we would deadlock
++     otherwise.  */
++
++  atexit (cleanup);
++
++  printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer);
++
++  if (tracer)
++    {
++      i = kill (tracer, SIGSTOP);
++      assert (i == 0);
++      state_wait (tracer, "T (stopped)");
++    }
++
++  timed_mutex_lock (&thread1_tid_mutex);
++  timed_mutex_lock (&thread2_tid_mutex);
++
++  /* Let the threads start.  */
++  i = pthread_mutex_unlock (&gdbstop_mutex);
++  assert (i == 0);
++
++  printf ("Waiting till the threads initialize their TIDs.\n");
++
++  if (thread1_tid == 0)
++    {
++      i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex);
++      assert (i == 0);
++
++      assert (thread1_tid > 0);
++    }
++
++  if (thread2_tid == 0)
++    {
++      i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex);
++      assert (i == 0);
++
++      assert (thread2_tid > 0);
++    }
++
++  printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n",
++	  (unsigned long) thread1_tid, (unsigned long) thread2_tid,
++	  (unsigned long) getpid ());
++
++  printf ("Waiting till the threads get trapped by the watchpoints.\n");
++
++  if (tracer)
++    {
++      /* s390x-unknown-linux-gnu will fail with "R (running)".  */
++
++      state_wait (thread1_tid, "T (tracing stop)");
++
++      state_wait (thread2_tid, "T (tracing stop)");
++    }
++
++  cleanup ();
++
++  printf ("Joining the threads.\n");
++
++  i = pthread_mutex_unlock (&terminate_mutex);
++  assert (i == 0);
++
++  i = pthread_join (thread1, NULL);
++  assert (i == 0);
++
++  i = pthread_join (thread2, NULL);
++  assert (i == 0);
++
++  printf ("Exiting.\n");	/* break-at-exit */
++
++  /* Just prevent compiler `warning: ^[$B!F^[(BunusedX_rwatch^[$B!G^[(B defined but not used'.  */
++  unused1_rwatch = 1;
++  unused2_rwatch = 2;
++
++  return EXIT_SUCCESS;
++}
+diff --git a/gdb/testsuite/gdb.threads/watchthreads-reorder.exp b/gdb/testsuite/gdb.threads/watchthreads-reorder.exp
+new file mode 100644
+index 0000000..8f65364
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchthreads-reorder.exp
+@@ -0,0 +1,101 @@
++# This testcase is part of GDB, the GNU debugger.
++
++# Copyright 2009 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++# Test GDB can cope with two watchpoints being hit by different threads at the
++# same time, GDB reports one of them and after "continue" to report the other
++# one GDB should not be confused by differently set watchpoints that time.
++# This is the goal of "reorder1".  "reorder0" tests the basic functionality of
++# two watchpoint being hit at the same time, without reordering them during the
++# stop.  The formerly broken functionality is due to the all-stop mode default
++# "show breakpoint always-inserted" being "off".  Formerly the remembered hit
++# could be assigned during continuation of a thread with pending SIGTRAP to the
++# different/new watchpoint, just based on the watchpoint/debug register number.
++
++if {[target_info exists gdb,no_hardware_watchpoints]
++    || ![istarget *-*-linux*]} {
++    return 0;
++}
++
++set testfile "watchthreads-reorder"
++set srcfile ${testfile}.c
++set binfile ${objdir}/${subdir}/${testfile}
++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" ${binfile} executable [list debug additional_flags=-lrt]] != "" } {
++    return -1
++}
++
++foreach reorder {0 1} {
++
++    global pf_prefix
++    set prefix_test $pf_prefix
++    lappend pf_prefix "reorder$reorder:"
++
++    clean_restart $testfile
++
++    gdb_test "set can-use-hw-watchpoints 1"
++
++    if ![runto_main] {
++	gdb_suppress_tests
++    }
++
++    # Use "rwatch" as "watch" would report the watchpoint changed just based on its
++    # read memory value during a stop by unrelated event.  We are interested to not
++    # to lose the hardware watchpoint trigger.
++
++    gdb_test "rwatch thread1_rwatch" "Hardware read watchpoint \[0-9\]+: thread1_rwatch"
++    gdb_test {set $rwatch1=$bpnum}
++    set test "rwatch thread2_rwatch"
++    gdb_test_multiple $test $test {
++	-re "Target does not support this type of hardware watchpoint\\.\r\n$gdb_prompt $" {
++	    # ppc64 supports at most 1 hw watchpoints.
++	    unsupported $test
++	    return
++	}
++	-re "Hardware read watchpoint \[0-9\]+: thread2_rwatch\r\n$gdb_prompt $" {
++	    pass $test
++	}
++    }
++    gdb_test {set $rwatch2=$bpnum}
++    gdb_breakpoint [gdb_get_line_number "break-at-exit"]
++
++    # The watchpoints can happen in arbitrary order depending on random:
++    # SEL: Found 2 SIGTRAP events, selecting #[01]
++    # As GDB contains no srand() on the specific host/OS it will behave always the
++    # same.  Such order cannot be guaranteed for GDB in general.
++
++    gdb_test "continue" \
++	     "Hardware read watchpoint \[0-9\]+: thread\[12\]_rwatch\r\n\r\nValue = 0\r\n0x\[0-9a-f\]+ in thread\[12\]_func .*" \
++	     "continue a"
++
++    if $reorder {
++	gdb_test {delete $rwatch1}
++	gdb_test {delete $rwatch2}
++
++	gdb_test "rwatch unused1_rwatch" "Hardware read watchpoint \[0-9\]+: unused1_rwatch"
++	gdb_test "rwatch unused2_rwatch" "Hardware read watchpoint \[0-9\]+: unused2_rwatch"
++
++	gdb_test "rwatch thread1_rwatch" "Hardware read watchpoint \[0-9\]+: thread1_rwatch"
++	gdb_test "rwatch thread2_rwatch" "Hardware read watchpoint \[0-9\]+: thread2_rwatch"
++    }
++
++    gdb_test "continue" \
++	     "Hardware read watchpoint \[0-9\]+: thread\[12\]_rwatch\r\n\r\nValue = 0\r\n0x\[0-9a-f\]+ in thread\[12\]_func .*" \
++	     "continue b"
++
++    gdb_continue_to_breakpoint "break-at-exit" ".*break-at-exit.*"
++
++    set pf_prefix $prefix_test
++}
 diff --git a/gdb/testsuite/lib/cp-support.exp b/gdb/testsuite/lib/cp-support.exp
 index dbd2f59..44e1b51 100644
 --- a/gdb/testsuite/lib/cp-support.exp

diff --git a/gdb.spec b/gdb.spec
index 5ae0202..a28864a 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -14,7 +14,7 @@ Version: 6.8.50.20090818
 
 # The release always contains a leading reserved number, start it at 1.
 # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
-Release: 2%{?_with_upstream:.upstream}%{?dist}
+Release: 3%{?_with_upstream:.upstream}%{?dist}
 
 License: GPLv3+
 Group: Development/Debuggers
@@ -821,6 +821,10 @@ fi
 %endif
 
 %changelog
+* Tue Aug 18 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20090818-3
+- archer-jankratochvil-fedora12 commit: 850e3cb38a25cb7fdfa4cef667626ffbde51bcac
+- Fix the hardware watchpoints.
+
 * Tue Aug 18 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20090818-2
 - Fix patch fuzz 0.
 

^ permalink raw reply related	[flat|nested] 5+ messages in thread
* [rpms/gdb] gdb-17.2-rebase-f44: - archer-jankratochvil-fedora12 commit:
@ 2026-06-27 23:54 Jan Kratochvil
  0 siblings, 0 replies; 5+ messages in thread
From: Jan Kratochvil @ 2026-06-27 23:54 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/gdb
            Branch : gdb-17.2-rebase-f44
            Commit : 833a63eb373c31c96a2ca3eee4e5b5bae4812e9c
            Author : Jan Kratochvil <jkratoch@fedoraproject.org>
            Date   : 2009-08-11T21:15:13+00:00
            Stats  : +151/-412 in 3 file(s)
            URL    : https://src.fedoraproject.org/rpms/gdb/c/833a63eb373c31c96a2ca3eee4e5b5bae4812e9c?branch=gdb-17.2-rebase-f44

            Log:
            - archer-jankratochvil-fedora12 commit:
    2888fafe63889757c6fd27ccc2f25661d43fd1a4
- Drop archer-jankratochvil-vla VAROBJ invalidate/revalidate split to fix
    regressions against FSF GDB HEAD.

---
diff --git a/gdb-6.3-pie-20050110.patch b/gdb-6.3-pie-20050110.patch
index c198814..9f8c948 100644
--- a/gdb-6.3-pie-20050110.patch
+++ b/gdb-6.3-pie-20050110.patch
@@ -26,10 +26,10 @@
 
 	Fix scan_dyntag() for binaries provided by valgrind (BZ 460319).
 
-Index: gdb-6.8.50.20090809/gdb/amd64-tdep.c
+Index: gdb-6.8.50.20090811/gdb/amd64-tdep.c
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/amd64-tdep.c	2009-08-10 00:50:30.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/amd64-tdep.c	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/amd64-tdep.c	2009-08-11 23:12:32.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/amd64-tdep.c	2009-08-11 23:12:34.000000000 +0200
 @@ -36,6 +36,7 @@
  #include "regcache.h"
  #include "regset.h"
@@ -138,10 +138,10 @@ Index: gdb-6.8.50.20090809/gdb/amd64-tdep.c
    return pc;
  }
  
-Index: gdb-6.8.50.20090809/gdb/auxv.c
+Index: gdb-6.8.50.20090811/gdb/auxv.c
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/auxv.c	2009-07-02 19:25:52.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/auxv.c	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/auxv.c	2009-07-02 19:25:52.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/auxv.c	2009-08-11 23:12:34.000000000 +0200
 @@ -78,7 +78,7 @@ procfs_xfer_auxv (struct target_ops *ops
     Return 1 if an entry was read into *TYPEP and *VALP.  */
  static int
@@ -230,10 +230,10 @@ Index: gdb-6.8.50.20090809/gdb/auxv.c
  	break;
      }
  
-Index: gdb-6.8.50.20090809/gdb/auxv.h
+Index: gdb-6.8.50.20090811/gdb/auxv.h
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/auxv.h	2009-06-07 21:07:08.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/auxv.h	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/auxv.h	2009-06-07 21:07:08.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/auxv.h	2009-08-11 23:12:34.000000000 +0200
 @@ -31,14 +31,14 @@
     Return 1 if an entry was read into *TYPEP and *VALP.  */
  extern int target_auxv_parse (struct target_ops *ops,
@@ -251,11 +251,11 @@ Index: gdb-6.8.50.20090809/gdb/auxv.h
  
  /* Print the contents of the target's AUXV on the specified file. */
  extern int fprint_target_auxv (struct ui_file *file, struct target_ops *ops);
-Index: gdb-6.8.50.20090809/gdb/dwarf2read.c
+Index: gdb-6.8.50.20090811/gdb/dwarf2read.c
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/dwarf2read.c	2009-08-10 14:59:28.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/dwarf2read.c	2009-08-10 14:59:58.000000000 +0200
-@@ -1659,7 +1659,7 @@ dwarf2_build_psymtabs (struct objfile *o
+--- gdb-6.8.50.20090811.orig/gdb/dwarf2read.c	2009-08-11 23:12:32.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/dwarf2read.c	2009-08-11 23:12:34.000000000 +0200
+@@ -1653,7 +1653,7 @@ dwarf2_build_psymtabs (struct objfile *o
    dwarf2_read_section (objfile, &dwarf2_per_objfile->eh_frame);
    dwarf2_read_section (objfile, &dwarf2_per_objfile->frame);
  
@@ -264,10 +264,10 @@ Index: gdb-6.8.50.20090809/gdb/dwarf2read.c
        || (objfile->global_psymbols.size == 0
  	  && objfile->static_psymbols.size == 0))
      {
-Index: gdb-6.8.50.20090809/gdb/elfread.c
+Index: gdb-6.8.50.20090811/gdb/elfread.c
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/elfread.c	2009-08-10 00:50:30.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/elfread.c	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/elfread.c	2009-08-11 23:12:31.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/elfread.c	2009-08-11 23:12:34.000000000 +0200
 @@ -681,7 +681,7 @@ elf_symfile_read (struct objfile *objfil
    /* If we are reinitializing, or if we have never loaded syms yet,
       set table to empty.  MAINLINE is cleared so that *_read_psymtab
@@ -277,10 +277,10 @@ Index: gdb-6.8.50.20090809/gdb/elfread.c
      {
        init_psymbol_list (objfile, 0);
        mainline = 0;
-Index: gdb-6.8.50.20090809/gdb/infrun.c
+Index: gdb-6.8.50.20090811/gdb/infrun.c
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/infrun.c	2009-08-10 00:50:30.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/infrun.c	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/infrun.c	2009-08-11 23:12:32.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/infrun.c	2009-08-11 23:12:34.000000000 +0200
 @@ -3531,6 +3531,10 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (
  #endif
  	  target_terminal_inferior ();
@@ -292,13 +292,13 @@ Index: gdb-6.8.50.20090809/gdb/infrun.c
  	  /* If requested, stop when the dynamic linker notifies
  	     gdb of events.  This allows the user to get control
  	     and place breakpoints in initializer routines for
-Index: gdb-6.8.50.20090809/gdb/objfiles.c
+Index: gdb-6.8.50.20090811/gdb/objfiles.c
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/objfiles.c	2009-08-10 00:50:30.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/objfiles.c	2009-08-10 14:59:58.000000000 +0200
-@@ -52,6 +52,9 @@
+--- gdb-6.8.50.20090811.orig/gdb/objfiles.c	2009-08-11 23:12:31.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/objfiles.c	2009-08-11 23:12:51.000000000 +0200
+@@ -51,6 +51,9 @@
+ #include "arch-utils.h"
  #include "exec.h"
- #include "observer.h"
  
 +#include "auxv.h"
 +#include "elf/common.h"
@@ -306,7 +306,7 @@ Index: gdb-6.8.50.20090809/gdb/objfiles.c
  /* Prototypes for local functions */
  
  static void objfile_alloc_data (struct objfile *objfile);
-@@ -279,9 +282,17 @@ init_entry_point_info (struct objfile *o
+@@ -278,9 +281,17 @@ init_entry_point_info (struct objfile *o
  CORE_ADDR
  entry_point_address (void)
  {
@@ -334,10 +334,10 @@ Index: gdb-6.8.50.20090809/gdb/objfiles.c
    /* Before the symbol table code was redone to make it easier to
       selectively load and remove information particular to a specific
       linkage unit, gdb used to do these things whenever the monolithic
-Index: gdb-6.8.50.20090809/gdb/solib-svr4.c
+Index: gdb-6.8.50.20090811/gdb/solib-svr4.c
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/solib-svr4.c	2009-08-10 14:56:11.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/solib-svr4.c	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/solib-svr4.c	2009-08-11 23:12:32.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/solib-svr4.c	2009-08-11 23:12:34.000000000 +0200
 @@ -47,6 +47,7 @@
  #include "exec.h"
  #include "auxv.h"
@@ -999,10 +999,10 @@ Index: gdb-6.8.50.20090809/gdb/solib-svr4.c
 +  add_info ("linkmap", info_linkmap_command,
 +	    "Display the inferior's linkmap.");
  }
-Index: gdb-6.8.50.20090809/gdb/solib.c
+Index: gdb-6.8.50.20090811/gdb/solib.c
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/solib.c	2009-08-10 00:50:30.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/solib.c	2009-08-10 15:07:13.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/solib.c	2009-08-11 23:12:31.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/solib.c	2009-08-11 23:12:34.000000000 +0200
 @@ -81,6 +81,8 @@ set_solib_ops (struct gdbarch *gdbarch, 
  
  /* external data declarations */
@@ -1021,7 +1021,7 @@ Index: gdb-6.8.50.20090809/gdb/solib.c
  /*
  
     GLOBAL FUNCTION
-@@ -453,14 +453,38 @@ symbol_add_stub (struct so_list *so, int
+@@ -449,14 +453,38 @@ symbol_add_stub (struct so_list *so, int
    /* Have we already loaded this shared object?  */
    ALL_OBJFILES (so->objfile)
      {
@@ -1139,10 +1139,10 @@ Index: gdb-6.8.50.20090809/gdb/solib.c
 +			   NULL, NULL,
 +			   &setdebuglist, &showdebuglist);
  }
-Index: gdb-6.8.50.20090809/gdb/solist.h
+Index: gdb-6.8.50.20090811/gdb/solist.h
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/solist.h	2009-08-10 00:50:30.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/solist.h	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/solist.h	2009-08-11 23:12:31.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/solist.h	2009-08-11 23:12:34.000000000 +0200
 @@ -61,6 +61,8 @@ struct so_list
      bfd *abfd;
      char symbols_loaded;	/* flag: symbols read in yet? */
@@ -1163,10 +1163,10 @@ Index: gdb-6.8.50.20090809/gdb/solist.h
 +extern int debug_solib;
 +
  #endif
-Index: gdb-6.8.50.20090809/gdb/symfile-mem.c
+Index: gdb-6.8.50.20090811/gdb/symfile-mem.c
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/symfile-mem.c	2009-08-10 00:50:30.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/symfile-mem.c	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/symfile-mem.c	2009-08-11 23:12:31.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/symfile-mem.c	2009-08-11 23:12:34.000000000 +0200
 @@ -115,7 +115,7 @@ symbol_file_add_from_memory (struct bfd 
  	++i;
        }
@@ -1176,10 +1176,10 @@ Index: gdb-6.8.50.20090809/gdb/symfile-mem.c
                                     sai, OBJF_SHARED);
  
    /* This might change our ideas about frames already looked at.  */
-Index: gdb-6.8.50.20090809/gdb/symfile.c
+Index: gdb-6.8.50.20090811/gdb/symfile.c
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/symfile.c	2009-08-10 14:59:28.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/symfile.c	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/symfile.c	2009-08-11 23:12:32.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/symfile.c	2009-08-11 23:12:34.000000000 +0200
 @@ -49,6 +49,7 @@
  #include "readline/readline.h"
  #include "gdb_assert.h"
@@ -1188,7 +1188,7 @@ Index: gdb-6.8.50.20090809/gdb/symfile.c
  #include "observer.h"
  #include "exec.h"
  #include "parser-defs.h"
-@@ -785,7 +786,7 @@ syms_from_objfile (struct objfile *objfi
+@@ -786,7 +787,7 @@ syms_from_objfile (struct objfile *objfi
  
    /* Now either addrs or offsets is non-zero.  */
  
@@ -1197,7 +1197,7 @@ Index: gdb-6.8.50.20090809/gdb/symfile.c
      {
        /* We will modify the main symbol table, make sure that all its users
           will be cleaned up if an error occurs during symbol reading.  */
-@@ -813,7 +814,7 @@ syms_from_objfile (struct objfile *objfi
+@@ -814,7 +815,7 @@ syms_from_objfile (struct objfile *objfi
  
       We no longer warn if the lowest section is not a text segment (as
       happens for the PA64 port.  */
@@ -1206,7 +1206,7 @@ Index: gdb-6.8.50.20090809/gdb/symfile.c
      {
        asection *lower_sect;
        asection *sect;
-@@ -896,7 +897,7 @@ syms_from_objfile (struct objfile *objfi
+@@ -897,7 +898,7 @@ syms_from_objfile (struct objfile *objfi
        init_objfile_sect_indices (objfile);
      }
  
@@ -1215,7 +1215,7 @@ Index: gdb-6.8.50.20090809/gdb/symfile.c
  
    /* Discard cleanups as symbol reading was successful.  */
  
-@@ -915,17 +916,22 @@ new_symfile_objfile (struct objfile *obj
+@@ -916,17 +917,22 @@ new_symfile_objfile (struct objfile *obj
    /* If this is the main symbol file we have to clean up all users of the
       old main symbol file. Otherwise it is sufficient to fixup all the
       breakpoints that may have been redefined by this symbol file.  */
@@ -1240,7 +1240,7 @@ Index: gdb-6.8.50.20090809/gdb/symfile.c
  
    /* We're done reading the symbol file; finish off complaints.  */
    clear_complaints (&symfile_complaints, 0, add_flags & SYMFILE_VERBOSE);
-@@ -982,7 +988,7 @@ symbol_file_add_with_addrs_or_offsets (b
+@@ -980,7 +986,7 @@ symbol_file_add_with_addrs_or_offsets (b
    /* Give user a chance to burp if we'd be
       interactively wiping out any existing symbols.  */
  
@@ -1249,7 +1249,7 @@ Index: gdb-6.8.50.20090809/gdb/symfile.c
        && (have_full_symbols () || have_partial_symbols ())
        && from_tty
        && (have_full_symbols () || have_partial_symbols ())
-@@ -1183,6 +1189,9 @@ symbol_file_clear (int from_tty)
+@@ -1181,6 +1187,9 @@ symbol_file_clear (int from_tty)
  		    symfile_objfile->name)
  	  : !query (_("Discard symbol table? "))))
      error (_("Not confirmed."));
@@ -1259,7 +1259,7 @@ Index: gdb-6.8.50.20090809/gdb/symfile.c
  
    free_all_objfiles ();
  
-@@ -3387,6 +3396,8 @@ reread_symbols (void)
+@@ -3385,6 +3394,8 @@ reread_symbols (void)
  	      /* Discard cleanups as symbol reading was successful.  */
  	      discard_cleanups (old_cleanups);
  
@@ -1268,10 +1268,10 @@ Index: gdb-6.8.50.20090809/gdb/symfile.c
  	      /* If the mtime has changed between the time we set new_modtime
  	         and now, we *want* this to be out of date, so don't call stat
  	         again now.  */
-Index: gdb-6.8.50.20090809/gdb/target.h
+Index: gdb-6.8.50.20090811/gdb/target.h
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/target.h	2009-08-10 14:59:28.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/target.h	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/target.h	2009-08-11 23:12:32.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/target.h	2009-08-11 23:12:34.000000000 +0200
 @@ -524,7 +524,7 @@ struct target_ops
         Return -1 if there is insufficient buffer for a whole entry.
         Return 1 if an entry was read into *TYPEP and *VALP.  */
@@ -1281,10 +1281,10 @@ Index: gdb-6.8.50.20090809/gdb/target.h
  
      /* Search SEARCH_SPACE_LEN bytes beginning at START_ADDR for the
         sequence of bytes in PATTERN with length PATTERN_LEN.
-Index: gdb-6.8.50.20090809/gdb/symfile.h
+Index: gdb-6.8.50.20090811/gdb/symfile.h
 ===================================================================
---- gdb-6.8.50.20090809.orig/gdb/symfile.h	2009-08-10 14:59:28.000000000 +0200
-+++ gdb-6.8.50.20090809/gdb/symfile.h	2009-08-10 14:59:58.000000000 +0200
+--- gdb-6.8.50.20090811.orig/gdb/symfile.h	2009-08-11 23:12:32.000000000 +0200
++++ gdb-6.8.50.20090811/gdb/symfile.h	2009-08-11 23:12:34.000000000 +0200
 @@ -229,7 +229,13 @@ enum symfile_add_flags
      SYMFILE_MAINLINE = 1 << 2,
  

diff --git a/gdb-archer.patch b/gdb-archer.patch
index b1b0e1d..9ed9cdf 100644
--- a/gdb-archer.patch
+++ b/gdb-archer.patch
@@ -2,7 +2,7 @@ http://sourceware.org/gdb/wiki/ProjectArcher
 http://sourceware.org/gdb/wiki/ArcherBranchManagement
 
 GIT snapshot:
-commit 93f5e942bdcdcc376ece452c309bedabae71def9
+commit 2888fafe63889757c6fd27ccc2f25661d43fd1a4
 
 branch `archer' - the merge of branches:
 archer-tromey-call-frame-cfa
@@ -3214,26 +3214,10 @@ index b1c0452..da24b98 100644
  
  @node Language Support
 diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
-index 4984f31..4bbbe4e 100644
+index 4984f31..fcf1b5d 100644
 --- a/gdb/doc/observer.texi
 +++ b/gdb/doc/observer.texi
-@@ -130,6 +130,15 @@ Called with @var{objfile} equal to @code{NULL} to indicate
- previously loaded symbol table data has now been invalidated.
- @end deftypefun
- 
-+@deftypefun void objfile_unloading (struct objfile *@var{objfile})
-+The file specified by @var{objfile} is going to be removed from @value{GDBN}.
-+@end deftypefun
-+
-+@deftypefun void objfile_unloaded (void)
-+Removal of @var{objfile} started by @code{objfile_unloading} finished and
-+@var{objfile} is no longer known to @value{GDBN}.
-+@end deftypefun
-+
- @deftypefun void new_thread (struct thread_info *@var{t})
- The thread specified by @var{t} has been created.
- @end deftypefun
-@@ -206,6 +215,11 @@ Either @value{GDBN} detached from the inferior, or the inferior
+@@ -206,6 +206,11 @@ Either @value{GDBN} detached from the inferior, or the inferior
  exited.  The argument @var{pid} identifies the inferior.
  @end deftypefun
  
@@ -10513,23 +10497,17 @@ index a84003f..924c1c5 100644
    default_symfile_offsets,	/* sym_offsets: dummy FIXME til implem sym reloc */
    default_symfile_segments,	/* sym_segments: Get segment information from
 diff --git a/gdb/objfiles.c b/gdb/objfiles.c
-index 586f5d0..a4bf719 100644
+index 586f5d0..6d0451c 100644
 --- a/gdb/objfiles.c
 +++ b/gdb/objfiles.c
-@@ -432,10 +432,9 @@ free_objfile (struct objfile *objfile)
- 	 doesn't reference it.  */
-       objfile->separate_debug_objfile_backlink->separate_debug_objfile = NULL;
-     }
--  
--  /* Remove any references to this objfile in the global value
--     lists.  */
--  preserve_values (objfile);
-+
-+  /* Remove any references to this objfile in the global value lists.  */
-+  observer_notify_objfile_unloading (objfile);
+@@ -50,7 +50,6 @@
+ #include "addrmap.h"
+ #include "arch-utils.h"
+ #include "exec.h"
+-#include "observer.h"
+ 
+ /* Prototypes for local functions */
  
-   /* First do any symbol file specific actions required when we are
-      finished with a particular symbol file.  Note that if the objfile
 @@ -458,12 +457,14 @@ free_objfile (struct objfile *objfile)
  
    unlink_objfile (objfile);
@@ -10842,7 +10820,7 @@ index cbda9c3..a07e6f2 100644
 +
  #endif /* PARSER_DEFS_H */
 diff --git a/gdb/printcmd.c b/gdb/printcmd.c
-index 5d8b936..49c575d 100644
+index 5d8b936..fb0a455 100644
 --- a/gdb/printcmd.c
 +++ b/gdb/printcmd.c
 @@ -46,7 +46,6 @@
@@ -10939,13 +10917,11 @@ index 5d8b936..49c575d 100644
  /* display_chain items point to blocks and expressions.  Some expressions in
     turn may point to symbols.
     Both symbols and blocks are obstack_alloc'd on objfile_stack, and are
-@@ -1851,20 +1827,18 @@ display_uses_solib_p (const struct display *d,
-    an item by re-parsing .exp_string field in the new execution context.  */
- 
+@@ -1853,18 +1829,20 @@ display_uses_solib_p (const struct display *d,
  static void
--clear_dangling_display_expressions (struct so_list *solib)
-+clear_dangling_display_expressions (struct objfile *objfile)
+ clear_dangling_display_expressions (struct so_list *solib)
  {
++  struct objfile *objfile = solib->objfile;
    struct display *d;
 -  struct objfile *objfile = NULL;
  
@@ -10958,6 +10934,9 @@ index 5d8b936..49c575d 100644
 -	  d->block = NULL;
 -	}
 -    }
++  if (objfile == NULL)
++    return;
++
 +  for (d = display_chain; d != NULL; d = d->next)
 +    if (block_objfile (d->block) == objfile
 +	|| (d->exp && exp_uses_objfile (d->exp, objfile)))
@@ -10969,16 +10948,7 @@ index 5d8b936..49c575d 100644
  }
  \f
  
-@@ -2593,7 +2567,7 @@ _initialize_printcmd (void)
- 
-   current_display_number = -1;
- 
--  observer_attach_solib_unloaded (clear_dangling_display_expressions);
-+  observer_attach_objfile_unloading (clear_dangling_display_expressions);
- 
-   add_info ("address", address_info,
- 	    _("Describe where symbol SYM is stored."));
-@@ -2749,4 +2723,6 @@ Show printing of source filename and line number with <symbol>."), NULL,
+@@ -2749,4 +2727,6 @@ Show printing of source filename and line number with <symbol>."), NULL,
  			   NULL,
  			   show_print_symbol_filename,
  			   &setprintlist, &showprintlist);
@@ -17497,26 +17467,13 @@ index 1c37801..594eb16 100644
  	  print_variable_and_value (NULL, sym, frame, stream, 4 * num_tabs);
  	  break;
 diff --git a/gdb/symfile.c b/gdb/symfile.c
-index c182faa..8b971fb 100644
+index c182faa..550d06a 100644
 --- a/gdb/symfile.c
 +++ b/gdb/symfile.c
-@@ -52,7 +52,6 @@
- #include "observer.h"
- #include "exec.h"
- #include "parser-defs.h"
--#include "varobj.h"
- #include "elf-bfd.h"
- #include "solib.h"
- #include "remote.h"
-@@ -926,6 +925,20 @@ new_symfile_objfile (struct objfile *objfile, int add_flags)
- 
-   /* We're done reading the symbol file; finish off complaints.  */
+@@ -928,6 +928,17 @@ new_symfile_objfile (struct objfile *objfile, int add_flags)
    clear_complaints (&symfile_complaints, 0, add_flags & SYMFILE_VERBOSE);
-+
-+  /* We have finished unloading of OBJFILE.  */
-+  observer_notify_objfile_unloaded ();
-+}
-+
+ }
+ 
 +/* A helper function which returns true if OBJFILE has any debug
 +   symbols, and false otherwise.  */
 +static int
@@ -17526,10 +17483,12 @@ index c182faa..8b971fb 100644
 +	  || (objfile->separate_debug_objfile
 +	      && (objfile->separate_debug_objfile->psymtabs
 +		  || objfile->separate_debug_objfile->quick_addrmap)));
- }
- 
++}
++
  /* Process a symbol file, as either the main file or as a dynamically
-@@ -965,13 +978,16 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
+    loaded file.
+ 
+@@ -965,13 +976,16 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
    /* Give user a chance to burp if we'd be
       interactively wiping out any existing symbols.  */
  
@@ -17548,7 +17507,7 @@ index c182faa..8b971fb 100644
    discard_cleanups (my_cleanups);
  
    if (addrs)
-@@ -1007,6 +1023,8 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
+@@ -1007,6 +1021,8 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
  
    if ((flags & OBJF_READNOW) || readnow_symbol_files)
      {
@@ -17557,7 +17516,7 @@ index c182faa..8b971fb 100644
        if ((from_tty || info_verbose) && print_symbol_loading)
  	{
  	  printf_unfiltered (_("expanding to full symbols..."));
-@@ -1025,7 +1043,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
+@@ -1025,7 +1041,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
    /* If the file has its own symbol tables it has no separate debug info.
       `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS.
       `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'.  */
@@ -17566,7 +17525,7 @@ index c182faa..8b971fb 100644
      debugfile = find_separate_debug_file (objfile);
    if (debugfile)
      {
-@@ -1049,8 +1067,11 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
+@@ -1049,8 +1065,11 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
        xfree (debugfile);
      }
  
@@ -17580,7 +17539,7 @@ index c182faa..8b971fb 100644
      {
        wrap_here ("");
        printf_unfiltered (_("(no debugging symbols found)"));
-@@ -1166,7 +1187,9 @@ symbol_file_clear (int from_tty)
+@@ -1166,7 +1185,9 @@ symbol_file_clear (int from_tty)
       descriptors as well.  */
    no_shared_libraries (NULL, from_tty);
  
@@ -17591,16 +17550,7 @@ index c182faa..8b971fb 100644
    if (from_tty)
      printf_unfiltered (_("No symbol file now.\n"));
  }
-@@ -2349,7 +2372,7 @@ reread_symbols (void)
- 
- 	      /* Remove any references to this objfile in the global
- 		 value lists.  */
--	      preserve_values (objfile);
-+	      observer_notify_objfile_unloading (objfile);
- 
- 	      /* Nuke all the state that we will re-read.  Much of the following
- 	         code which sets things to NULL really is necessary to tell
-@@ -2437,13 +2460,15 @@ reread_symbols (void)
+@@ -2437,13 +2458,15 @@ reread_symbols (void)
  	         zero is OK since dbxread.c also does what it needs to do if
  	         objfile->global_psymbols.size is 0.  */
  	      (*objfile->sf->sym_read) (objfile, 0);
@@ -17617,17 +17567,7 @@ index c182faa..8b971fb 100644
  	      /* We're done reading the symbol file; finish off complaints.  */
  	      clear_complaints (&symfile_complaints, 0, 1);
  
-@@ -2452,6 +2477,9 @@ reread_symbols (void)
- 
- 	      reinit_frame_cache ();
- 
-+	      /* We have finished reloading of OBJFILE.  */
-+	      observer_notify_objfile_unloaded ();
-+
- 	      /* Discard cleanups as symbol reading was successful.  */
- 	      discard_cleanups (old_cleanups);
- 
-@@ -2741,7 +2769,7 @@ allocate_symtab (char *filename, struct objfile *objfile)
+@@ -2741,7 +2764,7 @@ allocate_symtab (char *filename, struct objfile *objfile)
  }
  
  struct partial_symtab *
@@ -17636,18 +17576,7 @@ index c182faa..8b971fb 100644
  {
    struct partial_symtab *psymtab;
  
-@@ -2832,10 +2860,6 @@ clear_symtab_users (void)
-      between expressions and which ought to be reset each time.  */
-   expression_context_block = NULL;
-   innermost_block = NULL;
--
--  /* Varobj may refer to old symbols, perform a cleanup.  */
--  varobj_invalidate ();
--
- }
- 
- static void
-@@ -3055,7 +3079,8 @@ again2:
+@@ -3055,7 +3078,8 @@ again2:
  
  struct partial_symtab *
  start_psymtab_common (struct objfile *objfile,
@@ -25201,7 +25130,7 @@ index cbb5d94..cf35bf0 100644
  	  ++reps;
  	  ++rep1;
 diff --git a/gdb/value.c b/gdb/value.c
-index 65a5aa9..c943781 100644
+index 65a5aa9..fa39d3d 100644
 --- a/gdb/value.c
 +++ b/gdb/value.c
 @@ -37,8 +37,10 @@
@@ -25467,15 +25396,6 @@ index 65a5aa9..c943781 100644
        break;
  
      case INTERNALVAR_VALUE:
-@@ -1469,7 +1551,7 @@ preserve_one_internalvar (struct internalvar *var, struct objfile *objfile,
-    this objfile's types, and the convenience variables will be adjusted to
-    use the new global types.  */
- 
--void
-+static void
- preserve_values (struct objfile *objfile)
- {
-   htab_t copied_types;
 @@ -1490,8 +1572,7 @@ preserve_values (struct objfile *objfile)
    for (var = internalvars; var; var = var->next)
      preserve_one_internalvar (var, objfile, copied_types);
@@ -25567,18 +25487,17 @@ index 65a5aa9..c943781 100644
  /* Create a value representing a pointer of type TYPE to the address
     ADDR.  */
  struct value *
-@@ -2342,4 +2476,9 @@ VARIABLE is already initialized."));
+@@ -2342,4 +2476,8 @@ VARIABLE is already initialized."));
    add_prefix_cmd ("function", no_class, function_command, _("\
  Placeholder command for showing help on convenience functions."),
  		  &functionlist, "function ", 0, &cmdlist);
 +
 +  make_final_cleanup (value_history_cleanup, NULL);
 +
-+  observer_attach_objfile_unloading (preserve_values);
 +  observer_attach_mark_used (value_types_mark_used);
  }
 diff --git a/gdb/value.h b/gdb/value.h
-index 29ad783..ee8440b 100644
+index 29ad783..c357d80 100644
 --- a/gdb/value.h
 +++ b/gdb/value.h
 @@ -344,11 +344,16 @@ extern LONGEST unpack_field_as_long (struct type *type,
@@ -25606,13 +25525,7 @@ index 29ad783..ee8440b 100644
  					  int want_address,
  					  enum noside noside);
  
-@@ -658,12 +664,12 @@ extern void typedef_print (struct type *type, struct symbol *news,
- 
- extern char *internalvar_name (struct internalvar *var);
- 
--extern void preserve_values (struct objfile *);
--
- /* From values.c */
+@@ -664,6 +670,8 @@ extern void preserve_values (struct objfile *);
  
  extern struct value *value_copy (struct value *);
  
@@ -25621,7 +25534,7 @@ index 29ad783..ee8440b 100644
  /* From valops.c */
  
  extern struct value *varying_to_slice (struct value *);
-@@ -681,7 +687,7 @@ extern struct value *value_allocate_space_in_inferior (int);
+@@ -681,7 +689,7 @@ extern struct value *value_allocate_space_in_inferior (int);
  extern struct value *value_of_local (const char *name, int complain);
  
  extern struct value *value_subscripted_rvalue (struct value *array,
@@ -25631,10 +25544,10 @@ index 29ad783..ee8440b 100644
  /* User function handler.  */
  
 diff --git a/gdb/varobj.c b/gdb/varobj.c
-index 4a94988..34333fb 100644
+index 4a94988..f2654f0 100644
 --- a/gdb/varobj.c
 +++ b/gdb/varobj.c
-@@ -26,14 +26,18 @@
+@@ -26,9 +26,12 @@
  #include "gdbcmd.h"
  #include "block.h"
  #include "valprint.h"
@@ -25647,13 +25560,7 @@ index 4a94988..34333fb 100644
  
  #include "varobj.h"
  #include "vec.h"
- #include "gdbthread.h"
- #include "inferior.h"
-+#include "observer.h"
- 
- #if HAVE_PYTHON
- #include "python/python.h"
-@@ -59,6 +63,15 @@ char *varobj_format_string[] =
+@@ -59,6 +62,15 @@ char *varobj_format_string[] =
  /* String representations of gdb's known languages */
  char *varobj_language_string[] = { "unknown", "C", "C++", "Java" };
  
@@ -25669,7 +25576,7 @@ index 4a94988..34333fb 100644
  /* Data structures */
  
  /* Every root variable has one of these structures saved in its
-@@ -173,9 +186,31 @@ struct varobj
+@@ -173,9 +185,31 @@ struct varobj
       frozen.  */
    int not_fetched;
  
@@ -25701,7 +25608,7 @@ index 4a94988..34333fb 100644
  };
  
  struct cpstack
-@@ -221,6 +256,8 @@ static void free_variable (struct varobj *var);
+@@ -221,6 +255,8 @@ static void free_variable (struct varobj *var);
  
  static struct cleanup *make_cleanup_free_variable (struct varobj *var);
  
@@ -25710,7 +25617,7 @@ index 4a94988..34333fb 100644
  static struct type *get_type (struct varobj *var);
  
  static struct type *get_value_type (struct varobj *var);
-@@ -236,8 +273,6 @@ static char *cppop (struct cpstack **pstack);
+@@ -236,8 +272,6 @@ static char *cppop (struct cpstack **pstack);
  static int install_new_value (struct varobj *var, struct value *value, 
  			      int initial);
  
@@ -25719,7 +25626,7 @@ index 4a94988..34333fb 100644
  /* Language-specific routines. */
  
  static enum varobj_languages variable_language (struct varobj *var);
-@@ -450,6 +485,8 @@ is_root_p (struct varobj *var)
+@@ -450,6 +484,8 @@ is_root_p (struct varobj *var)
  struct cleanup *
  varobj_ensure_python_env (struct varobj *var)
  {
@@ -25728,7 +25635,7 @@ index 4a94988..34333fb 100644
    return ensure_python_env (var->root->exp->gdbarch,
  			    var->root->exp->language_defn);
  }
-@@ -614,9 +651,9 @@ varobj_create (char *objname,
+@@ -614,9 +650,9 @@ varobj_create (char *objname,
  	  do_cleanups (old_chain);
  	  return NULL;
  	}
@@ -25739,7 +25646,7 @@ index 4a94988..34333fb 100644
    discard_cleanups (old_chain);
    return var;
  }
-@@ -731,15 +768,8 @@ instantiate_pretty_printer (PyObject *constructor, struct value *value)
+@@ -731,15 +767,8 @@ instantiate_pretty_printer (PyObject *constructor, struct value *value)
  #if HAVE_PYTHON
    PyObject *val_obj = NULL; 
    PyObject *printer;
@@ -25755,7 +25662,7 @@ index 4a94988..34333fb 100644
    if (! val_obj)
      return NULL;
  
-@@ -792,7 +822,12 @@ varobj_get_display_hint (struct varobj *var)
+@@ -792,7 +821,12 @@ varobj_get_display_hint (struct varobj *var)
    char *result = NULL;
  
  #if HAVE_PYTHON
@@ -25769,7 +25676,7 @@ index 4a94988..34333fb 100644
  
    if (var->pretty_printer)
      result = gdbpy_get_display_hint (var->pretty_printer);
-@@ -803,6 +838,17 @@ varobj_get_display_hint (struct varobj *var)
+@@ -803,6 +837,17 @@ varobj_get_display_hint (struct varobj *var)
    return result;
  }
  
@@ -25787,7 +25694,7 @@ index 4a94988..34333fb 100644
  /* If the variable object is bound to a specific thread, that
     is its evaluation can always be done in context of a frame
     inside that thread, returns GDB id of the thread -- which
-@@ -835,22 +881,73 @@ varobj_get_frozen (struct varobj *var)
+@@ -835,22 +880,73 @@ varobj_get_frozen (struct varobj *var)
    return var->frozen;
  }
  
@@ -25869,7 +25776,7 @@ index 4a94988..34333fb 100644
    PyObject *printer = var->pretty_printer;
  
    back_to = varobj_ensure_python_env (var);
-@@ -862,96 +959,103 @@ update_dynamic_varobj_children (struct varobj *var,
+@@ -862,96 +958,103 @@ update_dynamic_varobj_children (struct varobj *var,
        return 0;
      }
  
@@ -25884,26 +25791,26 @@ index 4a94988..34333fb 100644
 -    }
 +      children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst,
 +					     NULL);
- 
--  make_cleanup_py_decref (children);
++
 +      if (!children)
 +	{
 +	  gdbpy_print_stack ();
 +	  error (_("Null value returned for children"));
 +	}
  
+-  make_cleanup_py_decref (children);
++      make_cleanup_py_decref (children);
+ 
 -  if (!PyIter_Check (children))
 -    error (_("Returned value is not iterable"));
-+      make_cleanup_py_decref (children);
++      if (!PyIter_Check (children))
++	error (_("Returned value is not iterable"));
  
 -  iterator = PyObject_GetIter (children);
 -  if (!iterator)
 -    {
 -      gdbpy_print_stack ();
 -      error (_("Could not get children iterator"));
-+      if (!PyIter_Check (children))
-+	error (_("Returned value is not iterable"));
-+
 +      Py_XDECREF (var->child_iter);
 +      var->child_iter = PyObject_GetIter (children);
 +      if (!var->child_iter)
@@ -26037,7 +25944,7 @@ index 4a94988..34333fb 100644
    return 1;
  #else
    gdb_assert (0 && "should never be called if Python is not enabled");
-@@ -964,8 +1068,7 @@ varobj_get_num_children (struct varobj *var)
+@@ -964,8 +1067,7 @@ varobj_get_num_children (struct varobj *var)
    if (var->num_children == -1)
      {
        int changed;
@@ -26047,7 +25954,7 @@ index 4a94988..34333fb 100644
  	var->num_children = number_of_children (var);
      }
  
-@@ -976,7 +1079,7 @@ varobj_get_num_children (struct varobj *var)
+@@ -976,7 +1078,7 @@ varobj_get_num_children (struct varobj *var)
     the return code is the number of such children or -1 on error */
  
  VEC (varobj_p)*
@@ -26056,7 +25963,7 @@ index 4a94988..34333fb 100644
  {
    struct varobj *child;
    char *name;
-@@ -988,8 +1091,12 @@ varobj_list_children (struct varobj *var)
+@@ -988,8 +1090,12 @@ varobj_list_children (struct varobj *var)
        /* This, in theory, can result in the number of children changing without
  	 frontend noticing.  But well, calling -var-list-children on the same
  	 varobj twice is not something a sane frontend would do.  */
@@ -26071,7 +25978,7 @@ index 4a94988..34333fb 100644
  
    if (var->num_children == -1)
      var->num_children = number_of_children (var);
-@@ -1015,10 +1122,10 @@ varobj_list_children (struct varobj *var)
+@@ -1015,10 +1121,10 @@ varobj_list_children (struct varobj *var)
  	  name = name_of_child (var, i);
  	  existing = create_child (var, i, name);
  	  VEC_replace (varobj_p, var->children, i, existing);
@@ -26083,7 +25990,7 @@ index 4a94988..34333fb 100644
    return var->children;
  }
  
-@@ -1029,7 +1136,6 @@ varobj_add_child (struct varobj *var, const char *name, struct value *value)
+@@ -1029,7 +1135,6 @@ varobj_add_child (struct varobj *var, const char *name, struct value *value)
  					VEC_length (varobj_p, var->children), 
  					name, value);
    VEC_safe_push (varobj_p, var->children, v);
@@ -26091,7 +25998,7 @@ index 4a94988..34333fb 100644
    return v;
  }
  
-@@ -1168,6 +1274,115 @@ varobj_set_value (struct varobj *var, char *expression)
+@@ -1168,6 +1273,115 @@ varobj_set_value (struct varobj *var, char *expression)
    return 1;
  }
  
@@ -26207,7 +26114,7 @@ index 4a94988..34333fb 100644
  /* Assign a new value to a variable object.  If INITIAL is non-zero,
     this is the first assignement after the variable object was just
     created, or changed type.  In that case, just assign the value 
-@@ -1274,7 +1489,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
+@@ -1274,7 +1488,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
  	{
  	  changed = 1;
  	}
@@ -26216,7 +26123,7 @@ index 4a94988..34333fb 100644
  	{
  	  /* Try to compare the values.  That requires that both
  	     values are non-lazy.  */
-@@ -1328,65 +1543,32 @@ install_new_value (struct varobj *var, struct value *value, int initial)
+@@ -1328,65 +1542,32 @@ install_new_value (struct varobj *var, struct value *value, int initial)
      var->not_fetched = 0;
    var->updated = 0;
  
@@ -26299,7 +26206,7 @@ index 4a94988..34333fb 100644
  }
  
  void 
-@@ -1404,31 +1586,19 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer)
+@@ -1404,31 +1585,19 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer)
    make_cleanup_py_decref (globals);
  
    constructor = PyRun_String (visualizer, Py_eval_input, globals, globals);
@@ -26312,9 +26219,9 @@ index 4a94988..34333fb 100644
 -    }
 -  else
 -    pretty_printer = instantiate_pretty_printer (constructor, var->value);
--
--  Py_XDECREF (constructor);
  
+-  Py_XDECREF (constructor);
+-
 -  if (! pretty_printer)
 +  if (! constructor)
      {
@@ -26337,7 +26244,7 @@ index 4a94988..34333fb 100644
  
    do_cleanups (back_to);
  #else
-@@ -1543,7 +1713,7 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
+@@ -1543,7 +1712,7 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
  	 UI, so we need not bother getting it.  */
        if (v->pretty_printer)
  	{
@@ -26346,7 +26253,7 @@ index 4a94988..34333fb 100644
  	  int i, children_changed;
  	  varobj_p tmp;
  
-@@ -1555,28 +1725,28 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
+@@ -1555,28 +1724,28 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
  
  	  /* If update_dynamic_varobj_children returns 0, then we have
  	     a non-conforming pretty-printer, so we skip it.  */
@@ -26387,7 +26294,7 @@ index 4a94988..34333fb 100644
  	      continue;
  	    }
  	}
-@@ -1864,7 +2034,12 @@ new_variable (void)
+@@ -1864,7 +2033,12 @@ new_variable (void)
    var->frozen = 0;
    var->not_fetched = 0;
    var->children_requested = 0;
@@ -26400,7 +26307,7 @@ index 4a94988..34333fb 100644
  
    return var;
  }
-@@ -1894,7 +2069,10 @@ free_variable (struct varobj *var)
+@@ -1894,7 +2068,10 @@ free_variable (struct varobj *var)
    if (var->pretty_printer)
      {
        struct cleanup *cleanup = varobj_ensure_python_env (var);
@@ -26412,7 +26319,7 @@ index 4a94988..34333fb 100644
        do_cleanups (cleanup);
      }
  #endif
-@@ -1927,6 +2105,18 @@ make_cleanup_free_variable (struct varobj *var)
+@@ -1927,6 +2104,18 @@ make_cleanup_free_variable (struct varobj *var)
    return make_cleanup (do_free_variable_cleanup, var);
  }
  
@@ -26431,7 +26338,7 @@ index 4a94988..34333fb 100644
  /* This returns the type of the variable. It also skips past typedefs
     to return the real type of the variable.
  
-@@ -2141,6 +2331,8 @@ value_of_root (struct varobj **var_handle, int *type_changed)
+@@ -2141,6 +2330,8 @@ value_of_root (struct varobj **var_handle, int *type_changed)
        else
  	{
  	  tmp_var->obj_name = xstrdup (var->obj_name);
@@ -26440,7 +26347,7 @@ index 4a94988..34333fb 100644
  	  varobj_delete (var, NULL, 0);
  
  	  install_variable (tmp_var);
-@@ -3173,6 +3365,19 @@ java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
+@@ -3173,6 +3364,19 @@ java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
    return cplus_value_of_variable (var, format);
  }
  
@@ -26460,41 +26367,26 @@ index 4a94988..34333fb 100644
  /* Iterate all the existing _root_ VAROBJs and call the FUNC callback for them
     with an arbitrary caller supplied DATA pointer.  */
  
-@@ -3190,48 +3395,110 @@ all_root_varobjs (void (*func) (struct varobj *var, void *data), void *data)
+@@ -3190,6 +3394,43 @@ all_root_varobjs (void (*func) (struct varobj *var, void *data), void *data)
        (*func) (var_root->rootvar, data);
      }
  }
--\f
--extern void _initialize_varobj (void);
--void
--_initialize_varobj (void)
 +
 +/* Helper for varobj_types_mark_used.  Call type_mark_used for any TYPEs
 +   referenced from this VAR.  */
 +
 +static void
 +varobj_types_mark_used_iter (struct varobj *var, void *unused)
- {
--  int sizeof_table = sizeof (struct vlist *) * VAROBJ_TABLE_SIZE;
++{
 +  /* Even FLOATING or IS_INVALID VARs with non-NULL TYPE references will
 +     free them in free_variable.  Still EXP may also reference TYPEs
 +     but these belong to SYMBOLs which should be always associated with
 +     an OBJFILE (and therefore not useful to be type_mark_used).  */
- 
--  varobj_table = xmalloc (sizeof_table);
--  memset (varobj_table, 0, sizeof_table);
++
 +  type_mark_used (var->type);
 +  if (var->value)
 +    type_mark_used (value_type (var->value));
- 
--  add_setshow_zinteger_cmd ("debugvarobj", class_maintenance,
--			    &varobjdebug, _("\
--Set varobj debugging."), _("\
--Show varobj debugging."), _("\
--When non-zero, varobj debugging is enabled."),
--			    NULL,
--			    show_varobjdebug,
--			    &setlist, &showlist);
++
 +  /* Check VAROBJROOTs only once during the varobj_types_mark_used pass.  */
 +
 +  if (var->root->rootvar == var)
@@ -26502,177 +26394,25 @@ index 4a94988..34333fb 100644
 +      if (var->root->exp)
 +	exp_types_mark_used (var->root->exp);
 +    }
- }
- 
--/* Invalidate varobj VAR if it is tied to locals and re-create it if it is
--   defined on globals.  It is a helper for varobj_invalidate.  */
-+/* Call type_mark_used for any TYPEs referenced from this GDB source file.  */
- 
- static void
--varobj_invalidate_iter (struct varobj *var, void *unused)
-+varobj_types_mark_used (void)
- {
--  /* Floating varobjs are reparsed on each stop, so we don't care if the
--     presently parsed expression refers to something that's gone.  */
--  if (var->root->floating)
--    return;
-+  /* Check all the VAROBJs, even non-root ones.  Child VAROBJs can reference
-+     types from other OBJFILEs through TYPE_IS_OPAQUE resolutions by
-+     check_typedef.  Such types references will not be interconnected into the
-+     same TYPE_GROUP.  */
-+
-+  all_varobjs (varobj_types_mark_used_iter, NULL);
-+}
-+
-+/* Invalidate VAR if it is tied to the specified OBJFILE.  Call this function
-+   before you start removing OBJFILE.
-+
-+   Call varobj_revalidate_iter after the OBJFILE update get finished.
-+
-+   Invalidated varobjs will be always printed in_scope="invalid".  */
-+
-+static void
-+varobj_invalidate_iter (struct varobj *var, void *objfile_voidp)
-+{
-+  struct objfile *objfile = objfile_voidp;
-+
-+  /* Check VAROBJROOTs only once during the varobj_invalidate pass.  */
-+
-+  if (var->root->rootvar == var)
-+    {
-+      /* Check even FLOATING VAROBJROOTs as their data will be still checked
-+	 during varobj_update by varobj_get_type.  */
-+
-+      if (var->root->is_valid
-+	  && block_objfile (var->root->valid_block) == objfile)
-+	var->root->is_valid = 0;
-+
-+      if (var->root->exp && exp_uses_objfile (var->root->exp, objfile))
-+	{
-+	  var->root->is_valid = 0;
-+
-+	  /* No one touches EXP for !IS_VALID varobj.  */
-+	  xfree (var->root->exp);
-+	  var->root->exp = NULL;
-+	}
-+    }
-+
-+  if (var->type && TYPE_OBJFILE (var->type) == objfile)
-+    {
-+      var->root->is_valid = 0;
-+
-+      var->type = NULL;
-+    }
-+
-+  if (var->value && TYPE_OBJFILE (value_type (var->value)) == objfile)
-+    {
-+      var->root->is_valid = 0;
-+
-+      value_free (var->value);
-+      var->value = NULL;
-+    }
 +}
 +
-+/* Recreate any global varobjs possibly previously invalidated.  If the
-+   expressions are no longer evaluatable set/keep the VAR invalid.  */
++/* Call type_mark_used for any TYPEs referenced from this GDB source file.  */
 +
 +static void
-+varobj_revalidate_iter (struct varobj *var, void *unused)
-+{
-+  /* Global VAR must be re-evaluated.  */
- 
--  /* global var must be re-evaluated.  */     
-   if (var->root->valid_block == NULL)
-     {
-       struct varobj *tmp_var;
- 
-       /* Try to create a varobj with same expression.  If we succeed
- 	 replace the old varobj, otherwise invalidate it.  */
--      tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0,
--			       USE_CURRENT_FRAME);
--      if (tmp_var != NULL) 
--	{ 
-+      tmp_var = varobj_create (NULL, var->name, 0, USE_CURRENT_FRAME);
-+      if (tmp_var != NULL)
-+	{
- 	  tmp_var->obj_name = xstrdup (var->obj_name);
- 	  varobj_delete (var, NULL, 0);
- 	  install_variable (tmp_var);
-@@ -3239,16 +3506,64 @@ varobj_invalidate_iter (struct varobj *var, void *unused)
-       else
- 	var->root->is_valid = 0;
-     }
--  else /* locals must be invalidated.  */
--    var->root->is_valid = 0;
- }
- 
--/* Invalidate the varobjs that are tied to locals and re-create the ones that
--   are defined on globals.
--   Invalidated varobjs will be always printed in_scope="invalid".  */
-+/* Call varobj_invalidate_iter for all the VAROBJs.  */
- 
--void 
--varobj_invalidate (void)
-+static void 
-+varobj_invalidate (struct objfile *objfile)
++varobj_types_mark_used (void)
 +{
 +  /* Check all the VAROBJs, even non-root ones.  Child VAROBJs can reference
 +     types from other OBJFILEs through TYPE_IS_OPAQUE resolutions by
-+     check_typedef.  */
-+
-+  all_varobjs (varobj_invalidate_iter, objfile);
-+}
-+
-+/* Call varobj_revalidate_iter for all the root VAROBJs.  */
-+
-+static void 
-+varobj_revalidate (void)
-+{
-+  /* Check only root VAROBJs.  Any successful revalidation will replace the
-+     whole VAROBJs tree starting with root VAROBJs and its children get created
-+     later on-demand.  So there is no point trying to revalidate the child
-+     VAROBJs.  */
-+
-+  all_root_varobjs (varobj_revalidate_iter, NULL);
-+}
-+
-+/* Call varobj_revalidate just providing a different function prototype.
-+   Currently existing VAROBJs may become valid or change with new symbols
-+   loaded.  */
++     check_typedef.  Such types references will not be interconnected into the
++     same TYPE_GROUP.  */
 +
-+static void
-+varobj_revalidate_for_objfile (struct objfile *objfile)
- {
--  all_root_varobjs (varobj_invalidate_iter, NULL);
-+  varobj_revalidate ();
++  all_varobjs (varobj_types_mark_used_iter, NULL);
 +}
-+\f
-+extern void _initialize_varobj (void);
-+void
-+_initialize_varobj (void)
-+{
-+  int sizeof_table = sizeof (struct vlist *) * VAROBJ_TABLE_SIZE;
-+
-+  varobj_table = xmalloc (sizeof_table);
-+  memset (varobj_table, 0, sizeof_table);
-+
-+  add_setshow_zinteger_cmd ("debugvarobj", class_maintenance,
-+			    &varobjdebug, _("\
-+Set varobj debugging."), _("\
-+Show varobj debugging."), _("\
-+When non-zero, varobj debugging is enabled."),
-+			    NULL,
-+			    show_varobjdebug,
-+			    &setlist, &showlist);
-+
-+
-+  observer_attach_objfile_unloading (varobj_invalidate );
-+  observer_attach_objfile_unloaded (varobj_revalidate);
-+  observer_attach_new_objfile (varobj_revalidate_for_objfile);
-+  observer_attach_mark_used (varobj_types_mark_used);
- }
+ \f
+ extern void _initialize_varobj (void);
+ void
 diff --git a/gdb/varobj.h b/gdb/varobj.h
-index 7297243..fbe2f2f 100644
+index 7297243..0744cc3 100644
 --- a/gdb/varobj.h
 +++ b/gdb/varobj.h
 @@ -78,6 +78,12 @@ typedef struct varobj_update_result_t
@@ -26716,13 +26456,7 @@ index 7297243..fbe2f2f 100644
  
  extern char *varobj_get_type (struct varobj *var);
  
-@@ -143,12 +160,15 @@ extern void all_root_varobjs (void (*func) (struct varobj *var, void *data),
- extern VEC(varobj_update_result) *varobj_update (struct varobj **varp, 
- 						 int explicit);
- 
--extern void varobj_invalidate (void);
--
- extern int varobj_editable_p (struct varobj *var);
+@@ -149,6 +166,11 @@ extern int varobj_editable_p (struct varobj *var);
  
  extern int varobj_floating_p (struct varobj *var);
  

diff --git a/gdb.spec b/gdb.spec
index da9abc2..db15b5c 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -14,7 +14,7 @@ Version: 6.8.50.20090811
 
 # The release always contains a leading reserved number, start it at 1.
 # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
-Release: 2%{?_with_upstream:.upstream}%{?dist}
+Release: 3%{?_with_upstream:.upstream}%{?dist}
 
 License: GPLv3+
 Group: Development/Debuggers
@@ -825,6 +825,11 @@ fi
 %endif
 
 %changelog
+* Tue Aug 11 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20090811-3
+- archer-jankratochvil-fedora12 commit: 2888fafe63889757c6fd27ccc2f25661d43fd1a4
+- Drop archer-jankratochvil-vla VAROBJ invalidate/revalidate split to fix
+  regressions against FSF GDB HEAD.
+
 * Tue Aug 11 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20090811-2
 - archer-jankratochvil-fedora12 commit: 93f5e942bdcdcc376ece452c309bedabae71def9
 - Fix "can't compute CFA for this frame" (by Tom Tromey, BZ 516627).

^ permalink raw reply related	[flat|nested] 5+ messages in thread
* [rpms/gdb] gdb-17.2-rebase-f44: - archer-jankratochvil-fedora12 commit:
@ 2026-06-27 23:54 Jan Kratochvil
  0 siblings, 0 replies; 5+ messages in thread
From: Jan Kratochvil @ 2026-06-27 23:54 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/gdb
            Branch : gdb-17.2-rebase-f44
            Commit : 99fa6c959f83ec29662eed8f6145a12c97676a64
            Author : Jan Kratochvil <jkratoch@fedoraproject.org>
            Date   : 2009-08-11T18:07:06+00:00
            Stats  : +478/-35 in 2 file(s)
            URL    : https://src.fedoraproject.org/rpms/gdb/c/99fa6c959f83ec29662eed8f6145a12c97676a64?branch=gdb-17.2-rebase-f44

            Log:
            - archer-jankratochvil-fedora12 commit:
    93f5e942bdcdcc376ece452c309bedabae71def9
- Fix "can't compute CFA for this frame" (by Tom Tromey, BZ 516627).

---
diff --git a/gdb-archer.patch b/gdb-archer.patch
index 6a010e4..b1b0e1d 100644
--- a/gdb-archer.patch
+++ b/gdb-archer.patch
@@ -2,7 +2,7 @@ http://sourceware.org/gdb/wiki/ProjectArcher
 http://sourceware.org/gdb/wiki/ArcherBranchManagement
 
 GIT snapshot:
-commit 81de3c6abae4f7e3738aa9bcc0ab2f8725cce252
+commit 93f5e942bdcdcc376ece452c309bedabae71def9
 
 branch `archer' - the merge of branches:
 archer-tromey-call-frame-cfa
@@ -3246,7 +3246,7 @@ index 4984f31..4bbbe4e 100644
  This observer is used for internal testing.  Do not use.  
  See testsuite/gdb.gdb/observer.exp.
 diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
-index 0f6da40..c1c162e 100644
+index 0f6da40..fc70309 100644
 --- a/gdb/dwarf2-frame.c
 +++ b/gdb/dwarf2-frame.c
 @@ -38,6 +38,7 @@
@@ -3271,7 +3271,18 @@ index 0f6da40..c1c162e 100644
  no_get_tls_address (void *baton, CORE_ADDR offset)
  {
    internal_error (__FILE__, __LINE__,
-@@ -360,14 +368,16 @@ execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size,
+@@ -352,24 +360,29 @@ execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size,
+ {
+   struct dwarf_expr_context *ctx;
+   CORE_ADDR result;
++  struct cleanup *old_chain;
+ 
+   ctx = new_dwarf_expr_context ();
++  old_chain = make_cleanup_free_dwarf_expr_context (ctx);
++
+   ctx->gdbarch = get_frame_arch (this_frame);
+   ctx->addr_size = addr_size;
+   ctx->baton = this_frame;
    ctx->read_reg = read_reg;
    ctx->read_mem = read_mem;
    ctx->get_frame_base = no_get_frame_base;
@@ -3287,9 +3298,12 @@ index 0f6da40..c1c162e 100644
      result = read_reg (this_frame, result);
 +  /* FIXME */
  
-   free_dwarf_expr_context (ctx);
+-  free_dwarf_expr_context (ctx);
++  do_cleanups (old_chain);
  
-@@ -1247,6 +1257,14 @@ dwarf2_frame_base_sniffer (struct frame_info *this_frame)
+   return result;
+ }
+@@ -1247,6 +1260,14 @@ dwarf2_frame_base_sniffer (struct frame_info *this_frame)
  
    return NULL;
  }
@@ -3297,14 +3311,14 @@ index 0f6da40..c1c162e 100644
 +CORE_ADDR
 +dwarf2_frame_cfa (struct frame_info *this_frame)
 +{
-+  if (! frame_base_is (this_frame, &dwarf2_frame_base))
++  if (! frame_unwinder_is (this_frame, &dwarf2_frame_unwind))
 +    error (_("can't compute CFA for this frame"));
-+  return get_frame_base_address (this_frame);
++  return get_frame_base (this_frame);
 +}
  \f
  const struct objfile_data *dwarf2_frame_objfile_data;
  
-@@ -1536,6 +1554,14 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
+@@ -1536,6 +1557,14 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
        CORE_ADDR offset;
        CORE_ADDR seek_pc;
  
@@ -3333,10 +3347,33 @@ index b203661..dd03d59 100644
 +
  #endif /* dwarf2-frame.h */
 diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
-index 8dbf976..aec7b92 100644
+index 8dbf976..228eae7 100644
 --- a/gdb/dwarf2expr.c
 +++ b/gdb/dwarf2expr.c
-@@ -109,8 +109,7 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
+@@ -61,6 +61,22 @@ free_dwarf_expr_context (struct dwarf_expr_context *ctx)
+   xfree (ctx);
+ }
+ 
++/* Helper for make_cleanup_free_dwarf_expr_context.  */
++
++static void
++free_dwarf_expr_context_cleanup (void *arg)
++{
++  free_dwarf_expr_context (arg);
++}
++
++/* Return a cleanup that calls free_dwarf_expr_context.  */
++
++struct cleanup *
++make_cleanup_free_dwarf_expr_context (struct dwarf_expr_context *ctx)
++{
++  return make_cleanup (free_dwarf_expr_context_cleanup, ctx);
++}
++
+ /* Expand the memory allocated to CTX's stack to contain at least
+    NEED more elements than are currently used.  */
+ 
+@@ -109,8 +125,7 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
  
  /* Add a new piece to CTX's piece list.  */
  static void
@@ -3346,7 +3383,7 @@ index 8dbf976..aec7b92 100644
  {
    struct dwarf_expr_piece *p;
  
-@@ -125,9 +124,15 @@ add_piece (struct dwarf_expr_context *ctx,
+@@ -125,9 +140,15 @@ add_piece (struct dwarf_expr_context *ctx,
                             * sizeof (struct dwarf_expr_piece));
  
    p = &ctx->pieces[ctx->num_pieces - 1];
@@ -3364,7 +3401,7 @@ index 8dbf976..aec7b92 100644
  }
  
  /* Evaluate the expression at ADDR (LEN bytes long) using the context
-@@ -271,6 +276,21 @@ signed_address_type (struct gdbarch *gdbarch, int addr_size)
+@@ -271,6 +292,21 @@ signed_address_type (struct gdbarch *gdbarch, int addr_size)
      }
  }
  \f
@@ -3386,7 +3423,7 @@ index 8dbf976..aec7b92 100644
  /* The engine for the expression evaluator.  Using the context in CTX,
     evaluate the expression between OP_PTR and OP_END.  */
  
-@@ -279,8 +299,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -279,8 +315,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  		  gdb_byte *op_ptr, gdb_byte *op_end)
  {
    enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
@@ -3396,7 +3433,7 @@ index 8dbf976..aec7b92 100644
    ctx->initialized = 1;  /* Default is initialized.  */
  
    if (ctx->recursion_depth > ctx->max_recursion_depth)
-@@ -420,20 +439,36 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -420,20 +455,36 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  		   "used either alone or in conjuction with DW_OP_piece."));
  
  	  result = op - DW_OP_reg0;
@@ -3439,7 +3476,7 @@ index 8dbf976..aec7b92 100644
  	case DW_OP_breg0:
  	case DW_OP_breg1:
  	case DW_OP_breg2:
-@@ -498,11 +533,12 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -498,11 +549,12 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  	    (ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
  	    dwarf_expr_eval (ctx, datastart, datalen);
  	    result = dwarf_expr_fetch (ctx, 0);
@@ -3454,7 +3491,7 @@ index 8dbf976..aec7b92 100644
  	  }
  	  break;
  	case DW_OP_dup:
-@@ -700,6 +736,10 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -700,6 +752,10 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  	  }
  	  break;
  
@@ -3465,7 +3502,7 @@ index 8dbf976..aec7b92 100644
  	case DW_OP_GNU_push_tls_address:
  	  /* Variable is at a constant offset in the thread-local
  	  storage block into the objfile for the current thread and
-@@ -738,12 +778,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -738,12 +794,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  
              /* Record the piece.  */
              op_ptr = read_uleb128 (op_ptr, op_end, &size);
@@ -3484,7 +3521,7 @@ index 8dbf976..aec7b92 100644
            }
            goto no_push;
  
-@@ -755,6 +796,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
+@@ -755,6 +812,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
  	  ctx->initialized = 0;
  	  goto no_push;
  
@@ -3499,7 +3536,7 @@ index 8dbf976..aec7b92 100644
  	  error (_("Unhandled dwarf expression opcode 0x%x"), op);
  	}
 diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
-index 7047922..232208d 100644
+index 7047922..597c2de 100644
 --- a/gdb/dwarf2expr.h
 +++ b/gdb/dwarf2expr.h
 @@ -23,6 +23,19 @@
@@ -3621,8 +3658,17 @@ index 7047922..232208d 100644
  
    /* The length of the piece, in bytes.  */
    ULONGEST size;
+@@ -131,6 +159,8 @@ struct dwarf_expr_piece
+ 
+ struct dwarf_expr_context *new_dwarf_expr_context (void);
+ void free_dwarf_expr_context (struct dwarf_expr_context *ctx);
++struct cleanup *
++    make_cleanup_free_dwarf_expr_context (struct dwarf_expr_context *ctx);
+ 
+ void dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value);
+ void dwarf_expr_pop (struct dwarf_expr_context *ctx);
 diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
-index 071b5ac..07bb8ba 100644
+index 071b5ac..7b2e488 100644
 --- a/gdb/dwarf2loc.c
 +++ b/gdb/dwarf2loc.c
 @@ -36,6 +36,7 @@
@@ -4004,7 +4050,20 @@ index 071b5ac..07bb8ba 100644
  /* Thread-local accesses do require a frame.  */
  static CORE_ADDR
  needs_frame_tls_address (void *baton, CORE_ADDR offset)
-@@ -356,11 +567,12 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
+@@ -346,21 +557,25 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
+   struct needs_frame_baton baton;
+   struct dwarf_expr_context *ctx;
+   int in_reg;
++  struct cleanup *old_chain;
+ 
+   baton.needs_frame = 0;
+ 
+   ctx = new_dwarf_expr_context ();
++  old_chain = make_cleanup_free_dwarf_expr_context (ctx);
++
+   ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (per_cu));
+   ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
+   ctx->baton = &baton;
    ctx->read_reg = needs_frame_read_reg;
    ctx->read_mem = needs_frame_read_mem;
    ctx->get_frame_base = needs_frame_frame_base;
@@ -4018,7 +4077,7 @@ index 071b5ac..07bb8ba 100644
  
    if (ctx->num_pieces > 0)
      {
-@@ -369,7 +581,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
+@@ -369,11 +584,11 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
        /* If the location has several pieces, and any of them are in
           registers, then we will need a frame to fetch them from.  */
        for (i = 0; i < ctx->num_pieces; i++)
@@ -4027,7 +4086,12 @@ index 071b5ac..07bb8ba 100644
            in_reg = 1;
      }
  
-@@ -601,7 +813,7 @@ static int
+-  free_dwarf_expr_context (ctx);
++  do_cleanups (old_chain);
+ 
+   return baton.needs_frame || in_reg;
+ }
+@@ -601,7 +816,7 @@ static int
  loclist_describe_location (struct symbol *symbol, struct ui_file *stream)
  {
    /* FIXME: Could print the entire list of locations.  */
@@ -4036,7 +4100,7 @@ index 071b5ac..07bb8ba 100644
    return 1;
  }
  
-@@ -617,16 +829,56 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
+@@ -617,16 +832,56 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
  
    data = find_location_expression (dlbaton, &size, ax->scope);
    if (data == NULL)
@@ -8250,7 +8314,7 @@ index 8c027c9..d201f76 100644
    else
      {
 diff --git a/gdb/frame.c b/gdb/frame.c
-index 67e0607..1eb7f9d 100644
+index 67e0607..49c3013 100644
 --- a/gdb/frame.c
 +++ b/gdb/frame.c
 @@ -1109,6 +1109,14 @@ has_stack_frames (void)
@@ -8268,7 +8332,7 @@ index 67e0607..1eb7f9d 100644
    /* Don't try to read from a dead thread.  */
    if (is_exited (inferior_ptid))
      return 0;
-@@ -1843,6 +1851,17 @@ get_frame_args_address (struct frame_info *fi)
+@@ -1843,6 +1851,15 @@ get_frame_args_address (struct frame_info *fi)
    return fi->base->this_args (fi, &fi->base_cache);
  }
  
@@ -8276,28 +8340,27 @@ index 67e0607..1eb7f9d 100644
 +   otherwise.  */
 +
 +int
-+frame_base_is (struct frame_info *fi, const struct frame_base *base)
++frame_unwinder_is (struct frame_info *fi, const struct frame_unwind *unwinder)
 +{
-+  if (fi->base == NULL)
-+    fi->base = frame_base_find_by_frame (fi);
-+  return fi->base == base;
++  return fi->unwind == unwinder;
 +}
 +
  /* Level of the selected frame: 0 for innermost, 1 for its caller, ...
     or -1 for a NULL frame.  */
  
 diff --git a/gdb/frame.h b/gdb/frame.h
-index febef5c..09bf628 100644
+index febef5c..611c6d3 100644
 --- a/gdb/frame.h
 +++ b/gdb/frame.h
-@@ -696,4 +696,9 @@ extern struct frame_info *deprecated_safe_get_selected_frame (void);
+@@ -696,4 +696,10 @@ extern struct frame_info *deprecated_safe_get_selected_frame (void);
  
  extern struct frame_info *create_new_frame (CORE_ADDR base, CORE_ADDR pc);
  
-+/* Return true if the frame base for frame FI is BASE; false
++/* Return true if the frame unwinder for frame FI is UNWINDER; false
 +   otherwise.  */
 +
-+extern int frame_base_is (struct frame_info *fi, const struct frame_base *base);
++extern int frame_unwinder_is (struct frame_info *fi,
++			      const struct frame_unwind *unwinder);
 +
  #endif /* !defined (FRAME_H)  */
 diff --git a/gdb/gdbinit.in b/gdb/gdbinit.in
@@ -21677,6 +21740,382 @@ index 0000000..6922eed
 +if [test_compiler_info gcc-4-3-*] then { setup_xfail *-*-* }
 +
 +gdb_test "print x" "= 11" "Print imported namespace x"
+diff --git a/gdb/testsuite/gdb.dwarf2/callframecfa.S b/gdb/testsuite/gdb.dwarf2/callframecfa.S
+new file mode 100644
+index 0000000..6d0421a
+--- /dev/null
++++ b/gdb/testsuite/gdb.dwarf2/callframecfa.S
+@@ -0,0 +1,309 @@
++/*
++   Copyright 2009 Free Software Foundation, Inc.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++/* This was compiled from a trivial program just to test the
++   DW_OP_call_frame_cfa operator:
++
++    int func (int arg) {
++      return arg + 23;
++    }
++
++    int main(int argc, char *argv[]) {
++      func (77);
++    }
++*/
++
++	.file	"q.c"
++	.section	.debug_abbrev,"",@progbits
++.Ldebug_abbrev0:
++	.section	.debug_info,"",@progbits
++.Ldebug_info0:
++	.section	.debug_line,"",@progbits
++.Ldebug_line0:
++	.text
++.Ltext0:
++.globl func
++	.type	func, @function
++func:
++.LFB0:
++	.file 1 "q.c"
++	.loc 1 2 0
++	.cfi_startproc
++	pushl	%ebp
++	.cfi_def_cfa_offset 8
++	movl	%esp, %ebp
++	.cfi_offset 5, -8
++	.cfi_def_cfa_register 5
++	.loc 1 3 0
++	movl	8(%ebp), %eax
++	addl	$23, %eax
++	.loc 1 4 0
++	popl	%ebp
++	.cfi_restore 5
++	.cfi_def_cfa 4, 4
++	ret
++	.cfi_endproc
++.LFE0:
++	.size	func, .-func
++.globl _start
++	.type	_start, @function
++_start:
++.LFB1:
++	.loc 1 6 0
++	.cfi_startproc
++	pushl	%ebp
++	.cfi_def_cfa_offset 8
++	movl	%esp, %ebp
++	.cfi_offset 5, -8
++	.cfi_def_cfa_register 5
++	subl	$4, %esp
++	.loc 1 7 0
++	movl	$77, (%esp)
++	call	func
++	.loc 1 8 0
++	leave
++	.cfi_restore 5
++	.cfi_def_cfa 4, 4
++	ret
++	.cfi_endproc
++.LFE1:
++	.size	_start, .-_start
++.Letext0:
++	.section	.debug_info
++	.long	0x9e
++	.value	0x3
++	.long	.Ldebug_abbrev0
++	.byte	0x4
++	.uleb128 0x1
++	.long	.LASF5
++	.byte	0x1
++	.string	"q.c"
++	.long	.LASF6
++	.long	.Ltext0
++	.long	.Letext0
++	.long	.Ldebug_line0
++	.uleb128 0x2
++	.byte	0x1
++	.long	.LASF0
++	.byte	0x1
++	.byte	0x1
++	.byte	0x1
++	.long	0x4f
++	.long	.LFB0
++	.long	.LFE0
++	.byte	0x1
++	.byte	0x9c
++	.long	0x4f
++	.uleb128 0x3
++	.string	"arg"
++	.byte	0x1
++	.byte	0x1
++	.long	0x4f
++	.byte	0x2
++	.byte	0x91
++	.sleb128 0
++	.byte	0x0
++	.uleb128 0x4
++	.byte	0x4
++	.byte	0x5
++	.string	"int"
++	.uleb128 0x2
++	.byte	0x1
++	.long	.LASF1
++	.byte	0x1
++	.byte	0x6
++	.byte	0x1
++	.long	0x4f
++	.long	.LFB1
++	.long	.LFE1
++	.byte	0x1
++	.byte	0x9c
++	.long	0x8e
++	.uleb128 0x5
++	.long	.LASF2
++	.byte	0x1
++	.byte	0x6
++	.long	0x4f
++	.byte	0x2
++	.byte	0x91
++	.sleb128 0
++	.uleb128 0x5
++	.long	.LASF3
++	.byte	0x1
++	.byte	0x6
++	.long	0x8e
++	.byte	0x2
++	.byte	0x91
++	.sleb128 4
++	.byte	0x0
++	.uleb128 0x6
++	.byte	0x4
++	.long	0x94
++	.uleb128 0x6
++	.byte	0x4
++	.long	0x9a
++	.uleb128 0x7
++	.byte	0x1
++	.byte	0x6
++	.long	.LASF4
++	.byte	0x0
++	.section	.debug_abbrev
++	.uleb128 0x1
++	.uleb128 0x11
++	.byte	0x1
++	.uleb128 0x25
++	.uleb128 0xe
++	.uleb128 0x13
++	.uleb128 0xb
++	.uleb128 0x3
++	.uleb128 0x8
++	.uleb128 0x1b
++	.uleb128 0xe
++	.uleb128 0x11
++	.uleb128 0x1
++	.uleb128 0x12
++	.uleb128 0x1
++	.uleb128 0x10
++	.uleb128 0x6
++	.byte	0x0
++	.byte	0x0
++	.uleb128 0x2
++	.uleb128 0x2e
++	.byte	0x1
++	.uleb128 0x3f
++	.uleb128 0xc
++	.uleb128 0x3
++	.uleb128 0xe
++	.uleb128 0x3a
++	.uleb128 0xb
++	.uleb128 0x3b
++	.uleb128 0xb
++	.uleb128 0x27
++	.uleb128 0xc
++	.uleb128 0x49
++	.uleb128 0x13
++	.uleb128 0x11
++	.uleb128 0x1
++	.uleb128 0x12
++	.uleb128 0x1
++	.uleb128 0x40
++	.uleb128 0xa
++	.uleb128 0x1
++	.uleb128 0x13
++	.byte	0x0
++	.byte	0x0
++	.uleb128 0x3
++	.uleb128 0x5
++	.byte	0x0
++	.uleb128 0x3
++	.uleb128 0x8
++	.uleb128 0x3a
++	.uleb128 0xb
++	.uleb128 0x3b
++	.uleb128 0xb
++	.uleb128 0x49
++	.uleb128 0x13
++	.uleb128 0x2
++	.uleb128 0xa
++	.byte	0x0
++	.byte	0x0
++	.uleb128 0x4
++	.uleb128 0x24
++	.byte	0x0
++	.uleb128 0xb
++	.uleb128 0xb
++	.uleb128 0x3e
++	.uleb128 0xb
++	.uleb128 0x3
++	.uleb128 0x8
++	.byte	0x0
++	.byte	0x0
++	.uleb128 0x5
++	.uleb128 0x5
++	.byte	0x0
++	.uleb128 0x3
++	.uleb128 0xe
++	.uleb128 0x3a
++	.uleb128 0xb
++	.uleb128 0x3b
++	.uleb128 0xb
++	.uleb128 0x49
++	.uleb128 0x13
++	.uleb128 0x2
++	.uleb128 0xa
++	.byte	0x0
++	.byte	0x0
++	.uleb128 0x6
++	.uleb128 0xf
++	.byte	0x0
++	.uleb128 0xb
++	.uleb128 0xb
++	.uleb128 0x49
++	.uleb128 0x13
++	.byte	0x0
++	.byte	0x0
++	.uleb128 0x7
++	.uleb128 0x24
++	.byte	0x0
++	.uleb128 0xb
++	.uleb128 0xb
++	.uleb128 0x3e
++	.uleb128 0xb
++	.uleb128 0x3
++	.uleb128 0xe
++	.byte	0x0
++	.byte	0x0
++	.byte	0x0
++	.section	.debug_pubnames,"",@progbits
++	.long	0x20
++	.value	0x2
++	.long	.Ldebug_info0
++	.long	0xa2
++	.long	0x25
++	.string	"func"
++	.long	0x56
++	.string	"main"
++	.long	0x0
++	.section	.debug_aranges,"",@progbits
++	.long	0x1c
++	.value	0x2
++	.long	.Ldebug_info0
++	.byte	0x4
++	.byte	0x0
++	.value	0x0
++	.value	0x0
++	.long	.Ltext0
++	.long	.Letext0-.Ltext0
++	.long	0x0
++	.long	0x0
++	.section	.debug_str,"MS",@progbits,1
++.LASF5:
++	.string	"GNU C 4.5.0 20090810 (experimental) [trunk revision 150633]"
++.LASF2:
++	.string	"argc"
++.LASF6:
++	.string	"/tmp"
++.LASF0:
++	.string	"func"
++.LASF3:
++	.string	"argv"
++.LASF1:
++	.string	"main"
++.LASF4:
++	.string	"char"
++	.ident	"GCC: (GNU) 4.5.0 20090810 (experimental) [trunk revision 150633]"
++	.section	.note.GNU-stack,"",@progbits
+diff --git a/gdb/testsuite/gdb.dwarf2/callframecfa.exp b/gdb/testsuite/gdb.dwarf2/callframecfa.exp
+new file mode 100644
+index 0000000..00d67fc
+--- /dev/null
++++ b/gdb/testsuite/gdb.dwarf2/callframecfa.exp
+@@ -0,0 +1,55 @@
++# Copyright 2009 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++# Test DW_OP_call_frame_cfa.
++
++# This test can only be run on targets which support DWARF-2 and use gas.
++# For now pick a sampling of likely targets.
++if {![istarget *-*-linux*]
++    && ![istarget *-*-gnu*]
++    && ![istarget *-*-elf*]
++    && ![istarget *-*-openbsd*]
++    && ![istarget arm-*-eabi*]
++    && ![istarget powerpc-*-eabi*]} {
++    return 0  
++}
++# This test can only be run on x86 targets.
++if {![istarget i?86-*]} {
++    return 0  
++}
++
++set testfile "callframecfa"
++set srcfile ${testfile}.S
++set binfile ${objdir}/${subdir}/${testfile}.x
++
++if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
++       [list {additional_flags=-nostdlib}]] != "" } {
++    return -1
++}
++
++gdb_exit
++gdb_start
++gdb_reinitialize_dir $srcdir/$subdir
++gdb_load ${binfile}
++
++gdb_test "break *func" "Breakpoint 1.*" "set breakpoint for call-frame-cfa"
++gdb_test "run" "" "run for call-frame-cfa"
++gdb_test "display arg" "arg = 77" "set display for call-frame-cfa"
++
++# We know how many instructions are in the function.  Note that we
++# can't handle the "ret" instruction due to the epilogue unwinder.
++for {set i 1} {$i < 5} {incr i} {
++    gdb_test "si" "arg = 77" "step $i for call-frame-cfa"
++}
 diff --git a/gdb/testsuite/gdb.dwarf2/dw2-stripped.c b/gdb/testsuite/gdb.dwarf2/dw2-stripped.c
 new file mode 100644
 index 0000000..1f02d90

diff --git a/gdb.spec b/gdb.spec
index c1171f2..da9abc2 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -14,7 +14,7 @@ Version: 6.8.50.20090811
 
 # The release always contains a leading reserved number, start it at 1.
 # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
-Release: 1%{?_with_upstream:.upstream}%{?dist}
+Release: 2%{?_with_upstream:.upstream}%{?dist}
 
 License: GPLv3+
 Group: Development/Debuggers
@@ -825,6 +825,10 @@ fi
 %endif
 
 %changelog
+* Tue Aug 11 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20090811-2
+- archer-jankratochvil-fedora12 commit: 93f5e942bdcdcc376ece452c309bedabae71def9
+- Fix "can't compute CFA for this frame" (by Tom Tromey, BZ 516627).
+
 * Tue Aug 11 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20090811-1
 - Support constant DW_AT_data_member_location by GCC PR debug/40659 (BZ 515377).
 - Fix .spec URL.

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-06-27 23:54 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-27 23:54 [rpms/gdb] gdb-17.2-rebase-f44: - archer-jankratochvil-fedora12 commit: Jan Kratochvil
  -- strict thread matches above, loose matches on Subject: below --
2026-06-27 23:54 Jan Kratochvil
2026-06-27 23:54 Jan Kratochvil
2026-06-27 23:54 Jan Kratochvil
2026-06-27 23:54 Jan Kratochvil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox