LCOV - code coverage report
Current view: directory - src/trusted/validator_arm - validator_tests.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 96 76 79.2 %
Date: 2014-07-02 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                 : #include "native_client/src/trusted/validator_arm/validator_tests.h"
       8                 : 
       9                 : namespace nacl_val_arm_test {
      10                 : 
      11            3480 : void ProblemSpy::ReportProblemMessage(Violation violation,
      12                 :                                       uint32_t vaddr,
      13                 :                                       const char* message) {
      14            3480 :   ProblemRecord prob(violation, vaddr, message);
      15            3480 :   problems_.push_back(prob);
      16            3480 : }
      17                 : 
      18              51 : ValidatorTests::ValidatorTests()
      19                 :     : _validator(NULL),
      20              51 :       _is_valid_single_instruction_destination_register() {
      21                 :   _is_valid_single_instruction_destination_register.
      22              51 :       Add(Register::Tp()).Add(Register::Sp()).Add(Register::Pc());
      23              51 : }
      24                 : 
      25            1365 : const nacl_arm_dec::ClassDecoder& ValidatorTests::decode(
      26                 :     nacl_arm_dec::Instruction inst) const {
      27            1365 :   return _validator->decode(inst);
      28                 : }
      29                 : 
      30          261882 : bool ValidatorTests::validate(const arm_inst *pattern,
      31                 :                               size_t inst_count,
      32                 :                               uint32_t start_addr,
      33                 :                               ProblemSink *sink) {
      34                 :   // We think in instructions; CodeSegment thinks in bytes.
      35          261882 :   const uint8_t *bytes = reinterpret_cast<const uint8_t *>(pattern);
      36          261882 :   CodeSegment segment(bytes, start_addr, inst_count * sizeof(arm_inst));
      37                 : 
      38          261882 :   vector<CodeSegment> segments;
      39          261882 :   segments.push_back(segment);
      40                 : 
      41          261882 :   return _validator->validate(segments, sink);
      42                 : }
      43                 : 
      44          372203 : ViolationSet ValidatorTests::find_violations(
      45                 :     const arm_inst *pattern,
      46                 :     size_t inst_count,
      47                 :     uint32_t start_addr,
      48                 :     ProblemSink *sink) {
      49                 :   // We think in instructions; CodeSegment thinks in bytes.
      50          372203 :   const uint8_t *bytes = reinterpret_cast<const uint8_t *>(pattern);
      51          372203 :   CodeSegment segment(bytes, start_addr, inst_count * sizeof(arm_inst));
      52                 : 
      53          372203 :   vector<CodeSegment> segments;
      54          372203 :   segments.push_back(segment);
      55                 : 
      56          372203 :   return _validator->find_violations(segments, sink);
      57                 : }
      58                 : 
      59          119969 : void ValidatorTests::validation_should_pass(const arm_inst *pattern,
      60                 :                                             size_t inst_count,
      61                 :                                             uint32_t base_addr,
      62                 :                                             const string &msg) {
      63          119969 :   ProblemSpy spy;
      64          119969 :   bool validation_result = validate(pattern, inst_count, base_addr, &spy);
      65                 : 
      66          119969 :   std::string errors;
      67          119969 :   vector<ProblemRecord> &problems = spy.get_problems();
      68          239938 :   for (vector<ProblemRecord>::const_iterator it = problems.begin();
      69          119969 :        it != problems.end();
      70                 :        ++it) {
      71               0 :     if (it != problems.begin()) {
      72               0 :       errors += "\n";
      73                 :     }
      74               0 :     errors += std::string("\t") + it->message();
      75                 :   }
      76                 : 
      77          119969 :   ASSERT_TRUE(validation_result) << msg << " should pass at " << base_addr <<
      78          119969 :       ":\n" << errors;
      79                 : }
      80                 : 
      81            1587 : void ValidatorTests::validation_should_pass2(const arm_inst *pattern,
      82                 :                                              size_t inst_count,
      83                 :                                              uint32_t base_addr,
      84                 :                                              const string &msg) {
      85                 :   // A couple sanity checks for correct usage.
      86            1587 :   ASSERT_EQ(2U, inst_count)
      87               0 :       << "This routine only supports 2-instruction patterns.";
      88            1587 :   ASSERT_TRUE(
      89                 :       _validator->bundle_for_address(base_addr).begin_addr() == base_addr)
      90               0 :       << "base_addr parameter must be bundle-aligned";
      91                 : 
      92                 :   // Try error case where second instruction occurs as first instruction.
      93                 :   arm_inst second_as_program[] = {
      94            1587 :     pattern[1]
      95            1587 :   };
      96            1587 :   ostringstream bad_first_message;
      97            1587 :   bad_first_message << msg << ": without first instruction";
      98                 :   validation_should_fail(second_as_program,
      99                 :                          NACL_ARRAY_SIZE(second_as_program),
     100                 :                          base_addr,
     101            1587 :                          bad_first_message.str());
     102                 : 
     103                 :   // Try the legitimate (non-overlapping) variations:
     104            1587 :   uint32_t last_addr = base_addr + (kBytesPerBundle - 4);
     105            6348 :   for (uint32_t addr = base_addr; addr < last_addr; addr += 4) {
     106            4761 :     validation_should_pass(pattern, inst_count, addr, msg);
     107                 :   }
     108                 : 
     109                 :   // Make sure it fails over bundle boundaries.
     110            1587 :   ProblemSpy spy;
     111                 :   ViolationSet violations = find_violations(
     112            1587 :       pattern, inst_count, last_addr, &spy);
     113                 : 
     114            1587 :   EXPECT_NE(violations, kNoViolations)
     115               0 :       << msg << " should fail at overlapping address " << last_addr;
     116            1587 :   EXPECT_TRUE(nacl_arm_dec::ContainsCrossesBundleViolation(violations))
     117               0 :       << msg << " should contain crosses bundle violation";
     118                 : 
     119            1587 :   vector<ProblemRecord> &problems = spy.get_problems();
     120            1587 :   ASSERT_EQ(1U, problems.size())
     121               0 :       << msg << " should have 1 problem at overlapping address " << last_addr;
     122                 : 
     123            1587 :   ProblemRecord first = problems[0];
     124                 : 
     125            1587 :   if (first.violation() !=
     126                 :       nacl_arm_dec::DATA_REGISTER_UPDATE_CROSSES_BUNDLE_VIOLATION) {
     127            1587 :     last_addr += 4;
     128                 :   }
     129            1587 :   EXPECT_EQ(last_addr, first.vaddr())
     130               0 :       << "Problem in valid but mis-aligned pseudo-instruction ("
     131               0 :       << msg
     132            1587 :       << ") must be reported at end of bundle";
     133            1587 :   EXPECT_FALSE(nacl_arm_dec::IsSafetyViolation(first.violation()))
     134               0 :       << "Just crossing a bundle should not make a safe instruction unsafe: "
     135            1587 :       << msg;
     136                 : 
     137                 :   // Be sure that we get one of the crosses bundle error messages.
     138            1587 :   EXPECT_TRUE(nacl_arm_dec::IsCrossesBundleViolation(first.violation()));
     139                 : }
     140                 : 
     141          370616 : ViolationSet ValidatorTests::validation_should_fail(
     142                 :     const arm_inst *pattern,
     143                 :     size_t inst_count,
     144                 :     uint32_t base_addr,
     145                 :     const string &msg,
     146                 :     ProblemSpy* spy) {
     147                 :   // TODO(cbiffle): test at various overlapping and non-overlapping addresses,
     148                 :   // like above.  Not that this is a spectacularly likely failure case, but
     149                 :   // it's worth exercising.
     150                 :   ViolationSet violations =
     151          370616 :       find_violations(pattern, inst_count, base_addr, spy);
     152          370616 :   EXPECT_NE(violations, kNoViolations) << "Expected to fail: " << msg;
     153                 : 
     154          370616 :   if (spy != NULL) {
     155                 :     // There should be at least one problem.
     156            1893 :     vector<ProblemRecord> &problems = spy->get_problems();
     157            1893 :     EXPECT_LT(static_cast<size_t>(0), problems.size());
     158                 : 
     159                 :     // Violations found in problems should match violations returned by
     160                 :     // find_violations.
     161            1893 :     ViolationSet problem_violations = kNoViolations;
     162            7572 :     for (vector<ProblemRecord>::iterator iter = problems.begin();
     163            3786 :          iter != problems.end();
     164                 :          ++iter) {
     165                 :       problem_violations = nacl_arm_dec::ViolationUnion(
     166                 :           problem_violations,
     167            1893 :           nacl_arm_dec::ViolationBit(iter->violation()));
     168                 :     }
     169            1893 :     EXPECT_EQ(violations, problem_violations)
     170               0 :         << "Violation differences: " << msg;
     171                 :   }
     172                 : 
     173                 :   // The rest of the checking is done in the caller.
     174          370616 :   return violations;
     175                 : }
     176                 : 
     177               0 : void ValidatorTests::all_cond_values_pass(const arm_inst prototype,
     178                 :                                           uint32_t base_addr,
     179                 :                                           const string &msg) {
     180               0 :   arm_inst test_inst = prototype;
     181               0 :   for (Instruction::Condition cond = Instruction::EQ;
     182                 :        cond < Instruction::UNCONDITIONAL;
     183                 :        cond = Instruction::Next(cond)) {
     184               0 :     test_inst = ChangeCond(test_inst, cond);
     185               0 :     EXPECT_TRUE(validate(&test_inst, 1, base_addr))
     186               0 :         << "Fails on cond " << Instruction::ToString(cond) << ": " << msg;
     187                 :   }
     188               0 : }
     189                 : 
     190             721 : void ValidatorTests::all_cond_values_fail(const arm_inst prototype,
     191                 :                                           uint32_t base_addr,
     192                 :                                           const string &msg) {
     193             721 :   arm_inst test_inst = prototype;
     194           11536 :   for (Instruction::Condition cond = Instruction::EQ;
     195                 :        cond < Instruction::UNCONDITIONAL;
     196                 :        cond = Instruction::Next(cond)) {
     197           10815 :     test_inst = ChangeCond(test_inst, cond);
     198           10815 :     EXPECT_FALSE(validate(&test_inst, 1, base_addr))
     199               0 :       << std::hex << test_inst
     200           10815 :         << ": Passes on cond " << Instruction::ToString(cond) << ": " << msg;
     201                 :   }
     202             721 : }
     203                 : 
     204               3 : }  // namespace nacl_val_arm_test

Generated by: LCOV version 1.7