Statistics
| Branch: | Revision:

root / linux-user / main.c @ 31e31b8a

History | View | Annotate | Download (7.1 kB)

1
/*
2
 *  emu main
3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 */
20
#include <stdlib.h>
21
#include <stdio.h>
22
#include <stdarg.h>
23
#include <elf.h>
24
#include <endian.h>
25
#include <errno.h>
26

    
27
#include "gemu.h"
28

    
29
#include "i386/hsw_interp.h"
30

    
31
unsigned long x86_stack_size;
32
unsigned long stktop;
33

    
34
void gemu_log(const char *fmt, ...)
35
{
36
    va_list ap;
37

    
38
    va_start(ap, fmt);
39
    vfprintf(stderr, fmt, ap);
40
    va_end(ap);
41
}
42

    
43
/* virtual x86 CPU stuff */
44

    
45
extern int invoke_code16(Interp_ENV *, int, int);
46
extern int invoke_code32(Interp_ENV *, int);
47
extern char *e_print_cpuemu_regs(ENVPARAMS, int is32);
48
extern char *e_emu_disasm(ENVPARAMS, unsigned char *org, int is32);
49
extern void init_npu(void);
50

    
51
Interp_ENV env_global;
52
Interp_ENV *envp_global;
53

    
54
QWORD EMUtime = 0;
55

    
56
int CEmuStat = 0;
57

    
58
long instr_count;
59

    
60
/* who will initialize this? */
61
unsigned long io_bitmap[IO_BITMAP_SIZE+1];
62

    
63
/* debug flag, 0=disable 1..9=level */
64
int d_emu = 0;
65

    
66
unsigned long CRs[5] =
67
{
68
        0x00000013,        /* valid bits: 0xe005003f */
69
        0x00000000,        /* invalid */
70
        0x00000000,
71
        0x00000000,
72
        0x00000000
73
};
74

    
75
/*
76
 * DR0-3 = linear address of breakpoint 0-3
77
 * DR4=5 = reserved
78
 * DR6        b0-b3 = BP active
79
 *        b13   = BD
80
 *        b14   = BS
81
 *        b15   = BT
82
 * DR7        b0-b1 = G:L bp#0
83
 *        b2-b3 = G:L bp#1
84
 *        b4-b5 = G:L bp#2
85
 *        b6-b7 = G:L bp#3
86
 *        b8-b9 = GE:LE
87
 *        b13   = GD
88
 *        b16-19= LLRW bp#0        LL=00(1),01(2),11(4)
89
 *        b20-23= LLRW bp#1        RW=00(x),01(w),11(rw)
90
 *        b24-27= LLRW bp#2
91
 *        b28-31= LLRW bp#3
92
 */
93
unsigned long DRs[8] =
94
{
95
        0x00000000,
96
        0x00000000,
97
        0x00000000,
98
        0x00000000,
99
        0xffff1ff0,
100
        0x00000400,
101
        0xffff1ff0,
102
        0x00000400
103
};
104

    
105
unsigned long TRs[2] =
106
{
107
        0x00000000,
108
        0x00000000
109
};
110

    
111
void FatalAppExit(UINT wAction, LPCSTR lpText)
112
{
113
    fprintf(stderr, "Fatal error '%s' in CPU\n", lpText);
114
    exit(1);
115
}
116

    
117
int e_debug_check(unsigned char *PC)
118
{
119
    register unsigned long d7 = DRs[7];
120

    
121
    if (d7&0x03) {
122
        if (d7&0x30000) return 0;        /* only execute(00) bkp */
123
        if ((long)PC==DRs[0]) {
124
            e_printf("DBRK: DR0 hit at %p\n",PC);
125
            DRs[6] |= 1;
126
            return 1;
127
        }
128
    }
129
    if (d7&0x0c) {
130
        if (d7&0x300000) return 0;
131
        if ((long)PC==DRs[1]) {
132
            e_printf("DBRK: DR1 hit at %p\n",PC);
133
            DRs[6] |= 2;
134
            return 1;
135
        }
136
    }
137
    if (d7&0x30) {
138
        if (d7&0x3000000) return 0;
139
        if ((long)PC==DRs[2]) {
140
            e_printf("DBRK: DR2 hit at %p\n",PC);
141
            DRs[6] |= 4;
142
            return 1;
143
        }
144
    }
145
    if (d7&0xc0) {
146
        if (d7&0x30000000) return 0;
147
        if ((long)PC==DRs[3]) {
148
            e_printf("DBRK: DR3 hit at %p\n",PC);
149
            DRs[6] |= 8;
150
            return 1;
151
        }
152
    }
153
    return 0;
154
}
155

    
156
/* Debug stuff */
157
void logstr(unsigned long mask, const char *fmt,...) 
158
{
159
    va_list ap;
160

    
161
    va_start(ap, fmt);
162
    vfprintf(stderr, fmt, ap);
163
    va_end(ap);
164
}
165

    
166
/* unconditional message into debug log and stderr */
167
#undef error
168
void error(const char *fmt, ...)
169
{
170
    va_list ap;
171

    
172
    va_start(ap, fmt);
173
    vfprintf(stderr, fmt, ap);
174
    va_end(ap);
175
    exit(1);
176
}
177

    
178
int PortIO(DWORD port, DWORD value, UINT size, BOOL is_write)
179
{
180
    fprintf(stderr, "IO: %s port=0x%lx value=0x%lx size=%d",
181
            is_write ? "write" : "read", port, value, size);
182
    return value;
183
}
184

    
185
void LogProcName(WORD wSel, WORD wOff, WORD wAction)
186
{
187

    
188
}
189

    
190
void INT_handler(int num, void *env)
191
{
192
  fprintf(stderr, "EM86: int %d\n", num);
193
}
194

    
195
/***********************************************************/
196

    
197
/* XXX: currently we use LDT entries */
198
#define __USER_CS        (0x23|4)
199
#define __USER_DS        (0x2B|4)
200

    
201
void usage(void)
202
{
203
    printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n"
204
           "usage: gemu program [arguments...]\n"
205
           "Linux x86 emulator\n"
206
           );
207
    exit(1);
208
}
209

    
210
int main(int argc, char **argv)
211
{
212
    const char *filename;
213
    struct pt_regs regs1, *regs = &regs1;
214
    struct image_info info1, *info = &info1;
215
    Interp_ENV *env;
216

    
217
    if (argc <= 1)
218
        usage();
219
    
220
    filename = argv[1];
221

    
222
    /* Zero out regs */
223
    memset(regs, 0, sizeof(struct pt_regs));
224

    
225
    /* Zero out image_info */
226
    memset(info, 0, sizeof(struct image_info));
227

    
228
    if(elf_exec(filename, argv+1, __environ, regs, info) != 0) {
229
        printf("Error loading %s\n", filename);
230
        exit(1);
231
    }
232
    
233
#if 0
234
    printf("start_brk   0x%08lx\n" , info->start_brk);
235
    printf("end_code    0x%08lx\n" , info->end_code);
236
    printf("start_code  0x%08lx\n" , info->start_code);
237
    printf("end_data    0x%08lx\n" , info->end_data);
238
    printf("start_stack 0x%08lx\n" , info->start_stack);
239
    printf("brk         0x%08lx\n" , info->brk);
240
    printf("esp         0x%08lx\n" , regs->esp);
241
    printf("eip         0x%08lx\n" , regs->eip);
242
#endif
243

    
244
    target_set_brk((char *)info->brk);
245
    syscall_init();
246

    
247
    env = &env_global;
248
    envp_global = env;
249
    memset(env, 0, sizeof(Interp_ENV));
250

    
251
    env->rax.e   = regs->eax;
252
    env->rbx.e   = regs->ebx;
253
    env->rcx.e   = regs->ecx;
254
    env->rdx.e   = regs->edx;
255
    env->rsi.esi = regs->esi;
256
    env->rdi.edi = regs->edi;
257
    env->rbp.ebp = regs->ebp;
258
    env->rsp.esp = regs->esp;
259
    env->cs.cs   = __USER_CS;
260
    env->ds.ds   = __USER_DS;
261
    env->es.es   = __USER_DS;
262
    env->ss.ss   = __USER_DS;
263
    env->fs.fs   = __USER_DS;
264
    env->gs.gs   = __USER_DS;
265
    env->trans_addr = regs->eip;
266

    
267
    LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
268
    LDT[__USER_CS >> 3].dwSelLimit = 0xfffff;
269
    LDT[__USER_CS >> 3].lpSelBase = NULL;
270

    
271
    LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
272
    LDT[__USER_DS >> 3].dwSelLimit = 0xfffff;
273
    LDT[__USER_DS >> 3].lpSelBase = NULL;
274
    init_npu();
275

    
276
    for(;;) {
277
        int err;
278
        uint8_t *pc;
279

    
280
        err = invoke_code32(env, -1);
281
        env->trans_addr = env->return_addr;
282
        pc = env->seg_regs[0] + env->trans_addr;
283
        switch(err) {
284
        case EXCP0D_GPF:
285
            if (pc[0] == 0xcd && pc[1] == 0x80) {
286
                /* syscall */
287
                env->trans_addr += 2;
288
                env->rax.e = do_syscall(env->rax.e, 
289
                                        env->rbx.e,
290
                                        env->rcx.e,
291
                                        env->rdx.e,
292
                                        env->rsi.esi,
293
                                        env->rdi.edi,
294
                                        env->rbp.ebp);
295
            } else {
296
                goto trap_error;
297
            }
298
            break;
299
        default:
300
        trap_error:
301
            fprintf(stderr, "GEMU: Unknown error %d, aborting\n", err);
302
            d_emu = 9;
303
            fprintf(stderr, "%s\n%s\n",
304
                    e_print_cpuemu_regs(env, 1), 
305
                    e_emu_disasm(env,pc,1));
306
            abort();
307
        }
308
    }
309
    return 0;
310
}