mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 12:03:41 +08:00
6ccf769a17
On fedora rawhide, with test-case gdb.base/rtld-step.exp I get: ... static-pie-static-libc.c: In function '_start':^M static-pie-static-libc.c:1:22: error: \ implicit declaration of function '_exit' [-Wimplicit-function-declaration]^M 1 | void _start (void) { _exit (0); }^M | ^~~~~^M compiler exited with status 1 ... UNTESTED: gdb.base/rtld-step.exp: failed to compile \ (-static-pie not supported or static libc missing) ... Fix this by adding the missing include. Tested on aarch64-linux. Approved-by: Kevin Buettner <kevinb@redhat.com>
150 lines
6.2 KiB
Plaintext
150 lines
6.2 KiB
Plaintext
# Copyright 2022-2024 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.)
|
|
require allow_shlib_tests is_elf_target
|
|
|
|
# (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]]
|
|
|
|
if { ![gdb_can_simple_compile static-pie-static-libc \
|
|
{
|
|
#include <unistd.h>
|
|
void _start (void) { _exit (0); }
|
|
} \
|
|
executable $rtld_flags] } {
|
|
set reason "-static-pie not supported or static libc missing"
|
|
untested "failed to compile ($reason)"
|
|
return -1
|
|
}
|
|
|
|
# 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" "\}" "next over baz in foo"
|
|
gdb_test "step" "bar \\(\\).*}" "step out of foo back into bar"
|
|
|
|
gdb_continue_to_end
|