[gdb/testsuite] Don't use default form in Dwarf::_guess_form
authorTom de Vries <tdevries@suse.de>
Fri, 23 Oct 2020 16:49:48 +0000 (18:49 +0200)
committerTom de Vries <tdevries@suse.de>
Fri, 23 Oct 2020 16:49:48 +0000 (18:49 +0200)
The only possible form for a DW_AT_low_pc attribute is DW_FORM_addr.

When specifying in dwarf assembly a low_pc attribute without explicit form:
...
  {low_pc {main_label - 4}}
...
the resulting attribute uses DW_FORM_string, which is misinterpreted by gdb
when reading it as:
...
        cu->base_address = attr->as_address ();
...

Stop using DW_FORM_string as default form.  Instead, use a default form based
on the attribute name, if possible and unambiguous.  Otherwise, error out.

F.i.:
- for DW_AT_low_pc we use DW_FORM_addr.
- For DW_AT_high_pc, we don't specify a default form because it could be
  either address or constant class.
- For DW_AT_name, we use DW_FORM_string.  While we could encode with
  DW_FORM_strp instead, DW_FORM_string is always ok.

Tested on x86_64-linux.

gdb/testsuite/ChangeLog:

2020-10-23  Tom de Vries  <tdevries@suse.de>

* lib/dwarf.exp (Dwarf::_guess_form): Return "" by default instead of
DW_FORM_string.
(Dwarf::_default_form): New proc.
(Dwarf::_handle_DW_TAG): Use _default_form.  Error out if no form was
guessed.

gdb/testsuite/ChangeLog
gdb/testsuite/lib/dwarf.exp

index 2683237a34f832da2b2c56bf83565841ca106a85..e2944f21806c7e3f4f44caab530bc91178fcf888 100644 (file)
@@ -1,3 +1,11 @@
+2020-10-23  Tom de Vries  <tdevries@suse.de>
+
+       * lib/dwarf.exp (Dwarf::_guess_form): Return "" by default instead of
+       DW_FORM_string.
+       (Dwarf::_default_form): New proc.
+       (Dwarf::_handle_DW_TAG): Use _default_form.  Error out if no form was
+       guessed.
+
 2020-10-23  Tom de Vries  <tdevries@suse.de>
 
        * gdb.dwarf2/ada-linkage-name.exp: Use $srcfile for DW_AT_name of CU.
index 5c8406310523c8915e23397ad4c95565766fb731..1a0cbf689e6a13c2a0ab12dc39d93c9528a22b8a 100644 (file)
@@ -247,11 +247,10 @@ proc get_func_info { name {options {debug}} } {
 #   and DW_FORM_ref4 is used.  See 'new_label' and 'define_label'.
 # * If VALUE starts with the "%" character, then it is a label
 #   reference too, but DW_FORM_ref_addr is used.
-# * Otherwise, VALUE is taken to be a string and DW_FORM_string is
-#   used.  In order to prevent bugs where a numeric value is given but
-#   no form is specified, it is an error if the value looks like a number
-#   (using Tcl's "string is integer") and no form is provided.
-# More form-guessing functionality may be added.
+# * Otherwise, if the attribute name has a default form (f.i. DW_FORM_addr for
+#   DW_AT_low_pc), then that one is used.
+# * Otherwise, an error is reported.  Either specify a form explicitly, or
+#   add a default for the the attribute name in _default_form.
 #
 # CHILDREN is just Tcl code that can be used to define child DIEs.  It
 # is evaluated in the caller's context.
@@ -590,9 +589,25 @@ namespace eval Dwarf {
            }
 
            default {
+               return ""
+           }
+       }
+    }
+
+    proc _default_form { attr } {
+       switch -exact -- $attr {
+           DW_AT_low_pc  {
+               return DW_FORM_addr
+           }
+           DW_AT_producer -
+           DW_AT_comp_dir -
+           DW_AT_linkage_name -
+           DW_AT_MIPS_linkage_name -
+           DW_AT_name {
                return DW_FORM_string
            }
        }
+       return ""
     }
 
     # Map NAME to its canonical form.
@@ -692,11 +707,13 @@ namespace eval Dwarf {
                        _guess_form $attr_value attr_value
                    }
                } else {
-                   # If the value looks like an integer, a form is required.
-                   if [string is integer $attr_value] {
-                       error "Integer value requires a form"
-                   }
                    set attr_form [_guess_form $attr_value attr_value]
+                   if { $attr_form eq "" } {
+                       set attr_form [_default_form $attr_name]
+                   }
+                   if { $attr_form eq "" } {
+                       error "No form for $attr_name $attr_value"
+                   }
                }
                set attr_form [_map_name $attr_form _FORM]