Rev 6536 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6536 | Rev 9874 | ||
---|---|---|---|
1 | #include |
1 | #include |
2 | #include |
2 | #include |
3 | #include |
3 | #include |
4 | #include |
4 | #include |
5 | #include |
5 | #include |
6 | #include |
6 | #include |
7 | #include |
7 | #include |
8 | 8 | ||
9 | #include |
9 | #include |
10 | 10 | ||
11 | #include "list.h" |
11 | #include "list.h" |
12 | #include "pe.h" |
12 | #include "pe.h" |
13 | 13 | ||
14 | #define unlikely(x) __builtin_expect(!!(x), 0) |
14 | #define unlikely(x) __builtin_expect(!!(x), 0) |
15 | 15 | ||
16 | //#define DBG(format,...) printf(format,##__VA_ARGS__) |
16 | //#define DBG(format,...) printf(format,##__VA_ARGS__) |
17 | 17 | ||
18 | #define DBG(format,...) |
18 | #define DBG(format,...) |
19 | 19 | ||
20 | 20 | ||
21 | void init_loader(void *libc_image); |
21 | void init_loader(void *libc_image); |
22 | void* create_image(void *raw); |
22 | void* create_image(void *raw); |
23 | int link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp); |
23 | int link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp); |
24 | 24 | void* load_library(const char *name); |
|
- | 25 | ||
25 | extern char* __appenv; |
26 | extern char* __appenv; |
26 | extern int __appenv_size; |
27 | extern int __appenv_size; |
27 | 28 | ||
28 | typedef struct tag_module module_t; |
29 | typedef struct tag_module module_t; |
29 | 30 | ||
30 | struct app_hdr |
31 | struct app_hdr |
31 | { |
32 | { |
32 | char banner[8]; |
33 | char banner[8]; |
33 | int version; |
34 | int version; |
34 | int start; |
35 | int start; |
35 | int iend; |
36 | int iend; |
36 | int memsize; |
37 | int memsize; |
37 | int stacktop; |
38 | int stacktop; |
38 | char *cmdline; |
39 | char *cmdline; |
39 | char *path; |
40 | char *path; |
40 | int reserved; |
41 | int reserved; |
41 | void *__idata_start; |
42 | void *__idata_start; |
42 | void *__idata_end; |
43 | void *__idata_end; |
43 | void (*main)(int argc, char **argv, char **envp); |
44 | void (*main)(int argc, char **argv, char **envp); |
44 | }; |
45 | }; |
45 | 46 | ||
46 | struct tag_module |
47 | struct tag_module |
47 | { |
48 | { |
48 | struct list_head list; |
49 | struct list_head list; |
49 | 50 | ||
50 | char *img_name; |
51 | char *img_name; |
51 | char *img_path; |
52 | char *img_path; |
52 | 53 | ||
53 | uint32_t refcount; |
54 | uint32_t refcount; |
54 | 55 | ||
55 | char *start; |
56 | char *start; |
56 | char *end; |
57 | char *end; |
57 | 58 | ||
58 | void *entry; |
59 | void *entry; |
59 | 60 | ||
60 | PIMAGE_NT_HEADERS32 img_hdr; |
61 | PIMAGE_NT_HEADERS32 img_hdr; |
61 | PIMAGE_SECTION_HEADER img_sec; |
62 | PIMAGE_SECTION_HEADER img_sec; |
62 | PIMAGE_EXPORT_DIRECTORY img_exp; |
63 | PIMAGE_EXPORT_DIRECTORY img_exp; |
63 | }; |
64 | }; |
64 | 65 | ||
65 | typedef struct |
66 | typedef struct |
66 | { |
67 | { |
67 | struct list_head list; |
68 | struct list_head list; |
68 | char *path; |
69 | char *path; |
69 | int path_len; |
70 | int path_len; |
70 | }dll_path_t; |
71 | }dll_path_t; |
71 | 72 | ||
72 | 73 | ||
73 | LIST_HEAD(path_list); |
74 | LIST_HEAD(path_list); |
74 | 75 | ||
75 | static module_t libc_dll; |
76 | static module_t libc_dll; |
76 | static char libc_name[] = "libc.dll"; |
77 | static char libc_name[] = "libc.dll"; |
77 | static char libc_path[] = "/KolibriOS/lib/libc.dll"; |
78 | static char libc_path[] = "/KolibriOS/lib/libc.dll"; |
78 | 79 | ||
79 | static inline int IsPowerOf2(uint32_t val) |
80 | static inline int IsPowerOf2(uint32_t val) |
80 | { |
81 | { |
81 | if(val == 0) |
82 | if(val == 0) |
82 | return 0; |
83 | return 0; |
83 | return (val & (val - 1)) == 0; |
84 | return (val & (val - 1)) == 0; |
84 | } |
85 | } |
85 | 86 | ||
86 | 87 | ||
87 | int validate_pe(void *raw, size_t raw_size, int is_exec) |
88 | int validate_pe(void *raw, size_t raw_size, int is_exec) |
88 | { |
89 | { |
89 | PIMAGE_DOS_HEADER dos; |
90 | PIMAGE_DOS_HEADER dos; |
90 | PIMAGE_NT_HEADERS32 nt; |
91 | PIMAGE_NT_HEADERS32 nt; |
91 | 92 | ||
92 | dos = (PIMAGE_DOS_HEADER)raw; |
93 | dos = (PIMAGE_DOS_HEADER)raw; |
93 | 94 | ||
94 | if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) ) |
95 | if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) ) |
95 | return 0; |
96 | return 0; |
96 | 97 | ||
97 | if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0) |
98 | if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0) |
98 | return 0; |
99 | return 0; |
99 | 100 | ||
100 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
101 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
101 | 102 | ||
102 | if( (uint32_t)nt < (uint32_t)raw) |
103 | if( (uint32_t)nt < (uint32_t)raw) |
103 | return 0; |
104 | return 0; |
104 | 105 | ||
105 | if(nt->Signature != IMAGE_NT_SIGNATURE) |
106 | if(nt->Signature != IMAGE_NT_SIGNATURE) |
106 | return 0; |
107 | return 0; |
107 | 108 | ||
108 | if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) |
109 | if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) |
109 | return 0; |
110 | return 0; |
110 | 111 | ||
111 | if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) |
112 | if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) |
112 | return 0; |
113 | return 0; |
113 | 114 | ||
114 | if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) |
115 | if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) |
115 | return 0; |
116 | return 0; |
116 | 117 | ||
117 | if( is_exec && nt->OptionalHeader.ImageBase != 0) |
118 | if( is_exec && nt->OptionalHeader.ImageBase != 0) |
118 | return 0; |
119 | return 0; |
119 | 120 | ||
120 | if(nt->OptionalHeader.SectionAlignment < 4096) |
121 | if(nt->OptionalHeader.SectionAlignment < 4096) |
121 | { |
122 | { |
122 | if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) |
123 | if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) |
123 | return 0; |
124 | return 0; |
124 | } |
125 | } |
125 | else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment) |
126 | else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment) |
126 | return 0; |
127 | return 0; |
127 | 128 | ||
128 | if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) || |
129 | if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) || |
129 | !IsPowerOf2(nt->OptionalHeader.FileAlignment)) |
130 | !IsPowerOf2(nt->OptionalHeader.FileAlignment)) |
130 | return 0; |
131 | return 0; |
131 | 132 | ||
132 | if(nt->FileHeader.NumberOfSections > 96) |
133 | if(nt->FileHeader.NumberOfSections > 96) |
133 | return 0; |
134 | return 0; |
134 | 135 | ||
135 | return 1; |
136 | return 1; |
136 | } |
137 | } |
137 | 138 | ||
138 | 139 | ||
139 | void init_loader(void *libc_image) |
140 | void init_loader(void *libc_image) |
140 | { |
141 | { |
141 | 142 | ||
142 | PIMAGE_DOS_HEADER dos; |
143 | PIMAGE_DOS_HEADER dos; |
143 | PIMAGE_NT_HEADERS32 nt; |
144 | PIMAGE_NT_HEADERS32 nt; |
144 | PIMAGE_EXPORT_DIRECTORY exp; |
145 | PIMAGE_EXPORT_DIRECTORY exp; |
145 | 146 | ||
146 | struct app_hdr *header = NULL; |
147 | struct app_hdr *header = NULL; |
147 | dll_path_t *path; |
148 | dll_path_t *path; |
148 | int len; |
149 | int len; |
149 | char *p; |
150 | char *p; |
150 | 151 | ||
151 | #if 0 |
152 | #if 0 |
152 | 153 | ||
153 | if(__appenv_size) |
154 | if(__appenv_size) |
154 | { |
155 | { |
155 | char *env; |
156 | char *env; |
156 | env = envz_get(__appenv, __appenv_size, "PATH"); |
157 | env = envz_get(__appenv, __appenv_size, "PATH"); |
157 | if( env ) |
158 | if( env ) |
158 | { |
159 | { |
159 | while( *env ) |
160 | while( *env ) |
160 | { |
161 | { |
161 | p = env; |
162 | p = env; |
162 | while(*p) |
163 | while(*p) |
163 | { |
164 | { |
164 | if( *p == 0x0D) |
165 | if( *p == 0x0D) |
165 | break; |
166 | break; |
166 | else if( *p == 0x0A) |
167 | else if( *p == 0x0A) |
167 | break; |
168 | break; |
168 | else if( *p == ':') |
169 | else if( *p == ':') |
169 | break; |
170 | break; |
170 | p++; |
171 | p++; |
171 | }; |
172 | }; |
172 | len = p-env; |
173 | len = p-env; |
173 | if(len) |
174 | if(len) |
174 | { |
175 | { |
175 | char *p1; |
176 | char *p1; |
176 | 177 | ||
177 | p1 = (char*)malloc(len+1); |
178 | p1 = (char*)malloc(len+1); |
178 | memcpy(p1, env, len); |
179 | memcpy(p1, env, len); |
179 | p1[len]=0; |
180 | p1[len]=0; |
180 | 181 | ||
181 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
182 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
182 | INIT_LIST_HEAD(&path->list); |
183 | INIT_LIST_HEAD(&path->list); |
183 | path->path = p1; |
184 | path->path = p1; |
184 | path->path_len = len; |
185 | path->path_len = len; |
185 | DBG("add libraries path %s\n", path->path); |
186 | DBG("add libraries path %s\n", path->path); |
186 | list_add_tail(&path->list, &path_list); |
187 | list_add_tail(&path->list, &path_list); |
187 | }; |
188 | }; |
188 | if(*p == ':') |
189 | if(*p == ':') |
189 | { |
190 | { |
190 | env = p+1; |
191 | env = p+1; |
191 | continue; |
192 | continue; |
192 | } |
193 | } |
193 | else break; |
194 | else break; |
194 | }; |
195 | }; |
195 | }; |
196 | }; |
196 | }; |
197 | }; |
197 | #endif |
198 | #endif |
198 | 199 | ||
199 | len = strrchr(header->path, '/') - header->path+1; |
200 | len = strrchr(header->path, '/') - header->path+1; |
200 | p = (char*)malloc(len+1); |
201 | p = (char*)malloc(len+1); |
201 | memcpy(p, header->path, len); |
202 | memcpy(p, header->path, len); |
202 | p[len]=0; |
203 | p[len]=0; |
203 | 204 | ||
204 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
205 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
205 | INIT_LIST_HEAD(&path->list); |
206 | INIT_LIST_HEAD(&path->list); |
206 | path->path = p; |
207 | path->path = p; |
207 | path->path_len = len; |
208 | path->path_len = len; |
208 | DBG("add libraries path %s\n", path->path); |
209 | DBG("add libraries path %s\n", path->path); |
209 | list_add_tail(&path->list, &path_list); |
210 | list_add_tail(&path->list, &path_list); |
210 | 211 | ||
211 | 212 | ||
212 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
213 | path = (dll_path_t*)malloc(sizeof(dll_path_t)); |
213 | INIT_LIST_HEAD(&path->list); |
214 | INIT_LIST_HEAD(&path->list); |
214 | path->path = "/kolibrios/lib/"; |
215 | path->path = "/kolibrios/lib/"; |
215 | path->path_len = 15; /* FIXME */ |
216 | path->path_len = 15; /* FIXME */ |
216 | DBG("add libraries path %s\n", path->path); |
217 | DBG("add libraries path %s\n", path->path); |
217 | list_add_tail(&path->list, &path_list); |
218 | list_add_tail(&path->list, &path_list); |
218 | 219 | ||
219 | INIT_LIST_HEAD(&libc_dll.list); |
220 | INIT_LIST_HEAD(&libc_dll.list); |
220 | 221 | ||
221 | libc_dll.img_name = libc_name; |
222 | libc_dll.img_name = libc_name; |
222 | libc_dll.img_path = libc_path; |
223 | libc_dll.img_path = libc_path; |
223 | 224 | ||
224 | libc_dll.refcount = 1; |
225 | libc_dll.refcount = 1; |
225 | 226 | ||
226 | dos = (PIMAGE_DOS_HEADER)libc_image; |
227 | dos = (PIMAGE_DOS_HEADER)libc_image; |
227 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
228 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
228 | exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, libc_image, |
229 | exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, libc_image, |
229 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
230 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
230 | 231 | ||
231 | libc_dll.start = libc_image; |
232 | libc_dll.start = libc_image; |
232 | libc_dll.end = MakePtr(char*,libc_image, nt->OptionalHeader.SizeOfImage); |
233 | libc_dll.end = MakePtr(char*,libc_image, nt->OptionalHeader.SizeOfImage); |
233 | 234 | ||
234 | libc_dll.img_hdr = nt; |
235 | libc_dll.img_hdr = nt; |
235 | libc_dll.img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
236 | libc_dll.img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
236 | libc_dll.img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,libc_image, |
237 | libc_dll.img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,libc_image, |
237 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
238 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
238 | 239 | ||
239 | }; |
240 | }; |
240 | 241 | ||
241 | static inline void sec_copy(void *dst, void *src, size_t len) |
242 | static inline void sec_copy(void *dst, void *src, size_t len) |
242 | { |
243 | { |
243 | __asm__ __volatile__ ( |
244 | __asm__ __volatile__ ( |
244 | "shrl $2, %%ecx \n\t" |
245 | "shrl $2, %%ecx \n\t" |
245 | "rep movsl" |
246 | "rep movsl" |
246 | : |
247 | : |
247 | :"c"(len),"S"(src),"D"(dst) |
248 | :"c"(len),"S"(src),"D"(dst) |
248 | :"cc"); |
249 | :"cc"); |
249 | __asm__ __volatile__ ( |
250 | __asm__ __volatile__ ( |
250 | "" |
251 | "" |
251 | :::"ecx","esi","edi"); |
252 | :::"ecx","esi","edi"); |
252 | }; |
253 | }; |
253 | 254 | ||
254 | 255 | ||
255 | void* create_image(void *raw) |
256 | void* create_image(void *raw) |
256 | { |
257 | { |
257 | PIMAGE_DOS_HEADER dos; |
258 | PIMAGE_DOS_HEADER dos; |
258 | PIMAGE_NT_HEADERS32 nt; |
259 | PIMAGE_NT_HEADERS32 nt; |
259 | PIMAGE_SECTION_HEADER img_sec; |
260 | PIMAGE_SECTION_HEADER img_sec; |
260 | 261 | ||
261 | void *img_base; |
262 | void *img_base; |
262 | uint32_t sec_align; |
263 | uint32_t sec_align; |
263 | int i; |
264 | int i; |
264 | 265 | ||
265 | dos = (PIMAGE_DOS_HEADER)raw; |
266 | dos = (PIMAGE_DOS_HEADER)raw; |
266 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
267 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
267 | 268 | ||
268 | img_base = user_alloc(nt->OptionalHeader.SizeOfImage); |
269 | img_base = _ksys_alloc(nt->OptionalHeader.SizeOfImage); |
269 | 270 | ||
270 | if(unlikely(img_base == NULL)) |
271 | if(unlikely(img_base == NULL)) |
271 | return 0; |
272 | return 0; |
272 | 273 | ||
273 | sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders); |
274 | sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders); |
274 | 275 | ||
275 | img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32)); |
276 | img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32)); |
276 | 277 | ||
277 | sec_align = nt->OptionalHeader.SectionAlignment; |
278 | sec_align = nt->OptionalHeader.SectionAlignment; |
278 | 279 | ||
279 | for(i=0; i< nt->FileHeader.NumberOfSections; i++) |
280 | for(i=0; i< nt->FileHeader.NumberOfSections; i++) |
280 | { |
281 | { |
281 | void *src_ptr; |
282 | void *src_ptr; |
282 | void *dest_ptr; |
283 | void *dest_ptr; |
283 | size_t sec_size; |
284 | size_t sec_size; |
284 | 285 | ||
285 | if ( img_sec->SizeOfRawData && img_sec->PointerToRawData ) |
286 | if ( img_sec->SizeOfRawData && img_sec->PointerToRawData ) |
286 | { |
287 | { |
287 | src_ptr = MakePtr(void*, raw, img_sec->PointerToRawData); |
288 | src_ptr = MakePtr(void*, raw, img_sec->PointerToRawData); |
288 | dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress); |
289 | dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress); |
289 | sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData); |
290 | sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData); |
290 | }; |
291 | }; |
291 | 292 | ||
292 | img_sec++; |
293 | img_sec++; |
293 | }; |
294 | }; |
294 | 295 | ||
295 | if(nt->OptionalHeader.DataDirectory[5].Size) |
296 | if(nt->OptionalHeader.DataDirectory[5].Size) |
296 | { |
297 | { |
297 | PIMAGE_BASE_RELOCATION reloc; |
298 | PIMAGE_BASE_RELOCATION reloc; |
298 | 299 | ||
299 | uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase; |
300 | uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase; |
300 | 301 | ||
301 | reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base, |
302 | reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base, |
302 | nt->OptionalHeader.DataDirectory[5].VirtualAddress); |
303 | nt->OptionalHeader.DataDirectory[5].VirtualAddress); |
303 | 304 | ||
304 | while ( reloc->SizeOfBlock != 0 ) |
305 | while ( reloc->SizeOfBlock != 0 ) |
305 | { |
306 | { |
306 | uint32_t cnt; |
307 | uint32_t cnt; |
307 | uint16_t *entry; |
308 | uint16_t *entry; |
308 | uint16_t reltype; |
309 | uint16_t reltype; |
309 | uint32_t offs; |
310 | uint32_t offs; |
310 | 311 | ||
311 | cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t); |
312 | cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t); |
312 | entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) ); |
313 | entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) ); |
313 | 314 | ||
314 | for ( i=0; i < cnt; i++ ) |
315 | for ( i=0; i < cnt; i++ ) |
315 | { |
316 | { |
316 | uint16_t *p16; |
317 | uint16_t *p16; |
317 | uint32_t *p32; |
318 | uint32_t *p32; |
318 | 319 | ||
319 | reltype = (*entry & 0xF000) >> 12; |
320 | reltype = (*entry & 0xF000) >> 12; |
320 | offs = (*entry & 0x0FFF) + reloc->VirtualAddress; |
321 | offs = (*entry & 0x0FFF) + reloc->VirtualAddress; |
321 | switch(reltype) |
322 | switch(reltype) |
322 | { |
323 | { |
323 | case 1: |
324 | case 1: |
324 | p16 = MakePtr(uint16_t*, img_base, offs); |
325 | p16 = MakePtr(uint16_t*, img_base, offs); |
325 | *p16+= (uint16_t)(delta>>16); |
326 | *p16+= (uint16_t)(delta>>16); |
326 | break; |
327 | break; |
327 | case 2: |
328 | case 2: |
328 | p16 = MakePtr(uint16_t*, img_base, offs); |
329 | p16 = MakePtr(uint16_t*, img_base, offs); |
329 | *p16+= (uint16_t)delta; |
330 | *p16+= (uint16_t)delta; |
330 | break; |
331 | break; |
331 | case 3: |
332 | case 3: |
332 | p32 = MakePtr(uint32_t*, img_base, offs); |
333 | p32 = MakePtr(uint32_t*, img_base, offs); |
333 | *p32+= delta; |
334 | *p32+= delta; |
334 | } |
335 | } |
335 | entry++; |
336 | entry++; |
336 | } |
337 | } |
337 | reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock); |
338 | reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock); |
338 | } |
339 | } |
339 | }; |
340 | }; |
340 | return img_base; |
341 | return img_base; |
341 | }; |
342 | }; |
342 | 343 | ||
343 | 344 | ||
344 | int link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp) |
345 | int link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp) |
345 | { |
346 | { |
346 | static jmp_buf loader_env; |
347 | static jmp_buf loader_env; |
347 | static int recursion = -1; |
348 | static int recursion = -1; |
348 | int warn = 0; |
349 | int warn = 0; |
349 | 350 | ||
350 | recursion++; |
351 | recursion++; |
351 | if( !recursion ) |
352 | if( !recursion ) |
352 | { |
353 | { |
353 | if( unlikely(setjmp(loader_env) != 0)) |
354 | if( unlikely(setjmp(loader_env) != 0)) |
354 | { |
355 | { |
355 | recursion = -1; |
356 | recursion = -1; |
356 | return 0; |
357 | return 0; |
357 | }; |
358 | }; |
358 | }; |
359 | }; |
359 | 360 | ||
360 | while ( imp->Name ) |
361 | while ( imp->Name ) |
361 | { |
362 | { |
362 | PIMAGE_DOS_HEADER expdos; |
363 | PIMAGE_DOS_HEADER expdos; |
363 | PIMAGE_NT_HEADERS32 expnt; |
364 | PIMAGE_NT_HEADERS32 expnt; |
364 | PIMAGE_EXPORT_DIRECTORY exp; |
365 | PIMAGE_EXPORT_DIRECTORY exp; |
365 | PIMAGE_THUNK_DATA32 thunk; |
366 | PIMAGE_THUNK_DATA32 thunk; |
366 | 367 | ||
367 | void **iat; |
368 | void **iat; |
368 | char *libname; |
369 | char *libname; |
369 | uint32_t *exp_functions; |
370 | uint32_t *exp_functions; |
370 | uint16_t *exp_ordinals; |
371 | uint16_t *exp_ordinals; |
371 | char **exp_names; |
372 | char **exp_names; |
372 | 373 | ||
373 | const module_t *api; |
374 | const module_t *api; |
374 | 375 | ||
375 | libname=MakePtr(char*,imp->Name, img_base); |
376 | libname=MakePtr(char*,imp->Name, img_base); |
376 | 377 | ||
377 | DBG("import from %s\n",libname); |
378 | DBG("import from %s\n",libname); |
378 | 379 | ||
379 | api = load_library(libname); |
380 | api = load_library(libname); |
380 | if(unlikely(api == NULL)) |
381 | if(unlikely(api == NULL)) |
381 | { |
382 | { |
382 | printf("library %s not found\n", libname); |
383 | printf("library %s not found\n", libname); |
383 | longjmp(loader_env, 1); |
384 | longjmp(loader_env, 1); |
384 | } |
385 | } |
385 | 386 | ||
386 | iat = MakePtr(void**,imp->FirstThunk, img_base); |
387 | iat = MakePtr(void**,imp->FirstThunk, img_base); |
387 | 388 | ||
388 | if(imp->OriginalFirstThunk !=0 ) |
389 | if(imp->OriginalFirstThunk !=0 ) |
389 | { |
390 | { |
390 | thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->OriginalFirstThunk, img_base); |
391 | thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->OriginalFirstThunk, img_base); |
391 | } |
392 | } |
392 | else |
393 | else |
393 | { |
394 | { |
394 | thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->FirstThunk, img_base); |
395 | thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->FirstThunk, img_base); |
395 | }; |
396 | }; |
396 | 397 | ||
397 | exp = api->img_exp; |
398 | exp = api->img_exp; |
398 | 399 | ||
399 | exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,api->start); |
400 | exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,api->start); |
400 | exp_ordinals = MakePtr(uint16_t*, exp->AddressOfNameOrdinals,api->start); |
401 | exp_ordinals = MakePtr(uint16_t*, exp->AddressOfNameOrdinals,api->start); |
401 | exp_names = MakePtr(char**, exp->AddressOfNames,api->start); |
402 | exp_names = MakePtr(char**, exp->AddressOfNames,api->start); |
402 | 403 | ||
403 | while ( thunk->u1.AddressOfData != 0 ) |
404 | while ( thunk->u1.AddressOfData != 0 ) |
404 | { |
405 | { |
405 | PIMAGE_IMPORT_BY_NAME imp_name; |
406 | PIMAGE_IMPORT_BY_NAME imp_name; |
406 | 407 | ||
407 | if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) |
408 | if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) |
408 | { |
409 | { |
409 | // ordinal = (*func_list) & 0x7fffffff; |
410 | // ordinal = (*func_list) & 0x7fffffff; |
410 | // *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal); |
411 | // *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal); |
411 | // if ((*ImportAddressList) == NULL) |
412 | // if ((*ImportAddressList) == NULL) |
412 | // { |
413 | // { |
413 | // DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName); |
414 | // DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName); |
414 | // RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName); |
415 | // RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName); |
415 | // return STATUS_ENTRYPOINT_NOT_FOUND; |
416 | // return STATUS_ENTRYPOINT_NOT_FOUND; |
416 | // } |
417 | // } |
417 | } |
418 | } |
418 | else |
419 | else |
419 | { |
420 | { |
420 | char *export_name; |
421 | char *export_name; |
421 | uint16_t ordinal; |
422 | uint16_t ordinal; |
422 | void *function; |
423 | void *function; |
423 | uint32_t minn; |
424 | uint32_t minn; |
424 | uint32_t maxn; |
425 | uint32_t maxn; |
425 | 426 | ||
426 | imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME, |
427 | imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME, |
427 | thunk->u1.AddressOfData, img_base); |
428 | thunk->u1.AddressOfData, img_base); |
428 | *iat = NULL; |
429 | *iat = NULL; |
429 | 430 | ||
430 | DBG("import %s", imp_name->Name); |
431 | DBG("import %s", imp_name->Name); |
431 | 432 | ||
432 | if(imp_name->Hint < exp->NumberOfNames) |
433 | if(imp_name->Hint < exp->NumberOfNames) |
433 | { |
434 | { |
434 | export_name = MakePtr(char*,exp_names[imp_name->Hint], |
435 | export_name = MakePtr(char*,exp_names[imp_name->Hint], |
435 | api->start); |
436 | api->start); |
436 | if(strcmp(imp_name->Name, export_name) == 0) |
437 | if(strcmp(imp_name->Name, export_name) == 0) |
437 | { |
438 | { |
438 | ordinal = exp_ordinals[imp_name->Hint]; |
439 | ordinal = exp_ordinals[imp_name->Hint]; |
439 | function = MakePtr(void*,exp_functions[ordinal], api->start); |
440 | function = MakePtr(void*,exp_functions[ordinal], api->start); |
440 | if((uint32_t)function >= (uint32_t)exp) |
441 | if((uint32_t)function >= (uint32_t)exp) |
441 | { |
442 | { |
442 | printf("forward %s\n", function); |
443 | printf("forward %s\n", function); |
443 | warn=1; |
444 | warn=1; |
444 | } |
445 | } |
445 | else |
446 | else |
446 | { |
447 | { |
447 | DBG(" \t\tat %x\n", function); |
448 | DBG(" \t\tat %x\n", function); |
448 | *iat = function; |
449 | *iat = function; |
449 | }; |
450 | }; |
450 | thunk++; // Advance to next thunk |
451 | thunk++; // Advance to next thunk |
451 | iat++; |
452 | iat++; |
452 | continue; |
453 | continue; |
453 | }; |
454 | }; |
454 | }; |
455 | }; |
455 | 456 | ||
456 | minn = 0; |
457 | minn = 0; |
457 | maxn = exp->NumberOfNames - 1; |
458 | maxn = exp->NumberOfNames - 1; |
458 | while (minn <= maxn) |
459 | while (minn <= maxn) |
459 | { |
460 | { |
460 | int mid; |
461 | int mid; |
461 | int res; |
462 | int res; |
462 | 463 | ||
463 | mid = (minn + maxn) / 2; |
464 | mid = (minn + maxn) / 2; |
464 | 465 | ||
465 | export_name = MakePtr(char*,exp_names[mid],api->start); |
466 | export_name = MakePtr(char*,exp_names[mid],api->start); |
466 | 467 | ||
467 | res = strcmp(export_name, imp_name->Name); |
468 | res = strcmp(export_name, imp_name->Name); |
468 | if (res == 0) |
469 | if (res == 0) |
469 | { |
470 | { |
470 | ordinal = exp_ordinals[mid]; |
471 | ordinal = exp_ordinals[mid]; |
471 | function = MakePtr(void*,exp_functions[ordinal], api->start); |
472 | function = MakePtr(void*,exp_functions[ordinal], api->start); |
472 | 473 | ||
473 | if((uint32_t)function >= (uint32_t)exp) |
474 | if((uint32_t)function >= (uint32_t)exp) |
474 | { |
475 | { |
475 | printf("forward %s\n", function); |
476 | printf("forward %s\n", function); |
476 | warn=1; |
477 | warn=1; |
477 | } |
478 | } |
478 | else |
479 | else |
479 | { |
480 | { |
480 | DBG(" \t\tat %x\n", function); |
481 | DBG(" \t\tat %x\n", function); |
481 | *iat = function; |
482 | *iat = function; |
482 | }; |
483 | }; |
483 | break; |
484 | break; |
484 | } |
485 | } |
485 | else if (minn == maxn) |
486 | else if (minn == maxn) |
486 | { |
487 | { |
487 | printf(" unresolved %s\n",imp_name->Name); |
488 | printf(" unresolved %s\n",imp_name->Name); |
488 | warn=1; |
489 | warn=1; |
489 | break; |
490 | break; |
490 | } |
491 | } |
491 | else if (res > 0) |
492 | else if (res > 0) |
492 | { |
493 | { |
493 | maxn = mid - 1; |
494 | maxn = mid - 1; |
494 | } |
495 | } |
495 | else |
496 | else |
496 | { |
497 | { |
497 | minn = mid + 1; |
498 | minn = mid + 1; |
498 | } |
499 | } |
499 | }; |
500 | }; |
500 | }; |
501 | }; |
501 | thunk++; // Advance to next thunk |
502 | thunk++; // Advance to next thunk |
502 | iat++; |
503 | iat++; |
503 | } |
504 | } |
504 | imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR |
505 | imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR |
505 | }; |
506 | }; |
506 | 507 | ||
507 | recursion--; |
508 | recursion--; |
508 | 509 | ||
509 | if ( !warn ) |
510 | if ( !warn ) |
510 | return 1; |
511 | return 1; |
511 | else |
512 | else |
512 | return 0; |
513 | return 0; |
513 | } |
514 | } |
514 | 515 | ||
515 | static void send_dbg_msg(void *msg) |
516 | static void send_dbg_msg(void *msg) |
516 | { |
517 | { |
517 | __asm__ __volatile__( |
518 | __asm__ __volatile__( |
518 | "int $0x40" |
519 | "int $0x40" |
519 | ::"a"(69), |
520 | ::"a"(69), |
520 | "b"(10), |
521 | "b"(10), |
521 | "S"(msg)); |
522 | "S"(msg)); |
522 | }; |
523 | }; |
523 | 524 | ||
524 | 525 | ||
525 | int link_app() |
526 | int link_app() |
526 | { |
527 | { |
527 | struct app_hdr *header = NULL; |
528 | struct app_hdr *header = NULL; |
528 | PIMAGE_IMPORT_DESCRIPTOR imp; |
529 | PIMAGE_IMPORT_DESCRIPTOR imp; |
529 | 530 | ||
530 | imp = (PIMAGE_IMPORT_DESCRIPTOR)header->__idata_start; |
531 | imp = (PIMAGE_IMPORT_DESCRIPTOR)header->__idata_start; |
531 | 532 | ||
532 | if(link_image(NULL, imp)) |
533 | if(link_image(NULL, imp)) |
533 | { |
534 | { |
534 | 535 | ||
535 | #ifdef DEBUG_INFO |
536 | #ifdef DEBUG_INFO |
536 | struct |
537 | struct |
537 | { |
538 | { |
538 | void *start; |
539 | void *start; |
539 | uint32_t end; |
540 | uint32_t end; |
540 | char name[24]; |
541 | char name[24]; |
541 | } dbg_msg; |
542 | } dbg_msg; |
542 | 543 | ||
543 | module_t *mod = &libc_dll; |
544 | module_t *mod = &libc_dll; |
544 | 545 | ||
545 | do |
546 | do |
546 | { |
547 | { |
547 | printf("%s %x - %x\n", |
548 | printf("%s %x - %x\n", |
548 | mod->img_name, mod->start, mod->end); |
549 | mod->img_name, mod->start, mod->end); |
549 | 550 | ||
550 | // asm volatile("int3"); |
551 | // asm volatile("int3"); |
551 | 552 | ||
552 | dbg_msg.start = mod->start; |
553 | dbg_msg.start = mod->start; |
553 | dbg_msg.end = mod->end; |
554 | dbg_msg.end = mod->end; |
554 | strcpy(dbg_msg.name, mod->img_name); |
555 | strcpy(dbg_msg.name, mod->img_name); |
555 | send_dbg_msg(&dbg_msg); |
556 | send_dbg_msg(&dbg_msg); |
556 | mod = (module_t*)mod->list.next; |
557 | mod = (module_t*)mod->list.next; |
557 | }while(mod != &libc_dll); |
558 | }while(mod != &libc_dll); |
558 | #endif |
559 | #endif |
559 | 560 | ||
560 | return 1; |
561 | return 1; |
561 | }; |
562 | }; |
562 | 563 | ||
563 | return 0; |
564 | return 0; |
564 | } |
565 | } |
565 | 566 | ||
566 | 567 | ||
567 | void* get_entry_point(void *raw) |
568 | void* get_entry_point(void *raw) |
568 | { |
569 | { |
569 | PIMAGE_DOS_HEADER dos; |
570 | PIMAGE_DOS_HEADER dos; |
570 | PIMAGE_NT_HEADERS32 nt; |
571 | PIMAGE_NT_HEADERS32 nt; |
571 | 572 | ||
572 | dos = (PIMAGE_DOS_HEADER)raw; |
573 | dos = (PIMAGE_DOS_HEADER)raw; |
573 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
574 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
574 | 575 | ||
575 | return MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint); |
576 | return MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint); |
576 | }; |
577 | }; |
577 | 578 | ||
578 | 579 | ||
579 | void *get_proc_address(void *handle, const char *proc_name) |
580 | void *get_proc_address(void *handle, const char *proc_name) |
580 | { |
581 | { |
581 | 582 | ||
582 | module_t *module = handle; |
583 | module_t *module = handle; |
583 | PIMAGE_DOS_HEADER expdos; |
584 | PIMAGE_DOS_HEADER expdos; |
584 | PIMAGE_NT_HEADERS32 expnt; |
585 | PIMAGE_NT_HEADERS32 expnt; |
585 | PIMAGE_EXPORT_DIRECTORY exp; |
586 | PIMAGE_EXPORT_DIRECTORY exp; |
586 | 587 | ||
587 | uint32_t *exp_functions; |
588 | uint32_t *exp_functions; |
588 | uint16_t *exp_ordinals; |
589 | uint16_t *exp_ordinals; |
589 | char **exp_names; |
590 | char **exp_names; |
590 | 591 | ||
591 | int minn, maxn; |
592 | int minn, maxn; |
592 | char *export_name; |
593 | char *export_name; |
593 | uint16_t ordinal; |
594 | uint16_t ordinal; |
594 | void *function=NULL; |
595 | void *function=NULL; |
595 | 596 | ||
596 | exp = module->img_exp; |
597 | exp = module->img_exp; |
597 | 598 | ||
598 | exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,module->start); |
599 | exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,module->start); |
599 | exp_ordinals = MakePtr(uint16_t*, exp->AddressOfNameOrdinals,module->start); |
600 | exp_ordinals = MakePtr(uint16_t*, exp->AddressOfNameOrdinals,module->start); |
600 | exp_names = MakePtr(char**, exp->AddressOfNames,module->start); |
601 | exp_names = MakePtr(char**, exp->AddressOfNames,module->start); |
601 | 602 | ||
602 | minn = 0; |
603 | minn = 0; |
603 | maxn = exp->NumberOfNames - 1; |
604 | maxn = exp->NumberOfNames - 1; |
604 | while (minn <= maxn) |
605 | while (minn <= maxn) |
605 | { |
606 | { |
606 | int mid; |
607 | int mid; |
607 | int res; |
608 | int res; |
608 | 609 | ||
609 | mid = (minn + maxn) / 2; |
610 | mid = (minn + maxn) / 2; |
610 | 611 | ||
611 | export_name = MakePtr(char*,exp_names[mid],module->start); |
612 | export_name = MakePtr(char*,exp_names[mid],module->start); |
612 | 613 | ||
613 | res = strcmp(export_name, proc_name); |
614 | res = strcmp(export_name, proc_name); |
614 | if (res == 0) |
615 | if (res == 0) |
615 | { |
616 | { |
616 | ordinal = exp_ordinals[mid]; |
617 | ordinal = exp_ordinals[mid]; |
617 | function = MakePtr(void*,exp_functions[ordinal], module->start); |
618 | function = MakePtr(void*,exp_functions[ordinal], module->start); |
618 | 619 | ||
619 | if((uint32_t)function >= (uint32_t)exp) |
620 | if((uint32_t)function >= (uint32_t)exp) |
620 | { |
621 | { |
621 | printf("forward %s\n", function); |
622 | printf("forward %s\n", function); |
622 | } |
623 | } |
623 | else |
624 | else |
624 | { |
625 | { |
625 | DBG(" \t\tat %x\n", function); |
626 | DBG(" \t\tat %x\n", function); |
626 | }; |
627 | }; |
627 | break; |
628 | break; |
628 | } |
629 | } |
629 | else if (minn == maxn) |
630 | else if (minn == maxn) |
630 | { |
631 | { |
631 | DBG(" unresolved %s\n",proc_name); |
632 | DBG(" unresolved %s\n",proc_name); |
632 | break; |
633 | break; |
633 | } |
634 | } |
634 | else if (res > 0) |
635 | else if (res > 0) |
635 | { |
636 | { |
636 | maxn = mid - 1; |
637 | maxn = mid - 1; |
637 | } |
638 | } |
638 | else |
639 | else |
639 | { |
640 | { |
640 | minn = mid + 1; |
641 | minn = mid + 1; |
641 | } |
642 | } |
642 | }; |
643 | }; |
643 | 644 | ||
644 | return function; |
645 | return function; |
645 | }; |
646 | }; |
646 | 647 | ||
647 | static void *load_lib_internal(const char *path) |
648 | static void *load_lib_internal(const char *path) |
648 | { |
649 | { |
649 | PIMAGE_DOS_HEADER dos; |
650 | PIMAGE_DOS_HEADER dos; |
650 | PIMAGE_NT_HEADERS32 nt; |
651 | PIMAGE_NT_HEADERS32 nt; |
651 | PIMAGE_EXPORT_DIRECTORY exp; |
652 | PIMAGE_EXPORT_DIRECTORY exp; |
652 | 653 | ||
653 | ufile_t uf; |
654 | ksys_ufile_t uf; |
654 | void *raw_img; |
655 | void *raw_img; |
655 | size_t raw_size; |
656 | size_t raw_size; |
656 | void *img_base = NULL; |
657 | void *img_base = NULL; |
657 | 658 | ||
658 | uf = load_file(path); |
659 | uf = _ksys_load_file(path); |
659 | raw_img = uf.data; |
660 | raw_img = uf.data; |
660 | raw_size = uf.size; |
661 | raw_size = uf.size; |
661 | 662 | ||
662 | if(raw_img == NULL) |
663 | if(raw_img == NULL) |
663 | return NULL; |
664 | return NULL; |
664 | 665 | ||
665 | if( validate_pe(raw_img, raw_size, 0) == 0) |
666 | if( validate_pe(raw_img, raw_size, 0) == 0) |
666 | { |
667 | { |
667 | printf("invalide module %s\n", path); |
668 | printf("invalide module %s\n", path); |
668 | user_free(raw_img); |
669 | _ksys_free(raw_img); |
669 | return NULL; |
670 | return NULL; |
670 | }; |
671 | }; |
671 | 672 | ||
672 | img_base = create_image(raw_img); |
673 | img_base = create_image(raw_img); |
673 | user_free(raw_img); |
674 | _ksys_free(raw_img); |
674 | 675 | ||
675 | if( unlikely(img_base == NULL) ) |
676 | if( unlikely(img_base == NULL) ) |
676 | printf("cannot create image %s\n",path); |
677 | printf("cannot create image %s\n",path); |
677 | 678 | ||
678 | return img_base; |
679 | return img_base; |
679 | } |
680 | } |
680 | 681 | ||
681 | void* load_library(const char *name) |
682 | void* load_library(const char *name) |
682 | { |
683 | { |
683 | PIMAGE_DOS_HEADER dos; |
684 | PIMAGE_DOS_HEADER dos; |
684 | PIMAGE_NT_HEADERS32 nt; |
685 | PIMAGE_NT_HEADERS32 nt; |
685 | PIMAGE_EXPORT_DIRECTORY exp; |
686 | PIMAGE_EXPORT_DIRECTORY exp; |
686 | 687 | ||
687 | module_t *module, *mod = &libc_dll; |
688 | module_t *module, *mod = &libc_dll; |
688 | dll_path_t *dllpath; |
689 | dll_path_t *dllpath; |
689 | char *path; |
690 | char *path; |
690 | int len; |
691 | int len; |
691 | char *libname, *tmp; |
692 | char *libname, *tmp; |
692 | void *img_base; |
693 | void *img_base; |
693 | 694 | ||
694 | 695 | ||
695 | /* check for already loaded libraries */ |
696 | /* check for already loaded libraries */ |
696 | 697 | ||
697 | tmp = strrchr(name, '/'); |
698 | tmp = strrchr(name, '/'); |
698 | libname = path = tmp != NULL ? tmp+1 : (char*)name; |
699 | libname = path = tmp != NULL ? tmp+1 : (char*)name; |
699 | 700 | ||
700 | // printf("path %s\n", path); |
701 | // printf("path %s\n", path); |
701 | 702 | ||
702 | do |
703 | do |
703 | { |
704 | { |
704 | if( !strncmp(path, mod->img_name, 16)) |
705 | if( !strncmp(path, mod->img_name, 16)) |
705 | return mod; |
706 | return mod; |
706 | mod = (module_t*)mod->list.next; |
707 | mod = (module_t*)mod->list.next; |
707 | }while(mod != &libc_dll); |
708 | }while(mod != &libc_dll); |
708 | 709 | ||
709 | if(name[0] == '/') |
710 | if(name[0] == '/') |
710 | { |
711 | { |
711 | path = (char*)name; |
712 | path = (char*)name; |
712 | img_base = load_lib_internal(path); |
713 | img_base = load_lib_internal(path); |
713 | } |
714 | } |
714 | else |
715 | else |
715 | { |
716 | { |
716 | len = strlen(libname); |
717 | len = strlen(libname); |
717 | list_for_each_entry(dllpath, &path_list, list) |
718 | list_for_each_entry(dllpath, &path_list, list) |
718 | { |
719 | { |
719 | path = alloca(len+dllpath->path_len+1); |
720 | path = alloca(len+dllpath->path_len+1); |
720 | memcpy(path, dllpath->path, dllpath->path_len); |
721 | memcpy(path, dllpath->path, dllpath->path_len); |
721 | 722 | ||
722 | memcpy(path+dllpath->path_len, libname, len); |
723 | memcpy(path+dllpath->path_len, libname, len); |
723 | path[len+dllpath->path_len]=0; |
724 | path[len+dllpath->path_len]=0; |
724 | 725 | ||
725 | // printf("%s\n", path); |
726 | // printf("%s\n", path); |
726 | 727 | ||
727 | img_base = load_lib_internal(path); |
728 | img_base = load_lib_internal(path); |
728 | 729 | ||
729 | if( unlikely(img_base == NULL) ) |
730 | if( unlikely(img_base == NULL) ) |
730 | continue; |
731 | continue; |
731 | }; |
732 | }; |
732 | } |
733 | } |
733 | 734 | ||
734 | if( unlikely(img_base == NULL) ) |
735 | if( unlikely(img_base == NULL) ) |
735 | { |
736 | { |
736 | printf("unable to load %s\n", name); |
737 | printf("unable to load %s\n", name); |
737 | return 0; |
738 | return 0; |
738 | }; |
739 | }; |
739 | 740 | ||
740 | module = malloc(sizeof(module_t)); |
741 | module = malloc(sizeof(module_t)); |
741 | 742 | ||
742 | if(unlikely(module == NULL)) |
743 | if(unlikely(module == NULL)) |
743 | { |
744 | { |
744 | printf("%s epic fail: no enough memory\n",__FUNCTION__); |
745 | printf("%s epic fail: no enough memory\n",__FUNCTION__); |
745 | goto err1; |
746 | goto err1; |
746 | } |
747 | } |
747 | 748 | ||
748 | INIT_LIST_HEAD(&module->list); |
749 | INIT_LIST_HEAD(&module->list); |
749 | 750 | ||
750 | module->img_name = strdup(libname); |
751 | module->img_name = strdup(libname); |
751 | module->img_path = strdup(path); |
752 | module->img_path = strdup(path); |
752 | module->start = img_base; |
753 | module->start = img_base; |
753 | module->entry = get_entry_point(img_base); |
754 | module->entry = get_entry_point(img_base); |
754 | module->refcount = 1; |
755 | module->refcount = 1; |
755 | 756 | ||
756 | dos = (PIMAGE_DOS_HEADER)img_base; |
757 | dos = (PIMAGE_DOS_HEADER)img_base; |
757 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
758 | nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
758 | exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base, |
759 | exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base, |
759 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
760 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
760 | 761 | ||
761 | module->end = MakePtr(char*,img_base, nt->OptionalHeader.SizeOfImage); |
762 | module->end = MakePtr(char*,img_base, nt->OptionalHeader.SizeOfImage); |
762 | 763 | ||
763 | module->img_hdr = nt; |
764 | module->img_hdr = nt; |
764 | module->img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
765 | module->img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
765 | module->img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base, |
766 | module->img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base, |
766 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
767 | nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
767 | 768 | ||
768 | list_add_tail(&module->list, &libc_dll.list); |
769 | list_add_tail(&module->list, &libc_dll.list); |
769 | 770 | ||
770 | if(nt->OptionalHeader.DataDirectory[1].Size) |
771 | if(nt->OptionalHeader.DataDirectory[1].Size) |
771 | { |
772 | { |
772 | PIMAGE_IMPORT_DESCRIPTOR imp; |
773 | PIMAGE_IMPORT_DESCRIPTOR imp; |
773 | int (*dll_startup)(module_t *mod, uint32_t reason); |
774 | int (*dll_startup)(module_t *mod, uint32_t reason); |
774 | 775 | ||
775 | imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base, |
776 | imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base, |
776 | nt->OptionalHeader.DataDirectory[1].VirtualAddress); |
777 | nt->OptionalHeader.DataDirectory[1].VirtualAddress); |
777 | 778 | ||
778 | if(link_image(img_base, imp) == 0) |
779 | if(link_image(img_base, imp) == 0) |
779 | goto err2; |
780 | goto err2; |
780 | 781 | ||
781 | dll_startup = get_proc_address(module, "DllStartup"); |
782 | dll_startup = get_proc_address(module, "DllStartup"); |
782 | if( dll_startup ) |
783 | if( dll_startup ) |
783 | { |
784 | { |
784 | if( 0 == dll_startup(module, 1)) |
785 | if( 0 == dll_startup(module, 1)) |
785 | goto err2; |
786 | goto err2; |
786 | } |
787 | } |
787 | }; |
788 | }; |
788 | 789 | ||
789 | // printf("module %s %p - %p\n", name, module->start, module->end); |
790 | // printf("module %s %p - %p\n", name, module->start, module->end); |
790 | 791 | ||
791 | return module; |
792 | return module; |
792 | 793 | ||
793 | err2: |
794 | err2: |
794 | list_del(&module->list); |
795 | list_del(&module->list); |
795 | free(module->img_name); |
796 | free(module->img_name); |
796 | free(module->img_path); |
797 | free(module->img_path); |
797 | free(module); |
798 | free(module); |
798 | err1: |
799 | err1: |
799 | user_free(img_base); |
800 | _ksys_free(img_base); |
800 | return NULL; |
801 | return NULL; |
801 | }; |
802 | }; |
802 | 803 | ||
803 | void enumerate_libraries(int (*callback)(void *handle, const char* name, |
804 | void enumerate_libraries(int (*callback)(void *handle, const char* name, |
804 | uint32_t base, uint32_t size, void *user_data), |
805 | uint32_t base, uint32_t size, void *user_data), |
805 | void *user_data) |
806 | void *user_data) |
806 | { |
807 | { |
807 | module_t *mod = &libc_dll; |
808 | module_t *mod = &libc_dll; |
808 | 809 | ||
809 | do |
810 | do |
810 | { |
811 | { |
811 | if(0 == callback(mod, mod->img_name, (uint32_t)mod->start, |
812 | if(0 == callback(mod, mod->img_name, (uint32_t)mod->start, |
812 | mod->end - mod->start, user_data)) |
813 | mod->end - mod->start, user_data)) |
813 | break; |
814 | break; |
814 | mod = (module_t*)mod->list.next; |
815 | mod = (module_t*)mod->list.next; |
815 | }while(mod != &libc_dll); |
816 | }while(mod != &libc_dll); |
816 | }=>=>>>>>>>=>> |
817 | }=>=>>>>>>>=>> |