Coverage for /Syzygy/core/disassembler_util_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%1451450.C++test

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   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/basictypes.h"
  18    :  #include "base/logging.h"
  19    :  #include "gmock/gmock.h"
  20    :  #include "gtest/gtest.h"
  21    :  
  22    :  namespace core {
  23    :  
  24    :  namespace {
  25    :  
  26    :  // Decompose a block of code using distorm wrapper.
  27    :  _DecodeResult DecomposeCode(const uint8* code_data,
  28    :                              size_t length,
  29    :                              _DInst result[],
  30    :                              const unsigned int max_results,
  31  E :                              unsigned int* result_count) {
  32  E :    _CodeInfo code = {};
  33  E :    code.dt = Decode32Bits;
  34  E :    code.features = DF_NONE;
  35  E :    code.codeOffset = 0;
  36  E :    code.codeLen = length;
  37  E :    code.code = code_data;
  38  E :    return DistormDecompose(&code, result, max_results, result_count);
  39  E :  }
  40    :  
  41    :  // Decompose a block of code using distorm directly.
  42    :  _DecodeResult RawDecomposeCode(const uint8* code_data,
  43    :                                 size_t length,
  44    :                                 _DInst result[],
  45    :                                 const unsigned int max_results,
  46  E :                                 unsigned int* result_count) {
  47  E :    _CodeInfo code = {};
  48  E :    code.dt = Decode32Bits;
  49  E :    code.features = DF_NONE;
  50  E :    code.codeOffset = 0;
  51  E :    code.codeLen = length;
  52  E :    code.code = code_data;
  53  E :    return distorm_decompose(&code, result, max_results, result_count);
  54  E :  }
  55    :  
  56  E :  _DInst DecodeBuffer(const uint8* buffer, size_t length) {
  57  E :    _DInst inst = {};
  58  E :    EXPECT_TRUE(DecodeOneInstruction(buffer, length, &inst));
  59  E :    EXPECT_EQ(length, inst.size);
  60  E :    return inst;
  61  E :  }
  62    :  
  63    :  // One of the AVX instructions that is currently not supported by distorm.
  64    :  // vxorps ymm0, ymm0, ymm0
  65    :  const uint8 kVxorps[] = { 0xC5, 0xFC, 0x57, 0xC0 };
  66    :  
  67    :  // Instructions for which distorm indicates a size of 0 for the destination
  68    :  // operand size.
  69    :  // fnstcw m16
  70    :  const uint8 kFnstcw[] = { 0xD9, 0x7D, 0xEA };
  71    :  // fldcw m16
  72    :  const uint8 kFldcw[] = { 0xD9, 0x6D, 0xE4 };
  73    :  
  74    :  // Nop Instruction byte sequences.
  75    :  const uint8 kNop2Mov[] = { 0x8B, 0xFF };
  76    :  const uint8 kNop3Lea[] = { 0x8D, 0x49, 0x00 };
  77    :  const uint8 kNop1[] = { 0x90 };
  78    :  const uint8 kNop2[] = { 0x66, 0x90 };
  79    :  const uint8 kNop3[] = { 0x66, 0x66, 0x90 };
  80    :  const uint8 kNop4[] = { 0x0F, 0x1F, 0x40, 0x00 };
  81    :  const uint8 kNop5[] = { 0x0F, 0x1F, 0x44, 0x00, 0x00 };
  82    :  const uint8 kNop6[] = { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 };
  83    :  const uint8 kNop7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 };
  84    :  const uint8 kNop8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
  85    :  const uint8 kNop9[] = {
  86    :      0x66,  // Prefix,
  87    :      0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00  // kNop8.
  88    :  };
  89    :  const uint8 kNop10[] = {
  90    :      0x66, 0x66,  // Prefix.
  91    :      0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00  // kNop8.
  92    :  };
  93    :  const uint8 kNop11[] = {
  94    :      0x66, 0x66, 0x66,  // Prefix.
  95    :      0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00  // kNop8
  96    :  };
  97    :  
  98    :  // Call instruction.
  99    :  const uint8 kCall[] = { 0xE8, 0xCA, 0xFE, 0xBA, 0xBE };
 100    :  
 101    :  // Control Flow byte sequences (note that the JMP is indirect).
 102    :  const uint8 kJmp[] = { 0xFF, 0x24, 0x8D, 0xCA, 0xFE, 0xBA, 0xBE };
 103    :  const uint8 kRet[] = { 0xC3 };
 104    :  const uint8 kRetN[] = { 0xC2, 0x08, 0x00 };
 105    :  const uint8 kJe[] = { 0x74, 0xCA };
 106    :  const uint8 kSysEnter[] = { 0x0F, 0x34 };
 107    :  const uint8 kSysExit[] = { 0x0F, 0x35 };
 108    :  
 109    :  // Interrupts.
 110    :  const uint8 kInt2[] = { 0xCD, 0x02 };
 111    :  const uint8 kInt3[] = { 0xCC };
 112    :  
 113    :  }  // namespace
 114    :  
 115  E :  TEST(DisassemblerUtilTest, DistormWrapperVxorpsPasses) {
 116  E :    _DInst inst = {};
 117  E :    EXPECT_TRUE(DecodeOneInstruction(kVxorps, sizeof(kVxorps), &inst));
 118  E :  }
 119    :  
 120  E :  TEST(DisassemblerUtilTest, InstructionToString) {
 121  E :    _DInst inst = {};
 122  E :    inst = DecodeBuffer(kNop1, sizeof(kNop1));
 123    :  
 124  E :    std::string Nop1Str;
 125  E :    EXPECT_TRUE(InstructionToString(inst, kNop1, sizeof(kNop1), &Nop1Str));
 126  E :    ASSERT_THAT(Nop1Str, testing::HasSubstr("90"));
 127  E :    ASSERT_THAT(Nop1Str, testing::HasSubstr("NOP"));
 128  E :  }
 129    :  
 130  E :  TEST(DisassemblerUtilTest, IsNop) {
 131  E :    EXPECT_FALSE(IsNop(DecodeBuffer(kJmp, sizeof(kJmp))));
 132  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop1, sizeof(kNop1))));
 133  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop2, sizeof(kNop2))));
 134  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop3, sizeof(kNop3))));
 135  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop4, sizeof(kNop4))));
 136  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop5, sizeof(kNop5))));
 137  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop6, sizeof(kNop6))));
 138  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop7, sizeof(kNop7))));
 139  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop8, sizeof(kNop8))));
 140  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop9, sizeof(kNop9))));
 141  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop10, sizeof(kNop10))));
 142  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop11, sizeof(kNop11))));
 143  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop2Mov, sizeof(kNop2Mov))));
 144  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop3Lea, sizeof(kNop3Lea))));
 145  E :  }
 146    :  
 147  E :  TEST(DisassemblerUtilTest, IsCall) {
 148  E :    EXPECT_FALSE(IsCall(DecodeBuffer(kJmp, sizeof(kJmp))));
 149  E :    EXPECT_FALSE(IsCall(DecodeBuffer(kNop1, sizeof(kNop1))));
 150  E :    EXPECT_TRUE(IsCall(DecodeBuffer(kCall, sizeof(kCall))));
 151  E :  }
 152    :  
 153  E :  TEST(DisassemblerUtilTest, IsSystemCall) {
 154  E :    EXPECT_FALSE(IsSystemCall(DecodeBuffer(kJmp, sizeof(kJmp))));
 155  E :    EXPECT_FALSE(IsSystemCall(DecodeBuffer(kNop1, sizeof(kNop1))));
 156  E :    EXPECT_TRUE(IsSystemCall(DecodeBuffer(kSysEnter, sizeof(kSysEnter))));
 157  E :    EXPECT_TRUE(IsSystemCall(DecodeBuffer(kSysExit, sizeof(kSysExit))));
 158  E :  }
 159    :  
 160  E :  TEST(DisassemblerUtilTest, IsConditionalBranch) {
 161  E :    EXPECT_FALSE(IsConditionalBranch(DecodeBuffer(kNop4, sizeof(kNop4))));
 162  E :    EXPECT_FALSE(IsConditionalBranch(DecodeBuffer(kJmp, sizeof(kJmp))));
 163  E :    EXPECT_FALSE(IsConditionalBranch(DecodeBuffer(kRet, sizeof(kRet))));
 164  E :    EXPECT_TRUE(IsConditionalBranch(DecodeBuffer(kJe, sizeof(kJe))));
 165  E :  }
 166    :  
 167  E :  TEST(DisassemblerUtilTest, IsUnconditionalBranch) {
 168  E :    EXPECT_FALSE(IsUnconditionalBranch(DecodeBuffer(kNop4, sizeof(kNop4))));
 169  E :    EXPECT_FALSE(IsUnconditionalBranch(DecodeBuffer(kRet, sizeof(kRet))));
 170  E :    EXPECT_FALSE(IsUnconditionalBranch(DecodeBuffer(kJe, sizeof(kJe))));
 171  E :    EXPECT_TRUE(IsUnconditionalBranch(DecodeBuffer(kJmp, sizeof(kJmp))));
 172  E :  }
 173    :  
 174  E :  TEST(DisassemblerUtilTest, IsBranch) {
 175  E :    EXPECT_FALSE(IsBranch(DecodeBuffer(kNop4, sizeof(kNop4))));
 176  E :    EXPECT_FALSE(IsBranch(DecodeBuffer(kRet, sizeof(kRet))));
 177  E :    EXPECT_TRUE(IsBranch(DecodeBuffer(kJe, sizeof(kJe))));
 178  E :    EXPECT_TRUE(IsBranch(DecodeBuffer(kJmp, sizeof(kJmp))));
 179  E :  }
 180    :  
 181  E :  TEST(DisassemblerUtilTest, HasPcRelativeOperand) {
 182  E :    EXPECT_FALSE(HasPcRelativeOperand(DecodeBuffer(kRetN, sizeof(kRet)), 0));
 183  E :    EXPECT_FALSE(HasPcRelativeOperand(DecodeBuffer(kJmp, sizeof(kJmp)), 0));
 184  E :    EXPECT_TRUE(HasPcRelativeOperand(DecodeBuffer(kJe, sizeof(kJe)), 0));
 185  E :  }
 186    :  
 187  E :  TEST(DisassemblerUtilTest, IsControlFlow) {
 188  E :    EXPECT_FALSE(IsControlFlow(DecodeBuffer(kNop4, sizeof(kNop4))));
 189  E :    EXPECT_TRUE(IsControlFlow(DecodeBuffer(kJmp, sizeof(kJmp))));
 190  E :    EXPECT_TRUE(IsControlFlow(DecodeBuffer(kRet, sizeof(kRet))));
 191  E :    EXPECT_TRUE(IsControlFlow(DecodeBuffer(kRetN, sizeof(kRetN))));
 192  E :    EXPECT_TRUE(IsControlFlow(DecodeBuffer(kJe, sizeof(kJe))));
 193  E :    EXPECT_TRUE(IsControlFlow(DecodeBuffer(kSysEnter, sizeof(kSysEnter))));
 194  E :  }
 195    :  
 196  E :  TEST(DisassemblerUtilTest, IsImplicitControlFlow) {
 197  E :    EXPECT_FALSE(IsImplicitControlFlow(DecodeBuffer(kJe, sizeof(kJe))));
 198  E :    EXPECT_TRUE(IsImplicitControlFlow(DecodeBuffer(kRet, sizeof(kRet))));
 199  E :    EXPECT_TRUE(IsImplicitControlFlow(DecodeBuffer(kRetN, sizeof(kRetN))));
 200  E :    EXPECT_TRUE(IsImplicitControlFlow(DecodeBuffer(kJmp, sizeof(kJmp))));
 201  E :  }
 202    :  
 203  E :  TEST(DisassemblerUtilTest, IsInterrupt) {
 204  E :    EXPECT_FALSE(IsInterrupt(DecodeBuffer(kJe, sizeof(kJe))));
 205  E :    EXPECT_TRUE(IsInterrupt(DecodeBuffer(kInt2, sizeof(kInt2))));
 206  E :    EXPECT_TRUE(IsInterrupt(DecodeBuffer(kInt3, sizeof(kInt3))));
 207  E :  }
 208    :  
 209  E :  TEST(DisassemblerUtilTest, IsDebugInterrupt) {
 210  E :    EXPECT_FALSE(IsDebugInterrupt(DecodeBuffer(kJe, sizeof(kJe))));
 211  E :    EXPECT_FALSE(IsDebugInterrupt(DecodeBuffer(kInt2, sizeof(kInt2))));
 212  E :    EXPECT_TRUE(IsDebugInterrupt(DecodeBuffer(kInt3, sizeof(kInt3))));
 213  E :  }
 214    :  
 215  E :  TEST(DisassemblerUtilTest, DistormDecompose) {
 216  E :    const unsigned int kMaxResults = 16;
 217  E :    unsigned int result_count = 0;
 218    :    _DInst results[kMaxResults];
 219    :    EXPECT_EQ(DECRES_SUCCESS,
 220    :              DecomposeCode(kNop3Lea,
 221    :                            sizeof(kNop3Lea),
 222    :                            results,
 223    :                            kMaxResults,
 224  E :                            &result_count));
 225  E :    EXPECT_EQ(1U, result_count);
 226  E :    EXPECT_EQ(32U, results[0].ops[0].size);
 227  E :  }
 228    :  
 229  E :  TEST(DisassemblerUtilTest, DistormDecomposeFnstcw) {
 230  E :    const unsigned int kMaxResults = 16;
 231  E :    unsigned int result_count = 0;
 232    :    _DInst results[kMaxResults];
 233    :    EXPECT_EQ(DECRES_SUCCESS,
 234    :              DecomposeCode(kFnstcw,
 235    :                            sizeof(kFnstcw),
 236    :                            results,
 237    :                            kMaxResults,
 238  E :                            &result_count));
 239  E :    EXPECT_EQ(1U, result_count);
 240  E :    EXPECT_EQ(16U, results[0].ops[0].size);
 241  E :  }
 242    :  
 243  E :  TEST(DisassemblerUtilTest, WrongAccessSizeOnRawDistormDecomposeFnstcw) {
 244  E :    const unsigned int kMaxResults = 16;
 245  E :    unsigned int result_count = 0;
 246    :    _DInst results[kMaxResults];
 247    :    EXPECT_EQ(DECRES_SUCCESS,
 248    :              RawDecomposeCode(kFldcw,
 249    :                               sizeof(kFldcw),
 250    :                               results,
 251    :                               kMaxResults,
 252  E :                               &result_count));
 253  E :    EXPECT_EQ(1U, result_count);
 254  E :    EXPECT_EQ(0U, results[0].ops[0].size);
 255  E :  }
 256    :  
 257  E :  TEST(DisassemblerUtilTest, DistormDecomposeFldcw) {
 258  E :    const unsigned int kMaxResults = 16;
 259  E :    unsigned int result_count = 0;
 260    :    _DInst results[kMaxResults];
 261    :    EXPECT_EQ(DECRES_SUCCESS,
 262    :              DecomposeCode(kFldcw,
 263    :                            sizeof(kFldcw),
 264    :                            results,
 265    :                            kMaxResults,
 266  E :                            &result_count));
 267  E :    EXPECT_EQ(1U, result_count);
 268  E :    EXPECT_EQ(16U, results[0].ops[0].size);
 269  E :  }
 270    :  
 271  E :  TEST(DisassemblerUtilTest, WrongAccessSizeOnRawDistormDecomposeFldcw) {
 272  E :    const unsigned int kMaxResults = 16;
 273  E :    unsigned int result_count = 0;
 274    :    _DInst results[kMaxResults];
 275    :    EXPECT_EQ(DECRES_SUCCESS,
 276    :              RawDecomposeCode(kFldcw,
 277    :                               sizeof(kFldcw),
 278    :                               results,
 279    :                               kMaxResults,
 280  E :                               &result_count));
 281  E :    EXPECT_EQ(1U, result_count);
 282  E :    EXPECT_EQ(0U, results[0].ops[0].size);
 283  E :  }
 284    :  
 285    :  }  // namespace core

Coverage information generated Thu Mar 14 11:53:36 2013.