modified: nfig1.py
[GalaxyCodeBases.git] / c_cpp / Mac / Csu-85 / crt.c
blob8d180f8ad7d7d66176d2bc370220e16843e3e01e
1 /*
2 * Copyright (c) 1999-2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
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 OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
22 * @APPLE_LICENSE_HEADER_END@
25 * The common startup code. This code is if'ed with the 'C' preprocessor
26 * macros __DYNAMIC__ and GCRT. It is used to create
27 * the following files when compiled with the following macros defined:
29 * File Dedined Macros Purpose
30 * crt1.o __DYNAMIC__ startup for programs compiled -dynamic
31 * gcrt1.o __DYNAMIC__, GCRT profiling startup, programs compiled -dynamic
33 * crt0.o startup for programs compiled -static
37 #include <stddef.h>
40 * Global data definitions (initialized data).
42 int NXArgc = 0;
43 const char** NXArgv = NULL;
44 const char** environ = NULL;
45 const char* __progname = NULL;
47 #if ADD_PROGRAM_VARS
48 extern void* __dso_handle;
49 struct ProgramVars
51 void* mh;
52 int* NXArgcPtr;
53 const char*** NXArgvPtr;
54 const char*** environPtr;
55 const char** __prognamePtr;
57 __attribute__((used)) static struct ProgramVars pvars
58 __attribute__ ((section ("__DATA,__program_vars"))) = { &__dso_handle, &NXArgc, &NXArgv, &environ, &__progname };
60 #endif
64 * This file is not needed for executables targeting 10.5 or later
65 * start calls main() directly.
67 #if __DYNAMIC__ && OLD_LIBSYSTEM_SUPPORT
69 * The following symbols are reference by System Framework symbolicly (instead
70 * of through undefined references (to allow prebinding). To get strip(1) to
71 * know these symbols are not to be stripped they need to have the
72 * REFERENCED_DYNAMICALLY bit (0x10) set. This would have been done automaticly
73 * by ld(1) if these symbols were referenced through undefined symbols.
74 * The catch_exception_raise symbol is special in that the Mach API specifically
75 * requires that the library call into the user program for its implementation.
76 * Therefore, we need to create a common definition and make sure the symbol
77 * doesn't get stripped.
79 asm(".desc _NXArgc, 0x10");
80 asm(".desc _NXArgv, 0x10");
81 asm(".desc _environ, 0x10");
82 asm(".desc __mh_execute_header, 0x10");
83 #if defined(__ppc__) || defined(__i386__)
84 asm(".comm _catch_exception_raise, 4");
85 asm(".desc _catch_exception_raise, 0x10");
86 asm(".comm _catch_exception_raise_state, 4");
87 asm(".desc _catch_exception_raise_state, 0x10");
88 asm(".comm _catch_exception_raise_state_identity, 4");
89 asm(".desc _catch_exception_raise_state_identity, 0x10");
90 asm(".comm _do_mach_notify_dead_name, 4");
91 asm(".desc _do_mach_notify_dead_name, 0x10");
92 asm(".comm _do_seqnos_mach_notify_dead_name, 4");
93 asm(".desc _do_seqnos_mach_notify_dead_name, 0x10");
94 asm(".comm _do_mach_notify_no_senders, 4");
95 asm(".desc _do_mach_notify_no_senders, 0x10");
96 asm(".comm _do_seqnos_mach_notify_no_senders, 4");
97 asm(".desc _do_seqnos_mach_notify_no_senders, 0x10");
98 asm(".comm _do_mach_notify_port_deleted, 4");
99 asm(".desc _do_mach_notify_port_deleted, 0x10");
100 asm(".comm _do_seqnos_mach_notify_port_deleted, 4");
101 asm(".desc _do_seqnos_mach_notify_port_deleted, 0x10");
102 asm(".comm _do_mach_notify_send_once, 4");
103 asm(".desc _do_mach_notify_send_once, 0x10");
104 asm(".comm _do_seqnos_mach_notify_send_once, 4");
105 asm(".desc _do_seqnos_mach_notify_send_once, 0x10");
106 asm(".comm _clock_alarm_reply, 4");
107 asm(".desc _clock_alarm_reply, 0x10");
108 asm(".comm _receive_samples, 4");
109 asm(".desc _receive_samples, 0x10");
110 #endif /* __ppc__ || __i386__ */
111 asm(".desc ___progname, 0x10");
114 * Common data definitions. If the routines in System Framework are not pulled
115 * into the executable then the static linker will allocate these as common
116 * symbols. The code in here tests the value of these are non-zero to know if
117 * the routines in System Framework got pulled in and should be called. The
118 * first two are pointers to functions. The second two use just the symbol
119 * itself. In the later case we are using the symbol with two different 'C'
120 * types. To make it as clean as possible the 'C' type declared is that of the
121 * external function. The common symbol is declared with an asm() and the code
122 * casts the function name to a pointer to an int and then indirects through
123 * the pointer to see if the value is not zero to know the function got linked
124 * in. Then the code uses a pointer in the data area to the function to call
125 * the function. The pointer in the data area is needed on various RISC
126 * architectutes like the PowerPC to avoid a relocation overflow error when
127 * linking programs with large data area.
129 extern int (*mach_init_routine)(void);
130 extern int (*_cthread_init_routine)(void);
131 #if !__DYNAMIC__
132 asm(".comm __cplus_init, 4");
133 extern void _cplus_init(void);
134 #endif
135 #if __DYNAMIC__ && __ppc__
136 asm(".comm ___darwin_gcc3_preregister_frame_info, 4");
137 extern void __darwin_gcc3_preregister_frame_info (void);
138 static void (*pointer_to__darwin_gcc3_preregister_frame_info)(void) =
139 __darwin_gcc3_preregister_frame_info;
140 #endif
143 * Prototypes for routines that are called.
145 extern int main(int argc, const char* argv[], const char* envp[], const char* apple[]);
146 extern void exit(int status) __attribute__ ((noreturn));
147 extern int atexit(void (*fcn)(void));
148 static const char* crt_basename(const char* path);
150 #if GCRT
151 extern void moninit(void);
152 static void _mcleanup(void);
153 extern void monitor(char *lowpc,char *highpc,char *buf,int bufsiz,int nfunc);
154 #endif /* GCRT */
156 #if __DYNAMIC__
157 extern int _dyld_func_lookup(const char *dyld_func_name,unsigned long *address);
158 extern void __keymgr_dwarf2_register_sections (void);
159 #endif /* __DYNAMIC__ */
161 #if __DYNAMIC__ && __ppc__
162 static void _call_objcInit(void);
163 #endif
165 extern int errno;
168 * _start() is called from the machine dependent assembly entry point "start:" .
169 * It takes care of setting up the stack so 'C' routines can be called and
170 * passes argc, argv and envp to here.
172 __private_extern__
173 void
174 _start(int argc, const char* argv[], const char* envp[])
176 const char** apple;
177 #if __DYNAMIC__
178 void (*term)(void);
179 void (*init)(void);
180 #endif
182 // initialize global variables
183 NXArgc = argc;
184 NXArgv = argv;
185 environ = envp;
186 __progname = ((argv[0] != NULL) ? crt_basename(argv[0]) : "");
187 // see start.s for how "apple" parameter follow envp
188 for(apple = envp; *apple != NULL; ++apple) { /* loop */ }
189 ++apple;
191 // initialize libSystem
192 if ( mach_init_routine != 0 )
193 (void) mach_init_routine();
194 if ( _cthread_init_routine != 0 )
195 (*_cthread_init_routine)();
197 #ifdef __DYNAMIC__
198 __keymgr_dwarf2_register_sections ();
199 #endif
201 #if __ppc__ && __DYNAMIC__
202 /* Call a ppc GCC 3.3-specific function (in libgcc.a) to
203 "preregister" exception frame info, meaning to set up the
204 dyld hooks that do the actual registration. */
205 if ( *((int *)pointer_to__darwin_gcc3_preregister_frame_info) != 0 )
206 pointer_to__darwin_gcc3_preregister_frame_info ();
207 #endif
209 #if !__DYNAMIC__
210 if(*((int *)_cplus_init) != 0)
211 _cplus_init();
212 #endif
214 #ifdef __DYNAMIC__
216 * Call into dyld to run all initializers. This must be done
217 * after mach_init()
219 _dyld_func_lookup("__dyld_make_delayed_module_initializer_calls",
220 (unsigned long *)&init);
221 init();
222 #endif
224 #if __DYNAMIC__ && __ppc__
225 _call_objcInit();
226 #endif
228 #ifdef GCRT
229 atexit(_mcleanup);
230 moninit();
231 #endif
233 #ifdef __DYNAMIC__
235 * If the dyld we are running with supports module termination routines
236 * for all types of images then register the function to call them with
237 * atexit().
239 _dyld_func_lookup("__dyld_mod_term_funcs", (unsigned long *)&term);
240 if ( term != 0 )
241 atexit(term);
242 #endif
244 // clear errno, so main() starts fresh
245 errno = 0;
247 // call main() and return to exit()
248 exit(main(argc, argv, envp, apple));
251 #if GCRT
253 * For profiling the routine _mcleanup gets registered with atexit so monitor(0)
254 * gets called.
256 static
257 void
258 _mcleanup(
259 void)
261 monitor(0,0,0,0,0);
263 #endif /* GCRT */
265 static
266 const char *
267 crt_basename(const char *path)
269 const char *s;
270 const char *last = path;
272 for (s = path; *s != '\0'; s++) {
273 if (*s == '/') last = s+1;
276 return last;
279 #if __DYNAMIC__ && __ppc__
280 static
282 crt_strbeginswith(const char *s1, const char *s2)
284 int i;
286 for (i = 0; ; i++) {
287 if (s2[i] == '\0') return 1;
288 else if (s1[i] != s2[i]) return 0;
293 * Look for a function called _objcInit() in any library whose name
294 * starts with "libobjc", and call it if one exists. This is used to
295 * initialize the Objective-C runtime on Mac OS X 10.3 and earlier.
296 * This is completely unnecessary on Mac OS X 10.4 and later.
298 static
299 void
300 _call_objcInit(void)
302 unsigned int i, count;
304 unsigned int (*_dyld_image_count_fn)(void);
305 const char *(*_dyld_get_image_name_fn)(unsigned int image_index);
306 const void *(*_dyld_get_image_header_fn)(unsigned int image_index);
307 const void *(*NSLookupSymbolInImage_fn)(const void *image, const char *symbolName, unsigned int options);
308 void *(*NSAddressOfSymbol_fn)(const void *symbol);
310 // Find some dyld functions.
311 _dyld_func_lookup("__dyld_image_count",
312 (unsigned long *)&_dyld_image_count_fn);
313 _dyld_func_lookup("__dyld_get_image_name",
314 (unsigned long *)&_dyld_get_image_name_fn);
315 _dyld_func_lookup("__dyld_get_image_header",
316 (unsigned long *)&_dyld_get_image_header_fn);
317 _dyld_func_lookup("__dyld_NSLookupSymbolInImage",
318 (unsigned long *)&NSLookupSymbolInImage_fn);
319 _dyld_func_lookup("__dyld_NSAddressOfSymbol",
320 (unsigned long *)&NSAddressOfSymbol_fn);
322 // If any of the dyld functions don't exist, assume we're
323 // on a post-Panther dyld and silently do nothing.
324 if (!_dyld_image_count_fn) return;
325 if (!_dyld_get_image_name_fn) return;
326 if (!_dyld_get_image_header_fn) return;
327 if (!NSLookupSymbolInImage_fn) return;
328 if (!NSAddressOfSymbol_fn) return;
330 // Search for an image whose library name starts with "libobjc".
331 count = (*_dyld_image_count_fn)();
332 for (i = 0; i < count; i++) {
333 const void *image;
334 const char *path = (*_dyld_get_image_name_fn)(i);
335 const char *base = crt_basename(path);
336 if (!crt_strbeginswith(base, "libobjc")) continue;
338 // Call _objcInit() if library exports it.
339 if ((image = (*_dyld_get_image_header_fn)(i))) {
340 const void *symbol;
341 // 4 == NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
342 if ((symbol = (*NSLookupSymbolInImage_fn)(image,"__objcInit",4))) {
343 void (*_objcInit_fn)(void) =
344 (void(*)(void))(*NSAddressOfSymbol_fn)(symbol);
345 if (_objcInit_fn) {
346 (*_objcInit_fn)();
347 break;
354 #endif /* __DYNAMIC__ && __ppc__ */
356 #endif /* __DYNAMIC__ && OLD_LIBSYSTEM_SUPPORT */