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 crash on empty DWARF expressions NULL DATA vs. zero SIZE


Hi,

GDB could crash as shown in the testcase.
#1  0x0000000000750274 in dwarf_expr_eval (ctx=0x4175ce0, addr=0x0, len=4796440) at dwarf2expr.c:365
                                                               ^^^

Indication of empty (<optimized out>) or otherwise invalid DWARF expressions
some code expects to be NULL address, some code expects it to be zero size and
another code checks for either NULL address or zero size.  And some code
creates them just with zero size (and non-NULL address), other code creates
them with NULL address and undefined (=non-zero) size; some code creates them
with both NULL address and zero size.

I found safer indicator to be zero size, therefore unified to code on this
indicator.  Removed address clearing as redundant and confusing now.

No regressions on {x86_64,x86_64-m32,i686}-fedora15-linux-gnu.


Thanks,
Jan


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

	Fix empty DWARF expressions DATA vs. SIZE conditionals.
	* dwarf2loc.c (dwarf2_find_location_expression): Clear *LOCEXPR_LENGTH.
	(dwarf_expr_frame_base_1): Indicate unavailability via zero *LENGTH.
	(locexpr_tracepoint_var_ref): Check only zero SIZE, not zero DATA.
	(loclist_read_variable, loclist_tracepoint_var_ref): Do not check for
	zero DATA.
	* dwarf2loc.h (struct dwarf2_locexpr_baton): Comment DATA vs. SIZE
	validity.
	* dwarf2read.c (struct dwarf_block): Comment DATA validity.
	(dwarf2_fetch_die_location_block, dwarf2_symbol_mark_computed): Do not
	clear DATA on zero SIZE.

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

	Fix empty DWARF expressions DATA vs. SIZE conditionals.
	* gdb.dwarf2/dw2-op-call.S (arraycallnoloc, arraynoloc): New DIEs.
	(loclist): New.
	(4): New abbrev.
	* gdb.dwarf2/dw2-op-call.exp: Remove variable srcfile and executable.
	Use prepare_for_testing, remove clean_restart.
	(p arraynoloc, p arraycallnoloc): New tests.

--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -109,7 +109,10 @@ dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton,
 
       /* An end-of-list entry.  */
       if (low == 0 && high == 0)
-	return NULL;
+	{
+	  *locexpr_length = 0;
+	  return NULL;
+	}
 
       /* Otherwise, a location expression entry.  */
       low += base_address;
@@ -194,7 +197,7 @@ dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc,
 			 const gdb_byte **start, size_t *length)
 {
   if (SYMBOL_LOCATION_BATON (framefunc) == NULL)
-    *start = NULL;
+    *length = 0;
   else if (SYMBOL_COMPUTED_OPS (framefunc) == &dwarf2_loclist_funcs)
     {
       struct dwarf2_loclist_baton *symbaton;
@@ -213,10 +216,10 @@ dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc,
 	  *start = symbaton->data;
 	}
       else
-	*start = NULL;
+	*length = 0;
     }
 
-  if (*start == NULL)
+  if (*length == 0)
     error (_("Could not find the frame base for \"%s\"."),
 	   SYMBOL_NATURAL_NAME (framefunc));
 }
@@ -2788,7 +2791,7 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
   unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
 
-  if (dlbaton->data == NULL || dlbaton->size == 0)
+  if (dlbaton->size == 0)
     value->optimized_out = 1;
   else
     dwarf2_compile_expr_to_ax (ax, value, gdbarch, addr_size,
@@ -2821,11 +2824,8 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame)
   CORE_ADDR pc = frame ? get_frame_address_in_block (frame) : 0;
 
   data = dwarf2_find_location_expression (dlbaton, &size, pc);
-  if (data == NULL)
-    val = allocate_optimized_out_value (SYMBOL_TYPE (symbol));
-  else
-    val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, data, size,
-				    dlbaton->per_cu);
+  val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, data, size,
+				  dlbaton->per_cu);
 
   return val;
 }
@@ -2938,7 +2938,7 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
   unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
 
   data = dwarf2_find_location_expression (dlbaton, &size, ax->scope);
-  if (data == NULL || size == 0)
+  if (size == 0)
     value->optimized_out = 1;
   else
     dwarf2_compile_expr_to_ax (ax, value, gdbarch, addr_size, data, data + size,
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -80,10 +80,12 @@ struct value *dwarf2_evaluate_loc_desc (struct type *type,
 
 struct dwarf2_locexpr_baton
 {
-  /* Pointer to the start of the location expression.  */
+  /* Pointer to the start of the location expression.  Valid only if SIZE is
+     not zero.  */
   const gdb_byte *data;
 
-  /* Length of the location expression.  */
+  /* Length of the location expression.  For optimized out expressions it is
+     zero.  */
   unsigned long size;
 
   /* The compilation unit containing the symbol whose location
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -712,6 +712,8 @@ struct function_range
 struct dwarf_block
   {
     unsigned int size;
+
+    /* Valid only if SIZE is not zero.  */
     gdb_byte *data;
   };
 
@@ -13838,7 +13840,6 @@ dwarf2_fetch_die_location_block (unsigned int offset,
     {
       /* DWARF: "If there is no such attribute, then there is no effect.".  */
 
-      retval.data = NULL;
       retval.size = 0;
     }
   else if (attr_form_is_section_offset (attr))
@@ -14970,7 +14971,6 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
 	  dwarf2_invalid_attrib_class_complaint ("location description",
 						 SYMBOL_NATURAL_NAME (sym));
 	  baton->size = 0;
-	  baton->data = NULL;
 	}
 
       SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs;
--- a/gdb/testsuite/gdb.dwarf2/dw2-op-call.S
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-call.S
@@ -72,10 +72,30 @@ array3:	.2byte	3
 	.uleb128	array3-array1		/*     <uconst> */
 2:
 
+	.uleb128	3			/* Abbrev: DW_TAG_variable */
+	.ascii		"arraycallnoloc\0"	/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin /* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		0x99			/*   DW_OP_call4 */
+	.4byte		.Larraynoloc-.Lcu1_begin /*     <current CU offset> */
+2:
+
+.Larraynoloc:
+	.uleb128	4			/* Abbrev: DW_TAG_variable-loclist */
+	.ascii		"arraynoloc\0"		/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin /* DW_AT_type */
+	.4byte		loclist			/* DW_AT_location */
+
 	.byte		0			/* End of children of CU */
 
 .Lcu1_end:
 
+/* Location list.  */
+	.section	.debug_loc
+loclist:
+	/* Location list end.  */
+	.4byte	0, 0
+
 /* Abbrev table */
 	.section .debug_abbrev
 .Labbrev1_begin:
@@ -115,5 +135,17 @@ array3:	.2byte	3
 	.byte		0x0			/* Terminator */
 	.byte		0x0			/* Terminator */
 
+	.uleb128	4			/* Abbrev code */
+	.uleb128	0x34			/* DW_TAG_variable-loclist */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.uleb128	0x2			/* DW_AT_location */
+	.uleb128	0x06			/* DW_FORM_data4 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
 	.byte		0x0			/* Terminator */
 	.byte		0x0			/* Terminator */
--- a/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp
@@ -22,15 +22,17 @@ if {![dwarf2_support]} {
 }
 
 set testfile "dw2-op-call"
-set srcfile ${testfile}.S
-set executable ${testfile}.x
-
-if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objdir}/${subdir}/${executable}" object {nodebug}] != "" } {
+if { [prepare_for_testing ${testfile}.exp ${testfile} [list ${testfile}.S main.c] {nodebug}] } {
     return -1
 }
 
-clean_restart $executable
-
 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"
+
+# Location lists need PC.
+if ![runto_main] {
+    return -1
+}
+gdb_test "p arraynoloc" " = <optimized out>"
+gdb_test "p arraycallnoloc" {Asked for position 0 of stack, stack only has 0 elements on it\.}


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