]>
git.saurik.com Git - apple/libplatform.git/blob - src/ucontext/generic/getmcontext.c
2 * Copyright (c) 2007, 2008, 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #define _XOPEN_SOURCE 600L
29 #include <TargetConditionals.h>
31 /* This is a macro to capture all the code added in here that is purely to make
32 * conformance tests pass and seems to have no functional reason nor is it
33 * required by the standard */
34 #define CONFORMANCE_SPECIFIC_HACK 1
37 extern int __in_sigtramp
;
38 #endif /* __DYNAMIC_ */
40 #if TARGET_OS_OSX || TARGET_OS_DRIVERKIT
42 #if defined(__x86_64__) || defined(__i386__)
44 #include <sys/resource.h>
49 #include <platform/string.h>
50 #include <platform/compat.h>
52 extern int __sigaltstack(const stack_t
* __restrict
, stack_t
* __restrict
);
55 extern int __in_sigtramp
;
56 #endif /* __DYNAMIC_ */
58 __attribute__((visibility("hidden")))
60 getmcontext(ucontext_t
*uctx
, void *sp
)
62 mcontext_t mctx
= (mcontext_t
)&uctx
->__mcontext_data
;
66 #if CONFORMANCE_SPECIFIC_HACK
67 uctx
->uc_stack
.ss_sp
= sp
;
68 uctx
->uc_stack
.ss_flags
= 0;
70 if (0 == __sigaltstack(NULL
, &stack
)) {
71 if (stack
.ss_flags
& SS_ONSTACK
) {
72 uctx
->uc_stack
= stack
;
73 stacksize
= stack
.ss_size
;
79 if (0 == getrlimit(RLIMIT_STACK
, &rlim
))
80 stacksize
= rlim
.rlim_cur
;
83 uctx
->uc_stack
.ss_size
= stacksize
;
86 uctx
->uc_mcontext
= mctx
;
87 uctx
->uc_mcsize
= sizeof(*mctx
);
89 #if CONFORMANCE_SPECIFIC_HACK
92 uctx
->uc_link
= (ucontext_t
*)(uintptr_t)__in_sigtramp
; /* non-zero if in signal handler */
93 #else /* !__DYNAMIC__ */
95 #endif /* __DYNAMIC__ */
97 #endif /* CONFORMANCE_SPECIFIC_HACK */
99 sigprocmask(0, NULL
, &uctx
->uc_sigmask
);
103 #elif defined(__arm64__)
109 #include <platform/string.h>
110 #include <platform/compat.h>
112 extern int __sigaltstack(const stack_t
* __restrict
, stack_t
* __restrict
);
114 /* @function populate_signal_stack_context
120 * __darwin_sigset_t uc_sigmask; // signal mask used by this context
121 * _STRUCT_SIGALTSTACK uc_stack; // stack used by this context
122 * _STRUCT_UCONTEXT *uc_link; // pointer to resuming context
123 * __darwin_size_t uc_mcsize; // size of the machine context passed in
124 * _STRUCT_MCONTEXT *uc_mcontext; // pointer to machine specific context
125 * #ifdef _XOPEN_SOURCE
126 * _STRUCT_MCONTEXT __mcontext_data;
130 * populate_signal_stack_context unconditionally populates the following fields:
137 * The standard specifies this about uc_stack:
139 * Before a call is made to makecontext(), the application shall ensure
140 * that the context being modified has a stack allocated for it.
142 * ie. the client is generally responsible for managing the stack on on which
143 * their context runs and initializing it properly.
145 __attribute__((visibility("hidden")))
147 populate_signal_stack_context(ucontext_t
*ucp
, void *sp
)
149 #if CONFORMANCE_SPECIFIC_HACK
150 /* The conformance tests seems to require that we populate the uc_stack in
151 * getcontext even though the standard requires - as stated above - that the
152 * clients manage the stack that their code runs on. This makes no
153 * functional sense but is put in here to make conformance tests work */
156 if (0 == __sigaltstack(NULL
, &stack
) && (stack
.ss_flags
& SA_ONSTACK
)) {
160 // This stacksize is the wrong number - it provides the stack size of
161 // the main thread and not the current thread. We can't know the
162 // stacksize of the current thread without jumping through some crazy
163 // hoops and it seems like per the standard, this field should not be
164 // required anyways since the client should be allocating and managing
165 // stacks themselves for makecontext.
167 if (0 == getrlimit(RLIMIT_STACK
, &rlim
))
168 stack
.ss_size
= rlim
.rlim_cur
;
170 ucp
->uc_stack
= stack
;
173 /* Populate signal information */
174 sigprocmask(SIG_UNBLOCK
, NULL
, &ucp
->uc_sigmask
);
176 /* Always use the mcontext that is embedded in the struct */
177 mcontext_t mctx
= (mcontext_t
) &ucp
->__mcontext_data
;
178 ucp
->uc_mcontext
= mctx
;
179 ucp
->uc_mcsize
= sizeof(*mctx
);
181 #if CONFORMANCE_SPECIFIC_HACK
182 /* The conformance tests for getcontext requires that:
183 * uc_link = 0 if we're in the "main context"
184 * uc_link = non-0 if we're on signal context while calling getcontext
186 * It seems like it doesn't require uc_link to a valid pointer in the 2nd
187 * case, just not 0. It also seems to require that the uc_link is
188 * diversified if we have multiple contexts populated from the signal stack.
189 * So we have it be the address of the in_signal_handler value.
191 * AFAICT, there seems to be no reason to require populating uc_link at all
192 * but it is what the tests expects.
195 ucp
->uc_link
= (ucontext_t
*)(uintptr_t)__in_sigtramp
; /* non-zero if in signal handler */
196 #else /* !__DYNAMIC__ */
198 #endif /* __DYNAMIC__ */
205 #endif /* arm64 || x86_64 || i386 */
210 getcontext(ucontext_t
*uctx
)