Coverage for /Syzygy/core/disassembler_util_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%1551550.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    :  // Instructions for which distorm do not activated the write flag.
  75    :  // fst qword ptr [0A374E8h]
  76    :  const uint8 kFst[] = { 0xDD, 0x15, 0xE8, 0x74, 0xA3, 0x00 };
  77    :  // fstp qword ptr [0A374E8h]
  78    :  const uint8 kFstp[] = { 0xDD, 0x1D, 0xE8, 0x74, 0xA3, 0x00 };
  79    :  // fist qword ptr [0A374E8h]
  80    :  const uint8 kFist[] = { 0xDB, 0x15, 0xE0, 0x74, 0xA3, 0x00 };
  81    :  // fistp qword ptr [0A374E8h]
  82    :  const uint8 kFistp[] = { 0xDB, 0x1D, 0xE0, 0x74, 0xA3, 0x00 };
  83    :  
  84    :  // Nop Instruction byte sequences.
  85    :  const uint8 kNop2Mov[] = { 0x8B, 0xFF };
  86    :  const uint8 kNop3Lea[] = { 0x8D, 0x49, 0x00 };
  87    :  const uint8 kNop1[] = { 0x90 };
  88    :  const uint8 kNop2[] = { 0x66, 0x90 };
  89    :  const uint8 kNop3[] = { 0x66, 0x66, 0x90 };
  90    :  const uint8 kNop4[] = { 0x0F, 0x1F, 0x40, 0x00 };
  91    :  const uint8 kNop5[] = { 0x0F, 0x1F, 0x44, 0x00, 0x00 };
  92    :  const uint8 kNop6[] = { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 };
  93    :  const uint8 kNop7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 };
  94    :  const uint8 kNop8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
  95    :  const uint8 kNop9[] = {
  96    :      0x66,  // Prefix,
  97    :      0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00  // kNop8.
  98    :  };
  99    :  const uint8 kNop10[] = {
 100    :      0x66, 0x66,  // Prefix.
 101    :      0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00  // kNop8.
 102    :  };
 103    :  const uint8 kNop11[] = {
 104    :      0x66, 0x66, 0x66,  // Prefix.
 105    :      0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00  // kNop8
 106    :  };
 107    :  
 108    :  // Call instruction.
 109    :  const uint8 kCall[] = { 0xE8, 0xCA, 0xFE, 0xBA, 0xBE };
 110    :  
 111    :  // Control Flow byte sequences (note that the JMP is indirect).
 112    :  const uint8 kJmp[] = { 0xFF, 0x24, 0x8D, 0xCA, 0xFE, 0xBA, 0xBE };
 113    :  const uint8 kRet[] = { 0xC3 };
 114    :  const uint8 kRetN[] = { 0xC2, 0x08, 0x00 };
 115    :  const uint8 kJe[] = { 0x74, 0xCA };
 116    :  const uint8 kSysEnter[] = { 0x0F, 0x34 };
 117    :  const uint8 kSysExit[] = { 0x0F, 0x35 };
 118    :  
 119    :  // Interrupts.
 120    :  const uint8 kInt2[] = { 0xCD, 0x02 };
 121    :  const uint8 kInt3[] = { 0xCC };
 122    :  
 123    :  }  // namespace
 124    :  
 125  E :  TEST(DisassemblerUtilTest, DistormWrapperVxorpsPasses) {
 126  E :    _DInst inst = {};
 127  E :    EXPECT_TRUE(DecodeOneInstruction(kVxorps, sizeof(kVxorps), &inst));
 128  E :  }
 129    :  
 130  E :  TEST(DisassemblerUtilTest, InstructionToString) {
 131  E :    _DInst inst = {};
 132  E :    inst = DecodeBuffer(kNop1, sizeof(kNop1));
 133    :  
 134  E :    std::string Nop1Str;
 135  E :    EXPECT_TRUE(InstructionToString(inst, kNop1, sizeof(kNop1), &Nop1Str));
 136  E :    ASSERT_THAT(Nop1Str, testing::HasSubstr("90"));
 137  E :    ASSERT_THAT(Nop1Str, testing::HasSubstr("NOP"));
 138  E :  }
 139    :  
 140  E :  TEST(DisassemblerUtilTest, IsNop) {
 141  E :    EXPECT_FALSE(IsNop(DecodeBuffer(kJmp, sizeof(kJmp))));
 142  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop1, sizeof(kNop1))));
 143  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop2, sizeof(kNop2))));
 144  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop3, sizeof(kNop3))));
 145  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop4, sizeof(kNop4))));
 146  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop5, sizeof(kNop5))));
 147  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop6, sizeof(kNop6))));
 148  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop7, sizeof(kNop7))));
 149  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop8, sizeof(kNop8))));
 150  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop9, sizeof(kNop9))));
 151  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop10, sizeof(kNop10))));
 152  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop11, sizeof(kNop11))));
 153  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop2Mov, sizeof(kNop2Mov))));
 154  E :    EXPECT_TRUE(IsNop(DecodeBuffer(kNop3Lea, sizeof(kNop3Lea))));
 155  E :  }
 156    :  
 157  E :  TEST(DisassemblerUtilTest, IsCall) {
 158  E :    EXPECT_FALSE(IsCall(DecodeBuffer(kJmp, sizeof(kJmp))));
 159  E :    EXPECT_FALSE(IsCall(DecodeBuffer(kNop1, sizeof(kNop1))));
 160  E :    EXPECT_TRUE(IsCall(DecodeBuffer(kCall, sizeof(kCall))));
 161  E :  }
 162    :  
 163  E :  TEST(DisassemblerUtilTest, IsSystemCall) {
 164  E :    EXPECT_FALSE(IsSystemCall(DecodeBuffer(kJmp, sizeof(kJmp))));
 165  E :    EXPECT_FALSE(IsSystemCall(DecodeBuffer(kNop1, sizeof(kNop1))));
 166  E :    EXPECT_TRUE(IsSystemCall(DecodeBuffer(kSysEnter, sizeof(kSysEnter))));
 167  E :    EXPECT_TRUE(IsSystemCall(DecodeBuffer(kSysExit, sizeof(kSysExit))));
 168  E :  }
 169    :  
 170  E :  TEST(DisassemblerUtilTest, IsConditionalBranch) {
 171  E :    EXPECT_FALSE(IsConditionalBranch(DecodeBuffer(kNop4, sizeof(kNop4))));
 172  E :    EXPECT_FALSE(IsConditionalBranch(DecodeBuffer(kJmp, sizeof(kJmp))));
 173  E :    EXPECT_FALSE(IsConditionalBranch(DecodeBuffer(kRet, sizeof(kRet))));
 174  E :    EXPECT_TRUE(IsConditionalBranch(DecodeBuffer(kJe, sizeof(kJe))));
 175  E :  }
 176    :  
 177  E :  TEST(DisassemblerUtilTest, IsUnconditionalBranch) {
 178  E :    EXPECT_FALSE(IsUnconditionalBranch(DecodeBuffer(kNop4, sizeof(kNop4))));
 179  E :    EXPECT_FALSE(IsUnconditionalBranch(DecodeBuffer(kRet, sizeof(kRet))));
 180  E :    EXPECT_FALSE(IsUnconditionalBranch(DecodeBuffer(kJe, sizeof(kJe))));
 181  E :    EXPECT_TRUE(IsUnconditionalBranch(DecodeBuffer(kJmp, sizeof(kJmp))));
 182  E :  }
 183    :  
 184  E :  TEST(DisassemblerUtilTest, IsBranch) {
 185  E :    EXPECT_FALSE(IsBranch(DecodeBuffer(kNop4, sizeof(kNop4))));
 186  E :    EXPECT_FALSE(IsBranch(DecodeBuffer(kRet, sizeof(kRet))));
 187  E :    EXPECT_TRUE(IsBranch(DecodeBuffer(kJe, sizeof(kJe))));
 188  E :    EXPECT_TRUE(IsBranch(DecodeBuffer(kJmp, sizeof(kJmp))));
 189  E :  }
 190    :  
 191  E :  TEST(DisassemblerUtilTest, HasPcRelativeOperand) {
 192  E :    EXPECT_FALSE(HasPcRelativeOperand(DecodeBuffer(kRetN, sizeof(kRet)), 0));
 193  E :    EXPECT_FALSE(HasPcRelativeOperand(DecodeBuffer(kJmp, sizeof(kJmp)), 0));
 194  E :    EXPECT_TRUE(HasPcRelativeOperand(DecodeBuffer(kJe, sizeof(kJe)), 0));
 195  E :  }
 196    :  
 197  E :  TEST(DisassemblerUtilTest, IsControlFlow) {
 198  E :    EXPECT_FALSE(IsControlFlow(DecodeBuffer(kNop4, sizeof(kNop4))));
 199  E :    EXPECT_TRUE(IsControlFlow(DecodeBuffer(kJmp, sizeof(kJmp))));
 200  E :    EXPECT_TRUE(IsControlFlow(DecodeBuffer(kRet, sizeof(kRet))));
 201  E :    EXPECT_TRUE(IsControlFlow(DecodeBuffer(kRetN, sizeof(kRetN))));
 202  E :    EXPECT_TRUE(IsControlFlow(DecodeBuffer(kJe, sizeof(kJe))));
 203  E :    EXPECT_TRUE(IsControlFlow(DecodeBuffer(kSysEnter, sizeof(kSysEnter))));
 204  E :  }
 205    :  
 206  E :  TEST(DisassemblerUtilTest, IsImplicitControlFlow) {
 207  E :    EXPECT_FALSE(IsImplicitControlFlow(DecodeBuffer(kJe, sizeof(kJe))));
 208  E :    EXPECT_TRUE(IsImplicitControlFlow(DecodeBuffer(kRet, sizeof(kRet))));
 209  E :    EXPECT_TRUE(IsImplicitControlFlow(DecodeBuffer(kRetN, sizeof(kRetN))));
 210  E :    EXPECT_TRUE(IsImplicitControlFlow(DecodeBuffer(kJmp, sizeof(kJmp))));
 211  E :  }
 212    :  
 213  E :  TEST(DisassemblerUtilTest, IsInterrupt) {
 214  E :    EXPECT_FALSE(IsInterrupt(DecodeBuffer(kJe, sizeof(kJe))));
 215  E :    EXPECT_TRUE(IsInterrupt(DecodeBuffer(kInt2, sizeof(kInt2))));
 216  E :    EXPECT_TRUE(IsInterrupt(DecodeBuffer(kInt3, sizeof(kInt3))));
 217  E :  }
 218    :  
 219  E :  TEST(DisassemblerUtilTest, IsDebugInterrupt) {
 220  E :    EXPECT_FALSE(IsDebugInterrupt(DecodeBuffer(kJe, sizeof(kJe))));
 221  E :    EXPECT_FALSE(IsDebugInterrupt(DecodeBuffer(kInt2, sizeof(kInt2))));
 222  E :    EXPECT_TRUE(IsDebugInterrupt(DecodeBuffer(kInt3, sizeof(kInt3))));
 223  E :  }
 224    :  
 225  E :  TEST(DisassemblerUtilTest, DistormDecompose) {
 226  E :    const unsigned int kMaxResults = 16;
 227  E :    unsigned int result_count = 0;
 228    :    _DInst results[kMaxResults];
 229    :    EXPECT_EQ(DECRES_SUCCESS,
 230    :              DecomposeCode(kNop3Lea,
 231    :                            sizeof(kNop3Lea),
 232    :                            results,
 233    :                            kMaxResults,
 234  E :                            &result_count));
 235  E :    EXPECT_EQ(1U, result_count);
 236  E :    EXPECT_EQ(32U, results[0].ops[0].size);
 237  E :  }
 238    :  
 239  E :  TEST(DisassemblerUtilTest, DistormDecomposeFnstcw) {
 240  E :    const unsigned int kMaxResults = 16;
 241  E :    unsigned int result_count = 0;
 242    :    _DInst results[kMaxResults];
 243    :    EXPECT_EQ(DECRES_SUCCESS,
 244    :              DecomposeCode(kFnstcw,
 245    :                            sizeof(kFnstcw),
 246    :                            results,
 247    :                            kMaxResults,
 248  E :                            &result_count));
 249  E :    EXPECT_EQ(1U, result_count);
 250  E :    EXPECT_EQ(16U, results[0].ops[0].size);
 251  E :  }
 252    :  
 253  E :  TEST(DisassemblerUtilTest, WrongAccessSizeOnRawDistormDecomposeFnstcw) {
 254  E :    const unsigned int kMaxResults = 16;
 255  E :    unsigned int result_count = 0;
 256    :    _DInst results[kMaxResults];
 257    :    EXPECT_EQ(DECRES_SUCCESS,
 258    :              RawDecomposeCode(kFldcw,
 259    :                               sizeof(kFldcw),
 260    :                               results,
 261    :                               kMaxResults,
 262  E :                               &result_count));
 263  E :    EXPECT_EQ(1U, result_count);
 264  E :    EXPECT_EQ(0U, results[0].ops[0].size);
 265  E :  }
 266    :  
 267  E :  TEST(DisassemblerUtilTest, DistormDecomposeFldcw) {
 268  E :    const unsigned int kMaxResults = 16;
 269  E :    unsigned int result_count = 0;
 270    :    _DInst results[kMaxResults];
 271    :    EXPECT_EQ(DECRES_SUCCESS,
 272    :              DecomposeCode(kFldcw,
 273    :                            sizeof(kFldcw),
 274    :                            results,
 275    :                            kMaxResults,
 276  E :                            &result_count));
 277  E :    EXPECT_EQ(1U, result_count);
 278  E :    EXPECT_EQ(16U, results[0].ops[0].size);
 279  E :  }
 280    :  
 281  E :  TEST(DisassemblerUtilTest, WrongAccessSizeOnRawDistormDecomposeFldcw) {
 282  E :    const unsigned int kMaxResults = 16;
 283  E :    unsigned int result_count = 0;
 284    :    _DInst results[kMaxResults];
 285    :    EXPECT_EQ(DECRES_SUCCESS,
 286    :              RawDecomposeCode(kFldcw,
 287    :                               sizeof(kFldcw),
 288    :                               results,
 289    :                               kMaxResults,
 290  E :                               &result_count));
 291  E :    EXPECT_EQ(1U, result_count);
 292  E :    EXPECT_EQ(0U, results[0].ops[0].size);
 293  E :  }
 294    :  
 295  E :  TEST(DisassemblerUtilTest, WrongWriteFlagOnRawDistormDecomposeFst) {
 296  E :    _DInst fst = DecodeBuffer(kFst, sizeof(kFst));
 297  E :    EXPECT_NE(0, fst.flags & FLAG_DST_WR);
 298    :  
 299  E :    _DInst fstp = DecodeBuffer(kFstp, sizeof(kFstp));
 300  E :    EXPECT_NE(0, fstp.flags & FLAG_DST_WR);
 301    :  
 302  E :    _DInst fist = DecodeBuffer(kFist, sizeof(kFist));
 303  E :    EXPECT_NE(0, fist.flags & FLAG_DST_WR);
 304    :  
 305  E :    _DInst fistp = DecodeBuffer(kFistp, sizeof(kFistp));
 306  E :    EXPECT_NE(0, fistp.flags & FLAG_DST_WR);
 307  E :  }
 308    :  
 309    :  }  // namespace core

Coverage information generated Tue Jun 25 13:56:24 2013.