]> git.saurik.com Git - apple/dyld.git/blob - src/dyldExceptions.c
dyld-239.3.tar.gz
[apple/dyld.git] / src / dyldExceptions.c
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004-2011 Apple Inc. All rights reserved.
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>
27 #include <mach-o/loader.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <stdbool.h>
31 #include <stdarg.h>
32 #include <pthread.h>
33 #include <Availability.h>
34
35 #include "mach-o/dyld_priv.h"
36 #include "dyldLibSystemInterface.h"
37
38 extern void _ZN4dyld3logEPKcz(const char*, ...);
39 extern struct LibSystemHelpers* _ZN4dyld17gLibSystemHelpersE;
40
41
42 #if __LP64__
43 #define LC_SEGMENT_COMMAND LC_SEGMENT_64
44 #define macho_header mach_header_64
45 #define macho_segment_command segment_command_64
46 #define macho_section section_64
47 #define getsectdatafromheader getsectdatafromheader_64
48 #else
49 #define LC_SEGMENT_COMMAND LC_SEGMENT
50 #define macho_header mach_header
51 #define macho_segment_command segment_command
52 #define macho_section section
53 #endif
54
55
56 //
57 // The standard versions of __cxa_get_globals*() from libstdc++-static.a cannot be used.
58 // On Mac OS X, they use keymgr which dyld does not implement.
59 // On iPhoneOS, they use pthread_key_create which dyld cannot use.
60 //
61 // Implement these ourselves to make upcalls into libSystem to malloc and create a pthread key
62 //
63 static pthread_key_t sCxaKey = 0;
64 static char sPreMainCxaGlobals[2*sizeof(long)];
65
66 // called by libstdc++.a
67 char* __cxa_get_globals()
68 {
69 // if libSystem.dylib not yet initialized, or is old libSystem, use shared global
70 if ( (_ZN4dyld17gLibSystemHelpersE == NULL) || (_ZN4dyld17gLibSystemHelpersE->version < 7) )
71 return sPreMainCxaGlobals;
72
73 if ( sCxaKey == 0 ) {
74 // create key
75 // we don't need a lock because only one thread can be in dyld at a time
76 _ZN4dyld17gLibSystemHelpersE->pthread_key_create(&sCxaKey, &free);
77 }
78 char* data = (char*)_ZN4dyld17gLibSystemHelpersE->pthread_getspecific(sCxaKey);
79 if ( data == NULL ) {
80 data = calloc(2,sizeof(void*));
81 _ZN4dyld17gLibSystemHelpersE->pthread_setspecific(sCxaKey, data);
82 }
83 return data;
84 }
85
86 // called by libstdc++.a
87 char* __cxa_get_globals_fast()
88 {
89 // if libSystem.dylib not yet initialized, or is old libSystem, use shared global
90 if ( (_ZN4dyld17gLibSystemHelpersE == NULL) || (_ZN4dyld17gLibSystemHelpersE->version < 7) )
91 return sPreMainCxaGlobals;
92
93 return _ZN4dyld17gLibSystemHelpersE->pthread_getspecific(sCxaKey);
94 }
95
96
97
98
99 #if !__arm__
100 //
101 // The intel versions of dyld uses zero-cost exceptions which are handled by
102 // linking with a special copy of libunwind.a
103 //
104
105 extern void* ehStart __asm("section$start$__TEXT$__eh_frame");
106 extern void* ehEnd __asm("section$end$__TEXT$__eh_frame");
107 extern void* uwStart __asm("section$start$__TEXT$__unwind_info");
108 extern void* uwEnd __asm("section$end$__TEXT$__unwind_info");
109
110 extern void* textStart __asm("section$start$__TEXT$__text");
111 extern void* textEnd __asm("section$end$__TEXT$__text");
112
113 extern void* __dso_handle;
114
115 // called by libuwind code to find unwind information sections in dyld
116 bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info)
117 {
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);
124 return true;
125 }
126 else {
127 return false;
128 }
129 }
130
131 #endif // !__arm__
132
133
134 #if __arm__
135
136 struct _Unwind_FunctionContext
137 {
138 // next function in stack of handlers
139 struct _Unwind_FunctionContext* prev;
140
141 };
142
143
144 static pthread_key_t sThreadChainKey = 0;
145 static struct _Unwind_FunctionContext* sStaticThreadChain = NULL;
146
147 //
148 // When libSystem's initializers are run, they call back into dyld's
149 // registerThreadHelpers which creates a pthread key and calls
150 // __Unwind_SjLj_SetThreadKey().
151 //
152 void __Unwind_SjLj_SetThreadKey(pthread_key_t key)
153 {
154 sThreadChainKey = key;
155 //_ZN4dyld3logEPKcz("__Unwind_SjLj_SetThreadKey(key=%d), sStaticThreadChain=%p\n", key, sStaticThreadChain);
156 // switch static chain to be per thread
157 _ZN4dyld17gLibSystemHelpersE->pthread_setspecific(sThreadChainKey, sStaticThreadChain);
158 sStaticThreadChain = NULL;
159 //_ZN4dyld3logEPKcz("__Unwind_SjLj_SetThreadKey(key=%d), result=%d, new top=%p\n", key, result, pthread_getspecific(sThreadChainKey));
160 }
161
162
163 //static void printChain()
164 //{
165 // _ZN4dyld3logEPKcz("chain: ");
166 // struct _Unwind_FunctionContext* start = sStaticThreadChain;
167 // if ( sThreadChainKey != 0 ) {
168 // start = (struct _Unwind_FunctionContext*)pthread_getspecific(sThreadChainKey);
169 // }
170 // for (struct _Unwind_FunctionContext* p = start; p != NULL; p = p->prev) {
171 // _ZN4dyld3logEPKcz("%p -> ", p);
172 // }
173 // _ZN4dyld3logEPKcz("\n");
174 //}
175
176
177 struct _Unwind_FunctionContext* __Unwind_SjLj_GetTopOfFunctionStack()
178 {
179 //_ZN4dyld3logEPKcz("__Unwind_SjLj_GetTopOfFunctionStack(), key=%d, ", sThreadChainKey);
180 //printChain();
181 if ( sThreadChainKey != 0 ) {
182 return (struct _Unwind_FunctionContext*)pthread_getspecific(sThreadChainKey);
183 }
184 else {
185 return sStaticThreadChain;
186 }
187 }
188
189 void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext* fc)
190 {
191 //_ZN4dyld3logEPKcz("__Unwind_SjLj_SetTopOfFunctionStack(%p), key=%d, prev=%p\n",
192 // fc, sThreadChainKey, (fc != NULL) ? fc->prev : NULL);
193 if ( sThreadChainKey != 0 )
194 _ZN4dyld17gLibSystemHelpersE->pthread_setspecific(sThreadChainKey, fc);
195 else
196 sStaticThreadChain = fc;
197 //_ZN4dyld3logEPKcz("__Unwind_SjLj_SetTopOfFunctionStack(%p), key=%d, ", fc, sThreadChainKey);
198 //printChain();
199 }
200
201 #endif
202
203
204