mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2025-01-09 02:43:42 +01:00
(Logical change 1.45)
This commit is contained in:
parent
5f94e2d488
commit
824d6619b5
21 changed files with 1667 additions and 0 deletions
|
@ -0,0 +1,136 @@
|
|||
'\" t
|
||||
.\" Manual page created with latex2man on Sat Feb 8 01:31:56 PST 2003
|
||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
||||
.de Vb
|
||||
.ft CW
|
||||
.nf
|
||||
..
|
||||
.de Ve
|
||||
.ft R
|
||||
|
||||
.fi
|
||||
..
|
||||
.TH "LIBUNWIND\-SETJMP" "3" "08 February 2003" "Programming Library " "Programming Library "
|
||||
.SH NAME
|
||||
|
||||
libunwind\-setjmp \-\- libunwind\-based non\-local gotos
|
||||
.PP
|
||||
.SH SYNOPSIS
|
||||
|
||||
.PP
|
||||
#include <setjmp.h>
|
||||
.br
|
||||
.PP
|
||||
int
|
||||
setjmp(jmp_buf env);
|
||||
.br
|
||||
void
|
||||
longjmp(jmp_buf env,
|
||||
int val);
|
||||
.br
|
||||
int
|
||||
_setjmp(jmp_buf env);
|
||||
.br
|
||||
void
|
||||
_longjmp(jmp_buf env,
|
||||
int val);
|
||||
.br
|
||||
int
|
||||
setjmp(sigjmp_buf env,
|
||||
int savemask);
|
||||
.br
|
||||
void
|
||||
siglongjmp(sigjmp_buf env,
|
||||
int val);
|
||||
.br
|
||||
.PP
|
||||
.SH DESCRIPTION
|
||||
|
||||
.PP
|
||||
The unwind\-setjmp
|
||||
library offers a libunwind\-based
|
||||
implementation of non\-local gotos. This implementation is intended to
|
||||
be a drop\-in replacement for the normal, system\-provided routines of
|
||||
the same name. The main advantage of using the unwind\-setjmp
|
||||
library is that setting up a non\-local goto via one of the
|
||||
setjmp()
|
||||
routines is very fast. Typically, just 2 or 3 words
|
||||
need to be saved in the jump\-buffer (plus one call to
|
||||
sigprocmask(2),
|
||||
in the case of sigsetjmp).
|
||||
On the
|
||||
other hand, executing a non\-local goto by calling one of the
|
||||
longjmp()
|
||||
routines tends to be much slower than with the
|
||||
system\-provided routines. In fact, the time spent on a
|
||||
longjmp()
|
||||
will be proportional to the number of call frames
|
||||
that exist between the points where setjmp()
|
||||
and
|
||||
longjmp()
|
||||
were called. For this reason, the
|
||||
unwind\-setjmp
|
||||
library is beneficial primarily in applications
|
||||
that frequently call setjmp()
|
||||
but only rarely call
|
||||
longjmp().
|
||||
.PP
|
||||
.SH CAVEATS
|
||||
|
||||
.PP
|
||||
.TP
|
||||
.B *
|
||||
The correct operation of this library depends on the presence of
|
||||
correct unwind information. On newer platforms, this is rarely an
|
||||
issue. On older platforms, care needs to be taken to
|
||||
ensure that each of the functions whose stack frames may have to be
|
||||
unwound during a longjmp()
|
||||
have correct unwind information
|
||||
(on those platforms, there is usually a compiler\-switch, such as
|
||||
\fB\-funwind\-tables\fP,
|
||||
to request the generation of unwind
|
||||
information).
|
||||
.TP
|
||||
.B *
|
||||
The contents of jmp_buf and sigjmp_buf as setup
|
||||
and used by these routines is completely different from the ones
|
||||
used by the system\-provided routines. Thus, a jump\-buffer created
|
||||
by the libunwind\-based setjmp()/_setjmp
|
||||
may only be
|
||||
used in a call to the libunwind\-based
|
||||
longjmp()/_longjmp().
|
||||
The analogous applies for
|
||||
sigjmp_buf
|
||||
with sigsetjmp()
|
||||
and siglongjmp().
|
||||
.PP
|
||||
.SH FILES
|
||||
|
||||
.PP
|
||||
.TP
|
||||
\fB\-l\fPunwind\-setjmp
|
||||
The library an application should
|
||||
be linked against to ensure it uses the libunwind\-based non\-local
|
||||
goto routines.
|
||||
.PP
|
||||
.SH SEE ALSO
|
||||
|
||||
.PP
|
||||
libunwind(3),
|
||||
setjmp(3), longjmp(3),
|
||||
_setjmp(3), _longjmp(3),
|
||||
sigsetjmp(3), siglongjmp(3)
|
||||
.PP
|
||||
.SH AUTHOR
|
||||
|
||||
.PP
|
||||
David Mosberger\-Tang
|
||||
.br
|
||||
Hewlett\-Packard Labs
|
||||
.br
|
||||
Palo\-Alto, CA 94304
|
||||
.br
|
||||
Email: \fBdavidm@hpl.hp.com\fP
|
||||
.br
|
||||
WWW: \fBhttp://www.hpl.hp.com/research/linux/libunwind/\fP\&.
|
||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
|
@ -0,0 +1,90 @@
|
|||
\documentclass{article}
|
||||
\usepackage[fancyhdr,pdf]{latex2man}
|
||||
|
||||
\input{common.tex}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{Name}{3}{libunwind-setjmp}{David Mosberger-Tang}{Programming Library}{libunwind-based non-local gotos}
|
||||
libunwind-setjmp -- libunwind-based non-local gotos
|
||||
\end{Name}
|
||||
|
||||
\section{Synopsis}
|
||||
|
||||
\File{\#include $<$setjmp.h$>$}\\
|
||||
|
||||
\noindent
|
||||
\Type{int} \Func{setjmp}(\Type{jmp\_buf}~\Var{env});\\
|
||||
\Type{void} \Func{longjmp}(\Type{jmp\_buf}~\Var{env}, \Type{int}~\Var{val});\\
|
||||
\Type{int} \Func{\_setjmp}(\Type{jmp\_buf}~\Var{env});\\
|
||||
\Type{void} \Func{\_longjmp}(\Type{jmp\_buf}~\Var{env}, \Type{int}~\Var{val});\\
|
||||
\Type{int} \Func{setjmp}(\Type{sigjmp\_buf}~\Var{env}, \Type{int}~\Var{savemask});\\
|
||||
\Type{void} \Func{siglongjmp}(\Type{sigjmp\_buf}~\Var{env}, \Type{int}~\Var{val});\\
|
||||
|
||||
\section{Description}
|
||||
|
||||
The \Prog{unwind-setjmp} library offers a \Prog{libunwind}-based
|
||||
implementation of non-local gotos. This implementation is intended to
|
||||
be a drop-in replacement for the normal, system-provided routines of
|
||||
the same name. The main advantage of using the \Prog{unwind-setjmp}
|
||||
library is that setting up a non-local goto via one of the
|
||||
\Func{setjmp}() routines is very fast. Typically, just 2 or 3 words
|
||||
need to be saved in the jump-buffer (plus one call to
|
||||
\Func{sigprocmask}(2), in the case of \Func{sigsetjmp}). On the
|
||||
other hand, executing a non-local goto by calling one of the
|
||||
\Func{longjmp}() routines tends to be much slower than with the
|
||||
system-provided routines. In fact, the time spent on a
|
||||
\Func{longjmp}() will be proportional to the number of call frames
|
||||
that exist between the points where \Func{setjmp}() and
|
||||
\Func{longjmp}() were called. For this reason, the
|
||||
\Prog{unwind-setjmp} library is beneficial primarily in applications
|
||||
that frequently call \Func{setjmp}() but only rarely call
|
||||
\Func{longjmp}().
|
||||
|
||||
\section{Caveats}
|
||||
|
||||
\begin{itemize}
|
||||
\item The correct operation of this library depends on the presence of
|
||||
correct unwind information. On newer platforms, this is rarely an
|
||||
issue. On older platforms, care needs to be taken to
|
||||
ensure that each of the functions whose stack frames may have to be
|
||||
unwound during a \Func{longjmp}() have correct unwind information
|
||||
(on those platforms, there is usually a compiler-switch, such as
|
||||
\Opt{-funwind-tables}, to request the generation of unwind
|
||||
information).
|
||||
\item The contents of \Type{jmp\_buf} and \Type{sigjmp\_buf} as setup
|
||||
and used by these routines is completely different from the ones
|
||||
used by the system-provided routines. Thus, a jump-buffer created
|
||||
by the libunwind-based \Func{setjmp}()/\Func{\_setjmp} may only be
|
||||
used in a call to the libunwind-based
|
||||
\Func{longjmp}()/\Func{\_longjmp}(). The analogous applies for
|
||||
\Type{sigjmp\_buf} with \Func{sigsetjmp}() and \Func{siglongjmp}().
|
||||
\end{itemize}
|
||||
|
||||
\section{Files}
|
||||
|
||||
\begin{Description}
|
||||
\item[\Opt{-l}\File{unwind-setjmp}] The library an application should
|
||||
be linked against to ensure it uses the libunwind-based non-local
|
||||
goto routines.
|
||||
\end{Description}
|
||||
|
||||
|
||||
\section{See Also}
|
||||
|
||||
\SeeAlso{libunwind(3)},
|
||||
setjmp(3), longjmp(3),
|
||||
\_setjmp(3), \_longjmp(3),
|
||||
sigsetjmp(3), siglongjmp(3)
|
||||
|
||||
\section{Author}
|
||||
|
||||
\noindent
|
||||
David Mosberger-Tang\\
|
||||
Hewlett-Packard Labs\\
|
||||
Palo-Alto, CA 94304\\
|
||||
Email: \Email{davidm@hpl.hp.com}\\
|
||||
WWW: \URL{http://www.hpl.hp.com/research/linux/libunwind/}.
|
||||
\LatexManEnd
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,107 @@
|
|||
'\" t
|
||||
.\" Manual page created with latex2man on Sat Feb 8 01:21:05 PST 2003
|
||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
||||
.de Vb
|
||||
.ft CW
|
||||
.nf
|
||||
..
|
||||
.de Ve
|
||||
.ft R
|
||||
|
||||
.fi
|
||||
..
|
||||
.TH "UNW\\_RESUME" "3" "08 February 2003" "Programming Library " "Programming Library "
|
||||
.SH NAME
|
||||
|
||||
.PP
|
||||
unw_resume \-\- resume execution in a particular stack frame
|
||||
.PP
|
||||
.SH SYNOPSIS
|
||||
|
||||
.PP
|
||||
#include <libunwind.h>
|
||||
.br
|
||||
.PP
|
||||
int
|
||||
unw_resume(unw_cursor_t *cursor);
|
||||
.br
|
||||
.PP
|
||||
.SH DESCRIPTION
|
||||
|
||||
.PP
|
||||
The unw_resume()
|
||||
routine resumes execution at the stack frame
|
||||
identified by cursor\&.
|
||||
Normally, this is accomplished by
|
||||
restoring the ``preserved\&'' (callee\-saved) machine state. However, if
|
||||
execution in any of the stack frames younger (more deeply nested) than
|
||||
the one identified by cursor
|
||||
was interrupted by a signal, then
|
||||
unw_resume()
|
||||
will restore the entire machine state, including
|
||||
the ``preserved\&'' and ``scratch\&'' (caller\-saved) registers, as well as
|
||||
the signal mask.
|
||||
.PP
|
||||
Most platforms reserve some registers to pass arguments to exception
|
||||
handlers (e.g., IA\-64 uses r15\-r18
|
||||
for this
|
||||
purpose). These registers are normally treated like ``scratch\&''
|
||||
registers. However, if libunwind
|
||||
is used to define an
|
||||
exception argument register, e.g., by calling unw_set_reg(),
|
||||
then unw_resume()
|
||||
will always install the new value as the
|
||||
contents of that register. In other words, the exception handling
|
||||
arguments are installed even in cases where normally only the
|
||||
``preserved\&'' registers are restored.
|
||||
.PP
|
||||
.SH RETURN VALUE
|
||||
|
||||
.PP
|
||||
For local unwinding, unw_resume()
|
||||
does not return on success.
|
||||
For remote unwinding, it returns 0 on success. On failure, the
|
||||
negative value of one of the errors below is returned.
|
||||
.PP
|
||||
.SH ERRORS
|
||||
|
||||
.PP
|
||||
.TP
|
||||
UNW_EUNSPEC
|
||||
An unspecified error occurred.
|
||||
.TP
|
||||
UNW_EBADREG
|
||||
A register needed by unw_resume()
|
||||
wasn\&'t
|
||||
accessible.
|
||||
.TP
|
||||
UNW_EINVALIDIP
|
||||
The instruction pointer identified by
|
||||
cursor
|
||||
is not valid.
|
||||
.TP
|
||||
UNW_BADFRAME
|
||||
The stack frame identified by
|
||||
cursor
|
||||
is not valid.
|
||||
.PP
|
||||
.SH SEE ALSO
|
||||
|
||||
.PP
|
||||
libunwind(3),
|
||||
unw_set_reg(3),
|
||||
sigprocmask(2)
|
||||
.PP
|
||||
.SH AUTHOR
|
||||
|
||||
.PP
|
||||
David Mosberger\-Tang
|
||||
.br
|
||||
Hewlett\-Packard Labs
|
||||
.br
|
||||
Palo\-Alto, CA 94304
|
||||
.br
|
||||
Email: \fBdavidm@hpl.hp.com\fP
|
||||
.br
|
||||
WWW: \fBhttp://www.hpl.hp.com/research/linux/libunwind/\fP\&.
|
||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
|
@ -0,0 +1,74 @@
|
|||
\documentclass{article}
|
||||
\usepackage[fancyhdr,pdf]{latex2man}
|
||||
|
||||
\input{common.tex}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{Name}{3}{unw\_resume}{David Mosberger-Tang}{Programming Library}{unw\_resume}
|
||||
|
||||
unw\_resume -- resume execution in a particular stack frame
|
||||
\end{Name}
|
||||
|
||||
\section{Synopsis}
|
||||
|
||||
\File{\#include $<$libunwind.h$>$}\\
|
||||
|
||||
\Type{int} \Func{unw\_resume}(\Type{unw\_cursor\_t~*}\Var{cursor});\\
|
||||
|
||||
\section{Description}
|
||||
|
||||
The \Func{unw\_resume}() routine resumes execution at the stack frame
|
||||
identified by \Var{cursor}. Normally, this is accomplished by
|
||||
restoring the ``preserved'' (callee-saved) machine state. However, if
|
||||
execution in any of the stack frames younger (more deeply nested) than
|
||||
the one identified by \Var{cursor} was interrupted by a signal, then
|
||||
\Func{unw\_resume}() will restore the entire machine state, including
|
||||
the ``preserved'' and ``scratch'' (caller-saved) registers, as well as
|
||||
the signal mask.
|
||||
|
||||
Most platforms reserve some registers to pass arguments to exception
|
||||
handlers (e.g., IA-64 uses \texttt{r15}-\texttt{r18} for this
|
||||
purpose). These registers are normally treated like ``scratch''
|
||||
registers. However, if \Prog{libunwind} is used to define an
|
||||
exception argument register, e.g., by calling \Func{unw\_set\_reg}(),
|
||||
then \Func{unw\_resume}() will always install the new value as the
|
||||
contents of that register. In other words, the exception handling
|
||||
arguments are installed even in cases where normally only the
|
||||
``preserved'' registers are restored.
|
||||
|
||||
\section{Return Value}
|
||||
|
||||
For local unwinding, \Func{unw\_resume}() does not return on success.
|
||||
For remote unwinding, it returns 0 on success. On failure, the
|
||||
negative value of one of the errors below is returned.
|
||||
|
||||
\section{Errors}
|
||||
|
||||
\begin{Description}
|
||||
\item[\Const{UNW\_EUNSPEC}] An unspecified error occurred.
|
||||
\item[\Const{UNW\_EBADREG}] A register needed by \Func{unw\_resume}() wasn't
|
||||
accessible.
|
||||
\item[\Const{UNW\_EINVALIDIP}] The instruction pointer identified by
|
||||
\Var{cursor} is not valid.
|
||||
\item[\Const{UNW\_BADFRAME}] The stack frame identified by
|
||||
\Var{cursor} is not valid.
|
||||
\end{Description}
|
||||
|
||||
\section{See Also}
|
||||
|
||||
\SeeAlso{libunwind(3)},
|
||||
\SeeAlso{unw\_set\_reg(3)},
|
||||
sigprocmask(2)
|
||||
|
||||
\section{Author}
|
||||
|
||||
\noindent
|
||||
David Mosberger-Tang\\
|
||||
Hewlett-Packard Labs\\
|
||||
Palo-Alto, CA 94304\\
|
||||
Email: \Email{davidm@hpl.hp.com}\\
|
||||
WWW: \URL{http://www.hpl.hp.com/research/linux/libunwind/}.
|
||||
\LatexManEnd
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,2 @@
|
|||
#include "elf32.h"
|
||||
#include "elfxx.c"
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef elf32_h
|
||||
#define elf32_h
|
||||
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#include "elfxx.h"
|
||||
|
||||
#endif /* elf32_h */
|
|
@ -0,0 +1,2 @@
|
|||
#include "elf64.h"
|
||||
#include "elfxx.c"
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef elf64_h
|
||||
#define elf64_h
|
||||
|
||||
#define ELF_CLASS ELFCLASS64
|
||||
#include "elfxx.h"
|
||||
|
||||
#endif /* elf64_h */
|
168
src/elfxx.c
168
src/elfxx.c
|
@ -0,0 +1,168 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
extern HIDDEN int
|
||||
elfW (valid_object) (struct elf_image *ei)
|
||||
{
|
||||
if (ei->size <= EI_CLASS)
|
||||
return 0;
|
||||
|
||||
return (memcmp (ei->image, ELFMAG, SELFMAG) == 0
|
||||
&& ((uint8_t *) ei->image)[EI_CLASS] == ELF_CLASS);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
elfW (lookup_symbol) (unw_word_t ip, struct elf_image *ei,
|
||||
ElfW (Addr) load_offset,
|
||||
char *buf, size_t buf_len, unw_word_t *offp)
|
||||
{
|
||||
size_t syment_size, str_size;
|
||||
ElfW (Ehdr) *ehdr = ei->image;
|
||||
ElfW (Sym) *sym, *symtab, *symtab_end;
|
||||
ElfW (Off) soff, str_soff;
|
||||
ElfW (Shdr) *shdr, *str_shdr;
|
||||
ElfW (Addr) val, min_dist = ~(ElfW (Addr))0;
|
||||
char *strtab;
|
||||
int i;
|
||||
|
||||
if (!elfW (valid_object) (ei))
|
||||
return -1;
|
||||
|
||||
soff = ehdr->e_shoff;
|
||||
if (soff + ehdr->e_shnum * ehdr->e_shentsize > ei->size)
|
||||
{
|
||||
debug (1, "%s: section table outside of image? (%lu > %lu)\n",
|
||||
__FUNCTION__, soff + ehdr->e_shnum * ehdr->e_shentsize,
|
||||
ei->size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
shdr = (ElfW (Shdr) *) ((char *) ei->image + soff);
|
||||
|
||||
for (i = 0; i < ehdr->e_shnum; ++i)
|
||||
{
|
||||
switch (shdr->sh_type)
|
||||
{
|
||||
case SHT_SYMTAB:
|
||||
case SHT_DYNSYM:
|
||||
symtab = (ElfW (Sym) *) ((char *) ei->image + shdr->sh_offset);
|
||||
symtab_end = (ElfW (Sym) *) ((char *) symtab + shdr->sh_size);
|
||||
syment_size = shdr->sh_entsize;
|
||||
|
||||
str_soff = soff + (shdr->sh_link * ehdr->e_shentsize);
|
||||
if (str_soff + ehdr->e_shentsize >= ei->size)
|
||||
{
|
||||
debug (1, "%s: string table outside of image? (%lu >= %lu)\n",
|
||||
__FUNCTION__, str_soff + ehdr->e_shentsize, ei->size);
|
||||
break;
|
||||
}
|
||||
str_shdr = (ElfW (Shdr) *) ((char *) ei->image + str_soff);
|
||||
str_size = str_shdr->sh_size;
|
||||
strtab = (char *) ei->image + str_shdr->sh_offset;
|
||||
|
||||
debug (10, "symtab=0x%lx[%d], strtab=0x%lx\n", shdr->sh_offset,
|
||||
shdr->sh_type, str_shdr->sh_offset);
|
||||
|
||||
for (sym = symtab;
|
||||
sym < symtab_end;
|
||||
sym = (ElfW (Sym) *) ((char *) sym + syment_size))
|
||||
{
|
||||
if (ELFW (ST_TYPE) (sym->st_info) == STT_FUNC
|
||||
&& sym->st_shndx != SHN_UNDEF)
|
||||
{
|
||||
val = sym->st_value;
|
||||
if (sym->st_shndx != SHN_ABS)
|
||||
val += load_offset;
|
||||
debug (100, "0x%016lx info=0x%02x %s\n",
|
||||
val, sym->st_info, strtab + sym->st_name);
|
||||
|
||||
if ((ElfW (Addr)) (ip - val) < min_dist)
|
||||
{
|
||||
min_dist = (ElfW (Addr)) (ip - val);
|
||||
buf[buf_len - 1] = 'x';
|
||||
strncpy (buf, strtab + sym->st_name, buf_len);
|
||||
buf[buf_len - 1] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
shdr = (Elf64_Shdr *) (((char *) shdr) + ehdr->e_shentsize);
|
||||
}
|
||||
if (min_dist >= ei->size)
|
||||
return -1; /* not found */
|
||||
if (offp)
|
||||
*offp = min_dist;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the ELF image that contains IP and return the "closest"
|
||||
procedure name, if there is one. With some caching, this could be
|
||||
sped up greatly, but until an application materializes that's
|
||||
sensitive to the performance of this routine, why bother... */
|
||||
|
||||
HIDDEN int
|
||||
elfW (get_proc_name) (unw_word_t ip, char *buf, size_t buf_len,
|
||||
unw_word_t *offp)
|
||||
{
|
||||
unsigned long segbase, mapoff;
|
||||
ElfW (Addr) load_offset = 0;
|
||||
struct elf_image ei;
|
||||
ElfW (Ehdr) *ehdr;
|
||||
ElfW (Phdr) *phdr;
|
||||
int i, ret;
|
||||
|
||||
ret = tdep_get_elf_image (&ei, getpid (), ip, &segbase, &mapoff);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ehdr = ei.image;
|
||||
phdr = (Elf64_Phdr *) ((char *) ei.image + ehdr->e_phoff);
|
||||
|
||||
for (i = 0; i < ehdr->e_phnum; ++i)
|
||||
if (phdr[i].p_type == PT_LOAD && phdr[i].p_offset == mapoff)
|
||||
{
|
||||
load_offset = segbase - phdr[i].p_vaddr;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = elfW (lookup_symbol) (ip, &ei, load_offset, buf, buf_len, offp);
|
||||
|
||||
munmap (ei.image, ei.size);
|
||||
ei.image = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
71
src/elfxx.h
71
src/elfxx.h
|
@ -0,0 +1,71 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include <elf.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#if ELF_CLASS == ELFCLASS32
|
||||
# define ELFW(x) ELF32_##x
|
||||
# define ElfW(x) Elf32_##x
|
||||
# define elfW(x) _Uelf32_##x
|
||||
#else
|
||||
# define ELFW(x) ELF64_##x
|
||||
# define ElfW(x) Elf64_##x
|
||||
# define elfW(x) _Uelf64_##x
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
elf_map_image (struct elf_image *ei, char *path)
|
||||
{
|
||||
struct stat stat;
|
||||
int fd;
|
||||
|
||||
fd = open (path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (fstat (fd, &stat) < 0)
|
||||
{
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ei->size = stat.st_size;
|
||||
ei->image = mmap (NULL, ei->size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
close (fd);
|
||||
if (ei->image == MAP_FAILED)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern HIDDEN int elfW (valid_object) (struct elf_image *ei);
|
||||
extern HIDDEN int elfW (get_proc_name) (unw_word_t ip, char *buf, size_t len,
|
||||
unw_word_t *offp);
|
|
@ -0,0 +1,104 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
/* Utility to generate cursor_i.h. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#ifdef offsetof
|
||||
# undef offsetof
|
||||
#endif
|
||||
|
||||
#define offsetof(type,field) ((char *) &((type *) 0)->field - (char *) 0)
|
||||
|
||||
struct
|
||||
{
|
||||
const char name[256];
|
||||
unsigned long value;
|
||||
}
|
||||
tab[] =
|
||||
{
|
||||
{ "IP_OFF", offsetof (struct cursor, ip) },
|
||||
{ "PR_OFF", offsetof (struct cursor, pr) },
|
||||
{ "BSP_OFF", offsetof (struct cursor, bsp) },
|
||||
{ "PSP_OFF", offsetof (struct cursor, psp) },
|
||||
{ "PFS_LOC_OFF", offsetof (struct cursor, pfs_loc) },
|
||||
{ "RNAT_LOC_OFF", offsetof (struct cursor, rnat_loc) },
|
||||
{ "UNAT_LOC_OFF", offsetof (struct cursor, unat_loc) },
|
||||
{ "LC_LOC_OFF", offsetof (struct cursor, lc_loc) },
|
||||
{ "FPSR_LOC_OFF", offsetof (struct cursor, fpsr_loc) },
|
||||
{ "B1_LOC_OFF", offsetof (struct cursor, b1_loc) },
|
||||
{ "B2_LOC_OFF", offsetof (struct cursor, b2_loc) },
|
||||
{ "B3_LOC_OFF", offsetof (struct cursor, b3_loc) },
|
||||
{ "B4_LOC_OFF", offsetof (struct cursor, b4_loc) },
|
||||
{ "B5_LOC_OFF", offsetof (struct cursor, b5_loc) },
|
||||
{ "F2_LOC_OFF", offsetof (struct cursor, f2_loc) },
|
||||
{ "F3_LOC_OFF", offsetof (struct cursor, f3_loc) },
|
||||
{ "F4_LOC_OFF", offsetof (struct cursor, f4_loc) },
|
||||
{ "F5_LOC_OFF", offsetof (struct cursor, f5_loc) },
|
||||
{ "FR_LOC_OFF", offsetof (struct cursor, fr_loc) },
|
||||
{ "SIGCONTEXT_LOC_OFF", offsetof (struct cursor, sigcontext_loc) },
|
||||
};
|
||||
|
||||
static const char *tabs = "\t\t\t\t\t\t\t\t\t\t";
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
const char *space;
|
||||
int i, num_tabs;
|
||||
size_t len;
|
||||
|
||||
printf ("#ifndef cursor_i_h\n");
|
||||
printf ("#define cursor_i_h\n\n");
|
||||
|
||||
printf ("/*\n * DO NOT MODIFY\n *\n * This file was generated by "
|
||||
"print_offsets.\n *\n */\n\n");
|
||||
|
||||
for (i = 0; i < (int) (sizeof (tab) / sizeof (tab[0])); ++i)
|
||||
{
|
||||
if (tab[i].name[0] == '\0')
|
||||
printf ("\n");
|
||||
else
|
||||
{
|
||||
len = strlen (tab[i].name);
|
||||
|
||||
num_tabs = (40 - len) / 8;
|
||||
if (num_tabs <= 0)
|
||||
space = " ";
|
||||
else
|
||||
space = strchr(tabs, '\0') - (40 - len) / 8;
|
||||
|
||||
printf ("#define %s%s%lu\t/* 0x%lx */\n",
|
||||
tab[i].name, space, tab[i].value, tab[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
printf ("\n#endif /* cursor_i_h */\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
.align 32
|
||||
|
||||
.global _setjmp
|
||||
|
||||
.proc _setjmp
|
||||
|
||||
_setjmp:
|
||||
mov r2 = ar.bsp
|
||||
st8 [r32] = r12 // jmp_buf[0] = sp
|
||||
mov r3 = rp
|
||||
|
||||
adds r16 = 8, r32
|
||||
adds r17 = 16, r32
|
||||
mov r8 = 0
|
||||
;;
|
||||
st8 [r16] = r3 // jmp_buf[1] = rp
|
||||
st8 [r17] = r2 // jmp_buf[2] = bsp
|
||||
br.ret.sptk.many rp
|
||||
|
||||
.endp _setjmp
|
|
@ -0,0 +1,64 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#define SIG_SETMASK 2
|
||||
|
||||
.globl _UI_siglongjmp_cont
|
||||
|
||||
.align 32
|
||||
.proc siglongjmp_continuation
|
||||
siglongjmp_continuation:
|
||||
_UI_siglongjmp_cont: // non-function label for {sig,}longjmp.c
|
||||
.prologue
|
||||
.save rp, r15
|
||||
.body
|
||||
nop 0
|
||||
nop 0
|
||||
br.call.sptk.many b6 = 1f
|
||||
;;
|
||||
.prologue
|
||||
.save ar.pfs, r33
|
||||
1: alloc loc1 = ar.pfs, 0, 3, 3, 0
|
||||
/*
|
||||
* Note: we can use the scratch stack are because the caller
|
||||
* of sigsetjmp() by definition is not a leaf-procedure.
|
||||
*/
|
||||
st8 [sp] = r17 // store signal mask
|
||||
.save rp, loc0
|
||||
mov loc0 = r15 // final continuation point
|
||||
;;
|
||||
.body
|
||||
mov loc2 = r16 // value to return in r8
|
||||
|
||||
mov out0 = SIG_SETMASK
|
||||
mov out1 = sp
|
||||
mov out2 = r0
|
||||
br.call.sptk.many rp = sigprocmask
|
||||
;;
|
||||
mov rp = loc0
|
||||
mov ar.pfs = loc1
|
||||
mov r8 = loc2
|
||||
br.ret.sptk.many rp
|
||||
.endp siglongjmp_continuation
|
|
@ -0,0 +1,64 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#define SIG_BLOCK 0
|
||||
|
||||
.align 32
|
||||
|
||||
.global __sigsetjmp
|
||||
|
||||
.proc __sigsetjmp
|
||||
|
||||
__sigsetjmp:
|
||||
.prologue
|
||||
.save ar.pfs, r35
|
||||
alloc loc1 = ar.pfs, 2, 3, 3, 0
|
||||
add r16 = 16, in0
|
||||
add out2 = 24, in0
|
||||
|
||||
st8 [in0] = sp, 8 // sigjmp_buf[0] = sp
|
||||
mov out0 = SIG_BLOCK
|
||||
.save rp, loc0
|
||||
mov loc0 = rp
|
||||
.body
|
||||
;;
|
||||
st8 [in0] = loc0, 24 // sigjmp_buf[1] = rp
|
||||
st8 [r16] = in1 // sigjmp_buf[2] = savemask
|
||||
cmp.ne p6, p0 = in1, r0
|
||||
|
||||
mov out1 = r0
|
||||
mov loc2 = ar.bsp
|
||||
(p6) br.call.sptk.many rp = sigprocmask // sigjmp_buf[3] = sigmask
|
||||
;;
|
||||
|
||||
st8 [in0] = loc2 // sigjmp_buf[4] = bsp
|
||||
mov rp = loc0
|
||||
nop 0
|
||||
|
||||
mov r8 = 0
|
||||
mov.i ar.pfs = loc1
|
||||
br.ret.sptk.many rp
|
||||
|
||||
.endp __sigsetjmp
|
109
src/longjmp.c
109
src/longjmp.c
|
@ -0,0 +1,109 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#define UNW_LOCAL_ONLY
|
||||
|
||||
#include <libunwind.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if UNW_TARGET_IA64
|
||||
# include "ia64/rse.h"
|
||||
#endif
|
||||
|
||||
void
|
||||
_longjmp (jmp_buf env, int val)
|
||||
{
|
||||
extern int _UI_siglongjmp_cont;
|
||||
sigset_t current_mask;
|
||||
unw_context_t uc;
|
||||
unw_cursor_t c;
|
||||
unw_word_t sp;
|
||||
unw_word_t *wp = (unw_word_t *) env;
|
||||
|
||||
if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0)
|
||||
abort ();
|
||||
|
||||
do
|
||||
{
|
||||
if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0)
|
||||
abort ();
|
||||
if (sp != wp[0])
|
||||
continue;
|
||||
|
||||
#if UNW_TARGET_IA64
|
||||
{
|
||||
unw_word_t bsp, pfs, sol;
|
||||
|
||||
if (unw_get_reg (&c, UNW_IA64_BSP, &bsp) < 0
|
||||
|| unw_get_reg (&c, UNW_IA64_AR_PFS, &pfs) < 0)
|
||||
abort ();
|
||||
|
||||
/* simulate the effect of "br.call setjmp" on ar.bsp: */
|
||||
sol = (pfs >> 7) & 0x7f;
|
||||
bsp = ia64_rse_skip_regs (bsp, sol);
|
||||
|
||||
if (bsp != wp[2])
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* found the right frame: */
|
||||
|
||||
if (sigprocmask (SIG_BLOCK, NULL, ¤t_mask) < 0)
|
||||
abort ();
|
||||
|
||||
if (unw_set_reg (&c, UNW_REG_EH_ARG0, wp[1]) < 0
|
||||
|| unw_set_reg (&c, UNW_REG_EH_ARG1, val) < 0
|
||||
|| unw_set_reg (&c, UNW_REG_EH_ARG2,
|
||||
((unw_word_t *) ¤t_mask)[0]) < 0
|
||||
|| unw_set_reg (&c, UNW_REG_IP,
|
||||
(unw_word_t) &_UI_siglongjmp_cont))
|
||||
abort ();
|
||||
|
||||
if (_NSIG > 8 * sizeof (unw_word_t))
|
||||
{
|
||||
if (_NSIG > 16 * sizeof (unw_word_t))
|
||||
abort ();
|
||||
if (unw_set_reg (&c, UNW_REG_EH_ARG3,
|
||||
((unw_word_t *) ¤t_mask)[1]) < 0)
|
||||
abort ();
|
||||
}
|
||||
|
||||
unw_resume (&c);
|
||||
|
||||
abort ();
|
||||
}
|
||||
while (unw_step (&c) >= 0);
|
||||
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
longjmp (jmp_buf env, int val)
|
||||
{
|
||||
_longjmp (env, val);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "os-linux.h"
|
||||
|
||||
/* Here, it doesn't matter whether we include elf64.h or elf32.h.
|
||||
Both define "struct elf_image" and elf_map_image() in an identical
|
||||
fashion. */
|
||||
#include "elf64.h"
|
||||
|
||||
HIDDEN int
|
||||
tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip,
|
||||
unsigned long *segbase, unsigned long *mapoff)
|
||||
{
|
||||
struct map_iterator mi;
|
||||
char path[PATH_MAX];
|
||||
int found = 0;
|
||||
unsigned long hi;
|
||||
|
||||
maps_init (&mi, pid);
|
||||
while (maps_next (&mi, segbase, &hi, mapoff, path))
|
||||
if (ip >= *segbase && ip < hi)
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
maps_close (&mi);
|
||||
|
||||
if (!found)
|
||||
return -1;
|
||||
|
||||
return elf_map_image (ei, path);
|
||||
}
|
||||
|
||||
#endif /* UNW_REMOTE_ONLY */
|
|
@ -0,0 +1,69 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#ifndef os_linux_h
|
||||
#define os_linux_h
|
||||
|
||||
struct map_iterator
|
||||
{
|
||||
FILE *fp;
|
||||
};
|
||||
|
||||
static inline void
|
||||
maps_init (struct map_iterator *mi, pid_t pid)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
snprintf (path, sizeof (path), "/proc/%d/maps", pid);
|
||||
mi->fp = fopen (path, "r");
|
||||
}
|
||||
|
||||
static inline int
|
||||
maps_next (struct map_iterator *mi,
|
||||
unsigned long *low, unsigned long *high, unsigned long *offset,
|
||||
char *path)
|
||||
{
|
||||
char line[256+PATH_MAX];
|
||||
|
||||
if (!mi->fp)
|
||||
return 0;
|
||||
|
||||
while (fgets (line, sizeof (line), mi->fp))
|
||||
{
|
||||
if (sscanf (line, "%lx-%lx %*4c %lx %*x:%*x %*d %s\n",
|
||||
low, high, offset, path) == 4)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
maps_close (struct map_iterator *mi)
|
||||
{
|
||||
fclose (mi->fp);
|
||||
mi->fp = NULL;
|
||||
}
|
||||
|
||||
#endif /* os_linux_h */
|
52
src/setjmp.c
52
src/setjmp.c
|
@ -0,0 +1,52 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include <libunwind.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
/* Why use K&R syntax here? setjmp() is often a macro and that
|
||||
expands into a call to, say, __setjmp() and we need to define the
|
||||
libunwind-version of setjmp() with the name of the actual function.
|
||||
Using K&R syntax lets us keep the setjmp() macro while keeping the
|
||||
syntax valid... This trick works provided setjmp() doesn't do
|
||||
anything other than a function call. */
|
||||
|
||||
int
|
||||
setjmp (env)
|
||||
jmp_buf env;
|
||||
{
|
||||
void **wp = (void **) env;
|
||||
|
||||
#if UNW_TARGET_IA64
|
||||
wp[0] = __builtin_dwarf_cfa () - 16;
|
||||
wp[1] = __builtin_ia64_bsp ();
|
||||
#else
|
||||
/* this should work on most platforms, but may not be
|
||||
performance-optimal; check the code! */
|
||||
wp[0] = __builtin_frame_address (0);
|
||||
wp[1] = (void *) (uintptr_t) 0;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
108
src/siglongjmp.c
108
src/siglongjmp.c
|
@ -0,0 +1,108 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#define UNW_LOCAL_ONLY
|
||||
|
||||
#include <libunwind.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if UNW_TARGET_IA64
|
||||
# include "ia64/rse.h"
|
||||
#endif
|
||||
|
||||
void
|
||||
siglongjmp (sigjmp_buf env, int val)
|
||||
{
|
||||
unw_word_t *mp, *wp = (unw_word_t *) env;
|
||||
extern int _UI_siglongjmp_cont;
|
||||
sigset_t current_mask;
|
||||
unw_context_t uc;
|
||||
unw_cursor_t c;
|
||||
unw_word_t sp;
|
||||
|
||||
if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0)
|
||||
abort ();
|
||||
|
||||
do
|
||||
{
|
||||
if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0)
|
||||
abort ();
|
||||
if (sp != wp[0])
|
||||
continue;
|
||||
|
||||
#if UNW_TARGET_IA64
|
||||
{
|
||||
unw_word_t bsp, pfs, sol;
|
||||
|
||||
if (unw_get_reg (&c, UNW_IA64_BSP, &bsp) < 0
|
||||
|| unw_get_reg (&c, UNW_IA64_AR_PFS, &pfs) < 0)
|
||||
abort ();
|
||||
|
||||
/* simulate the effect of "br.call sigsetjmp" on ar.bsp: */
|
||||
sol = (pfs >> 7) & 0x7f;
|
||||
bsp = ia64_rse_skip_regs (bsp, sol);
|
||||
|
||||
if (bsp != wp[4])
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* found the right frame: */
|
||||
|
||||
if (wp[2])
|
||||
mp = wp + 3;
|
||||
else
|
||||
{
|
||||
/* sigmask wasn't saved; get it now so we can leave it unchanged. */
|
||||
if (sigprocmask (SIG_BLOCK, NULL, ¤t_mask) < 0)
|
||||
abort ();
|
||||
mp = (unw_word_t *) ¤t_mask;
|
||||
}
|
||||
|
||||
if (unw_set_reg (&c, UNW_REG_EH_ARG0, wp[1]) < 0
|
||||
|| unw_set_reg (&c, UNW_REG_EH_ARG1, val) < 0
|
||||
|| unw_set_reg (&c, UNW_REG_EH_ARG2, mp[0]) < 0
|
||||
|| unw_set_reg (&c, UNW_REG_IP,
|
||||
(unw_word_t) &_UI_siglongjmp_cont))
|
||||
abort ();
|
||||
|
||||
if (_NSIG > 8 * sizeof (unw_word_t))
|
||||
{
|
||||
if (_NSIG > 16 * sizeof (unw_word_t))
|
||||
abort ();
|
||||
if (unw_set_reg (&c, UNW_REG_EH_ARG3, mp[1]) < 0)
|
||||
abort ();
|
||||
}
|
||||
|
||||
unw_resume (&c);
|
||||
|
||||
abort ();
|
||||
}
|
||||
while (unw_step (&c) >= 0);
|
||||
|
||||
abort ();
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include <libunwind.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
sigsetjmp (sigjmp_buf env, int savemask)
|
||||
{
|
||||
unw_word_t *wp = (unw_word_t *) env;
|
||||
|
||||
/* This should work on most platforms, but may not be
|
||||
performance-optimal; check the code! */
|
||||
|
||||
wp[0] = (unw_word_t) __builtin_frame_address (0);
|
||||
wp[1] = (unw_word_t) __builtin_return_address (0);
|
||||
wp[2] = savemask;
|
||||
|
||||
/* Note: we assume here that "wp" has same or better alignment as
|
||||
sigset_t. */
|
||||
if (savemask && sigprocmask (SIG_BLOCK, NULL, (sigset_t *) (wp + 3)) < 0)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,278 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
/* The setjmp()/longjmp(), sigsetjmp()/siglongjmp(). */
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int nerrors;
|
||||
int verbose;
|
||||
|
||||
static jmp_buf jbuf;
|
||||
static sigjmp_buf sigjbuf;
|
||||
static sigset_t sigset4;
|
||||
|
||||
void
|
||||
raise_longjmp (jmp_buf jbuf, int i, int n)
|
||||
{
|
||||
while (i < n)
|
||||
raise_longjmp (jbuf, i + 1, n);
|
||||
|
||||
longjmp (jbuf, n);
|
||||
}
|
||||
|
||||
void
|
||||
test_setjmp (void)
|
||||
{
|
||||
volatile int i;
|
||||
jmp_buf jbuf;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < 10; ++i)
|
||||
{
|
||||
if ((ret = setjmp (jbuf)))
|
||||
{
|
||||
if (verbose)
|
||||
printf ("%s: secondary setjmp () return, ret=%d\n",
|
||||
__FUNCTION__, ret);
|
||||
if (ret != i + 1)
|
||||
{
|
||||
fprintf (stderr, "%s: setjmp() returned %d, expected %d\n",
|
||||
__FUNCTION__, ret, i + 1);
|
||||
++nerrors;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (verbose)
|
||||
printf ("%s.%d: done with setjmp(); calling children\n",
|
||||
__FUNCTION__, i + 1);
|
||||
|
||||
raise_longjmp (jbuf, 0, i + 1);
|
||||
|
||||
fprintf (stderr, "%s: raise_longjmp() returned unexpected\n",
|
||||
__FUNCTION__);
|
||||
++nerrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
raise_siglongjmp (sigjmp_buf jbuf, int i, int n)
|
||||
{
|
||||
while (i < n)
|
||||
raise_siglongjmp (jbuf, i + 1, n);
|
||||
|
||||
siglongjmp (jbuf, n);
|
||||
}
|
||||
|
||||
void
|
||||
test_sigsetjmp (void)
|
||||
{
|
||||
sigjmp_buf jbuf;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < 10; ++i)
|
||||
{
|
||||
if ((ret = sigsetjmp (jbuf, 1)))
|
||||
{
|
||||
if (verbose)
|
||||
printf ("%s: secondary sigsetjmp () return, ret=%d\n",
|
||||
__FUNCTION__, ret);
|
||||
if (ret != i + 1)
|
||||
{
|
||||
fprintf (stderr, "%s: sigsetjmp() returned %d, expected %d\n",
|
||||
__FUNCTION__, ret, i + 1);
|
||||
++nerrors;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (verbose)
|
||||
printf ("%s.%d: done with sigsetjmp(); calling children\n",
|
||||
__FUNCTION__, i + 1);
|
||||
|
||||
raise_siglongjmp (jbuf, 0, i + 1);
|
||||
|
||||
fprintf (stderr, "%s: raise_siglongjmp() returned unexpected\n",
|
||||
__FUNCTION__);
|
||||
++nerrors;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sighandler (int signal)
|
||||
{
|
||||
if (verbose)
|
||||
printf ("%s: got signal %d\n", __FUNCTION__, signal);
|
||||
|
||||
sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset4);
|
||||
siglongjmp (sigjbuf, 1);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
volatile sigset_t sigset1, sigset2, sigset3;
|
||||
volatile struct sigaction act;
|
||||
|
||||
if (argc > 1)
|
||||
verbose = 1;
|
||||
|
||||
sigemptyset ((sigset_t *) &sigset1);
|
||||
sigaddset ((sigset_t *) &sigset1, SIGUSR1);
|
||||
sigemptyset ((sigset_t *) &sigset2);
|
||||
sigaddset ((sigset_t *) &sigset2, SIGUSR2);
|
||||
|
||||
memset ((void *) &act, 0, sizeof (act));
|
||||
act.sa_handler = sighandler;
|
||||
sigaction (SIGTERM, (struct sigaction *) &act, NULL);
|
||||
|
||||
test_setjmp ();
|
||||
test_sigsetjmp ();
|
||||
|
||||
/* _setjmp() MUST NOT change signal mask: */
|
||||
sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
|
||||
if (_setjmp (jbuf))
|
||||
{
|
||||
sigemptyset ((sigset_t *) &sigset3);
|
||||
sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
|
||||
if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset2,
|
||||
sizeof (sigset_t)) != 0)
|
||||
{
|
||||
fprintf (stderr, "FAILURE: _longjmp() manipulated signal mask!\n");
|
||||
++nerrors;
|
||||
}
|
||||
else if (verbose)
|
||||
printf ("OK: _longjmp() seems not to change signal mask\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
|
||||
_longjmp (jbuf, 1);
|
||||
}
|
||||
|
||||
/* sigsetjmp(jbuf, 1) MUST preserve signal mask: */
|
||||
sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
|
||||
if (sigsetjmp (sigjbuf, 1))
|
||||
{
|
||||
sigemptyset ((sigset_t *) &sigset3);
|
||||
sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
|
||||
if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset1,
|
||||
sizeof (sigset_t)) != 0)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"FAILURE: siglongjmp() didn't restore signal mask!\n");
|
||||
++nerrors;
|
||||
}
|
||||
else if (verbose)
|
||||
printf ("OK: siglongjmp() restores signal mask when asked to\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
|
||||
siglongjmp (sigjbuf, 1);
|
||||
}
|
||||
|
||||
/* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */
|
||||
sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
|
||||
if (sigsetjmp (sigjbuf, 0))
|
||||
{
|
||||
sigemptyset ((sigset_t *) &sigset3);
|
||||
sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
|
||||
if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset2,
|
||||
sizeof (sigset_t)) != 0)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"FAILURE: siglongjmp() changed signal mask!\n");
|
||||
++nerrors;
|
||||
}
|
||||
else if (verbose)
|
||||
printf ("OK: siglongjmp() leaves signal mask along when asked to\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
|
||||
siglongjmp (sigjbuf, 1);
|
||||
}
|
||||
|
||||
/* sigsetjmp(jbuf, 1) MUST preserve signal mask: */
|
||||
sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
|
||||
if (sigsetjmp (sigjbuf, 1))
|
||||
{
|
||||
sigemptyset ((sigset_t *) &sigset3);
|
||||
sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
|
||||
if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset1,
|
||||
sizeof (sigset_t)) != 0)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"FAILURE: siglongjmp() didn't restore signal mask!\n");
|
||||
++nerrors;
|
||||
}
|
||||
else if (verbose)
|
||||
printf ("OK: siglongjmp() restores signal mask when asked to\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
|
||||
kill (getpid (), SIGTERM);
|
||||
fprintf (stderr, "FAILURE: unexpected return from kill()\n");
|
||||
++nerrors;
|
||||
}
|
||||
|
||||
/* sigsetjmp(jbuf, 0) MUST NOT preserve signal mask: */
|
||||
sigprocmask (SIG_SETMASK, (sigset_t *) &sigset1, NULL);
|
||||
if (sigsetjmp (sigjbuf, 0))
|
||||
{
|
||||
sigemptyset ((sigset_t *) &sigset3);
|
||||
sigprocmask (SIG_BLOCK, NULL, (sigset_t *) &sigset3);
|
||||
if (memcmp ((sigset_t *) &sigset3, (sigset_t *) &sigset4,
|
||||
sizeof (sigset_t)) != 0)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"FAILURE: siglongjmp() changed signal mask!\n");
|
||||
++nerrors;
|
||||
}
|
||||
else if (verbose)
|
||||
printf ("OK: siglongjmp() leaves signal mask along when asked to\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sigprocmask (SIG_SETMASK, (sigset_t *) &sigset2, NULL);
|
||||
kill (getpid (), SIGTERM);
|
||||
fprintf (stderr, "FAILURE: unexpected return from kill()\n");
|
||||
++nerrors;
|
||||
}
|
||||
|
||||
if (nerrors > 0)
|
||||
{
|
||||
fprintf (stderr, "FAILURE: detected %d failures\n", nerrors);
|
||||
exit (-1);
|
||||
}
|
||||
if (verbose)
|
||||
printf ("SUCCESS\n");
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue