This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[pushed] Make sym-file.exp work with remote targets and hosts.


The main issue here is that this test passes the host's absolute path
to the library to load to the "dlopen"-like routine, which doesn't
work when either the target or the host are remote, unless a shared
filesystem has been set up.

Tests that dynamically load a library solve this by dlopen'ing by
basename, and setting rpath to $ORIGIN.  See gdb_compile.

This test doesn't use dlopen, but instead uses its own simple elf
loader.  The fix is to pass this loader the library basename, and
teach it to look up the library by basename in the executable's
directory as well, i.e., assuming/emulating RPATH=$ORIGIN.

Tested on x86_64 Fedora 17, native and gdbserver.

I looked around in the web to figure out Linux's /proc/self/exe
equivalents in other ELF OSs.  I think I covered all relevant, but if
not, I think it'll be simple enough to add more.  (Note the test is
skipped on non-ELF targets.)

Tested on x86_64 Fedora 17, native and gdbserver.

gdb/testsuite/
2014-04-15  Pedro Alves  <palves@redhat.com>

	* gdb.base/sym-file-loader.c: Include <limits.h>.
	(SELF_LINK): New define.
	(get_origin): New function.
	(load_shlib): Use it.
	* gdb.base/sym-file.exp: Don't early return if the target is
	remote.  Use runto_main, and issue fail is that fails.  Use
	gdb_load_shlibs.
	(shlib_name): Delete.
	(lib_so, lib_syms, lib_dlopen): New globals.  Use them throughout.
---
 gdb/testsuite/ChangeLog                  | 12 ++++++
 gdb/testsuite/gdb.base/sym-file-loader.c | 70 ++++++++++++++++++++++++++++++--
 gdb/testsuite/gdb.base/sym-file.exp      | 50 ++++++++++++-----------
 3 files changed, 106 insertions(+), 26 deletions(-)

diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 0d773b6..64e4cbd 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,15 @@
+2014-04-15  Pedro Alves  <palves@redhat.com>
+
+	* gdb.base/sym-file-loader.c: Include <limits.h>.
+	(SELF_LINK): New define.
+	(get_origin): New function.
+	(load_shlib): Use it.
+	* gdb.base/sym-file.exp: Don't early return if the target is
+	remote.  Use runto_main, and issue fail is that fails.  Use
+	gdb_load_shlibs.
+	(shlib_name): Delete.
+	(lib_so, lib_syms, lib_dlopen): New globals.  Use them throughout.
+
 2014-04-15  Pedro Alves <palves@redhat.com>
 
 	* gdb.base/sym-file.exp: Remove regex characters from test
diff --git a/gdb/testsuite/gdb.base/sym-file-loader.c b/gdb/testsuite/gdb.base/sym-file-loader.c
index 65c48be..625788a 100644
--- a/gdb/testsuite/gdb.base/sym-file-loader.c
+++ b/gdb/testsuite/gdb.base/sym-file-loader.c
@@ -15,6 +15,7 @@
 
 #include <unistd.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -77,6 +78,48 @@ load (uint8_t *addr, Elf_External_Phdr *phdr, struct segment *tail_seg)
   return seg;
 }
 
+#ifdef __linux__
+# define SELF_LINK "/proc/self/exe"
+#elif defined NETBSD
+# define SELK_LINK "/proc/curproc/exe"
+#elif defined __OpenBSD__ || defined __FreeBSD__ || defined __DragonFly__
+# define SELK_LINK "/proc/curproc/file"
+#elif defined SunOS
+# define SELK_LINK "/proc/self/path/a.out"
+#endif
+
+/* Like RPATH=$ORIGIN, return the dirname of the current
+   executable.  */
+
+static const char *
+get_origin (void)
+{
+  static char self_path[PATH_MAX];
+  static ssize_t self_path_len;
+
+  if (self_path_len == 0)
+    {
+#ifdef SELF_LINK
+      self_path_len = readlink (SELF_LINK, self_path, PATH_MAX - 1);
+      if (self_path_len != -1)
+	{
+	  char *dirsep;
+
+	  self_path[self_path_len] = '\0';
+	  dirsep = strrchr (self_path, '/');
+	  *dirsep = '\0';
+	}
+#else
+      self_path_len = -1;
+#endif
+    }
+
+  if (self_path_len == -1)
+    return NULL;
+  else
+    return self_path;
+}
+
 /* Mini shared library loader.  No reallocation
    is performed for the sake of simplicity.  */
 
@@ -85,16 +128,37 @@ load_shlib (const char *file, Elf_External_Ehdr **ehdr_out,
 	    struct segment **seg_out)
 {
   uint64_t i;
-  int fd;
+  int fd = -1;
   off_t fsize;
   uint8_t *addr;
   Elf_External_Ehdr *ehdr;
   Elf_External_Phdr *phdr;
   struct segment *head_seg = NULL;
   struct segment *tail_seg = NULL;
+  const char *origin;
+  char *path;
+
+  /* Map the lib in memory for reading.
+
+     If the file name is relative, try looking it up relative to the
+     main executable's path.  I.e., emulate RPATH=$ORIGIN.  */
+  if (file[0] != '/')
+    {
+      origin = get_origin ();
+      if (origin == NULL)
+	{
+	  fprintf (stderr, "get_origin not implemented.");
+	  return -1;
+	}
+
+      path = alloca (strlen (origin) + 1 + strlen (file) + 1);
+      sprintf (path, "%s/%s", origin, file);
+      fd = open (path, O_RDONLY);
+    }
+
+  if (fd < 0)
+    fd = open (file, O_RDONLY);
 
-  /* Map the lib in memory for reading.  */
-  fd = open (file, O_RDONLY);
   if (fd < 0)
     {
       perror ("fopen failed.");
diff --git a/gdb/testsuite/gdb.base/sym-file.exp b/gdb/testsuite/gdb.base/sym-file.exp
index 9ee12e5..c87c3c7 100644
--- a/gdb/testsuite/gdb.base/sym-file.exp
+++ b/gdb/testsuite/gdb.base/sym-file.exp
@@ -16,14 +16,14 @@
 # Test adding and removing a symbol file dynamically:
 # 1)  Run to gdb_add_symbol_file in $srcfile.
 # 2)  Set a pending breakpoint at bar in $srcfile3.
-# 3)  Load $shlib_name using 'add-symbol-file'.
+# 3)  Load the library's symbols using 'add-symbol-file'.
 # 4)  'info files' must display ${lib_basename}.
 # 5)  Continue to bar in $srcfile3.
 # 6)  Set a breakpoint at foo in $srcfile3.
 # 7)  Continue to foo in $srcfile3.
 # 8)  Set a breakpoint at gdb_remove_symbol_file.
 # 9)  Continue to gdb_remove_symbol_file in $srcfile.
-# 10) Remove $shlib_name using 'remove-symbol-file'.
+# 10) Remove the library's symbols using 'remove-symbol-file'.
 # 11) 'info files' must not display ${lib_basename}, anymore.
 # 12) Check that the breakpoints at foo and bar are pending.
 # 13) Check that the execution can continue without error.
@@ -36,10 +36,6 @@ if [skip_shlib_tests] {
     return 0
 }
 
-if [is_remote target] {
-    return 0
-}
-
 set target_size TARGET_UNKNOWN
 if {[is_lp64_target]} {
     set target_size TARGET_LP64
@@ -56,15 +52,18 @@ set lib_basename sym-file-lib
 standard_testfile $main_basename.c $loader_basename.c $lib_basename.c
 
 set libsrc "${srcdir}/${subdir}/${srcfile3}"
-set shlib_name [standard_output_file ${lib_basename}.so]
+set lib_so [standard_output_file ${lib_basename}.so]
+set lib_syms [shlib_symbol_file ${lib_so}]
+set lib_dlopen [shlib_target_file ${lib_basename}.so]
+
 set exec_opts [list debug "additional_flags= -I$srcdir/../../include/ -D$target_size\
- -DSHLIB_NAME\\=\"$shlib_name\""]
+ -DSHLIB_NAME\\=\"$lib_dlopen\""]
 
 if [get_compiler_info] {
     return -1
 }
 
-if {[gdb_compile_shlib $libsrc $shlib_name {debug}] != ""} {
+if {[gdb_compile_shlib $libsrc $lib_so {debug}] != ""} {
     untested ${testfile}
     return
 }
@@ -73,22 +72,27 @@ if {[prepare_for_testing $testfile  $binfile "$srcfile $srcfile2" $exec_opts]} {
     return
 }
 
-# 1) Run to GDB_ADD_SYMBOl_FILE in $srcfile for adding
-#    $shlib_name.
-set result [runto gdb_add_symbol_file]
-if {!$result} then {
-   return
+gdb_load_shlibs ${lib_so}
+
+if ![runto_main] then {
+    fail "Can't run to main"
+    return
 }
 
+# 1) Run to gdb_add_symbol_file in $srcfile for adding the library's
+#    symbols.
+gdb_breakpoint gdb_add_symbol_file
+gdb_continue_to_breakpoint gdb_add_symbol_file
+
 # 2) Set a pending breakpoint at bar in $srcfile3.
 set result [gdb_breakpoint bar allow-pending]
 if {!$result} then {
    return
 }
 
-# 3) Add $shlib_name using 'add-symbol-file'.
-set result [gdb_test "add-symbol-file ${shlib_name} addr" \
-		     "Reading symbols from .*${lib_basename}\\.so\\.\\.\\.done\\." \
+# 3) Add the library's symbols using 'add-symbol-file'.
+set result [gdb_test "add-symbol-file ${lib_syms} addr" \
+		     "Reading symbols from .*${lib_syms}\\.\\.\\.done\\." \
 		     "add-symbol-file ${lib_basename}.so addr" \
 		     "add symbol table from file \".*${lib_basename}\\.so\"\
  at.*\\(y or n\\) " \
@@ -119,7 +123,7 @@ set lnum_foo [gdb_get_line_number "break at foo" $srcfile3]
 gdb_continue_to_breakpoint foo ".*${lib_basename}\\.c:$lnum_foo.*"
 
 # 8) Set a breakpoint at gdb_remove_symbol_file in $srcfile for
-#    removing $shlib_name.
+#    removing the library's symbols.
 set result [gdb_breakpoint gdb_remove_symbol_file]
 if {!$result} then {
     return
@@ -128,7 +132,7 @@ if {!$result} then {
 # 9) Continue to gdb_remove_symbol_file in $srcfile.
 gdb_continue_to_breakpoint gdb_remove_symbol_file
 
-# 10) Remove $shlib_name using 'remove-symbol-file'.
+# 10) Remove the library's symbols using 'remove-symbol-file'.
 set result [gdb_test "remove-symbol-file -a addr" \
 		     ""\
 		     "remove-symbol-file -a addr" \
@@ -144,13 +148,13 @@ gdb_test "info files" \
 	 "^(?!(.*${lib_basename})).*" \
 	 "info files must not display ${lib_basename}"
 
-# 12) Check that the breakpoints at foo and bar are pending after removing
-#     $shlib_name.
-gdb_test "info breakpoints 2" \
+# 12) Check that the breakpoints at foo and bar are pending after
+#     removing the library's symbols.
+gdb_test "info breakpoints 3" \
 	 ".*PENDING.*" \
 	 "breakpoint at foo is pending"
 
-gdb_test "info breakpoints 3" \
+gdb_test "info breakpoints 4" \
 	 ".*PENDING.*" \
 	 "breakpoint at bar is pending"
 
-- 
1.7.11.7


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]