Chameleon

Chameleon Commit Details

Date:2011-01-30 02:52:42 (13 years 2 months ago)
Author:Evan Lojewski
Commit:717
Parents: 716
Message:Module system fixes. Symbols.dylib now contains correct addresses for global symbols. KextPather only tries to patch dev ids with 0x433F or less, reenabled Resolution.dylib
Changes:
M/branches/meklort/i386/modules/Makefile
M/branches/meklort/i386/modules/Memory/spd.c
M/branches/meklort/i386/boot2/modules_support.s
M/branches/meklort/i386/modules/KextPatcher/kext_patcher.c
M/branches/meklort/i386/boot2/modules.c
M/branches/meklort/i386/modules/Resolution/Resolution.c
M/branches/meklort/i386/boot2/Makefile
M/branches/meklort/i386/boot2/modules.h

File differences

branches/meklort/i386/boot2/modules.c
33
44
55
6
7
8
69
710
811
912
1013
11
12
13
1414
1515
16
16
17
1718
1819
20
1921
2022
2123
......
3133
3234
3335
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
5136
5237
5338
......
6146
6247
6348
64
49
6550
6651
6752
......
9277
9378
9479
95
80
9681
9782
9883
......
121106
122107
123108
124
125109
126110
127111
......
149133
150134
151135
152
153
154
155136
156137
157138
......
161142
162143
163144
164
145
165146
166147
167148
......
171152
172153
173154
174
155
175156
176157
177158
......
180161
181162
182163
164
183165
184
166
185167
186168
187169
......
195177
196178
197179
180
198181
199182
200183
201184
202
203
204
205
206
185
186
187
188
189
207190
208
191
209192
210
211
193
212194
213
195
196
197
198
199
214200
215
216
217
201
218202
219
203
204
220205
221
222
223
224
206
207
225208
226
227
228
229
230
231
209
232210
233
234211
235
212
213
236214
215
216
217
218
219
220
221
222
223
237224
238225
239
240
241
242
243
244
226
245227
246228
247229
248230
249
250231
251
252
253
254
255
256
232
257233
258
259
260
234
235
236
237
261238
262
263
239
240
241
242
243
244
245
246
247
248
249
250
251
264252
265
266
267
268
269
270
271
272
273
274
275
276
277
253
278254
279
255
256
280257
281
282
258
283259
284
285
286
287
288
289
290
291
292
260
293261
294
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
295278
296
297
298
299
300
301
302
303
304
305
306
307
279
280
308281
309282
310283
311
312
313
314
315
316
317
318
284
319285
286
320287
288
289
290
291
292
293
294
295
296
297
298
299
321300
322
301
323302
324303
325
304
305
326306
327307
308
309
310
328311
329312
330313
......
342325
343326
344327
345
346
347
328
329
330
348331
349332
350333
......
353336
354337
355338
356
339
357340
358341
359342
360
343
361344
362345
363346
......
376359
377360
378361
379
380
381362
363
364
382365
383
384
385
386
387
366
367
368
369
370
388371
389372
390373
......
392375
393376
394377
395
396378
379
397380
398381
399
382
400383
401384
402385
......
430413
431414
432415
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
416
458417
459418
460419
......
485444
486445
487446
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
447
513448
514
515449
516450
517451
......
528462
529463
530464
531
465
532466
533467
534468
......
536470
537471
538472
539
473
540474
541475
542476
543477
544478
545
546
479
480
547481
548482
549
483
550484
485
551486
552487
553488
......
561496
562497
563498
564
499
565500
566
501
567502
568503
569504
570
571
505
506
572507
573508
574
509
575510
576511
577512
......
595530
596531
597532
598
533
599534
600535
601536
602537
538
539
540
541
603542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
604597
605598
606599
......
626619
627620
628621
629
630622
623
631624
632625
633626
......
647640
648641
649642
650
643
651644
652645
653646
......
661654
662655
663656
664
665
657
658
666659
667660
668661
......
705698
706699
707700
708
709701
702
710703
711704
712705
......
762755
763756
764757
765
758
766759
767760
768761
......
773766
774767
775768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
776784
777785
778786
......
783791
784792
785793
786
794
787795
788796
789797
790798
791799
792
800
793801
794
802
795803
796804
797805
......
814822
815823
816824
825
826
827
828
829
830
831
817832
818833
819834
......
834849
835850
836851
837
852
838853
839854
840855
841856
842857
843858
844
859
845860
846861
847862
848863
849864
850865
851
852
866
867
853868
854
869
855870
856871
857872
858873
859874
860875
861
876
862877
863878
864879
......
878893
879894
880895
881
896
882897
883898
884899
......
905920
906921
907922
908
909
910923
911924
912925
......
921934
922935
923936
924
925937
926938
927939
928
929
940
930941
931
932
942
943
944
933945
934946
935947
936
937
938
939
940
941
942
943
944
945
946
947
948
948
949
949950
950951
952
951953
952954
953955
954956
955
956
957
958957
959958
960959
......
964963
965964
966965
967
968
969
966
967
970968
971
969
970
971
972972
973973
974974
975
976
977
978
979
980
981
982
983
984
985
975
976
986977
987
988978
979
989980
981
990982
991983
992984
993
994
985
995986
996
987
988
989
997990
998991
999992
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
993
994
1011995
1012996
1013
1014997
998
1015999
10161000
10171001
1018
1002
10191003
10201004
10211005
......
10241008
10251009
10261010
1027
10281011
1012
10291013
10301014
10311015
......
10361020
10371021
10381022
1039
1040
1041
10421023
10431024
10441025
10451026
10461027
10471028
1048
1049
1050
1051
1052
1053
1054
1055
1056
1029
10571030
10581031
10591032
10601033
10611034
1062
1063
1064
1065
1066
1067
1068
1069
1070
1035
1036
10711037
10721038
10731039
......
10781044
10791045
10801046
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
10951047
10961048
10971049
10981050
1099
1051
11001052
11011053
11021054
11031055
1104
1056
11051057
11061058
1107
1059
11081060
11091061
11101062
11111063
1112
1064
11131065
11141066
11151067
1068
1069
1070
11161071
11171072
1118
1119
1120
1121
1122
1123
1124
1073
1074
1075
1076
1077
11251078
1126
1127
1128
1129
1130
1079
1080
1081
1082
1083
1084
11311085
1132
1086
1087
11331088
1134
1135
1089
1090
1091
1092
1093
1094
1095
1096
11361097
1137
1098
11381099
1139
1140
1141
1142
1143
1144
1145
1146
1100
11471101
1102
1103
11481104
1149
1150
1151
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
11521117
1153
1118
11541119
1155
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
11561134
11571135
11581136
1159
1137
1138
1139
11601140
11611141
11621142
11631143
1144
11641145
1165
1166
1146
1147
1148
1149
1150
11671151
1168
1169
1170
1171
1172
1173
1174
1152
1153
1154
11751155
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1156
1157
1158
11861159
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1160
1161
1162
1163
1164
11981165
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1166
12111167
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
12221178
12231179
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
12351180
1236
1237
1181
1182
12381183
1239
1240
1184
12411185
12421186
12431187
1244
1245
1246
1247
1248
1249
1188
12501189
1251
1252
1190
12531191
1254
1255
1256
1257
1258
1259
1192
1193
1194
12601195
1261
1262
1196
12631197
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1198
1199
12751200
1201
12761202
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1203
1204
13001205
13011206
13021207
1303
1304
1305
1306
1307
1308
1309
1208
1209
13101210
1311
1312
1313
1314
1315
1316
1211
13171212
1318
1319
1213
1214
13201215
1321
1322
1323
1324
1325
1326
1327
1328
1216
1217
13291218
1330
1331
1332
1333
1334
13351219
1220
13361221
1222
1223
1224
1225
13371226
13381227
13391228
1340
1341
1229
1230
1231
*
* TODO: Zero out bss if needed
*/
#ifndef DEBUG_MODULES
#define DEBUG_MODULES 0
#endif
#include "boot.h"
#include "bootstruct.h"
#include "modules.h"
#ifndef DEBUG_MODULES
#define DEBUG_MODULES 0
#endif
#if DEBUG_MODULES
#define DBG(x...)printf(x); getc()
#define DBG(x...)printf(x);
#define DBGPAUSE()getc()
#else
#define DBG(x...)
#define DBGPAUSE()
#endif
// NOTE: Global so that modules can link with this
unsigned int (*lookup_symbol)(const char*) = NULL;
#if DEBUG_MODULES
void print_hook_list()
{
printf("---Hook Table---\n");
moduleHook_t* hooks = moduleCallbacks;
while(hooks)
{
printf("Hook: %s\n", hooks->name);
hooks = hooks->next;
}
}
#endif
/*
* Initialize the module system by loading the Symbols.dylib module.
* Once loaded, locate the _lookup_symbol function so that internal
// Intialize module system
if(symbols_module_start == (void*)0xFFFFFFFF)
{
DBG("Module system not compiled in\n");
DBG("Module system not compiled in.\n"); DBGPAUSE();
load_module(SYMBOLS_MODULE);
lookup_symbol = (void*)lookup_all_symbols(SYMBOL_LOOKUP_SYMBOL);
}
else {
// The module does not have a valid start function
printf("Unable to start %s\n", SYMBOLS_MODULE);
printf("Unable to start %s\n", SYMBOLS_MODULE); DBGPAUSE();
getc();
}
return 0;
char* tmp = malloc(strlen(name) + 1);
strcpy(tmp, name);
DBG("Attempting to load %s\n", tmp);
if(!load_module(tmp))
{
// failed to load
// Check to see if the module has already been loaded
if(is_module_loaded(module))
{
// NOTE: Symbols.dylib tries to load twice, this catches it as well
// as when a module links with an already loaded module
DBG("Module %s already loaded\n", module);
return 1;
}
fh = open(modString, 0);
if(fh < 0)
{
printf("Unable to locate module %s\n", modString);
printf("Unable to locate module %s\n", modString); DBGPAUSE();
getc();
return 0;
}
if (moduleSize && read(fh, module_base, moduleSize) == moduleSize)
{
DBG("Module %s read in.\n", modString);
//DBG("Module %s read in.\n", modString);
// Module loaded into memory, parse it
module_start = parse_mach(module_base, &load_module, &add_symbol);
{
// Notify the system that it was laoded
module_loaded(module/*moduleName, moduleVersion, moduleCompat*/);
(*module_start)();// Start the module
DBG("Module %s Loaded.\n", module);
DBG("Module %s Loaded.\n", module); DBGPAUSE();
}
else {
// The module does not have a valid start function
getc();
}
close(fh);
return 1;
}
/*
*execute_hook( const char* name )
*name - Name of the module hook
*If any callbacks have been registered for this hook
*they will be executed now in the same order that the
*hooks were added.
* add_symbol
* This function adds a symbol from a module to the list of known symbols
* possibly change to a pointer and add this to the Symbol module so that it can
* adjust it's internal symbol list (sort) to optimize locating new symbols
* NOTE: returns the address if the symbol is "start", else returns 0xFFFFFFFF
*/
int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4)
long long add_symbol(char* symbol, long long addr, char is64)
{
DBG("Attempting to execute hook '%s'\n", name);
moduleHook_t* hooks = moduleCallbacks;
if(is64) return 0xFFFFFFFF; // Fixme
while(hooks && strcmp(name, hooks->name) < 0)
// This only can handle 32bit symbols
symbolList_t* entry;
//DBG("Adding symbol %s at 0x%X\n", symbol, addr);
if(!moduleSymbols)
{
//DBG("%s cmp %s = %d\n", name, hooks->name, strcmp(name, hooks->name));
hooks = hooks->next;
}
moduleSymbols = entry = malloc(sizeof(symbolList_t));
if(hooks && strcmp(name, hooks->name) == 0)
}
else
{
// Loop through all callbacks for this module
callbackList_t* callbacks = hooks->callbacks;
while(callbacks)
entry = moduleSymbols;
while(entry->next)
{
DBG("Executing '%s' with callback 0x%X.\n", name, callbacks->callback);
// Execute callback
callbacks->callback(arg1, arg2, arg3, arg4);
callbacks = callbacks->next;
DBG("Hook '%s' callback executed, next is 0x%X.\n", name, callbacks);
entry = entry->next;
}
DBG("Hook '%s' executed.\n", name);
return 1;
entry->next = malloc(sizeof(symbolList_t));
entry = entry->next;
}
entry->next = NULL;
entry->addr = (UInt32)addr;
entry->symbol = symbol;
if(strcmp(symbol, "start") == 0)
{
return addr;
}
else
{
DBG("No callbacks for '%s' hook.\n", name);
// Callbaack for this module doesn't exist;
//verbose("Unable execute hook '%s', no callbacks registered.\n", name);
//pause();
return 0;
return 0xFFFFFFFF; // fixme
}
}
/*
*register_hook_callback( const char* name, void(*callback)())
*name - Name of the module hook to attach to.
*callbacks - The funciton pointer that will be called when the
*hook is executed. When registering a new callback name, the callback is added sorted.
*NOTE: the hooks take four void* arguments.
*TODO: refactor
* print out the information about the loaded module
*/
void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*))
{
DBG("Adding callback for '%s' hook.\n", name);
void module_loaded(const char* name/*, UInt32 version, UInt32 compat*/)
{
// TODO: insert sorted
moduleList_t* new_entry = malloc(sizeof(moduleList_t));
moduleHook_t* newHook = malloc(sizeof(moduleHook_t));
if(!moduleCallbacks)
new_entry->next = loadedModules;
loadedModules = new_entry;
new_entry->module = (char*)name;
new_entry->version = 0; //version;
new_entry->compat = 0; //compat;
}
int is_module_loaded(const char* name)
{
// todo sorted search
moduleList_t* entry = loadedModules;
while(entry)
{
newHook->next = moduleCallbacks;
moduleCallbacks = newHook;
newHook->name = name;
newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));
newHook->callbacks->callback = callback;
newHook->callbacks->next = NULL;
}
else
{
moduleHook_t* hooks = moduleCallbacks;
while(hooks->next && strcmp(name, hooks->next->name) < 0)
if(strcmp(entry->module, name) == 0)
{
hooks = hooks->next;
DBG("Located module %s\n", name); DBGPAUSE();
return 1;
}
if(!hooks->next)
else
{
// Appent to the end
newHook->next = NULL;
hooks->next = newHook;
newHook->name = name;
newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));
newHook->callbacks->callback = callback;
newHook->callbacks->next = NULL;
entry = entry->next;
}
else if(strcmp(name, hooks->next->name) == 0)
}
DBG("Module %s not found\n", name); DBGPAUSE();
return 0;
}
// Look for symbols using the Smbols moduel function.
// If non are found, look through the list of module symbols
unsigned int lookup_all_symbols(const char* name)
{
unsigned int addr = 0xFFFFFFFF;
symbolList_t* entry = moduleSymbols;
while(entry)
{
if(strcmp(entry->symbol, name) == 0)
{
// We found the hook
// Hook alreday exists, add a callback to this hook
callbackList_t* callbacks = hooks->next->callbacks;
while(callbacks->next != NULL)
{
callbacks = callbacks->next;
}
// Add new entry to end of hook list.
callbacks->next = (callbackList_t*)malloc(sizeof(callbackList_t));
callbacks = callbacks->next;
callbacks->next = NULL;
callbacks->callback = callback;
//DBG("External symbol %s located at 0x%X\n", name, entry->addr);
return entry->addr;
}
else
{
// We are too far beyond the hook
newHook->next = hooks->next;
hooks->next = newHook;
newHook->name = name;
newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));
newHook->callbacks->callback = callback;
newHook->callbacks->next = NULL;
entry = entry->next;
}
}
if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF)
{
addr = lookup_symbol(name);
if(addr != 0xFFFFFFFF)
{
//DBG("Internal symbol %s located at 0x%X\n", name, addr);
return addr;
}
}
#if DEBUG_MODULES
print_hook_list();
verbose("Unable to locate symbol %s\n", name);
getc();
#endif
return 0xFFFFFFFF;
}
/********************************************************************************/
/*Macho Parser*/
/********************************************************************************/
/*
* Parse through a macho module. The module will be rebased and binded
// Module info
/*char* moduleName = NULL;
UInt32 moduleVersion = 0;
UInt32 moduleCompat = 0;
*/
UInt32 moduleVersion = 0;
UInt32 moduleCompat = 0;
*/
// TODO convert all of the structs to a union
struct load_command *loadCommand = NULL;
struct dylib_command* dylibCommand = NULL;
struct symtab_command* symtabCommand = NULL;
struct segment_command *segCommand = NULL;
struct segment_command_64 *segCommand64 = NULL;
//struct dysymtab_command* dysymtabCommand = NULL;
UInt32 binaryIndex = 0;
UInt16 cmd = 0;
// Parse through the load commands
if(((struct mach_header*)binary)->magic == MH_MAGIC)
{
getc();
return NULL;
}
/*if(((struct mach_header*)binary)->filetype != MH_DYLIB)
{
printf("Module is not a dylib. Unable to load.\n");
getc();
return NULL; // Module is in the incorrect format
}*/
{
printf("Module is not a dylib. Unable to load.\n");
getc();
return NULL; // Module is in the incorrect format
}*/
while(cmd < ((struct mach_header*)binary)->ncmds)
{
loadCommand = binary + binaryIndex;
UInt32 cmdSize = loadCommand->cmdsize;
switch ((loadCommand->cmd & 0x7FFFFFFF))
{
// TODO: sepeare function to handel appropriate sections
// TODO: sepeare function to handel appropriate sections
case LC_SYMTAB:
symtabCommand = binary + binaryIndex;
break;
}
}
}
else if(strcmp("__DATA", segCommand->segname) == 0)
{
UInt32 sectionIndex;
sectionIndex = sizeof(struct segment_command);
struct section *sect;
while(sectionIndex < segCommand->cmdsize)
{
sect = binary + binaryIndex + sectionIndex;
sectionIndex += sizeof(struct section);
if(strcmp("__bss", sect->sectname) == 0)
{
// __TEXT,__text found, save the offset and address for when looking for the calls.
//printf("__DATA,__bss found.\n"); getc();
break;
}
}
}
break;
case LC_SEGMENT_64:// 64bit macho's
segCommand64 = binary + binaryIndex;
break;
}
}
}
else if(strcmp("__DATA", segCommand->segname) == 0)
{
UInt32 sectionIndex;
sectionIndex = sizeof(struct segment_command_64);
struct section_64 *sect;
while(sectionIndex < segCommand->cmdsize)
{
sect = binary + binaryIndex + sectionIndex;
sectionIndex += sizeof(struct section);
if(strcmp("__bss", sect->sectname) == 0)
{
// __TEXT,__text found, save the offset and address for when looking for the calls.
//printf("__DATA,__bss found.\n"); getc();
break;
}
}
}
}
break;
case LC_DYSYMTAB:
{
char* name = malloc(strlen(module) + strlen(".dylib") + 1);
sprintf(name, "%s.dylib", module);
if (!dylib_loader(name))
{
free(name);
//return NULL;
}
}
break;
case LC_ID_DYLIB:
dylibCommand = binary + binaryIndex;
/*moduleName =binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));
moduleVersion =dylibCommand->dylib.current_version;
moduleCompat =dylibCommand->dylib.compatibility_version;
moduleVersion =dylibCommand->dylib.current_version;
moduleCompat =dylibCommand->dylib.compatibility_version;
*/
break;
case LC_DYLD_INFO:
//case LC_DYLD_INFO_ONLY:// compressed info, 10.6+ macho files, already handeled
// Bind and rebase info is stored here
dyldInfoCommand = binary + binaryIndex;
break;
default:
DBG("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);
break;
}
binaryIndex += cmdSize;
}
//if(!moduleName) return NULL;
// bind_macho uses the symbols.
module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbol_handler, is64);
// Rebase the module before binding it.
if(dyldInfoCommand && dyldInfoCommand->rebase_off)
{
// This should be changed to bind when a symbol is referened at runtime instead.
bind_macho(binary, (char*)dyldInfoCommand->lazy_bind_off, dyldInfoCommand->lazy_bind_size);
}
return module_start;
}
/*
* parse the symbol table
* Lookup any undefined symbols
*/
unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, long long, char), char is64)
{
// TODO: verify that the _TEXT,_text segment starts at the same locaiton in the file. If not
//subtract the vmaddress and add the actual file address back on. (NOTE: if compiled properly, not needed)
unsigned int module_start = 0xFFFFFFFF;
UInt32 symbolIndex = 0;
char* symbolString = base + (char*)symtabCommand->stroff;
//char* symbolTable = base + symtabCommand->symoff;
if(!is64)
{
struct nlist* symbolEntry = (void*)base + symtabCommand->symoff;
while(symbolIndex < symtabCommand->nsyms)
{
// If the symbol is exported by this module
if(symbolEntry->n_value &&
symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF)
{
// Module start located. Start is an alias so don't register it
module_start = base + symbolEntry->n_value;
}
symbolEntry++;
symbolIndex++;// TODO remove
}
}
else
{
struct nlist_64* symbolEntry = (void*)base + symtabCommand->symoff;
// NOTE First entry is *not* correct, but we can ignore it (i'm getting radar:// right now)
while(symbolIndex < symtabCommand->nsyms)
{
// If the symbol is exported by this module
if(symbolEntry->n_value &&
symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF)
{
// Module start located. Start is an alias so don't register it
module_start = base + symbolEntry->n_value;
}
symbolEntry++;
symbolIndex++;// TODO remove
}
}
return module_start;
}
// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp
void rebase_macho(void* base, char* rebase_stream, UInt32 size)
{
{
immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK;
opcode = rebase_stream[i] & REBASE_OPCODE_MASK;
switch(opcode)
{
case REBASE_OPCODE_DONE:
case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
// Locate address to begin rebasing
segmentAddress = 0;
struct segment_command* segCommand = NULL; // NOTE: 32bit only
unsigned int binIndex = 0;
index++;
}
while(index <= immediate);
segmentAddress = segCommand->fileoff;
tmp = 0;
segmentAddress += sizeof(void*);
}
break;
case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
tmp = 0;
bits = 0;
index = 0;
for (index = 0; index < tmp; ++index) {
rebase_location(base + segmentAddress, (char*)base, type);
segmentAddress += tmp2 + sizeof(void*);
}
}
inline void rebase_location(UInt32* location, char* base, int type)
{
switch(type)
{
case REBASE_TYPE_POINTER:
case REBASE_TYPE_TEXT_ABSOLUTE32:
*location += (UInt32)base;
break;
default:
break;
}
}
// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp
// NOTE: this uses 32bit values, and not 64bit values.
// There is apossibility that this could cause issues,
UInt8 immediate = 0;
UInt8 opcode = 0;
UInt8 type = 0;
UInt8 type = BIND_TYPE_POINTER;
UInt32 segmentAddress = 0;
UInt32 address = 0;
SInt32 addend = 0;// TODO: handle this
SInt32 addend = 0;
SInt32 libraryOrdinal = 0;
const char* symbolName = NULL;
UInt8 symboFlags = 0;
UInt32 symbolAddr = 0xFFFFFFFF;
switch(opcode)
{
case BIND_OPCODE_DONE:
// reset vars
type = BIND_TYPE_POINTER;
segmentAddress = 0;
address = 0;
addend = 0;
libraryOrdinal = 0;
symbolAddr = 0xFFFFFFFF;
//done = 1;
default:
break;
while(bind_stream[i] & 0x80);
//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: %d\n", libraryOrdinal);
break;
case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
// NOTE: this is wrong, fortunately we don't use it
libraryOrdinal = immediate ? (SInt8)(BIND_OPCODE_MASK | immediate) : immediate;
//printf("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);
break;
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
symboFlags = immediate;
symbolName = (char*)&bind_stream[++i];
i += strlen((char*)&bind_stream[i]);
//DBG("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X\n", symbolName, symboFlags);
//DBG("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X", symbolName, symboFlags);
symbolAddr = lookup_all_symbols(symbolName);
//DBG(", addr = 0x%X\n", symbolAddr);
break;
case BIND_OPCODE_SET_TYPE_IMM:
// Set bind type (pointer, absolute32, pcrel32)
type = immediate;
//DBG("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);
break;
case BIND_OPCODE_SET_ADDEND_SLEB:
case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
segmentAddress = 0;
// Locate address
struct segment_command* segCommand = NULL;// NOTE: 32bit only
while(bind_stream[i] & 0x80);
segmentAddress += tmp;
//DBG("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 0x%X\n", segmentAddress);
break;
case BIND_OPCODE_ADD_ADDR_ULEB:
while(bind_stream[i] & 0x80);
segmentAddress += tmp;
//DBG("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress);
break;
case BIND_OPCODE_DO_BIND:
//DBG("BIND_OPCODE_DO_BIND\n");
if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER)
if(symbolAddr != 0xFFFFFFFF)
{
// HACK(ish)
// Internal symbol, don't bind
address = segmentAddress + (UInt32)base;
bind_location((UInt32*)address, (char*)symbolAddr, addend, type);
}
else
{
//printf("Binding symbol %s, libraryOrdinal = %d, symboFlags = %d, type = %d\n", symbolName, libraryOrdinal, symboFlags, type);
if(symbolAddr != 0xFFFFFFFF)
{
address = segmentAddress + (UInt32)base;
bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);
}
else
{
printf("Unable to bind symbol %s, libraryOrdinal = %d, symboFlags = %d, type = %d\n", symbolName, libraryOrdinal, symboFlags, type);
getc();
}
printf("Unable to bind symbol %s, libraryOrdinal = %d, symboFlags = %d, type = %d\n", symbolName, libraryOrdinal, symboFlags, type);
getc();
}
segmentAddress += sizeof(void*);
break;
case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
//DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n");
// Read in offset
tmp = 0;
bits = 0;
bits += 7;
}
while(bind_stream[i] & 0x80);
if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER)
if(symbolAddr != 0xFFFFFFFF)
{
// Internal symbol, don't bind
address = segmentAddress + (UInt32)base;
bind_location((UInt32*)address, (char*)symbolAddr, addend, type);
}
else
{
if(symbolAddr != 0xFFFFFFFF)
{
address = segmentAddress + (UInt32)base;
bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);
}
else
{
printf("Unable to bind symbol %s\n", symbolName);
getc();
}
printf("Unable to bind symbol %s\n", symbolName);
getc();
}
segmentAddress += tmp + sizeof(void*);
segmentAddress += tmp + sizeof(void*);
break;
case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
//DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");
if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER)
if(symbolAddr != 0xFFFFFFFF)
{
// Internal symbol, don't bind
address = segmentAddress + (UInt32)base;
bind_location((UInt32*)address, (char*)symbolAddr, addend, type);
}
else
{
if(symbolAddr != 0xFFFFFFFF)
{
address = segmentAddress + (UInt32)base;
bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);
}
else
{
printf("Unable to bind symbol %s\n", symbolName);
getc();
}
printf("Unable to bind symbol %s\n", symbolName);
getc();
}
segmentAddress += (immediate * sizeof(void*)) + sizeof(void*);
break;
case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
tmp = 0;
bits = 0;
do
bits += 7;
}
while(bind_stream[i] & 0x80);
tmp2 = 0;
bits = 0;
do
while(bind_stream[i] & 0x80);
//DBG("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2);
if(symbolAddr != 0xFFFFFFFF)
{
for(index = 0; index < tmp; index++)
{
address = segmentAddress + (UInt32)base;
if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER)
{
// Internal symbol, don't bind
}
else
{
bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);
}
bind_location((UInt32*)address, (char*)symbolAddr, addend, type);
segmentAddress += tmp2 + sizeof(void*);
}
}
else
{
if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER)
{
// Internal symbol, don't bind
}
else
{
printf("Unable to bind symbol %s\n", symbolName);
getc();
}
printf("Unable to bind symbol %s\n", symbolName);
getc();
}
}
}
inline void rebase_location(UInt32* location, char* base, int type)
{
switch(type)
{
case REBASE_TYPE_POINTER:
case REBASE_TYPE_TEXT_ABSOLUTE32:
*location += (UInt32)base;
break;
default:
break;
}
}
inline void bind_location(UInt32* location, char* value, UInt32 addend, int type)
{
// do actual update
char* newValue = value + addend;
switch (type) {
case BIND_TYPE_POINTER:
case BIND_TYPE_TEXT_ABSOLUTE32:
break;
case BIND_TYPE_TEXT_PCREL32:
newValue -= ((UInt32)location + 4);
break;
default:
return;
}
//DBG("Binding 0x%X to 0x%X (was 0x%X)\n", location, newValue, *location);
*location = (UInt32)newValue;
}
/********************************************************************************/
/*Module Hook Interface*/
/********************************************************************************/
/*
* add_symbol
* This function adds a symbol from a module to the list of known symbols
* possibly change to a pointer and add this to the Symbol module so that it can
* adjust it's internal symbol list (sort) to optimize locating new symbols
* NOTE: returns the address if the symbol is "start", else returns 0xFFFFFFFF
*/
long long add_symbol(char* symbol, long long addr, char is64)
* Locate the symbol for an already loaded function and modify the beginning of
* the function to jump directly to the new one
* example: replace_function("_HelloWorld_start", &replacement_start);
*/
int replace_function(const char* symbol, void* newAddress)
{
if(is64) return 0xFFFFFFFF; // Fixme
// This only can handle 32bit symbols
symbolList_t* entry;
//DBG("Adding symbol %s at 0x%X\n", symbol, addr);
UInt32* jumpPointer = malloc(sizeof(UInt32*));
// TODO: look into using the next four bytes of the function instead
// Most functions should support this, as they probably will be at
// least 10 bytes long, but you never know, this is sligtly safer as
// function can be as small as 6 bytes.
UInt32 addr = lookup_all_symbols(symbol);
if(!moduleSymbols)
char* binary = (char*)addr;
if(addr != 0xFFFFFFFF)
{
moduleSymbols = entry = malloc(sizeof(symbolList_t));
//DBG("Replacing %s to point to 0x%x\n", symbol, newAddress);
*binary++ = 0xFF;// Jump
*binary++ = 0x25;// Long Jump
*((UInt32*)binary) = (UInt32)jumpPointer;
*jumpPointer = (UInt32)newAddress;
return 1;
}
else
else
{
entry = moduleSymbols;
while(entry->next)
{
entry = entry->next;
}
entry->next = malloc(sizeof(symbolList_t));
entry = entry->next;
return 0;
}
}
entry->next = NULL;
entry->addr = (UInt32)addr;
entry->symbol = symbol;
/*
*execute_hook( const char* name )
*name - Name of the module hook
*If any callbacks have been registered for this hook
*they will be executed now in the same order that the
*hooks were added.
*/
int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4)
{
DBG("Attempting to execute hook '%s'\n", name); DBGPAUSE();
moduleHook_t* hook = hook_exists(name);
if(strcmp(symbol, "start") == 0)
if(hook)
{
return addr;
// Loop through all callbacks for this module
callbackList_t* callbacks = hook->callbacks;
while(callbacks)
{
//DBG("Executing '%s' callback at 0x%X.\n", name, callbacks->callback);
// Execute callback
callbacks->callback(arg1, arg2, arg3, arg4);
callbacks = callbacks->next;
//DBG("Hook '%s' callback executed, next is 0x%X.\n", name, callbacks);
}
DBG("Hook '%s' executed.\n", name); DBGPAUSE();
return 1;
}
else
{
return 0xFFFFFFFF; // fixme
// Callback for this hook doesn't exist;
DBG("No callbacks for '%s' hook.\n", name);
return 0;
}
}
/*
* print out the information about the loaded module
*register_hook_callback( const char* name, void(*callback)())
*name - Name of the module hook to attach to.
*callbacks - The funciton pointer that will be called when the
*hook is executed. When registering a new callback name, the callback is added sorted.
*NOTE: the hooks take four void* arguments.
*/
void module_loaded(const char* name/*, UInt32 version, UInt32 compat*/)
{
// TODO: insert sorted
moduleList_t* new_entry = malloc(sizeof(moduleList_t));
new_entry->next = loadedModules;
loadedModules = new_entry;
void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*))
{
DBG("Adding callback for '%s' hook.\n", name); DBGPAUSE();
new_entry->module = (char*)name;
new_entry->version = 0; //version;
new_entry->compat = 0; //compat;
}
int is_module_loaded(const char* name)
{
// todo sorted search
moduleList_t* entry = loadedModules;
while(entry)
moduleHook_t* hook = hook_exists(name);
if(hook)
{
DBG("Comparing %s with %s\n", name, entry->module);
if(strcmp(entry->module, name) == 0)
{
DBG("Located module %s\n", name);
return 1;
}
else
{
entry = entry->next;
}
// append
callbackList_t* newCallback = malloc(sizeof(callbackList_t));
newCallback->next = hook->callbacks;
hook->callbacks = newCallback;
newCallback->callback = callback;
}
DBG("Module %s not found\n", name);
return 0;
}
// Look for symbols using the Smbols moduel function.
// If non are found, look through the list of module symbols
unsigned int lookup_all_symbols(const char* name)
{
unsigned int addr = 0xFFFFFFFF;
symbolList_t* entry = moduleSymbols;
while(entry)
else
{
if(strcmp(entry->symbol, name) == 0)
{
//DBG("External symbol %s located at 0x%X\n", name, entry->addr);
return entry->addr;
}
else
{
entry = entry->next;
}
// create new hook
moduleHook_t* newHook = malloc(sizeof(moduleHook_t));
newHook->name = name;
newHook->callbacks = malloc(sizeof(callbackList_t));
newHook->callbacks->callback = callback;
newHook->callbacks->next = NULL;
newHook->next = moduleCallbacks;
moduleCallbacks = newHook;
}
if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF)
{
addr = lookup_symbol(name);
if(addr != 0xFFFFFFFF)
{
//DBG("Internal symbol %s located at 0x%X\n", name, addr);
return addr;
}
}
#if DEBUG_MODULES
verbose("Unable to locate symbol %s\n", name);
getc();
//print_hook_list();
//getc();
#endif
return 0xFFFFFFFF;
}
/*
* parse the symbol table
* Lookup any undefined symbols
*/
unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, long long, char), char is64)
moduleHook_t* hook_exists(const char* name)
{
// TODO: verify that the _TEXT,_text segment starts at the same locaiton in the file. If not
//subtract the vmaddress and add the actual file address back on. (NOTE: if compiled properly, not needed)
moduleHook_t* hooks = moduleCallbacks;
unsigned int module_start = 0xFFFFFFFF;
UInt32 symbolIndex = 0;
char* symbolString = base + (char*)symtabCommand->stroff;
//char* symbolTable = base + symtabCommand->symoff;
if(!is64)
// look for a hook. If it exists, return the moduleHook_t*,
// If not, return NULL.
while(hooks)
{
struct nlist* symbolEntry = (void*)base + symtabCommand->symoff;
while(symbolIndex < symtabCommand->nsyms)
if(strcmp(name, hooks->name) == 0)
{
// If the symbol is exported by this module
if(symbolEntry->n_value &&
symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF)
{
// Module start located. Start is an alias so don't register it
module_start = base + symbolEntry->n_value;
}
symbolEntry++;
symbolIndex++;// TODO remove
//DBG("Located hook %s\n", name);
return hooks;
}
hooks = hooks->next;
}
else
{
struct nlist_64* symbolEntry = (void*)base + symtabCommand->symoff;
// NOTE First entry is *not* correct, but we can ignore it (i'm getting radar:// right now)
while(symbolIndex < symtabCommand->nsyms)
{
// If the symbol is exported by this module
if(symbolEntry->n_value &&
symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF)
{
// Module start located. Start is an alias so don't register it
module_start = base + symbolEntry->n_value;
}
symbolEntry++;
symbolIndex++;// TODO remove
}
}
return module_start;
//DBG("Hook %s does not exist\n", name);
return NULL;
}
/*
* Locate the symbol for an already loaded function and modify the beginning of
* the function to jump directly to the new one
* example: replace_function("_HelloWorld_start", &replacement_start);
*/
int replace_function(const char* symbol, void* newAddress)
#if DEBUG_MODULES
void print_hook_list()
{
UInt32* jumpPointer = malloc(sizeof(UInt32*));
// TODO: look into using the next four bytes of the function instead
// Most functions should support this, as they probably will be at
// least 10 bytes long, but you never know, this is sligtly safer as
// function can be as small as 6 bytes.
UInt32 addr = lookup_all_symbols(symbol);
printf("---Hook Table---\n");
char* binary = (char*)addr;
if(addr != 0xFFFFFFFF)
moduleHook_t* hooks = moduleCallbacks;
while(hooks)
{
DBG("Replacing %s to point to 0x%x\n", symbol, newAddress);
*binary++ = 0xFF;// Jump
*binary++ = 0x25;// Long Jump
*((UInt32*)binary) = (UInt32)jumpPointer;
*jumpPointer = (UInt32)newAddress;
return 1;
printf("Hook: %s\n", hooks->name);
hooks = hooks->next;
}
else
{
return 0;
}
}
#endif
/********************************************************************************/
/*dyld / Linker Interface*/
/********************************************************************************/
void dyld_stub_binder()
{
// TODO: actualy impliment this function (asm)
stop("ERROR: dyld_stub_binder was called, should have been take care of by the linker.\n");
}
printf("ERROR: dyld_stub_binder was called, should have been take care of by the linker.\n");
getc();
}
branches/meklort/i386/boot2/modules.h
6464
6565
6666
67
68
69
70
71
72
73
74
75
76
77
78
7967
80
81
82
83
8468
8569
8670
8771
8872
89
9073
91
92
93
94
9574
96
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
9791
9892
9993
100
101
94
95
96
97
10298
103
10499
105
106100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
107119
int init_module_system();
void load_all_modules();
/*
* Modules Interface
* execute_hook
*Exexutes a registered hook. All callbaks are
*called in the same order that they were added
*
* register_hook_callback
*registers a void function to be executed when a
*hook is executed.
*/
int execute_hook(const char* name, void*, void*, void*, void*);
void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*));
inline void rebase_location(UInt32* location, char* base, int type);
inline void bind_location(UInt32* location, char* value, UInt32 addend, int type);
void rebase_macho(void* base, char* rebase_stream, UInt32 size);
void bind_macho(void* base, char* bind_stream, UInt32 size);
int load_module(char* module);
int is_module_loaded(const char* name);
void module_loaded(const char* name/*, UInt32 version, UInt32 compat*/);
long long add_symbol(char* symbol, long long addr, char is64);
void* parse_mach(void* binary,
int(*dylib_loader)(char*),
long long(*symbol_handler)(char*, long long, char)
);
unsigned int handle_symtable(UInt32 base,
/********************************************************************************/
/*Symbol Functions*/
/********************************************************************************/
long longadd_symbol(char* symbol, long long addr, char is64);
unsigned intlookup_all_symbols(const char* name);
/********************************************************************************/
/*Macho Parser*/
/********************************************************************************/
void*parse_mach(void* binary,
int(*dylib_loader)(char*),
long long(*symbol_handler)(char*, long long, char));
unsigned inthandle_symtable(UInt32 base,
struct symtab_command* symtabCommand,
long long(*symbol_handler)(char*, long long, char),
char is64);
unsigned int lookup_all_symbols(const char* name);
voidrebase_macho(void* base, char* rebase_stream, UInt32 size);
inline voidrebase_location(UInt32* location, char* base, int type);
voidbind_macho(void* base, char* bind_stream, UInt32 size);
inline voidbind_location(UInt32* location, char* value, UInt32 addend, int type);
int replace_function(const char* symbol, void* newAddress);
//extern unsigned int (*lookup_symbol)(const char*);
/********************************************************************************/
/*Module Interface*/
/********************************************************************************/
intreplace_function(const char* symbol, void* newAddress);
intexecute_hook(const char* name, void*, void*, void*, void*);
voidregister_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*));
moduleHook_t*hook_exists(const char* name);
#if DEBUG_MODULES
voidprint_hook_list();
#endif
/********************************************************************************/
/*dyld Interface*/
/********************************************************************************/
void dyld_stub_binder();
#endif /* __BOOT_MODULES_H */
branches/meklort/i386/boot2/modules_support.s
11
22
33
4
4
#include <architecture/i386/asm_help.h>
LABEL(dyld_stub_binder)
ret
jmp_dyld_stub_binder
branches/meklort/i386/boot2/Makefile
9393
9494
9595
96
97
98
99
100
96101
102
103
104
105
106
107
97108
109
110
98111
99112
100113
......
107120
108121
109122
123
110124
111125
112126
-Wl,-sectcreate,__DATA,__Symbols,$(SYMROOT)/Symbols.dylib \
-o $(SYMROOT)/boot.sys $(filter %.o,$^) $(LIBS) -lcc_kext
@# Second pass, fixup global var locations
@${RM} $(OBJROOT)/Symbols.o
@${RM} $(SYMROOT)/${SYMBOLS_MODULE}
@${RM} $(SYMROOT)/Symbols.h
@make Symbols.dylib
@${RM} $(SYMROOT)/boot.sys
@echo "\t[LD] boot.sys"
@$(LD) -static -Wl,-preload -Wl,-segaddr,__INIT,$(BOOT2ADDR) \
-nostdlib -arch i386 -Wl,-segalign,20 \
-Wl,-sectcreate,__DATA,__Symbols,$(SYMROOT)/Symbols.dylib \
-o $(SYMROOT)/boot.sys $(filter %.o,$^) $(LIBS) -lcc_kext
@ld -arch i386 \
-undefined dynamic_lookup \
-dylib -read_only_relocs suppress \
@make embed_symbols# this is done in a sub process after boot.sys exists so the strings are populated correctly
@${RM} $(SYMROOT)/boot2.sys
@${RM} $(SYMROOT)/${SYMBOLS_MODULE}
branches/meklort/i386/modules/KextPatcher/kext_patcher.c
424424
425425
426426
427
427
428428
429429
430430
case PCI_CLASS_NETWORK_OTHER:
// Patch BCM43xx
if(current->vendor_id == 0x14E4 && ((current->device_id & 0xFF00) == 0x4300))
if(current->vendor_id == 0x14E4 && ((current->device_id & 0xFFD0) == 0x4300))
{
patch_bcm_deviceid = current->device_id;
}
branches/meklort/i386/modules/Resolution/Resolution.c
99
1010
1111
12
12
1313
1414
void Resolution_start()
{
//patchVideoBios();
patchVideoBios();
}
branches/meklort/i386/modules/Memory/spd.c
8080
8181
8282
83
84
85
86
87
88
83
8984
9085
9186
outb(base + SMBHSTSTS, 0x1f);// reset SMBus Controller
outb(base + SMBHSTDAT, 0xff);
while( inb(base + SMBHSTSTS) & 0x01)
{
rdtsc(l2, h2);
t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / (Platform->CPU.TSCFrequency / 100);
if(t > 50) return 0xFF;// hack, exit if unresponsive.
}
while( inb(base + SMBHSTSTS) & 0x01);
outb(base + SMBHSTCMD, cmd);
outb(base + SMBHSTADD, (adr << 1) | 0x01 );
branches/meklort/i386/modules/Makefile
2626
2727
2828
29
29
3030
3131
3232
VPATH = $(OBJROOT):$(SYMROOT)
# The order of building is important.
SUBDIRS = klibc uClibc++ Resolution KernelPatcher GUI KextPatcher GraphicsEnabler HPET USBFix Memory Networking NetbookInstaller ACPIPatcher HelloWorld
SUBDIRS = klibc uClibc++ Resolution KernelPatcher GUI KextPatcher GraphicsEnabler HPET USBFix Memory Networking NetbookInstaller ACPIPatcher
#SUBDIRS = HelloWorld
all embedtheme optionrom tags debug install installhdrs: objroot_dirs lazydylib1.o

Archive Download the corresponding diff file

Revision: 717