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/rfc] Recognize non-DW_AT_location <value optimized out> symbols


Hi,

this patch is far from a perfect solution but it would be fine to check it in
if there is an approval as this patch is a regression-free GDB improvement:

for:
echo 'int main () { int x = 42; return x; }' | gcc -Wall -O2 -g -x c -

current GDB prints:
(gdb) p x
No symbol "x" in current context.
(gdb) ptype x
No symbol "x" in current context.

while patched GDB prints:
(gdb) p x
$1 = <value optimized out>
(gdb) ptype x
type = int

It can also happen for gcc-4.4 -O0 -g but that is more its bug (PR debug/39474).

With the current -O2 debugging situation I find the `No symbol ...' statements
even more confusing than pragmatic <value optimized out>.

Still this patch is just a fixup of the current incorrect GDB parsing code,
the proper solution should rewrite it from scratch.  But it has no regressions
on x86_64-unknown-linux-gnu so it is at least an improvement.

Existing problems even with this patch:

* zero-length DW_AT_location should be the same as missing DW_AT_location.
  https://fedorahosted.org/pipermail/elfutils-devel/2009-March/000180.html

  GCC seems to use zero-length DW_AT_location for optimized-out variables and
  no DW_AT_location if it fails to provide it for whatever reason.  But not
  always.

  If GDB would always use zero-length DW_AT_location for optimized-out symbols
  vs. no DW_AT_location for non-defining declarations this GDB patch would not
  be needed as this is the current (DWARF-noncompliant) GDB expectation.

* Missing DWARF3 2.13.2 Declarations Completing Non-Defining Declarations:
Current ignorance of LOC_OPTIMIZED_OUT symbols was used for C++ symbols
completion.  Fixing the LOC_OPTIMIZED_OUT symbols presents break C++ symbols
completion as the code then recognizes the first instance of the symbol (even
if it is LOC_OPTIMIZED_OUT) thus ignoring its later completion such as for:
 <3><247>: Abbrev Number: 18 (DW_TAG_variable)
    <248>   DW_AT_name        : cX
    <24d>   DW_AT_type        : <0xca>
    <251>   DW_AT_declaration : 1
 <1><5c5>: Abbrev Number: 37 (DW_TAG_variable)
    <5c6>   DW_AT_specification: <0x247>
    <5ca>   DW_AT_const_value : 6
The insert_symbol_hashed() part of the patch fixes up this specific case to
have no testsuite regressions on gcc.  Still a more general fix should be made.

* For external variables it still prints
    Address of symbol "foo" is unknown.
  while it should print
    <value optimized out>
  because (read_var_value <LOC_UNRESOLVED> <msym == NULL>) should return
  not_lval+set_value_optimized_out but providing such patch causes regression
  on other GDB C++ support code.

* The updated testcase is probably incompatible with Alpha (larger than 32bit
  file addresses), also it should test more types of symbol placements, `main'
  range is not correct, CU range is not correct etc.

Updated patch fixes for current GDB its new testcases:
FAIL: gdb.dwarf2/dw2-noloc.exp: print noloc_local  (file-scope optimized-out)
FAIL: gdb.dwarf2/dw2-noloc.exp: ptype noloc_local
FAIL: gdb.dwarf2/dw2-noloc.exp: print noloc_local2 (function-scope optimized-out)
FAIL: gdb.dwarf2/dw2-noloc.exp: ptype noloc_local2


Thanks,
Jan

gdb/
2009-03-16  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Recognize missing DW_AT_location as <value optimized out>.
	* dictionary.c (insert_symbol_hashed): New variables `iterp', `iter'.
	Remove non-defining declaration completed by later declarations.
	* dwarf2read.c
	(new_symbol <DW_TAG_variable> <!DW_AT_location> <!DW_AT_external>):
	Call add_symbol_to_list.

gdb/testsuite/
2009-03-16  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.dwarf2/dw2-noloc.exp: Compile main.c with nodebug.
	(print noloc): Rename to ...
	(print noloc_unresolvable): ... here.
	(print hasloc_direct, print hasloc_resolvable, print noloc_local)
	(print hasloc_direct2, print hasloc_resolvable2)
	(print noloc_unresolvable2, print noloc_local2): New.
	* gdb.dwarf2/dw2-noloc.S (main_end, hasloc_resolvable)
	(hasloc_resolvable2): New.
	(DW_AT_high_pc): Change it to `main_end'.
	(noloc): Rename to ...
	(noloc_unresolvable): ... here.
	(hasloc_direct, hasloc_resolvable, noloc_local, hasloc_direct2)
	(hasloc_resolvable2, noloc_unresolvable2, noloc_local2): New.

--- gdb/dictionary.c	3 Jan 2009 05:57:51 -0000	1.10
+++ gdb/dictionary.c	16 Mar 2009 18:18:49 -0000
@@ -670,10 +670,34 @@ insert_symbol_hashed (struct dictionary 
 		      struct symbol *sym)
 {
   unsigned int hash_index;
-  struct symbol **buckets = DICT_HASHED_BUCKETS (dict);
+  struct symbol **buckets = DICT_HASHED_BUCKETS (dict), **iterp, *iter;
 
   hash_index = (msymbol_hash_iw (SYMBOL_SEARCH_NAME (sym))
 		% DICT_HASHED_NBUCKETS (dict));
+
+  /* Remove non-defining declaration completed by later declarations
+     (DWARF3 2.13.2).  As there may be multiple symbols of the same
+     SYMBOL_SEARCH_NAME but different SYMBOL_CLASS replace only those that have
+     lower validity (in the order of LOC* > LOC_UNRESOLVED > LOC_OPTIMIZED_OUT).
+
+     dict_create_linear should also contain such code but the C++ declarations
+     completing in practice exists only for file/global symbols which are being
+     indexed only using this function insert_symbol_hashed.
+
+     As this function is called in a reverse order than the placement of the
+     symbols in the inferior the RETURN statement will ensure the symbol gets
+     replaced.  */
+
+  if (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT
+      || SYMBOL_CLASS (sym) == LOC_UNRESOLVED)
+    for (iterp = &buckets[hash_index]; (iter = *iterp) != NULL;
+	 iterp = &iter->hash_next)
+      if (strcmp (SYMBOL_SEARCH_NAME (iter), SYMBOL_SEARCH_NAME (sym)) == 0
+	  && (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT
+	      || (SYMBOL_CLASS (sym) == LOC_UNRESOLVED
+		  && SYMBOL_CLASS (iter) == LOC_OPTIMIZED_OUT)))
+	return;
+
   sym->hash_next = buckets[hash_index];
   buckets[hash_index] = sym;
 }
--- gdb/dwarf2read.c	9 Mar 2009 18:53:48 -0000	1.296
+++ gdb/dwarf2read.c	16 Mar 2009 18:18:53 -0000
@@ -7658,6 +7658,11 @@ new_symbol (struct die_info *die, struct
 		  SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
 		  add_symbol_to_list (sym, &global_symbols);
 		}
+	      else
+		{
+		  /* Use the default LOC_OPTIMIZED_OUT class.  */
+		  add_symbol_to_list (sym, cu->list_in_scope);
+		}
 	    }
 	  break;
 	case DW_TAG_formal_parameter:
--- gdb/testsuite/gdb.dwarf2/dw2-noloc.S	3 Jan 2009 05:58:04 -0000	1.4
+++ gdb/testsuite/gdb.dwarf2/dw2-noloc.S	16 Mar 2009 18:18:54 -0000
@@ -26,6 +26,15 @@ func_cu1:
 	.size func_cu1, .-func_cu1
 .Lend_text1:
 
+	.equ	main_end, main + 0x100		/* Just an estimate.  */
+
+	.data
+	.globl hasloc_resolvable
+	.globl hasloc_resolvable2
+hasloc_resolvable:
+hasloc_resolvable2:
+	.4byte	1234567890
+
 /* Debug information */
 
 	.section .debug_info
@@ -40,7 +49,7 @@ func_cu1:
 	/* CU die */
 	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
 	.4byte	.Lline1_begin			/* DW_AT_stmt_list */
-	.4byte	.Lend_text1			/* DW_AT_high_pc */
+	.4byte	main_end			/* DW_AT_high_pc */
 	.4byte	.Lbegin_text1			/* DW_AT_low_pc */
 	.ascii	"file1.txt\0"			/* DW_AT_name */
 	.ascii	"GNU C 3.3.3\0"			/* DW_AT_producer */
@@ -64,11 +73,65 @@ func_cu1:
 	.byte		4			/* DW_AT_byte_size */
 	.byte		5			/* DW_AT_encoding */
 
-	.uleb128	4			/* Abbrev: DW_TAG_variable */
-	.ascii		"noloc\0"		/* DW_AT_name */
+	.uleb128	7			/* Abbrev: DW_TAG_variable (location) */
+	.ascii		"hasloc_direct\0"	/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:
+	.byte		3			/*   DW_OP_addr */
+	.4byte		hasloc_resolvable	/*   <addr> */
+2:
+
+	.uleb128	4			/* Abbrev: DW_TAG_variable (extern) */
+	.ascii		"hasloc_resolvable\0"	/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+	.byte		1			/* DW_AT_external */
+
+	.uleb128	4			/* Abbrev: DW_TAG_variable (extern) */
+	.ascii		"noloc_unresolvable\0"	/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+	.byte		1			/* DW_AT_external */
+
+	.uleb128	5			/* Abbrev: DW_TAG_variable (local) */
+	.ascii		"noloc_local\0"		/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+
+	/* main */
+	.uleb128	6			/* Abbrev: DW_TAG_subprogram */
+	.byte		1			/* DW_AT_decl_file */
+	.byte		2			/* DW_AT_decl_line */
+	.ascii		"main\0"		/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+	.4byte		main			/* DW_AT_low_pc */
+	.4byte		main_end		/* DW_AT_high_pc */
+	.byte		1			/* DW_AT_frame_base: length */
+	.byte		0x55			/* DW_AT_frame_base: DW_OP_reg5 */
+
+	.uleb128	7			/* Abbrev: DW_TAG_variable (location) */
+	.ascii		"hasloc_direct2\0"	/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:
+	.byte		3			/*   DW_OP_addr */
+	.4byte		hasloc_resolvable	/*   <addr> */
+2:
+
+	.uleb128	4			/* Abbrev: DW_TAG_variable (extern) */
+	.ascii		"hasloc_resolvable2\0"	/* DW_AT_name */
 	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
 	.byte		1			/* DW_AT_external */
 
+	.uleb128	4			/* Abbrev: DW_TAG_variable (extern) */
+	.ascii		"noloc_unresolvable2\0"	/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+	.byte		1			/* DW_AT_external */
+
+	.uleb128	5			/* Abbrev: DW_TAG_variable (local) */
+	.ascii		"noloc_local2\0"	/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+
+	.byte		0			/* End of children of main */
+
 	.byte		0			/* End of children of CU */
 
 .Lcu1_end:
@@ -128,7 +191,7 @@ func_cu1:
 	.byte		0x0			/* Terminator */
 	.byte		0x0			/* Terminator */
 
-	.uleb128	4			/* Abbrev code */
+	.uleb128	4			/* Abbrev code (extern) */
 	.uleb128	0x34			/* DW_TAG_variable */
 	.byte		0			/* has_children */
 	.uleb128	0x3			/* DW_AT_name */
@@ -140,6 +203,48 @@ func_cu1:
 	.byte		0x0			/* Terminator */
 	.byte		0x0			/* Terminator */
 
+	.uleb128	5			/* Abbrev code (local) */
+	.uleb128	0x34			/* DW_TAG_variable */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	6			/* Abbrev code */
+	.uleb128	0x2e			/* DW_TAG_subprogram */
+	.byte		1			/* has_children */
+	.uleb128	0x3a			/* DW_AT_decl_file */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3b			/* DW_AT_decl_line */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.uleb128	0x11			/* DW_AT_low_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x12			/* DW_AT_high_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x40			/* DW_AT_frame_base */
+	.uleb128	0xa			/* DW_FORM_block1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	7			/* Abbrev code (location) */
+	.uleb128	0x34			/* DW_TAG_variable */
+	.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	0xa			/* DW_FORM_block1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
 	.byte		0x0			/* Terminator */
 	.byte		0x0			/* Terminator */
 
--- gdb/testsuite/gdb.dwarf2/dw2-noloc.exp	3 Jan 2009 05:58:04 -0000	1.4
+++ gdb/testsuite/gdb.dwarf2/dw2-noloc.exp	16 Mar 2009 18:18:54 -0000
@@ -28,7 +28,7 @@ set testfile "dw2-noloc"
 set srcfile ${testfile}.S
 set binfile ${objdir}/${subdir}/${testfile}.x
 
-if  { [gdb_compile "${srcdir}/${subdir}/main.c" "main.o" object {debug}] != "" } {
+if  { [gdb_compile "${srcdir}/${subdir}/main.c" "main.o" object {nodebug}] != "" } {
     return -1
 }
 
@@ -45,4 +45,30 @@ gdb_start
 gdb_reinitialize_dir $srcdir/$subdir
 gdb_load ${binfile}
 
-gdb_test "print noloc" "Address of symbol \"noloc\" is unknown." "print noloc"
+gdb_test "print hasloc_direct" "= 1234567890"
+gdb_test "ptype hasloc_direct" "type = int"
+
+gdb_test "print hasloc_resolvable" "= 1234567890"
+gdb_test "ptype hasloc_resolvable" "type = int"
+
+gdb_test "print noloc_unresolvable" "Address of symbol \"noloc_unresolvable\" is unknown\\."
+gdb_test "ptype noloc_unresolvable" "type = int"
+
+gdb_test "print noloc_local" "= <value optimized out>"
+gdb_test "ptype noloc_local" "type = int"
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test "print hasloc_direct2" "= 1234567890"
+gdb_test "ptype hasloc_direct2" "type = int"
+
+gdb_test "print hasloc_resolvable2" "= 1234567890"
+gdb_test "ptype hasloc_resolvable2" "type = int"
+
+gdb_test "print noloc_unresolvable2" "Address of symbol \"noloc_unresolvable2\" is unknown\\."
+gdb_test "ptype noloc_unresolvable2" "type = int"
+
+gdb_test "print noloc_local2" "= <value optimized out>"
+gdb_test "ptype noloc_local2" "type = int"


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