public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] Test stepping within a runtime loader / dynamic linker
@ 2022-10-20  2:41 Kevin Buettner
  0 siblings, 0 replies; only message in thread
From: Kevin Buettner @ 2022-10-20  2:41 UTC (permalink / raw)
  To: gdb-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=97df7412a183b73a1bfaeed55a4d951c2aede7d4

commit 97df7412a183b73a1bfaeed55a4d951c2aede7d4
Author: Kevin Buettner <kevinb@redhat.com>
Date:   Wed Oct 19 19:36:07 2022 -0700

    Test stepping within a runtime loader / dynamic linker
    
    See the remarks in rtld-step.exp for a description of what this
    test is about.
    
    This test case has been tested using gcc on the following x86-64 Linux
    distributions/releases:
    
        Fedora 28
        Fedora 32
        Fedora 33
        Fedora 34
        Fedora 35
        Fedora 36
        Fedora 37
        rawhide (f38)
        RHEL 9.1
        Ubuntu 22.04.1 LTS
    
    It's also been tested (and found to be working) with
    RUNTESTFLAGS="CC_FOR_TARGET=clang" on all of the above expect for
    Fedora 28.  The (old) version of clang available on F28 did not
    accept the -static-pie option.
    
    I also tried to make this test work on FreeBSD 13.1.  While I think I
    made significant progress, I was ultimately stymied by this message
    which occurs when attempting to run the main program which has been
    set to use the fake/pretend RTLD as the ELF interpreter:
    
    ELF interpreter /path/to/rtld-step-rtld not found, error 22
    
    I have left one of the flags (-static) in place which I believe
    to be needed for FreeBSD (though since I never got it to work, I
    don't know for sure.)  I've also left some declarations needed
    for FreeBSD in rtld-step-rtld.c.  They're currently disabled via
    a #if 0; you'll need to enable them if you want to try to make
    it work on FreeBSD.

Diff:
---
 gdb/testsuite/gdb.base/rtld-step-main.c |  22 +++++
 gdb/testsuite/gdb.base/rtld-step-rtld.c |  65 +++++++++++++++
 gdb/testsuite/gdb.base/rtld-step.exp    | 140 ++++++++++++++++++++++++++++++++
 3 files changed, 227 insertions(+)

diff --git a/gdb/testsuite/gdb.base/rtld-step-main.c b/gdb/testsuite/gdb.base/rtld-step-main.c
new file mode 100644
index 00000000000..6b3984dc7d2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/rtld-step-main.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2022 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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/rtld-step-rtld.c b/gdb/testsuite/gdb.base/rtld-step-rtld.c
new file mode 100644
index 00000000000..e234ebf9ead
--- /dev/null
+++ b/gdb/testsuite/gdb.base/rtld-step-rtld.c
@@ -0,0 +1,65 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2022 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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+
+/* The declarations below are needed if you try to make this test case
+   work on FreeBSD.  They're disabled because there are other problems
+   with this test on FreeBSD.  See the .exp file for more info.  If
+   those other problems can be resolved, it may be worth reenabling
+   these declarations.  */
+#if 0
+__attribute__((weak))
+char *__progname = "fake-rtld";
+
+__attribute__((weak))
+char **environ = 0;
+#endif
+
+void
+baz (int i)
+{
+}
+
+void
+foo (int a)
+{
+  baz (a);
+}
+
+void
+bar ()
+{
+  foo (1);
+  baz (99);
+  foo (2);
+}
+
+int
+main ()
+{
+  foo (0);
+  bar ();
+  return 0;
+}
+
+void
+_start ()
+{
+  main ();
+  _exit (0);
+}
diff --git a/gdb/testsuite/gdb.base/rtld-step.exp b/gdb/testsuite/gdb.base/rtld-step.exp
new file mode 100644
index 00000000000..4773fa8de3d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/rtld-step.exp
@@ -0,0 +1,140 @@
+# Copyright 2022 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 3 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, see <http://www.gnu.org/licenses/>.
+
+# Test stepping through a runtime loader / dynamic linker (RTLD):
+#
+# While it'd be nice to have a test which steps through an actual
+# runtime loader / dynamic linker, constructing such a test would be
+# non-portable; we would need to know implementation details such
+# as the names of some of the symbols and the order of calls to
+# various functions that implement the RTLD.  So, instead, we'll use a
+# program which doesn't even pretend to implement this functionality,
+# but which will instead be invoked in the same fashion (for ELF
+# binaries anyway) as would be expected for an ELF-based RTLD.
+#
+# To that end, we have two programs, one which will pretend to be an
+# RTLD and the other which will be caused to use the pretend RTLD.
+#
+# When the main program is run, the pretend/fake RTLD is run instead,
+# due to it being specified as the ELF interpreter for the main
+# program.  Within GDB, we then attempt to do some simple debugging
+# involving 'step', 'next', and 'finish'.
+
+# This test can't be run on targets lacking shared library support
+# or for non-ELF targets.  (We're not really testing or building
+# shared libraries here, but having a RTLD implies having shared
+# libraries on the target.)
+if { [skip_shlib_tests] || ![is_elf_target] } {
+    return 0
+}
+
+# (Pretend) RTLD file names and flags:
+set rtld_basename ${::gdb_test_file_name}-rtld
+set srcfile_rtld ${srcdir}/${subdir}/${rtld_basename}.c
+set binfile_rtld [standard_output_file ${rtld_basename}]
+
+# Placing 'pie' in the flag list (for rtld_flags) doesn't work, but
+# using -static-pie -FPIE in additional_flags does.  Apparently, when
+# 'pie' is listed, gdb_compile will (on Linux) use both -fPIE and
+# -pie.	 Testing shows that use of -pie creates a dynamically linked
+# executable when either a static or static-pie executable is desired
+# instead.  (This is probably fragile.)
+#
+# While developing this code on Fedora Linux, it was found that (only)
+# the flags -static-pie -fPIE were needed for Fedora 35 through Fedora
+# 38.  The source file rtld-step-rtld.c didn't need the _start()
+# function either.  And, better still, it was possible to call
+# printf() to output progress messages in the pretend/fake RTLD. 
+# Sadly, these output statements had to be removed in order to obtain
+# code which would work on other Linux distributions / releases.
+#
+# When testing against earlier versions of Fedora, RHEL 9, and
+# also Ubuntu 22.04, that short flag list didn't work.	For these
+# linux releases, it was found that -nostdlib -lc were also required.
+# Due to the use of -nostdlib, a _start() function had to be added
+# to the RTLD code.
+#
+# Finally, on FreeBSD, it was found that in order to end up with a
+# statically linked executable, -static was also needed.
+# Unfortunately, when attempting to run the rtld-step-main under GDB
+# on FreeBSD 13.1, this message was/is encountered:
+#
+# ELF interpreter /path/to/rtld-step-rtld not found, error 22
+#
+# So, sadly, this test does not currently work on FreeBSD.  If you try
+# to make it work on FreeBSD, you'll probably need to enable the
+# declarations for __progname and environ in rtld-step-rtld.c.
+#
+# If this test becomes broken at some point in the future, you might
+# try removing -static from the flags below as it is not needed for
+# Linux.
+#
+# Also, because the RTLD is static, you'll need static versions of
+# libc/glibc installed on your system.  (A message such as "cannot
+# find -lc" is a clue that you're missing a static version of libc.)
+
+set rtld_flags [list debug additional_flags=[list -static-pie -fPIE \
+						  -nostdlib -static -lc]]
+
+# Main program file names and flags:
+set main_basename ${::gdb_test_file_name}-main
+set srcfile_main ${srcdir}/${subdir}/${main_basename}.c
+set binfile_main [standard_output_file ${main_basename}]
+set main_flags [list debug additional_flags="-Wl,--dynamic-linker=${binfile_rtld}"]
+
+# Compile pretend RTLD:
+if { [gdb_compile ${srcfile_rtld} ${binfile_rtld} executable $rtld_flags] != "" } {
+    untested "failed to compile"
+    return -1
+}
+
+# Compile main program:
+if { [gdb_compile ${srcfile_main} ${binfile_main} executable $main_flags] != "" } {
+    untested "failed to compile"
+    return -1
+}
+
+clean_restart ${binfile_main}
+
+if {![runto_main]} {
+    return 0
+}
+
+# Running the command 'info sharedlibrary' should output a path to
+# the pretend/fake RTLD along with the address range.  Check that
+# this path is present and, if so, extract the address range.
+gdb_test_multiple "info sharedlibrary" "" {
+    -re -wrap "($hex)\[ \t\]+($hex)\[ \t\]+Yes\[ \t\]+$fullname_syntax$rtld_basename" {
+	set rtld_lower $expect_out(1,string)
+	set rtld_upper $expect_out(2,string)
+	pass $gdb_test_name
+    }
+}
+
+# Fetch PC value.
+set pc [get_hexadecimal_valueof "\$pc" 0]
+
+# Verify that PC is in the address range of the pretend/fake RTLD.
+gdb_assert { $rtld_lower <= $pc && $pc < $rtld_upper } "pc is in rtld"
+
+gdb_test "next" {bar \(\);} "next over foo 0"
+gdb_test "step" {bar \(\) at.*foo \(1\);.*} "step into bar"
+gdb_test "step" {baz \(.*?\);} "step into foo 1"
+gdb_test "finish" {Run till exit.*bar \(\).*baz.*} "finish out of foo 1"
+gdb_test "next" {foo \(2\);} "next over baz in bar"
+gdb_test "step" {baz \(.*?\);} "step into foo 2"
+gdb_test "next" "\}\[\r\n\]+" "next over baz in foo"
+gdb_test "step" "bar \\(\\).*}\[\r\n\]+.*" "step out of foo back into bar"
+
+gdb_continue_to_end

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-10-20  2:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-20  2:41 [binutils-gdb] Test stepping within a runtime loader / dynamic linker Kevin Buettner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).