aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog23
-rw-r--r--gdb/Makefile.in5
-rw-r--r--gdb/NEWS4
-rw-r--r--gdb/cp-namespace.c2
-rw-r--r--gdb/solib-svr4.c212
-rw-r--r--gdb/solib.c18
-rw-r--r--gdb/solist.h18
-rw-r--r--gdb/symtab.c85
-rw-r--r--gdb/symtab.h9
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.base/solib-symbol-lib.c32
-rw-r--r--gdb/testsuite/gdb.base/solib-symbol-main.c43
-rw-r--r--gdb/testsuite/gdb.base/solib-symbol.exp80
13 files changed, 428 insertions, 109 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d75da08..4848e0f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,26 @@
+2007-07-03 Markus Deuling <deuling@de.ibm.com>
+
+ * cp-namespace.c (lookup_symbol_file): Add block to
+ lookup_symbol_global call.
+ * Makefile.in (solist_h): Add dependency on symtab header.
+ (symtab.o): Add dependency on solist header.
+ * solib.c (solib_global_lookup): New function.
+ * solib-svr4.c (scan_dyntag): Likewise.
+ (elf_locate_base): Call helper routine scan_dyntag.
+ (elf_lookup_lib_symbol): New function.
+ (_initialize_svr4_solib): Add elf_lookup_lib_symbol to svr4_so_ops.
+ * solist.h (symtab.h): New include.
+ (struct target_so_ops): New member lookup_lib_global_symbol.
+ (solib_global_lookup): New prototype.
+ * symtab.c: New include solist.h.
+ (lookup_objfile_from_block): New function.
+ (lookup_global_symbol_from_objfile): New function.
+ (basic_lookup_symbol_nonlocal): Add block to lookup_symbol_global call.
+ (lookup_symbol_global): Call library-specific lookup procedure.
+ * symtab.h (lookup_global_symbol_from_objfile): New prototype.
+
+ * NEWS: Document framework.
+
2007-07-02 Daniel Jacobowitz <dan@codesourcery.com>
* target-descriptions.c (tdesc_create_reg): Do not set reg->type
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 5d71855..b278a28 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -799,7 +799,7 @@ solib_h = solib.h
solib_pa64_h = solib-pa64.h
solib_som_h = solib-som.h
solib_svr4_h = solib-svr4.h
-solist_h = solist.h
+solist_h = solist.h $(symtab_h)
source_h = source.h
sparc64_tdep_h = sparc64-tdep.h $(sparc_tdep_h)
sparc_nat_h = sparc-nat.h
@@ -2724,7 +2724,8 @@ symtab.o: symtab.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \
$(language_h) $(demangle_h) $(inferior_h) $(linespec_h) $(source_h) \
$(filenames_h) $(objc_lang_h) $(ada_lang_h) $(hashtab_h) \
$(gdb_obstack_h) $(block_h) $(dictionary_h) $(gdb_string_h) \
- $(gdb_stat_h) $(cp_abi_h) $(observer_h) $(gdb_assert_h)
+ $(gdb_stat_h) $(cp_abi_h) $(observer_h) $(gdb_assert_h) \
+ $(solist_h)
target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \
diff --git a/gdb/NEWS b/gdb/NEWS
index 8148073..b3bd08a 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,10 @@
*** Changes since GDB 6.6
+* When looking up multiply-defined global symbols, GDB will now prefer the
+symbol definition in the current shared library if it was built using the
+-Bsymbolic linker option.
+
* When the Text User Interface (TUI) is not configured, GDB will now
recognize the -tui command-line option and print a message that the TUI
is not supported.
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index f6ea710..4007c72 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -491,7 +491,7 @@ lookup_symbol_file (const char *name,
}
else
{
- sym = lookup_symbol_global (name, linkage_name, domain, symtab);
+ sym = lookup_symbol_global (name, linkage_name, block, domain, symtab);
}
if (sym != NULL)
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index c531ccb..7dfe707e 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -354,6 +354,76 @@ bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
return symaddr;
}
+/* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1 is
+ returned and the corresponding PTR is set. */
+
+static int
+scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
+{
+ int arch_size, step, sect_size;
+ long dyn_tag;
+ CORE_ADDR dyn_ptr, dyn_addr;
+ gdb_byte *bufend, *buf;
+ Elf32_External_Dyn *x_dynp_32;
+ Elf64_External_Dyn *x_dynp_64;
+ struct bfd_section *sect;
+
+ if (abfd == NULL)
+ return 0;
+ arch_size = bfd_get_arch_size (abfd);
+ if (arch_size == -1)
+ return 0;
+
+ /* Find the start address of the .dynamic section. */
+ sect = bfd_get_section_by_name (abfd, ".dynamic");
+ if (sect == NULL)
+ return 0;
+ dyn_addr = bfd_section_vma (abfd, sect);
+
+ /* Read in .dynamic section, silently ignore errors. */
+ sect_size = bfd_section_size (abfd, sect);
+ buf = alloca (sect_size);
+ if (target_read_memory (dyn_addr, buf, sect_size))
+ {
+ /* If target_read_memory fails, try reading the BFD file. */
+ if (!bfd_get_section_contents (abfd, sect,
+ buf, 0, sect_size))
+ return 0;
+ }
+
+ /* Iterate over BUF and scan for DYNTAG. If found, set PTR and return. */
+ step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
+ : sizeof (Elf64_External_Dyn);
+ for (bufend = buf + sect_size;
+ buf < bufend;
+ buf += step)
+ {
+ if (arch_size == 32)
+ {
+ x_dynp_32 = (Elf32_External_Dyn *) buf;
+ dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag);
+ dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr);
+ }
+ else
+ {
+ x_dynp_64 = (Elf64_External_Dyn *) buf;
+ dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
+ dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
+ }
+ if (dyn_tag == DT_NULL)
+ return 0;
+ if (dyn_tag == dyntag)
+ {
+ if (ptr)
+ *ptr = dyn_ptr;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
/*
LOCAL FUNCTION
@@ -381,114 +451,31 @@ bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
static CORE_ADDR
elf_locate_base (void)
{
- struct bfd_section *dyninfo_sect;
- int dyninfo_sect_size;
- CORE_ADDR dyninfo_addr;
- gdb_byte *buf;
- gdb_byte *bufend;
- int arch_size;
+ struct minimal_symbol *msymbol;
+ CORE_ADDR dyn_ptr;
- /* Find the start address of the .dynamic section. */
- dyninfo_sect = bfd_get_section_by_name (exec_bfd, ".dynamic");
- if (dyninfo_sect == NULL)
- {
- /* This may be a static executable. Look for the symbol
- conventionally named _r_debug, as a last resort. */
- struct minimal_symbol *msymbol;
+ /* Find DT_DEBUG. */
+ if (scan_dyntag (DT_DEBUG, exec_bfd, &dyn_ptr))
+ return dyn_ptr;
- msymbol = lookup_minimal_symbol ("_r_debug", NULL, symfile_objfile);
- if (msymbol != NULL)
- return SYMBOL_VALUE_ADDRESS (msymbol);
- else
+ /* Find DT_MIPS_RLD_MAP. */
+ if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr))
+ {
+ gdb_byte *pbuf;
+ int pbuf_size = TYPE_LENGTH (builtin_type_void_data_ptr);
+ pbuf = alloca (pbuf_size);
+ /* DT_MIPS_RLD_MAP contains a pointer to the address
+ of the dynamic link structure. */
+ if (target_read_memory (dyn_ptr, pbuf, pbuf_size))
return 0;
+ return extract_typed_address (pbuf, builtin_type_void_data_ptr);
}
- dyninfo_addr = bfd_section_vma (exec_bfd, dyninfo_sect);
-
- /* Read in .dynamic section, silently ignore errors. */
- dyninfo_sect_size = bfd_section_size (exec_bfd, dyninfo_sect);
- buf = alloca (dyninfo_sect_size);
- if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size))
- return 0;
-
- /* Find the DT_DEBUG entry in the the .dynamic section.
- For mips elf we look for DT_MIPS_RLD_MAP, mips elf apparently has
- no DT_DEBUG entries. */
-
- arch_size = bfd_get_arch_size (exec_bfd);
- if (arch_size == -1) /* failure */
- return 0;
-
- if (arch_size == 32)
- { /* 32-bit elf */
- for (bufend = buf + dyninfo_sect_size;
- buf < bufend;
- buf += sizeof (Elf32_External_Dyn))
- {
- Elf32_External_Dyn *x_dynp = (Elf32_External_Dyn *) buf;
- long dyn_tag;
- CORE_ADDR dyn_ptr;
-
- dyn_tag = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
- if (dyn_tag == DT_NULL)
- break;
- else if (dyn_tag == DT_DEBUG)
- {
- dyn_ptr = bfd_h_get_32 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- return dyn_ptr;
- }
- else if (dyn_tag == DT_MIPS_RLD_MAP)
- {
- gdb_byte *pbuf;
- int pbuf_size = TYPE_LENGTH (builtin_type_void_data_ptr);
-
- pbuf = alloca (pbuf_size);
- /* DT_MIPS_RLD_MAP contains a pointer to the address
- of the dynamic link structure. */
- dyn_ptr = bfd_h_get_32 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- if (target_read_memory (dyn_ptr, pbuf, pbuf_size))
- return 0;
- return extract_typed_address (pbuf, builtin_type_void_data_ptr);
- }
- }
- }
- else /* 64-bit elf */
- {
- for (bufend = buf + dyninfo_sect_size;
- buf < bufend;
- buf += sizeof (Elf64_External_Dyn))
- {
- Elf64_External_Dyn *x_dynp = (Elf64_External_Dyn *) buf;
- long dyn_tag;
- CORE_ADDR dyn_ptr;
-
- dyn_tag = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
- if (dyn_tag == DT_NULL)
- break;
- else if (dyn_tag == DT_DEBUG)
- {
- dyn_ptr = bfd_h_get_64 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- return dyn_ptr;
- }
- else if (dyn_tag == DT_MIPS_RLD_MAP)
- {
- gdb_byte *pbuf;
- int pbuf_size = TYPE_LENGTH (builtin_type_void_data_ptr);
-
- pbuf = alloca (pbuf_size);
- /* DT_MIPS_RLD_MAP contains a pointer to the address
- of the dynamic link structure. */
- dyn_ptr = bfd_h_get_64 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- if (target_read_memory (dyn_ptr, pbuf, pbuf_size))
- return 0;
- return extract_typed_address (pbuf, builtin_type_void_data_ptr);
- }
- }
- }
+ /* This may be a static executable. Look for the symbol
+ conventionally named _r_debug, as a last resort. */
+ msymbol = lookup_minimal_symbol ("_r_debug", NULL, symfile_objfile);
+ if (msymbol != NULL)
+ return SYMBOL_VALUE_ADDRESS (msymbol);
/* DT_DEBUG entry not found. */
return 0;
@@ -1554,6 +1541,24 @@ svr4_lp64_fetch_link_map_offsets (void)
struct target_so_ops svr4_so_ops;
+/* Lookup global symbol for ELF DSOs linked with -Bsymbolic. Those DSOs have a
+ different rule for symbol lookup. The lookup begins here in the DSO, not in
+ the main executable. */
+
+static struct symbol *
+elf_lookup_lib_symbol (const struct objfile *objfile,
+ const char *name,
+ const char *linkage_name,
+ const domain_enum domain, struct symtab **symtab)
+{
+ if (objfile->obfd == NULL
+ || scan_dyntag (DT_SYMBOLIC, objfile->obfd, NULL) != 1)
+ return NULL;
+
+ return lookup_global_symbol_from_objfile
+ (objfile, name, linkage_name, domain, symtab);
+}
+
extern initialize_file_ftype _initialize_svr4_solib; /* -Wmissing-prototypes */
void
@@ -1569,6 +1574,7 @@ _initialize_svr4_solib (void)
svr4_so_ops.current_sos = svr4_current_sos;
svr4_so_ops.open_symbol_file_object = open_symbol_file_object;
svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;
+ svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
/* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */
current_target_so_ops = &svr4_so_ops;
diff --git a/gdb/solib.c b/gdb/solib.c
index f48b0a2..f522812 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -961,6 +961,24 @@ show_auto_solib_add (struct ui_file *file, int from_tty,
}
+/* Handler for library-specific lookup of global symbol NAME in OBJFILE. Call
+ the library-specific handler if it is installed for the current target. */
+
+struct symbol *
+solib_global_lookup (const struct objfile *objfile,
+ const char *name,
+ const char *linkage_name,
+ const domain_enum domain,
+ struct symtab **symtab)
+{
+ if (current_target_so_ops->lookup_lib_global_symbol != NULL)
+ return current_target_so_ops->lookup_lib_global_symbol (objfile,
+ name, linkage_name, domain, symtab);
+
+ return NULL;
+}
+
+
extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
void
diff --git a/gdb/solist.h b/gdb/solist.h
index c883686..38c292e 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -23,6 +23,8 @@
#define SOLIST_H
#define SO_NAME_MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */
+/* For domain_enum domain. */
+#include "symtab.h"
/* Forward declaration for target specific link map information. This
struct is opaque to all but the target specific file. */
@@ -107,7 +109,14 @@ struct target_so_ops
Convenience function for remote debuggers finding host libs. */
int (*find_and_open_solib) (char *soname,
unsigned o_flags, char **temp_pathname);
-
+
+ /* Hook for looking up global symbols in a library-specific way. */
+ struct symbol * (*lookup_lib_global_symbol) (const struct objfile *objfile,
+ const char *name,
+ const char *linkage_name,
+ const domain_enum domain,
+ struct symtab **symtab);
+
};
/* Free the memory associated with a (so_list *). */
@@ -129,4 +138,11 @@ extern struct target_so_ops *current_target_so_ops;
#define TARGET_SO_IN_DYNSYM_RESOLVE_CODE \
(current_target_so_ops->in_dynsym_resolve_code)
+/* Handler for library-specific global symbol lookup in solib.c. */
+struct symbol *solib_global_lookup (const struct objfile *objfile,
+ const char *name,
+ const char *linkage_name,
+ const domain_enum domain,
+ struct symtab **symtab);
+
#endif
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 6a9ef41..2bb414b 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -57,6 +57,7 @@
#include "cp-abi.h"
#include "observer.h"
#include "gdb_assert.h"
+#include "solist.h"
/* Prototypes for local functions */
@@ -1261,6 +1262,26 @@ lookup_symbol_aux_local (const char *name, const char *linkage_name,
return NULL;
}
+/* Look up OBJFILE to BLOCK. */
+
+static struct objfile *
+lookup_objfile_from_block (const struct block *block)
+{
+ struct objfile *obj;
+ struct symtab *s;
+
+ if (block == NULL)
+ return NULL;
+
+ block = block_global_block (block);
+ /* Go through SYMTABS. */
+ ALL_SYMTABS (obj, s)
+ if (block == BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK))
+ return obj;
+
+ return NULL;
+}
+
/* Look up a symbol in a block; if found, locate its symtab, fixup the
symbol, and set block_found appropriately. */
@@ -1302,6 +1323,57 @@ lookup_symbol_aux_block (const char *name, const char *linkage_name,
return NULL;
}
+/* Check all global symbols in OBJFILE in symtabs and
+ psymtabs. */
+
+struct symbol *
+lookup_global_symbol_from_objfile (const struct objfile *objfile,
+ const char *name,
+ const char *linkage_name,
+ const domain_enum domain,
+ struct symtab **symtab)
+{
+ struct symbol *sym;
+ struct blockvector *bv;
+ const struct block *block;
+ struct symtab *s;
+ struct partial_symtab *ps;
+
+ /* Go through symtabs. */
+ ALL_OBJFILE_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, linkage_name, domain);
+ if (sym)
+ {
+ block_found = block;
+ if (symtab != NULL)
+ *symtab = s;
+ return fixup_symbol_section (sym, (struct objfile *)objfile);
+ }
+ }
+
+ /* Now go through psymtabs. */
+ ALL_OBJFILE_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin
+ && lookup_partial_symbol (ps, name, linkage_name,
+ 1, domain))
+ {
+ s = PSYMTAB_TO_SYMTAB (ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, linkage_name, domain);
+ if (symtab != NULL)
+ *symtab = s;
+ return fixup_symbol_section (sym, (struct objfile *)objfile);
+ }
+ }
+
+ return NULL;
+}
+
/* Check to see if the symbol is defined in one of the symtabs.
BLOCK_INDEX should be either GLOBAL_BLOCK or STATIC_BLOCK,
depending on whether or not we want to search global symbols or
@@ -1567,7 +1639,7 @@ basic_lookup_symbol_nonlocal (const char *name,
if (sym != NULL)
return sym;
- return lookup_symbol_global (name, linkage_name, domain, symtab);
+ return lookup_symbol_global (name, linkage_name, block, domain, symtab);
}
/* Lookup a symbol in the static block associated to BLOCK, if there
@@ -1595,10 +1667,19 @@ lookup_symbol_static (const char *name,
struct symbol *
lookup_symbol_global (const char *name,
const char *linkage_name,
+ const struct block *block,
const domain_enum domain,
struct symtab **symtab)
{
- struct symbol *sym;
+ struct symbol *sym = NULL;
+ struct objfile *objfile = NULL;
+
+ /* Call library-specific lookup procedure. */
+ objfile = lookup_objfile_from_block (block);
+ if (objfile != NULL)
+ sym = solib_global_lookup (objfile, name, linkage_name, domain, symtab);
+ if (sym != NULL)
+ return sym;
sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, linkage_name,
domain, symtab);
diff --git a/gdb/symtab.h b/gdb/symtab.h
index db6a0a9..faeb5ea 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -1050,6 +1050,7 @@ extern struct symbol *lookup_symbol_static (const char *name,
extern struct symbol *lookup_symbol_global (const char *name,
const char *linkage_name,
+ const struct block *block,
const domain_enum domain,
struct symtab **symtab);
@@ -1398,4 +1399,12 @@ extern struct cleanup *make_cleanup_free_search_symbols (struct symbol_search
extern void set_main_name (const char *name);
extern /*const */ char *main_name (void);
+/* Check global symbols in objfile. */
+struct symbol *lookup_global_symbol_from_objfile (const struct objfile *objfile,
+ const char *name,
+ const char *linkage_name,
+ const domain_enum domain,
+ struct symtab **symtab);
+
+
#endif /* !defined(SYMTAB_H) */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 0508519..79994cc 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2007-07-03 Markus Deuling <deuling@de.ibm.com>
+
+ * gdb.base/solib-symbol.exp: New file (testcase multiple symbol lookup).
+ * gdb.base/solib-symbol-lib.c: Likewise.
+ * gdb.base/solib-symbol-main.c: Likewise.
+
2007-07-02 Daniel Jacobowitz <dan@codesourcery.com>
* config/gdbserver.exp (gdb_reconnect): New.
diff --git a/gdb/testsuite/gdb.base/solib-symbol-lib.c b/gdb/testsuite/gdb.base/solib-symbol-lib.c
new file mode 100644
index 0000000..45f72b6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-symbol-lib.c
@@ -0,0 +1,32 @@
+/* Copyright 2007 Free Software Foundation, Inc.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contributed by Markus Deuling <deuling@de.ibm.com>.
+*/
+#include <stdio.h>
+
+void
+foo ()
+{
+ printf ("foo in lib\n");
+ return;
+}
+
+void
+foo2()
+{
+ printf ("foo2 in lib\n");
+ return;
+}
diff --git a/gdb/testsuite/gdb.base/solib-symbol-main.c b/gdb/testsuite/gdb.base/solib-symbol-main.c
new file mode 100644
index 0000000..9c28f2b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-symbol-main.c
@@ -0,0 +1,43 @@
+/* Copyright 2007 Free Software Foundation, Inc.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contributed by Markus Deuling <deuling@de.ibm.com>.
+*/
+#include <stdio.h>
+
+extern void foo();
+void foo3();
+void foo2();
+
+int main ()
+{
+ printf ("in main\n");
+ foo ();
+ foo3 ();
+ return 0;
+}
+
+void foo3()
+{
+ printf ("foo3 in main\n");
+ return;
+}
+
+void foo2()
+{
+ printf ("foo2 in main\n");
+ return;
+}
+
diff --git a/gdb/testsuite/gdb.base/solib-symbol.exp b/gdb/testsuite/gdb.base/solib-symbol.exp
new file mode 100644
index 0000000..0aeeaa1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-symbol.exp
@@ -0,0 +1,80 @@
+# Copyright 2007 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Contributed by Markus Deuling <deuling@de.ibm.com>.
+#
+
+if {[skip_shlib_tests]} {
+ return 0
+}
+
+# Library file.
+set libname "solib-symbol-lib"
+set srcfile_lib ${srcdir}/${subdir}/${libname}.c
+set binfile_lib ${objdir}/${subdir}/${libname}.so
+set lib_flags [list debug ldflags=-Wl,-Bsymbolic]
+# Binary file.
+set testfile "solib-symbol-main"
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set bin_flags [list debug shlib=${binfile_lib}]
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != ""
+ || [gdb_compile ${srcfile} ${binfile} executable $bin_flags] != "" } {
+ untested "Could not compile $binfile_lib or $binfile."
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+gdb_load_shlibs $binfile_lib
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+# Set a breakpoint in the binary.
+gdb_test "br foo2" \
+ "Breakpoint.*file.*${srcfile}.*" \
+ "foo2 in main"
+
+delete_breakpoints
+
+# Break in the library.
+gdb_test "br foo" \
+ "" \
+ "foo in libmd"
+
+gdb_test "continue" \
+ "Continuing.*" \
+ "continue"
+
+# This symbol is now looked up in the ELF library.
+gdb_test "br foo2" \
+ "Breakpoint.*file.*${srcfile_lib}.*" \
+ "foo2 in mdlib"
+
+gdb_exit
+
+return 0
+
+