Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Context-based output infrastructure (V3_Print, etc) and modifications to use it
[palacios.git] / palacios / src / palacios / vmm_decoder.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21 #include <palacios/vmm_decoder.h>
22
23
24
25
26
27 uint8_t v3_get_prefixes(uint8_t * instr, struct x86_prefixes * prefixes) {
28     uint8_t * instr_cursor = instr;
29
30     while (1) {
31         switch (*instr_cursor) {
32             case 0xF0:      // lock
33                 prefixes->lock = 1;
34                 break;
35
36             case 0xF2:      // REPNE/REPNZ
37                 prefixes->repnz = 1;
38                 prefixes->repne = 1;
39                 break;
40
41             case 0xF3:      // REP or REPE/REPZ
42                 prefixes->rep = 1;
43                 prefixes->repe = 1;
44                 prefixes->repz = 1; 
45                 break;
46
47             case 0x2E:      // CS override or Branch hint not taken (with Jcc instr_cursors)
48                 prefixes->cs_override = 1;
49                 prefixes->br_not_taken = 1;
50                 break;
51
52             case 0x36:      // SS override
53                 prefixes->ss_override = 1;
54                 break;
55
56             case 0x3E:      // DS override or Branch hint taken (with Jcc instr_cursors)
57                 prefixes->ds_override = 1;
58                 prefixes->br_taken = 1;
59                 break;
60
61             case 0x26:      // ES override
62                 prefixes->es_override = 1;
63                 break;
64
65             case 0x64:      // FS override
66                 prefixes->fs_override = 1;
67                 break;
68       
69             case 0x65:      // GS override
70                 prefixes->gs_override = 1;
71                 break;
72
73             case 0x66:      // operand size override
74                 prefixes->op_size = 1;
75                 break;
76
77             case 0x67:    // address size override
78                 prefixes->addr_size = 1;
79                 break;
80
81             default:
82                 return (instr_cursor - instr);
83         }
84
85         instr_cursor++;
86     }
87 }
88
89 void v3_strip_rep_prefix(uchar_t * instr, int length) {
90     int read_ctr = 0;
91     int write_ctr = 0;
92     int found = 0;
93
94     while (read_ctr < length) {
95         if ((!found) && 
96             ( (instr[read_ctr] == 0xF2) ||
97               (instr[read_ctr] == 0xF3))) {
98             read_ctr++;
99             found = 1;
100         } else {
101             instr[write_ctr] = instr[read_ctr];
102             write_ctr++;
103             read_ctr++;
104         }
105     }
106 }
107
108
109 static char * op_type_to_str(v3_op_type_t type) {
110     switch (type) {
111         case V3_OP_MOVCR2: return "V3_OP_MOVCR2"; 
112         case V3_OP_MOV2CR: return "V3_OP_MOV2CR"; 
113         case V3_OP_SMSW: return "V3_OP_SMSW"; 
114         case V3_OP_LMSW: return "V3_OP_LMSW"; 
115         case V3_OP_CLTS: return "V3_OP_CLTS";
116         case V3_OP_INVLPG: return "V3_OP_INVLPG";
117         case V3_OP_ADC: return "V3_OP_ADC"; 
118         case V3_OP_ADD: return "V3_OP_ADD";
119         case V3_OP_AND: return "V3_OP_AND"; 
120         case V3_OP_OR: return "V3_OP_OR"; 
121         case V3_OP_XOR: return "V3_OP_XOR"; 
122         case V3_OP_SUB: return "V3_OP_SUB";
123         case V3_OP_INC: return "V3_OP_INC"; 
124         case V3_OP_DEC: return "V3_OP_DEC"; 
125         case V3_OP_NEG: return "V3_OP_NEG"; 
126         case V3_OP_MOV: return "V3_OP_MOV"; 
127         case V3_OP_NOT: return "V3_OP_NOT"; 
128         case V3_OP_XCHG: return "V3_OP_XCHG"; 
129         case V3_OP_SETB: return "V3_OP_SETB"; 
130         case V3_OP_SETBE: return "V3_OP_SETBE"; 
131         case V3_OP_SETL: return "V3_OP_SETL"; 
132         case V3_OP_SETLE: return "V3_OP_SETLE"; 
133         case V3_OP_SETNB: return "V3_OP_SETNB"; 
134         case V3_OP_SETNBE: return "V3_OP_SETNBE"; 
135         case V3_OP_SETNL: return "V3_OP_SETNL"; 
136         case V3_OP_SETNLE: return "V3_OP_SETNLE"; 
137         case V3_OP_SETNO: return "V3_OP_SETNO"; 
138         case V3_OP_SETNP: return "V3_OP_SETNP";
139         case V3_OP_SETNS: return "V3_OP_SETNS"; 
140         case V3_OP_SETNZ: return "V3_OP_SETNZ"; 
141         case V3_OP_SETO: return "V3_OP_SETO"; 
142         case V3_OP_SETP: return "V3_OP_SETP"; 
143         case V3_OP_SETS: return "V3_OP_SETS"; 
144         case V3_OP_SETZ: return "V3_OP_SETZ"; 
145         case V3_OP_MOVS: return "V3_OP_MOVS"; 
146         case V3_OP_STOS: return "V3_OP_STOS"; 
147         case V3_OP_MOVZX: return "V3_OP_MOVZX"; 
148         case V3_OP_MOVSX: return "V3_OP_MOVSX";
149         case V3_OP_INT: return "V3_OP_INT";
150         case V3_INVALID_OP: 
151         default:
152             return "V3_INVALID_OP";
153     }
154 }
155
156
157 static char * operand_type_to_str(v3_operand_type_t op) {
158     switch (op) {
159         case REG_OPERAND: return "REG_OPERAND";
160         case MEM_OPERAND: return "MEM_OPERAND";
161         case IMM_OPERAND: return "IMM_OPERAND";
162         default:
163             return "INVALID_OPERAND";
164     }
165 }
166
167
168 static const ullong_t mask_1 = 0x00000000000000ffLL;
169 static const ullong_t mask_2 = 0x000000000000ffffLL;
170 static const ullong_t mask_4 = 0x00000000ffffffffLL;
171 static const ullong_t mask_8 = 0xffffffffffffffffLL;
172
173
174 #define MASK(val, length) ({                    \
175             ullong_t mask = 0x0LL;              \
176             switch (length) {                   \
177                 case 1:                         \
178                     mask = mask_1;              \
179                     break;                      \
180                 case 2:                         \
181                     mask = mask_2;              \
182                     break;                      \
183                 case 4:                         \
184                     mask = mask_4;              \
185                     break;                      \
186                 case 8:                         \
187                     mask = mask_8;              \
188                     break;                      \
189             }                                   \
190             val & mask;                         \
191         })
192
193 void v3_print_instr(struct x86_instr * instr) {
194     V3_Print(VM_NONE, VCORE_NONE, "Instr: %s (Len: %d)\n", op_type_to_str(instr->op_type), instr->instr_length);
195
196     V3_Print(VM_NONE, VCORE_NONE, "Prefixes= %x\n", instr->prefixes.val);
197
198     if (instr->is_str_op) {
199         V3_Print(VM_NONE, VCORE_NONE, "String OP (len=%d)\n", (uint32_t)instr->str_op_length);
200     }
201
202     V3_Print(VM_NONE, VCORE_NONE, "Number of operands: %d\n", instr->num_operands);
203
204     if (instr->num_operands > 0) {
205         V3_Print(VM_NONE, VCORE_NONE, "Src Operand (%s)\n", operand_type_to_str(instr->src_operand.type));
206         V3_Print(VM_NONE, VCORE_NONE, "\tLen=%d (Addr: %p)\n", instr->src_operand.size, 
207                  (void *)instr->src_operand.operand);
208         if (instr->src_operand.type == REG_OPERAND) {
209             V3_Print(VM_NONE, VCORE_NONE, "\tVal: 0x%llx\n", MASK(*(uint64_t *)(instr->src_operand.operand), instr->src_operand.size));
210         }
211     }
212
213     if (instr->num_operands > 1) {
214         V3_Print(VM_NONE, VCORE_NONE, "Dst Operand (%s)\n", operand_type_to_str(instr->dst_operand.type));
215         V3_Print(VM_NONE, VCORE_NONE, "\tLen=%d (Addr: %p)\n", instr->dst_operand.size, 
216                  (void *)instr->dst_operand.operand);
217         if (instr->dst_operand.type == REG_OPERAND) {
218             V3_Print(VM_NONE, VCORE_NONE, "\tVal: 0x%llx\n", MASK(*(uint64_t *)(instr->dst_operand.operand), instr->dst_operand.size));
219         }
220     }
221
222     if (instr->num_operands > 2) {
223         V3_Print(VM_NONE, VCORE_NONE, "Third Operand (%s)\n", operand_type_to_str(instr->third_operand.type));
224         V3_Print(VM_NONE, VCORE_NONE, "\tLen=%d (Addr: %p)\n", instr->third_operand.size, 
225                  (void *)instr->third_operand.operand);
226         if (instr->third_operand.type == REG_OPERAND) {
227             V3_Print(VM_NONE, VCORE_NONE, "\tVal: 0x%llx\n", MASK(*(uint64_t *)(instr->third_operand.operand), instr->third_operand.size));
228         }
229     }
230 }
231
232