gdb.dwarf2: Define and use gdb_target_symbol_prefix for symbol prefixes

Message ID 20151029212509.438b5642@pinnacle.lan
State New, archived
Headers

Commit Message

Kevin Buettner Oct. 30, 2015, 4:25 a.m. UTC
  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.

gdb/testsuite/ChangeLog:
    
    	* lib/gdb.exp (gdb_target_symbol_prefix): New proc.
    	* gdb.dwarf2/atomic-type.exp (Dwarf::assemble): Fetch
    	linker symbol prefix and prepend it to f.
    	* gdb.dwarf2/data-loc.exp (Dwarf::assemble): Fetch linker
    	symbol prefix and prepend it to table_1 and table_2.
    	* gdb.dwarf2/dw2-bad-mips-linkage-name.exp (Dwarf::assemble): Fetch
    	linker symbol prefix and prepend it to f and g.
    	* gdb.dwarf2/dw2-ifort-parameter.exp (Dwarf::assemble): Fetch
    	linker symbol prefix and prepend it to ptr.
    	* gdb.dwarf2/dw2-regno-invalid.exp (Dwarf::assemble): Fetch linker
    	symbol prefix and prepend it to main.
    	* gdb.dwarf2/dynarr-ptr.exp (Dwarf::assemble): Fetch linker symbol
    	prefix and prepend it to table_1_ptr and table_2_ptr.
---
 gdb/testsuite/gdb.dwarf2/atomic-type.exp           |  4 ++-
 gdb/testsuite/gdb.dwarf2/data-loc.exp              | 10 +++---
 .../gdb.dwarf2/dw2-bad-mips-linkage-name.exp       |  6 ++--
 gdb/testsuite/gdb.dwarf2/dw2-ifort-parameter.exp   |  3 +-
 gdb/testsuite/gdb.dwarf2/dw2-regno-invalid.exp     | 10 +++---
 gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp            | 10 +++---
 gdb/testsuite/lib/gdb.exp                          | 39 ++++++++++++++++++++++
 7 files changed, 66 insertions(+), 16 deletions(-)
  

Comments

Kevin Buettner Oct. 30, 2015, 5:25 a.m. UTC | #1
On Thu, 29 Oct 2015 21:25:09 -0700
Kevin Buettner <kevinb@redhat.com> wrote:

> 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.

Several of the .S files in gdb.dwarf2 have the same problem.  E.g.
when linking the test case for gdb.dwarf2/method-ptr.exp, I see a
linker error "undefined reference to `main'".  It appears that crt0
is generating a reference to _main, but the .S file only provides a
reference to main.

Any thoughts on what to do about this?

(It occurs to me that I could define both _main and main in the .S
file, but this doesn't solve the problem should some other prefix be
used instead.)

Kevin
  
Pedro Alves Oct. 30, 2015, 11:06 a.m. UTC | #2
On 10/30/2015 04:25 AM, Kevin Buettner wrote:

> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index 048070b..f8e35ac 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -5521,6 +5521,45 @@ 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.
> +
> +proc gdb_target_symbol_prefix {} {

Shouldn't this be gdb_caching_proc ?

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.

> +	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?

Thanks,
Pedro Alves
  
Pedro Alves Oct. 30, 2015, 11:11 a.m. UTC | #3
On 10/30/2015 05:25 AM, Kevin Buettner wrote:
> On Thu, 29 Oct 2015 21:25:09 -0700
> Kevin Buettner <kevinb@redhat.com> wrote:
> 
>> 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.
> 
> Several of the .S files in gdb.dwarf2 have the same problem.  E.g.
> when linking the test case for gdb.dwarf2/method-ptr.exp, I see a
> linker error "undefined reference to `main'".  It appears that crt0
> is generating a reference to _main, but the .S file only provides a
> reference to main.
> 
> Any thoughts on what to do about this?

Isn't this being addressed by gdb_target_symbol_prefix_flags in
the existing tests that use it?  E.g., gdb.arch/i386-bp_permanent.c:

#ifdef SYMBOL_PREFIX
#define SYMBOL(str)     SYMBOL_PREFIX #str
#else
#define SYMBOL(str)     #str
#endif

...

#ifdef __x86_64__
asm(".text\n"
    "    .align 8\n"
    SYMBOL (standard) ":\n"

Thanks,
Pedro Alves
  
Kevin Buettner Nov. 5, 2015, 6:39 a.m. UTC | #4
On Fri, 30 Oct 2015 11:11:33 +0000
Pedro Alves <palves@redhat.com> wrote:

> On 10/30/2015 05:25 AM, Kevin Buettner wrote:
> > On Thu, 29 Oct 2015 21:25:09 -0700
> > Kevin Buettner <kevinb@redhat.com> wrote:
> > 
> >> 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.
> > 
> > Several of the .S files in gdb.dwarf2 have the same problem.  E.g.
> > when linking the test case for gdb.dwarf2/method-ptr.exp, I see a
> > linker error "undefined reference to `main'".  It appears that crt0
> > is generating a reference to _main, but the .S file only provides a
> > reference to main.
> > 
> > Any thoughts on what to do about this?
> 
> Isn't this being addressed by gdb_target_symbol_prefix_flags in
> the existing tests that use it?  E.g., gdb.arch/i386-bp_permanent.c:
> 
> #ifdef SYMBOL_PREFIX
> #define SYMBOL(str)     SYMBOL_PREFIX #str
> #else
> #define SYMBOL(str)     #str
> #endif
> 
> ...
> 
> #ifdef __x86_64__
> asm(".text\n"
>     "    .align 8\n"
>     SYMBOL (standard) ":\n"

This seems like the right general approach, but it appears to me that
the current mechanism is broken for assembly files.

For targets which need an _ prefix, gdb_target_symbol_prefix_flags
returns this:

additional_flags=-DSYMBOL_PREFIX="_"

(The code in question escapes the double quotes. I don't show that here.)

When the compiler is invoked, the relevant part of the command line
looks something like this:

rx-elf-gcc   -DSYMBOL_PREFIX="_" ...

This is invoked via tcl and not via bash or similar shell.  Therefore, the
value of SYMBOL_PREFIX is actually "_" (with the quotes).

(For a while, I was puzzled about why things worked in when I pasted,
into bash, the exact command from log output that showed an error.  It
turns out that bash was eliminating the quotes as part of its argument
processing.  When I pasted the command into tclsh instead, I was able
to reproduce the error.)

Anyway, with those quotes in place, the macro defining SYMBOL will work
just fine for inline assembler in C/C++.

But for a .S file, we need to do something like this (as shown in
gdb.arch/i386-float.S):

#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b

#ifdef SYMBOL_PREFIX
# define SYMBOL(str)     CONCAT1(SYMBOL_PREFIX, str)
#else
# define SYMBOL(str)     str
#endif

	.text
	.globl SYMBOL(main)
SYMBOL(main):

I don't understand the reason for both CONCAT1 and CONCAT2, but when
I use this code in one of the files that I'm working on, I end
up seeing an error due to the double quotes.  Here's the source:

#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b

#ifdef SYMBOL_PREFIX
# define SYMBOL(str)     CONCAT1(SYMBOL_PREFIX, str)
#else
# define SYMBOL(str)     str
#endif

	.text
SYMBOL(main):	.globl SYMBOL(main)

...

And this is what it translates to:

 .text
"_"main: .globl "_"main

I don't think there's any way to, within the C preprocessor, strip
the quotes from the _.

It seems to me that the way to fix this is to make
gdb_target_symbol_prefix_flags return an unquoted prefix.  I.e.
it should return:

additional_flags=-DSYMBOL_PREFIX=_

instead of:

additional_flags=-DSYMBOL_PREFIX="_"

Then, within C files, SYMBOL is defined as follows:

#ifdef SYMBOL_PREFIX
#define SYMBOL(str)     #SYMBOL_PREFIX #str
#else
#define SYMBOL(str)     #str
#endif

Note that this is the same as before, except that I added a # to
the front of SYMBOL_PREFIX.  It's possible that this won't work -
we might end up with "SYMBOL_PREFIX" instead of "_" for the prefix.
If that's the case, then some layering is needed, perhaps something
like this:

#define STRCAT1(a,b) #a #b
#ifdef SYMBOL_PREFIX
#define SYMBOL(str)     STRCAT1(SYMBOL_PREFIX,str)
#else
#define SYMBOL(str)     #str
#endif

I'm willing to make these changes, but I want to first be sure that
I'm not missing an easier fix.

Kevin
  
Pedro Alves Nov. 5, 2015, 10:46 a.m. UTC | #5
On 11/05/2015 06:39 AM, Kevin Buettner wrote:
> On Fri, 30 Oct 2015 11:11:33 +0000
> Pedro Alves <palves@redhat.com> wrote:


> But for a .S file, we need to do something like this (as shown in
> gdb.arch/i386-float.S):
> 
> #define CONCAT1(a, b) CONCAT2(a, b)
> #define CONCAT2(a, b) a ## b
> 
> #ifdef SYMBOL_PREFIX
> # define SYMBOL(str)     CONCAT1(SYMBOL_PREFIX, str)
> #else
> # define SYMBOL(str)     str
> #endif
> 
> 	.text
> 	.globl SYMBOL(main)
> SYMBOL(main):
> 
> I don't understand the reason for both CONCAT1 and CONCAT2,

You need two levels in order to first expand SYMBOL_PREFIX, and
then concat the result.  Otherwise SYMBOL(main) expands to
literally "SYMBOL_PREFIXmain" (minus quotes).

> It seems to me that the way to fix this is to make
> gdb_target_symbol_prefix_flags return an unquoted prefix.  I.e.
> it should return:
> 
> additional_flags=-DSYMBOL_PREFIX=_
> 
> instead of:
> 
> additional_flags=-DSYMBOL_PREFIX="_"

Yup.

> 
> Then, within C files, SYMBOL is defined as follows:
> 
> #ifdef SYMBOL_PREFIX
> #define SYMBOL(str)     #SYMBOL_PREFIX #str
> #else
> #define SYMBOL(str)     #str
> #endif
> 
> Note that this is the same as before, except that I added a # to
> the front of SYMBOL_PREFIX.  It's possible that this won't work -

It wont.  # can only be used with a macro parameter.

> we might end up with "SYMBOL_PREFIX" instead of "_" for the prefix.
> If that's the case, then some layering is needed, perhaps something
> like this:
> 
> #define STRCAT1(a,b) #a #b
> #ifdef SYMBOL_PREFIX
> #define SYMBOL(str)     STRCAT1(SYMBOL_PREFIX,str)
> #else
> #define SYMBOL(str)     #str
> #endif
> 

That still needs double expansion.

> I'm willing to make these changes, but I want to first be sure that
> I'm not missing an easier fix.

IMO, it's clearer to separate the concerns -- concatenation
and final stringification.

Start with the usual concatenation:

#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b

#ifdef SYMBOL_PREFIX
# define SYMBOL1(str)     CONCAT1(SYMBOL_PREFIX, str)
#else
# define SYMBOL1(str)     str
#endif


Then add a stringification layer:

#define STR1(s) #s
#define STR(s) STR1(s)

#define SYMBOL(str)     STR(SYMBOL1(str))


This way you have these expansions:

 SYMBOL1(main) -> _main
 SYMBOL(main) -> "_main"

Thanks,
Pedro Alves
  
Pedro Alves Nov. 5, 2015, 10:54 a.m. UTC | #6
On 11/05/2015 10:46 AM, Pedro Alves wrote:
>> > I'm willing to make these changes, but I want to first be sure that
>> > I'm not missing an easier fix.

BTW, an alternative to the below would be to have two tcl procedures,
one for asm, and another for C/C++/etc, like
gdb_target_symbol_prefix_flags_asm / gdb_target_symbol_prefix_flags.
The C version would just call the asm version and add the double
quotes.

Thanks,
Pedro Alves

> IMO, it's clearer to separate the concerns -- concatenation
> and final stringification.
> 
> Start with the usual concatenation:
> 
> #define CONCAT1(a, b) CONCAT2(a, b)
> #define CONCAT2(a, b) a ## b
> 
> #ifdef SYMBOL_PREFIX
> # define SYMBOL1(str)     CONCAT1(SYMBOL_PREFIX, str)
> #else
> # define SYMBOL1(str)     str
> #endif
> 
> 
> Then add a stringification layer:
> 
> #define STR1(s) #s
> #define STR(s) STR1(s)
> 
> #define SYMBOL(str)     STR(SYMBOL1(str))
> 
> 
> This way you have these expansions:
> 
>  SYMBOL1(main) -> _main
>  SYMBOL(main) -> "_main"
  
Kevin Buettner Nov. 6, 2015, 5:33 a.m. UTC | #7
On Thu, 05 Nov 2015 10:54:56 +0000
Pedro Alves <palves@redhat.com> wrote:

> On 11/05/2015 10:46 AM, Pedro Alves wrote:
> >> > I'm willing to make these changes, but I want to first be sure that
> >> > I'm not missing an easier fix.
> 
> BTW, an alternative to the below would be to have two tcl procedures,
> one for asm, and another for C/C++/etc, like
> gdb_target_symbol_prefix_flags_asm / gdb_target_symbol_prefix_flags.
> The C version would just call the asm version and add the double
> quotes.

This is a really good idea.  It means that I don't need to touch
already working test cases contained in .c files.  Also, the SYMBOL
macros contained therein stay simpler and (presumably) easier to
maintain.

I've just posted a patch implementing this idea.  See:

https://sourceware.org/ml/gdb-patches/2015-11/msg00192.html

Thanks!

Kevin
  

Patch

diff --git a/gdb/testsuite/gdb.dwarf2/atomic-type.exp b/gdb/testsuite/gdb.dwarf2/atomic-type.exp
index fb315e3..43e28c8 100644
--- a/gdb/testsuite/gdb.dwarf2/atomic-type.exp
+++ b/gdb/testsuite/gdb.dwarf2/atomic-type.exp
@@ -25,6 +25,8 @@  standard_testfile atomic.c atomic-type-dw.S
 
 set asm_file [standard_output_file $srcfile2]
 Dwarf::assemble $asm_file {
+    set prefix [gdb_target_symbol_prefix]
+
     cu {} {
 	DW_TAG_compile_unit {
                 {DW_AT_language @DW_LANG_C11}
@@ -68,7 +70,7 @@  Dwarf::assemble $asm_file {
 
             DW_TAG_subprogram {
                 {name f}
-                {low_pc f addr}
+                {low_pc ${prefix}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..4802a0a 100644
--- a/gdb/testsuite/gdb.dwarf2/data-loc.exp
+++ b/gdb/testsuite/gdb.dwarf2/data-loc.exp
@@ -36,6 +36,8 @@  if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
 # Make some DWARF for the test.
 set asm_file [standard_output_file $srcfile2]
 Dwarf::assemble $asm_file {
+    set prefix [gdb_target_symbol_prefix]
+
     cu {} {
  	DW_TAG_compile_unit {
                 {DW_AT_language @DW_LANG_Ada95}
@@ -84,7 +86,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 ${prefix}table_1
                 } SPECIAL_expr}
                 {external 1 flag}
             }
@@ -92,7 +94,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 ${prefix}table_1
                 } SPECIAL_expr}
                 {external 1 flag}
             }
@@ -100,7 +102,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 ${prefix}table_2
                 } SPECIAL_expr}
                 {external 1 flag}
             }
@@ -108,7 +110,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 ${prefix}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..decd531 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-bad-mips-linkage-name.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-bad-mips-linkage-name.exp
@@ -26,6 +26,8 @@  standard_testfile dw2-bad-mips-linkage-name.c dw2-bad-mips-linkage-name.S
 
 set asm_file [standard_output_file $srcfile2]
 Dwarf::assemble $asm_file {
+    set prefix [gdb_target_symbol_prefix]
+
     cu {} {
 	DW_TAG_compile_unit {
                 {DW_AT_language @DW_LANG_C}
@@ -42,14 +44,14 @@  Dwarf::assemble $asm_file {
 	    }
             DW_TAG_subprogram {
                 {name f}
-                {low_pc f addr}
+                {low_pc ${prefix}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 ${prefix}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..d55fd43 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-ifort-parameter.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-ifort-parameter.exp
@@ -27,6 +27,7 @@  standard_testfile .c dw2-ifort-parameter-dw.S
 # Make some DWARF for the test.
 set asm_file [standard_output_file $srcfile2]
 Dwarf::assemble $asm_file {
+    set prefix [gdb_target_symbol_prefix]
     declare_labels int_label
 
     extern func_start func_end ptr
@@ -53,7 +54,7 @@  Dwarf::assemble $asm_file {
 		    {variable_parameter 1 flag}
 		    {type :$int_label}
 		    {location {
-			addr ptr
+			addr ${prefix}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..620d438 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-regno-invalid.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-regno-invalid.exp
@@ -27,10 +27,12 @@  standard_testfile .S main.c
 # Make some DWARF for the test.
 set asm_file [standard_output_file $srcfile]
 Dwarf::assemble $asm_file {
+    set prefix [gdb_target_symbol_prefix]
+
     cu {} {
 	compile_unit {
-	    {low_pc main DW_FORM_addr}
-	    {high_pc main+0x10000 DW_FORM_addr}
+	    {low_pc ${prefix}main DW_FORM_addr}
+	    {high_pc ${prefix}main+0x10000 DW_FORM_addr}
 	} {
 	    declare_labels integer_label
 
@@ -43,8 +45,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 ${prefix}main DW_FORM_addr}
+		{high_pc ${prefix}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..d0a74be 100644
--- a/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
+++ b/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
@@ -36,6 +36,8 @@  if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
 # Make some DWARF for the test.
 set asm_file [standard_output_file $srcfile2]
 Dwarf::assemble $asm_file {
+    set prefix [gdb_target_symbol_prefix]
+
     cu {} {
  	DW_TAG_compile_unit {
                 {DW_AT_language @DW_LANG_Ada95}
@@ -85,7 +87,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 ${prefix}table_1_ptr
                 } SPECIAL_expr}
                 {external 1 flag}
             }
@@ -93,7 +95,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 ${prefix}table_1_ptr
                 } SPECIAL_expr}
                 {external 1 flag}
             }
@@ -101,7 +103,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 ${prefix}table_2_ptr
                 } SPECIAL_expr}
                 {external 1 flag}
             }
@@ -109,7 +111,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 ${prefix}table_2_ptr
                 } SPECIAL_expr}
                 {external 1 flag}
             }
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 048070b..f8e35ac 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -5521,6 +5521,45 @@  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.
+
+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 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
+	}
+    }
+
+    file delete $src
+    file delete $exe
+
+    return $prefix
+}
+
 # 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