Coverage for /Syzygy/core/disassembler_util.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
95.0%57600.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/core/disassembler_util.h"
  16    :  
  17    :  #include "base/logging.h"
  18    :  #include "mnemonics.h"  // NOLINT
  19    :  
  20    :  namespace core {
  21    :  
  22    :  bool DecodeOneInstruction(
  23  E :      uint32 address, const uint8* buffer, size_t length, _DInst* instruction) {
  24  E :    DCHECK(buffer != NULL);
  25  E :    DCHECK(instruction != NULL);
  26    :  
  27  E :    _CodeInfo code = {};
  28  E :    code.dt = Decode32Bits;
  29  E :    code.features = DF_NONE;
  30  E :    code.codeOffset = address;
  31  E :    code.codeLen = length;
  32  E :    code.code = buffer;
  33    :  
  34  E :    unsigned int decoded = 0;
  35  E :    ::memset(instruction, 0, sizeof(instruction));
  36  E :    _DecodeResult result = distorm_decompose(&code, instruction, 1, &decoded);
  37    :  
  38  E :    if (result != DECRES_MEMORYERR && result != DECRES_SUCCESS)
  39  i :      return false;
  40    :  
  41  E :    DCHECK_EQ(1u, decoded);
  42  E :    DCHECK_GE(length, instruction->size);
  43  E :    DCHECK_LT(0, instruction->size);
  44    :  
  45  E :    return true;
  46  E :  }
  47    :  
  48    :  bool DecodeOneInstruction(
  49  E :      const uint8* buffer, size_t length, _DInst* instruction) {
  50  E :    DCHECK(buffer != NULL);
  51  E :    DCHECK(instruction != NULL);
  52  E :    if (!DecodeOneInstruction(0x10000000, buffer, length, instruction))
  53  i :      return false;
  54  E :    return true;
  55  E :  }
  56    :  
  57  E :  bool IsNop(const _DInst& instruction) {
  58  E :    switch (instruction.opcode) {
  59    :      default:
  60    :        // Only the sequences recognized below qualify as NOP instructions.
  61  E :        return false;
  62    :  
  63    :      case I_XCHG:
  64    :        // This handles the 1 bytes NOP sequence.
  65    :        //     1-byte: xchg eax, eax.
  66    :        return instruction.ops[0].type == O_REG &&
  67    :            instruction.ops[0].index == RM_AX &&
  68    :            instruction.ops[1].type == O_REG &&
  69  i :            instruction.ops[1].index == RM_AX;
  70    :  
  71    :      case I_NOP:
  72    :        // This handles the 2, 4, 5, 7, 8 and 9 byte NOP sequences.
  73    :        //     2-byte: 66 NOP
  74    :        //     4-byte: NOP DWORD PTR [EAX + 0] (8-bit displacement)
  75    :        //     5-byte: NOP DWORD PTR [EAX + EAX*1 + 0] (8-bit displacement)
  76    :        //     7-byte: NOP DWORD PTR [EAX + 0] (32-bit displacement)
  77    :        //     8-byte: NOP DWORD PTR [EAX + EAX*1 + 0] (32-bit displacement)
  78    :        //     9-byte: NOP WORD PTR [EAX + EAX*1 + 0] (32-bit displacement)
  79  E :        return true;
  80    :  
  81    :      case I_LEA:
  82    :        // This handles the 3 and 6 byte NOP sequences.
  83    :        //     3-byte: LEA REG, 0 (REG) (8-bit displacement)
  84    :        //     6-byte: LEA REG, 0 (REG) (32-bit displacement)
  85    :        return instruction.ops[0].type == O_REG &&
  86    :            instruction.ops[1].type == O_SMEM &&
  87    :            instruction.ops[0].index == instruction.ops[1].index &&
  88  E :            instruction.disp == 0;
  89    :  
  90    :      case I_MOV:
  91    :        // Not documented in the Intel manuals, but we see "mov reg, reg" a lot.
  92    :        return instruction.ops[0].type == O_REG &&
  93    :            instruction.ops[1].type == O_REG &&
  94  E :            instruction.ops[0].index == instruction.ops[1].index;
  95    :    }
  96  E :  }
  97    :  
  98  E :  bool IsCall(const _DInst& instruction) {
  99  E :    uint8 fc = META_GET_FC(instruction.meta);
 100  E :    if (fc == FC_CALL)
 101  E :      return true;
 102  E :    return false;
 103  E :  }
 104    :  
 105  E :  bool IsControlFlow(const _DInst& instruction) {
 106  E :    uint8 fc = META_GET_FC(instruction.meta);
 107    :    if (fc == FC_CND_BRANCH || fc == FC_UNC_BRANCH ||
 108  E :        fc == FC_RET || fc == FC_SYS) {
 109  E :      return true;
 110    :    }
 111  E :    return false;
 112  E :  }
 113    :  
 114  E :  bool IsImplicitControlFlow(const _DInst& instruction) {
 115  E :    uint8 fc = META_GET_FC(instruction.meta);
 116  E :    if (fc == FC_RET || fc == FC_SYS) {
 117    :      // Control flow jumps implicitly out of the block.
 118  E :      return true;
 119  E :    } else if (fc == FC_UNC_BRANCH && instruction.ops[0].type != O_PC) {
 120    :      // There is an explicit branch but the target is not explicitly given as
 121    :      // a PC relative value (i.e., the target is computed, stored in a register,
 122    :      // stored in a memory location, or otherwise indirect).
 123  E :      return true;
 124    :    }
 125  E :    return false;
 126  E :  }
 127    :  
 128  E :  bool IsInterrupt(const _DInst& instruction) {
 129  E :    return META_GET_FC(instruction.meta) == FC_INT;
 130  E :  }
 131    :  
 132  E :  bool IsDebugInterrupt(const _DInst& instruction) {
 133    :    return IsInterrupt(instruction) && instruction.size == 1 &&
 134  E :        instruction.opcode == I_INT_3;
 135  E :  }
 136    :  
 137    :  }  // namespace core

Coverage information generated Thu Sep 06 11:30:46 2012.