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 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 121 EDOperand::~EDOperand() { 122 } 123 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 245 int EDOperand::isRegister() { 246 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister); 247 } 248 249 unsigned EDOperand::regVal() { 250 return Inst.Inst->getOperand(MCOpIndex).getReg(); 251 } 252 253 int EDOperand::isImmediate() { 254 return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate); 255 } 256 257 uint64_t EDOperand::immediateVal() { 258 return Inst.Inst->getOperand(MCOpIndex).getImm(); 259 } 260 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 305 static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) { 306 RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg; 307 return wrapper->regBlock(value, regID); 308 } 309 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