2002-09-17 23:50:03 +00:00
|
|
|
/* Return backtrace of current program state.
|
2020-01-01 00:14:33 +00:00
|
|
|
Copyright (C) 1998-2020 Free Software Foundation, Inc.
|
2002-09-17 23:50:03 +00:00
|
|
|
This file is part of the GNU C Library.
|
|
|
|
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public License as
|
|
|
|
published by the Free Software Foundation; either version 2 of the
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
The GNU C Library 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public
|
2012-02-09 23:18:22 +00:00
|
|
|
License along with the GNU C Library; see the file COPYING.LIB. If
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 05:40:42 +00:00
|
|
|
not, see <https://www.gnu.org/licenses/>. */
|
2002-09-17 23:50:03 +00:00
|
|
|
|
|
|
|
#include <stddef.h>
|
2013-08-20 20:01:59 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <signal.h>
|
2017-05-08 14:22:20 +00:00
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include <execinfo.h>
|
2015-04-13 19:38:16 +00:00
|
|
|
#include <libc-vdso.h>
|
2002-09-17 23:50:03 +00:00
|
|
|
|
|
|
|
/* This is the stack layout we see with every stack frame.
|
|
|
|
Note that every routine is required by the ABI to lay out the stack
|
|
|
|
like this.
|
|
|
|
|
|
|
|
+----------------+ +-----------------+
|
|
|
|
%r1 -> | %r1 last frame--------> | %r1 last frame--->... --> NULL
|
|
|
|
| | | |
|
|
|
|
| cr save | | cr save |
|
|
|
|
| | | |
|
|
|
|
| (unused) | | return address |
|
|
|
|
+----------------+ +-----------------+
|
|
|
|
*/
|
|
|
|
struct layout
|
|
|
|
{
|
2013-02-13 23:30:40 +00:00
|
|
|
struct layout *next;
|
2017-05-08 14:22:20 +00:00
|
|
|
long int condition_register;
|
2013-02-13 23:30:40 +00:00
|
|
|
void *return_address;
|
2002-09-17 23:50:03 +00:00
|
|
|
};
|
|
|
|
|
2013-08-20 20:01:59 +00:00
|
|
|
/* Since the signal handler is just like any other function it needs to
|
|
|
|
save/restore its LR and it will save it into callers stack frame.
|
|
|
|
Since a signal handler doesn't have a caller, the kernel creates a
|
|
|
|
dummy frame to make it look like it has a caller. */
|
|
|
|
struct signal_frame_64 {
|
|
|
|
#define SIGNAL_FRAMESIZE 128
|
2017-05-08 14:22:20 +00:00
|
|
|
char dummy[SIGNAL_FRAMESIZE];
|
2017-06-26 22:03:58 +00:00
|
|
|
ucontext_t uc;
|
2013-08-20 20:01:59 +00:00
|
|
|
/* We don't care about the rest, since the IP value is at 'uc' field. */
|
|
|
|
};
|
|
|
|
|
elf: Move vDSO setup to rtld (BZ#24967)
This patch moves the vDSO setup from libc to loader code, just after
the vDSO link_map setup. For static case the initialization
is moved to _dl_non_dynamic_init instead.
Instead of using the mangled pointer, the vDSO data is set as
attribute_relro (on _rtld_global_ro for shared or _dl_vdso_* for
static). It is read-only even with partial relro.
It fixes BZ#24967 now that the vDSO pointer is setup earlier than
malloc interposition is called.
Also, vDSO calls should not be a problem for static dlopen as
indicated by BZ#20802. The vDSO pointer would be zero-initialized
and the syscall will be issued instead.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
arm-linux-gnueabihf, powerpc64le-linux-gnu, powerpc64-linux-gnu,
powerpc-linux-gnu, s390x-linux-gnu, sparc64-linux-gnu, and
sparcv9-linux-gnu. I also run some tests on mips.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
2019-11-29 13:44:59 +00:00
|
|
|
static inline bool
|
2017-05-08 14:22:20 +00:00
|
|
|
is_sigtramp_address (void *nip)
|
2013-08-20 20:01:59 +00:00
|
|
|
{
|
Refactor vDSO initialization code
Linux vDSO initialization code the internal function pointers require a
lot of duplicated boilerplate over different architectures. This patch
aims to simplify not only the code but the required definition to enable
a vDSO symbol.
The changes are:
1. Consolidate all init-first.c on only one implementation and enable
the symbol based on HAVE_*_VSYSCALL existence.
2. Set the HAVE_*_VSYSCALL to the architecture expected names string.
3. Add a new internal implementation, get_vdso_mangle_symbol, which
returns a mangled function pointer.
Currently the clock_gettime, clock_getres, gettimeofday, getcpu, and time
are handled in an arch-independent way, powerpc still uses some
arch-specific vDSO symbol handled in a specific init-first implementation.
Checked on aarch64-linux-gnu, arm-linux-gnueabihf, i386-linux-gnu,
mips64-linux-gnu, powerpc64le-linux-gnu, s390x-linux-gnu,
sparc64-linux-gnu, and x86_64-linux-gnu.
* sysdeps/powerpc/powerpc32/backtrace.c (is_sigtramp_address,
is_sigtramp_address_rt): Use HAVE_SIGTRAMP_{RT}32 instead of SHARED.
* sysdeps/powerpc/powerpc64/backtrace.c (is_sigtramp_address):
Likewise.
* sysdeps/unix/sysv/linux/aarch64/init-first.c: Remove file.
* sysdeps/unix/sysv/linux/aarch64/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/arm/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/arm/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/mips/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/mips/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/i386/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/riscv/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/riscv/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/s390/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/s390/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/sparc/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/sparc/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/x86/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/x86_64/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/aarch64/sysdep.h
(HAVE_CLOCK_GETRES_VSYSCALL, HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETTIMEOFDAY_VSYSCALL): Define value based on kernel exported
name.
* sysdeps/unix/sysv/linux/arm/sysdep.h (HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETTIMEOFDAY_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/i386/sysdep.h (HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETTIMEOFDAY_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/mips/sysdep.h (HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETTIMEOFDAY_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/powerpc/sysdep.h
(HAVE_CLOCK_GETRES_VSYSCALL, HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETCPU_VSYSCALL, HAVE_TIME_VSYSCALL, HAVE_GET_TBFREQ,
HAVE_SIGTRAMP_RT64, HAVE_SIGTRAMP_32, HAVE_SIGTRAMP_RT32i,
HAVE_GETTIMEOFDAY_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/riscv/sysdep.h (HAVE_CLOCK_GETRES_VSYSCALL,
HAVE_CLOCK_GETTIME_VSYSCALL, HAVE_GETTIMEOFDAY_VSYSCALL,
HAVE_GETCPU_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/s390/sysdep.h (HAVE_CLOCK_GETRES_VSYSCALL,
HAVE_CLOCK_GETTIME_VSYSCALL, HAVE_GETTIMEOFDAY_VSYSCALL,
HAVE_GETCPU_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/sparc/sysdep.h (HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETTIMEOFDAY_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/x86_64/sysdep.h
(HAVE_CLOCK_GETTIME_VSYSCALL, HAVE_GETTIMEOFDAY_VSYSCALL,
HAVE_GETCPU_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/dl-vdso.h (VDSO_NAME, VDSO_HASH): Define to
invalid names if architecture does not define them.
(get_vdso_mangle_symbol): New symbol.
* sysdeps/unix/sysv/linux/init-first.c: New file.
* sysdeps/unix/sysv/linux/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/powerpc/init-first.c (gettimeofday,
clock_gettime, clock_getres, getcpu, time): Remove declaration.
(__libc_vdso_platform_setup_arch): Likewise and use
get_vdso_mangle_symbol to setup vDSO symbols.
(sigtramp_rt64, sigtramp32, sigtramp_rt32, get_tbfreq): Add
attribute_hidden.
* sysdeps/unix/sysv/linux/powerpc/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/sysdep-vdso.h (VDSO_SYMBOL): Remove
definition.
2019-06-03 13:22:13 +00:00
|
|
|
#ifdef HAVE_SIGTRAMP_RT64
|
elf: Move vDSO setup to rtld (BZ#24967)
This patch moves the vDSO setup from libc to loader code, just after
the vDSO link_map setup. For static case the initialization
is moved to _dl_non_dynamic_init instead.
Instead of using the mangled pointer, the vDSO data is set as
attribute_relro (on _rtld_global_ro for shared or _dl_vdso_* for
static). It is read-only even with partial relro.
It fixes BZ#24967 now that the vDSO pointer is setup earlier than
malloc interposition is called.
Also, vDSO calls should not be a problem for static dlopen as
indicated by BZ#20802. The vDSO pointer would be zero-initialized
and the syscall will be issued instead.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
arm-linux-gnueabihf, powerpc64le-linux-gnu, powerpc64-linux-gnu,
powerpc-linux-gnu, s390x-linux-gnu, sparc64-linux-gnu, and
sparcv9-linux-gnu. I also run some tests on mips.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
2019-11-29 13:44:59 +00:00
|
|
|
if (nip == GLRO (dl_vdso_sigtramp_rt64))
|
|
|
|
return true;
|
2013-08-20 20:01:59 +00:00
|
|
|
#endif
|
elf: Move vDSO setup to rtld (BZ#24967)
This patch moves the vDSO setup from libc to loader code, just after
the vDSO link_map setup. For static case the initialization
is moved to _dl_non_dynamic_init instead.
Instead of using the mangled pointer, the vDSO data is set as
attribute_relro (on _rtld_global_ro for shared or _dl_vdso_* for
static). It is read-only even with partial relro.
It fixes BZ#24967 now that the vDSO pointer is setup earlier than
malloc interposition is called.
Also, vDSO calls should not be a problem for static dlopen as
indicated by BZ#20802. The vDSO pointer would be zero-initialized
and the syscall will be issued instead.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
arm-linux-gnueabihf, powerpc64le-linux-gnu, powerpc64-linux-gnu,
powerpc-linux-gnu, s390x-linux-gnu, sparc64-linux-gnu, and
sparcv9-linux-gnu. I also run some tests on mips.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
2019-11-29 13:44:59 +00:00
|
|
|
return false;
|
2013-08-20 20:01:59 +00:00
|
|
|
}
|
|
|
|
|
2002-09-17 23:50:03 +00:00
|
|
|
int
|
|
|
|
__backtrace (void **array, int size)
|
|
|
|
{
|
|
|
|
struct layout *current;
|
|
|
|
int count;
|
|
|
|
|
|
|
|
/* Force gcc to spill LR. */
|
|
|
|
asm volatile ("" : "=l"(current));
|
|
|
|
|
|
|
|
/* Get the address on top-of-stack. */
|
|
|
|
asm volatile ("ld %0,0(1)" : "=r"(current));
|
|
|
|
|
|
|
|
for ( count = 0;
|
|
|
|
current != NULL && count < size;
|
2013-02-01 06:35:29 +00:00
|
|
|
current = current->next, count++)
|
2013-08-20 20:01:59 +00:00
|
|
|
{
|
|
|
|
array[count] = current->return_address;
|
|
|
|
|
|
|
|
/* Check if the symbol is the signal trampoline and get the interrupted
|
|
|
|
* symbol address from the trampoline saved area. */
|
2017-05-08 14:22:20 +00:00
|
|
|
if (is_sigtramp_address (current->return_address))
|
2013-08-20 20:01:59 +00:00
|
|
|
{
|
|
|
|
struct signal_frame_64 *sigframe = (struct signal_frame_64*) current;
|
2020-01-20 16:01:50 +00:00
|
|
|
if (count + 1 == size)
|
|
|
|
break;
|
2017-05-08 14:22:20 +00:00
|
|
|
array[++count] = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_NIP];
|
|
|
|
current = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_R1];
|
2013-08-20 20:01:59 +00:00
|
|
|
}
|
|
|
|
}
|
2002-09-17 23:50:03 +00:00
|
|
|
|
|
|
|
/* It's possible the second-last stack frame can't return
|
|
|
|
(that is, it's __libc_start_main), in which case
|
|
|
|
the CRT startup code will have set its LR to 'NULL'. */
|
|
|
|
if (count > 0 && array[count-1] == NULL)
|
|
|
|
count--;
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
weak_alias (__backtrace, backtrace)
|
2005-06-14 15:55:44 +00:00
|
|
|
libc_hidden_def (__backtrace)
|