1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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
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.
22 * @APPLE_LICENSE_HEADER_END@
27 #include <mach-o/loader.h>
31 // BEGIN copy of code from libgcc.a source file unwind-dw2-fde-darwin.c
33 #define KEYMGR_API_MAJOR_GCC3 3
34 /* ... with these keys. */
35 #define KEYMGR_GCC3_LIVE_IMAGE_LIST 301 /* loaded images */
36 #define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */
37 #define KEYMGR_EH_GLOBALS_KEY 13
39 /* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST. Info about each resident image. */
41 unsigned long this_size
; /* sizeof (live_images) */
42 struct mach_header
*mh
; /* the image info */
43 unsigned long vm_slide
;
44 void (*destructor
)(struct live_images
*); /* destructor for this */
45 struct live_images
*next
;
46 unsigned int examined_p
;
49 unsigned long info
[2]; /* Future use. */
52 // END copy of code from libgcc.a source file unwind-dw2-fde-darwin.c
57 // dyld is built as stand alone executable with a static copy of libc, libstdc++, and libgcc.
59 // In order for C++ exceptions to work within dyld, the C++ exception handling code
60 // must be able to find the exception handling frame data inside dyld. The standard
61 // exception handling code uses crt and keymgr to keep track of all images and calls
62 // getsectdatafromheader("__eh_frame") to find the EH data for each image. We implement
63 // our own copy of those functions below to enable exceptions within dyld.
65 // Note: This exception handling is completely separate from any user code exception .
66 // handling which has its own keymgr (in libSystem).
70 static struct live_images sDyldImage
; // zero filled
71 static void* sObjectList
= NULL
;
72 #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
73 static void* sEHGlobals
= NULL
;
77 // called by dyldStartup.s very early
78 void dyld_exceptions_init(struct mach_header
*mh
, uintptr_t slide
)
80 sDyldImage
.this_size
= sizeof(struct live_images
);
82 sDyldImage
.vm_slide
= slide
;
87 // Hack for gcc 3.5's use of keymgr includes accessing __keymgr_global
88 #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
89 typedef struct Sinfo_Node
{
90 uint32_t size
; /* Size of this node. */
91 uint16_t major_version
; /* API major version. */
92 uint16_t minor_version
; /* API minor version. */
94 static const Tinfo_Node keymgr_info
= { sizeof (Tinfo_Node
), KEYMGR_API_MAJOR_GCC3
, 0 };
95 const Tinfo_Node
* __keymgr_global
[3] = { NULL
, NULL
, &keymgr_info
};
98 static __attribute__((noreturn
))
101 //dyld::log("internal dyld error\n");
105 void* _keymgr_get_and_lock_processwide_ptr(unsigned int key
)
107 // The C++ exception handling code uses two keys. No other keys should be seen
108 if ( key
== KEYMGR_GCC3_LIVE_IMAGE_LIST
) {
111 else if ( key
== KEYMGR_GCC3_DW2_OBJ_LIST
) {
117 void _keymgr_set_and_unlock_processwide_ptr(unsigned int key
, void* value
)
119 // The C++ exception handling code uses just this key. No other keys should be seen
120 if ( key
== KEYMGR_GCC3_DW2_OBJ_LIST
) {
127 void _keymgr_unlock_processwide_ptr(unsigned int key
)
129 // The C++ exception handling code uses just this key. No other keys should be seen
130 if ( key
== KEYMGR_GCC3_LIVE_IMAGE_LIST
) {
136 void* _keymgr_get_per_thread_data(unsigned int key
)
138 #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
139 // gcc 3.5 and later use this key
140 if ( key
== KEYMGR_EH_GLOBALS_KEY
)
144 // used by std::termination which dyld does not use
148 void _keymgr_set_per_thread_data(unsigned int key
, void *keydata
)
150 #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
151 // gcc 3.5 and later use this key
152 if ( key
== KEYMGR_EH_GLOBALS_KEY
) {
153 sEHGlobals
= keydata
;
157 // used by std::termination which dyld does not use
162 #define LC_SEGMENT_COMMAND LC_SEGMENT_64
163 #define macho_header mach_header_64
164 #define macho_segment_command segment_command_64
165 #define macho_section section_64
166 #define getsectdatafromheader getsectdatafromheader_64
168 #define LC_SEGMENT_COMMAND LC_SEGMENT
169 #define macho_header mach_header
170 #define macho_segment_command segment_command
171 #define macho_section section
174 // needed by C++ exception handling code to find __eh_frame section
175 const void* getsectdatafromheader(struct mach_header
* mh
, const char* segname
, const char* sectname
, unsigned long* size
)
177 const struct load_command
* cmd
;
180 cmd
= (struct load_command
*) ((char *)mh
+ sizeof(struct macho_header
));
181 for(i
= 0; i
< mh
->ncmds
; i
++) {
182 if ( cmd
->cmd
== LC_SEGMENT_COMMAND
) {
183 const struct macho_segment_command
* seg
= (struct macho_segment_command
*)cmd
;
184 if ( strcmp(seg
->segname
, segname
) == 0 ) {
185 const struct macho_section
* sect
= (struct macho_section
*)( (char*)seg
+ sizeof(struct macho_segment_command
) );
187 for (j
= 0; j
< seg
->nsects
; j
++) {
188 if ( strcmp(sect
[j
].sectname
, sectname
) == 0 ) {
189 *size
= sect
[j
].size
;
190 return (void*)(sect
[j
].addr
);
195 cmd
= (struct load_command
*)( (char*)cmd
+ cmd
->cmdsize
);
201 // Hack for transition of rdar://problem/3933738
202 // Can be removed later.
203 // Allow C++ runtime to call getsectdatafromheader or getsectdatafromheader_64
205 #undef getsectdatafromheader
206 const void* getsectdatafromheader(struct mach_header
* mh
, const char* segname
, const char* sectname
, unsigned long* size
)
208 return getsectdatafromheader_64(mh
, segname
, sectname
, size
);