Subversion Repositories Kolibri OS

Rev

Rev 1906 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1906 Rev 1907
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      __fastcall init_loader(void *libc_image);
21
void      __fastcall init_loader(void *libc_image);
22
void*     __fastcall create_image(void *raw);
22
void*     __fastcall create_image(void *raw);
23
int       __fastcall link_image(void *img_base);
23
int       __fastcall link_image(void *img_base);
24
int       __fastcall do_exec(uint32_t my_app, uint32_t *params);
24
int       __fastcall do_exec(uint32_t my_app, uint32_t *params);
25
 
25
 
26
 
26
 
27
extern char* __appenv;
27
extern char* __appenv;
28
extern int   __appenv_size;
28
extern int   __appenv_size;
29
 
29
 
30
typedef struct tag_module module_t;
30
typedef struct tag_module module_t;
31
 
31
 
32
struct app_hdr
32
struct app_hdr
33
{
33
{
34
    char  banner[8];
34
    char  banner[8];
35
    int   version;
35
    int   version;
36
    int   start;
36
    int   start;
37
    int   iend;
37
    int   iend;
38
    int   memsize;
38
    int   memsize;
39
    int   stacktop;
39
    int   stacktop;
40
    char  *cmdline;
40
    char  *cmdline;
41
    char  *path;
41
    char  *path;
42
};
42
};
43
 
43
 
44
struct tag_module
44
struct tag_module
45
{
45
{
46
    struct list_head list;
46
    struct list_head list;
47
 
47
 
48
    char       *img_name;
48
    char       *img_name;
49
    char       *img_path;
49
    char       *img_path;
50
 
50
 
51
    uint32_t    refcount;
51
    uint32_t    refcount;
52
 
52
 
53
    void       *start;
53
    void       *start;
54
    uint32_t    end;
54
    uint32_t    end;
55
 
55
 
56
    void       *entry;
56
    void       *entry;
57
 
57
 
58
    PIMAGE_NT_HEADERS32      img_hdr;
58
    PIMAGE_NT_HEADERS32      img_hdr;
59
    PIMAGE_SECTION_HEADER    img_sec;
59
    PIMAGE_SECTION_HEADER    img_sec;
60
    PIMAGE_EXPORT_DIRECTORY  img_exp;
60
    PIMAGE_EXPORT_DIRECTORY  img_exp;
61
};
61
};
62
 
62
 
63
typedef struct
63
typedef struct
64
{
64
{
65
    struct list_head list;
65
    struct list_head list;
66
    char *path;
66
    char *path;
67
    int   path_len;
67
    int   path_len;
68
}dll_path_t;
68
}dll_path_t;
69
 
69
 
70
module_t* load_module(const char *name);
70
module_t* load_module(const char *name);
71
 
71
 
72
LIST_HEAD(dll_list);
72
LIST_HEAD(dll_list);
73
LIST_HEAD(path_list);
73
LIST_HEAD(path_list);
74
 
74
 
75
static module_t libc_dll;
75
static module_t libc_dll;
76
static char libc_name[] = "libc.dll";
76
static char libc_name[] = "libc.dll";
77
static char libc_path[] = "/sys/lib/libc.dll";
77
static char libc_path[] = "/sys/lib/libc.dll";
78
 
78
 
79
static inline int IsPowerOf2(uint32_t val)
79
static inline int IsPowerOf2(uint32_t val)
80
{
80
{
81
    if(val == 0)
81
    if(val == 0)
82
        return 0;
82
        return 0;
83
    return (val & (val - 1)) == 0;
83
    return (val & (val - 1)) == 0;
84
}
84
}
85
 
85
 
86
 
86
 
87
int validate_pe(void *raw, size_t raw_size, int is_exec)
87
int validate_pe(void *raw, size_t raw_size, int is_exec)
88
{
88
{
89
    PIMAGE_DOS_HEADER     dos;
89
    PIMAGE_DOS_HEADER     dos;
90
    PIMAGE_NT_HEADERS32   nt;
90
    PIMAGE_NT_HEADERS32   nt;
91
 
91
 
92
    dos = (PIMAGE_DOS_HEADER)raw;
92
    dos = (PIMAGE_DOS_HEADER)raw;
93
 
93
 
94
    if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) )
94
    if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) )
95
        return 0;
95
        return 0;
96
 
96
 
97
    if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0)
97
    if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0)
98
        return 0;
98
        return 0;
99
 
99
 
100
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
100
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
101
 
101
 
102
    if( (uint32_t)nt < (uint32_t)raw)
102
    if( (uint32_t)nt < (uint32_t)raw)
103
        return 0;
103
        return 0;
104
 
104
 
105
    if(nt->Signature != IMAGE_NT_SIGNATURE)
105
    if(nt->Signature != IMAGE_NT_SIGNATURE)
106
        return 0;
106
        return 0;
107
 
107
 
108
    if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
108
    if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
109
        return 0;
109
        return 0;
110
 
110
 
111
    if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
111
    if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
112
        return 0;
112
        return 0;
113
 
113
 
114
    if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
114
    if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
115
        return 0;
115
        return 0;
116
 
116
 
117
    if( is_exec && nt->OptionalHeader.ImageBase != 0)
117
    if( is_exec && nt->OptionalHeader.ImageBase != 0)
118
        return 0;
118
        return 0;
119
 
119
 
120
    if(nt->OptionalHeader.SectionAlignment < 4096)
120
    if(nt->OptionalHeader.SectionAlignment < 4096)
121
    {
121
    {
122
        if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
122
        if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
123
            return 0;
123
            return 0;
124
    }
124
    }
125
    else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
125
    else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
126
        return 0;
126
        return 0;
127
 
127
 
128
    if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
128
    if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
129
       !IsPowerOf2(nt->OptionalHeader.FileAlignment))
129
       !IsPowerOf2(nt->OptionalHeader.FileAlignment))
130
        return 0;
130
        return 0;
131
 
131
 
132
    if(nt->FileHeader.NumberOfSections > 96)
132
    if(nt->FileHeader.NumberOfSections > 96)
133
        return 0;
133
        return 0;
134
 
134
 
135
    return 1;
135
    return 1;
136
}
136
}
137
 
137
 
138
 
138
 
139
void __fastcall init_loader(void *libc_image)
139
void __fastcall init_loader(void *libc_image)
140
{
140
{
141
 
141
 
142
    PIMAGE_DOS_HEADER        dos;
142
    PIMAGE_DOS_HEADER        dos;
143
    PIMAGE_NT_HEADERS32      nt;
143
    PIMAGE_NT_HEADERS32      nt;
144
    PIMAGE_EXPORT_DIRECTORY  exp;
144
    PIMAGE_EXPORT_DIRECTORY  exp;
145
 
145
 
146
    struct   app_hdr *header;
146
    struct   app_hdr *header;
147
 
147
 
148
    dll_path_t *path;
148
    dll_path_t *path;
149
    int len;
149
    int len;
150
    char *p;
150
    char *p;
151
 
151
 
152
    if(__appenv_size)
152
    if(__appenv_size)
153
    {
153
    {
154
        char *env;
154
        char *env;
155
        env = envz_get(__appenv, __appenv_size, "PATH");
155
        env = envz_get(__appenv, __appenv_size, "PATH");
156
        if( env )
156
        if( env )
157
        {
157
        {
158
            while( *env )
158
            while( *env )
159
            {
159
            {
160
                p = env;
160
                p = env;
161
                while(*p)
161
                while(*p)
162
                {
162
                {
163
                    if( *p == 0x0D)
163
                    if( *p == 0x0D)
164
                        break;
164
                        break;
165
                    else if( *p == 0x0A)
165
                    else if( *p == 0x0A)
166
                        break;
166
                        break;
167
                    else if( *p == ':')
167
                    else if( *p == ':')
168
                        break;
168
                        break;
169
                    p++;
169
                    p++;
170
                };
170
                };
171
                len = p-env;
171
                len = p-env;
172
                if(len)
172
                if(len)
173
                {
173
                {
174
                    char *p1;
174
                    char *p1;
175
 
175
 
176
                    p1 = (char*)malloc(len+1);
176
                    p1 = (char*)malloc(len+1);
177
                    memcpy(p1, env, len);
177
                    memcpy(p1, env, len);
178
                    p1[len]=0;
178
                    p1[len]=0;
179
 
179
 
180
                    path = (dll_path_t*)malloc(sizeof(dll_path_t));
180
                    path = (dll_path_t*)malloc(sizeof(dll_path_t));
181
                    INIT_LIST_HEAD(&path->list);
181
                    INIT_LIST_HEAD(&path->list);
182
                    path->path = p1;
182
                    path->path = p1;
183
                    path->path_len = len;
183
                    path->path_len = len;
184
                    DBG("add libraries path %s\n", path->path);
184
                    DBG("add libraries path %s\n", path->path);
185
                    list_add_tail(&path->list, &path_list);
185
                    list_add_tail(&path->list, &path_list);
186
                };
186
                };
187
                if(*p == ':')
187
                if(*p == ':')
188
                {
188
                {
189
                    env = p+1;
189
                    env = p+1;
190
                    continue;
190
                    continue;
191
                }
191
                }
192
                else break;
192
                else break;
193
            };
193
            };
194
        };
194
        };
195
    };
195
    };
196
 
196
 
197
    header = (struct app_hdr*)NULL;
197
    header = (struct app_hdr*)NULL;
198
 
198
 
199
    len = strrchr(header->path, '/') - header->path+1;
199
    len = strrchr(header->path, '/') - header->path+1;
200
    p = (char*)malloc(len+1);
200
    p = (char*)malloc(len+1);
201
    memcpy(p, header->path, len);
201
    memcpy(p, header->path, len);
202
    p[len]=0;
202
    p[len]=0;
203
 
203
 
204
    path = (dll_path_t*)malloc(sizeof(dll_path_t));
204
    path = (dll_path_t*)malloc(sizeof(dll_path_t));
205
    INIT_LIST_HEAD(&path->list);
205
    INIT_LIST_HEAD(&path->list);
206
    path->path = p;
206
    path->path = p;
207
    path->path_len = len;
207
    path->path_len = len;
208
    DBG("add libraries path %s\n", path->path);
208
    DBG("add libraries path %s\n", path->path);
209
    list_add_tail(&path->list, &path_list);
209
    list_add_tail(&path->list, &path_list);
210
 
210
 
211
 
211
 
212
#if 0
212
#if 0
213
    path = (dll_path_t*)malloc(sizeof(dll_path_t));
213
    path = (dll_path_t*)malloc(sizeof(dll_path_t));
214
    INIT_LIST_HEAD(&path->list);
214
    INIT_LIST_HEAD(&path->list);
215
    path->path = "/sys/lib/";
215
    path->path = "/sys/lib/";
216
    path->path_len = 9;                           /* FIXME */
216
    path->path_len = 9;                           /* FIXME */
217
    DBG("add libraries path %s\n", path->path);
217
    DBG("add libraries path %s\n", path->path);
218
    list_add_tail(&path->list, &path_list);
218
    list_add_tail(&path->list, &path_list);
219
#endif
219
#endif
220
 
220
 
221
    INIT_LIST_HEAD(&libc_dll.list);
221
    INIT_LIST_HEAD(&libc_dll.list);
222
 
222
 
223
    libc_dll.img_name = libc_name;
223
    libc_dll.img_name = libc_name;
224
    libc_dll.img_path = libc_path;
224
    libc_dll.img_path = libc_path;
225
 
225
 
226
    libc_dll.refcount = 1;
226
    libc_dll.refcount = 1;
227
 
227
 
228
    dos =  (PIMAGE_DOS_HEADER)libc_image;
228
    dos =  (PIMAGE_DOS_HEADER)libc_image;
229
    nt  =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
229
    nt  =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
230
    exp =  MakePtr(PIMAGE_EXPORT_DIRECTORY, libc_image,
230
    exp =  MakePtr(PIMAGE_EXPORT_DIRECTORY, libc_image,
231
                   nt->OptionalHeader.DataDirectory[0].VirtualAddress);
231
                   nt->OptionalHeader.DataDirectory[0].VirtualAddress);
232
 
232
 
233
    libc_dll.start = libc_image;
233
    libc_dll.start = libc_image;
234
    libc_dll.end   = MakePtr(uint32_t,libc_image, nt->OptionalHeader.SizeOfImage);
234
    libc_dll.end   = MakePtr(uint32_t,libc_image, nt->OptionalHeader.SizeOfImage);
235
 
235
 
236
    libc_dll.img_hdr  = nt;
236
    libc_dll.img_hdr  = nt;
237
    libc_dll.img_sec  = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32));
237
    libc_dll.img_sec  = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32));
238
    libc_dll.img_exp  = MakePtr(PIMAGE_EXPORT_DIRECTORY,libc_image,
238
    libc_dll.img_exp  = MakePtr(PIMAGE_EXPORT_DIRECTORY,libc_image,
239
                        nt->OptionalHeader.DataDirectory[0].VirtualAddress);
239
                        nt->OptionalHeader.DataDirectory[0].VirtualAddress);
240
 
240
 
241
    list_add_tail(&libc_dll.list, &dll_list);
241
    list_add_tail(&libc_dll.list, &dll_list);
242
};
242
};
243
 
243
 
244
const module_t* find_module(const char *name)
244
const module_t* find_module(const char *name)
245
{
245
{
246
    module_t* mod;
246
    module_t* mod;
247
 
247
 
248
    list_for_each_entry(mod, &dll_list, list)
248
    list_for_each_entry(mod, &dll_list, list)
249
    {
249
    {
250
        if( !strncmp(name, mod->img_name, 16))
250
        if( !strncmp(name, mod->img_name, 16))
251
            return mod;
251
            return mod;
252
    };
252
    };
253
 
253
 
254
    return load_module(name);
254
    return load_module(name);
255
};
255
};
256
 
256
 
257
static inline void sec_copy(void *dst, void *src, size_t len)
257
static inline void sec_copy(void *dst, void *src, size_t len)
258
{
258
{
259
    __asm__ __volatile__ (
259
    __asm__ __volatile__ (
260
    "shrl $2, %%ecx         \n\t"
260
    "shrl $2, %%ecx         \n\t"
261
    "rep movsl"
261
    "rep movsl"
262
    :
262
    :
263
    :"c"(len),"S"(src),"D"(dst)
263
    :"c"(len),"S"(src),"D"(dst)
264
    :"cc");
264
    :"cc");
265
    __asm__ __volatile__ (
265
    __asm__ __volatile__ (
266
    ""
266
    ""
267
    :::"ecx","esi","edi");
267
    :::"ecx","esi","edi");
268
};
268
};
269
 
269
 
270
static inline void *user_alloc(size_t size)
270
static inline void *user_alloc(size_t size)
271
{
271
{
272
    void *val;
272
    void *val;
273
    __asm__ __volatile__(
273
    __asm__ __volatile__(
274
    "int $0x40"
274
    "int $0x40"
275
    :"=eax"(val)
275
    :"=eax"(val)
276
    :"a"(68),"b"(12),"c"(size));
276
    :"a"(68),"b"(12),"c"(size));
277
    return val;
277
    return val;
278
}
278
}
279
 
279
 
280
void* __fastcall create_image(void *raw)
280
void* __fastcall create_image(void *raw)
281
{
281
{
282
    PIMAGE_DOS_HEADER     dos;
282
    PIMAGE_DOS_HEADER     dos;
283
    PIMAGE_NT_HEADERS32   nt;
283
    PIMAGE_NT_HEADERS32   nt;
284
    PIMAGE_SECTION_HEADER img_sec;
284
    PIMAGE_SECTION_HEADER img_sec;
285
 
285
 
286
    void  *img_base;
286
    void  *img_base;
287
    uint32_t  sec_align;
287
    uint32_t  sec_align;
288
    int    i;
288
    int    i;
289
 
289
 
290
    dos = (PIMAGE_DOS_HEADER)raw;
290
    dos = (PIMAGE_DOS_HEADER)raw;
291
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
291
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
292
 
292
 
293
    img_base = user_alloc(nt->OptionalHeader.SizeOfImage);
293
    img_base = user_alloc(nt->OptionalHeader.SizeOfImage);
294
 
294
 
295
    if(unlikely(img_base == NULL))
295
    if(unlikely(img_base == NULL))
296
        return 0;
296
        return 0;
297
 
297
 
298
    sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
298
    sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
299
 
299
 
300
    img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
300
    img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
301
 
301
 
302
    sec_align = nt->OptionalHeader.SectionAlignment;
302
    sec_align = nt->OptionalHeader.SectionAlignment;
303
 
303
 
304
    for(i=0; i< nt->FileHeader.NumberOfSections; i++)
304
    for(i=0; i< nt->FileHeader.NumberOfSections; i++)
305
    {
305
    {
306
        void *src_ptr;
306
        void *src_ptr;
307
        void *dest_ptr;
307
        void *dest_ptr;
308
        size_t   sec_size;
308
        size_t   sec_size;
309
 
309
 
310
        if ( img_sec->SizeOfRawData && img_sec->PointerToRawData )
310
        if ( img_sec->SizeOfRawData && img_sec->PointerToRawData )
311
        {
311
        {
312
            src_ptr  = MakePtr(void*, raw, img_sec->PointerToRawData);
312
            src_ptr  = MakePtr(void*, raw, img_sec->PointerToRawData);
313
            dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress);
313
            dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress);
314
            sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
314
            sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
315
        };
315
        };
316
 
316
 
317
        img_sec++;
317
        img_sec++;
318
    };
318
    };
319
 
319
 
320
    if(nt->OptionalHeader.DataDirectory[5].Size)
320
    if(nt->OptionalHeader.DataDirectory[5].Size)
321
    {
321
    {
322
        PIMAGE_BASE_RELOCATION reloc;
322
        PIMAGE_BASE_RELOCATION reloc;
323
 
323
 
324
        uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase;
324
        uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase;
325
 
325
 
326
        reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
326
        reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
327
                        nt->OptionalHeader.DataDirectory[5].VirtualAddress);
327
                        nt->OptionalHeader.DataDirectory[5].VirtualAddress);
328
 
328
 
329
        while ( reloc->SizeOfBlock != 0 )
329
        while ( reloc->SizeOfBlock != 0 )
330
        {
330
        {
331
            uint32_t  cnt;
331
            uint32_t  cnt;
332
            uint16_t *entry;
332
            uint16_t *entry;
333
            uint16_t  reltype;
333
            uint16_t  reltype;
334
            uint32_t  offs;
334
            uint32_t  offs;
335
 
335
 
336
            cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t);
336
            cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t);
337
            entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) );
337
            entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) );
338
 
338
 
339
            for ( i=0; i < cnt; i++ )
339
            for ( i=0; i < cnt; i++ )
340
            {
340
            {
341
                uint16_t *p16;
341
                uint16_t *p16;
342
                uint32_t *p32;
342
                uint32_t *p32;
343
 
343
 
344
                reltype = (*entry & 0xF000) >> 12;
344
                reltype = (*entry & 0xF000) >> 12;
345
                offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
345
                offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
346
                switch(reltype)
346
                switch(reltype)
347
                {
347
                {
348
                    case 1:
348
                    case 1:
349
                        p16 = MakePtr(uint16_t*, img_base, offs);
349
                        p16 = MakePtr(uint16_t*, img_base, offs);
350
                        *p16+= (uint16_t)(delta>>16);
350
                        *p16+= (uint16_t)(delta>>16);
351
                        break;
351
                        break;
352
                    case 2:
352
                    case 2:
353
                        p16 = MakePtr(uint16_t*, img_base, offs);
353
                        p16 = MakePtr(uint16_t*, img_base, offs);
354
                        *p16+= (uint16_t)delta;
354
                        *p16+= (uint16_t)delta;
355
                        break;
355
                        break;
356
                    case 3:
356
                    case 3:
357
                        p32 = MakePtr(uint32_t*, img_base, offs);
357
                        p32 = MakePtr(uint32_t*, img_base, offs);
358
                        *p32+= delta;
358
                        *p32+= delta;
359
                }
359
                }
360
                entry++;
360
                entry++;
361
            }
361
            }
362
            reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock);
362
            reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock);
363
        }
363
        }
364
    };
364
    };
365
    return img_base;
365
    return img_base;
366
};
366
};
367
 
367
 
368
int __fastcall link_image(void *img_base)
368
int __fastcall link_image(void *img_base)
369
{
369
{
370
    static jmp_buf loader_env;
370
    static jmp_buf loader_env;
371
    static recursion = -1;
371
    static recursion = -1;
372
 
372
 
373
    PIMAGE_DOS_HEADER     dos;
373
    PIMAGE_DOS_HEADER     dos;
374
    PIMAGE_NT_HEADERS32   nt;
374
    PIMAGE_NT_HEADERS32   nt;
375
    int warn = 0;
375
    int warn = 0;
376
 
376
 
377
    recursion++;
377
    recursion++;
378
    if( !recursion )
378
    if( !recursion )
379
    {
379
    {
380
        if( unlikely(setjmp(loader_env) != 0))
380
        if( unlikely(setjmp(loader_env) != 0))
381
        {
381
        {
382
            recursion = -1;
382
            recursion = -1;
383
            return 0;
383
            return 0;
384
        };
384
        };
385
    };
385
    };
386
 
386
 
387
    dos = (PIMAGE_DOS_HEADER)img_base;
387
    dos = (PIMAGE_DOS_HEADER)img_base;
388
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
388
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
389
 
389
 
390
    if(nt->OptionalHeader.DataDirectory[1].Size)
390
    if(nt->OptionalHeader.DataDirectory[1].Size)
391
    {
391
    {
392
        PIMAGE_IMPORT_DESCRIPTOR imp;
392
        PIMAGE_IMPORT_DESCRIPTOR imp;
393
 
393
 
394
        imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base,
394
        imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base,
395
                      nt->OptionalHeader.DataDirectory[1].VirtualAddress);
395
                      nt->OptionalHeader.DataDirectory[1].VirtualAddress);
396
 
396
 
397
        while ( imp->Name )
397
        while ( imp->Name )
398
        {
398
        {
399
            PIMAGE_DOS_HEADER        expdos;
399
            PIMAGE_DOS_HEADER        expdos;
400
            PIMAGE_NT_HEADERS32      expnt;
400
            PIMAGE_NT_HEADERS32      expnt;
401
            PIMAGE_EXPORT_DIRECTORY  exp;
401
            PIMAGE_EXPORT_DIRECTORY  exp;
402
            PIMAGE_THUNK_DATA32      thunk;
402
            PIMAGE_THUNK_DATA32      thunk;
403
 
403
 
404
            void       **iat;
404
            void       **iat;
405
            char       *libname;
405
            char       *libname;
406
            uint32_t   *exp_functions;
406
            uint32_t   *exp_functions;
407
            uint16_t   *exp_ordinals;
407
            uint16_t   *exp_ordinals;
408
            char      **exp_names;
408
            char      **exp_names;
409
 
409
 
410
            const module_t *api;
410
            const module_t *api;
411
 
411
 
412
            libname=MakePtr(char*,imp->Name, img_base);
412
            libname=MakePtr(char*,imp->Name, img_base);
413
 
413
 
414
            DBG("import from %s\n",libname);
414
            DBG("import from %s\n",libname);
415
 
415
 
416
            api = find_module(libname);
416
            api = find_module(libname);
417
            if(unlikely(api == NULL))
417
            if(unlikely(api == NULL))
418
            {
418
            {
419
                printf("library %s not found\n", libname);
419
                printf("library %s not found\n", libname);
420
                longjmp(loader_env, 1);
420
                longjmp(loader_env, 1);
421
            }
421
            }
422
 
422
 
423
            iat = MakePtr(void**,imp->FirstThunk, img_base);
423
            iat = MakePtr(void**,imp->FirstThunk, img_base);
424
 
424
 
425
            if(imp->OriginalFirstThunk !=0 )
425
            if(imp->OriginalFirstThunk !=0 )
426
            {
426
            {
427
                thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->OriginalFirstThunk, img_base);
427
                thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->OriginalFirstThunk, img_base);
428
            }
428
            }
429
            else
429
            else
430
            {
430
            {
431
                thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->FirstThunk, img_base);
431
                thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->FirstThunk, img_base);
432
            };
432
            };
433
 
433
 
434
            exp = api->img_exp;
434
            exp = api->img_exp;
435
 
435
 
436
            exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,api->start);
436
            exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,api->start);
437
            exp_ordinals = MakePtr(uint16_t*,  exp->AddressOfNameOrdinals,api->start);
437
            exp_ordinals = MakePtr(uint16_t*,  exp->AddressOfNameOrdinals,api->start);
438
            exp_names = MakePtr(char**, exp->AddressOfNames,api->start);
438
            exp_names = MakePtr(char**, exp->AddressOfNames,api->start);
439
 
439
 
440
            while ( thunk->u1.AddressOfData != 0 )
440
            while ( thunk->u1.AddressOfData != 0 )
441
            {
441
            {
442
                PIMAGE_IMPORT_BY_NAME imp_name;
442
                PIMAGE_IMPORT_BY_NAME imp_name;
443
 
443
 
444
                if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
444
                if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
445
                {
445
                {
446
//                    ordinal = (*func_list) & 0x7fffffff;
446
//                    ordinal = (*func_list) & 0x7fffffff;
447
//                   *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal);
447
//                   *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal);
448
//                    if ((*ImportAddressList) == NULL)
448
//                    if ((*ImportAddressList) == NULL)
449
//                    {
449
//                    {
450
//                        DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName);
450
//                        DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName);
451
//                        RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName);
451
//                        RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName);
452
//                        return STATUS_ENTRYPOINT_NOT_FOUND;
452
//                        return STATUS_ENTRYPOINT_NOT_FOUND;
453
//                    }
453
//                    }
454
                }
454
                }
455
                else
455
                else
456
                {
456
                {
457
                    char *export_name;
457
                    char *export_name;
458
                    uint16_t   ordinal;
458
                    uint16_t   ordinal;
459
                    void      *function;
459
                    void      *function;
460
                    uint32_t   minn;
460
                    uint32_t   minn;
461
                    uint32_t   maxn;
461
                    uint32_t   maxn;
462
 
462
 
463
                    imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME,
463
                    imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME,
464
                                  thunk->u1.AddressOfData, img_base);
464
                                  thunk->u1.AddressOfData, img_base);
465
                    *iat = NULL;
465
                    *iat = NULL;
466
 
466
 
467
                    DBG("import %s", imp_name->Name);
467
                    DBG("import %s", imp_name->Name);
468
 
468
 
469
                    if(imp_name->Hint < exp->NumberOfNames)
469
                    if(imp_name->Hint < exp->NumberOfNames)
470
                    {
470
                    {
471
                        export_name = MakePtr(char*,exp_names[imp_name->Hint],
471
                        export_name = MakePtr(char*,exp_names[imp_name->Hint],
472
                                              api->start);
472
                                              api->start);
473
                        if(strcmp(imp_name->Name, export_name) == 0)
473
                        if(strcmp(imp_name->Name, export_name) == 0)
474
                        {
474
                        {
475
                            ordinal = exp_ordinals[imp_name->Hint];
475
                            ordinal = exp_ordinals[imp_name->Hint];
476
                            function = MakePtr(void*,exp_functions[ordinal], api->start);
476
                            function = MakePtr(void*,exp_functions[ordinal], api->start);
477
                            if((uint32_t)function >= (uint32_t)exp)
477
                            if((uint32_t)function >= (uint32_t)exp)
478
                            {
478
                            {
479
                                printf("forward %s\n", function);
479
                                printf("forward %s\n", function);
480
                                warn=1;
480
                                warn=1;
481
                            }
481
                            }
482
                            else
482
                            else
483
                            {
483
                            {
484
                                DBG(" \t\tat %x\n", function);
484
                                DBG(" \t\tat %x\n", function);
485
                                *iat = function;
485
                                *iat = function;
486
                            };
486
                            };
487
                            thunk++;  // Advance to next thunk
487
                            thunk++;  // Advance to next thunk
488
                            iat++;
488
                            iat++;
489
                            continue;
489
                            continue;
490
                        };
490
                        };
491
                    };
491
                    };
492
 
492
 
493
 
493
 
494
                    minn = 0;
494
                    minn = 0;
495
                    maxn = exp->NumberOfNames - 1;
495
                    maxn = exp->NumberOfNames - 1;
496
                    while (minn <= maxn)
496
                    while (minn <= maxn)
497
                    {
497
                    {
498
                        int mid;
498
                        int mid;
499
                        int res;
499
                        int res;
500
 
500
 
501
                        mid = (minn + maxn) / 2;
501
                        mid = (minn + maxn) / 2;
502
 
502
 
503
                        export_name = MakePtr(char*,exp_names[mid],api->start);
503
                        export_name = MakePtr(char*,exp_names[mid],api->start);
504
 
504
 
505
                        res = strcmp(export_name, imp_name->Name);
505
                        res = strcmp(export_name, imp_name->Name);
506
                        if (res == 0)
506
                        if (res == 0)
507
                        {
507
                        {
508
                            ordinal  = exp_ordinals[mid];
508
                            ordinal  = exp_ordinals[mid];
509
                            function = MakePtr(void*,exp_functions[ordinal], api->start);
509
                            function = MakePtr(void*,exp_functions[ordinal], api->start);
510
 
510
 
511
                            if((uint32_t)function >= (uint32_t)exp)
511
                            if((uint32_t)function >= (uint32_t)exp)
512
                            {
512
                            {
513
                                printf("forward %s\n", function);
513
                                printf("forward %s\n", function);
514
                                warn=1;
514
                                warn=1;
515
                            }
515
                            }
516
                            else
516
                            else
517
                            {
517
                            {
518
                                DBG(" \t\tat %x\n", function);
518
                                DBG(" \t\tat %x\n", function);
519
                                *iat = function;
519
                                *iat = function;
520
                            };
520
                            };
521
                            break;
521
                            break;
522
                        }
522
                        }
523
                        else if (minn == maxn)
523
                        else if (minn == maxn)
524
                        {
524
                        {
525
                            printf(" unresolved\n",imp_name->Name);
525
                            printf(" unresolved %s\n",imp_name->Name);
526
                            warn=1;
526
                            warn=1;
527
                            break;
527
                            break;
528
                        }
528
                        }
529
                        else if (res > 0)
529
                        else if (res > 0)
530
                        {
530
                        {
531
                            maxn = mid - 1;
531
                            maxn = mid - 1;
532
                        }
532
                        }
533
                        else
533
                        else
534
                        {
534
                        {
535
                            minn = mid + 1;
535
                            minn = mid + 1;
536
                        }
536
                        }
537
                    };
537
                    };
538
                };
538
                };
539
                thunk++;            // Advance to next thunk
539
                thunk++;            // Advance to next thunk
540
                iat++;
540
                iat++;
541
            }
541
            }
542
            imp++;  // advance to next IMAGE_IMPORT_DESCRIPTOR
542
            imp++;  // advance to next IMAGE_IMPORT_DESCRIPTOR
543
        };
543
        };
544
    };
544
    };
545
 
545
 
546
    recursion--;
546
    recursion--;
547
 
547
 
548
    if ( !warn )
548
    if ( !warn )
549
        return 1;
549
        return 1;
550
    else
550
    else
551
        return 0;
551
        return 0;
552
}
552
}
553
 
553
 
554
void* get_entry_point(void *raw)
554
void* get_entry_point(void *raw)
555
{
555
{
556
    PIMAGE_DOS_HEADER     dos;
556
    PIMAGE_DOS_HEADER     dos;
557
    PIMAGE_NT_HEADERS32   nt;
557
    PIMAGE_NT_HEADERS32   nt;
558
 
558
 
559
    dos = (PIMAGE_DOS_HEADER)raw;
559
    dos = (PIMAGE_DOS_HEADER)raw;
560
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
560
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
561
 
561
 
562
    return  MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
562
    return  MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
563
}
563
}
564
 
564
 
565
 
565
 
566
module_t* load_module(const char *name)
566
module_t* load_module(const char *name)
567
{
567
{
568
    char *path;
568
    char *path;
569
    int   len;
569
    int   len;
570
 
570
 
571
    len = strlen(name);
571
    len = strlen(name);
572
 
572
 
573
    dll_path_t *dllpath;
573
    dll_path_t *dllpath;
574
 
574
 
575
    list_for_each_entry(dllpath, &path_list, list)
575
    list_for_each_entry(dllpath, &path_list, list)
576
    {
576
    {
577
        PIMAGE_DOS_HEADER        dos;
577
        PIMAGE_DOS_HEADER        dos;
578
        PIMAGE_NT_HEADERS32      nt;
578
        PIMAGE_NT_HEADERS32      nt;
579
        PIMAGE_EXPORT_DIRECTORY  exp;
579
        PIMAGE_EXPORT_DIRECTORY  exp;
580
 
580
 
581
        module_t *module;
581
        module_t *module;
582
        void     *raw_img;
582
        void     *raw_img;
583
        size_t    raw_size;
583
        size_t    raw_size;
584
        void     *img_base;
584
        void     *img_base;
585
 
585
 
586
        path = alloca(len+dllpath->path_len+1);
586
        path = alloca(len+dllpath->path_len+1);
587
        memcpy(path, dllpath->path, dllpath->path_len);
587
        memcpy(path, dllpath->path, dllpath->path_len);
588
 
588
 
589
        memcpy(path+dllpath->path_len, name, len);
589
        memcpy(path+dllpath->path_len, name, len);
590
        path[len+dllpath->path_len]=0;
590
        path[len+dllpath->path_len]=0;
591
 
591
 
592
        raw_img = load_file(path, &raw_size);
592
        raw_img = load_file(path, &raw_size);
593
        if(raw_img == NULL)
593
        if(raw_img == NULL)
594
            continue;
594
            continue;
595
 
595
 
596
        if( validate_pe(raw_img, raw_size, 0) == 0)
596
        if( validate_pe(raw_img, raw_size, 0) == 0)
597
        {
597
        {
598
            printf("invalide module %s\n", path);
598
            printf("invalide module %s\n", path);
599
            user_free(raw_img);
599
            user_free(raw_img);
600
            continue;
600
            continue;
601
        };
601
        };
602
 
602
 
603
        img_base = create_image(raw_img);
603
        img_base = create_image(raw_img);
604
        user_free(raw_img);
604
        user_free(raw_img);
605
 
605
 
606
        if( unlikely(img_base == NULL) )
606
        if( unlikely(img_base == NULL) )
607
        {
607
        {
608
            printf("cannot create image %s\n",path);
608
            printf("cannot create image %s\n",path);
609
            continue;
609
            continue;
610
        };
610
        };
611
 
611
 
612
        module = (module_t*)malloc(sizeof(module_t));
612
        module = (module_t*)malloc(sizeof(module_t));
613
 
613
 
614
        if(unlikely(module == NULL))
614
        if(unlikely(module == NULL))
615
        {
615
        {
616
            printf("%s epic fail: no enough memory\n",__FUNCTION__);
616
            printf("%s epic fail: no enough memory\n",__FUNCTION__);
617
            user_free(img_base);
617
            user_free(img_base);
618
            return 0;
618
            return 0;
619
        }
619
        }
620
 
620
 
621
        INIT_LIST_HEAD(&module->list);
621
        INIT_LIST_HEAD(&module->list);
622
 
622
 
623
        module->img_name = strdup(name);
623
        module->img_name = strdup(name);
624
        module->img_path = strdup(path);
624
        module->img_path = strdup(path);
625
        module->start    = img_base;
625
        module->start    = img_base;
626
        module->entry    = get_entry_point(img_base);
626
        module->entry    = get_entry_point(img_base);
627
        module->refcount = 1;
627
        module->refcount = 1;
628
 
628
 
629
        dos =  (PIMAGE_DOS_HEADER)img_base;
629
        dos =  (PIMAGE_DOS_HEADER)img_base;
630
        nt  =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
630
        nt  =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
631
        exp =  MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
631
        exp =  MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
632
                   nt->OptionalHeader.DataDirectory[0].VirtualAddress);
632
                   nt->OptionalHeader.DataDirectory[0].VirtualAddress);
633
 
633
 
634
        module->end   = MakePtr(uint32_t,img_base, nt->OptionalHeader.SizeOfImage);
634
        module->end   = MakePtr(uint32_t,img_base, nt->OptionalHeader.SizeOfImage);
635
 
635
 
636
        module->img_hdr  = nt;
636
        module->img_hdr  = nt;
637
        module->img_sec  = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32));
637
        module->img_sec  = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32));
638
        module->img_exp  = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
638
        module->img_exp  = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
639
                           nt->OptionalHeader.DataDirectory[0].VirtualAddress);
639
                           nt->OptionalHeader.DataDirectory[0].VirtualAddress);
640
 
640
 
641
        list_add_tail(&module->list, &dll_list);
641
        list_add_tail(&module->list, &dll_list);
642
 
642
 
643
        if( link_image(img_base))
643
        if( link_image(img_base))
644
            return module;
644
            return module;
645
        return NULL;
645
        return NULL;
646
    };
646
    };
647
 
647
 
648
    return NULL;
648
    return NULL;
649
};
649
};