Add some error checking to DWARF assembler
authorTom Tromey <tromey@adacore.com>
Wed, 31 Mar 2021 15:17:23 +0000 (09:17 -0600)
committerTom Tromey <tromey@adacore.com>
Wed, 31 Mar 2021 15:17:23 +0000 (09:17 -0600)
I had written a DWARF location expression like

    DW_OP_const1u
    DW_OP_stack_value

... and was surprised to see that the DW_OP_stack_value didn't appear
in the "readelf" output.

The problem here is that DW_OP_const1u requires an operand, but
neither the DWARF assembler nor gas diagnosed this problem.

This patch adds some checking to Dwarf::_location to try to avoid this
in the future.  The checking is done via a helper proc that also
dissects the argument list and sets an array in the caller's frame.

gdb/testsuite/ChangeLog
2021-03-31  Tom Tromey  <tromey@adacore.com>

* lib/dwarf.exp (Dwarf::_get_args): New proc.
(Dwarf::_location): Use it.

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

index 2c73da6ade13ce17335ec88082168ffc72dfaf8b..eb655a0ab8a8c8a23014e8a33f7cc2bc1853b1ed 100644 (file)
@@ -1,3 +1,8 @@
+2021-03-31  Tom Tromey  <tromey@adacore.com>
+
+       * lib/dwarf.exp (Dwarf::_get_args): New proc.
+       (Dwarf::_location): Use it.
+
 2021-03-31  Tom de Vries  <tdevries@suse.de>
 
        PR testsuite/27667
index 4cd5e16c60401cbe3995327588c4fced009a4df7..b9a493863a879277b2b33fb0e147ac9165a89d1c 100644 (file)
@@ -890,6 +890,20 @@ namespace eval Dwarf {
        }
     }
 
+    # Assign elements from LINE to the elements of an array named
+    # "argvec" in the caller scope.  The keys used are named in ARGS.
+    # If the wrong number of elements appear in LINE, error.
+    proc _get_args {line op args} {
+       if {[llength $line] != [llength $args] + 1} {
+           error "usage: $op [string toupper $args]"
+       }
+
+       upvar argvec argvec
+       foreach var $args value [lreplace $line 0 0] {
+           set argvec($var) $value
+       }
+    }
+
     # This is a miniature assembler for location expressions.  It is
     # suitable for use in the attributes to a DIE.  Its output is
     # prefixed with "=" to make it automatically use DW_FORM_block.
@@ -924,59 +938,72 @@ namespace eval Dwarf {
            set opcode [_map_name [lindex $line 0] _OP]
            _op .byte $_constants($opcode) $opcode
 
+           array unset argvec *
            switch -exact -- $opcode {
                DW_OP_addr {
-                   _op .${addr_size}byte [lindex $line 1]
+                   _get_args $line $opcode size
+                   _op .${addr_size}byte $argvec(size)
                }
 
                DW_OP_regx {
-                   _op .uleb128 [lindex $line 1]
+                   _get_args $line $opcode register
+                   _op .uleb128 $argvec(register)
                }
 
                DW_OP_pick -
                DW_OP_const1u -
                DW_OP_const1s {
-                   _op .byte [lindex $line 1]
+                   _get_args $line $opcode const
+                   _op .byte $argvec(const)
                }
 
                DW_OP_const2u -
                DW_OP_const2s {
-                   _op .2byte [lindex $line 1]
+                   _get_args $line $opcode const
+                   _op .2byte $argvec(const)
                }
 
                DW_OP_const4u -
                DW_OP_const4s {
-                   _op .4byte [lindex $line 1]
+                   _get_args $line $opcode const
+                   _op .4byte $argvec(const)
                }
 
                DW_OP_const8u -
                DW_OP_const8s {
-                   _op .8byte [lindex $line 1]
+                   _get_args $line $opcode const
+                   _op .8byte $argvec(const)
                }
 
                DW_OP_constu {
-                   _op .uleb128 [lindex $line 1]
+                   _get_args $line $opcode const
+                   _op .uleb128 $argvec(const)
                }
                DW_OP_consts {
-                   _op .sleb128 [lindex $line 1]
+                   _get_args $line $opcode const
+                   _op .sleb128 $argvec(const)
                }
 
                DW_OP_plus_uconst {
-                   _op .uleb128 [lindex $line 1]
+                   _get_args $line $opcode const
+                   _op .uleb128 $argvec(const)
                }
 
                DW_OP_piece {
-                   _op .uleb128 [lindex $line 1]
+                   _get_args $line $opcode size
+                   _op .uleb128 $argvec(size)
                }
 
                DW_OP_bit_piece {
-                   _op .uleb128 [lindex $line 1]
-                   _op .uleb128 [lindex $line 2]
+                   _get_args $line $opcode size offset
+                   _op .uleb128 $argvec(size)
+                   _op .uleb128 $argvec(offset)
                }
 
                DW_OP_skip -
                DW_OP_bra {
-                   _op .2byte [lindex $line 1]
+                   _get_args $line $opcode label
+                   _op .2byte $argvec(label)
                }
 
                DW_OP_implicit_value {
@@ -1000,45 +1027,37 @@ namespace eval Dwarf {
 
                DW_OP_implicit_pointer -
                DW_OP_GNU_implicit_pointer {
-                   if {[llength $line] != 3} {
-                       error "usage: $opcode LABEL OFFSET"
-                   }
+                   _get_args $line $opcode label offset
 
                    # Here label is a section offset.
-                   set label [lindex $line 1]
                    if { $dwarf_version == 2 } {
-                       _op .${addr_size}byte $label
+                       _op .${addr_size}byte $argvec(label)
                    } else {
-                       _op .${offset_size}byte $label
+                       _op .${offset_size}byte $argvec(label)
                    }
-                   _op .sleb128 [lindex $line 2]
+                   _op .sleb128 $argvec(offset)
                }
 
                DW_OP_GNU_variable_value {
-                   if {[llength $line] != 2} {
-                       error "usage: $opcode LABEL"
-                   }
+                   _get_args $line $opcode label
 
                    # Here label is a section offset.
-                   set label [lindex $line 1]
                    if { $dwarf_version == 2 } {
-                       _op .${addr_size}byte $label
+                       _op .${addr_size}byte $argvec(label)
                    } else {
-                       _op .${offset_size}byte $label
+                       _op .${offset_size}byte $argvec(label)
                    }
                }
 
                DW_OP_deref_size {
-                   if {[llength $line] != 2} {
-                       error "usage: DW_OP_deref_size SIZE"
-                   }
-
-                   _op .byte [lindex $line 1]
+                   _get_args $line $opcode size
+                   _op .byte $argvec(size)
                }
 
                DW_OP_bregx {
-                   _op .uleb128 [lindex $line 1]
-                   _op .sleb128 [lindex $line 2]
+                   _get_args $line $opcode register offset
+                   _op .uleb128 $argvec(register)
+                   _op .sleb128 $argvec(offset)
                }
 
                default {