LCOV - code coverage report
Current view: directory - src/trusted/validator_arm - validator_small_tests.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 596 563 94.5 %
Date: 2014-10-23 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #ifndef NACL_TRUSTED_BUT_NOT_TCB
       8                 : #error This file is not meant for use in the TCB
       9                 : #endif
      10                 : 
      11                 : /*
      12                 :  * Small unit tests for the ARM validator
      13                 :  *
      14                 :  * Also see validator_large_tests.cc,
      15                 :  * and validator_tests.h for the testing infrastructure.
      16                 :  */
      17                 : 
      18                 : #include "native_client/src/trusted/validator_arm/validator_tests.h"
      19                 : 
      20                 : using nacl_val_arm_test::ProblemRecord;
      21                 : using nacl_val_arm_test::ProblemSpy;
      22                 : using nacl_val_arm_test::ValidatorTests;
      23                 : using nacl_val_arm_test::kDefaultBaseAddr;
      24                 : using nacl_val_arm_test::kBytesPerBundle;
      25                 : using nacl_val_arm_test::kCodeRegionSize;
      26                 : using nacl_val_arm_test::kDataRegionSize;
      27                 : using nacl_val_arm_test::kAbiReadOnlyRegisters;
      28                 : using nacl_val_arm_test::kAbiDataAddrRegisters;
      29                 : using nacl_val_arm_test::arm_inst;
      30                 : using nacl_arm_dec::kArm32InstSize;
      31                 : using nacl_arm_dec::kNop;
      32                 : using nacl_arm_dec::kLiteralPoolHead;
      33                 : using nacl_arm_dec::kFailValidation;
      34                 : using nacl_arm_dec::Instruction;
      35                 : using nacl_arm_dec::ClassDecoder;
      36                 : 
      37                 : namespace {
      38                 : 
      39                 : const arm_inst kSvc0 = 0xEF000000;  // SVC #0
      40                 : 
      41                 : // Holds instruction and message to print if there is an issue when it
      42                 : // is tested.
      43                 : struct AnnotatedInstruction {
      44                 :   arm_inst inst;
      45                 :   const char *about;
      46                 : };
      47                 : 
      48            2070 : arm_inst ChangeInstCond(Instruction inst, Instruction::Condition cond) {
      49            2070 :   return ValidatorTests::ChangeCond(inst.Bits(), cond);
      50                 : }
      51                 : 
      52                 : // Tests if a list of instructions generate the same dynamic code
      53                 : // replacement sentinel.
      54               6 : void test_if_dynamic_code_replacement_sentinels_match(
      55                 :     const ValidatorTests* tester,
      56                 :     const AnnotatedInstruction* insts,
      57                 :     size_t num_insts,
      58                 :     arm_inst expected_sentinel) {
      59               6 :   const Instruction expected_inst(expected_sentinel);
      60                 : 
      61                 :   // Try each instruction.
      62              42 :   for (size_t i = 0; i < num_insts; i++) {
      63              36 :     Instruction test_inst(insts[i].inst);
      64                 : 
      65                 :     // Try each possible condition (conditions shouldn't affect this virtual).
      66             576 :     for (Instruction::Condition cond = Instruction::EQ;
      67                 :          cond < Instruction::UNCONDITIONAL;
      68                 :          cond = Instruction::Next(cond)) {
      69             540 :       Instruction test(ChangeInstCond(test_inst, cond));
      70             540 :       Instruction expected(ChangeInstCond(expected_inst, cond));
      71                 : 
      72             540 :       const ClassDecoder& decoder = tester->decode(test);
      73             540 :       Instruction sentinel(decoder.dynamic_code_replacement_sentinel(test));
      74             540 :       EXPECT_TRUE(expected.Equals(sentinel)) <<
      75               0 :         std::hex << test.Bits() << "->" <<
      76               0 :           std::hex << sentinel.Bits() << " != " <<
      77             540 :           std::hex << expected.Bits() << ": " << insts[i].about;
      78                 :     }
      79                 :   }
      80               6 : }
      81                 : 
      82                 : // Tests if a list of instructions generate the same dynamic code replacement
      83                 : // sentinel.
      84               6 : void test_if_dynamic_code_replacement_sentinels_unchanged(
      85                 :     const ValidatorTests* tester,
      86                 :     const AnnotatedInstruction* insts,
      87                 :     size_t num_insts) {
      88                 :   // Try each instruction.
      89              61 :   for (size_t i = 0; i < num_insts; i++) {
      90              55 :     Instruction test_inst(insts[i].inst);
      91                 : 
      92                 :     // Try each possible condition (conditions shouldn't affect this virtual).
      93             880 :     for (Instruction::Condition cond = Instruction::EQ;
      94                 :          cond < Instruction::UNCONDITIONAL;
      95                 :          cond = Instruction::Next(cond)) {
      96             825 :       Instruction test(ChangeInstCond(test_inst, cond));
      97             825 :       const ClassDecoder& decoder = tester->decode(test);
      98             825 :       Instruction sentinel(decoder.dynamic_code_replacement_sentinel(test));
      99             825 :       EXPECT_TRUE(test.Equals(sentinel)) <<
     100               0 :           std::hex << test.Bits() << "->" <<
     101             825 :           std::hex << sentinel.Bits() << ": " << insts[i].about;
     102                 :     }
     103                 :   }
     104               6 : }
     105                 : 
     106                 : // Test that the old code can be replaced by the new code.
     107               4 : void TestDynamicCodeReplacement(
     108                 :     SfiValidator *validator,
     109                 :     bool expected_result,
     110                 :     const vector<arm_inst>& old_code,
     111                 :     const vector<arm_inst>& new_code,
     112                 :     const char *msg) {
     113               4 :   EXPECT_EQ(old_code.size(), new_code.size());
     114                 : 
     115               4 :   size_t size = old_code.size() * kArm32InstSize / CHAR_BIT;
     116               4 :   CodeSegment new_segment((uint8_t *) &new_code[0], kDefaultBaseAddr, size);
     117               4 :   CodeSegment old_segment((uint8_t *) &old_code[0], kDefaultBaseAddr, size);
     118                 : 
     119               4 :   EXPECT_EQ(expected_result,
     120                 :             validator->ValidateSegmentPair(old_segment, new_segment, NULL)) <<
     121               0 :       "Code replacement expected different validation result for " << msg;
     122               4 : }
     123                 : 
     124                 : // Verify that there is enough room in ViolationSet to include all
     125                 : // elements in enum Violation.
     126               5 : TEST_F(ValidatorTests, ViolationsFitInViolationSet) {
     127               1 :   EXPECT_LT(static_cast<size_t>(nacl_arm_dec::OTHER_VIOLATION),
     128               1 :             sizeof(nacl_arm_dec::ViolationSet) * CHAR_BIT);
     129               1 : }
     130                 : 
     131               5 : TEST_F(ValidatorTests, NopBundle) {
     132               1 :   vector<arm_inst> code(_validator->InstructionsPerBundle(), kNop);
     133               1 :   validation_should_pass(&code[0], code.size(), kDefaultBaseAddr,
     134               2 :                          "NOP bundle");
     135               1 : }
     136                 : 
     137                 : /*
     138                 :  * Primitive tests checking various constructor properties.  Any of these
     139                 :  * failing would be a very bad sign indeed.
     140                 :  */
     141                 : 
     142               5 : TEST_F(ValidatorTests, RecognizesDataAddressRegisters) {
     143                 :   // Note that the logic below needs to be kept in sync with the definition
     144                 :   // of kAbiDataAddrRegisters at the top of this file.
     145                 :   //
     146                 :   // This test is pretty trivial -- we can exercise the data_address_register
     147                 :   // functionality more deeply with pattern tests below.
     148              17 :   for (int i = 0; i < 16; i++) {
     149              16 :     Register r(i);
     150              16 :     if (r.Equals(nacl_arm_dec::Register::Sp())) {
     151               1 :       EXPECT_TRUE(_validator->is_data_address_register(r))
     152               0 :           << "Stack pointer must be a data address register.";
     153                 :     } else {
     154              15 :       EXPECT_FALSE(_validator->is_data_address_register(r))
     155               0 :           << "Only the stack pointer must be a data address register.";
     156                 :     }
     157                 :   }
     158               1 : }
     159                 : 
     160               5 : TEST_F(ValidatorTests, GeneratesCorrectMasksFromSizes) {
     161               1 :   EXPECT_EQ(0xC0000000, _validator->data_address_mask());
     162               1 :   EXPECT_EQ(0xE000000F, _validator->code_address_mask());
     163                 : 
     164                 :   // Reinitialize the validator to test a different bundle size.
     165                 :   SfiValidator *new_validator = new SfiValidator(32,
     166                 :                                                  kCodeRegionSize,
     167                 :                                                  kDataRegionSize,
     168                 :                                                  kAbiReadOnlyRegisters,
     169                 :                                                  kAbiDataAddrRegisters,
     170               1 :                                                  _validator->CpuFeatures());
     171               1 :   delete _validator;
     172               1 :   _validator = new_validator;
     173                 : 
     174               1 :   EXPECT_EQ(0xC0000000, _validator->data_address_mask())
     175               0 :       << "Changes in bundle size should not affect the data mask.";
     176               1 :   EXPECT_EQ(0xE000001F, _validator->code_address_mask())
     177               0 :       << "Changes in bundle size must affect the code mask.";
     178               1 : }
     179                 : 
     180                 : // Code validation tests
     181                 : 
     182               5 : TEST_F(ValidatorTests, DirectBranchTargetCalculation) {
     183               1 :   const nacl_arm_dec::Arm32DecoderState decode_state;
     184                 :   // Try decoding PC-relative branches from interesting PCs.
     185                 :   uint32_t start_addrs[] = { 0x00000000, 0x00010000, 0x00020000, 0x06789abc,
     186               1 :                              0x12345678, 0x3fffffff, 0xdeadbeef, 0xff000000, };
     187               9 :   for (size_t a = 0; a < NACL_ARRAY_SIZE(start_addrs); ++a) {
     188               8 :     uint32_t start_addr = start_addrs[a];
     189                 :     // All PC-relative branches supported by NaCl.
     190                 :     arm_inst insts[] = {
     191                 :       0xea000000,  // B PC+8+0
     192                 :       0xeb000000,  // BL PC+8+0
     193               8 :     };
     194              24 :     for (arm_inst* inst = insts;
     195                 :          inst < insts + NACL_ARRAY_SIZE(insts);
     196                 :          ++inst) {
     197             256 :       for (Instruction::Condition cond = Instruction::EQ;
     198                 :            cond <= Instruction::AL;
     199                 :            cond = Instruction::Next(cond)) {
     200             240 :         *inst = ChangeCond(*inst, cond);
     201          984240 :         for (int32_t imm = -2050; imm < 2050; ++imm) {
     202                 :           // For all PC-relative branches that NaCl supports:
     203                 :           //   imm24(23:0);
     204                 :           //   imm32 = SignExtend(imm24:'00', 32);
     205                 :           //   targetAddress = Align(PC,4) + imm32;
     206                 :           // Where:
     207                 :           //   The PC value of an instruction is its address plus 8 for an
     208                 :           //   ARM instruction. The Align(PC, 4) value of an instruction is
     209                 :           //   its PC value ANDed with 0xFFFFFFFC to force it to be
     210                 :           //   word-aligned. There is no difference between the PC and
     211                 :           //   Align(PC, 4) values for an ARM instruction.
     212          984000 :           *inst = (*inst & 0xff000000) | ((imm >> 2) & 0x00ffffff);
     213          984000 :           const uint8_t *bytes = reinterpret_cast<const uint8_t *>(inst);
     214          984000 :           CodeSegment segment(bytes, start_addr, sizeof(arm_inst));
     215                 :           nacl_arm_val::DecodedInstruction inst(start_addr, segment[start_addr],
     216                 :                                                 decode_state.decode(
     217          984000 :                                                     segment[start_addr]));
     218          984000 :           EXPECT_TRUE(inst.is_relative_branch());
     219          984000 :           EXPECT_EQ(start_addr + 8 + (imm & 0xfffffffc), inst.branch_target());
     220                 :         }
     221                 :       }
     222                 :     }
     223               1 :   }
     224               1 : }
     225                 : 
     226                 : // Here are examples of every form of safe store permitted in a Native Client
     227                 : // program.  These stores have common properties:
     228                 : //  1. The high nibble is 0, to allow tests to write an arbitrary predicate.
     229                 : //  2. They address memory only through r1 (assumed to be the first register
     230                 : //     in the about text).
     231                 : //  3. They do not do anything dumb, like try to alter SP or PC.
     232                 : static const AnnotatedInstruction examples_of_safe_stores[] = {
     233                 :   // Single-register stores
     234                 :   { 0x05810000, "str r0, [r1]: simple no-displacement store" },
     235                 :   { 0x05810123, "str r0, [r1, #0x123]: positive displacement" },
     236                 :   { 0x05010123, "str r0, [r1, #-0x123]: negative displacement" },
     237                 :   { 0x05A10123, "str r0, [r1, #0x123]!: positive disp + writeback" },
     238                 :   { 0x05210123, "str r0, [r1, #-0x123]!: negative disp + writeback" },
     239                 :   { 0x04810123, "str r0, [r1], #0x123: positive post-indexing" },
     240                 :   { 0x04010123, "str r0, [r1], #-0x123: negative post-indexing" },
     241                 :   { 0x06810002, "str r0, [r1], r2: positive register post-indexing" },
     242                 :   { 0x06010002, "str r0, [r1], -r2: negative register post-indexing" },
     243                 : 
     244                 :   // Two-register store
     245                 :   { 0x01C120F0, "strd r2, r3, [r1]: basic 64-bit store" },
     246                 :   { 0x01C124F2, "strd r2, r3, [r1, #42]: positive disp 64-bit store" },
     247                 :   { 0x014124F2, "strd r2, r3, [r1, #-42]: negative disp 64-bit store" },
     248                 :   { 0x01E124F2, "strd r2, r3, [r1, #42]!: positive disp 64-bit store + wb" },
     249                 :   { 0x016124F2, "strd r2, r3, [r1, #-42]!: negative disp 64-bit store + wb" },
     250                 :   { 0x00C124F2, "strd r2, r3, [r1], #42: post-inc 64-bit store" },
     251                 :   { 0x004124F2, "strd r2, r3, [r1], #-42: post-dec 64-bit store" },
     252                 : 
     253                 :   // Store-exclusive
     254                 :   { 0x01810F92, "strex r0, r2, [r1]: store exclusive" },
     255                 : 
     256                 :   // Store-multiple
     257                 :   // Note: It is illegal to store r9 (NaCl constraint), so it must
     258                 :   // be ommitted from the register sets.
     259                 :   { 0x0881FDFF, "stm r1, { r0-r8, r10-r15 }: store multiple, no writeback" },
     260                 :   // Note: can't store registers whose number is less than Rt when there is
     261                 :   //       writeback. E.g. stm r1! { r0-r15 } is unknown.
     262                 :   { 0x08A1FDFE, "stm r1!, { r1-r8, r10-r15 }: store multiple, writeback" },
     263                 :   { 0x08A1FDFC, "stm r1!, { r2-r8, r10-r15 }: store multiple, writeback" },
     264                 : 
     265                 :   // Stores from the floating point / vector register file
     266                 :   // These all compile to STC instructions.
     267                 :   { 0x0D810B00, "vstr d0, [r1]: direct vector store" },
     268                 :   { 0x0D810B99, "vstr d0, [r1, #0x99]: positive displacement vector store" },
     269                 :   { 0x0D010B99, "vstr d0, [r1, #-0x99]: negative displacement vector store" },
     270                 :   { 0x0C810B10, "vstmia r1, { d0-d7 }: no writeback" },
     271                 :   { 0x0CA10B10, "vstmia r1!, { d0-d7 }: writeback" },
     272                 : };
     273                 : 
     274                 : // Note: We assume that r3 is used for the operand, if it isn't the same
     275                 : // as the destination (i.e. r1).
     276                 : static const AnnotatedInstruction examples_of_safe_masks[] = {
     277                 :   { 0x03C11103, "bic r1, r1, #0xC0000000: simple in-place mask (form 1)" },
     278                 :   { 0x03C114C0, "bic r1, r1, #0xC0000000: simple in-place mask (form 2)" },
     279                 :   { 0x03C314C0, "bic r1, r3, #0xC0000000: mask with register move" },
     280                 :   { 0x03C114FF, "bic r1, r1, #0xFF000000: overzealous but correct mask" },
     281                 : };
     282                 : 
     283               5 : TEST_F(ValidatorTests, SafeMaskedStores) {
     284                 :   // Produces many examples of masked stores using the safe store table (above)
     285                 :   // and the list of possible masking instructions (below).
     286                 :   //
     287                 :   // Each mask instruction must leave a valid (data) address in r1.
     288              16 :   for (unsigned p = 0; p < 15; p++) {
     289                 :     // Conditionally executed instructions have a top nibble of 0..14.
     290                 :     // 15 is an escape sequence used to fit in additional encodings.
     291              15 :     arm_inst predicate = p << 28;
     292                 : 
     293              75 :     for (unsigned m = 0; m < NACL_ARRAY_SIZE(examples_of_safe_masks); m++) {
     294            1560 :       for (unsigned s = 0; s < NACL_ARRAY_SIZE(examples_of_safe_stores); s++) {
     295            1500 :         ostringstream message;
     296            1500 :         message << examples_of_safe_masks[m].about
     297            1500 :                 << ", "
     298            3000 :                 << examples_of_safe_stores[s].about
     299            1500 :                 << " (predicate #" << p << ")";
     300                 :         arm_inst program[] = {
     301                 :           examples_of_safe_masks[m].inst | predicate,
     302                 :           examples_of_safe_stores[s].inst | predicate,
     303            1500 :         };
     304                 :         validation_should_pass2(program,
     305                 :                                 2,
     306                 :                                 kDefaultBaseAddr,
     307            1500 :                                 message.str());
     308            1500 :       }
     309                 :     }
     310                 :   }
     311               1 : }
     312                 : 
     313                 : static const AnnotatedInstruction examples_of_safe_unconditional_stores[] = {
     314                 :   // Vector stores
     315                 :   { 0xF481A5AF, "vst2.16 {d10[2],d12[2]}, [r1]: simple vector store" },
     316                 :   { 0xF401A64F, "vst1.16 {d10-d12}, [r1]: larger vector store" },
     317                 :   { 0xF4010711, "vst1.8 {d0}, [r1, :64], r1: register post-increment" },
     318                 : };
     319                 : 
     320               5 : TEST_F(ValidatorTests, SafeUnconditionalMaskedStores) {
     321                 :   // Produces many examples of unconditional masked stores using the safe
     322                 :   // unconditional store table (above) and the list of possible masking
     323                 :   // instructions (below).
     324                 :   //
     325                 :   // Each mask instruction must leave a valid (data) address in r1.
     326                 : 
     327               5 :   for (unsigned m = 0; m < NACL_ARRAY_SIZE(examples_of_safe_masks); m++) {
     328              16 :     for (unsigned s = 0;
     329                 :          s < NACL_ARRAY_SIZE(examples_of_safe_unconditional_stores);
     330                 :          s++) {
     331              12 :       ostringstream message;
     332              12 :       message << examples_of_safe_masks[m].about
     333              12 :               << ", "
     334              24 :               << examples_of_safe_unconditional_stores[s].about;
     335                 :       arm_inst program[] = {
     336                 :         ValidatorTests::ChangeCond(examples_of_safe_masks[m].inst,
     337              12 :                                    Instruction::AL),
     338                 :         examples_of_safe_unconditional_stores[s].inst,
     339              12 :       };
     340                 :       validation_should_pass2(program,
     341                 :                               2,
     342                 :                               kDefaultBaseAddr,
     343              12 :                               message.str());
     344              12 :     }
     345                 :   }
     346               1 : }
     347                 : 
     348               5 : TEST_F(ValidatorTests, SafeConditionalStores) {
     349                 :   // Produces many examples of conditional stores using the safe store table
     350                 :   // (above) and the list of possible conditional guards (below).
     351                 :   //
     352                 :   // Each conditional guard must set the Z flag iff r1 contains a valid address.
     353                 :   static const AnnotatedInstruction guards[] = {
     354                 :     { 0x03110103, "tst r1, #0xC0000000: precise guard, GCC encoding" },
     355                 :     { 0x031104C0, "tst r1, #0xC0000000: precise guard, alternative encoding" },
     356                 :     { 0x031101C3, "tst r1, #0xF0000000: overzealous (but correct) guard" },
     357                 :   };
     358                 : 
     359                 :   // Reinitialize the validator to test both allowing and disallowing
     360                 :   // conditional memory accesses.
     361               3 :   for (int allow_cond = 0; allow_cond <= 1; ++allow_cond) {
     362                 :     NaClCPUFeaturesArm cpu_features;
     363               2 :     NaClCopyCPUFeaturesArm(&cpu_features, _validator->CpuFeatures());
     364                 :     NaClSetCPUFeatureArm(&cpu_features, NaClCPUFeatureArm_CanUseTstMem,
     365               2 :                          allow_cond);
     366               2 :     delete _validator;
     367                 :     _validator = new SfiValidator(kBytesPerBundle,
     368                 :                                   kCodeRegionSize,
     369                 :                                   kDataRegionSize,
     370                 :                                   kAbiReadOnlyRegisters,
     371                 :                                   kAbiDataAddrRegisters,
     372               2 :                                   &cpu_features);
     373                 : 
     374                 :     // Currently we only support *unconditional* conditional stores.
     375                 :     // Meaning the guard is unconditional and the store is if-equal.
     376                 :     //   e.g.: tst.al rbase, #mask
     377                 :     //         str.eq rval, [rbase]
     378              32 :     for (Instruction::Condition guard_cond = Instruction::EQ;
     379                 :          guard_cond <= Instruction::AL;
     380                 :          guard_cond = Instruction::Next(guard_cond)) {
     381             480 :       for (Instruction::Condition store_cond = Instruction::EQ;
     382                 :            store_cond <= Instruction::AL;
     383                 :            store_cond = Instruction::Next(store_cond)) {
     384            1800 :         for (size_t guard = 0;
     385                 :              guard < NACL_ARRAY_SIZE(guards);
     386                 :              guard++) {
     387            1350 :           arm_inst guard_inst = guards[guard].inst;
     388            4050 :           for (int use_same_base = 0; use_same_base <= 1; ++use_same_base) {
     389                 :             // Alternate between using the same rbase for tst and str.
     390                 :             // TODO(jfb) This is hackish, and should be better handled
     391                 :             //           throughout these tests. AnnotatedInstruction is
     392                 :             //           probably the right place for this.
     393            2700 :             unsigned base = use_same_base ? 1 : 2;  // Rn is now r1 or r2.
     394            2700 :             guard_inst &= 0xFFF0FFFF;  // Rn is at (19:16).
     395            2700 :             guard_inst |= base << 16;
     396           70200 :             for (size_t store = 0;
     397                 :                  store < NACL_ARRAY_SIZE(examples_of_safe_stores);
     398                 :                  store++) {
     399           67500 :               arm_inst store_inst = examples_of_safe_stores[store].inst;
     400           67500 :               ostringstream message;
     401           67500 :               message << guards[guard].about << " with condition "
     402          135000 :                       << Instruction::ToString(guard_cond)
     403                 :                       << (use_same_base ?
     404                 :                           " and same base registers," :
     405          135000 :                           " and different base registers,")
     406           67500 :                       << " followed by "
     407          135000 :                       << examples_of_safe_stores[store].about
     408           67500 :                       << " with condition "
     409          135000 :                       << Instruction::ToString(store_cond);
     410                 :               arm_inst program[] = {
     411           67500 :                 ValidatorTests::ChangeCond(guard_inst, guard_cond),
     412           67500 :                 ValidatorTests::ChangeCond(store_inst, store_cond),
     413          135000 :               };
     414           67500 :               if (allow_cond &&
     415                 :                   use_same_base &&
     416                 :                   (guard_cond == Instruction::AL) &&
     417                 :                   (store_cond == Instruction::EQ)) {
     418                 :                 validation_should_pass2(program,
     419                 :                                         2,
     420                 :                                         kDefaultBaseAddr,
     421              75 :                                         message.str());
     422                 :               } else {
     423                 :                 validation_should_fail(program,
     424                 :                                        2,
     425                 :                                        kDefaultBaseAddr,
     426           67425 :                                        message.str());
     427                 :               }
     428           67500 :             }
     429                 :           }
     430                 :         }
     431                 :       }
     432                 :     }
     433                 :   }
     434               1 : }
     435                 : 
     436                 : static const AnnotatedInstruction examples_of_invalid_masks[] = {
     437                 :   { 0x01A01003, "mov r1, r3: not even a mask" },
     438                 :   { 0x03C31000, "bic r1, r3, #0: doesn't mask anything" },
     439                 :   { 0x03C31102, "bic r1, r3, #0x80000000: doesn't mask enough bits" },
     440                 :   { 0x03C311C1, "bic r1, r3, #0x70000000: masks the wrong bits" },
     441                 : };
     442                 : 
     443               5 : TEST_F(ValidatorTests, InvalidMasksOnSafeStores) {
     444              16 :   for (unsigned p = 0; p < 15; p++) {
     445                 :     // Conditionally executed instructions have a top nibble of 0..14.
     446                 :     // 15 is an escape sequence used to fit in additional encodings.
     447              15 :     arm_inst predicate = p << 28;
     448                 : 
     449              75 :     for (unsigned m = 0; m < NACL_ARRAY_SIZE(examples_of_invalid_masks); m++) {
     450            1560 :       for (unsigned s = 0; s < NACL_ARRAY_SIZE(examples_of_safe_stores); s++) {
     451            1500 :         ostringstream message;
     452            1500 :         message << examples_of_invalid_masks[m].about
     453            1500 :                 << ", "
     454            3000 :                 << examples_of_safe_stores[s].about
     455            1500 :                 << " (predicate #" << p << ")";
     456                 :         arm_inst program[] = {
     457                 :           examples_of_invalid_masks[m].inst | predicate,
     458                 :           examples_of_safe_stores[s].inst | predicate,
     459            1500 :         };
     460                 : 
     461            1500 :         ProblemSpy spy;
     462                 :         validation_should_fail(program,
     463                 :                                NACL_ARRAY_SIZE(program),
     464                 :                                kDefaultBaseAddr,
     465                 :                                message.str(),
     466            1500 :                                &spy);
     467            1500 :         vector<ProblemRecord> problems = spy.get_problems();
     468                 : 
     469                 :         // EXPECT/continue rather than ASSERT so that we run the other cases.
     470            1500 :         EXPECT_EQ(1U, problems.size());
     471            1500 :         if (problems.size() != 1) continue;
     472                 : 
     473            1500 :         ProblemRecord first = problems[0];
     474            1500 :         EXPECT_EQ(kDefaultBaseAddr + 4, first.vaddr())
     475               0 :             << "Problem report must point to the store: "
     476               0 :             << message.str();
     477            1500 :         EXPECT_FALSE(nacl_arm_dec::IsSafetyViolation(first.violation()))
     478               0 :             << "Store should not be unsafe even though the mask is bogys:"
     479               0 :             << message.str();
     480            1500 :         EXPECT_EQ(nacl_arm_dec::LOADSTORE_VIOLATION, first.violation())
     481               0 :             << message.str();
     482            1500 :       }
     483                 :     }
     484                 :   }
     485               1 : }
     486                 : 
     487               5 : TEST_F(ValidatorTests, InvalidGuardsOnSafeStores) {
     488                 :   static const AnnotatedInstruction invalid_guards[] = {
     489                 :     { 0x03110100, "tst r1, #0: always sets Z" },
     490                 :     { 0x03110102, "tst r1, #0x80000000: doesn't test enough bits" },
     491                 :     { 0x031101C1, "tst r1, #0x70000000: doesn't test the right bits" },
     492                 :     { 0x01A01003, "mov r1, r3: not even a test" },
     493                 :     { 0x03310103, "teq r1, #0xC0000000: does the inverse of what we want" },
     494                 :     { 0x03510103, "cmp r1, #0xC0000000: does the inverse of what we want" },
     495                 :   };
     496                 : 
     497                 :   // We don't currently support conditional versions of the conditional guard.
     498                 :   //
     499                 :   // TODO(cbiffle): verify this in the test
     500                 :   static const arm_inst guard_predicate = 0xE0000000;  // unconditional
     501                 :   static const arm_inst store_predicate = 0x00000000;  // if-equal
     502                 : 
     503               7 :   for (unsigned m = 0; m < NACL_ARRAY_SIZE(invalid_guards); m++) {
     504             156 :     for (unsigned s = 0; s < NACL_ARRAY_SIZE(examples_of_safe_stores); s++) {
     505             150 :       ostringstream message;
     506             150 :       message << invalid_guards[m].about
     507             150 :               << ", "
     508             300 :               << examples_of_safe_stores[s].about;
     509                 :       arm_inst program[] = {
     510                 :         invalid_guards[m].inst | guard_predicate,
     511                 :         examples_of_safe_stores[s].inst | store_predicate,
     512             150 :       };
     513                 : 
     514             150 :       ProblemSpy spy;
     515                 :       validation_should_fail(program,
     516                 :                              NACL_ARRAY_SIZE(program),
     517                 :                              kDefaultBaseAddr,
     518                 :                              message.str(),
     519             150 :                              &spy);
     520             150 :       vector<ProblemRecord> problems = spy.get_problems();
     521                 : 
     522                 :       // EXPECT/continue rather than ASSERT so that we run the other cases.
     523             150 :       EXPECT_EQ(1U, problems.size());
     524             150 :       if (problems.size() != 1) continue;
     525                 : 
     526             150 :       ProblemRecord first = problems[0];
     527             150 :       EXPECT_EQ(kDefaultBaseAddr + 4, first.vaddr())
     528               0 :           << "Problem report must point to the store: "
     529               0 :           << message.str();
     530             150 :       EXPECT_FALSE(nacl_arm_dec::IsSafetyViolation(first.violation()))
     531               0 :           << "Store should not be unsafe even though guard is bogus:"
     532             150 :           << message;
     533             150 :       EXPECT_EQ(nacl_arm_dec::LOADSTORE_VIOLATION, first.violation())
     534               0 :           << message;
     535             150 :     }
     536                 :   }
     537               1 : }
     538                 : 
     539               5 : TEST_F(ValidatorTests, ValidMasksOnUnsafeStores) {
     540                 :   static const AnnotatedInstruction invalid_stores[] = {
     541                 :     { 0x07810002, "str r0, [r1, r2]: register-plus-register addressing" },
     542                 :     { 0x07010002, "str r0, [r1, -r2]: register-minus-register addressing" },
     543                 :     { 0x07810182, "str r0, [r1, r2, LSL #3]: complicated addressing 1" },
     544                 :     { 0x07018482, "str r0, [r1, -r2, ASR #16]: complicated addressing 2" },
     545                 :   };
     546                 : 
     547              16 :   for (unsigned p = 0; p < 15; p++) {
     548                 :     // Conditionally executed instructions have a top nibble of 0..14.
     549                 :     // 15 is an escape sequence used to fit in additional encodings.
     550              15 :     arm_inst predicate = p << 28;
     551                 : 
     552              75 :     for (unsigned m = 0; m < NACL_ARRAY_SIZE(examples_of_safe_masks); m++) {
     553             300 :       for (unsigned s = 0; s < NACL_ARRAY_SIZE(invalid_stores); s++) {
     554             240 :         ostringstream message;
     555             240 :         message << examples_of_safe_masks[m].about
     556             240 :                 << ", "
     557             480 :                 << invalid_stores[s].about
     558             240 :                 << " (predicate #" << p << ")";
     559                 :         arm_inst program[] = {
     560                 :           examples_of_safe_masks[m].inst | predicate,
     561                 :           invalid_stores[s].inst | predicate,
     562             240 :         };
     563                 : 
     564             240 :         ProblemSpy spy;
     565                 :         validation_should_fail(program,
     566                 :                                NACL_ARRAY_SIZE(program),
     567                 :                                kDefaultBaseAddr,
     568                 :                                message.str(),
     569             240 :                                &spy);
     570             240 :         vector<ProblemRecord> problems = spy.get_problems();
     571                 : 
     572                 :         // EXPECT/continue rather than ASSERT so that we run the other cases.
     573             240 :         EXPECT_EQ(1U, problems.size());
     574             240 :         if (problems.size() != 1) continue;
     575                 : 
     576             240 :         ProblemRecord first = problems[0];
     577             240 :         EXPECT_EQ(kDefaultBaseAddr + 4, first.vaddr())
     578               0 :             << "Problem report must point to the store: "
     579               0 :             << message.str();
     580             240 :         EXPECT_TRUE(nacl_arm_dec::IsSafetyViolation(first.violation()));
     581             240 :       }
     582                 :     }
     583                 :   }
     584               1 : }
     585                 : 
     586               5 : TEST_F(ValidatorTests, ScaryUndefinedInstructions) {
     587                 :   // These instructions are undefined today (ARMv7-A) but may become defined
     588                 :   // tomorrow.  We ban them since we can't reason about their side effects.
     589                 :   static const AnnotatedInstruction undefined_insts[] = {
     590                 :     { 0xE05DEA9D, "An undefined instruction in the multiply space" },
     591                 :   };
     592               2 :   for (unsigned i = 0; i < NACL_ARRAY_SIZE(undefined_insts); i++) {
     593               1 :     arm_inst program[] = { undefined_insts[i].inst };
     594                 : 
     595               1 :     ProblemSpy spy;
     596                 :     validation_should_fail(program,
     597                 :                            NACL_ARRAY_SIZE(program),
     598                 :                            kDefaultBaseAddr,
     599                 :                            undefined_insts[i].about,
     600               1 :                            &spy);
     601               1 :     vector<ProblemRecord> problems = spy.get_problems();
     602                 : 
     603                 :     // EXPECT/continue rather than ASSERT so that we run the other cases.
     604               1 :     EXPECT_EQ(1U, problems.size());
     605               1 :     if (problems.size() != 1) continue;
     606                 : 
     607               1 :     ProblemRecord first = problems[0];
     608               1 :     EXPECT_EQ(kDefaultBaseAddr, first.vaddr())
     609               0 :         << "Problem report must point to the only instruction: "
     610               1 :         << undefined_insts[i].about;
     611               1 :     EXPECT_TRUE(nacl_arm_dec::IsSafetyViolation(first.violation()))
     612               0 :         << "Instruction must be flagged by the decoder as unsafe:"
     613               1 :         << undefined_insts[i].about;
     614               1 :     EXPECT_EQ(nacl_arm_dec::UNDEFINED_VIOLATION, first.violation())
     615               0 :         << "Instruction must be flagged as UNDEFINED:"
     616               1 :         << undefined_insts[i].about;
     617               1 :   }
     618               1 : }
     619                 : 
     620               5 : TEST_F(ValidatorTests, PcRelativeFirstInst) {
     621                 :   // Note: This tests the fix for issue 2771.
     622                 :   static const arm_inst pcrel_boundary_tests[] = {
     623                 :     0xe59f0000,  // ldr     r0, [pc, #0]
     624                 :     kNop,
     625                 :     kNop,
     626                 :     kNop,
     627                 :   };
     628                 :   validation_should_pass(pcrel_boundary_tests,
     629                 :                          NACL_ARRAY_SIZE(pcrel_boundary_tests),
     630                 :                          kDefaultBaseAddr,
     631               1 :                          "pc relative first instruction in first bundle");
     632               1 : }
     633                 : 
     634               5 : TEST_F(ValidatorTests, PcRelativeFirst2ndBundle) {
     635                 :   // Note: This tests the fix for issue 2771.
     636                 :   static const arm_inst pcrel_boundary_tests[] = {
     637                 :     kNop,
     638                 :     kNop,
     639                 :     kNop,
     640                 :     kNop,
     641                 :     0xe59f0000,  // ldr     r0, [pc, #0]
     642                 :   };
     643                 :   validation_should_pass(pcrel_boundary_tests,
     644                 :                          NACL_ARRAY_SIZE(pcrel_boundary_tests),
     645                 :                          kDefaultBaseAddr,
     646               1 :                          "pc relative first instruction in 2nd bundle");
     647               1 : }
     648                 : 
     649               5 : TEST_F(ValidatorTests, SafeConditionalBicLdrTest) {
     650                 :   // Test if we fixed bug with conditional Bic Loads (issue 2769).
     651                 :   static const arm_inst bic_ldr_safe_test[] = {
     652                 :     0x03c22103,  // biceq   r2, r2, #-1073741824    ; 0xc0000000
     653                 :     0x01920f9f,  // ldrexeq r0, [r2]
     654                 :   };
     655                 :   validation_should_pass(bic_ldr_safe_test,
     656                 :                          NACL_ARRAY_SIZE(bic_ldr_safe_test),
     657                 :                          kDefaultBaseAddr,
     658               1 :                          "Safe conditional bic ldr test");
     659               1 : }
     660                 : 
     661               5 : TEST_F(ValidatorTests, ConditionalBicsLdrTest) {
     662                 :   // Test if we fail because Bic updates the flags register, making
     663                 :   // the conditional Bic load incorrect (issue 2769).
     664                 :   static const arm_inst bics_ldr_unsafe_test[] = {
     665                 :     0x03d22103,  // bicseq  r2, r2, #-1073741824    ; 0xc0000000
     666                 :     0x01920f9f,  // ldrexeq r0, [r2]
     667                 :   };
     668                 : 
     669               1 :   ProblemSpy spy;
     670                 :   validation_should_fail(bics_ldr_unsafe_test,
     671                 :                          NACL_ARRAY_SIZE(bics_ldr_unsafe_test),
     672                 :                          kDefaultBaseAddr,
     673                 :                          "Conditional bics ldr test",
     674               1 :                          &spy);
     675               1 :   vector<ProblemRecord> problems = spy.get_problems();
     676                 : 
     677               1 :   EXPECT_EQ(1U, problems.size());
     678               2 :   if (problems.size() == 0) return;
     679                 : 
     680               1 :   ProblemRecord problem = problems[0];
     681               1 :   EXPECT_EQ(kDefaultBaseAddr + 4, problem.vaddr())
     682               0 :       << "Problem report should point to the ldr instruction.";
     683               1 :   EXPECT_FALSE(nacl_arm_dec::IsSafetyViolation(problem.violation()));
     684               1 :   EXPECT_EQ(nacl_arm_dec::LOADSTORE_VIOLATION, problem.violation());
     685                 : }
     686                 : 
     687               5 : TEST_F(ValidatorTests, DifferentConditionsBicLdrTest) {
     688                 :   // Test if we fail because the Bic and Ldr instructions have
     689                 :   // different conditional flags.
     690                 :   static const arm_inst bic_ldr_diff_conds[] = {
     691                 :     0x03c22103,  // biceq   r2, r2, #-1073741824    ; 0xc0000000
     692                 :     0xc1920f9f,  // ldrexgt r0, [r2]
     693                 :   };
     694                 : 
     695               1 :   ProblemSpy spy;
     696                 :   validation_should_fail(bic_ldr_diff_conds,
     697                 :                          NACL_ARRAY_SIZE(bic_ldr_diff_conds),
     698                 :                          kDefaultBaseAddr,
     699                 :                          "Different conditions bic ldr test",
     700               1 :                          &spy);
     701               1 :   vector<ProblemRecord> problems = spy.get_problems();
     702                 : 
     703               1 :   EXPECT_EQ(1U, problems.size());
     704               2 :   if (problems.size() == 0) return;
     705                 : 
     706               1 :   ProblemRecord problem = problems[0];
     707               1 :   EXPECT_EQ(kDefaultBaseAddr + 4, problem.vaddr())
     708               0 :       << "Problem report should point to the ldr instruction.";
     709               1 :   EXPECT_FALSE(nacl_arm_dec::IsSafetyViolation(problem.violation()));
     710               1 :   EXPECT_EQ(nacl_arm_dec::LOADSTORE_VIOLATION, problem.violation());
     711                 : }
     712                 : 
     713               5 : TEST_F(ValidatorTests, BfcLdrInst) {
     714                 :   static const arm_inst bfc_inst[] = {
     715                 :     0xe7df2f1f,  // bfc r2, #30, #2
     716                 :     0xe1920f9f,  // ldrex r0, [r2]
     717                 :   };
     718                 :   validation_should_fail(bfc_inst,
     719                 :                          NACL_ARRAY_SIZE(bfc_inst),
     720                 :                          kDefaultBaseAddr,
     721                 :                          "Bfc Ldr instruction mask has a mask that's "
     722                 :                          "technically safe, but we disallow it out of "
     723               1 :                          "paranoia");
     724               1 : }
     725                 : 
     726               5 : TEST_F(ValidatorTests, BfcLdrInstMaskTooBigTest) {
     727                 :   static const arm_inst bfc_inst[] = {
     728                 :     0xe7df2e9f,  // bfc r2, #29, #3
     729                 :     0xe1920f9f,  // ldrex r0, [r2]
     730                 :   };
     731                 :   validation_should_fail(bfc_inst,
     732                 :                          NACL_ARRAY_SIZE(bfc_inst),
     733                 :                          kDefaultBaseAddr,
     734                 :                          "Bfc Ldr instruction mask has a mask that's "
     735                 :                          "technically safe (even too wide!), but we "
     736               1 :                          "disallow it out of paranoia");
     737               1 : }
     738                 : 
     739               5 : TEST_F(ValidatorTests, BfcLdrInstMaskWrongPlaceTest) {
     740                 :   static const arm_inst bfc_inst[] = {
     741                 :     0xe7da2c9f,  // bfc r2, #25, #2
     742                 :     0xe1920f9f,  // ldrex r0, [r2]
     743                 :   };
     744                 :   validation_should_fail(bfc_inst,
     745                 :                          NACL_ARRAY_SIZE(bfc_inst),
     746                 :                          kDefaultBaseAddr,
     747                 :                          "Bfc Ldr instruction mask has a mask that's "
     748                 :                          "not safe, and anyways we disallow it out of "
     749               1 :                          "paranoia");
     750               1 : }
     751                 : 
     752                 : // Test effects of virtual dynamic_code_replacement_sentinel on the movw
     753                 : // instruction.
     754               5 : TEST_F(ValidatorTests, DynamicCodeReplacementSentinelMovw) {
     755                 :   // Test cases where the sentinel changes for movw.
     756                 :   const AnnotatedInstruction inst[] = {
     757                 :     {0xe30a3aaa, "movw    r3, #43690      ; 0xaaaa"},
     758                 :     {0xe3053555, "movw    r3, #21845      ; 0x5555"},
     759               1 :   };
     760                 : 
     761                 :   // Test cases where the sentinel doesn't change for movw.
     762                 :   test_if_dynamic_code_replacement_sentinels_match(
     763                 :       static_cast<const ValidatorTests*>(this),
     764               1 :       inst, NACL_ARRAY_SIZE(inst), 0xe3003000);
     765                 :   const AnnotatedInstruction unchanged[] = {
     766                 :     // If already the sentinel, nothing changes.
     767                 :     {0xe3003000, "movw    r3, #0          ; 0x0000"},
     768                 :     // Note: These instructions may not validate for other reasons,
     769                 :     // but we are only testing the virtual
     770                 :     // dynamic_code_replacement_sentinel, and that it doesn't
     771                 :     // apply changes when the register is in {r9, sp, lr, pc}.
     772                 :     {0xe3059555, "movw    r9, #21845      ; 0x5555"},
     773                 :     {0xe305d555, "movw    sp, #21845      ; 0x5555"},
     774                 :     {0xe305e555, "movw    lr, #21845      ; 0x5555"},
     775                 :     {0xe305f555, "movw    pc, #21845      ; 0x5555"},
     776               1 :   };
     777                 :   test_if_dynamic_code_replacement_sentinels_unchanged(
     778                 :       static_cast<const ValidatorTests*>(this),
     779               1 :       unchanged, NACL_ARRAY_SIZE(unchanged));
     780               1 : }
     781                 : 
     782                 : // Test effects of virtual dynamic_code_replacement_sentinel on the movt
     783                 : // instruction.
     784               5 : TEST_F(ValidatorTests, DynamicCodeReplacementSentinelMovt) {
     785                 :   // Test cases where the sentinel changes for movt.
     786                 :   const AnnotatedInstruction inst[] = {
     787                 :     {0xe34a5aaa, "movt    r5, #43690      ; 0xaaaa"},
     788                 :     {0xe3455555, "movt    r5, #21845      ; 0x5555"},
     789               1 :   };
     790                 :   test_if_dynamic_code_replacement_sentinels_match(
     791                 :       static_cast<const ValidatorTests*>(this),
     792               1 :       inst, NACL_ARRAY_SIZE(inst), 0xe3405000);
     793                 : 
     794                 :   // Test cases where the sentinel doesn't change for movt.
     795                 :   const AnnotatedInstruction unchanged[] = {
     796                 :     // If already the sentinel, nothing changes.
     797                 :     {0xe3405000, "movt    r5, #0          ; 0x0000"},
     798                 :     // Note: These instructions may not validate for other reasons,
     799                 :     // but we are only testing the virtual
     800                 :     // dynamic_code_replacement_sentinel, and that it doesn't
     801                 :     // apply changes when the register is in {r9, sp, lr, pc}.
     802                 :     {0xe3459555, "movt    r9, #21845      ; 0x5555"},
     803                 :     {0xe345d555, "movt    sp, #21845      ; 0x5555"},
     804                 :     {0xe345e555, "movt    lr, #21845      ; 0x5555"},
     805                 :     {0xe345f555, "movt    pc, #21845      ; 0x5555"},
     806               1 :   };
     807                 :   test_if_dynamic_code_replacement_sentinels_unchanged(
     808                 :       static_cast<const ValidatorTests*>(this),
     809               1 :       unchanged, NACL_ARRAY_SIZE(unchanged));
     810               1 : }
     811                 : 
     812                 : // Test effects of virtual dynamic_code_replacement_sentinel on the orr
     813                 : // instruction.
     814               5 : TEST_F(ValidatorTests, DynamicCodeReplacementSentinelOrr) {
     815                 :   // Test cases where the sentinel changes for orr.
     816                 :   const AnnotatedInstruction orr[] = {
     817                 :     {0xe38454aa, "orr     r5, r4, #-1442840576    ; 0xaa000000"},
     818                 :     {0xe38458aa, "orr     r5, r4, #11141120       ; 0xaa0000"},
     819                 :     {0xe3845caa, "orr     r5, r4, #43520  ; 0xaa00"},
     820                 :     {0xe38450aa, "orr     r5, r4, #170    ; 0xaa"},
     821                 :     {0xe3845455, "orr     r5, r4, #1426063360     ; 0x55000000"},
     822                 :     {0xe3845855, "orr     r5, r4, #5570560        ; 0x550000"},
     823                 :     {0xe3845c55, "orr     r5, r4, #21760  ; 0x5500"},
     824                 :     {0xe3845055, "orr     r5, r4, #85     ; 0x55"},
     825               1 :   };
     826                 :   test_if_dynamic_code_replacement_sentinels_match(
     827                 :       static_cast<const ValidatorTests*>(this),
     828               1 :       orr, NACL_ARRAY_SIZE(orr), 0xe3845000);
     829                 :   const AnnotatedInstruction orrs[] = {
     830                 :     {0xe39454aa, "orrs    r5, r4, #-1442840576    ; 0xaa000000"},
     831                 :     {0xe39458aa, "orrs    r5, r4, #11141120       ; 0xaa0000"},
     832                 :     {0xe3945caa, "orrs    r5, r4, #43520  ; 0xaa00"},
     833                 :     {0xe39450aa, "orrs    r5, r4, #170    ; 0xaa"},
     834                 :     {0xe3945455, "orrs    r5, r4, #1426063360     ; 0x55000000"},
     835                 :     {0xe3945855, "orrs    r5, r4, #5570560        ; 0x550000"},
     836                 :     {0xe3945c55, "orrs    r5, r4, #21760  ; 0x5500"},
     837                 :     {0xe3945055, "orrs    r5, r4, #85     ; 0x55"},
     838               1 :   };
     839                 :   test_if_dynamic_code_replacement_sentinels_match(
     840                 :       static_cast<const ValidatorTests*>(this),
     841               1 :       orrs, NACL_ARRAY_SIZE(orrs), 0xe3945000);
     842                 : 
     843                 :   // Test cases where the sentinel doesn't change for orr.
     844                 :   const AnnotatedInstruction unchanged[] = {
     845                 :     // Note: These instructions may not validate for other reasons,
     846                 :     // but we are only testing the virtual
     847                 :     // dynamic_code_replacement_sentinel, and that it doesn't
     848                 :     // apply changes when the register is in {r9, sp, lr, pc}.
     849                 :     {0xe3849055, "orr     r9, r4, #85     ; 0x55"},
     850                 :     {0xe384d055, "orr     sp, r4, #85     ; 0x55"},
     851                 :     {0xe384e055, "orr     lr, r4, #85     ; 0x55"},
     852                 :     {0xe384f055, "orr     pc, r4, #85     ; 0x55"},
     853                 :     {0xe3949055, "orrs    r9, r4, #85     ; 0x55"},
     854                 :     {0xe394d055, "orrs    sp, r4, #85     ; 0x55"},
     855                 :     {0xe394e055, "orrs    lr, r4, #85     ; 0x55"},
     856                 :     {0xe394f055, "orrs    pc, r4, #85     ; 0x55"},
     857               1 :   };
     858                 :   test_if_dynamic_code_replacement_sentinels_unchanged(
     859                 :       static_cast<const ValidatorTests*>(this),
     860               1 :       unchanged, NACL_ARRAY_SIZE(unchanged));
     861               1 : }
     862                 : 
     863                 : // Test effects of virtual dynamic_code_replacement_sentinel on the mvn
     864                 : // instruction.
     865               5 : TEST_F(ValidatorTests, DynamicCodeReplacementSentinelMvn) {
     866                 :   // Test cases where the sentinel changes for mvn.
     867                 :   const AnnotatedInstruction mvn[] = {
     868                 :     {0xe3e064aa, "mvn     r6, #-1442840576        ; 0xaa000000"},
     869                 :     {0xe3e068aa, "mvn     r6, #11141120   ; 0xaa0000"},
     870                 :     {0xe3e06caa, "mvn     r6, #43520      ; 0xaa00"},
     871                 :     {0xe3e060aa, "mvn     r6, #170        ; 0xaa"},
     872                 :     {0xe3e06455, "mvn     r6, #1426063360 ; 0x55000000"},
     873                 :     {0xe3e06855, "mvn     r6, #5570560    ; 0x550000"},
     874                 :     {0xe3e06c55, "mvn     r6, #21760      ; 0x5500"},
     875                 :     {0xe3e06055, "mvn     r6, #85 ; 0x55"},
     876               1 :   };
     877                 :   test_if_dynamic_code_replacement_sentinels_match(
     878                 :       static_cast<const ValidatorTests*>(this),
     879               1 :       mvn, NACL_ARRAY_SIZE(mvn), 0xe3e06000);
     880                 :   const AnnotatedInstruction mvns[] = {
     881                 :     {0xe3f064aa, "mvns    r6, #-1442840576        ; 0xaa000000"},
     882                 :     {0xe3f068aa, "mvns    r6, #11141120   ; 0xaa0000"},
     883                 :     {0xe3f06caa, "mvns    r6, #43520      ; 0xaa00"},
     884                 :     {0xe3f060aa, "mvns    r6, #170        ; 0xaa"},
     885                 :     {0xe3f06455, "mvns    r6, #1426063360 ; 0x55000000"},
     886                 :     {0xe3f06855, "mvns    r6, #5570560    ; 0x550000"},
     887                 :     {0xe3f06c55, "mvns    r6, #21760      ; 0x5500"},
     888                 :     {0xe3f06055, "mvns    r6, #85 ; 0x55"},
     889               1 :   };
     890                 :   test_if_dynamic_code_replacement_sentinels_match(
     891                 :       static_cast<const ValidatorTests*>(this),
     892               1 :       mvns, NACL_ARRAY_SIZE(mvns), 0xe3f06000);
     893                 : 
     894                 :   // Test cases where the sentinel doesn't change for orr.
     895                 :   const AnnotatedInstruction unchanged[] = {
     896                 :     // Note: These instructions may not validate for other reasons,
     897                 :     // but we are only testing the virtual
     898                 :     // dynamic_code_replacement_sentinel, and that it doesn't
     899                 :     // apply changes when the register is in {r9, sp, lr, pc}.
     900                 :     {0xe3e09055, "mvn     r9, #85 ; 0x55"},
     901                 :     {0xe3e0d055, "mvn     sp, #85 ; 0x55"},
     902                 :     {0xe3e0e055, "mvn     lr, #85 ; 0x55"},
     903                 :     {0xe3e0f055, "mvn     pc, #85 ; 0x55"},
     904                 :     {0xe3f09055, "mvns    r9, #85 ; 0x55"},
     905                 :     {0xe3f0d055, "mvns    sp, #85 ; 0x55"},
     906                 :     {0xe3f0e055, "mvns    lr, #85 ; 0x55"},
     907                 :     {0xe3f0f055, "mvns    pc, #85 ; 0x55"},
     908               1 :   };
     909                 :   test_if_dynamic_code_replacement_sentinels_unchanged(
     910                 :       static_cast<const ValidatorTests*>(this),
     911               1 :       unchanged, NACL_ARRAY_SIZE(unchanged));
     912               1 : }
     913                 : 
     914                 : // Test other instructions for which dynamic code replacement can't be applied.
     915               5 : TEST_F(ValidatorTests, DynamicCodeReplacementSentinelOther) {
     916                 :   test_if_dynamic_code_replacement_sentinels_unchanged(
     917                 :       static_cast<const ValidatorTests*>(this),
     918               1 :       examples_of_safe_stores, NACL_ARRAY_SIZE(examples_of_safe_stores));
     919                 :   test_if_dynamic_code_replacement_sentinels_unchanged(
     920                 :       static_cast<const ValidatorTests*>(this),
     921               1 :       examples_of_safe_masks, NACL_ARRAY_SIZE(examples_of_safe_masks));
     922               1 : }
     923                 : 
     924               5 : TEST_F(ValidatorTests, DynamicCodeReplacementLiteralPool) {
     925                 :   // Start with an evil-looking value, and replace with another evil-looking
     926                 :   // value. It should work because these are all data in two consecutive
     927                 :   // literal pools, not actual instructions.
     928               1 :   vector<arm_inst>::size_type bundle_size(_validator->InstructionsPerBundle());
     929               1 :   vector<arm_inst>::size_type size(bundle_size * 2);
     930               1 :   vector<arm_inst> old_code(size, kSvc0);
     931               1 :   vector<arm_inst> new_code(size, kFailValidation);
     932               1 :   old_code[0] = new_code[0] =
     933               1 :       old_code[bundle_size] = new_code[bundle_size] =
     934               1 :       kLiteralPoolHead;
     935                 :   TestDynamicCodeReplacement(
     936                 :       _validator, true, old_code, new_code,
     937               1 :       "literal pool data change");
     938                 : 
     939                 :   // Change the new code so that its first bundle is still a literal
     940                 :   // pool but its second isn't. This should now fail validation because
     941                 :   // the data is now executable code.
     942               1 :   new_code[bundle_size] = kNop;
     943                 :   TestDynamicCodeReplacement(
     944                 :       _validator, false, old_code, new_code,
     945               1 :       "literal pool becoming non-literal pool");
     946                 : 
     947                 :   // Change the old code so that its second bundle also isn't a literal
     948                 :   // pool. This should also fail, not because the code is dangerous
     949                 :   // (which it is, but that's checked separately), but because the old
     950                 :   // instructions can't be substituted for the new.
     951               1 :   old_code[bundle_size] = kNop;
     952                 :   TestDynamicCodeReplacement(
     953                 :       _validator, false, old_code, new_code,
     954               1 :       "literal pool followed by non-literal pool with invalid replacement");
     955                 : 
     956                 :   // Change the new code's second bundle to a literal pool, which it
     957                 :   // wasn't in the old. This should also fail because we don't allow the
     958                 :   // user to dynamically create literal pools where none existed before.
     959               1 :   new_code[bundle_size] = kLiteralPoolHead;
     960                 :   TestDynamicCodeReplacement(
     961                 :       _validator, false, old_code, new_code,
     962               1 :       "non-literal pool becoming literal pool");
     963               1 : }
     964                 : 
     965                 : struct AlwaysDominatesTestInfo {
     966                 :   arm_inst inst[2];
     967                 :   const char* name[2];
     968                 :   bool first_inst_can_set_flags;
     969                 : };
     970               5 : TEST_F(ValidatorTests, AlwaysDominatesTest) {
     971                 :   // Test always_dominates, with all conditional combinations of:
     972                 :   AlwaysDominatesTestInfo test[] = {
     973                 :     { {
     974                 :         // BIC (potentially setting flags) followed by a branch.
     975                 :         0xe3cee2fe,  // bic[s]CC lr, lr, #-536870897     ; 0xe000000f
     976                 :         0xe12fff1e,  // bxCC lr
     977                 :       }, { "bic", "bx" }, true },
     978               1 :   };
     979                 : 
     980               2 :   for (AlwaysDominatesTestInfo* t = &test[0];
     981                 :        t != &test[NACL_ARRAY_SIZE(test)];
     982                 :        ++t) {
     983               3 :     for (int s = 0; s < (t->first_inst_can_set_flags ? 2 : 1); ++s) {
     984               2 :       if (t->first_inst_can_set_flags) {
     985               2 :         t->inst[0] = SetSBit(t->inst[0], s);
     986                 :       }
     987                 : 
     988                 :       Instruction::Condition cond[2];
     989              64 :       for (cond[0] = Instruction::EQ;
     990              32 :            cond[0] <= Instruction::AL;
     991              30 :            cond[0] = Instruction::Next(cond[0])) {
     992             960 :         for (cond[1] = Instruction::EQ;
     993             480 :              cond[1] <= Instruction::AL;
     994             450 :              cond[1] = Instruction::Next(cond[1])) {
     995             450 :           t->inst[0] = ChangeCond(t->inst[0], cond[0]);
     996             450 :           t->inst[1] = ChangeCond(t->inst[1], cond[1]);
     997                 : 
     998                 :           std::string name0(std::string(t->name[0]) + (s ? "s" : "") +
     999             450 :                             Instruction::ToString(cond[0]));
    1000                 :           std::string name1(std::string(t->name[1]) +
    1001             450 :                             Instruction::ToString(cond[1]));
    1002             450 :           ostringstream message;
    1003             450 :           message << name0 <<
    1004             900 :               " (0x" << std::hex << std::setfill('0') << std::setw(8) <<
    1005             900 :               static_cast<uint32_t>(t->inst[0]) <<
    1006             900 :               std::resetiosflags(std::ios_base::showbase) << ") "
    1007             450 :               "with a correct mask, followed by " << name1 <<
    1008             900 :               " (0x" << std::hex << std::setfill('0') << std::setw(8) <<
    1009             900 :               static_cast<uint32_t>(t->inst[1]) <<
    1010             900 :               std::resetiosflags(std::ios_base::showbase) << "): ";
    1011                 : 
    1012             450 :           if (s) {
    1013                 :             validation_should_fail(t->inst, NACL_ARRAY_SIZE(t->inst),
    1014                 :                                    kDefaultBaseAddr,
    1015                 :                                    message.str() + name0 + " sets flags "
    1016                 :                                    "when it's only supposed to enforce SFI on "
    1017                 :                                    "the subsequent " + name1 + ", we "
    1018                 :                                    "could allow this but it makes the "
    1019                 :                                    "validator's code more complex and it's "
    1020                 :                                    "harder to reason about back-to-back "
    1021                 :                                    "conditional instructions with "
    1022                 :                                    "intervening flag setting (especially with "
    1023             225 :                                    "ARM's partial NZCV flag setting).");
    1024             225 :           } else if (cond[0] == Instruction::AL) {
    1025                 :             validation_should_pass(t->inst, NACL_ARRAY_SIZE(t->inst),
    1026                 :                                    kDefaultBaseAddr,
    1027                 :                                    message.str() + "an unconditional " +
    1028                 :                                    name0 + " always dominates the "
    1029                 :                                    "subsequent " + name1 +
    1030              15 :                                    " instruction.");
    1031             210 :           } else if (cond[1] == Instruction::AL) {
    1032              14 :             EXPECT_NE(cond[0], Instruction::AL);
    1033                 :             validation_should_fail(t->inst, NACL_ARRAY_SIZE(t->inst),
    1034                 :                                    kDefaultBaseAddr,
    1035                 :                                    message.str() + name0 + " is "
    1036                 :                                    "conditional, but the subsequent " +
    1037              14 :                                    name1 + " isn't.");
    1038             196 :           } else if ((cond[1] == cond[0]) ||
    1039                 :                      // TODO(jfb) Put back mixed-condition handling.
    1040                 :                      //           See issue #3221.
    1041                 :                      /*
    1042                 :                    (cond[1] == Instruction::EQ && cond[0] == Instruction::LS) ||
    1043                 :                    (cond[1] == Instruction::CC && cond[0] == Instruction::LS) ||
    1044                 :                    (cond[1] == Instruction::HI && cond[0] == Instruction::NE) ||
    1045                 :                    (cond[1] == Instruction::HI && cond[0] == Instruction::CS) ||
    1046                 :                    (cond[1] == Instruction::GT && cond[0] == Instruction::NE) ||
    1047                 :                    (cond[1] == Instruction::GT && cond[0] == Instruction::GE) ||
    1048                 :                    (cond[1] == Instruction::LE && cond[0] == Instruction::EQ) ||
    1049                 :                    (cond[1] == Instruction::LE && cond[0] == Instruction::LS) ||
    1050                 :                    (cond[1] == Instruction::LE && cond[0] == Instruction::LT) */
    1051                 :                      false) {
    1052                 :             validation_should_pass(t->inst, NACL_ARRAY_SIZE(t->inst),
    1053                 :                                    kDefaultBaseAddr,
    1054                 :                                    message.str() + name1 + "'s "
    1055                 :                                    "condition being true necessarily implies "
    1056                 :                                    "that " + name0 + "'s condition was "
    1057              14 :                                    "also true.");
    1058                 :           } else {
    1059                 :             validation_should_fail(t->inst, NACL_ARRAY_SIZE(t->inst),
    1060                 :                                    kDefaultBaseAddr,
    1061                 :                                    message.str() + name1 + "'s condition "
    1062                 :                                    "being true doesn't necessarily imply "
    1063                 :                                    "that " + name0 + "'s condition was "
    1064                 :                                    "also true, err on the side of caution and "
    1065             182 :                                    "disallow.");
    1066                 :           }
    1067             450 :         }
    1068                 :       }
    1069                 :     }
    1070                 :   }
    1071               1 : }
    1072                 : 
    1073               5 : TEST_F(ValidatorTests, UnmaskedSpUpdate) {
    1074               1 :   vector<arm_inst> code(_validator->InstructionsPerBundle(), kNop);
    1075               5 :   for (vector<arm_inst>::size_type i = 0; i < code.size(); ++i) {
    1076               4 :     std::fill(code.begin(), code.end(), kNop);
    1077               4 :     code[i] = 0xE1A0D000;  // MOV SP, R0
    1078               4 :     validation_should_fail(&code[0], code.size(), kDefaultBaseAddr,
    1079               8 :                            "unmasked SP update");
    1080               1 :   }
    1081               1 : }
    1082                 : 
    1083               5 : TEST_F(ValidatorTests, MaskedSpUpdate) {
    1084               1 :   vector<arm_inst> code(_validator->InstructionsPerBundle() * 2, kNop);
    1085               8 :   for (vector<arm_inst>::size_type i = 0; i < code.size() - 1; ++i) {
    1086               7 :     std::fill(code.begin(), code.end(), kNop);
    1087               7 :     code[i] = 0xE1A0D000;      // MOV SP, R0
    1088               7 :     code[i + 1] = 0xE3CDD2FF;  // BIC SP, SP, #-268435441 ; 0xf000000f
    1089               7 :     if (i == _validator->InstructionsPerBundle() - 1) {
    1090               1 :       validation_should_fail(&code[0], code.size(), kDefaultBaseAddr,
    1091                 :                              "masked SP update straddling a bundle boundary"
    1092                 :                              " (this is technically safe, but we simplify the "
    1093                 :                              "validator by disallowing instruction pairs that "
    1094               2 :                              "straddle a bundle boundary)");
    1095                 :     } else {
    1096               6 :       validation_should_pass(&code[0], code.size(), kDefaultBaseAddr,
    1097              12 :                              "masked SP update");
    1098                 :     }
    1099               1 :   }
    1100               1 : }
    1101                 : 
    1102               5 : TEST_F(ValidatorTests, AddConstToSpTest) {
    1103                 :   // Show that we can add a constant to the stack pointer is fine,
    1104                 :   // so long as we follow it with a mask instruction.
    1105                 :   static const arm_inst sp_inst[] = {
    1106                 :     0xe28dd00c,  // add sp, sp, #12
    1107                 :     0xe3cdd2ff,  // bic     sp, sp, #-268435441     ; 0xf000000f
    1108                 :   };
    1109                 :   validation_should_pass(sp_inst,
    1110                 :                          NACL_ARRAY_SIZE(sp_inst),
    1111                 :                          kDefaultBaseAddr,
    1112               1 :                          "Add constant (12) to sp, then mask with bic");
    1113               1 : }
    1114                 : 
    1115               5 : TEST_F(ValidatorTests, BicSpFirstInstTest) {
    1116                 :   // Show that if we bit clear SP as the first instruction, it is ok.
    1117                 :   static const arm_inst bic_inst[] = {
    1118                 :     0xe3cdd2ff,  // bic     sp, sp, #-268435441     ; 0xf000000f
    1119                 :   };
    1120                 :   validation_should_pass(bic_inst,
    1121                 :                          NACL_ARRAY_SIZE(bic_inst),
    1122                 :                          kDefaultBaseAddr,
    1123               1 :                          "Bit clear sp as first instruction.");
    1124               1 : }
    1125                 : 
    1126               5 : TEST_F(ValidatorTests, BicSpSecondInstTest) {
    1127                 :   // Show that if we bit clear SP as the second instruction, and
    1128                 :   // the first doesn't update SP, we are ok.
    1129                 :   static const arm_inst bic_inst[] = {
    1130                 :     kNop,
    1131                 :     0xe3cdd2ff,  // bic     sp, sp, #-268435441     ; 0xf000000f
    1132                 :   };
    1133                 :   validation_should_pass(bic_inst,
    1134                 :                          NACL_ARRAY_SIZE(bic_inst),
    1135                 :                          kDefaultBaseAddr,
    1136               1 :                          "Bit clear sp as second instruction.");
    1137               1 : }
    1138                 : 
    1139               5 : TEST_F(ValidatorTests, AddConstToSpBicTestDoesFollows) {
    1140                 :   // Run test where we conditionally add a constant to a stack pointer,
    1141                 :   // followed by a mask.
    1142                 :   // Note: Implicitly tests always_postdominates.
    1143              15 :   for (int cond = Instruction::EQ; cond < Instruction::AL; ++cond) {
    1144                 :     arm_inst inst[] = {
    1145                 :       0x028dd00c,  // addeq sp, sp, #12
    1146                 :       0xe3cdd2ff,  // bic sp, sp, #-268435441     ; 0xf000000f
    1147              14 :     };
    1148              14 :     inst[0] = ChangeCond(inst[0], static_cast<Instruction::Condition>(cond));
    1149                 :     validation_should_pass(inst,
    1150                 :                            NACL_ARRAY_SIZE(inst),
    1151                 :                            kDefaultBaseAddr,
    1152                 :                            "Add constant (12) to sp, then mask with bic, "
    1153              14 :                            "tests always_postdominates succeeds");
    1154                 :   }
    1155               1 : }
    1156                 : 
    1157               5 : TEST_F(ValidatorTests, AddConstToSpBicTestDoesntFollows) {
    1158                 :   // Run test where we add a constant to a stack pointer, followed
    1159                 :   // by a conditional mask.
    1160                 :   // Note: Implicitly tests always_postdominates.
    1161              15 :   for (int cond = Instruction::EQ; cond < Instruction::AL; ++cond) {
    1162                 :     arm_inst inst[] = {
    1163                 :       0xe28dd00c,  // add sp, sp, #12
    1164                 :       0x03cdd2ff,  // biceq sp, sp, #-268435441   ; 0xf000000f
    1165              14 :     };
    1166              14 :     inst[1] = ChangeCond(inst[1], static_cast<Instruction::Condition>(cond));
    1167                 :     validation_should_fail(inst,
    1168                 :                            NACL_ARRAY_SIZE(inst),
    1169                 :                            kDefaultBaseAddr,
    1170                 :                            "Add constant (12) to sp, then mask with bic, "
    1171              14 :                            "tests always_postdominates fails");
    1172                 :   }
    1173               1 : }
    1174                 : 
    1175               5 : TEST_F(ValidatorTests, CheckVectorLoadPcRelative) {
    1176                 :   // Run test where we do a vector load using a pc relative address.
    1177                 :   // Corresponds to issue 2906.
    1178                 :   static const arm_inst load_inst[] = {
    1179                 :     0xed9f0b04,  // vldr        d0, [pc, #16]
    1180                 :   };
    1181                 :   validation_should_pass(load_inst,
    1182                 :                          NACL_ARRAY_SIZE(load_inst),
    1183                 :                          kDefaultBaseAddr,
    1184               1 :                          "Load vector register using pc relative address");
    1185               1 : }
    1186                 : 
    1187               5 : TEST_F(ValidatorTests, CheckPushSpUnpredictable) {
    1188                 :   // Run test to verify that "Push {sp}", encoding A2 on a8-248 of ARM manual,
    1189                 :   // is unpredictable (i.e. unsafe).
    1190                 :   all_cond_values_fail(0xe52dd004,  // push {sp}
    1191                 :                        kDefaultBaseAddr,
    1192               1 :                        "push {sp} (A2 a8-248) should be unpredictable");
    1193               1 : }
    1194                 : 
    1195               5 : TEST_F(ValidatorTests, ConditionalBreakpoints) {
    1196               1 :   arm_inst bkpt = 0xE1200070;  // BKPT #0
    1197               1 :   arm_inst pool_head = kLiteralPoolHead;
    1198              15 :   for (Instruction::Condition cond = Instruction::EQ;
    1199                 :        cond < Instruction::AL;
    1200                 :        cond = Instruction::Next(cond)) {
    1201              14 :     bkpt = ChangeCond(bkpt, cond);
    1202              14 :     pool_head = ChangeCond(pool_head, cond);
    1203              14 :     EXPECT_FALSE(validate(&bkpt, 1, kDefaultBaseAddr))
    1204               0 :         << "conditional breakpoint should be unpredictable";
    1205              14 :     EXPECT_FALSE(validate(&pool_head, 1, kDefaultBaseAddr))
    1206               0 :         << "conditional literal pool head should be unpredictable";
    1207                 :   }
    1208               1 : }
    1209                 : 
    1210               5 : TEST_F(ValidatorTests, CheckLoadStoreWritebackUnpredictable) {
    1211                 :   // See issue #2816: compilers used to emit some unpredictable load/store
    1212                 :   // instructions with writeback, and the validator accepted them for a while.
    1213                 :   //
    1214                 :   // Theses unpredictables have writeback and either Rn=Rt or Rn=Rt2.
    1215                 :   //
    1216                 :   // The instructions are all from A5.2.8 Extra Load/Store Instructions:
    1217                 :   //   cccc 000P UaWa nnnn tttt xxxx 1bb1 xxxx
    1218                 :   // With an exclusion for data-processing and miscellaneous as noted below.
    1219                 :   //
    1220                 :   // Nibbles 0 and 2 are either zeroes/Rm (register variants) or
    1221                 :   // imm4H/imm4L (integer variant). Only test when they're all zero.
    1222               1 :   arm_inst templ = 0x00000090;
    1223               5 :   for (uint32_t op2 = 0; op2 <= 0x3; ++op2) {  // op2 is in inst(6:5).
    1224             132 :     for (uint32_t op1 = 0; op1 <= 0x1F; ++op1) {  // op1 is in inst(24:20).
    1225             128 :       if (!(op1 & 0x2))
    1226              64 :         continue;  // Only undefined with writeback.
    1227              64 :       if ((op2 == 0x0) ||
    1228                 :           ((op1 & 0x13) == 0x03) ||
    1229                 :           (((op1 & 0x13) == 0x02) && ((op2 & 0x2) == 0x0)))
    1230              32 :         continue;  // Not in A5.2.8: actually Data-processing and miscellaneous.
    1231                 :       // Dual load/store encode Rt2 as Rt+1.
    1232              32 :       bool is_dual = ((op1 & 0x01) == 0x00) && ((op2 == 0x2) || (op2 == 0x3));
    1233             512 :       for (uint32_t n = 0; n < 15; ++n) {  // Ignore Rn=PC, it can't writeback.
    1234             480 :         uint32_t t = n;
    1235             480 :         arm_inst base = (templ | (op1 << 20) | (t << 12) | (op2 << 5));
    1236             480 :         arm_inst inst = base | (n << 16);  // Rn=Rt.
    1237             480 :         arm_inst inst_dual = base | ((n + 1) << 16);  // Rn=Rt2.
    1238                 :         all_cond_values_fail(inst, kDefaultBaseAddr, "extra load/store "
    1239                 :                              "with writeback and Rn==Rt should be "
    1240             480 :                              "unpredictable");
    1241             480 :         if (is_dual) {
    1242                 :           all_cond_values_fail(inst_dual, kDefaultBaseAddr, "extra load/store "
    1243                 :                                "with writeback and Rn==Rt2 should be "
    1244             240 :                                "unpredictable");
    1245                 :         }
    1246                 :       }
    1247                 :     }
    1248                 :   }
    1249               1 : }
    1250                 : 
    1251               5 : TEST_F(ValidatorTests, LiteralPoolHeadIsBreakpoint) {
    1252               1 :   EXPECT_EQ(kLiteralPoolHead & 0xFFF000F0, 0xE1200070)  // BKPT #0
    1253                 :       << ("the literal pool head should be a breakpoint: "
    1254               0 :           "it needs to act as a roadblock");
    1255               1 : }
    1256                 : 
    1257               5 : TEST_F(ValidatorTests, Breakpoint) {
    1258               1 :   EXPECT_EQ(nacl_arm_dec::kBreakpoint & 0xFFF000F0,
    1259                 :             0xE1200070)  // BKPT #0
    1260                 :       << ("the breakpoint instruction should be a breakpoint: "
    1261               0 :           "it needs to trap");
    1262               1 : }
    1263                 : 
    1264               5 : TEST_F(ValidatorTests, HaltFill) {
    1265               1 :   EXPECT_EQ(nacl_arm_dec::kHaltFill & 0xFFF000F0,
    1266                 :             0xE7F000F0)  // UDF #0
    1267                 :       << ("the halt fill instruction should be UDF: "
    1268               0 :           "it needs to trap");
    1269               1 : }
    1270                 : 
    1271               5 : TEST_F(ValidatorTests, AbortNow) {
    1272               1 :   EXPECT_EQ(nacl_arm_dec::kAbortNow & 0xFFF000F0,
    1273                 :             0xE7F000F0)  // UDF #0
    1274                 :       << ("the abort now instruction should be UDF: "
    1275               0 :           "it needs to trap");
    1276               1 : }
    1277                 : 
    1278               5 : TEST_F(ValidatorTests, FailValidation) {
    1279               1 :   EXPECT_EQ(kFailValidation & 0xFFF000F0, 0xE7F000F0)  // UDF #0
    1280                 :       << ("the fail validation instruction should be UDF: "
    1281               0 :           "it needs to trap");
    1282               1 : }
    1283                 : 
    1284               5 : TEST_F(ValidatorTests, UDFAndBKPTValidateAsExpected) {
    1285           65536 :   for (uint32_t i = 0; i < 0xFFFF; ++i) {
    1286           65535 :     arm_inst bkpt_inst = 0xE1200070 | ((i & 0xFFF0) << 4) | (i & 0xF);
    1287           65535 :     arm_inst udf_inst  = 0xE7F000F0 | ((i & 0xFFF0) << 4) | (i & 0xF);
    1288           65535 :     EXPECT_EQ(validate(&bkpt_inst, 1, kDefaultBaseAddr),
    1289                 :               ((bkpt_inst == kLiteralPoolHead) ||
    1290           65535 :                (bkpt_inst == nacl_arm_dec::kBreakpoint)));
    1291           65535 :     EXPECT_EQ(validate(&udf_inst, 1, kDefaultBaseAddr),
    1292                 :               ((udf_inst == nacl_arm_dec::kHaltFill) ||
    1293           65535 :                (udf_inst == nacl_arm_dec::kAbortNow)));
    1294                 :     // Tautological note: kFailValidation should fail validation.
    1295                 :   }
    1296               1 : }
    1297                 : 
    1298               5 : TEST_F(ValidatorTests, LiteralPoolHeadInstruction) {
    1299                 :   // Make sure that literal pools are handled properly: they should be preceded
    1300                 :   // by a special breakpoint instruction at the start of the bundle, and can
    1301                 :   // then contain any bits that would otherwise look malicious.
    1302                 :   // Each literal pool bundle has to start with such a literal pool head.
    1303               1 :   vector<arm_inst> literal_pool(_validator->InstructionsPerBundle(), kSvc0);
    1304               1 :   literal_pool[0] = 0xE1200070;  // BKPT #0
    1305                 :   // Try out all BKPT encodings, and make sure only one of them works.
    1306           65537 :   for (uint32_t imm16 = 0; imm16 <= 0xFFFF; ++imm16) {
    1307           65536 :     literal_pool[0] = (literal_pool[0] & 0xFFF000F0) |
    1308                 :         (imm16 & 0xF) |
    1309           65536 :         ((imm16 & 0xFFF0) << 8);
    1310           65536 :     if (literal_pool[0] == kLiteralPoolHead) {
    1311               0 :       validation_should_pass(&literal_pool.front(),
    1312                 :                              literal_pool.size(),
    1313                 :                              kDefaultBaseAddr,
    1314                 :                              "valid literal pool: "
    1315               0 :                              "starts with special BKPT");
    1316                 :     } else {
    1317           65536 :       validation_should_fail(&literal_pool.front(),
    1318                 :                              literal_pool.size(),
    1319                 :                              kDefaultBaseAddr,
    1320                 :                              "invalid literal pool: "
    1321          131072 :                              "starts with just a regular BKPT");
    1322                 :     }
    1323               1 :   }
    1324               1 : }
    1325                 : 
    1326               5 : TEST_F(ValidatorTests, LiteralPoolHeadPosition) {
    1327                 :   // Literal pools should only work when the head instruction is indeed at
    1328                 :   // the head.
    1329               1 :   vector<arm_inst> literal_pool(_validator->InstructionsPerBundle());
    1330               5 :   for (size_t pos = 0; pos < literal_pool.size(); ++pos) {
    1331               4 :     std::fill(literal_pool.begin(), literal_pool.end(), kSvc0);
    1332               4 :     if (pos != literal_pool.size() - 1) {
    1333                 :       // We do one iteration without a literal pool head at all.
    1334               3 :       literal_pool[pos] = kLiteralPoolHead;
    1335                 :     }
    1336               4 :     if (pos == 0) {
    1337               1 :       validation_should_pass(&literal_pool.front(),
    1338                 :                              literal_pool.size(),
    1339                 :                              kDefaultBaseAddr,
    1340                 :                              "valid literal pool: "
    1341               2 :                              "starts with special head instruction");
    1342                 :     } else {
    1343               3 :       validation_should_fail(&literal_pool.front(),
    1344                 :                              literal_pool.size(),
    1345                 :                              kDefaultBaseAddr,
    1346                 :                              "invalid literal pool: "
    1347               6 :                              "doesn't start with special  head instruction");
    1348                 :     }
    1349               1 :   }
    1350               1 : }
    1351                 : 
    1352               5 : TEST_F(ValidatorTests, LiteralPoolBig) {
    1353                 :   // Literal pools should be a single bundle wide, each must be preceded by
    1354                 :   // a pool head.
    1355               1 :   vector<arm_inst> literal_pools(2 * _validator->InstructionsPerBundle());
    1356               9 :   for (size_t pos = 0; pos < literal_pools.size(); ++pos) {
    1357               8 :     std::fill(literal_pools.begin(), literal_pools.end(), kSvc0);
    1358               8 :     literal_pools[pos] = kLiteralPoolHead;
    1359               8 :     validation_should_fail(&literal_pools.front(),
    1360                 :                            literal_pools.size(),
    1361                 :                            kDefaultBaseAddr,
    1362              16 :                            "invalid literal pool: two pools, one head");
    1363               1 :   }
    1364               1 : }
    1365                 : 
    1366               5 : TEST_F(ValidatorTests, LiteralPoolBranch) {
    1367                 :   // Branching to a literal pool should only work at the head.
    1368                 :   // Construct a code region with a bundle of code, then a bundle-wide
    1369                 :   // literal pool, then another bundle of code.
    1370                 :   // Add a branch from different code locations, pointing at different
    1371                 :   // parts of the code. Pointing in the literal pool should fail, except
    1372                 :   // when pointing at the head.
    1373                 :   // Note that we don't actually put anything malicious in the literal pool,
    1374                 :   // and we still shouldn't be able to jump in the middle of it.
    1375               1 :   const size_t bundle_pos = _validator->InstructionsPerBundle();
    1376               1 :   vector<arm_inst> code(3 * bundle_pos);
    1377              13 :   for (size_t b_pos = 0; b_pos < code.size(); ++b_pos) {
    1378              12 :     if ((bundle_pos <= b_pos) && (b_pos < bundle_pos * 2)) {
    1379                 :       // Don't try putting the branch in the middle of the literal pool.
    1380               4 :       continue;
    1381                 :     }
    1382               8 :     std::fill(code.begin(), code.end(), kNop);
    1383               8 :     code[bundle_pos] = kLiteralPoolHead;
    1384             104 :     for (size_t b_target = 0; b_target < code.size(); ++b_target) {
    1385                 :       // PC reads as current instruction address plus 8 (e.g. two instructions
    1386                 :       // ahead of b_pos).
    1387                 :       // imm24 is encoded with the bottom two bits zeroed out, which we
    1388                 :       // implicitly do by working with instructions instead of bytes.
    1389              96 :       uint32_t imm24 = (b_target - b_pos - 2) & 0x00FFFFFF;
    1390              96 :       code[b_pos] = 0xEA000000 | imm24;  // B #imm
    1391                 :       bool target_in_pool = (bundle_pos < b_target) &&
    1392              96 :           (b_target < bundle_pos * 2);  // Excluding head.
    1393              96 :       if (target_in_pool) {
    1394              24 :         validation_should_fail(&code.front(),
    1395                 :                                code.size(),
    1396                 :                                kDefaultBaseAddr,
    1397              48 :                                "branch inside a literal pool");
    1398                 :       } else {
    1399              72 :         validation_should_pass(&code.front(),
    1400                 :                                code.size(),
    1401                 :                                kDefaultBaseAddr,
    1402             144 :                                "branch around or at head of a literal pool");
    1403                 :       }
    1404                 :     }
    1405               1 :   }
    1406               1 : }
    1407                 : 
    1408               5 : TEST_F(ValidatorTests, Preloads) {
    1409                 :   // Preloads leak information on some ARM CPUs and are therefore treated
    1410                 :   // similar to no-destination loads. They come in three flavors:
    1411                 :   // - PLD{W} [<Rn>, #+/-<imm12>] simply needs to mask Rn.
    1412                 :   // - PLD <label> doesn't need masking: its immediate is limited to 12 bits.
    1413                 :   // - PLD{W} [<Rn>,+/-<Rm>{, <shift>}] is disallowed.
    1414                 :   // The same applies for PLI, which has analogous variants.
    1415                 : 
    1416                 :   // PLD{W} [<Rn>, #+/-<imm12>] as well as PLI.
    1417                 :   // PLD{W}: 1111 0101 UR01 nnnn 1111 iiii iiii iiii
    1418                 :   // PLI:    1111 0100 U101 nnnn 1111 iiii iiii iiii
    1419               3 :   for (uint32_t is_pld = 0; is_pld <= 1; ++is_pld) {
    1420               5 :     for (uint32_t r = is_pld ? 0 : 1; r <= 1; ++r) {
    1421               9 :       for (uint32_t u = 0; u <= 1; ++u) {
    1422               6 :         uint32_t rn = 0x1;  // TODO(jfb) The BIC patterns only test Rn==R1.
    1423           24582 :         for (uint32_t imm12 = 0; imm12 <= 0xFFF; ++imm12) {
    1424                 :           arm_inst pl_inst = 0xF410F000 |
    1425           24576 :               (is_pld << 24) | (u << 23) | (r << 22) | (rn << 16) | imm12;
    1426                 :           validation_should_fail(&pl_inst, 1, kDefaultBaseAddr,
    1427           24576 :                                  "unmasked preloads");
    1428          122880 :           for (size_t m = 0; m < NACL_ARRAY_SIZE(examples_of_safe_masks);
    1429                 :                ++m) {
    1430                 :             arm_inst program[] = {
    1431                 :               ChangeCond(examples_of_safe_masks[m].inst,
    1432           98304 :                          Instruction::AL),
    1433                 :               pl_inst,
    1434           98304 :             };
    1435                 :             validation_should_pass(program, NACL_ARRAY_SIZE(program),
    1436                 :                                    kDefaultBaseAddr,
    1437           98304 :                                    "masked preload with safe mask");
    1438                 :           }
    1439          122880 :           for (size_t m = 0; m < NACL_ARRAY_SIZE(examples_of_invalid_masks);
    1440                 :                ++m) {
    1441                 :             arm_inst program[] = {
    1442                 :               ChangeCond(examples_of_invalid_masks[m].inst,
    1443           98304 :                          Instruction::AL),
    1444                 :               pl_inst,
    1445           98304 :             };
    1446                 :             validation_should_fail(program, NACL_ARRAY_SIZE(program),
    1447                 :                                    kDefaultBaseAddr,
    1448           98304 :                                    "masked preload with invalid mask");
    1449                 :           }
    1450                 :         }
    1451                 :       }
    1452                 :     }
    1453                 :   }
    1454                 : 
    1455                 :   // PLD <label> as well as PLI.
    1456                 :   // PLD: 1111 0101 U101 1111 1111 iiii iiii iiii
    1457                 :   // PLI: 1111 0100 U101 1111 1111 iiii iiii iiii
    1458               3 :   for (uint32_t is_pld = 0; is_pld <= 1; ++is_pld) {
    1459               6 :     for (uint32_t u = 0; u <= 1; ++u) {
    1460           16388 :       for (uint32_t imm12 = 0; imm12 <= 0xFFF; ++imm12) {
    1461                 :         arm_inst pl_inst = 0xF45FF000 |
    1462           16384 :             (is_pld << 24) | (u << 23) | imm12;
    1463                 :         validation_should_pass(&pl_inst, 1, kDefaultBaseAddr,
    1464           16384 :                                "unmasked literal preloads");
    1465                 :       }
    1466                 :     }
    1467                 :   }
    1468                 : 
    1469                 :   // PLD{W} [<Rn>, +/-Rm{, shift}] as well as PLI.
    1470                 :   // PLD{W}: 1111 0111 UR01 nnnn 1111 iiii itt0 mmmm
    1471                 :   // PLI:    1111 0110 U101 nnnn 1111 iiii itt0 mmmm
    1472               3 :   for (uint32_t is_pld = 0; is_pld <= 1; ++is_pld) {
    1473               5 :     for (uint32_t r = is_pld ? 0 : 1; r <= 1; ++r) {
    1474               9 :       for (uint32_t u = 0; u <= 1; ++u) {
    1475              30 :         for (uint32_t t = 0; t <= 3; ++t) {
    1476             408 :           for (uint32_t rm = 0; rm <= 0xF; ++rm) {
    1477             384 :             uint32_t rn = 0x1;  // TODO(jfb) The BIC patterns only test Rn==R1.
    1478           12672 :             for (uint32_t imm5 = 0; imm5 <= 0x1F; ++imm5) {
    1479                 :               arm_inst pl_inst = 0xF610F000 |
    1480                 :                   (is_pld << 24) | (u << 23) | (r << 22) | (rn << 16) |
    1481           12288 :                   (imm5 << 7) | (t << 5) | rm;
    1482                 :               validation_should_fail(&pl_inst, 1, kDefaultBaseAddr,
    1483           12288 :                                      "unmasked register-register preloads");
    1484           61440 :               for (size_t m = 0; m < NACL_ARRAY_SIZE(examples_of_safe_masks);
    1485                 :                    ++m) {
    1486                 :                 arm_inst program[] = {
    1487                 :                   ChangeCond(examples_of_safe_masks[m].inst,
    1488           49152 :                              Instruction::AL),
    1489                 :                   pl_inst,
    1490           49152 :                 };
    1491                 :                 validation_should_fail(program, NACL_ARRAY_SIZE(program),
    1492                 :                                        kDefaultBaseAddr,
    1493                 :                                        "masked register-register preload "
    1494           49152 :                                        "with safe mask");
    1495                 :               }
    1496           61440 :               for (size_t m = 0; m < NACL_ARRAY_SIZE(examples_of_invalid_masks);
    1497                 :                    ++m) {
    1498                 :                 arm_inst program[] = {
    1499                 :                   ChangeCond(examples_of_invalid_masks[m].inst,
    1500           49152 :                              Instruction::AL),
    1501                 :                   pl_inst,
    1502           49152 :                 };
    1503                 :                 validation_should_fail(program, NACL_ARRAY_SIZE(program),
    1504                 :                                        kDefaultBaseAddr,
    1505                 :                                        "masked register-register preload "
    1506           49152 :                                        "with invalid mask");
    1507                 :               }
    1508                 :             }
    1509                 :           }
    1510                 :         }
    1511                 :       }
    1512                 :     }
    1513                 :   }
    1514               1 : }
    1515                 : 
    1516               5 : TEST_F(ValidatorTests, LoadThreadLocalPtr) {
    1517                 :   // Verify that we recognize valid load thread local pointer instructions.
    1518                 :   static const AnnotatedInstruction loadr9_insts[] = {
    1519                 :     {0xe5990000,  "ldr<c> r0, [r9]"},
    1520                 :     {0xe5990004,  "ldr<c> r0, [r9, #4]"},
    1521                 :   };
    1522                 : 
    1523                 :   // Try each load instruction
    1524               3 :   for (size_t i = 0; i < NACL_ARRAY_SIZE(loadr9_insts); ++i) {
    1525               2 :     Instruction test_base(loadr9_insts[i].inst);
    1526                 : 
    1527                 :     // Try each possible condition.
    1528              32 :     for (Instruction::Condition cond = Instruction::EQ;
    1529                 :          cond < Instruction::UNCONDITIONAL;
    1530                 :          cond = Instruction::Next(cond)) {
    1531              30 :       Instruction test_cond(ChangeInstCond(test_base, cond));
    1532                 : 
    1533                 :       // Try each register to assign (i.e. replace r0).
    1534             510 :       for (uint32_t r = 0; r < 16; ++r) {
    1535             480 :         Register reg(r);
    1536             480 :         Instruction test(test_cond);
    1537             480 :         test.SetBits(15, 12, r);  // I.e. set Rt(15:12) to r;
    1538                 : 
    1539                 :         // Generate string describing instruction being tested.
    1540             480 :         ostringstream message;
    1541             480 :         string msg(loadr9_insts[i].about);
    1542             480 :         const char* r0 = "r0";
    1543             480 :         msg.replace(msg.find(r0), strlen(r0), reg.ToString());
    1544             480 :         const char* cc = "<c>";
    1545             480 :         msg.replace(msg.find(cc), strlen(cc), Instruction::ToString(cond));
    1546             480 :         message << "Test '" << msg << "'";
    1547                 : 
    1548                 :         // Test the generated instruction.
    1549             480 :         arm_inst insts[1] = { test.Bits() };
    1550             480 :         if (IsValidSingleInstructionDestinationRegister(reg)) {
    1551                 :           validation_should_pass(insts, NACL_ARRAY_SIZE(insts),
    1552             390 :                                  kDefaultBaseAddr, message.str());
    1553                 :         } else {
    1554                 :           validation_should_fail(insts, NACL_ARRAY_SIZE(insts),
    1555              90 :                                  kDefaultBaseAddr, message.str());
    1556                 :         }
    1557             480 :       }
    1558                 :     }
    1559                 :   }
    1560               1 : }
    1561                 : 
    1562               5 : TEST_F(ValidatorTests, UseR9) {
    1563                 :   // Verify that we report about illegal uses of thread local pointer.
    1564                 :   static const AnnotatedInstruction use_r9_insts[] = {
    1565                 :     {0xe0892009, "add r2, r9, r9"},
    1566                 :     { 0x03C99103, "bic r9, r9, #0xC0000000: simple in-place mask (form 1)" },
    1567                 :     { 0x03C91103, "bic r1, r9, #0xC0000000: mask with register move (form 1)" },
    1568                 :     { 0x03C19103, "bic r9, r1, #0xC0000000: mask with register move (form 1)" },
    1569                 :     { 0x03C994C0, "bic r9, r9, #0xC0000000: simple in-place mask (form 2)" },
    1570                 :     { 0x03C914C0, "bic r1, r9, #0xC0000000: mask with register move (form 2)" },
    1571                 :     { 0x03C394C0, "bic r9, r3, #0xC0000000: mask with register move (form 2)" },
    1572                 :     { 0x03C994FF, "bic r9, r9, #0xFF000000: overzealous but correct mask" },
    1573                 :     {0xe7df9f1f, "bfc   r9, #30, #2"},
    1574                 :     // TODO(karl): Add load/store examples, when implemented, like:
    1575                 :     //    STR r9, [rt]; MOV rd, r9; MOV sd, r9
    1576                 :   };
    1577                 : 
    1578                 :   // Try each test instruction.
    1579              10 :   for (size_t i = 0; i < NACL_ARRAY_SIZE(use_r9_insts); ++i) {
    1580               9 :     Instruction test(use_r9_insts[i].inst);
    1581                 : 
    1582                 :     // Try each possible condition.
    1583             144 :     for (Instruction::Condition cond = Instruction::EQ;
    1584                 :          cond < Instruction::UNCONDITIONAL;
    1585                 :          cond = Instruction::Next(cond)) {
    1586             135 :       Instruction test_cond(ChangeInstCond(test, cond));
    1587                 : 
    1588             135 :       ostringstream message;
    1589             135 :       message << "Test use of r9 with cond=" << Instruction::ToString(cond)
    1590             270 :               << ": " << use_r9_insts[i].about;
    1591                 :       validation_should_fail(&use_r9_insts[i].inst, 1, kDefaultBaseAddr,
    1592             135 :                              message.str());
    1593             135 :     }
    1594                 :   }
    1595               1 : }
    1596                 : 
    1597                 : };  // anonymous namespace
    1598                 : 
    1599                 : // Test driver function.
    1600               1 : int main(int argc, char *argv[]) {
    1601               1 :   testing::InitGoogleTest(&argc, argv);
    1602               1 :   return RUN_ALL_TESTS();
    1603               3 : }

Generated by: LCOV version 1.7