This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Fix DW_OP_call2 and DW_OP_call4 for max-cache-age 0 #2


On Thu, 02 Sep 2010 20:39:58 +0200, Doug Evans wrote:
> Assuming (and I don't know dwarf2_fetch_die_location_block well) just
> needs the dies and not a symtab,

Yes, it needs CU but not symtab.  I guess I probably messed up these two
before.


> how about moving this bit of code to
> its own function, and calling it from both dw2_do_instantiate_symtab
> and dwarf2_fetch_die_location_block.
> 
>     if (per_cu->from_debug_types)
>       read_signatured_type_at_offset (objfile, per_cu->offset);
>     else
>       load_full_comp_unit (per_cu, objfile);

Done.


> max-cache-age == 0 is defined to disable the cache.  It's a useful
> test vehicle, and I don't see any reason to disallow it either.

The testsuite now PASSes with max-cache-age == 0.  I haven't made it a global
default.


That `if' there is in fact a workaround, `load_cu' could be called
unconditionally:
+  if (per_cu->cu == NULL)
+    load_cu (per_cu);

But such conditional for load_full_comp_unit is already present there as in
follow_die_offset and it faces a change in:
	Re: [RFA] template names with arguments out of DW_AT_name
	http://sourceware.org/ml/gdb-patches/2010-08/msg00161.html
which implemented RealView compatibility without a testcase and RealView
download is only for MS-Windows (I haven't tried if it is Wine compatible).

Anyway I find that conditional need there as a different Bug.

No regressions on {x86_64,x86_64-m32,i686}-fedora15-linux-gnu.  Also with no
global "maintenance set dwarf2 max-cache-age 0".


Thanks,
Jan


gdb/
2011-07-13  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Fix crash if referenced CU is aged out.
	* dwarf2loc.c (per_cu_dwarf_call): New variable back_to, use to for
	xfree of block.data.
	(indirect_pieced_value): New variable back_to, use to for xfree of
	baton.data.
	(dwarf2_compile_expr_to_ax): New variable back_to, use to for xfree of
	block.data.
	* dwarf2read.c (dwarf2_find_base_address): New prototype.
	(load_cu): New function from ...
	(dw2_do_instantiate_symtab): ... the code here ...
	(process_full_comp_unit): ... and here.
	(dwarf2_fetch_die_location_block): Call load_cu first.  Call xmemdup on
	retval.data.

gdb/testsuite/
2011-07-13  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.dwarf2/dw2-op-call.exp (maintenance set dwarf2 max-cache-age 0):
	New.
	* gdb.dwarf2/implptr.exp: Likewise.

--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -265,14 +268,19 @@ per_cu_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset,
 		   void *baton)
 {
   struct dwarf2_locexpr_baton block;
+  struct cleanup *back_to;
 
   block = dwarf2_fetch_die_location_block (die_offset, per_cu,
 					   get_frame_pc, baton);
 
+  back_to = make_cleanup (xfree, (void *) block.data);
+
   /* DW_OP_call_ref is currently not supported.  */
   gdb_assert (block.per_cu == per_cu);
 
   dwarf_expr_eval (ctx, block.data, block.size);
+
+  do_cleanups (back_to);
 }
 
 /* Helper interface of per_cu_dwarf_call for dwarf2_evaluate_loc_desc.  */
@@ -966,6 +974,7 @@ indirect_pieced_value (struct value *value)
   struct dwarf_expr_piece *piece = NULL;
   struct value *result;
   LONGEST byte_offset;
+  struct cleanup *back_to;
 
   type = value_type (value);
   if (TYPE_CODE (type) != TYPE_CODE_PTR)
@@ -1013,10 +1022,14 @@ indirect_pieced_value (struct value *value)
 					   get_frame_address_in_block_wrapper,
 					   frame);
 
+  back_to = make_cleanup (xfree, (void *) baton.data);
+
   result = dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame,
 					  baton.data, baton.size, baton.per_cu,
 					  byte_offset);
 
+  do_cleanups (back_to);
+
   return result;
 }
 
@@ -2108,12 +2121,14 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
 	  {
 	    struct dwarf2_locexpr_baton block;
 	    int size = (op == DW_OP_call2 ? 2 : 4);
+	    struct cleanup *back_to;
 
 	    uoffset = extract_unsigned_integer (op_ptr, size, byte_order);
 	    op_ptr += size;
 
 	    block = dwarf2_fetch_die_location_block (uoffset, per_cu,
 						     get_ax_pc, expr);
+	    back_to = make_cleanup (xfree, (void *) block.data);
 
 	    /* DW_OP_call_ref is currently not supported.  */
 	    gdb_assert (block.per_cu == per_cu);
@@ -2121,6 +2136,8 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
 	    dwarf2_compile_expr_to_ax (expr, loc, arch, addr_size,
 				       block.data, block.data + block.size,
 				       per_cu);
+
+	    do_cleanups (back_to);
 	  }
 	  break;
 
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -884,6 +884,9 @@ static void dwarf2_locate_sections (bfd *, asection *, void *);
 static void dwarf2_create_include_psymtab (char *, struct partial_symtab *,
                                            struct objfile *);
 
+static void dwarf2_find_base_address (struct die_info *die,
+				      struct dwarf2_cu *cu);
+
 static void dwarf2_build_psymtabs_hard (struct objfile *);
 
 static void scan_partial_symbols (struct partial_die_info *,
@@ -1788,6 +1791,23 @@ create_quick_file_names_table (unsigned int nr_initial_entries)
 			    delete_file_name_entry, xcalloc, xfree);
 }
 
+/* Read in PER_CU->CU.  This function is unrelated to symtabs, symtab would
+   have to be created afterwards.  You should call age_cached_comp_units after
+   processing PER_CU->CU.  dw2_setup must have been already called.  */
+
+static void
+load_cu (struct dwarf2_per_cu_data *per_cu)
+{
+  if (per_cu->from_debug_types)
+    read_signatured_type_at_offset (per_cu->objfile, per_cu->offset);
+  else
+    load_full_comp_unit (per_cu, per_cu->objfile);
+
+  dwarf2_find_base_address (per_cu->cu->dies, per_cu->cu);
+
+  gdb_assert (per_cu->cu != NULL);
+}
+
 /* Read in the symbols for PER_CU.  OBJFILE is the objfile from which
    this CU came.  */
 
@@ -1801,10 +1821,7 @@ dw2_do_instantiate_symtab (struct objfile *objfile,
 
   queue_comp_unit (per_cu, objfile);
 
-  if (per_cu->from_debug_types)
-    read_signatured_type_at_offset (objfile, per_cu->offset);
-  else
-    load_full_comp_unit (per_cu, objfile);
+  load_cu (per_cu);
 
   process_queue (objfile);
 
@@ -4714,8 +4731,6 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
 
   cu->list_in_scope = &file_symbols;
 
-  dwarf2_find_base_address (cu->dies, cu);
-
   /* Do line number decoding in read_file_scope () */
   process_die (cu->dies, cu);
 
@@ -13813,7 +13828,8 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr,
 }
 
 /* Return DWARF block and its CU referenced by OFFSET at PER_CU.  Returned
-   value is intended for DW_OP_call*.  */
+   value is intended for DW_OP_call*.  You must call xfree on returned
+   dwarf2_locexpr_baton->data.  */
 
 struct dwarf2_locexpr_baton
 dwarf2_fetch_die_location_block (unsigned int offset,
@@ -13821,13 +13837,17 @@ dwarf2_fetch_die_location_block (unsigned int offset,
 				 CORE_ADDR (*get_frame_pc) (void *baton),
 				 void *baton)
 {
-  struct dwarf2_cu *cu = per_cu->cu;
+  struct dwarf2_cu *cu;
   struct die_info *die;
   struct attribute *attr;
   struct dwarf2_locexpr_baton retval;
 
   dw2_setup (per_cu->objfile);
 
+  if (per_cu->cu == NULL)
+    load_cu (per_cu);
+  cu = per_cu->cu;
+
   die = follow_die_offset (offset, &cu);
   if (!die)
     error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
@@ -13864,6 +13884,12 @@ dwarf2_fetch_die_location_block (unsigned int offset,
       retval.size = DW_BLOCK (attr)->size;
     }
   retval.per_cu = cu->per_cu;
+
+  if (retval.data)
+    retval.data = xmemdup (retval.data, retval.size, retval.size);
+
+  age_cached_comp_units ();
+
   return retval;
 }
 
--- a/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp
@@ -31,6 +31,9 @@ if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objdir}/${subdir}/${execu
 
 clean_restart $executable
 
+# Additional test to verify the referenced CU is not aged out.
+gdb_test_no_output "maintenance set dwarf2 max-cache-age 0"
+
 gdb_test "p array1" " = 1"
 gdb_test "p array2" " = 2" "array2 using DW_OP_call2"
 gdb_test "p array3" " = 3" "array3 using DW_OP_call4"
--- a/gdb/testsuite/gdb.dwarf2/implptr.exp
+++ b/gdb/testsuite/gdb.dwarf2/implptr.exp
@@ -34,6 +34,9 @@ if {[prepare_for_testing ${testfile}.exp ${testfile}.x $srcfile]} {
     return -1
 }
 
+# Additional test to verify the referenced CU is not aged out.
+gdb_test_no_output "maintenance set dwarf2 max-cache-age 0"
+
 if ![runto_main] {
     return -1
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]