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 Triple::ArchType arch = Disassembler.TgtTriple.getArch(); 34 35 if (arch == Triple::x86 || 36 arch == Triple::x86_64) { 37 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex]; 38 39 switch (operandType) { 40 default: 41 break; 42 case kOperandTypeImmediate: 43 numMCOperands = 1; 44 break; 45 case kOperandTypeRegister: 46 numMCOperands = 1; 47 break; 48 case kOperandTypeX86Memory: 49 numMCOperands = 5; 50 break; 51 case kOperandTypeX86EffectiveAddress: 52 numMCOperands = 4; 53 break; 54 case kOperandTypeX86PCRelative: 55 numMCOperands = 1; 56 break; 57 } 58 } 59 else if (arch == Triple::arm || 60 arch == Triple::thumb) { 61 uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex]; 62 63 switch (operandType) { 64 default: 65 case kOperandTypeARMRegisterList: 66 case kOperandTypeARMDPRRegisterList: 67 case kOperandTypeARMSPRRegisterList: 68 break; 69 case kOperandTypeImmediate: 70 case kOperandTypeRegister: 71 case kOperandTypeARMBranchTarget: 72 case kOperandTypeARMSoImm: 73 case kOperandTypeARMRotImm: 74 case kOperandTypeThumb2SoImm: 75 case kOperandTypeARMSoImm2Part: 76 case kOperandTypeARMPredicate: 77 case kOperandTypeThumbITMask: 78 case kOperandTypeThumb2AddrModeImm8Offset: 79 case kOperandTypeARMTBAddrMode: 80 case kOperandTypeThumb2AddrModeImm8s4Offset: 81 case kOperandTypeARMAddrMode7: 82 case kOperandTypeThumb2AddrModeReg: 83 numMCOperands = 1; 84 break; 85 case kOperandTypeThumb2SoReg: 86 case kOperandTypeAddrModeImm12: 87 case kOperandTypeARMAddrMode2Offset: 88 case kOperandTypeARMAddrMode3Offset: 89 case kOperandTypeARMAddrMode4: 90 case kOperandTypeARMAddrMode5: 91 case kOperandTypeARMAddrModePC: 92 case kOperandTypeThumb2AddrModeImm8: 93 case kOperandTypeThumb2AddrModeImm12: 94 case kOperandTypeThumb2AddrModeImm8s4: 95 case kOperandTypeThumbAddrModeImmS1: 96 case kOperandTypeThumbAddrModeImmS2: 97 case kOperandTypeThumbAddrModeImmS4: 98 case kOperandTypeThumbAddrModeRR: 99 case kOperandTypeThumbAddrModeSP: 100 case kOperandTypeThumbAddrModePC: 101 numMCOperands = 2; 102 break; 103 case kOperandTypeARMSoReg: 104 case kOperandTypeLdStSOReg: 105 case kOperandTypeARMAddrMode2: 106 case kOperandTypeARMAddrMode3: 107 case kOperandTypeThumb2AddrModeSoReg: 108 case kOperandTypeThumbAddrModeRegS1: 109 case kOperandTypeThumbAddrModeRegS2: 110 case kOperandTypeThumbAddrModeRegS4: 111 case kOperandTypeARMAddrMode6Offset: 112 numMCOperands = 3; 113 break; 114 case kOperandTypeARMAddrMode6: 115 numMCOperands = 4; 116 break; 117 } 118 } 119 120 mcOpIndex += numMCOperands; 121 } 122 123 EDOperand::~EDOperand() { 124 } 125 126 int EDOperand::evaluate(uint64_t &result, 127 EDRegisterReaderCallback callback, 128 void *arg) { 129 uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex]; 130 131 Triple::ArchType arch = Disassembler.TgtTriple.getArch(); 132 133 switch (arch) { 134 default: 135 return -1; 136 case Triple::x86: 137 case Triple::x86_64: 138 switch (operandType) { 139 default: 140 return -1; 141 case kOperandTypeImmediate: 142 result = Inst.Inst->getOperand(MCOpIndex).getImm(); 143 return 0; 144 case kOperandTypeRegister: 145 { 146 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg(); 147 return callback(&result, reg, arg); 148 } 149 case kOperandTypeX86PCRelative: 150 { 151 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm(); 152 153 uint64_t ripVal; 154 155 // TODO fix how we do this 156 157 if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg)) 158 return -1; 159 160 result = ripVal + displacement; 161 return 0; 162 } 163 case kOperandTypeX86Memory: 164 case kOperandTypeX86EffectiveAddress: 165 { 166 unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg(); 167 uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm(); 168 unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg(); 169 int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm(); 170 171 uint64_t addr = 0; 172 173 unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg(); 174 175 if (segmentReg != 0 && arch == Triple::x86_64) { 176 unsigned fsID = Disassembler.registerIDWithName("FS"); 177 unsigned gsID = Disassembler.registerIDWithName("GS"); 178 179 if (segmentReg == fsID || 180 segmentReg == gsID) { 181 uint64_t segmentBase; 182 if (!callback(&segmentBase, segmentReg, arg)) 183 addr += segmentBase; 184 } 185 } 186 187 if (baseReg) { 188 uint64_t baseVal; 189 if (callback(&baseVal, baseReg, arg)) 190 return -1; 191 addr += baseVal; 192 } 193 194 if (indexReg) { 195 uint64_t indexVal; 196 if (callback(&indexVal, indexReg, arg)) 197 return -1; 198 addr += (scaleAmount * indexVal); 199 } 200 201 addr += displacement; 202 203 result = addr; 204 return 0; 205 } 206 } // switch (operandType) 207 case Triple::arm: 208 case Triple::thumb: 209 switch (operandType) { 210 default: 211 return -1; 212 case kOperandTypeImmediate: 213 if (!Inst.Inst->getOperand(MCOpIndex).isImm()) 214 return -1; 215 216 result = Inst.Inst->getOperand(MCOpIndex).getImm(); 217 return 0; 218 case kOperandTypeRegister: 219 { 220 if (!Inst.Inst->getOperand(MCOpIndex).isReg()) 221 return -1; 222 223 unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg(); 224 return callback(&result, reg, arg); 225 } 226 case kOperandTypeARMBranchTarget: 227 { 228 if (!Inst.Inst->getOperand(MCOpIndex).isImm()) 229 return -1; 230 231 int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm(); 232 233 uint64_t pcVal; 234 235 if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg)) 236 return -1; 237 238 result = pcVal + displacement; 239 return 0; 240 } 241 } 242 } 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