Subversion Repositories Kolibri OS

Rev

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

Rev 3809 Rev 3915
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
static inline void sec_copy(void *dst, void *src, size_t len)
20
static inline void sec_copy(void *dst, void *src, size_t len)
21
{
21
{
22
    __asm__ __volatile__ (
22
    __asm__ __volatile__ (
23
    "shrl $2, %%ecx         \n\t"
23
    "shrl $2, %%ecx         \n\t"
24
    "rep movsl"
24
    "rep movsl"
25
    :
25
    :
26
    :"c"(len),"S"(src),"D"(dst)
26
    :"c"(len),"S"(src),"D"(dst)
27
    :"cc");
27
    :"cc");
28
    __asm__ __volatile__ (
28
    __asm__ __volatile__ (
29
    ""
29
    ""
30
    :::"ecx","esi","edi");
30
    :::"ecx","esi","edi");
31
};
31
};
32
 
32
 
33
void* load_libc();
33
void* load_libc();
34
 
34
 
35
static inline int IsPowerOf2(uint32_t val)
35
static inline int IsPowerOf2(uint32_t val)
36
{
36
{
37
    if(val == 0)
37
    if(val == 0)
38
        return 0;
38
        return 0;
39
    return (val & (val - 1)) == 0;
39
    return (val & (val - 1)) == 0;
40
}
40
}
41
 
41
 
42
int validate_pe(void *raw, size_t raw_size, int is_exec)
42
int validate_pe(void *raw, size_t raw_size)
43
{
43
{
44
    PIMAGE_DOS_HEADER     dos;
44
    PIMAGE_DOS_HEADER     dos;
45
    PIMAGE_NT_HEADERS32   nt;
45
    PIMAGE_NT_HEADERS32   nt;
46
 
46
 
47
    dos = (PIMAGE_DOS_HEADER)raw;
47
    dos = (PIMAGE_DOS_HEADER)raw;
48
 
48
 
49
    if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) )
49
    if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) )
50
        return 0;
50
        return 0;
51
 
51
 
52
    if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0)
52
    if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0)
53
        return 0;
53
        return 0;
54
 
54
 
55
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
55
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
56
 
56
 
57
    if( (uint32_t)nt < (uint32_t)raw)
57
    if( (uint32_t)nt < (uint32_t)raw)
58
        return 0;
58
        return 0;
59
 
59
 
60
    if(nt->Signature != IMAGE_NT_SIGNATURE)
60
    if(nt->Signature != IMAGE_NT_SIGNATURE)
61
        return 0;
61
        return 0;
62
 
62
 
63
    if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
63
    if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
64
        return 0;
64
        return 0;
65
 
-
 
66
    if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
-
 
67
        return 0;
-
 
68
 
65
 
69
    if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
66
    if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
70
        return 0;
67
        return 0;
71
 
-
 
72
    if( is_exec && nt->OptionalHeader.ImageBase != 0)
-
 
73
        return 0;
-
 
74
 
68
 
75
    if(nt->OptionalHeader.SectionAlignment < 4096)
69
    if(nt->OptionalHeader.SectionAlignment < 4096)
76
    {
70
    {
77
        if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
71
        if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
78
            return 0;
72
            return 0;
79
    }
73
    }
80
    else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
74
    else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
81
        return 0;
75
        return 0;
82
 
76
 
83
    if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
77
    if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
84
       !IsPowerOf2(nt->OptionalHeader.FileAlignment))
78
       !IsPowerOf2(nt->OptionalHeader.FileAlignment))
85
        return 0;
79
        return 0;
86
 
80
 
87
    if(nt->FileHeader.NumberOfSections > 96)
81
    if(nt->FileHeader.NumberOfSections > 96)
88
        return 0;
82
        return 0;
89
 
83
 
90
    return 1;
84
    return 1;
91
}
85
}
92
 
86
 
93
void* create_image(void *raw)
87
void* create_image(void *raw)
94
{
88
{
95
    PIMAGE_DOS_HEADER     dos;
89
    PIMAGE_DOS_HEADER     dos;
96
    PIMAGE_NT_HEADERS32   nt;
90
    PIMAGE_NT_HEADERS32   nt;
97
    PIMAGE_SECTION_HEADER img_sec;
91
    PIMAGE_SECTION_HEADER img_sec;
98
 
92
 
99
    void  *img_base;
93
    void  *img_base;
100
    uint32_t  sec_align;
94
    uint32_t  sec_align;
101
    int    i;
95
    int    i;
102
 
96
 
103
    dos = (PIMAGE_DOS_HEADER)raw;
97
    dos = (PIMAGE_DOS_HEADER)raw;
104
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
98
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
105
 
99
 
106
    img_base = user_alloc(nt->OptionalHeader.SizeOfImage);
100
    img_base = user_alloc(nt->OptionalHeader.SizeOfImage);
107
 
101
 
108
    if(unlikely(img_base == NULL))
102
    if(unlikely(img_base == NULL))
109
        return 0;
103
        return 0;
110
 
104
 
111
    sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
105
    sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
112
 
106
 
113
    img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
107
    img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
114
 
108
 
115
    sec_align = nt->OptionalHeader.SectionAlignment;
109
    sec_align = nt->OptionalHeader.SectionAlignment;
116
 
110
 
117
    for(i=0; i< nt->FileHeader.NumberOfSections; i++)
111
    for(i=0; i< nt->FileHeader.NumberOfSections; i++)
118
    {
112
    {
119
        void *src_ptr;
113
        void *src_ptr;
120
        void *dest_ptr;
114
        void *dest_ptr;
121
        size_t   sec_size;
115
        size_t   sec_size;
122
 
116
 
123
        if ( img_sec->SizeOfRawData && img_sec->PointerToRawData )
117
        if ( img_sec->SizeOfRawData && img_sec->PointerToRawData )
124
        {
118
        {
125
            src_ptr  = MakePtr(void*, raw, img_sec->PointerToRawData);
119
            src_ptr  = MakePtr(void*, raw, img_sec->PointerToRawData);
126
            dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress);
120
            dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress);
127
            sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
121
            sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
128
        };
122
        };
129
 
123
 
130
        img_sec++;
124
        img_sec++;
131
    };
125
    };
132
 
126
 
133
    if(nt->OptionalHeader.DataDirectory[5].Size)
127
    if(nt->OptionalHeader.DataDirectory[5].Size)
134
    {
128
    {
135
        PIMAGE_BASE_RELOCATION reloc;
129
        PIMAGE_BASE_RELOCATION reloc;
136
 
130
 
137
        uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase;
131
        uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase;
138
 
132
 
139
        reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
133
        reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
140
                        nt->OptionalHeader.DataDirectory[5].VirtualAddress);
134
                        nt->OptionalHeader.DataDirectory[5].VirtualAddress);
141
 
135
 
142
        while ( reloc->SizeOfBlock != 0 )
136
        while ( reloc->SizeOfBlock != 0 )
143
        {
137
        {
144
            uint32_t  cnt;
138
            uint32_t  cnt;
145
            uint16_t *entry;
139
            uint16_t *entry;
146
            uint16_t  reltype;
140
            uint16_t  reltype;
147
            uint32_t  offs;
141
            uint32_t  offs;
148
 
142
 
149
            cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t);
143
            cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t);
150
            entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) );
144
            entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) );
151
 
145
 
152
            for ( i=0; i < cnt; i++ )
146
            for ( i=0; i < cnt; i++ )
153
            {
147
            {
154
                uint16_t *p16;
148
                uint16_t *p16;
155
                uint32_t *p32;
149
                uint32_t *p32;
156
 
150
 
157
                reltype = (*entry & 0xF000) >> 12;
151
                reltype = (*entry & 0xF000) >> 12;
158
                offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
152
                offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
159
                switch(reltype)
153
                switch(reltype)
160
                {
154
                {
161
                    case 1:
155
                    case 1:
162
                        p16 = MakePtr(uint16_t*, img_base, offs);
156
                        p16 = MakePtr(uint16_t*, img_base, offs);
163
                        *p16+= (uint16_t)(delta>>16);
157
                        *p16+= (uint16_t)(delta>>16);
164
                        break;
158
                        break;
165
                    case 2:
159
                    case 2:
166
                        p16 = MakePtr(uint16_t*, img_base, offs);
160
                        p16 = MakePtr(uint16_t*, img_base, offs);
167
                        *p16+= (uint16_t)delta;
161
                        *p16+= (uint16_t)delta;
168
                        break;
162
                        break;
169
                    case 3:
163
                    case 3:
170
                        p32 = MakePtr(uint32_t*, img_base, offs);
164
                        p32 = MakePtr(uint32_t*, img_base, offs);
171
                        *p32+= delta;
165
                        *p32+= delta;
172
                }
166
                }
173
                entry++;
167
                entry++;
174
            }
168
            }
175
            reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock);
169
            reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock);
176
        };
170
        };
177
//        printf("unmap base %p offset %x %d page(s)\n",
171
//        printf("unmap base %p offset %x %d page(s)\n",
178
//                img_base,
172
//                img_base,
179
//                nt->OptionalHeader.DataDirectory[5].VirtualAddress,
173
//                nt->OptionalHeader.DataDirectory[5].VirtualAddress,
180
//                (nt->OptionalHeader.DataDirectory[5].Size+4095)>>12);
174
//                (nt->OptionalHeader.DataDirectory[5].Size+4095)>>12);
181
 
175
 
182
        user_unmap(img_base,nt->OptionalHeader.DataDirectory[5].VirtualAddress,
176
        user_unmap(img_base,nt->OptionalHeader.DataDirectory[5].VirtualAddress,
183
                   nt->OptionalHeader.DataDirectory[5].Size);
177
                   nt->OptionalHeader.DataDirectory[5].Size);
184
    };
178
    };
185
    return img_base;
179
    return img_base;
186
};
180
};
187
 
181
 
188
void* get_entry_point(void *raw)
182
void* get_entry_point(void *raw)
189
{
183
{
190
    PIMAGE_DOS_HEADER     dos;
184
    PIMAGE_DOS_HEADER     dos;
191
    PIMAGE_NT_HEADERS32   nt;
185
    PIMAGE_NT_HEADERS32   nt;
192
 
186
 
193
    dos = (PIMAGE_DOS_HEADER)raw;
187
    dos = (PIMAGE_DOS_HEADER)raw;
194
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
188
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
195
 
189
 
196
    return  MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
190
    return  MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
197
};
191
};
198
 
192
 
199
 
193
 
200
void* load_libc()
194
void* load_libc()
201
{
195
{
202
    void     *raw_img;
196
    void     *raw_img;
203
    size_t    raw_size;
197
    size_t    raw_size;
204
    void     *img_base = NULL;
198
    void     *img_base = NULL;
205
    ufile_t   uf;
199
    ufile_t   uf;
206
 
200
 
207
    uf = load_file("/kolibrios/lib/libc.dll");
201
    uf = load_file("/kolibrios/lib/libc.dll");
208
 
202
 
209
    raw_img   = uf.data;
203
    raw_img   = uf.data;
210
    raw_size  = uf.size;
204
    raw_size  = uf.size;
211
 
205
 
212
    if(raw_img == NULL)
206
    if(raw_img == NULL)
213
        return NULL;
207
        return NULL;
214
 
208
 
215
//    printf("libc.dll raw %p, size %d\n", raw_img, raw_size);
209
//    printf("libc.dll raw %p, size %d\n", raw_img, raw_size);
216
 
210
 
217
    if(validate_pe(raw_img, raw_size, 0) != 0)
211
    if(validate_pe(raw_img, raw_size) != 0)
218
    {
212
    {
219
//        printf("invalide libc.dll\n");
213
//        printf("invalide libc.dll\n");
220
        img_base = create_image(raw_img);
214
        img_base = create_image(raw_img);
221
    };
215
    };
222
 
216
 
223
    user_free(raw_img);
217
    user_free(raw_img);
224
 
218
 
225
    return img_base;
219
    return img_base;
226
 
220
 
227
}
221
}