Subversion Repositories Kolibri OS

Rev

Rev 4874 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
#include 
2
#include 
3
#include 
4
#include 
5
#include 
6
#include 
7
#include 
8
 
9874 turbocat 9
#include 
4349 Serge 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)
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(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
67
        return 0;
68
 
69
    if(nt->OptionalHeader.SectionAlignment < 4096)
70
    {
71
        if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
72
            return 0;
73
    }
74
    else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
75
        return 0;
76
 
77
    if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
78
       !IsPowerOf2(nt->OptionalHeader.FileAlignment))
79
        return 0;
80
 
81
    if(nt->FileHeader.NumberOfSections > 96)
82
        return 0;
83
 
84
    return 1;
85
}
86
 
87
void* create_image(void *raw)
88
{
89
    PIMAGE_DOS_HEADER     dos;
90
    PIMAGE_NT_HEADERS32   nt;
91
    PIMAGE_SECTION_HEADER img_sec;
92
 
93
    void  *img_base;
94
    uint32_t  sec_align;
95
    int    i;
96
 
97
    dos = (PIMAGE_DOS_HEADER)raw;
98
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
99
 
9874 turbocat 100
    img_base = _ksys_alloc(nt->OptionalHeader.SizeOfImage);
4349 Serge 101
 
102
    if(unlikely(img_base == NULL))
103
        return 0;
104
 
105
    sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
106
 
107
    img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
108
 
109
    sec_align = nt->OptionalHeader.SectionAlignment;
110
 
111
    for(i=0; i< nt->FileHeader.NumberOfSections; i++)
112
    {
113
        void *src_ptr;
114
        void *dest_ptr;
115
        size_t   sec_size;
116
 
117
        if ( img_sec->SizeOfRawData && img_sec->PointerToRawData )
118
        {
119
            src_ptr  = MakePtr(void*, raw, img_sec->PointerToRawData);
120
            dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress);
121
            sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
122
        };
123
 
124
        img_sec++;
125
    };
126
 
127
    if(nt->OptionalHeader.DataDirectory[5].Size)
128
    {
129
        PIMAGE_BASE_RELOCATION reloc;
130
 
131
        uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase;
132
 
133
        reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
134
                        nt->OptionalHeader.DataDirectory[5].VirtualAddress);
135
 
136
        while ( reloc->SizeOfBlock != 0 )
137
        {
138
            uint32_t  cnt;
139
            uint16_t *entry;
140
            uint16_t  reltype;
141
            uint32_t  offs;
142
 
143
            cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t);
144
            entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) );
145
 
146
            for ( i=0; i < cnt; i++ )
147
            {
148
                uint16_t *p16;
149
                uint32_t *p32;
150
 
151
                reltype = (*entry & 0xF000) >> 12;
152
                offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
153
                switch(reltype)
154
                {
155
                    case 1:
156
                        p16 = MakePtr(uint16_t*, img_base, offs);
157
                        *p16+= (uint16_t)(delta>>16);
158
                        break;
159
                    case 2:
160
                        p16 = MakePtr(uint16_t*, img_base, offs);
161
                        *p16+= (uint16_t)delta;
162
                        break;
163
                    case 3:
164
                        p32 = MakePtr(uint32_t*, img_base, offs);
165
                        *p32+= delta;
166
                }
167
                entry++;
168
            }
169
            reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock);
170
        };
171
//        printf("unmap base %p offset %x %d page(s)\n",
172
//                img_base,
173
//                nt->OptionalHeader.DataDirectory[5].VirtualAddress,
174
//                (nt->OptionalHeader.DataDirectory[5].Size+4095)>>12);
175
 
176
        user_unmap(img_base,nt->OptionalHeader.DataDirectory[5].VirtualAddress,
177
                   nt->OptionalHeader.DataDirectory[5].Size);
178
    };
179
    return img_base;
180
};
181
 
182
void* get_entry_point(void *raw)
183
{
184
    PIMAGE_DOS_HEADER     dos;
185
    PIMAGE_NT_HEADERS32   nt;
186
 
187
    dos = (PIMAGE_DOS_HEADER)raw;
188
    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
189
 
190
    return  MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
191
};
192
 
193
 
194
void* load_libc()
195
{
196
    void     *raw_img;
197
    size_t    raw_size;
198
    void     *img_base = NULL;
9874 turbocat 199
    ksys_ufile_t   uf;
4349 Serge 200
 
9874 turbocat 201
    uf = _ksys_load_file("/kolibrios/lib/libc.dll");
4349 Serge 202
 
203
    raw_img   = uf.data;
204
    raw_size  = uf.size;
205
 
206
    if(raw_img == NULL)
207
        return NULL;
208
 
209
//    printf("libc.dll raw %p, size %d\n", raw_img, raw_size);
210
 
211
    if(validate_pe(raw_img, raw_size) != 0)
212
    {
213
//        printf("invalide libc.dll\n");
214
        img_base = create_image(raw_img);
215
    };
216
 
9874 turbocat 217
    _ksys_free(raw_img);
4349 Serge 218
 
219
    return img_base;
220
 
221
}
222