1/* 2 * Copyright (c) 1999-2008 Apple Inc. All rights reserved. 3 * 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. 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 OR NON- INFRINGEMENT. Please see the 19 * License for the specific language governing rights and limitations 20 * under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24/* 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: 28 * 29 * File Dedined Macros Purpose 30 * crt1.o __DYNAMIC__ startup for programs compiled -dynamic 31 * gcrt1.o __DYNAMIC__, GCRT profiling startup, programs compiled -dynamic 32 * 33 * crt0.o startup for programs compiled -static 34 * 35 */ 36 37#include <stddef.h> 38 39/* 40 * Global data definitions (initialized data). 41 */ 42int NXArgc = 0; 43const char** NXArgv = NULL; 44const char** environ = NULL; 45const char* __progname = NULL; 46 47#if ADD_PROGRAM_VARS 48extern void* __dso_handle; 49struct ProgramVars 50{ 51 void* mh; 52 int* NXArgcPtr; 53 const char*** NXArgvPtr; 54 const char*** environPtr; 55 const char** __prognamePtr; 56}; 57__attribute__((used)) static struct ProgramVars pvars 58__attribute__ ((section ("__DATA,__program_vars"))) = { &__dso_handle, &NXArgc, &NXArgv, &environ, &__progname }; 59 60#endif 61 62 63/* 64 * This file is not needed for executables targeting 10.5 or later 65 * start calls main() directly. 66 */ 67#if __DYNAMIC__ && OLD_LIBSYSTEM_SUPPORT 68/* 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. 78 */ 79asm(".desc _NXArgc, 0x10"); 80asm(".desc _NXArgv, 0x10"); 81asm(".desc _environ, 0x10"); 82asm(".desc __mh_execute_header, 0x10"); 83#if defined(__ppc__) || defined(__i386__) 84asm(".comm _catch_exception_raise, 4"); 85asm(".desc _catch_exception_raise, 0x10"); 86asm(".comm _catch_exception_raise_state, 4"); 87asm(".desc _catch_exception_raise_state, 0x10"); 88asm(".comm _catch_exception_raise_state_identity, 4"); 89asm(".desc _catch_exception_raise_state_identity, 0x10"); 90asm(".comm _do_mach_notify_dead_name, 4"); 91asm(".desc _do_mach_notify_dead_name, 0x10"); 92asm(".comm _do_seqnos_mach_notify_dead_name, 4"); 93asm(".desc _do_seqnos_mach_notify_dead_name, 0x10"); 94asm(".comm _do_mach_notify_no_senders, 4"); 95asm(".desc _do_mach_notify_no_senders, 0x10"); 96asm(".comm _do_seqnos_mach_notify_no_senders, 4"); 97asm(".desc _do_seqnos_mach_notify_no_senders, 0x10"); 98asm(".comm _do_mach_notify_port_deleted, 4"); 99asm(".desc _do_mach_notify_port_deleted, 0x10"); 100asm(".comm _do_seqnos_mach_notify_port_deleted, 4"); 101asm(".desc _do_seqnos_mach_notify_port_deleted, 0x10"); 102asm(".comm _do_mach_notify_send_once, 4"); 103asm(".desc _do_mach_notify_send_once, 0x10"); 104asm(".comm _do_seqnos_mach_notify_send_once, 4"); 105asm(".desc _do_seqnos_mach_notify_send_once, 0x10"); 106asm(".comm _clock_alarm_reply, 4"); 107asm(".desc _clock_alarm_reply, 0x10"); 108asm(".comm _receive_samples, 4"); 109asm(".desc _receive_samples, 0x10"); 110#endif /* __ppc__ || __i386__ */ 111asm(".desc ___progname, 0x10"); 112 113/* 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. 128 */ 129extern int (*mach_init_routine)(void); 130extern int (*_cthread_init_routine)(void); 131#if !__DYNAMIC__ 132asm(".comm __cplus_init, 4"); 133extern void _cplus_init(void); 134#endif 135#if __DYNAMIC__ && __ppc__ 136asm(".comm ___darwin_gcc3_preregister_frame_info, 4"); 137extern void __darwin_gcc3_preregister_frame_info (void); 138static void (*pointer_to__darwin_gcc3_preregister_frame_info)(void) = 139 __darwin_gcc3_preregister_frame_info; 140#endif 141 142/* 143 * Prototypes for routines that are called. 144 */ 145extern int main(int argc, const char* argv[], const char* envp[], const char* apple[]); 146extern void exit(int status) __attribute__ ((noreturn)); 147extern int atexit(void (*fcn)(void)); 148static const char* crt_basename(const char* path); 149 150#if GCRT 151extern void moninit(void); 152static void _mcleanup(void); 153extern void monitor(char *lowpc,char *highpc,char *buf,int bufsiz,int nfunc); 154#endif /* GCRT */ 155 156#if __DYNAMIC__ 157extern int _dyld_func_lookup(const char *dyld_func_name,unsigned long *address); 158extern void __keymgr_dwarf2_register_sections (void); 159#endif /* __DYNAMIC__ */ 160 161#if __DYNAMIC__ && __ppc__ 162static void _call_objcInit(void); 163#endif 164 165extern int errno; 166 167/* 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. 171 */ 172__private_extern__ 173void 174_start(int argc, const char* argv[], const char* envp[]) 175{ 176 const char** apple; 177#if __DYNAMIC__ 178 void (*term)(void); 179 void (*init)(void); 180#endif 181 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; 190 191 // initialize libSystem 192 if ( mach_init_routine != 0 ) 193 (void) mach_init_routine(); 194 if ( _cthread_init_routine != 0 ) 195 (*_cthread_init_routine)(); 196 197#ifdef __DYNAMIC__ 198 __keymgr_dwarf2_register_sections (); 199#endif 200 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 208 209#if !__DYNAMIC__ 210 if(*((int *)_cplus_init) != 0) 211 _cplus_init(); 212#endif 213 214#ifdef __DYNAMIC__ 215 /* 216 * Call into dyld to run all initializers. This must be done 217 * after mach_init() 218 */ 219 _dyld_func_lookup("__dyld_make_delayed_module_initializer_calls", 220 (unsigned long *)&init); 221 init(); 222#endif 223 224#if __DYNAMIC__ && __ppc__ 225 _call_objcInit(); 226#endif 227 228#ifdef GCRT 229 atexit(_mcleanup); 230 moninit(); 231#endif 232 233#ifdef __DYNAMIC__ 234 /* 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(). 238 */ 239 _dyld_func_lookup("__dyld_mod_term_funcs", (unsigned long *)&term); 240 if ( term != 0 ) 241 atexit(term); 242#endif 243 244 // clear errno, so main() starts fresh 245 errno = 0; 246 247 // call main() and return to exit() 248 exit(main(argc, argv, envp, apple)); 249} 250 251#if GCRT 252/* 253 * For profiling the routine _mcleanup gets registered with atexit so monitor(0) 254 * gets called. 255 */ 256static 257void 258_mcleanup( 259void) 260{ 261 monitor(0,0,0,0,0); 262} 263#endif /* GCRT */ 264 265static 266const char * 267crt_basename(const char *path) 268{ 269 const char *s; 270 const char *last = path; 271 272 for (s = path; *s != '\0'; s++) { 273 if (*s == '/') last = s+1; 274 } 275 276 return last; 277} 278 279#if __DYNAMIC__ && __ppc__ 280static 281int 282crt_strbeginswith(const char *s1, const char *s2) 283{ 284 int i; 285 286 for (i = 0; ; i++) { 287 if (s2[i] == '\0') return 1; 288 else if (s1[i] != s2[i]) return 0; 289 } 290} 291 292/* 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. 297 */ 298static 299void 300_call_objcInit(void) 301{ 302 unsigned int i, count; 303 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); 309 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); 321 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; 329 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; 337 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; 348 } 349 } 350 } 351 } 352} 353 354#endif /* __DYNAMIC__ && __ppc__ */ 355 356#endif /* __DYNAMIC__ && OLD_LIBSYSTEM_SUPPORT */ 357