]>
git.saurik.com Git - apple/dyld.git/blob - testing/test-cases/kernel-helpers.h
3 #include <mach-o/fixup-chains.h>
4 #include <mach-o/loader.h>
6 #include "kernel-fixups.h"
8 #ifndef LC_FILESET_ENTRY
9 #define LC_FILESET_ENTRY (0x35 | LC_REQ_DYLD) /* used with fileset_entry_command */
10 struct fileset_entry_command
{
11 uint32_t cmd
; /* LC_FILESET_ENTRY */
12 uint32_t cmdsize
; /* includes id string */
13 uint64_t vmaddr
; /* memory address of the dylib */
14 uint64_t fileoff
; /* file offset of the dylib */
15 union lc_str entry_id
; /* contained entry id */
16 uint32_t reserved
; /* entry_id is 32-bits long, so this is the reserved padding */
20 typedef int (* ModInitLogFunc
)( const char *, ...);
21 static const int LogModInits
= 0 ;
23 struct TestRunnerFunctions
;
24 typedef int (* InitializerFunc
)( const TestRunnerFunctions
*);
27 __attribute__ (( section (( "__HIB, __text" ))))
29 __attribute__ (( section (( "__TEXT_EXEC, __text" ))))
31 static int getSlide ( const struct mach_header
* mh
, ModInitLogFunc logFunc
,
33 uint64_t textVMAddr
= 0 ;
36 logFunc ( "[LOG] kernel-slide: mh %p \n " , mh
);
40 logFunc ( "[LOG] kernel-slide: parsing load commands \n " );
43 const struct load_command
* startCmds
= 0 ;
44 if ( mh
-> magic
== MH_MAGIC_64
)
45 startCmds
= ( struct load_command
*)(( char *) mh
+ sizeof ( struct mach_header_64
));
46 else if ( mh
-> magic
== MH_MAGIC
)
47 startCmds
= ( struct load_command
*)(( char *) mh
+ sizeof ( struct mach_header
));
49 const uint32_t * h
= ( uint32_t *) mh
;
50 //diag.error("file does not start with MH_MAGIC[_64]: 0x%08X 0x%08X", h[0], h [1]);
51 return 1 ; // not a mach-o file
53 const struct load_command
* const cmdsEnd
= ( struct load_command
*)(( char *) startCmds
+ mh
-> sizeofcmds
);
54 const struct load_command
* cmd
= startCmds
;
55 for ( uint32_t i
= 0 ; i
< mh
-> ncmds
; ++ i
) {
57 logFunc ( "[LOG] kernel-slide: parsing load command %d with cmd=0x %x \n " , i
, cmd
-> cmd
);
59 const struct load_command
* nextCmd
= ( struct load_command
*)(( char *) cmd
+ cmd
-> cmdsize
);
60 if ( cmd
-> cmdsize
< 8 ) {
61 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) too small", i, this->ncmds, cmd, this, cmd->cmdsize);
64 if ( ( nextCmd
> cmdsEnd
) || ( nextCmd
< startCmds
) ) {
65 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) is too large, load commands end at %p", i, this->ncmds, cmd, this, cmd->cmdsize, cmdsEnd);
68 if ( cmd
-> cmd
== LC_SEGMENT_64
) {
69 const struct segment_command_64
* seg
= ( const struct segment_command_64
*) cmd
;
70 if ( areEqual ( seg
-> segname
, "__TEXT" ) ) {
71 textVMAddr
= seg
-> vmaddr
;
77 * slide
= ( uintptr_t ) mh
- textVMAddr
;
82 __attribute__ (( section (( "__HIB, __text" ))))
84 __attribute__ (( section (( "__TEXT_EXEC, __text" ))))
86 static int runAllModInitFunctions ( const struct mach_header
* mh
, ModInitLogFunc logFunc
,
87 const TestRunnerFunctions
* funcs
) {
89 if ( getSlide ( mh
, logFunc
, & slide
) != 0 ) {
93 const struct load_command
* startCmds
= 0 ;
94 if ( mh
-> magic
== MH_MAGIC_64
)
95 startCmds
= ( struct load_command
*)(( char *) mh
+ sizeof ( struct mach_header_64
));
96 else if ( mh
-> magic
== MH_MAGIC
)
97 startCmds
= ( struct load_command
*)(( char *) mh
+ sizeof ( struct mach_header
));
99 const uint32_t * h
= ( uint32_t *) mh
;
100 //diag.error("file does not start with MH_MAGIC[_64]: 0x%08X 0x%08X", h[0], h [1]);
101 return 1 ; // not a mach-o file
104 const struct load_command
* const cmdsEnd
= ( struct load_command
*)(( char *) startCmds
+ mh
-> sizeofcmds
);
105 const struct load_command
* cmd
= startCmds
;
106 for ( uint32_t i
= 0 ; i
< mh
-> ncmds
; ++ i
) {
108 logFunc ( "[LOG] kernel-mod-inits: parsing load command %d with cmd=0x %x \n " , i
, cmd
-> cmd
);
110 const struct load_command
* nextCmd
= ( struct load_command
*)(( char *) cmd
+ cmd
-> cmdsize
);
111 if ( cmd
-> cmdsize
< 8 ) {
112 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) too small", i, this->ncmds, cmd, this, cmd->cmdsize);
115 if ( ( nextCmd
> cmdsEnd
) || ( nextCmd
< startCmds
) ) {
116 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) is too large, load commands end at %p", i, this->ncmds, cmd, this, cmd->cmdsize, cmdsEnd);
119 if ( cmd
-> cmd
== LC_SEGMENT_64
) {
120 const struct segment_command_64
* seg
= ( const struct segment_command_64
*) cmd
;
121 const struct section_64
* const sectionsStart
= ( struct section_64
*)(( char *) seg
+ sizeof ( struct segment_command_64
));
122 const struct section_64
* const sectionsEnd
= & sectionsStart
[ seg
-> nsects
];
123 for ( const struct section_64
* sect
= sectionsStart
; sect
< sectionsEnd
; ++ sect
) {
124 const uint8_t type
= sect
-> flags
& SECTION_TYPE
;
126 logFunc ( "[LOG] kernel-mod-inits: section: %s %s \n " , sect
-> segname
, sect
-> sectname
);
128 if ( type
== S_MOD_INIT_FUNC_POINTERS
) {
129 InitializerFunc
* inits
= ( InitializerFunc
*)( sect
-> addr
+ slide
);
130 const uintptr_t count
= sect
-> size
/ sizeof ( uintptr_t );
131 // Ensure __mod_init_func section is within segment
132 if ( ( sect
-> addr
< seg
-> vmaddr
) || ( sect
-> addr
+ sect
-> size
> seg
-> vmaddr
+ seg
-> vmsize
) || ( sect
-> addr
+ sect
-> size
< sect
-> addr
) ) {
133 logFunc ( "[LOG] kernel-mod-inits: __mod_init_funcs section has malformed address range \n " );
136 for ( uintptr_t j
= 0 ; j
< count
; ++ j
) {
137 InitializerFunc func
= inits
[ j
];
138 #if __has_feature(ptrauth_calls)
139 func
= ( InitializerFunc
) __builtin_ptrauth_sign_unauthenticated (( void *) func
, ptrauth_key_asia
, 0 );
142 logFunc ( "[LOG] kernel-mod-inits: running mod init %p \n " , ( const void *) func
);
144 int initResult
= func ( funcs
);
145 if ( initResult
!= 0 ) {
146 logFunc ( "[LOG] kernel-mod-inits: mod init %p , result = %d \n " , ( const void *) func
, initResult
);
160 __attribute__ (( section (( "__HIB, __text" ))))
162 __attribute__ (( section (( "__TEXT_EXEC, __text" ))))
164 static int runAllModInitFunctionsForAppCache ( const struct mach_header
* appCacheMH
, ModInitLogFunc logFunc
,
165 const TestRunnerFunctions
* funcs
) {
167 if ( getSlide ( appCacheMH
, logFunc
, & slide
) != 0 ) {
172 logFunc ( "[LOG] mod-init: appCacheMH %p \n " , appCacheMH
);
176 logFunc ( "[LOG] mod-init: parsing load commands \n " );
179 const struct load_command
* startCmds
= 0 ;
180 if ( appCacheMH
-> magic
== MH_MAGIC_64
)
181 startCmds
= ( struct load_command
*)(( char *) appCacheMH
+ sizeof ( struct mach_header_64
));
182 else if ( appCacheMH
-> magic
== MH_MAGIC
)
183 startCmds
= ( struct load_command
*)(( char *) appCacheMH
+ sizeof ( struct mach_header
));
185 const uint32_t * h
= ( uint32_t *) appCacheMH
;
186 //diag.error("file does not start with MH_MAGIC[_64]: 0x%08X 0x%08X", h[0], h [1]);
187 return 1 ; // not a mach-o file
189 const struct load_command
* const cmdsEnd
= ( struct load_command
*)(( char *) startCmds
+ appCacheMH
-> sizeofcmds
);
190 const struct load_command
* cmd
= startCmds
;
191 for ( uint32_t i
= 0 ; i
< appCacheMH
-> ncmds
; ++ i
) {
193 logFunc ( "[LOG] mod-init: parsing load command %d with cmd=0x %x \n " , i
, cmd
-> cmd
);
195 const struct load_command
* nextCmd
= ( struct load_command
*)(( char *) cmd
+ cmd
-> cmdsize
);
196 if ( cmd
-> cmdsize
< 8 ) {
197 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) too small", i, this->ncmds, cmd, this, cmd->cmdsize);
200 if ( ( nextCmd
> cmdsEnd
) || ( nextCmd
< startCmds
) ) {
201 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) is too large, load commands end at %p", i, this->ncmds, cmd, this, cmd->cmdsize, cmdsEnd);
204 if ( cmd
-> cmd
== LC_FILESET_ENTRY
) {
205 const struct fileset_entry_command
* app_cache_cmd
= ( const struct fileset_entry_command
*) cmd
;
206 const char * name
= ( char *) app_cache_cmd
+ app_cache_cmd
-> entry_id
. offset
;
207 const struct mach_header
* mh
= ( const struct mach_header
*)( app_cache_cmd
-> vmaddr
+ slide
);
209 logFunc ( "[LOG] mod-init: Running mod inits for %p : %s \n " , mh
, name
);
211 int result
= runAllModInitFunctions ( mh
, logFunc
, funcs
);
223 __attribute__ (( section (( "__HIB, __text" ))))
225 __attribute__ (( section (( "__TEXT_EXEC, __text" ))))
227 static int slideKextsInsideKernelCollection ( const struct mach_header
* appCacheMH
, const void * basePointers
[ 4 ],
228 FixupsLogFunc logFunc
, const TestRunnerFunctions
* funcs
) {
229 uintptr_t slideAmount
= 0 ;
230 if ( getSlide ( appCacheMH
, logFunc
, & slideAmount
) != 0 ) {
235 logFunc ( "[LOG] slide-pageable: appCacheMH %p \n " , appCacheMH
);
239 logFunc ( "[LOG] slide-pageable: parsing load commands \n " );
242 const struct load_command
* startCmds
= 0 ;
243 if ( appCacheMH
-> magic
== MH_MAGIC_64
)
244 startCmds
= ( struct load_command
*)(( char *) appCacheMH
+ sizeof ( struct mach_header_64
));
245 else if ( appCacheMH
-> magic
== MH_MAGIC
)
246 startCmds
= ( struct load_command
*)(( char *) appCacheMH
+ sizeof ( struct mach_header
));
248 const uint32_t * h
= ( uint32_t *) appCacheMH
;
249 //diag.error("file does not start with MH_MAGIC[_64]: 0x%08X 0x%08X", h[0], h [1]);
250 return 1 ; // not a mach-o file
252 const struct load_command
* const cmdsEnd
= ( struct load_command
*)(( char *) startCmds
+ appCacheMH
-> sizeofcmds
);
253 const struct load_command
* cmd
= startCmds
;
254 for ( uint32_t i
= 0 ; i
< appCacheMH
-> ncmds
; ++ i
) {
256 logFunc ( "[LOG] slide-pageable: parsing load command %d with cmd=0x %x \n " , i
, cmd
-> cmd
);
258 const struct load_command
* nextCmd
= ( struct load_command
*)(( char *) cmd
+ cmd
-> cmdsize
);
259 if ( cmd
-> cmdsize
< 8 ) {
260 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) too small", i, this->ncmds, cmd, this, cmd->cmdsize);
263 if ( ( nextCmd
> cmdsEnd
) || ( nextCmd
< startCmds
) ) {
264 //diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) is too large, load commands end at %p", i, this->ncmds, cmd, this, cmd->cmdsize, cmdsEnd);
267 if ( cmd
-> cmd
== LC_FILESET_ENTRY
) {
268 const struct fileset_entry_command
* app_cache_cmd
= ( const struct fileset_entry_command
*) cmd
;
269 const char * name
= ( char *) app_cache_cmd
+ app_cache_cmd
-> entry_id
. offset
;
270 const struct mach_header
* mh
= ( const struct mach_header
*)( app_cache_cmd
-> vmaddr
+ slideAmount
);
272 logFunc ( "[LOG] slide-pageable: Sliding %p : %s \n " , mh
, name
);
274 int slideReturnCode
= slide ( mh
, basePointers
, logFunc
);
275 if ( slideReturnCode
!= 0 ) {
276 FAIL ( "mh slide = %d \n " , slideReturnCode
);