• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- EDOperand.cpp - LLVM Enhanced Disassembler ------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the Enhanced Disassembly library's operand class.  The
11 // operand is responsible for allowing evaluation given a particular register
12 // context.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "EDOperand.h"
17 #include "EDDisassembler.h"
18 #include "EDInst.h"
19 #include "llvm/MC/EDInstInfo.h"
20 #include "llvm/MC/MCInst.h"
21 using namespace llvm;
22 
EDOperand(const EDDisassembler & disassembler,const EDInst & inst,unsigned int opIndex,unsigned int & mcOpIndex)23 EDOperand::EDOperand(const EDDisassembler &disassembler,
24                      const EDInst &inst,
25                      unsigned int opIndex,
26                      unsigned int &mcOpIndex) :
27   Disassembler(disassembler),
28   Inst(inst),
29   OpIndex(opIndex),
30   MCOpIndex(mcOpIndex) {
31   unsigned int numMCOperands = 0;
32 
33   if (Disassembler.Key.Arch == Triple::x86 ||
34       Disassembler.Key.Arch == Triple::x86_64) {
35     uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
36 
37     switch (operandType) {
38     default:
39       break;
40     case kOperandTypeImmediate:
41       numMCOperands = 1;
42       break;
43     case kOperandTypeRegister:
44       numMCOperands = 1;
45       break;
46     case kOperandTypeX86Memory:
47       numMCOperands = 5;
48       break;
49     case kOperandTypeX86EffectiveAddress:
50       numMCOperands = 4;
51       break;
52     case kOperandTypeX86PCRelative:
53       numMCOperands = 1;
54       break;
55     }
56   }
57   else if (Disassembler.Key.Arch == Triple::arm ||
58            Disassembler.Key.Arch == Triple::thumb) {
59     uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex];
60 
61     switch (operandType) {
62     default:
63     case kOperandTypeARMRegisterList:
64     case kOperandTypeARMDPRRegisterList:
65     case kOperandTypeARMSPRRegisterList:
66       break;
67     case kOperandTypeImmediate:
68     case kOperandTypeRegister:
69     case kOperandTypeARMBranchTarget:
70     case kOperandTypeARMSoImm:
71     case kOperandTypeARMRotImm:
72     case kOperandTypeThumb2SoImm:
73     case kOperandTypeARMSoImm2Part:
74     case kOperandTypeARMPredicate:
75     case kOperandTypeThumbITMask:
76     case kOperandTypeThumb2AddrModeImm8Offset:
77     case kOperandTypeARMTBAddrMode:
78     case kOperandTypeThumb2AddrModeImm8s4Offset:
79     case kOperandTypeARMAddrMode7:
80     case kOperandTypeThumb2AddrModeReg:
81       numMCOperands = 1;
82       break;
83     case kOperandTypeThumb2SoReg:
84     case kOperandTypeAddrModeImm12:
85     case kOperandTypeARMAddrMode2Offset:
86     case kOperandTypeARMAddrMode3Offset:
87     case kOperandTypeARMAddrMode4:
88     case kOperandTypeARMAddrMode5:
89     case kOperandTypeARMAddrModePC:
90     case kOperandTypeThumb2AddrModeImm8:
91     case kOperandTypeThumb2AddrModeImm12:
92     case kOperandTypeThumb2AddrModeImm8s4:
93     case kOperandTypeThumbAddrModeImmS1:
94     case kOperandTypeThumbAddrModeImmS2:
95     case kOperandTypeThumbAddrModeImmS4:
96     case kOperandTypeThumbAddrModeRR:
97     case kOperandTypeThumbAddrModeSP:
98     case kOperandTypeThumbAddrModePC:
99       numMCOperands = 2;
100       break;
101     case kOperandTypeARMSoReg:
102     case kOperandTypeLdStSOReg:
103     case kOperandTypeARMAddrMode2:
104     case kOperandTypeARMAddrMode3:
105     case kOperandTypeThumb2AddrModeSoReg:
106     case kOperandTypeThumbAddrModeRegS1:
107     case kOperandTypeThumbAddrModeRegS2:
108     case kOperandTypeThumbAddrModeRegS4:
109     case kOperandTypeARMAddrMode6Offset:
110       numMCOperands = 3;
111       break;
112     case kOperandTypeARMAddrMode6:
113       numMCOperands = 4;
114       break;
115     }
116   }
117 
118   mcOpIndex += numMCOperands;
119 }
120 
~EDOperand()121 EDOperand::~EDOperand() {
122 }
123 
evaluate(uint64_t & result,EDRegisterReaderCallback callback,void * arg)124 int EDOperand::evaluate(uint64_t &result,
125                         EDRegisterReaderCallback callback,
126                         void *arg) {
127   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
128 
129   switch (Disassembler.Key.Arch) {
130   default:
131     return -1;
132   case Triple::x86:
133   case Triple::x86_64:
134     switch (operandType) {
135     default:
136       return -1;
137     case kOperandTypeImmediate:
138       result = Inst.Inst->getOperand(MCOpIndex).getImm();
139       return 0;
140     case kOperandTypeRegister:
141     {
142       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
143       return callback(&result, reg, arg);
144     }
145     case kOperandTypeX86PCRelative:
146     {
147       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
148 
149       uint64_t ripVal;
150 
151       // TODO fix how we do this
152 
153       if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg))
154         return -1;
155 
156       result = ripVal + displacement;
157       return 0;
158     }
159     case kOperandTypeX86Memory:
160     case kOperandTypeX86EffectiveAddress:
161     {
162       unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg();
163       uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
164       unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
165       int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
166 
167       uint64_t addr = 0;
168 
169       unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
170 
171       if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
172         unsigned fsID = Disassembler.registerIDWithName("FS");
173         unsigned gsID = Disassembler.registerIDWithName("GS");
174 
175         if (segmentReg == fsID ||
176             segmentReg == gsID) {
177           uint64_t segmentBase;
178           if (!callback(&segmentBase, segmentReg, arg))
179             addr += segmentBase;
180         }
181       }
182 
183       if (baseReg) {
184         uint64_t baseVal;
185         if (callback(&baseVal, baseReg, arg))
186           return -1;
187         addr += baseVal;
188       }
189 
190       if (indexReg) {
191         uint64_t indexVal;
192         if (callback(&indexVal, indexReg, arg))
193           return -1;
194         addr += (scaleAmount * indexVal);
195       }
196 
197       addr += displacement;
198 
199       result = addr;
200       return 0;
201     }
202     } // switch (operandType)
203     break;
204   case Triple::arm:
205   case Triple::thumb:
206     switch (operandType) {
207     default:
208       return -1;
209     case kOperandTypeImmediate:
210       if (!Inst.Inst->getOperand(MCOpIndex).isImm())
211         return -1;
212 
213       result = Inst.Inst->getOperand(MCOpIndex).getImm();
214       return 0;
215     case kOperandTypeRegister:
216     {
217       if (!Inst.Inst->getOperand(MCOpIndex).isReg())
218         return -1;
219 
220       unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
221       return callback(&result, reg, arg);
222     }
223     case kOperandTypeARMBranchTarget:
224     {
225       if (!Inst.Inst->getOperand(MCOpIndex).isImm())
226         return -1;
227 
228       int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
229 
230       uint64_t pcVal;
231 
232       if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg))
233         return -1;
234 
235       result = pcVal + displacement;
236       return 0;
237     }
238     }
239     break;
240   }
241 
242   return -1;
243 }
244 
isRegister()245 int EDOperand::isRegister() {
246   return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister);
247 }
248 
regVal()249 unsigned EDOperand::regVal() {
250   return Inst.Inst->getOperand(MCOpIndex).getReg();
251 }
252 
isImmediate()253 int EDOperand::isImmediate() {
254   return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate);
255 }
256 
immediateVal()257 uint64_t EDOperand::immediateVal() {
258   return Inst.Inst->getOperand(MCOpIndex).getImm();
259 }
260 
isMemory()261 int EDOperand::isMemory() {
262   uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex];
263 
264   switch (operandType) {
265   default:
266     return 0;
267   case kOperandTypeX86Memory:
268   case kOperandTypeX86PCRelative:
269   case kOperandTypeX86EffectiveAddress:
270   case kOperandTypeARMSoReg:
271   case kOperandTypeARMSoImm:
272   case kOperandTypeARMAddrMode2:
273   case kOperandTypeARMAddrMode2Offset:
274   case kOperandTypeARMAddrMode3:
275   case kOperandTypeARMAddrMode3Offset:
276   case kOperandTypeARMAddrMode4:
277   case kOperandTypeARMAddrMode5:
278   case kOperandTypeARMAddrMode6:
279   case kOperandTypeARMAddrMode7:
280   case kOperandTypeARMAddrModePC:
281   case kOperandTypeARMBranchTarget:
282   case kOperandTypeThumbAddrModeRegS1:
283   case kOperandTypeThumbAddrModeRegS2:
284   case kOperandTypeThumbAddrModeRegS4:
285   case kOperandTypeThumbAddrModeRR:
286   case kOperandTypeThumbAddrModeSP:
287   case kOperandTypeThumb2SoImm:
288   case kOperandTypeThumb2AddrModeImm8:
289   case kOperandTypeThumb2AddrModeImm8Offset:
290   case kOperandTypeThumb2AddrModeImm12:
291   case kOperandTypeThumb2AddrModeSoReg:
292   case kOperandTypeThumb2AddrModeImm8s4:
293   case kOperandTypeThumb2AddrModeReg:
294     return 1;
295   }
296 }
297 
298 #ifdef __BLOCKS__
299 namespace {
300   struct RegisterReaderWrapper {
301     EDOperand::EDRegisterBlock_t regBlock;
302   };
303 }
304 
readerWrapperCallback(uint64_t * value,unsigned regID,void * arg)305 static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) {
306   RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg;
307   return wrapper->regBlock(value, regID);
308 }
309 
evaluate(uint64_t & result,EDRegisterBlock_t regBlock)310 int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) {
311   RegisterReaderWrapper wrapper;
312   wrapper.regBlock = regBlock;
313   return evaluate(result, readerWrapperCallback, (void*)&wrapper);
314 }
315 #endif
316