2 * Copyright (c) 1999-2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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
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
40 * Global data definitions (initialized data).
43 const char** NXArgv
= NULL
;
44 const char** environ
= NULL
;
45 const char* __progname
= NULL
;
48 extern void* __dso_handle
;
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
};
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);
132 asm(".comm __cplus_init, 4");
133 extern void _cplus_init(void);
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
;
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
);
151 extern void moninit(void);
152 static void _mcleanup(void);
153 extern void monitor(char *lowpc
,char *highpc
,char *buf
,int bufsiz
,int nfunc
);
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);
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.
174 _start(int argc
, const char* argv
[], const char* envp
[])
182 // initialize global variables
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 */ }
191 // initialize libSystem
192 if ( mach_init_routine
!= 0 )
193 (void) mach_init_routine();
194 if ( _cthread_init_routine
!= 0 )
195 (*_cthread_init_routine
)();
198 __keymgr_dwarf2_register_sections ();
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 ();
210 if(*((int *)_cplus_init
) != 0)
216 * Call into dyld to run all initializers. This must be done
219 _dyld_func_lookup("__dyld_make_delayed_module_initializer_calls",
220 (unsigned long *)&init
);
224 #if __DYNAMIC__ && __ppc__
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
239 _dyld_func_lookup("__dyld_mod_term_funcs", (unsigned long *)&term
);
244 // clear errno, so main() starts fresh
247 // call main() and return to exit()
248 exit(main(argc
, argv
, envp
, apple
));
253 * For profiling the routine _mcleanup gets registered with atexit so monitor(0)
267 crt_basename(const char *path
)
270 const char *last
= path
;
272 for (s
= path
; *s
!= '\0'; s
++) {
273 if (*s
== '/') last
= s
+1;
279 #if __DYNAMIC__ && __ppc__
282 crt_strbeginswith(const char *s1
, const char *s2
)
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.
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
++) {
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
))) {
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
);
354 #endif /* __DYNAMIC__ && __ppc__ */
356 #endif /* __DYNAMIC__ && OLD_LIBSYSTEM_SUPPORT */