]> git.saurik.com Git - apple/dyld.git/blame - src/dyldExceptions.c
dyld-360.21.tar.gz
[apple/dyld.git] / src / dyldExceptions.c
CommitLineData
0959b6d4
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
832b6fce 3 * Copyright (c) 2004-2011 Apple Inc. All rights reserved.
0959b6d4
A
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include <stdlib.h>
26#include <string.h>
0959b6d4 27#include <mach-o/loader.h>
bac542e6 28#include <unistd.h>
39a8cd10
A
29#include <stdio.h>
30#include <stdbool.h>
31#include <stdarg.h>
32#include <pthread.h>
412ebb8e 33#include <Availability.h>
39a8cd10
A
34
35#include "mach-o/dyld_priv.h"
36#include "dyldLibSystemInterface.h"
37
19894a12 38
39a8cd10
A
39extern void _ZN4dyld3logEPKcz(const char*, ...);
40extern struct LibSystemHelpers* _ZN4dyld17gLibSystemHelpersE;
41
42
43#if __LP64__
44 #define LC_SEGMENT_COMMAND LC_SEGMENT_64
45 #define macho_header mach_header_64
46 #define macho_segment_command segment_command_64
47 #define macho_section section_64
48 #define getsectdatafromheader getsectdatafromheader_64
49#else
50 #define LC_SEGMENT_COMMAND LC_SEGMENT
51 #define macho_header mach_header
52 #define macho_segment_command segment_command
53 #define macho_section section
54#endif
55
56
412ebb8e
A
57//
58// The standard versions of __cxa_get_globals*() from libstdc++-static.a cannot be used.
59// On Mac OS X, they use keymgr which dyld does not implement.
60// On iPhoneOS, they use pthread_key_create which dyld cannot use.
61//
62// Implement these ourselves to make upcalls into libSystem to malloc and create a pthread key
63//
64static pthread_key_t sCxaKey = 0;
65static char sPreMainCxaGlobals[2*sizeof(long)];
66
67// called by libstdc++.a
68char* __cxa_get_globals()
69{
70 // if libSystem.dylib not yet initialized, or is old libSystem, use shared global
2fd3f4e8 71 if ( (_ZN4dyld17gLibSystemHelpersE == NULL) || (_ZN4dyld17gLibSystemHelpersE->version < 7) )
412ebb8e
A
72 return sPreMainCxaGlobals;
73
74 if ( sCxaKey == 0 ) {
75 // create key
76 // we don't need a lock because only one thread can be in dyld at a time
77 _ZN4dyld17gLibSystemHelpersE->pthread_key_create(&sCxaKey, &free);
78 }
2fd3f4e8 79 char* data = (char*)_ZN4dyld17gLibSystemHelpersE->pthread_getspecific(sCxaKey);
412ebb8e
A
80 if ( data == NULL ) {
81 data = calloc(2,sizeof(void*));
82 _ZN4dyld17gLibSystemHelpersE->pthread_setspecific(sCxaKey, data);
83 }
84 return data;
85}
86
87// called by libstdc++.a
88char* __cxa_get_globals_fast()
89{
90 // if libSystem.dylib not yet initialized, or is old libSystem, use shared global
2fd3f4e8 91 if ( (_ZN4dyld17gLibSystemHelpersE == NULL) || (_ZN4dyld17gLibSystemHelpersE->version < 7) )
412ebb8e
A
92 return sPreMainCxaGlobals;
93
2fd3f4e8 94 return _ZN4dyld17gLibSystemHelpersE->pthread_getspecific(sCxaKey);
412ebb8e
A
95}
96
97
98
19894a12 99#if !__USING_SJLJ_EXCEPTIONS__
412ebb8e 100//
19894a12
A
101// When dyld uses zero-cost exceptions it just needs to implement
102// _dyld_find_unwind_sections to return sections inside dyld proper.
412ebb8e 103//
39a8cd10 104
832b6fce
A
105extern void* ehStart __asm("section$start$__TEXT$__eh_frame");
106extern void* ehEnd __asm("section$end$__TEXT$__eh_frame");
107extern void* uwStart __asm("section$start$__TEXT$__unwind_info");
108extern void* uwEnd __asm("section$end$__TEXT$__unwind_info");
39a8cd10 109
832b6fce
A
110extern void* textStart __asm("section$start$__TEXT$__text");
111extern void* textEnd __asm("section$end$__TEXT$__text");
39a8cd10 112
832b6fce
A
113extern void* __dso_handle;
114
115// called by libuwind code to find unwind information sections in dyld
39a8cd10
A
116bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info)
117{
832b6fce
A
118 if ( ((void*)&textStart < addr) && (addr < (void*)&textEnd) ) {
119 info->mh = (struct mach_header*)&__dso_handle;
120 info->dwarf_section = &ehStart;
121 info->dwarf_section_length = ((char*)&ehEnd - (char*)&ehStart);
122 info->compact_unwind_section = &uwStart;
123 info->compact_unwind_section_length = ((char*)&uwEnd - (char*)&uwStart);
39a8cd10
A
124 return true;
125 }
126 else {
127 return false;
128 }
129}
130
19894a12
A
131#else
132//
133// When dyld uses setjump-longjump exceptions it needs to implement
134// routines to push and pop a stack of _Unwind_FunctionContext.
135//
39a8cd10 136
412ebb8e
A
137struct _Unwind_FunctionContext
138{
139 // next function in stack of handlers
140 struct _Unwind_FunctionContext* prev;
39a8cd10 141
0959b6d4 142};
0959b6d4 143
0959b6d4 144
412ebb8e
A
145static pthread_key_t sThreadChainKey = 0;
146static struct _Unwind_FunctionContext* sStaticThreadChain = NULL;
0959b6d4 147
412ebb8e
A
148//
149// When libSystem's initializers are run, they call back into dyld's
150// registerThreadHelpers which creates a pthread key and calls
151// __Unwind_SjLj_SetThreadKey().
152//
153void __Unwind_SjLj_SetThreadKey(pthread_key_t key)
0959b6d4 154{
412ebb8e
A
155 sThreadChainKey = key;
156 //_ZN4dyld3logEPKcz("__Unwind_SjLj_SetThreadKey(key=%d), sStaticThreadChain=%p\n", key, sStaticThreadChain);
157 // switch static chain to be per thread
158 _ZN4dyld17gLibSystemHelpersE->pthread_setspecific(sThreadChainKey, sStaticThreadChain);
159 sStaticThreadChain = NULL;
160 //_ZN4dyld3logEPKcz("__Unwind_SjLj_SetThreadKey(key=%d), result=%d, new top=%p\n", key, result, pthread_getspecific(sThreadChainKey));
0959b6d4
A
161}
162
0959b6d4 163
412ebb8e
A
164//static void printChain()
165//{
166// _ZN4dyld3logEPKcz("chain: ");
167// struct _Unwind_FunctionContext* start = sStaticThreadChain;
168// if ( sThreadChainKey != 0 ) {
169// start = (struct _Unwind_FunctionContext*)pthread_getspecific(sThreadChainKey);
170// }
171// for (struct _Unwind_FunctionContext* p = start; p != NULL; p = p->prev) {
172// _ZN4dyld3logEPKcz("%p -> ", p);
173// }
174// _ZN4dyld3logEPKcz("\n");
175//}
0959b6d4 176
0959b6d4 177
412ebb8e 178struct _Unwind_FunctionContext* __Unwind_SjLj_GetTopOfFunctionStack()
0959b6d4 179{
412ebb8e
A
180 //_ZN4dyld3logEPKcz("__Unwind_SjLj_GetTopOfFunctionStack(), key=%d, ", sThreadChainKey);
181 //printChain();
182 if ( sThreadChainKey != 0 ) {
183 return (struct _Unwind_FunctionContext*)pthread_getspecific(sThreadChainKey);
184 }
185 else {
186 return sStaticThreadChain;
0959b6d4 187 }
0959b6d4
A
188}
189
412ebb8e 190void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext* fc)
0959b6d4 191{
412ebb8e
A
192 //_ZN4dyld3logEPKcz("__Unwind_SjLj_SetTopOfFunctionStack(%p), key=%d, prev=%p\n",
193 // fc, sThreadChainKey, (fc != NULL) ? fc->prev : NULL);
194 if ( sThreadChainKey != 0 )
195 _ZN4dyld17gLibSystemHelpersE->pthread_setspecific(sThreadChainKey, fc);
196 else
197 sStaticThreadChain = fc;
198 //_ZN4dyld3logEPKcz("__Unwind_SjLj_SetTopOfFunctionStack(%p), key=%d, ", fc, sThreadChainKey);
199 //printChain();
0959b6d4
A
200}
201
39a8cd10
A
202#endif
203
204
0959b6d4 205