diff options
Diffstat (limited to 'libc/sysdeps/linux/common')
-rw-r--r-- | libc/sysdeps/linux/common/Makefile.in | 10 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/bits/kernel-features.h | 25 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/epoll.c | 53 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/getcwd.c | 3 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/longjmp.c | 4 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/pipe2.c | 16 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/stubs.c | 106 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/sys/epoll.h | 64 | ||||
-rw-r--r-- | libc/sysdeps/linux/common/unwind.h | 220 |
9 files changed, 487 insertions, 14 deletions
diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in index 8811268d0..8f936ffcc 100644 --- a/libc/sysdeps/linux/common/Makefile.in +++ b/libc/sysdeps/linux/common/Makefile.in @@ -19,14 +19,14 @@ CSRC-$(UCLIBC_LINUX_MODULE_24) += create_module.c query_module.c \ get_kernel_syms.c # we need these internally: fstatfs.c statfs.c CSRC-$(UCLIBC_LINUX_SPECIFIC) += capget.c capset.c inotify.c ioperm.c iopl.c \ - madvise.c modify_ldt.c personality.c ppoll.c prctl.c readahead.c reboot.c \ + modify_ldt.c pipe2.c personality.c ppoll.c prctl.c \ + readahead.c reboot.c \ remap_file_pages.c sched_getaffinity.c sched_setaffinity.c \ sendfile64.c sendfile.c setfsgid.c setfsuid.c setresuid.c \ splice.c vmsplice.c tee.c signalfd.c swapoff.c swapon.c \ sync_file_range.c sysctl.c sysinfo.c timerfd.c uselib.c vhangup.c -ifeq ($(UCLIBC_LINUX_SPECIFIC)$(UCLIBC_HAS_THREADS_NATIVE),yy) -CSRC-y += madvise.c -endif +# NPTL needs these internally: madvise.c +CSRC-$(findstring y,$(UCLIBC_LINUX_SPECIFIC)$(UCLIBC_HAS_THREADS_NATIVE)) += madvise.c ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) CSRC- += fork.c getpid.c raise.c open.c close.c read.c write.c CSRC- += $(if $(findstring =arm=,=$(TARGET_ARCH)=),vfork.c) @@ -52,7 +52,7 @@ CSRC-$(UCLIBC_HAS_XATTR) += xattr.c CSRC-$(UCLIBC_HAS_PROFILING) += noophooks.c #pcprofile.c CSRC-$(UCLIBC_SV4_DEPRECATED) += ustat.c CSRC- += $(if $(findstring =c6x=,=$(TARGET_ARCH)=),vfork.c) -CSRC- += $(if $(findstring =sh=,=$(TARGET_ARCH)=),longjmp.c vfork.c) +CSRC- += $(if $(findstring =sh=,=$(TARGET_ARCH)=),vfork.c) CSRC- += $(if $(findstring =sparc=,=$(TARGET_ARCH)=),vfork.c) CSRC- += $(if $(findstring =i386=,=$(TARGET_ARCH)=),vfork.c) diff --git a/libc/sysdeps/linux/common/bits/kernel-features.h b/libc/sysdeps/linux/common/bits/kernel-features.h index 68b881c09..6bf554457 100644 --- a/libc/sysdeps/linux/common/bits/kernel-features.h +++ b/libc/sysdeps/linux/common/bits/kernel-features.h @@ -309,6 +309,19 @@ # define __ASSUME_O_CLOEXEC 1 #endif +/* Support for various CLOEXEC and NONBLOCK flags was added for x86, + * x86-64, PPC, IA-64, and SPARC in 2.6.27. */ +#if __LINUX_KERNEL_VERSION >= 0x02061b \ + && (defined __i386__ || defined __x86_64__ || defined __powerpc__ \ + || defined __ia64__ || defined __sparc__ || defined __s390__) +/* # define __ASSUME_SOCK_CLOEXEC 1 */ +/* # define __ASSUME_IN_NONBLOCK 1 */ +# define __ASSUME_PIPE2 1 +/* # define __ASSUME_EVENTFD2 1 */ +/* # define __ASSUME_SIGNALFD4 1 */ +#endif + + /* These features were surely available with 2.4.12. */ #if __LINUX_KERNEL_VERSION >= 132108 && defined __mc68000__ # define __ASSUME_MMAP2_SYSCALL 1 @@ -454,6 +467,18 @@ #define __ASSUME_IEEE_RAISE_EXCEPTION 1 #endif +/* Support for the accept4 syscall was added in 2.6.28. */ +#if __LINUX_KERNEL_VERSION >= 0x02061c \ + && (defined __i386__ || defined __x86_64__ || defined __powerpc__ \ + || defined __sparc__ || defined __s390__) +# define __ASSUME_ACCEPT4 1 +#endif + +/* Support for the accept4 syscall for alpha was added after 2.6.33-rc1. */ +#if __LINUX_KERNEL_VERSION >= 0x020621 && defined __alpha__ +# define __ASSUME_ACCEPT4 1 +#endif + /* Support for the FUTEX_CLOCK_REALTIME flag was added in 2.6.29. */ #if __LINUX_KERNEL_VERSION >= 0x02061d # define __ASSUME_FUTEX_CLOCK_REALTIME 1 diff --git a/libc/sysdeps/linux/common/epoll.c b/libc/sysdeps/linux/common/epoll.c index dda92282e..ab3e73bb7 100644 --- a/libc/sysdeps/linux/common/epoll.c +++ b/libc/sysdeps/linux/common/epoll.c @@ -9,6 +9,11 @@ #include <sys/syscall.h> #include <sys/epoll.h> +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# include <sysdep-cancel.h> +#else +# define SINGLE_THREAD_P 1 +#endif /* * epoll_create() @@ -18,6 +23,13 @@ _syscall1(int, epoll_create, int, size) #endif /* + * epoll_create1() + */ +#ifdef __NR_epoll_create1 +_syscall1(int, epoll_create1, int, flags) +#endif + +/* * epoll_ctl() */ #ifdef __NR_epoll_ctl @@ -28,5 +40,44 @@ _syscall4(int,epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, even * epoll_wait() */ #ifdef __NR_epoll_wait -_syscall4(int, epoll_wait, int, epfd, struct epoll_event *, events, int, maxevents, int, timeout) +extern __typeof(epoll_wait) __libc_epoll_wait; +int __libc_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) +{ + if (SINGLE_THREAD_P) + return INLINE_SYSCALL(epoll_wait, 4, epfd, events, maxevents, timeout); +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ + else { + int oldtype = LIBC_CANCEL_ASYNC (); + int result = INLINE_SYSCALL(epoll_wait, 4, epfd, events, maxevents, timeout); + LIBC_CANCEL_RESET (oldtype); + return result; + } +# endif +} +weak_alias(__libc_epoll_wait, epoll_wait) +#endif + +/* + * epoll_pwait() + */ +#ifdef __NR_epoll_pwait +# include <signal.h> + +extern __typeof(epoll_pwait) __libc_epoll_pwait; +int __libc_epoll_pwait(int epfd, struct epoll_event *events, int maxevents, + int timeout, const sigset_t *set) +{ + int nsig = _NSIG / 8; + if (SINGLE_THREAD_P) + return INLINE_SYSCALL(epoll_pwait, 6, epfd, events, maxevents, timeout, set, nsig); +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ + else { + int oldtype = LIBC_CANCEL_ASYNC (); + int result = INLINE_SYSCALL(epoll_pwait, 6, epfd, events, maxevents, timeout, set, nsig); + LIBC_CANCEL_RESET (oldtype); + return result; + } +# endif +} +weak_alias(__libc_epoll_pwait, epoll_pwait) #endif diff --git a/libc/sysdeps/linux/common/getcwd.c b/libc/sysdeps/linux/common/getcwd.c index 75d7a1c8b..87510019e 100644 --- a/libc/sysdeps/linux/common/getcwd.c +++ b/libc/sysdeps/linux/common/getcwd.c @@ -69,7 +69,7 @@ static char *search_dir(dev_t this_dev, ino_t this_ino, char *path_buf, int path slen++; dp = opendir(path_buf); - if (dp == 0) { + if (!dp) { goto oops; } @@ -78,6 +78,7 @@ static char *search_dir(dev_t this_dev, ino_t this_ino, char *path_buf, int path if (slow_search || this_ino == d->d_ino) { # endif if (slen + strlen(d->d_name) > path_size) { + closedir(dp); goto oops; } strcpy(ptr + 1, d->d_name); diff --git a/libc/sysdeps/linux/common/longjmp.c b/libc/sysdeps/linux/common/longjmp.c index b07eced6a..f3448bc6f 100644 --- a/libc/sysdeps/linux/common/longjmp.c +++ b/libc/sysdeps/linux/common/longjmp.c @@ -24,7 +24,7 @@ extern void __longjmp (__jmp_buf __env, int __val) attribute_noreturn; libc_hidden_proto(__longjmp) -#if 0 +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ extern void _longjmp_unwind (jmp_buf env, int val); #endif @@ -34,7 +34,7 @@ extern __typeof(longjmp) __libc_longjmp attribute_noreturn; call there to return VAL, or 1 if VAL is 0. */ void __libc_longjmp (sigjmp_buf env, int val) { -#if 0 +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ /* Perform any cleanups needed by the frames being unwound. */ _longjmp_unwind (env, val); #endif diff --git a/libc/sysdeps/linux/common/pipe2.c b/libc/sysdeps/linux/common/pipe2.c new file mode 100644 index 000000000..0a3686d81 --- /dev/null +++ b/libc/sysdeps/linux/common/pipe2.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * pipe2() for uClibc + * + * Copyright (C) 2011 Bernhard Reutner-Fischer <uclibc@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> +#include <unistd.h> + +#ifdef __NR_pipe2 +_syscall2(int, pipe2, int *, filedes, int, flags) +libc_hidden_def(pipe2) +#endif diff --git a/libc/sysdeps/linux/common/stubs.c b/libc/sysdeps/linux/common/stubs.c index 655c64001..e14bbc3a0 100644 --- a/libc/sysdeps/linux/common/stubs.c +++ b/libc/sysdeps/linux/common/stubs.c @@ -31,10 +31,48 @@ static int enosys_stub(void) # undef __NR_sync_file_range #endif +#ifndef __UCLIBC_LINUX_SPECIFIC__ +# undef __NR_pipe2 +#endif + +#ifndef __UCLIBC_HAS_SOCKET__ +# undef __NR_accept +# undef __NR_accept4 +# undef __NR_bind +# undef __NR_connect +# undef __NR_getpeername +# undef __NR_getsockname +# undef __NR_getsockopt +# undef __NR_listen +# undef __NR_recv +# undef __NR_recvfrom +# undef __NR_recvmsg +# undef __NR_send +# undef __NR_sendmsg +# undef __NR_sendto +# undef __NR_setsockopt +# undef __NR_shutdown +# undef __NR_socket +# undef __NR_socketcall +# undef __NR_socketpair +#endif + +#if !defined __NR_accept && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(accept) +#endif + +#if !defined __NR_accept4 && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(accept4) +#endif + #ifndef __NR_bdflush make_stub(bdflush) #endif +#if !defined __NR_bind && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(bind) +#endif + #ifndef __NR_capget make_stub(capget) #endif @@ -43,6 +81,10 @@ make_stub(capget) make_stub(capset) #endif +#if !defined __NR_connect && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(connect) +#endif + #ifndef __NR_create_module make_stub(create_module) #endif @@ -91,10 +133,22 @@ make_stub(fsetxattr) make_stub(get_kernel_syms) #endif +#if !defined __NR_getpeername && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(getpeername) +#endif + #if !defined(__NR_getpgrp) && (defined(__NR_getpgid) && (defined(__NR_getpid) || defined(__NR_getxpid))) make_stub(getpgrp) #endif +#if !defined __NR_getsockname && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(getsockname) +#endif + +#if !defined __NR_getsockopt && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(getsockopt) +#endif + #ifndef __NR_getxattr make_stub(getxattr) #endif @@ -107,6 +161,10 @@ make_stub(init_module) make_stub(lgetxattr) #endif +#if !defined __NR_listen && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(listen) +#endif + #ifndef __NR_listxattr make_stub(listxattr) #endif @@ -123,6 +181,10 @@ make_stub(lremovexattr) make_stub(lsetxattr) #endif +#ifndef __NR_pipe2 +make_stub(pipe2) +#endif + #ifndef __NR_pivot_root make_stub(pivot_root) #endif @@ -131,6 +193,18 @@ make_stub(pivot_root) make_stub(query_module) #endif +#if !defined __NR_recv && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(recv) +#endif + +#if !defined __NR_recvfrom && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(recvfrom) +#endif + +#if !defined __NR_recvmsg && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(recvmsg) +#endif + #ifndef __NR_removexattr make_stub(removexattr) #endif @@ -143,14 +217,46 @@ make_stub(sched_getaffinity) make_stub(sched_setaffinity) #endif +#if !defined __NR_send && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(send) +#endif + +#if !defined __NR_sendmsg && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(sendmsg) +#endif + +#if !defined __NR_sendto && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(sendto) +#endif + +#if !defined __NR_setsockopt && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(setsockopt) +#endif + #ifndef __NR_setxattr make_stub(setxattr) #endif +#if !defined __NR_shutdown && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(shutdown) +#endif + #if !defined(__NR_signalfd4) && !defined(__NR_signalfd) make_stub(signalfd) #endif +#if !defined __NR_socket && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(socket) +#endif + +#if !defined __NR_socketcall && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(socketcall) +#endif + +#if !defined __NR_socketpair && !defined __NR_socketcall && !defined __UCLIBC_HAS_SOCKET__ +make_stub(socketpair) +#endif + #ifndef __NR_rt_sigtimedwait make_stub(sigtimedwait) make_stub(sigwaitinfo) diff --git a/libc/sysdeps/linux/common/sys/epoll.h b/libc/sysdeps/linux/common/sys/epoll.h index 44e814bfd..a04bd704c 100644 --- a/libc/sysdeps/linux/common/sys/epoll.h +++ b/libc/sysdeps/linux/common/sys/epoll.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002-2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -22,6 +22,42 @@ #include <stdint.h> #include <sys/types.h> +/* Get __sigset_t. */ +#include <bits/sigset.h> + +#ifndef __sigset_t_defined +# define __sigset_t_defined +typedef __sigset_t sigset_t; +#endif + + +/* Flags to be passed to epoll_create1. */ + +enum + { +#if defined __alpha__ + EPOLL_CLOEXEC = 010000000, +# define EPOLL_CLOEXEC EPOLL_CLOEXEC + EPOLL_NONBLOCK = 04 +# define EPOLL_NONBLOCK EPOLL_NONBLOCK +#else +# if defined __sparc__ + EPOLL_CLOEXEC = 020000000, +# else + EPOLL_CLOEXEC = 02000000, +# endif +# define EPOLL_CLOEXEC EPOLL_CLOEXEC +# if defined __mips__ + EPOLL_NONBLOCK = 0200 +# elif defined __sparc__ + EPOLL_NONBLOCK = 040000 +# else + EPOLL_NONBLOCK = 04000 +# endif +#define EPOLL_NONBLOCK EPOLL_NONBLOCK +#endif + }; + enum EPOLL_EVENTS { @@ -55,9 +91,9 @@ enum EPOLL_EVENTS /* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */ -#define EPOLL_CTL_ADD 1 /* Add a file decriptor to the interface. */ -#define EPOLL_CTL_DEL 2 /* Remove a file decriptor from the interface. */ -#define EPOLL_CTL_MOD 3 /* Change file decriptor epoll_event structure. */ +#define EPOLL_CTL_ADD 1 /* Add a file descriptor to the interface. */ +#define EPOLL_CTL_DEL 2 /* Remove a file descriptor from the interface. */ +#define EPOLL_CTL_MOD 3 /* Change file descriptor epoll_event structure. */ typedef union epoll_data @@ -72,7 +108,11 @@ struct epoll_event { uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */ -}; +} +#if defined __x86_64__ +__attribute__((packed)) +#endif +; __BEGIN_DECLS @@ -83,6 +123,10 @@ __BEGIN_DECLS returned by epoll_create() should be closed with close(). */ extern int epoll_create (int __size) __THROW; +/* Same as epoll_create but with a FLAGS parameter. The unused SIZE + parameter has been dropped. */ +extern int epoll_create1 (int __flags) __THROW; + /* Manipulate an epoll instance "epfd". Returns 0 in case of success, -1 in case of error ( the "errno" variable will contain the @@ -107,6 +151,16 @@ extern int epoll_ctl (int __epfd, int __op, int __fd, extern int epoll_wait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout); + +/* Same as epoll_wait, but the thread's signal mask is temporarily + and atomically replaced with the one provided as parameter. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int epoll_pwait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout, + __const __sigset_t *__ss); + __END_DECLS #endif /* sys/epoll.h */ diff --git a/libc/sysdeps/linux/common/unwind.h b/libc/sysdeps/linux/common/unwind.h new file mode 100644 index 000000000..81fc4db55 --- /dev/null +++ b/libc/sysdeps/linux/common/unwind.h @@ -0,0 +1,220 @@ +/* Exception handling and frame unwind runtime interface routines. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. + + 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is derived from the C++ ABI for IA-64. Where we diverge + for cross-architecture compatibility are noted with "@@@". */ + +#ifndef _UNWIND_H +#define _UNWIND_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Level 1: Base ABI */ + +/* @@@ The IA-64 ABI uses uint64 throughout. Most places this is + inefficient for 32-bit and smaller machines. */ +typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); +typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); +#if defined(__ia64__) && defined(__hpux__) +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__word__))); +#else +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); +#endif +typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__))); + +/* @@@ The IA-64 ABI uses a 64-bit word to identify the producer and + consumer of an exception. We'll go along with this for now even on + 32-bit machines. We'll need to provide some other option for + 16-bit machines and for machines with > 8 bits per byte. */ +typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__))); + +/* The unwind interface uses reason codes in several contexts to + identify the reasons for failures or other actions. */ +typedef enum +{ + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 +} _Unwind_Reason_Code; + + +/* The unwind interface uses a pointer to an exception header object + as its representation of an exception being thrown. In general, the + full representation of an exception object is language- and + implementation-specific, but it will be prefixed by a header + understood by the unwind interface. */ + +struct _Unwind_Exception; + +typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, + struct _Unwind_Exception *); + +struct _Unwind_Exception +{ + _Unwind_Exception_Class exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + _Unwind_Word private_1; + _Unwind_Word private_2; + + /* @@@ The IA-64 ABI says that this structure must be double-word aligned. + Taking that literally does not make much sense generically. Instead we + provide the maximum alignment required by any type for the machine. */ +} __attribute__((__aligned__)); + + +/* The ACTIONS argument to the personality routine is a bitwise OR of one + or more of the following constants. */ +typedef int _Unwind_Action; + +#define _UA_SEARCH_PHASE 1 +#define _UA_CLEANUP_PHASE 2 +#define _UA_HANDLER_FRAME 4 +#define _UA_FORCE_UNWIND 8 +#define _UA_END_OF_STACK 16 + +/* This is an opaque type used to refer to a system-specific data + structure used by the system unwinder. This context is created and + destroyed by the system, and passed to the personality routine + during unwinding. */ +struct _Unwind_Context; + +/* Raise an exception, passing along the given exception object. */ +extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *); + +/* Raise an exception for forced unwinding. */ + +typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *, void *); + +extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *, + _Unwind_Stop_Fn, + void *); + +/* Helper to invoke the exception_cleanup routine. */ +extern void _Unwind_DeleteException (struct _Unwind_Exception *); + +/* Resume propagation of an existing exception. This is used after + e.g. executing cleanup code, and not to implement rethrowing. */ +extern void _Unwind_Resume (struct _Unwind_Exception *); + +/* @@@ Use unwind data to perform a stack backtrace. The trace callback + is called for every stack frame in the call chain, but no cleanup + actions are performed. */ +typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) + (struct _Unwind_Context *, void *); + +extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); + +/* These functions are used for communicating information about the unwind + context (i.e. the unwind descriptors and the user register state) between + the unwind library and the personality routine and landing pad. Only + selected registers maybe manipulated. */ + +extern _Unwind_Word _Unwind_GetGR (struct _Unwind_Context *, int); +extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word); + +extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *); +extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr); + +/* @@@ Retrieve the CFA of the given context. */ +extern _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *); + +extern void *_Unwind_GetLanguageSpecificData (struct _Unwind_Context *); + +extern _Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *); + + +/* The personality routine is the function in the C++ (or other language) + runtime library which serves as an interface between the system unwind + library and language-specific exception handling semantics. It is + specific to the code fragment described by an unwind info block, and + it is always referenced via the pointer in the unwind info block, and + hence it has no ABI-specified name. + + Note that this implies that two different C++ implementations can + use different names, and have different contents in the language + specific data area. Moreover, that the language specific data + area contains no version info because name of the function invoked + provides more effective versioning by detecting at link time the + lack of code to handle the different data format. */ + +typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *); + +/* @@@ The following alternate entry points are for setjmp/longjmp + based unwinding. */ + +struct SjLj_Function_Context; +extern void _Unwind_SjLj_Register (struct SjLj_Function_Context *); +extern void _Unwind_SjLj_Unregister (struct SjLj_Function_Context *); + +extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException + (struct _Unwind_Exception *); +extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); +extern void _Unwind_SjLj_Resume (struct _Unwind_Exception *); + +/* @@@ The following provide access to the base addresses for text + and data-relative addressing in the LDSA. In order to stay link + compatible with the standard ABI for IA-64, we inline these. */ + +#ifdef __ia64__ +#include <stdlib.h> + +static inline _Unwind_Ptr +_Unwind_GetDataRelBase (struct _Unwind_Context *_C) +{ + /* The GP is stored in R1. */ + return _Unwind_GetGR (_C, 1); +} + +static inline _Unwind_Ptr +_Unwind_GetTextRelBase (struct _Unwind_Context *_C) +{ + abort (); + return 0; +} + +/* @@@ Retrieve the Backing Store Pointer of the given context. */ +extern _Unwind_Word _Unwind_GetBSP (struct _Unwind_Context *); +#else +extern _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *); +extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *); +#endif + +/* @@@ Given an address, return the entry point of the function that + contains it. */ +extern void * _Unwind_FindEnclosingFunction (void *pc); + +#ifdef __cplusplus +} +#endif + +#endif /* unwind.h */ |