Re: [PATCH] gdb.dwarf2: Define and use gdb_target_symbol_prefix for symbol prefixes

Kevin Buettner
2015-11-04T21:49:15Z

On Fri, 30 Oct 2015 11:06:09 +0000
Pedro Alves <palves@redhat.com> wrote:

> On 10/30/2015 04:25 AM, Kevin Buettner wrote:
>
> > +# gdb_target_symbol_prefix compiles a test program and uses readelf
> > +# to determine the prefix (such as underscore) for linker symbol
> > +# prefixes.
> > +
> > +proc gdb_target_symbol_prefix {} {
>
> Shouldn't this be gdb_caching_proc ?

Yes, it should. I've fixed this in my new patch.

> Then T wonder whether something like:
>
> - DW_OP_addr table_2_ptr
> + DW_OP_addr [gdb_symbol table_2_ptr]
>
> instead of prepending the $prefix variable results in clearer
> test code.

I like this idea too. I used the name 'gdb_target_symbol' for this.

Defining the obvious proc (for gdb_target_symbol) worked out of the
box for all cases except gdb.dwarf2/atomic-type.exp. For that I
needed to make a change to lib/dwarf.exp (and learned a bit more about
tcl in the process). If you know of a cleaner way to code it, let me
know - I couldn't think of a way to do it without adding the if-else
statement.

> > + set readelf_program [gdb_find_readelf]
> > + set result [catch "exec $readelf_program --syms $exe" output]
> > +
> > + if { $result == 0 \
> > + && ![regexp { ([^ a-zA-Z0-9]*)main$} $output dummy prefix] } {
> > + verbose "gdb_target_symbol_prefix: Could not find main in readelf output; returning null prefix" 2
> > + }
>
> I'm wondering about using a method that would work for mingw/cygwin
> as well. The only existing use of the target symbol prefix in the
> tree is for those targets, which are coff/pe, not elf. See
> gdb_target_symbol_prefix_flags. Maybe just use objdump instead?

I've adjusted my patch to use objdump instead. This, in turn, helped
me to find a bug with the regexp command that I was using. (By
default, $ doesn't match an end of line, only the end of string.)

With regard to gdb_target_symbol_prefix_flags, I think I'll change
it to call the new gdb_target_symbol_prefix. That seems preferable
to hardcoding a bunch of targets. If it all works out, I'll submit a
separate patch.

The new patch is below...

gdb.dwarf2: Define and use gdb_target_symbol for symbol prefixes

Some of the tests in gdb.dwarf2 which use Dwarf::assemble refer to
(minimal/linker) symbols created in the course of building a small
test program. Some targets use a prefix such as underscore ("_") on
these symbols. Many of the tests in gdb.dwarf2 do not take this into
account. As a consequence, these tests fail to build, resulting
either in failures or untested testcases.

Here is an example from gdb.dwarf2/dw2-regno-invalid.exp:

Dwarf::assemble $asm_file {
cu {} {
compile_unit {
{low_pc main DW_FORM_addr}
{high_pc main+0x10000 DW_FORM_addr}
} {
...
}

For targets which require an underscore prefix on linker symbols,
the two occurrences of "main" would have to have a prepended underscore,
i.e. _main instead of main.

For the above case, a call to the new proc gdb_target_symbol is used
prepend the correct prefix to the symbol. I.e. the above code is
rewritten (as shown in the patch) as follows:

Dwarf::assemble $asm_file {
cu {} {
compile_unit {
{low_pc [gdb_target_symbol main] DW_FORM_addr}
{high_pc [gdb_target_symbol main]+0x10000 DW_FORM_addr}
} {
...
}

I also found it necessary to make an adjustment to lib/dwarf.exp so that
expressions of more than just one list element can be used in DW_TAG_...
constructs. The change to atomic-type.exp was the only change which
required this new functionality.

gdb/testsuite/ChangeLog:

* lib/gdb.exp (gdb_target_symbol_prefix, gdb_target_symbol):
New procs.
* lib/dwarf.exp (_handle_DW_TAG): Handle attribute values,
representing expressions, of more than one list element.
* gdb.dwarf2/atomic-type.exp (Dwarf::assemble): Use gdb_target_symbol
to prepend linker symbol prefix to f.
* gdb.dwarf2/data-loc.exp (Dwarf::assemble): Likewise, for
table_1 and table_2.
* gdb.dwarf2/dw2-bad-mips-linkage-name.exp (Dwarf::assemble):
Likewise, for f and g.
* gdb.dwarf2/dw2-ifort-parameter.exp (Dwarf::assemble): Likewise,
for ptr.
* gdb.dwarf2/dw2-regno-invalid.exp (Dwarf::assemble): Likewise,
for main.
* gdb.dwarf2/dynarr-ptr.exp (Dwarf::assemble): Likewise, for
table_1_ptr and table_2_ptr.
---
gdb/testsuite/gdb.dwarf2/atomic-type.exp | 2 +-
gdb/testsuite/gdb.dwarf2/data-loc.exp | 8 ++--
.../gdb.dwarf2/dw2-bad-mips-linkage-name.exp | 4 +-
gdb/testsuite/gdb.dwarf2/dw2-ifort-parameter.exp | 2 +-
gdb/testsuite/gdb.dwarf2/dw2-regno-invalid.exp | 8 ++--
gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp | 8 ++--
gdb/testsuite/lib/dwarf.exp | 15 ++++++-
gdb/testsuite/lib/gdb.exp | 48 ++++++++++++++++++++++
8 files changed, 77 insertions(+), 18 deletions(-)

diff --git a/gdb/testsuite/gdb.dwarf2/atomic-type.exp b/gdb/testsuite/gdb.dwarf2/atomic-type.exp
index fb315e3..e2a3447 100644
--- a/gdb/testsuite/gdb.dwarf2/atomic-type.exp
+++ b/gdb/testsuite/gdb.dwarf2/atomic-type.exp
@@ -68,7 +68,7 @@ Dwarf::assemble $asm_file {

DW_TAG_subprogram {
{name f}
- {low_pc f addr}
+ {low_pc [gdb_target_symbol f] addr}
{high_pc f_end_lbl addr}
{type :$i_l}
} {
diff --git a/gdb/testsuite/gdb.dwarf2/data-loc.exp b/gdb/testsuite/gdb.dwarf2/data-loc.exp
index e9e702c..a1fb772 100644
--- a/gdb/testsuite/gdb.dwarf2/data-loc.exp
+++ b/gdb/testsuite/gdb.dwarf2/data-loc.exp
@@ -84,7 +84,7 @@ Dwarf::assemble $asm_file {
{DW_AT_name foo__three}
{DW_AT_type :$array_label}
{DW_AT_location {
- DW_OP_addr table_1
+ DW_OP_addr [gdb_target_symbol table_1]
} SPECIAL_expr}
{external 1 flag}
}
@@ -92,7 +92,7 @@ Dwarf::assemble $asm_file {
{DW_AT_name foo__three_tdef}
{DW_AT_type :$array_ptr_label}
{DW_AT_location {
- DW_OP_addr table_1
+ DW_OP_addr [gdb_target_symbol table_1]
} SPECIAL_expr}
{external 1 flag}
}
@@ -100,7 +100,7 @@ Dwarf::assemble $asm_file {
{DW_AT_name foo__five}
{DW_AT_type :$array_label}
{DW_AT_location {
- DW_OP_addr table_2
+ DW_OP_addr [gdb_target_symbol table_2]
} SPECIAL_expr}
{external 1 flag}
}
@@ -108,7 +108,7 @@ Dwarf::assemble $asm_file {
{DW_AT_name foo__five_tdef}
{DW_AT_type :$array_ptr_label}
{DW_AT_location {
- DW_OP_addr table_2
+ DW_OP_addr [gdb_target_symbol table_2]
} SPECIAL_expr}
{external 1 flag}
}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-bad-mips-linkage-name.exp b/gdb/testsuite/gdb.dwarf2/dw2-bad-mips-linkage-name.exp
index 77f6175..dfb9567 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-bad-mips-linkage-name.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-bad-mips-linkage-name.exp
@@ -42,14 +42,14 @@ Dwarf::assemble $asm_file {
}
DW_TAG_subprogram {
{name f}
- {low_pc f addr}
+ {low_pc [gdb_target_symbol f] addr}
{high_pc f_end_lbl addr}
{type :$b_l}
{DW_AT_MIPS_linkage_name _Z1fv}
}
DW_TAG_subprogram {
{name g}
- {low_pc g addr}
+ {low_pc [gdb_target_symbol g] addr}
{high_pc g_end_lbl addr}
{type :$b_l}
{DW_AT_MIPS_linkage_name 42 DW_FORM_data1}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-ifort-parameter.exp b/gdb/testsuite/gdb.dwarf2/dw2-ifort-parameter.exp
index c71103d..4f07b50 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-ifort-parameter.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-ifort-parameter.exp
@@ -53,7 +53,7 @@ Dwarf::assemble $asm_file {
{variable_parameter 1 flag}
{type :$int_label}
{location {
- addr ptr
+ addr [gdb_target_symbol ptr]
deref
} SPECIAL_expr}
}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-regno-invalid.exp b/gdb/testsuite/gdb.dwarf2/dw2-regno-invalid.exp
index a7d77c5..53897bd 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-regno-invalid.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-regno-invalid.exp
@@ -29,8 +29,8 @@ set asm_file [standard_output_file $srcfile]
Dwarf::assemble $asm_file {
cu {} {
compile_unit {
- {low_pc main DW_FORM_addr}
- {high_pc main+0x10000 DW_FORM_addr}
+ {low_pc [gdb_target_symbol main] DW_FORM_addr}
+ {high_pc [gdb_target_symbol main]+0x10000 DW_FORM_addr}
} {
declare_labels integer_label

@@ -43,8 +43,8 @@ Dwarf::assemble $asm_file {
DW_TAG_subprogram {
{name main}
{DW_AT_external 1 flag}
- {low_pc main DW_FORM_addr}
- {high_pc main+0x10000 DW_FORM_addr}
+ {low_pc [gdb_target_symbol main] DW_FORM_addr}
+ {high_pc [gdb_target_symbol main]+0x10000 DW_FORM_addr}
} {
DW_TAG_variable {
{DW_AT_name bregx}
diff --git a/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp b/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
index 3dcb3d7..0a612fe 100644
--- a/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
+++ b/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
@@ -85,7 +85,7 @@ Dwarf::assemble $asm_file {
{DW_AT_name foo__three_ptr}
{DW_AT_type :$array_ptr_label}
{DW_AT_location {
- DW_OP_addr table_1_ptr
+ DW_OP_addr [gdb_target_symbol table_1_ptr]
} SPECIAL_expr}
{external 1 flag}
}
@@ -93,7 +93,7 @@ Dwarf::assemble $asm_file {
{DW_AT_name foo__three_ptr_tdef}
{DW_AT_type :$array_typedef_label}
{DW_AT_location {
- DW_OP_addr table_1_ptr
+ DW_OP_addr [gdb_target_symbol table_1_ptr]
} SPECIAL_expr}
{external 1 flag}
}
@@ -101,7 +101,7 @@ Dwarf::assemble $asm_file {
{DW_AT_name foo__five_ptr}
{DW_AT_type :$array_ptr_label}
{DW_AT_location {
- DW_OP_addr table_2_ptr
+ DW_OP_addr [gdb_target_symbol table_2_ptr]
} SPECIAL_expr}
{external 1 flag}
}
@@ -109,7 +109,7 @@ Dwarf::assemble $asm_file {
{DW_AT_name foo__five_ptr_tdef}
{DW_AT_type :$array_typedef_label}
{DW_AT_location {
- DW_OP_addr table_2_ptr
+ DW_OP_addr [gdb_target_symbol table_2_ptr]
} SPECIAL_expr}
{external 1 flag}
}
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 888ba94..eb2e59c 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -621,7 +621,18 @@ namespace eval Dwarf {

foreach attr $attrs {
set attr_name [_map_name [lindex $attr 0] _AT]
- set attr_value [uplevel 2 [list subst [lindex $attr 1]]]
+
+ # When the length of ATTR is greater than 2, the last element
+ # of the list must be a form. The second through the
+ # penultimate elements are joined together and evaluated
+ # using subst. This allows constructs such as
+ # [gdb_target_symbol foo] to be used.
+
+ if {[llength $attr] > 2} {
+ set attr_value [uplevel 2 [list subst [join [lrange $attr 1 end-1]]]]
+ } {
+ set attr_value [uplevel 2 [list subst [lindex $attr 1]]]
+ }

if { [string equal "MACRO_AT_func" $attr_name] } {
_handle_macro_at_func $attr_value
@@ -629,7 +640,7 @@ namespace eval Dwarf {
_handle_macro_at_range $attr_value
} else {
if {[llength $attr] > 2} {
- set attr_form [lindex $attr 2]
+ set attr_form [lindex $attr end]
} else {
# If the value looks like an integer, a form is required.
if [string is integer $attr_value] {
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 048070b..e1c9839 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -5521,6 +5521,54 @@ proc core_find {binfile {deletefiles {}} {arg ""}} {
return $destcore
}

+# gdb_target_symbol_prefix compiles a test program and uses readelf to
+# determine the prefix (such as underscore) for linker symbol
+# prefixes.
+
+gdb_caching_proc gdb_target_symbol_prefix {
+ # Set up and compile a simple test program...
+ set src [standard_temp_file main[pid].c]
+ set exe [standard_temp_file main[pid].x]
+
+ gdb_produce_source $src {
+ int main() {
+ return 0;
+ }
+ }
+
+ verbose "compiling testfile $src" 2
+ set compile_flags {debug nowarnings quiet}
+ set lines [gdb_compile $src $exe executable $compile_flags]
+
+ set prefix ""
+
+ if ![string match "" $lines] then {
+ verbose "gdb_target_symbol_prefix: testfile compilation failed, returning null prefix" 2
+ } else {
+ set objdump_program [gdb_find_objdump]
+ set result [catch "exec $objdump_program --syms $exe" output]
+
+ if { $result == 0 \
+ && ![regexp -lineanchor \
+ { ([^ a-zA-Z0-9]*)main$} $output dummy prefix] } {
+ verbose "gdb_target_symbol_prefix: Could not find main in objdump output; returning null prefix" 2
+ }
+ }
+
+ file delete $src
+ file delete $exe
+
+ return $prefix
+}
+
+# gdb_target_symbol returns the provided symbol with the correct prefix
+# prepended. (See gdb_target_symbol_prefix, above.)
+
+proc gdb_target_symbol { symbol } {
+ set prefix [gdb_target_symbol_prefix]
+ return "${prefix}${symbol}"
+}
+
# gdb_target_symbol_prefix_flags returns a string that can be added
# to gdb_compile options to define SYMBOL_PREFIX macro value
# symbol_prefix_flags returns a string that can be added