Chameleon

Chameleon Commit Details

Date:2010-08-24 03:10:33 (13 years 7 months ago)
Author:Evan Lojewski
Commit:429
Parents: 428
Message:Updated module system. Hooks can now be used within modules when cetaion functions are called in chameleon. Note that onle two hooks currently exist, more need to be added. I also updated the HelloWorld module to use a hook instead of print out right away.
Changes:
M/branches/meklort/i386/boot2/boot.c
M/branches/meklort/TODO
M/branches/meklort/i386/boot2/modules.c
M/branches/meklort/CHANGES
M/branches/meklort/i386/modules/HelloWorld/HelloWorld.c
M/branches/meklort/i386/boot2/modules.h

File differences

branches/meklort/TODO
2323
2424
2525
26
26
2727
2828
2929
to provide any other acpi table.
- Add a new module capable of writing proprietary Chameleon data to ioreg:
Using the DT__xxx() API, we will creat e a set of functions to write
Using the DT__xxx() API, we will create a set of functions to write
to log info, chameleon boot info to be retrieved by helper applications...
the only public function for log info purpose of this module would be:
logMessageToIOREG(...); // var args printf style format
branches/meklort/CHANGES
1
2
13
24
35
- Added module hooks + callback system. Main code still needs ot be populated with hooks
- Added module support
- Fixed lapic_init patch. Fixed _cpuid_set_info patch to work on the 10.6.0 / 10.6.1 kernel (patches cpumodel)
- Added USB Legacy Off patch. Modified to run immediately *before* the kernel is executed, that
way no files need to be loaded after the usb device is reset.
branches/meklort/i386/boot2/boot.c
198198
199199
200200
201
201
202
203
204
202205
203206
204207
......
282285
283286
284287
285
286
287
288288
289289
290290
291291
292292
293
294
295
296
297
293298
294299
295300
......
585590
586591
587592
593
594
588595
589596
590597
finalizeBootStruct();
usb_loop();
// Jump to kernel's entry point. There's no going back now.
execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgs, NULL, NULL);// Notify modules that the kernel is about to be started
// Jump to kernel's entry point. There's no going back now.
startprog( kernelEntry, bootArgs );
// Not reached
firstRun = false;
}
// Loading preboot ramdisk if exists.
loadPrebootRAMDisk();
// Intialize module system
if(init_module_system())
{
load_all_modules();
}
// Loading preboot ramdisk if exists.
loadPrebootRAMDisk();
// Disable rescan option by default
gEnableCDROMRescan = false;
}
} else {
/* Won't return if successful. */
// Notify modules that ExecKernel is about to be called
execute_hook("ExecKernel", binary, NULL, NULL, NULL);
ret = ExecKernel(binary);
}
}
branches/meklort/i386/boot2/modules.c
88
99
1010
11
12
13
1114
15
16
17
18
19
20
21
22
1223
1324
1425
......
2940
3041
3142
43
44
45
46
47
48
3249
3350
34
35
36
37
38
39
40
41
51
4252
4353
54
4455
4556
4657
......
5869
5970
6071
61
62
72
6373
64
74
6575
6676
6777
......
97107
98108
99109
100
110
101111
102112
103113
......
105115
106116
107117
108
118
109119
110120
111
121
122
112123
113
114
115
116
117124
118125
119126
......
125132
126133
127134
135
128136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
129282
130283
131284
......
162315
163316
164317
318
165319
166320
167321
168322
169323
170324
325
171326
172327
173328
......
210365
211366
212367
368
213369
214370
215371
......
275431
276432
277433
278
434
279435
280436
281437
......
540696
541697
542698
543
699
544700
545701
546702
......
553709
554710
555711
556
712
557713
558714
559715
560716
561717
562718
563
719
564720
565721
566722
......
568724
569725
570726
571
727
572728
573729
574730
......
577733
578734
579735
580
736
581737
582738
583739
......
593749
594750
595751
596
752
597753
598754
599755
......
626782
627783
628784
629
785
630786
631787
632788
......
641797
642798
643799
644
800
645801
646802
647803
648
804
649805
650806
651807
......
664820
665821
666822
667
823
668824
669825
670826
......
698854
699855
700856
701
857
702858
703859
704860
......
740896
741897
742898
743
899
744900
745901
746902
......
785941
786942
787943
788
944
789945
790946
791947
......
818974
819975
820976
821
977
822978
823979
824980
......
8791035
8801036
8811037
882
1038
8831039
8841040
8851041
......
8901046
8911047
8921048
893
1049
8941050
8951051
8961052
......
9581114
9591115
9601116
961
1117
9621118
9631119
9641120
#include "multiboot.h"
#include "modules.h"
#ifndef DEBUG_MODULES
#define DEBUG_MODULES 0
#endif
#if DEBUG_MODULES
#define DBG(x...)printf(x); getc()
#else
#define DBG(x...)
#endif
moduleHook_t* moduleCallbacks = NULL;
moduleList_t* loadedModules = NULL;
symbolList_t* moduleSymbols = NULL;
unsigned int (*lookup_symbol)(const char*) = NULL;
if(load_module(SYMBOLS_MODULE))
{
lookup_symbol = (void*)lookup_all_symbols("_lookup_symbol");
if((UInt32)lookup_symbol != 0xFFFFFFFF)
{
return 1;
}
}
if((UInt32)lookup_symbol == 0xFFFFFFFF)
{
return 0;
}
else
{
return 1;
}
return 0;
}
/*
* Load all modules in the /Extra/modules/ directory
* Module depencdies will be loaded first
struct dirstuff* moduleDir = opendir("/Extra/modules/");
while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)
{
// TODO: verify ends in .dylib
if(strlen(name) > sizeof(".dylib"))
if(strcmp(&name[strlen(name) - sizeof("dylib")], ".dylib") == 0)
{
name[strlen(name) - sizeof(".dylib")] = 0;
name[strlen(name) - sizeof("dylib")] = 0;
load_module(name);
}
}
{
void (*module_start)(void) = NULL;
printf("Module %s read in.\n", modString);
//printf("Module %s read in.\n", modString);
// Module loaded into memory, parse it
module_start = parse_mach(module_base);
if(module_start)
{
(*module_start)();// Start the module
printf("Module started\n");
DBG("Module %s.dylib Loaded.\n", module);
}
else {
printf("Unabel to locate module start\n");
printf("Unabel to start %s.dylib\n", module);
getc();
}
getc();
// TODO: Add module to loaded list if loaded successfuly
}
return 1;
}
/*
* register_hook( const char* name )
*name - Name of the module Hook.
* NOTE: If the name already exists in the list, it'll
* still be added, however the entry will not be used, the first one
* will instead. That also means the the hook will most likely be
* called twice.
*
* Registers a hook with the module system, This allows modules to
* register a callback when the hook is executed.
*/
inline void register_hook(const char* name)
{
moduleHook_t* hooks;
if(moduleCallbacks == NULL)
{
moduleCallbacks = malloc(sizeof(moduleHook_t));
moduleCallbacks->next = NULL;
}
hooks = moduleCallbacks;
while(hooks->next != NULL)
{
hooks = hooks->next;
}
hooks->name = name;
hooks->callbacks = NULL;
}
/*
*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);
if(moduleCallbacks != NULL)
{
moduleHook_t* hooks = moduleCallbacks;
while(hooks != NULL && strcmp(name, hooks->name) != 0)
{
hooks = hooks->next;
}
if(hooks != NULL)
{
// Loop through all callbacks for this module
callbackList_t* callbacks = hooks->callbacks;
while(callbacks)
{
// Execute callback
callbacks->callback(arg1, arg2, arg3, arg4);
callbacks = callbacks->next;
}
DBG("Hook '%s' executed.\n", name);
return 1;
}
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;
}
}
DBG("No hooks have been registered.\n", name);
return 0;
}
/*
*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.
*NOTE: the hooks take four void* arguments.
*/
/*
void register_hook_callback(const char* name,
void(*callback)(void*, void*, void*, void*),
)*/
void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*))
{
// Locate Module hook
if(moduleCallbacks == NULL)
{
register_hook(name);
}
volatile moduleHook_t* hooks = moduleCallbacks;
while(hooks != NULL && strcmp(name, hooks->name) != 0)
{
hooks = hooks->next;
}
if(hooks == NULL)
{
// Hook doesn't exist, add it.
register_hook(name);
// This is just a pointer, the data was modified in the register_hook function.
hooks = hooks->next;
}
// Module Hooks located
if(hooks->callbacks == NULL)
{
// Initialize hook list
hooks->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));
hooks->callbacks->callback = callback;
hooks->callbacks->next = NULL;
}
else
{
callbackList_t* callbacks = hooks->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;
}
}
/*
* Parse through a macho module. The module will be rebased and binded
* as specified in the macho header. If the module is sucessfuly laoded
* the module iinit address will be returned.
if(((struct mach_header*)binary)->magic != MH_MAGIC)
{
printf("Module is not 32bit\n");
getc();
return NULL;// 32bit only
}
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
}
break;
case S_LAZY_SYMBOL_POINTERS:
// NOTE: Theses currently are not handled.
//nonlazy = binary + section->offset;
//printf("%s S_LAZY_SYMBOL_POINTERS section, 0x%X\n", SECT_NON_LAZY_SYMBOL_PTR, nonlazy);
// Fucntions
break;
default:
printf("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);
DBG("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);
break;
}
case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
libraryOrdinal = immediate;
//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: %d\n", libraryOrdinal);
//DBG("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: %d\n", libraryOrdinal);
break;
case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
}
while(bind_stream[i] & 0x80);
//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: %d\n", libraryOrdinal);
//DBG("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;
//printf("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);
//DBG("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);
break;
symboFlags = immediate;
symbolName = (char*)&bind_stream[++i];
i += strlen((char*)&bind_stream[i]);
//printf("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X\n", symbolName, symboFlags);
//DBG("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X\n", symbolName, symboFlags);
symbolAddr = lookup_all_symbols(symbolName);
case BIND_OPCODE_SET_TYPE_IMM:
// Set bind type (pointer, absolute32, pcrel32)
type = immediate;
//printf("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);
//DBG("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);
break;
if(!(bind_stream[i-1] & 0x40)) addend *= -1;
//printf("BIND_OPCODE_SET_ADDEND_SLEB: %d\n", addend);
//DBG("BIND_OPCODE_SET_ADDEND_SLEB: %d\n", addend);
break;
case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
segmentAddress += tmp;
//printf("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 0x%X\n", segmentAddress);
//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;
//printf("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress);
//DBG("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress);
break;
case BIND_OPCODE_DO_BIND:
//printf("BIND_OPCODE_DO_BIND\n");
//DBG("BIND_OPCODE_DO_BIND\n");
if(symbolAddr != 0xFFFFFFFF)
{
address = segmentAddress + (UInt32)base;
break;
case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
//printf("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n");
//DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n");
// Read in offset
break;
case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
//printf("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");
//DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");
if(symbolAddr != 0xFFFFFFFF)
{
while(bind_stream[i] & 0x80);
//printf("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2);
//DBG("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2);
if(symbolAddr != 0xFFFFFFFF)
void add_symbol(char* symbol, void* addr)
{
symbolList_t* entry;
//printf("Adding symbol %s at 0x%X\n", symbol, addr);
//DBG("Adding symbol %s at 0x%X\n", symbol, addr);
if(!moduleSymbols)
{
{
moduleList_t* entry;
/*
printf("\%s.dylib Version %d.%d.%d loaded\n"
DBG("\%s.dylib Version %d.%d.%d loaded\n"
"\tCompatibility Version: %d.%d.%d\n",
name,
(version >> 16) & 0xFFFF,
addr = lookup_symbol(name);
if(addr != 0xFFFFFFFF)
{
//printf("Internal symbol %s located at 0x%X\n", name, addr);
//DBG("Internal symbol %s located at 0x%X\n", name, addr);
return addr;
}
}
{
if(strcmp(entry->symbol, name) == 0)
{
//printf("External symbol %s located at 0x%X\n", name, entry->addr);
//DBG("External symbol %s located at 0x%X\n", name, entry->addr);
return entry->addr;
}
else
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 saver as
// 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);
branches/meklort/i386/boot2/modules.h
1111
1212
1313
14
14
15
1516
1617
1718
1819
1920
20
21
22
2123
2224
2325
2426
2527
2628
29
30
31
32
33
2734
35
36
37
38
39
40
41
42
2843
2944
3045
......
3853
3954
4055
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
4173
4274
4375
#define __BOOT_MODULES_H
typedef struct symbolList_t{
typedef struct symbolList_t
{
char* symbol;
unsigned int addr;
struct symbolList_t* next;
} symbolList_t;
typedef struct moduleList_t{
typedef struct moduleList_t
{
char* module;
unsigned int version;
unsigned int compat;
struct moduleList_t* next;
} moduleList_t;
typedef struct callbackList_t
{
void(*callback)(void*, void*, void*, void*);
struct callbackList_t* next;
} callbackList_t;
typedef struct moduleHook_t
{
const char* name;
callbackList_t* callbacks;
struct moduleHook_t* next;
} moduleHook_t;
#define SYMBOLS_MODULE "Symbols"
#define SYMBOL_DYLD_STUB_BINDER"dyld_stub_binder"
int init_module_system();
void load_all_modules();
/*
* Modules Interface
* register_hook
*Notifies the module system that it should log requests
*for callbacks on the hool execution
*
* 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.
*/
inline void register_hook(const char* name);
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);
branches/meklort/i386/modules/HelloWorld/HelloWorld.c
55
66
77
8
9
10
11
12
13
14
15
816
917
10
18
19
1120
21
#include "libsaio.h"
void helloWorld(void* binary, void* arg2, void* arg3, void* arg4)
{
printf("Hello world from ExecKernel hook. Binary located at 0x%X\n", binary);
getc();
}
void HelloWorld_start()
{
printf("Hello World from a module\n");
//printf("Hooking 'ExecKernel'\n");
register_hook_callback("ExecKernel", &helloWorld);
}

Archive Download the corresponding diff file

Revision: 429