Subversion Repositories Kolibri OS

Rev

Rev 3799 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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