]>
Commit | Line | Data |
---|---|---|
0959b6d4 A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
39a8cd10 | 3 | * Copyright (c) 2004-2008 Apple Inc. All rights reserved. |
0959b6d4 A |
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 | ||
bac542e6 A |
25 | #define __STDC_LIMIT_MACROS |
26 | #include <stdint.h> | |
0959b6d4 A |
27 | #include <stddef.h> |
28 | #include <string.h> | |
bac542e6 | 29 | #include <stdlib.h> |
cf998323 | 30 | #include <sys/mman.h> |
0959b6d4 | 31 | #include <mach/mach.h> |
bac542e6 | 32 | |
cf998323 A |
33 | #include "dyld2.h" |
34 | #include "dyldSyscallInterface.h" | |
35 | #include "MachOAnalyzer.h" | |
36 | #include "Tracing.h" | |
6cae9b63 | 37 | |
cf998323 A |
38 | // from libc.a |
39 | extern "C" void mach_init(); | |
40 | extern "C" void __guard_setup(const char* apple[]); | |
bc3b7c8c | 41 | extern "C" void _subsystem_init(const char* apple[]); |
6cae9b63 | 42 | |
cf998323 A |
43 | // from dyld_debugger.cpp |
44 | extern void syncProcessInfo(); | |
2fd3f4e8 | 45 | |
2fd3f4e8 | 46 | const dyld::SyscallHelpers* gSyscallHelpers = NULL; |
bac542e6 A |
47 | |
48 | ||
0959b6d4 A |
49 | // |
50 | // Code to bootstrap dyld into a runnable state | |
51 | // | |
52 | // | |
53 | ||
54 | namespace dyldbootstrap { | |
55 | ||
56 | ||
cf998323 A |
57 | // currently dyld has no initializers, but if some come back, set this to non-zero |
58 | #define DYLD_INITIALIZER_SUPPORT 0 | |
59 | ||
2fd3f4e8 A |
60 | |
61 | #if DYLD_INITIALIZER_SUPPORT | |
62 | ||
0959b6d4 A |
63 | typedef void (*Initializer)(int argc, const char* argv[], const char* envp[], const char* apple[]); |
64 | ||
2fd3f4e8 A |
65 | extern const Initializer inits_start __asm("section$start$__DATA$__mod_init_func"); |
66 | extern const Initializer inits_end __asm("section$end$__DATA$__mod_init_func"); | |
67 | ||
0959b6d4 A |
68 | // |
69 | // For a regular executable, the crt code calls dyld to run the executables initializers. | |
70 | // For a static executable, crt directly runs the initializers. | |
71 | // dyld (should be static) but is a dynamic executable and needs this hack to run its own initializers. | |
72 | // We pass argc, argv, etc in case libc.a uses those arguments | |
73 | // | |
cf998323 | 74 | static void runDyldInitializers(int argc, const char* argv[], const char* envp[], const char* apple[]) |
0959b6d4 | 75 | { |
2fd3f4e8 A |
76 | for (const Initializer* p = &inits_start; p < &inits_end; ++p) { |
77 | (*p)(argc, argv, envp, apple); | |
0959b6d4 A |
78 | } |
79 | } | |
2fd3f4e8 | 80 | #endif // DYLD_INITIALIZER_SUPPORT |
0959b6d4 | 81 | |
412ebb8e A |
82 | |
83 | // | |
cf998323 A |
84 | // On disk, all pointers in dyld's DATA segment are chained together. |
85 | // They need to be fixed up to be real pointers to run. | |
0959b6d4 | 86 | // |
cf998323 | 87 | static void rebaseDyld(const dyld3::MachOLoaded* dyldMH) |
0959b6d4 | 88 | { |
cf998323 A |
89 | // walk all fixups chains and rebase dyld |
90 | const dyld3::MachOAnalyzer* ma = (dyld3::MachOAnalyzer*)dyldMH; | |
91 | assert(ma->hasChainedFixups()); | |
92 | uintptr_t slide = (long)ma; // all fixup chain based images have a base address of zero, so slide == load address | |
93 | __block Diagnostics diag; | |
94 | ma->withChainStarts(diag, 0, ^(const dyld_chained_starts_in_image* starts) { | |
95 | ma->fixupAllChainedFixups(diag, starts, slide, dyld3::Array<const void*>(), nullptr); | |
96 | }); | |
97 | diag.assertNoError(); | |
98 | ||
99 | // now that rebasing done, initialize mach/syscall layer | |
100 | mach_init(); | |
101 | ||
102 | // <rdar://47805386> mark __DATA_CONST segment in dyld as read-only (once fixups are done) | |
103 | ma->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& info, bool& stop) { | |
104 | if ( info.readOnlyData ) { | |
105 | ::mprotect(((uint8_t*)(dyldMH))+info.vmAddr, (size_t)info.vmSize, VM_PROT_READ); | |
6cae9b63 | 106 | } |
cf998323 | 107 | }); |
0959b6d4 A |
108 | } |
109 | ||
3d7c199a | 110 | |
bac542e6 | 111 | |
0959b6d4 A |
112 | // |
113 | // This is code to bootstrap dyld. This work in normally done for a program by dyld and crt. | |
114 | // In dyld we have to do this manually. | |
115 | // | |
cf998323 A |
116 | uintptr_t start(const dyld3::MachOLoaded* appsMachHeader, int argc, const char* argv[], |
117 | const dyld3::MachOLoaded* dyldsMachHeader, uintptr_t* startGlue) | |
0959b6d4 | 118 | { |
cf998323 A |
119 | |
120 | // Emit kdebug tracepoint to indicate dyld bootstrap has started <rdar://46878536> | |
121 | dyld3::kdebug_trace_dyld_marker(DBG_DYLD_TIMING_BOOTSTRAP_START, 0, 0, 0, 0); | |
122 | ||
0959b6d4 A |
123 | // if kernel had to slide dyld, we need to fix up load sensitive locations |
124 | // we have to do this before using any global variables | |
cf998323 | 125 | rebaseDyld(dyldsMachHeader); |
0959b6d4 | 126 | |
0959b6d4 A |
127 | // kernel sets up env pointer to be just past end of agv array |
128 | const char** envp = &argv[argc+1]; | |
129 | ||
130 | // kernel sets up apple pointer to be just past end of envp array | |
131 | const char** apple = envp; | |
132 | while(*apple != NULL) { ++apple; } | |
133 | ++apple; | |
134 | ||
2fd3f4e8 A |
135 | // set up random value for stack canary |
136 | __guard_setup(apple); | |
137 | ||
138 | #if DYLD_INITIALIZER_SUPPORT | |
0959b6d4 | 139 | // run all C++ initializers inside dyld |
cf998323 | 140 | runDyldInitializers(argc, argv, envp, apple); |
2fd3f4e8 A |
141 | #endif |
142 | ||
bc3b7c8c A |
143 | _subsystem_init(apple); |
144 | ||
0959b6d4 | 145 | // now that we are done bootstrapping dyld, call dyld's main |
cf998323 A |
146 | uintptr_t appsSlide = appsMachHeader->getSlide(); |
147 | return dyld::_main((macho_header*)appsMachHeader, appsSlide, argc, argv, envp, apple, startGlue); | |
0959b6d4 A |
148 | } |
149 | ||
150 | ||
cf998323 | 151 | #if TARGET_OS_SIMULATOR |
2fd3f4e8 A |
152 | |
153 | extern "C" uintptr_t start_sim(int argc, const char* argv[], const char* envp[], const char* apple[], | |
cf998323 | 154 | const dyld3::MachOLoaded* mainExecutableMH, const dyld3::MachOLoaded* dyldMH, uintptr_t dyldSlide, |
2fd3f4e8 A |
155 | const dyld::SyscallHelpers*, uintptr_t* startGlue); |
156 | ||
cf998323 | 157 | |
2fd3f4e8 | 158 | uintptr_t start_sim(int argc, const char* argv[], const char* envp[], const char* apple[], |
cf998323 | 159 | const dyld3::MachOLoaded* mainExecutableMH, const dyld3::MachOLoaded* dyldSimMH, uintptr_t dyldSlide, |
2fd3f4e8 A |
160 | const dyld::SyscallHelpers* sc, uintptr_t* startGlue) |
161 | { | |
cf998323 A |
162 | // save table of syscall pointers |
163 | gSyscallHelpers = sc; | |
2fd3f4e8 | 164 | |
cf998323 A |
165 | // dyld_sim uses chained rebases, so it always need to be fixed up |
166 | rebaseDyld(dyldSimMH); | |
2fd3f4e8 A |
167 | |
168 | // set up random value for stack canary | |
169 | __guard_setup(apple); | |
170 | ||
171 | // setup gProcessInfo to point to host dyld's struct | |
172 | dyld::gProcessInfo = (struct dyld_all_image_infos*)(sc->getProcessInfo()); | |
173 | syncProcessInfo(); | |
174 | ||
175 | // now that we are done bootstrapping dyld, call dyld's main | |
cf998323 A |
176 | uintptr_t appsSlide = mainExecutableMH->getSlide(); |
177 | return dyld::_main((macho_header*)mainExecutableMH, appsSlide, argc, argv, envp, apple, startGlue); | |
2fd3f4e8 A |
178 | } |
179 | #endif | |
0959b6d4 A |
180 | |
181 | ||
182 | } // end of namespace | |
183 | ||
184 | ||
185 | ||
186 |