OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 Google Inc. All Rights Reserved. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 #include "syzygy/experimental/protect/protect_lib/integrity_check_transform.h" |
| 16 |
| 17 #include <sstream> |
| 18 #include <map> |
| 19 |
| 20 #include "gtest/gtest.h" |
| 21 #include "syzygy/block_graph/basic_block.h" |
| 22 #include "syzygy/block_graph/basic_block_assembler.h" |
| 23 #include "syzygy/block_graph/basic_block_decomposer.h" |
| 24 #include "syzygy/block_graph/basic_block_subgraph.h" |
| 25 #include "syzygy/block_graph/block_graph.h" |
| 26 #include "syzygy/block_graph/block_util.h" |
| 27 #include "syzygy/block_graph/typed_block.h" |
| 28 #include "syzygy/common/indexed_frequency_data.h" |
| 29 #include "syzygy/instrument/transforms/unittest_util.h" |
| 30 |
| 31 namespace protect { |
| 32 namespace { |
| 33 |
| 34 //using base::DictionaryValue; |
| 35 //using base::ListValue; |
| 36 //using base::Value; |
| 37 |
| 38 using block_graph::BasicBlock; |
| 39 using block_graph::BasicBlockDecomposer; |
| 40 using block_graph::BasicBlockSubGraph; |
| 41 using block_graph::BasicCodeBlock; |
| 42 using block_graph::BlockGraph; |
| 43 using block_graph::Instruction; |
| 44 |
| 45 //typedef AllocationFilterTransform::Offset Offset; |
| 46 //typedef AllocationFilterTransform::OffsetSet OffsetSet; |
| 47 //typedef AllocationFilterTransform::FunctionNameOffsetMap |
| 48 // FunctionNameOffsetMap; |
| 49 |
| 50 static wchar_t kConfigBadPathDoesNotExist[] = |
| 51 L"syzygy/instrument/test_data/" |
| 52 L"allocation-filter-bad-path-does-not-exist.json"; |
| 53 |
| 54 class TestIntegrityCheckTransform : public IntegrityCheckTransform { |
| 55 public: |
| 56 //using IntegrityCheckTransform::pre_call_hook_ref_; |
| 57 //using AllocationFilterTransform::post_call_hook_ref_; |
| 58 using IntegrityCheckTransform::target_names_; |
| 59 using IntegrityCheckTransform::partition_unit_map_; |
| 60 using IntegrityCheckTransform::label_name_to_block_; |
| 61 using IntegrityCheckTransform::dll_id_to_block_reference_; |
| 62 using IntegrityCheckTransform::nr_pc_relative_refs_; |
| 63 using IntegrityCheckTransform::is_bb_checked_map_; |
| 64 using IntegrityCheckTransform::ic_block_chunk_index_map_; |
| 65 using IntegrityCheckTransform::ic_block_reference_free_chunks; |
| 66 using IntegrityCheckTransform::ic_chunk_checker_to_checkee_map_; |
| 67 using IntegrityCheckTransform::precomputed_hashes_; |
| 68 using IntegrityCheckTransform::checker_to_checkee_map_; |
| 69 using IntegrityCheckTransform::xhash_block_; |
| 70 using IntegrityCheckTransform::hash_block_; |
| 71 using IntegrityCheckTransform::response_block_; |
| 72 using IntegrityCheckTransform::id_to_label_; |
| 73 using IntegrityCheckTransform::basic_block_sizes_; |
| 74 using IntegrityCheckTransform::num_chunks_per_block; |
| 75 using IntegrityCheckTransform::GetHashBlock;//done mohsen |
| 76 using IntegrityCheckTransform::SetHashBlock;//done mohsen |
| 77 using IntegrityCheckTransform::CheckHash;//done mohsen |
| 78 using IntegrityCheckTransform::FixPrecomputedHashes;//done mohsen |
| 79 using IntegrityCheckTransform::PatchPrecomputedHashes;//mohsen |
| 80 using IntegrityCheckTransform::PatchBlockReference;//done mohsen |
| 81 using IntegrityCheckTransform::RecomputeXorChunks;//done mohsen |
| 82 using IntegrityCheckTransform::RecomputePivot;//done mohsen |
| 83 using IntegrityCheckTransform::ComputeAggregatedChunksHash;//done mohsen |
| 84 using IntegrityCheckTransform::ComputeAggregatedBlocksHash;//done mohsen |
| 85 using IntegrityCheckTransform::PatchPivot;//done mohsen |
| 86 using IntegrityCheckTransform::PatchBlockReferencesAndSizes;//done mohsen |
| 87 using IntegrityCheckTransform::AddChunkIntegrityCheckCode;//done mohsen |
| 88 using IntegrityCheckTransform::AddIntegrityCheckCode;//done mohsen |
| 89 using IntegrityCheckTransform::ComputeChunks;//done mohsen |
| 90 using IntegrityCheckTransform::AddChunkIntoIndexMap;//done mohsen |
| 91 using IntegrityCheckTransform::GenerateChunkCombinations;//mohsen |
| 92 using IntegrityCheckTransform::GetChunkUniqueKey;//done mohsen |
| 93 using IntegrityCheckTransform::PrecomputeHash; |
| 94 using IntegrityCheckTransform::IsIdInPartitionUnitMap; |
| 95 using IntegrityCheckTransform::GenerateLabelToBlockMap; |
| 96 using IntegrityCheckTransform::UpdateLabelToBlockMap; |
| 97 using IntegrityCheckTransform::PopulatePartitionKey; |
| 98 using IntegrityCheckTransform::AllBasicBlocksChecked; |
| 99 using IntegrityCheckTransform::IsBogusBlock; |
| 100 using IntegrityCheckTransform::PopulateCheckMaps; |
| 101 using IntegrityCheckTransform::RandomlySelectChecker; |
| 102 using IntegrityCheckTransform::AddReference; |
| 103 using IntegrityCheckTransform::GetBasicBlockIdByLabel; |
| 104 using IntegrityCheckTransform::TransformBasicBlockSubGraph; |
| 105 using IntegrityCheckTransform::ProcessAllBlocks; |
| 106 using IntegrityCheckTransform::GenerateBasicBlockCombinations; |
| 107 using IntegrityCheckTransform::ShouldProcessBlock; |
| 108 using IntegrityCheckTransform::TransformBlockGraph; |
| 109 |
| 110 TestIntegrityCheckTransform() |
| 111 : IntegrityCheckTransform(std::set<std::string>(),1.0f) { |
| 112 } |
| 113 |
| 114 void ResetTransform(); |
| 115 |
| 116 }; |
| 117 |
| 118 |
| 119 |
| 120 |
| 121 // Cleans state of the IntegrityCheckTransform |
| 122 void TestIntegrityCheckTransform::ResetTransform() { |
| 123 this->hash_block_ = NULL; |
| 124 this->xhash_block_ = NULL; |
| 125 this->response_block_ = NULL; |
| 126 this->nr_hashes_patched_ = 0; |
| 127 this->nr_pc_relative_refs_ = 0; |
| 128 this->num_chunks_per_block = 0; |
| 129 this->chunk_checking_coverage = 0; |
| 130 this->label_name_to_block_.clear(); |
| 131 this->dll_id_to_block_reference_.clear(); |
| 132 this->adjust_label_by_offset_.clear(); |
| 133 this->target_names_.clear(); |
| 134 this->subgraph_vector_.clear(); |
| 135 this->checker_to_checkee_map_.clear(); |
| 136 this->is_bb_checked_map_.clear(); |
| 137 this->basic_block_has_ref_.clear(); |
| 138 this->basic_block_sizes_.clear(); |
| 139 this->precomputed_hashes_.clear(); |
| 140 this->partition_map_.clear(); |
| 141 this->partition_unit_map_.clear(); |
| 142 this->id_to_label_.clear(); |
| 143 this->ic_block_reference_free_chunks.clear(); |
| 144 this->ic_block_chunk_index_map_.clear(); |
| 145 this->ic_chunk_checker_to_checkee_map_.clear(); |
| 146 } |
| 147 |
| 148 class IntegrityCheckTransformTest : public testing::TestDllTransformTest { |
| 149 protected: |
| 150 TestIntegrityCheckTransform tx_; |
| 151 //static int *x; |
| 152 static void SetUpTestCase(){ |
| 153 //x = new int[10]; |
| 154 } |
| 155 static void TearDownTestCase(){ |
| 156 // delete x; |
| 157 } |
| 158 }; |
| 159 |
| 160 } // namespace |
| 161 |
| 162 TEST_F(IntegrityCheckTransformTest, CheckIsIdInParitionUnitMap) { |
| 163 ASSERT_FALSE(tx_.IsIdInPartitionUnitMap(0)); |
| 164 ASSERT_FALSE(tx_.IsIdInPartitionUnitMap(125)); |
| 165 |
| 166 std::set<uint64> st; |
| 167 st.insert(125); |
| 168 std::pair<int, std::set<uint64>> x(0, st); |
| 169 tx_.partition_unit_map_.insert(x); |
| 170 |
| 171 ASSERT_TRUE(tx_.IsIdInPartitionUnitMap(125)); |
| 172 ASSERT_FALSE(tx_.IsIdInPartitionUnitMap(123)); |
| 173 |
| 174 tx_.partition_unit_map_.erase(tx_.partition_unit_map_.find(0)); |
| 175 ASSERT_FALSE(tx_.IsIdInPartitionUnitMap(125)); |
| 176 |
| 177 tx_.ResetTransform(); |
| 178 } |
| 179 |
| 180 |
| 181 TEST_F(IntegrityCheckTransformTest, CheckGenerateLabelToBlockMap) { |
| 182 BlockGraph *bgraph = NULL; |
| 183 BlockGraph::Block *test_block_a = NULL; |
| 184 BlockGraph::Block *test_block_b = NULL; |
| 185 BlockGraph::Block *test_block_c = NULL; |
| 186 |
| 187 bgraph = new BlockGraph(); |
| 188 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "sample a"); |
| 189 test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "sample b"); |
| 190 test_block_c = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "sample c"); |
| 191 test_block_a->SetLabel(10, BlockGraph::Label("test a", BlockGraph::CODE_LABEL)
); |
| 192 test_block_b->SetLabel(20, BlockGraph::Label("test b", BlockGraph::CODE_LABEL)
); |
| 193 test_block_c->SetLabel(500, BlockGraph::Label("test c", BlockGraph::CODE_LABEL
)); |
| 194 |
| 195 tx_.GenerateLabelToBlockMap(bgraph); |
| 196 // Check for presence and value |
| 197 auto res = tx_.label_name_to_block_.find("test a"); |
| 198 ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
| 199 ASSERT_TRUE(res->second.first == test_block_a); |
| 200 res = tx_.label_name_to_block_.find("test b"); |
| 201 ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
| 202 ASSERT_TRUE(res->second.first == test_block_b); |
| 203 res = tx_.label_name_to_block_.find("test c"); |
| 204 ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
| 205 ASSERT_TRUE(res->second.first == test_block_c); |
| 206 |
| 207 res = tx_.label_name_to_block_.find("test d"); |
| 208 ASSERT_TRUE(res == tx_.label_name_to_block_.end()); |
| 209 |
| 210 tx_.ResetTransform(); |
| 211 delete bgraph; |
| 212 } |
| 213 |
| 214 TEST_F(IntegrityCheckTransformTest, CheckUpdateLabelToBlockMap) { |
| 215 BlockGraph *bgraph = NULL; |
| 216 BlockGraph::Block *test_block = NULL; |
| 217 |
| 218 bgraph = new BlockGraph(); |
| 219 test_block = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "sample"); |
| 220 test_block->SetLabel(10, BlockGraph::Label("test a", BlockGraph::CODE_LABEL)); |
| 221 test_block->SetLabel(20, BlockGraph::Label("test b", BlockGraph::CODE_LABEL)); |
| 222 test_block->SetLabel(500, BlockGraph::Label("test c", BlockGraph::CODE_LABEL))
; |
| 223 |
| 224 tx_.UpdateLabelToBlockMap(test_block); |
| 225 |
| 226 // Check for presence and value |
| 227 auto res = tx_.label_name_to_block_.find("test a"); |
| 228 ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
| 229 ASSERT_TRUE(res->second.first == test_block); |
| 230 res = tx_.label_name_to_block_.find("test b"); |
| 231 ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
| 232 ASSERT_TRUE(res->second.first == test_block); |
| 233 res = tx_.label_name_to_block_.find("test c"); |
| 234 ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
| 235 ASSERT_TRUE(res->second.first == test_block); |
| 236 |
| 237 res = tx_.label_name_to_block_.find("test d"); |
| 238 ASSERT_TRUE(res == tx_.label_name_to_block_.end()); |
| 239 |
| 240 tx_.ResetTransform(); |
| 241 delete bgraph; |
| 242 } |
| 243 |
| 244 TEST_F(IntegrityCheckTransformTest, CheckAllBasicBlocksChecked) { |
| 245 std::set<uint64> test_set; |
| 246 test_set.insert(0); |
| 247 |
| 248 std::map<std::set<uint64>, int> check_order; |
| 249 check_order.insert(std::pair<std::set<uint64>, int>(test_set, 0)); |
| 250 |
| 251 ASSERT_TRUE(tx_.is_bb_checked_map_[0] == 0); |
| 252 ASSERT_TRUE(tx_.AllBasicBlocksChecked(check_order) == false); |
| 253 |
| 254 tx_.is_bb_checked_map_.insert(std::pair<uint64, int > (0, 1)); |
| 255 ASSERT_FALSE(tx_.AllBasicBlocksChecked(check_order) == true); |
| 256 |
| 257 tx_.ResetTransform(); |
| 258 } |
| 259 |
| 260 TEST_F(IntegrityCheckTransformTest, CheckPopulateCheckMaps) { |
| 261 // TODO: Understand how it works |
| 262 } |
| 263 |
| 264 TEST_F(IntegrityCheckTransformTest, CheckIsBogusBlock) { |
| 265 BlockGraph *bgraph = new BlockGraph(); |
| 266 BlockGraph::Block *test_block = NULL; |
| 267 test_block = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "sample a"); |
| 268 |
| 269 ASSERT_FALSE(tx_.IsBogusBlock(test_block)); |
| 270 |
| 271 std::set<uint64> test_set; |
| 272 test_set.insert(test_block->id()); |
| 273 std::pair<int, std::set<uint64>> x(0, test_set); |
| 274 tx_.partition_unit_map_.insert(x); |
| 275 |
| 276 ASSERT_TRUE(tx_.IsBogusBlock(test_block)); |
| 277 |
| 278 tx_.ResetTransform(); |
| 279 delete bgraph; |
| 280 } |
| 281 |
| 282 TEST_F(IntegrityCheckTransformTest, CheckPatchBlockReference) { |
| 283 BlockGraph *bgraph = NULL; |
| 284 BlockGraph::Block *test_block_a = NULL; |
| 285 BlockGraph::Block *test_block_b = NULL; |
| 286 BlockGraph::Block *test_block_c = NULL; |
| 287 |
| 288 bgraph = new BlockGraph(); |
| 289 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
| 290 test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_b"); |
| 291 test_block_c = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "code_block"); |
| 292 |
| 293 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 294 subgraph->set_original_block(test_block_c); |
| 295 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 296 0x60000000); |
| 297 |
| 298 subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
| 299 BlockGraph::CODE_BLOCK, |
| 300 code_section->id(), 1, 0); |
| 301 |
| 302 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
| 303 auto inst_iter = bb->instructions().begin(); |
| 304 block_graph::BasicBlockAssembler assm(inst_iter, |
| 305 &bb->instructions()); |
| 306 |
| 307 int original_offset = 100; |
| 308 int label_offset = 10; |
| 309 assm.push(block_graph::Operand(block_graph::Displacement(test_block_a, |
| 310 original_offset))); |
| 311 |
| 312 // Insert the label and update label_name_to_block_ |
| 313 test_block_b->SetLabel(label_offset, |
| 314 BlockGraph::Label("Test Label", |
| 315 BlockGraph::CODE_LABEL)); |
| 316 auto lab_it(test_block_b->labels().begin()); |
| 317 tx_.label_name_to_block_[lab_it->second.name()] = |
| 318 std::make_pair(test_block_b, lab_it->first); |
| 319 |
| 320 // Prepare parameters for calling PatchBlockReference |
| 321 auto label_to_block_it = tx_.label_name_to_block_.find(lab_it->second.name()); |
| 322 CHECK(label_to_block_it != tx_.label_name_to_block_.end()); |
| 323 auto reference_free_block = label_to_block_it->second.first; |
| 324 uint32 new_bb_ref_offset = label_to_block_it->second.second; |
| 325 int intermediate_offset = 150; |
| 326 |
| 327 // Check initial offset and reference |
| 328 inst_iter = bb->instructions().begin(); |
| 329 Instruction::BasicBlockReferenceMap &ref_block_map = |
| 330 inst_iter->references(); |
| 331 auto instruction_references_it = ref_block_map.begin(); |
| 332 BlockGraph::Offset reference_offset = |
| 333 instruction_references_it->first; |
| 334 block_graph::BasicBlockReference old_bb_ref = |
| 335 instruction_references_it->second; |
| 336 ASSERT_TRUE(old_bb_ref.block() == test_block_a); |
| 337 ASSERT_TRUE(old_bb_ref.offset() == original_offset); |
| 338 |
| 339 // Patch the instruction without changing the block |
| 340 tx_.PatchBlockReference(inst_iter, reference_free_block, |
| 341 intermediate_offset, false); |
| 342 |
| 343 // Check the modifications |
| 344 instruction_references_it = inst_iter->references().begin(); |
| 345 reference_offset = instruction_references_it->first; |
| 346 block_graph::BasicBlockReference new_bb_ref = |
| 347 instruction_references_it->second; |
| 348 |
| 349 ASSERT_TRUE(new_bb_ref.block() == test_block_a); |
| 350 ASSERT_TRUE(new_bb_ref.offset() == intermediate_offset); |
| 351 |
| 352 // Patch the instruction including changing the block |
| 353 tx_.PatchBlockReference(inst_iter, reference_free_block, |
| 354 new_bb_ref_offset, true); |
| 355 |
| 356 instruction_references_it = inst_iter->references().begin(); |
| 357 reference_offset = instruction_references_it->first; |
| 358 new_bb_ref = instruction_references_it->second; |
| 359 |
| 360 ASSERT_TRUE(new_bb_ref.block() == test_block_b); |
| 361 ASSERT_TRUE((uint32)new_bb_ref.offset() == new_bb_ref_offset); |
| 362 |
| 363 tx_.ResetTransform(); |
| 364 delete bgraph; |
| 365 delete subgraph; |
| 366 } |
| 367 |
| 368 TEST_F(IntegrityCheckTransformTest, CheckCheckHash) { |
| 369 BlockGraph *bgraph = new BlockGraph(); |
| 370 BlockGraph::Block *test_block_b = NULL; |
| 371 test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 2000, "sample b"); |
| 372 base::StringPiece test_block_tag = "1"; |
| 373 auto test_block_label = block_graph::BlockGraph::Label( |
| 374 test_block_tag, |
| 375 BlockGraph::CODE_LABEL); |
| 376 uint64 test_block_id = 1; |
| 377 uint32 test_block_size = 1; |
| 378 // push eax equals to 0x50 |
| 379 uint8 test_block_value = 0x50; |
| 380 //prepare id to label map |
| 381 tx_.id_to_label_[test_block_id] = test_block_label; |
| 382 //set the size |
| 383 tx_.basic_block_sizes_[test_block_id] = test_block_size; |
| 384 |
| 385 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 386 subgraph->set_original_block(test_block_b); |
| 387 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 388 0x60000000); |
| 389 |
| 390 subgraph->AddBlockDescription("sample c", code_section->name(), |
| 391 BlockGraph::CODE_BLOCK, |
| 392 code_section->id(), 1, 0); |
| 393 |
| 394 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("sample b"); |
| 395 |
| 396 auto inst_iter = bb->instructions().begin(); |
| 397 block_graph::BasicBlockAssembler assm(inst_iter, |
| 398 &bb->instructions()); |
| 399 |
| 400 assm.push(assm::eax); |
| 401 //add label to the block |
| 402 auto instr = bb->instructions().begin(); |
| 403 instr->set_label(test_block_label); |
| 404 |
| 405 |
| 406 std::vector<uint8> test_buffer; |
| 407 test_buffer.insert(test_buffer.begin(), test_block_value); |
| 408 //offset in the test buffer |
| 409 bb->set_offset(0); |
| 410 tx_.CheckHash(bb, test_buffer); |
| 411 |
| 412 //we should have a hash computed for this block |
| 413 ASSERT_TRUE(tx_.precomputed_hashes_[test_block_id] == test_block_value); |
| 414 |
| 415 tx_.ResetTransform(); |
| 416 delete bgraph; |
| 417 delete subgraph; |
| 418 } |
| 419 |
| 420 TEST_F(IntegrityCheckTransformTest, CheckFixPrecomputedHashes) { |
| 421 //what the hell to test here! |
| 422 } |
| 423 |
| 424 TEST_F(IntegrityCheckTransformTest, CheckRecomputeXorChunks){ |
| 425 uint64 test_block_id = 1; |
| 426 uint8 test_old_size[1] = { 1 }; |
| 427 uint8 test_new_size[1] = { 2 }; |
| 428 uint64 test_chunk_bb_id = 1; |
| 429 uint32 test_chunk_index = 0; |
| 430 uint32 test_chunk_size = 1; |
| 431 uint8 test_chunk_hash = 0x50; |
| 432 //new hash = old hash ^ old_size ^ new_size |
| 433 uint8 test_chunk_new_hash = 0x53; |
| 434 |
| 435 uint64 test_vector_index = 0; |
| 436 tx_.ic_block_chunk_index_map_[tx_.GetChunkUniqueKey(test_chunk_bb_id, |
| 437 test_chunk_index)] = |
| 438 test_vector_index; |
| 439 |
| 440 ChunkInfo test_chunk(test_chunk_bb_id,test_chunk_size, |
| 441 test_chunk_hash, test_chunk_index,0); |
| 442 tx_.ic_block_reference_free_chunks.insert( |
| 443 tx_.ic_block_reference_free_chunks.begin(), test_chunk); |
| 444 |
| 445 tx_.RecomputeXorChunks(test_block_id, test_old_size, test_new_size, |
| 446 test_chunk_bb_id, test_chunk_index); |
| 447 |
| 448 //we should have a hash computed for this block |
| 449 auto updated_chunk = tx_.ic_block_reference_free_chunks[test_vector_index]; |
| 450 |
| 451 ASSERT_EQ(updated_chunk.hash_,test_chunk_new_hash); |
| 452 |
| 453 tx_.ResetTransform(); |
| 454 } |
| 455 TEST_F(IntegrityCheckTransformTest, CheckGetHashBlock) { |
| 456 ASSERT_TRUE(tx_.GetHashBlock()==NULL); |
| 457 } |
| 458 TEST_F(IntegrityCheckTransformTest, CheckSetHashBlock) { |
| 459 BlockGraph *bgraph = NULL; |
| 460 BlockGraph::Block *test_block_a = NULL; |
| 461 |
| 462 bgraph = new BlockGraph(); |
| 463 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
| 464 |
| 465 tx_.SetHashBlock(test_block_a); |
| 466 auto ret_block = tx_.GetHashBlock(); |
| 467 ASSERT_TRUE(ret_block == test_block_a); |
| 468 tx_.ResetTransform(); |
| 469 delete bgraph; |
| 470 } |
| 471 |
| 472 |
| 473 TEST_F(IntegrityCheckTransformTest, CheckRecomputePivot){ |
| 474 BlockGraph *bgraph = new BlockGraph(); |
| 475 BlockGraph::Block *test_block_b = NULL; |
| 476 test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 2000, "sample b"); |
| 477 uint8 old_hash = 0x1; |
| 478 // push eax, pivot, sub al, old hash |
| 479 uint8 test_block_data[5] = { 0x50, 0x0, 0x2c, old_hash }; |
| 480 |
| 481 test_block_b->SetData(test_block_data, sizeof(test_block_data)); |
| 482 |
| 483 |
| 484 uint64 test_block_id = 1; |
| 485 uint8 test_precomputed_hash = 0x7c; |
| 486 uint8 test_precomputed_xor = 1; |
| 487 uint32 test_pivot_offset = 1; |
| 488 uint32 test_sub_offset = 2; |
| 489 tx_.RecomputePivot(test_block_id, test_precomputed_hash, test_precomputed_xor, |
| 490 test_pivot_offset, test_sub_offset, test_block_b); |
| 491 // pivot + new hash = old hash |
| 492 uint8 hash_diff = test_block_b->data()[test_pivot_offset] + |
| 493 test_block_b->data()[test_sub_offset + 1]; |
| 494 bool is_pivot_correct = hash_diff == old_hash; |
| 495 |
| 496 ASSERT_TRUE(is_pivot_correct); |
| 497 delete bgraph; |
| 498 |
| 499 } |
| 500 |
| 501 TEST_F(IntegrityCheckTransformTest, CheckComputeAggregatedBlocksHash){ |
| 502 uint64 test_bb_id = 1; |
| 503 std::map<uint64, int> test_checkee_map; |
| 504 test_checkee_map[2] = 1; |
| 505 test_checkee_map[3] = -1; |
| 506 tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
| 507 tx_.precomputed_hashes_[2] = 0x20; |
| 508 tx_.precomputed_hashes_[3] = 0x10; |
| 509 uint8 computed_hash = tx_.ComputeAggregatedBlocksHash(test_bb_id); |
| 510 ASSERT_EQ(0x10, computed_hash); |
| 511 |
| 512 tx_.ResetTransform(); |
| 513 } |
| 514 TEST_F(IntegrityCheckTransformTest, CheckComputeAggregatedChunksHash){ |
| 515 uint8 hash1 = 0x1; |
| 516 uint8 hash2 = 0x2; |
| 517 tx_.ic_block_reference_free_chunks.insert( |
| 518 tx_.ic_block_reference_free_chunks.begin(), ChunkInfo(1, 1, hash1, 0, 0)); |
| 519 tx_.ic_block_reference_free_chunks.insert( |
| 520 tx_.ic_block_reference_free_chunks.begin(), ChunkInfo(1, 1, hash2, 0, 0)); |
| 521 std::set<uint32> test_chunk_index_set; |
| 522 test_chunk_index_set.insert(0); |
| 523 test_chunk_index_set.insert(1); |
| 524 uint8 computed_hash = tx_.ComputeAggregatedChunksHash(test_chunk_index_set); |
| 525 ASSERT_EQ(0x3, computed_hash); |
| 526 |
| 527 tx_.ResetTransform(); |
| 528 } |
| 529 |
| 530 TEST_F(IntegrityCheckTransformTest, CheckPatchPivot){ |
| 531 BlockGraph *bgraph = new BlockGraph(); |
| 532 BlockGraph::Block *test_block_b = NULL; |
| 533 test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 2000, "sample b"); |
| 534 base::StringPiece test_block_tag = "1"; |
| 535 auto test_block_label = block_graph::BlockGraph::Label( |
| 536 test_block_tag, |
| 537 BlockGraph::CODE_LABEL); |
| 538 uint64 test_block_id = 1; |
| 539 uint32 test_block_size = 1; |
| 540 //prepare id to label map |
| 541 tx_.id_to_label_[test_block_id] = test_block_label; |
| 542 //set the size |
| 543 tx_.basic_block_sizes_[test_block_id] = test_block_size; |
| 544 |
| 545 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 546 subgraph->set_original_block(test_block_b); |
| 547 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 548 0x60000000); |
| 549 |
| 550 subgraph->AddBlockDescription("sample c", code_section->name(), |
| 551 BlockGraph::CODE_BLOCK, |
| 552 code_section->id(), 1, 0); |
| 553 |
| 554 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("sample b"); |
| 555 |
| 556 auto inst_iter = bb->instructions().begin(); |
| 557 block_graph::BasicBlockAssembler assm(inst_iter, |
| 558 &bb->instructions()); |
| 559 |
| 560 uint8 old_hash = 0x1; |
| 561 |
| 562 assm.push(assm::eax); |
| 563 assm.data(0); |
| 564 assm.sub(assm::al,block_graph::Immediate(old_hash, |
| 565 assm::ValueSize::kSize8Bit)); |
| 566 //add labels to the block |
| 567 auto instr = bb->instructions().begin(); |
| 568 instr->set_label(test_block_label); |
| 569 uint32 test_pivot_offset = 1; |
| 570 uint32 test_sub_offset = 2; |
| 571 uint32 test_hash_offset = 3; |
| 572 tx_.label_name_to_block_["Pivot:1"] = std::make_pair(test_block_b, |
| 573 test_pivot_offset); |
| 574 tx_.label_name_to_block_["sub 1"] = std::make_pair(test_block_b, |
| 575 test_sub_offset); |
| 576 |
| 577 uint64 test_bb_id = 1; |
| 578 std::map<uint64, int> test_checkee_map; |
| 579 test_checkee_map[2] = 1; |
| 580 test_checkee_map[3] = -1; |
| 581 tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
| 582 tx_.precomputed_hashes_[2] = 0x20; |
| 583 tx_.precomputed_hashes_[3] = 0x10; |
| 584 |
| 585 |
| 586 uint8 hash1 = 0x1; |
| 587 uint8 hash2 = 0x2; |
| 588 tx_.ic_block_reference_free_chunks.insert( |
| 589 tx_.ic_block_reference_free_chunks.begin(), ChunkInfo(1, 1, hash1, 0, 0)); |
| 590 tx_.ic_block_reference_free_chunks.insert( |
| 591 tx_.ic_block_reference_free_chunks.begin(), ChunkInfo(1, 1, hash2, 0, 0)); |
| 592 std::set<uint32> test_chunk_index_set; |
| 593 test_chunk_index_set.insert(0); |
| 594 test_chunk_index_set.insert(1); |
| 595 tx_.ic_chunk_checker_to_checkee_map_[test_bb_id] = test_chunk_index_set; |
| 596 |
| 597 |
| 598 // push eax, pivot, sub al, old hash |
| 599 uint8 test_block_data[5] = { 0x50, 0x0, 0x2c, old_hash }; |
| 600 |
| 601 test_block_b->SetData(test_block_data, sizeof(test_block_data)); |
| 602 |
| 603 |
| 604 FILE *file=NULL; |
| 605 tx_.PatchPivot(bb, subgraph, bgraph, file); |
| 606 |
| 607 //hash = precomputed sum + precomputed xor |
| 608 //hash = 0x10 + 0x3 |
| 609 ASSERT_EQ(test_block_b->data()[test_hash_offset], 0x13); |
| 610 |
| 611 uint8 hash_diff = test_block_b->data()[test_pivot_offset] + |
| 612 test_block_b->data()[test_hash_offset]; |
| 613 bool is_pivot_correct = hash_diff == old_hash; |
| 614 |
| 615 ASSERT_TRUE(is_pivot_correct); |
| 616 |
| 617 tx_.ResetTransform(); |
| 618 |
| 619 delete bgraph; |
| 620 delete subgraph; |
| 621 } |
| 622 |
| 623 TEST_F(IntegrityCheckTransformTest, CheckPatchSizesByLabel){ |
| 624 BlockGraph *bgraph = new BlockGraph(); |
| 625 BlockGraph::Block *test_block_b = NULL; |
| 626 test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 2000, "sample b"); |
| 627 base::StringPiece test_block_tag = "1"; |
| 628 auto test_block_label = block_graph::BlockGraph::Label( |
| 629 test_block_tag, |
| 630 BlockGraph::CODE_LABEL); |
| 631 uint64 test_block_id = 1; |
| 632 uint32 test_block_size = 1; |
| 633 //prepare id to label map |
| 634 tx_.id_to_label_[test_block_id] = test_block_label; |
| 635 //set the size |
| 636 tx_.basic_block_sizes_[test_block_id] = test_block_size; |
| 637 |
| 638 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 639 subgraph->set_original_block(test_block_b); |
| 640 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 641 0x60000000); |
| 642 |
| 643 subgraph->AddBlockDescription("sample c", code_section->name(), |
| 644 BlockGraph::CODE_BLOCK, |
| 645 code_section->id(), 1, 0); |
| 646 |
| 647 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("sample b"); |
| 648 |
| 649 auto inst_iter = bb->instructions().begin(); |
| 650 block_graph::BasicBlockAssembler assm(inst_iter, |
| 651 &bb->instructions()); |
| 652 |
| 653 uint32 test_old_block_size = 0x10; |
| 654 uint32 test_new_block_size = 0x11; |
| 655 uint64 test_reference_block_id = 2; |
| 656 assm.push(assm::eax); |
| 657 assm.push(block_graph::Immediate(test_old_block_size, assm::kSize32Bit)); |
| 658 |
| 659 |
| 660 inst_iter = bb->instructions().begin(); |
| 661 //set chunk finger label |
| 662 inst_iter->set_label(block_graph::BlockGraph::Label("n 1 0", |
| 663 BlockGraph::CODE_LABEL)); |
| 664 ++inst_iter; |
| 665 inst_iter->set_label(block_graph::BlockGraph::Label("size 2 1", |
| 666 BlockGraph::CODE_LABEL)); |
| 667 tx_.basic_block_sizes_[test_reference_block_id] = test_new_block_size; |
| 668 |
| 669 uint64 test_chunk_bb_id = 1; |
| 670 uint32 test_chunk_index = 0; |
| 671 uint32 test_chunk_size = 1; |
| 672 uint8 test_chunk_hash = 0x50; |
| 673 |
| 674 |
| 675 uint64 test_vector_index = 0; |
| 676 tx_.ic_block_chunk_index_map_[tx_.GetChunkUniqueKey(test_chunk_bb_id, |
| 677 test_chunk_index)] = |
| 678 test_vector_index; |
| 679 |
| 680 ChunkInfo test_chunk(test_chunk_bb_id, test_chunk_size, |
| 681 test_chunk_hash, test_chunk_index, 0); |
| 682 tx_.ic_block_reference_free_chunks.insert( |
| 683 tx_.ic_block_reference_free_chunks.begin(), test_chunk); |
| 684 |
| 685 tx_.PatchBlockReferencesAndSizes(bb, subgraph, bgraph); |
| 686 ASSERT_EQ(inst_iter->data()[1], test_new_block_size); |
| 687 |
| 688 tx_.ResetTransform(); |
| 689 delete bgraph; |
| 690 delete subgraph; |
| 691 |
| 692 } |
| 693 |
| 694 TEST_F(IntegrityCheckTransformTest, CheckPatchBlockReferenceByLabel) { |
| 695 BlockGraph *bgraph = NULL; |
| 696 BlockGraph::Block *test_block_a = NULL; |
| 697 |
| 698 bgraph = new BlockGraph(); |
| 699 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
| 700 |
| 701 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 702 subgraph->set_original_block(test_block_a); |
| 703 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 704 0x60000000); |
| 705 |
| 706 subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
| 707 BlockGraph::CODE_BLOCK, |
| 708 code_section->id(), 1, 0); |
| 709 |
| 710 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
| 711 auto inst_iter = bb->instructions().begin(); |
| 712 block_graph::BasicBlockAssembler assm(inst_iter, |
| 713 &bb->instructions()); |
| 714 |
| 715 int original_offset = 100; |
| 716 assm.push(block_graph::Immediate(test_block_a, original_offset)); |
| 717 inst_iter = bb->instructions().begin(); |
| 718 inst_iter->set_label(BlockGraph::Label("block 2", |
| 719 BlockGraph::CODE_LABEL)); |
| 720 int intermediate_offset = 150; |
| 721 |
| 722 //move block offset |
| 723 tx_.label_name_to_block_["2"] = |
| 724 std::make_pair(test_block_a, intermediate_offset); |
| 725 |
| 726 // Check initial offset and reference |
| 727 inst_iter = bb->instructions().begin(); |
| 728 Instruction::BasicBlockReferenceMap &ref_block_map = |
| 729 inst_iter->references(); |
| 730 auto instruction_references_it = ref_block_map.begin(); |
| 731 BlockGraph::Offset reference_offset = instruction_references_it->first; |
| 732 block_graph::BasicBlockReference old_bb_ref = |
| 733 instruction_references_it->second; |
| 734 ASSERT_TRUE(old_bb_ref.block() == test_block_a); |
| 735 ASSERT_TRUE(old_bb_ref.offset() == original_offset); |
| 736 |
| 737 |
| 738 |
| 739 tx_.PatchBlockReferencesAndSizes(bb, subgraph, bgraph); |
| 740 |
| 741 inst_iter = bb->instructions().begin(); |
| 742 // Check the modifications |
| 743 instruction_references_it = inst_iter->references().begin(); |
| 744 reference_offset = instruction_references_it->first; |
| 745 block_graph::BasicBlockReference new_bb_ref = |
| 746 instruction_references_it->second; |
| 747 |
| 748 ASSERT_TRUE(new_bb_ref.block() == test_block_a); |
| 749 ASSERT_TRUE(new_bb_ref.offset() == intermediate_offset); |
| 750 } |
| 751 |
| 752 TEST_F(IntegrityCheckTransformTest, CheckPatchChunkReferenceByLabel) { |
| 753 BlockGraph *bgraph = NULL; |
| 754 BlockGraph::Block *test_block_a = NULL; |
| 755 |
| 756 bgraph = new BlockGraph(); |
| 757 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
| 758 |
| 759 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 760 subgraph->set_original_block(test_block_a); |
| 761 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 762 0x60000000); |
| 763 |
| 764 subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
| 765 BlockGraph::CODE_BLOCK, |
| 766 code_section->id(), 1, 0); |
| 767 |
| 768 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
| 769 auto inst_iter = bb->instructions().begin(); |
| 770 block_graph::BasicBlockAssembler assm(inst_iter, |
| 771 &bb->instructions()); |
| 772 |
| 773 int original_offset = 100; |
| 774 assm.push(block_graph::Immediate(test_block_a, original_offset)); |
| 775 inst_iter = bb->instructions().begin(); |
| 776 inst_iter->set_label(BlockGraph::Label("nrc 2 0", |
| 777 BlockGraph::CODE_LABEL)); |
| 778 int intermediate_offset = 150; |
| 779 |
| 780 //move block offset |
| 781 tx_.label_name_to_block_["n 2 0"] = |
| 782 std::make_pair(test_block_a, intermediate_offset); |
| 783 |
| 784 // Check initial offset and reference |
| 785 inst_iter = bb->instructions().begin(); |
| 786 Instruction::BasicBlockReferenceMap &ref_block_map = |
| 787 inst_iter->references(); |
| 788 auto instruction_references_it = ref_block_map.begin(); |
| 789 BlockGraph::Offset reference_offset = instruction_references_it->first; |
| 790 block_graph::BasicBlockReference old_bb_ref = |
| 791 instruction_references_it->second; |
| 792 ASSERT_TRUE(old_bb_ref.block() == test_block_a); |
| 793 ASSERT_TRUE(old_bb_ref.offset() == original_offset); |
| 794 |
| 795 |
| 796 |
| 797 tx_.PatchBlockReferencesAndSizes(bb, subgraph, bgraph); |
| 798 |
| 799 inst_iter = bb->instructions().begin(); |
| 800 // Check the modifications |
| 801 instruction_references_it = inst_iter->references().begin(); |
| 802 reference_offset = instruction_references_it->first; |
| 803 block_graph::BasicBlockReference new_bb_ref = |
| 804 instruction_references_it->second; |
| 805 |
| 806 ASSERT_TRUE(new_bb_ref.block() == test_block_a); |
| 807 ASSERT_TRUE(new_bb_ref.offset() == intermediate_offset); |
| 808 } |
| 809 TEST_F(IntegrityCheckTransformTest, CheckAddChunkIntegrityCheckCode) { |
| 810 |
| 811 uint64 test_bb_id = 1; |
| 812 //set total chunks |
| 813 tx_.num_chunks_per_block = 10; |
| 814 |
| 815 BlockGraph *bgraph = NULL; |
| 816 BlockGraph::Block *test_block_a = NULL; |
| 817 |
| 818 bgraph = new BlockGraph(); |
| 819 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
| 820 |
| 821 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 822 subgraph->set_original_block(test_block_a); |
| 823 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 824 0x60000000); |
| 825 |
| 826 subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
| 827 BlockGraph::CODE_BLOCK, |
| 828 code_section->id(), 1, 0); |
| 829 |
| 830 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
| 831 auto inst_iter = bb->instructions().begin(); |
| 832 block_graph::BasicBlockAssembler assm(inst_iter, |
| 833 &bb->instructions()); |
| 834 |
| 835 assm.push(assm::eax); |
| 836 inst_iter = bb->instructions().begin(); |
| 837 //set block id label |
| 838 auto test_block_label = BlockGraph::Label(std::to_string(test_bb_id), |
| 839 BlockGraph::CODE_LABEL); |
| 840 inst_iter->set_label(test_block_label); |
| 841 //set a dummy hash block |
| 842 tx_.xhash_block_ = test_block_a; |
| 843 |
| 844 //prepare id to label map |
| 845 tx_.id_to_label_[test_bb_id] = test_block_label; |
| 846 //set block size |
| 847 uint32 old_size = inst_iter->size(); |
| 848 tx_.basic_block_sizes_[test_bb_id] = old_size; |
| 849 |
| 850 //set checker checkee map |
| 851 |
| 852 std::map<uint64, int> test_checkee_map; |
| 853 test_checkee_map[2] = 1; |
| 854 test_checkee_map[3] = -1; |
| 855 tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
| 856 tx_.precomputed_hashes_[2] = 0x20; |
| 857 tx_.precomputed_hashes_[3] = 0x10; |
| 858 |
| 859 //set chunk checker map |
| 860 uint8 hash1 = 0x1; |
| 861 std::set<uint32> test_chunk_index_set; |
| 862 for (uint32 i = 0; i < tx_.num_chunks_per_block; ++i){ |
| 863 tx_.ic_block_reference_free_chunks.insert( |
| 864 tx_.ic_block_reference_free_chunks.begin(), ChunkInfo(1, 1, hash1, i,0))
; |
| 865 test_chunk_index_set.insert(i); |
| 866 char *buffersearch = new char[50]; |
| 867 sprintf_s(buffersearch, 50, "n %llu %lu", test_bb_id, i); |
| 868 tx_.label_name_to_block_[buffersearch] = std::make_pair(test_block_a, 0); |
| 869 delete[] buffersearch; |
| 870 } |
| 871 tx_.ic_chunk_checker_to_checkee_map_[test_bb_id] = test_chunk_index_set; |
| 872 |
| 873 |
| 874 tx_.AddChunkIntegrityCheckCode(bb, subgraph, bgraph); |
| 875 |
| 876 //Ensure basic_block_sizes_[bb_id] is larger than before |
| 877 ASSERT_GT(tx_.basic_block_sizes_[test_bb_id], old_size); |
| 878 //Check there are equal number of chunks and nrc labels |
| 879 inst_iter = bb->instructions().begin(); |
| 880 uint32 nr_added_labels = 0; |
| 881 std::string chunk_pointerlabel = "nrc"; |
| 882 for (; inst_iter != bb->instructions().end(); ++inst_iter){ |
| 883 if (inst_iter->label().name() |
| 884 .compare(0, chunk_pointerlabel.length(), chunk_pointerlabel) == 0){ |
| 885 ++nr_added_labels; |
| 886 } |
| 887 } |
| 888 |
| 889 //Ensure kNumChunksPerBlock == #chunks |
| 890 ASSERT_EQ(tx_.num_chunks_per_block, nr_added_labels); |
| 891 |
| 892 tx_.ResetTransform(); |
| 893 delete bgraph; |
| 894 delete subgraph; |
| 895 } |
| 896 |
| 897 TEST_F(IntegrityCheckTransformTest, CheckAddIntegrityCheckCode) { |
| 898 //check labels block, pivot, size, sub instruction |
| 899 uint64 test_bb_id = 1; |
| 900 uint64 test_checkee1_id = 2; |
| 901 uint64 test_checkee2_id = 3; |
| 902 BlockGraph *bgraph = NULL; |
| 903 BlockGraph::Block *test_block_a = NULL; |
| 904 BlockGraph::Block *test_block_b = NULL; |
| 905 |
| 906 bgraph = new BlockGraph(); |
| 907 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
| 908 test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_b"); |
| 909 |
| 910 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 911 subgraph->set_original_block(test_block_a); |
| 912 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 913 0x60000000); |
| 914 |
| 915 subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
| 916 BlockGraph::CODE_BLOCK, |
| 917 code_section->id(), 1, 0); |
| 918 |
| 919 BasicBlockSubGraph* subgraph_b = new BasicBlockSubGraph(); |
| 920 subgraph_b->set_original_block(test_block_b); |
| 921 |
| 922 subgraph_b->AddBlockDescription("test_subgraph", code_section->name(), |
| 923 BlockGraph::CODE_BLOCK, |
| 924 code_section->id(), 1, 0); |
| 925 |
| 926 |
| 927 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
| 928 auto inst_iter = bb->instructions().begin(); |
| 929 block_graph::BasicBlockAssembler assm(inst_iter, |
| 930 &bb->instructions()); |
| 931 |
| 932 assm.push(assm::eax); |
| 933 inst_iter = bb->instructions().begin(); |
| 934 //set block id label |
| 935 auto test_block_label = BlockGraph::Label(std::to_string(test_bb_id), |
| 936 BlockGraph::CODE_LABEL); |
| 937 inst_iter->set_label(test_block_label); |
| 938 //prepare id to label map |
| 939 tx_.id_to_label_[test_bb_id] = test_block_label; |
| 940 //set block id label |
| 941 auto test_checkee1_label = BlockGraph::Label(std::to_string(test_checkee1_id), |
| 942 BlockGraph::CODE_LABEL); |
| 943 tx_.id_to_label_[test_checkee1_id] = test_checkee1_label; |
| 944 tx_.label_name_to_block_[std::to_string(test_checkee1_id)] = |
| 945 std::make_pair(test_block_b, 0); |
| 946 auto test_checkee2_label = BlockGraph::Label(std::to_string(test_checkee2_id), |
| 947 BlockGraph::CODE_LABEL); |
| 948 tx_.id_to_label_[test_checkee2_id] = test_checkee2_label; |
| 949 |
| 950 tx_.label_name_to_block_[std::to_string(test_checkee2_id)] = |
| 951 std::make_pair(test_block_b, 0); |
| 952 //set a dummy hash block |
| 953 tx_.hash_block_ = test_block_a; |
| 954 //set dummy response block |
| 955 tx_.response_block_ = test_block_a; |
| 956 //set block size |
| 957 uint32 old_size = inst_iter->size(); |
| 958 tx_.basic_block_sizes_[test_bb_id] = old_size; |
| 959 tx_.basic_block_sizes_[test_checkee1_id] = 1; |
| 960 tx_.basic_block_sizes_[test_checkee2_id] = 1; |
| 961 //set checker checkee map |
| 962 |
| 963 std::map<uint64, int> test_checkee_map; |
| 964 test_checkee_map[test_checkee1_id] = 1; |
| 965 test_checkee_map[test_checkee2_id] = -1; |
| 966 tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
| 967 tx_.precomputed_hashes_[test_checkee1_id] = 0x20; |
| 968 tx_.precomputed_hashes_[test_checkee2_id] = 0x10; |
| 969 |
| 970 tx_.AddIntegrityCheckCode(bb, subgraph, bgraph); |
| 971 |
| 972 //Ensure basic_block_sizes_[bb_id] is larger than before |
| 973 ASSERT_GT(tx_.basic_block_sizes_[test_bb_id], old_size); |
| 974 //Check there are equal number of chunks and nrc labels |
| 975 inst_iter = bb->instructions().begin(); |
| 976 uint32 nr_added_block_labels = 0; |
| 977 std::string block_pointerlabel = "block"; |
| 978 uint32 nr_added_size_labels = 0; |
| 979 std::string size_pointerlabel = "size"; |
| 980 uint32 nr_added_pivot_labels = 0; |
| 981 std::string pivot_pointerlabel = "Pivot"; |
| 982 uint32 nr_added_sub_labels = 0; |
| 983 std::string sub_pointerlabel = "sub"; |
| 984 for (; inst_iter != bb->instructions().end(); ++inst_iter){ |
| 985 if (inst_iter->label().name() |
| 986 .compare(0, block_pointerlabel.length(), block_pointerlabel) == 0){ |
| 987 ++nr_added_block_labels; |
| 988 } else if (inst_iter->label().name() |
| 989 .compare(0, size_pointerlabel.length(), size_pointerlabel) == 0){ |
| 990 ++nr_added_size_labels; |
| 991 } |
| 992 else if (inst_iter->label().name().compare(0, pivot_pointerlabel.length(), |
| 993 pivot_pointerlabel) == 0){ |
| 994 ++nr_added_pivot_labels; |
| 995 } else if (inst_iter->label().name().compare(0, sub_pointerlabel.length(), |
| 996 sub_pointerlabel) == 0){ |
| 997 ++nr_added_sub_labels; |
| 998 } |
| 999 |
| 1000 } |
| 1001 |
| 1002 //Ensure kNumChunksPerBlock == #chunks |
| 1003 ASSERT_EQ(test_checkee_map.size(), nr_added_block_labels); |
| 1004 ASSERT_EQ(test_checkee_map.size(), nr_added_size_labels); |
| 1005 ASSERT_EQ(1, nr_added_pivot_labels); |
| 1006 ASSERT_EQ(1, nr_added_sub_labels); |
| 1007 |
| 1008 tx_.ResetTransform(); |
| 1009 delete bgraph; |
| 1010 delete subgraph; |
| 1011 delete subgraph_b; |
| 1012 } |
| 1013 |
| 1014 TEST_F(IntegrityCheckTransformTest, CheckComputeChunksWhenInstructionHasLabel) { |
| 1015 uint64 test_bb_id = 1; |
| 1016 BlockGraph *bgraph = NULL; |
| 1017 BlockGraph::Block *test_block_a = NULL; |
| 1018 |
| 1019 bgraph = new BlockGraph(); |
| 1020 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
| 1021 |
| 1022 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 1023 subgraph->set_original_block(test_block_a); |
| 1024 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 1025 0x60000000); |
| 1026 |
| 1027 subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
| 1028 BlockGraph::CODE_BLOCK, |
| 1029 code_section->id(), 1, 0); |
| 1030 |
| 1031 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
| 1032 auto inst_iter = bb->instructions().begin(); |
| 1033 block_graph::BasicBlockAssembler assm(inst_iter, |
| 1034 &bb->instructions()); |
| 1035 |
| 1036 assm.push(assm::eax); |
| 1037 assm.data(0); |
| 1038 |
| 1039 auto test_label = BlockGraph::Label(std::to_string(test_bb_id), |
| 1040 BlockGraph::CODE_LABEL); |
| 1041 inst_iter = bb->instructions().begin(); |
| 1042 inst_iter->set_label(test_label); |
| 1043 //Every checker comes with a pivot |
| 1044 ++inst_iter; |
| 1045 inst_iter->set_label(BlockGraph::Label("Pivot:", |
| 1046 BlockGraph::CODE_LABEL)); |
| 1047 |
| 1048 tx_.id_to_label_[test_bb_id] = test_label; |
| 1049 |
| 1050 //make the block a checker |
| 1051 |
| 1052 uint64 test_checkee1_id = 2; |
| 1053 uint64 test_checkee2_id = 3; |
| 1054 std::map<uint64, int> test_checkee_map; |
| 1055 test_checkee_map[test_checkee1_id] = 1; |
| 1056 test_checkee_map[test_checkee2_id] = -1; |
| 1057 tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
| 1058 tx_.precomputed_hashes_[test_checkee1_id] = 0x20; |
| 1059 tx_.precomputed_hashes_[test_checkee2_id] = 0x10; |
| 1060 |
| 1061 |
| 1062 tx_.ComputeChunks(bb); |
| 1063 |
| 1064 //on instructions with label don't set chunk label |
| 1065 ASSERT_EQ(0, tx_.ic_block_reference_free_chunks.size()); |
| 1066 |
| 1067 tx_.ResetTransform(); |
| 1068 delete bgraph; |
| 1069 delete subgraph; |
| 1070 } |
| 1071 TEST_F(IntegrityCheckTransformTest, CheckComputeChunksWhenLastInstruction) { |
| 1072 uint64 test_bb_id = 1; |
| 1073 BlockGraph *bgraph = NULL; |
| 1074 BlockGraph::Block *test_block_a = NULL; |
| 1075 |
| 1076 bgraph = new BlockGraph(); |
| 1077 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
| 1078 |
| 1079 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 1080 subgraph->set_original_block(test_block_a); |
| 1081 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 1082 0x60000000); |
| 1083 |
| 1084 subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
| 1085 BlockGraph::CODE_BLOCK, |
| 1086 code_section->id(), 1, 0); |
| 1087 |
| 1088 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
| 1089 auto inst_iter = bb->instructions().begin(); |
| 1090 block_graph::BasicBlockAssembler assm(inst_iter, |
| 1091 &bb->instructions()); |
| 1092 |
| 1093 assm.push(assm::eax); |
| 1094 assm.data(0); |
| 1095 assm.push(assm::ebx); |
| 1096 |
| 1097 auto test_label = BlockGraph::Label(std::to_string(test_bb_id), |
| 1098 BlockGraph::CODE_LABEL); |
| 1099 inst_iter = bb->instructions().begin(); |
| 1100 inst_iter->set_label(test_label); |
| 1101 //Every checker comes with a pivot |
| 1102 ++inst_iter; |
| 1103 inst_iter->set_label(BlockGraph::Label("Pivot:", |
| 1104 BlockGraph::CODE_LABEL)); |
| 1105 |
| 1106 tx_.id_to_label_[test_bb_id] = test_label; |
| 1107 |
| 1108 //make the block a checker |
| 1109 |
| 1110 uint64 test_checkee1_id = 2; |
| 1111 uint64 test_checkee2_id = 3; |
| 1112 std::map<uint64, int> test_checkee_map; |
| 1113 test_checkee_map[test_checkee1_id] = 1; |
| 1114 test_checkee_map[test_checkee2_id] = -1; |
| 1115 tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
| 1116 tx_.precomputed_hashes_[test_checkee1_id] = 0x20; |
| 1117 tx_.precomputed_hashes_[test_checkee2_id] = 0x10; |
| 1118 |
| 1119 |
| 1120 tx_.ComputeChunks(bb); |
| 1121 |
| 1122 //last push ebx should be recognized as a chunk |
| 1123 ASSERT_EQ(1, tx_.ic_block_reference_free_chunks.size()); |
| 1124 |
| 1125 tx_.ResetTransform(); |
| 1126 delete bgraph; |
| 1127 delete subgraph; |
| 1128 } |
| 1129 |
| 1130 TEST_F(IntegrityCheckTransformTest, CheckComputeChunksWhenAbsReferenceBetween) { |
| 1131 uint64 test_bb_id = 1; |
| 1132 BlockGraph *bgraph = NULL; |
| 1133 BlockGraph::Block *test_block_a = NULL; |
| 1134 |
| 1135 bgraph = new BlockGraph(); |
| 1136 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
| 1137 |
| 1138 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 1139 subgraph->set_original_block(test_block_a); |
| 1140 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 1141 0x60000000); |
| 1142 |
| 1143 subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
| 1144 BlockGraph::CODE_BLOCK, |
| 1145 code_section->id(), 1, 0); |
| 1146 |
| 1147 BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
| 1148 auto inst_iter = bb->instructions().begin(); |
| 1149 block_graph::BasicBlockAssembler assm(inst_iter, |
| 1150 &bb->instructions()); |
| 1151 |
| 1152 assm.push(assm::eax); |
| 1153 assm.data(0); |
| 1154 assm.push(assm::ebx); |
| 1155 assm.push(block_graph::Immediate(test_block_a, 0)); |
| 1156 assm.add(assm::eax, assm::ebx); |
| 1157 |
| 1158 auto test_label = BlockGraph::Label(std::to_string(test_bb_id), |
| 1159 BlockGraph::CODE_LABEL); |
| 1160 inst_iter = bb->instructions().begin(); |
| 1161 inst_iter->set_label(test_label); |
| 1162 //Every checker comes with a pivot |
| 1163 ++inst_iter; |
| 1164 inst_iter->set_label(BlockGraph::Label("Pivot:", |
| 1165 BlockGraph::CODE_LABEL)); |
| 1166 |
| 1167 tx_.id_to_label_[test_bb_id] = test_label; |
| 1168 |
| 1169 //make the block a checker |
| 1170 |
| 1171 uint64 test_checkee1_id = 2; |
| 1172 uint64 test_checkee2_id = 3; |
| 1173 std::map<uint64, int> test_checkee_map; |
| 1174 test_checkee_map[test_checkee1_id] = 1; |
| 1175 test_checkee_map[test_checkee2_id] = -1; |
| 1176 tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
| 1177 tx_.precomputed_hashes_[test_checkee1_id] = 0x20; |
| 1178 tx_.precomputed_hashes_[test_checkee2_id] = 0x10; |
| 1179 |
| 1180 |
| 1181 tx_.ComputeChunks(bb); |
| 1182 |
| 1183 //push ebx and add eax,ebx are two chunks spearated by an abs reference |
| 1184 ASSERT_EQ(2, tx_.ic_block_reference_free_chunks.size()); |
| 1185 |
| 1186 //push ebx is one byte |
| 1187 ASSERT_EQ(1, tx_.ic_block_reference_free_chunks[0].size_); |
| 1188 //add eax,ebx is two bytes |
| 1189 ASSERT_EQ(2, tx_.ic_block_reference_free_chunks[1].size_); |
| 1190 |
| 1191 tx_.ResetTransform(); |
| 1192 delete bgraph; |
| 1193 delete subgraph; |
| 1194 } |
| 1195 |
| 1196 TEST_F(IntegrityCheckTransformTest, CheckAddChunkIntoIndexMap) { |
| 1197 uint64 test_chunk_bb_id = 1; |
| 1198 uint32 test_chunk_index = 0; |
| 1199 uint32 test_vector_index = 0; |
| 1200 tx_.AddChunkIntoIndexMap(test_chunk_bb_id, |
| 1201 test_chunk_index, |
| 1202 test_vector_index); |
| 1203 ASSERT_EQ(test_vector_index, tx_.ic_block_chunk_index_map_[ |
| 1204 tx_.GetChunkUniqueKey(test_chunk_bb_id, test_chunk_index)]); |
| 1205 |
| 1206 tx_.ResetTransform(); |
| 1207 } |
| 1208 |
| 1209 TEST_F(IntegrityCheckTransformTest, CheckGetChunkUniqueKey) { |
| 1210 uint64 test_chunk_bb_id = 1; |
| 1211 uint32 test_chunk_index = 0; |
| 1212 uint64 unique_id = tx_.GetChunkUniqueKey(test_chunk_bb_id, test_chunk_index); |
| 1213 |
| 1214 ASSERT_NE(static_cast<uint64>(0), unique_id); |
| 1215 tx_.ResetTransform(); |
| 1216 } |
| 1217 |
| 1218 TEST_F(IntegrityCheckTransformTest, CheckGenerateChunkCombinations) { |
| 1219 //build 2 checkers in two subgraphs because chunks are assigned to different |
| 1220 //subgraphs |
| 1221 BlockGraph *bgraph = NULL; |
| 1222 BlockGraph::Block *test_block_a = NULL; |
| 1223 BlockGraph::Block *test_block_b = NULL; |
| 1224 uint64 test_bb1_id = 1; |
| 1225 uint64 test_bb2_id = 4; |
| 1226 std::vector<ChunkInfo> test_chunks; |
| 1227 |
| 1228 bgraph = new BlockGraph(); |
| 1229 test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
| 1230 test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_b"); |
| 1231 |
| 1232 BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
| 1233 subgraph->set_original_block(test_block_a); |
| 1234 BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
| 1235 0x60000000); |
| 1236 |
| 1237 subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
| 1238 BlockGraph::CODE_BLOCK, |
| 1239 code_section->id(), 1, 0); |
| 1240 |
| 1241 BasicBlockSubGraph* subgraph_b = new BasicBlockSubGraph(); |
| 1242 subgraph_b->set_original_block(test_block_b); |
| 1243 |
| 1244 subgraph_b->AddBlockDescription("test_subgraph", code_section->name(), |
| 1245 BlockGraph::CODE_BLOCK, |
| 1246 code_section->id(), 1, 0); |
| 1247 |
| 1248 |
| 1249 |
| 1250 //set block id label |
| 1251 auto test_block1_label = BlockGraph::Label(std::to_string(test_bb1_id), |
| 1252 BlockGraph::CODE_LABEL); |
| 1253 auto test_block2_label = BlockGraph::Label(std::to_string(test_bb2_id), |
| 1254 BlockGraph::CODE_LABEL); |
| 1255 //prepare id to label map |
| 1256 tx_.id_to_label_[test_bb1_id] = test_block1_label; |
| 1257 tx_.id_to_label_[test_bb2_id] = test_block2_label; |
| 1258 |
| 1259 |
| 1260 //add chunks label |
| 1261 for (uint32 i = 0; i< tx_.num_chunks_per_block; ++i) { |
| 1262 std::string label = "n " + std::to_string(test_bb1_id) |
| 1263 + " " + std::to_string(i); |
| 1264 tx_.label_name_to_block_[label] = std::make_pair(test_block_a, 0); |
| 1265 test_chunks.insert(test_chunks.begin(), ChunkInfo(test_bb1_id, 1, 1, i,0)); |
| 1266 } |
| 1267 for (uint32 i = 0; i< tx_.num_chunks_per_block; ++i) { |
| 1268 std::string label = "n " + std::to_string(test_bb2_id) |
| 1269 + " " + std::to_string(i); |
| 1270 tx_.label_name_to_block_[label] = std::make_pair(test_block_b, 0); |
| 1271 test_chunks.insert(test_chunks.begin(), ChunkInfo(test_bb2_id, 1, 1, i,0)); |
| 1272 } |
| 1273 |
| 1274 tx_.label_name_to_block_[std::to_string(test_bb1_id)] = |
| 1275 std::make_pair(test_block_a, 0); |
| 1276 tx_.label_name_to_block_[std::to_string(test_bb2_id)] = |
| 1277 std::make_pair(test_block_b, 0); |
| 1278 |
| 1279 uint64 test_checkee1_id = 2; |
| 1280 uint64 test_checkee2_id = 3; |
| 1281 std::map<uint64, int> test_checkee_map; |
| 1282 test_checkee_map[test_checkee1_id] = 1; |
| 1283 test_checkee_map[test_checkee2_id] = -1; |
| 1284 tx_.checker_to_checkee_map_[test_bb1_id] = test_checkee_map; |
| 1285 tx_.checker_to_checkee_map_[test_bb2_id] = test_checkee_map; |
| 1286 |
| 1287 //prepare 20 chunks from these two checkers |
| 1288 //20 n labels |
| 1289 float test_chunk_coverage = 0.5; |
| 1290 bool test_force_all = false; |
| 1291 uint32 chunk_per_block = 0; |
| 1292 auto chunk_map = tx_.GenerateChunkCombinations(test_chunks, |
| 1293 test_chunk_coverage, |
| 1294 test_force_all, |
| 1295 &chunk_per_block |
| 1296 ); |
| 1297 |
| 1298 |
| 1299 ASSERT_EQ(2, chunk_map.size()); |
| 1300 ASSERT_EQ(5, chunk_map[test_bb1_id].size()); |
| 1301 ASSERT_EQ(5, chunk_map[test_bb2_id].size()); |
| 1302 ASSERT_EQ(5, chunk_per_block); |
| 1303 |
| 1304 //strictly picking all blocks |
| 1305 test_chunk_coverage = 1; |
| 1306 test_force_all = true; |
| 1307 chunk_per_block = 0; |
| 1308 chunk_map = tx_.GenerateChunkCombinations(test_chunks, |
| 1309 test_chunk_coverage, |
| 1310 test_force_all, |
| 1311 &chunk_per_block); |
| 1312 |
| 1313 ASSERT_EQ(2, chunk_map.size()); |
| 1314 ASSERT_EQ(10, chunk_map[test_bb1_id].size()); |
| 1315 ASSERT_EQ(10, chunk_map[test_bb2_id].size()); |
| 1316 ASSERT_EQ(10, chunk_per_block); |
| 1317 |
| 1318 tx_.ResetTransform(); |
| 1319 delete bgraph; |
| 1320 delete subgraph; |
| 1321 delete subgraph_b; |
| 1322 } |
| 1323 |
| 1324 TEST_F(IntegrityCheckTransformTest, CheckRandomlySelectChecker) { |
| 1325 |
| 1326 } |
| 1327 |
| 1328 TEST_F(IntegrityCheckTransformTest, CheckIsIdInPartitionUnitMap) { |
| 1329 |
| 1330 } |
| 1331 |
| 1332 TEST_F(IntegrityCheckTransformTest, CheckFixAllCheckeesOfBasicBlock) { |
| 1333 |
| 1334 } |
| 1335 |
| 1336 TEST_F(IntegrityCheckTransformTest, CheckPatchInterBlockReferences) { |
| 1337 |
| 1338 } |
| 1339 |
| 1340 TEST_F(IntegrityCheckTransformTest, CheckPrecomputeHash) { |
| 1341 |
| 1342 } |
| 1343 |
| 1344 TEST_F(IntegrityCheckTransformTest, CheckAddReference) { |
| 1345 |
| 1346 } |
| 1347 |
| 1348 TEST_F(IntegrityCheckTransformTest, CheckGetBasicBlockIdByLabel) { |
| 1349 |
| 1350 } |
| 1351 |
| 1352 TEST_F(IntegrityCheckTransformTest, CheckTransformBasicBlockSubGraph) { |
| 1353 |
| 1354 } |
| 1355 |
| 1356 |
| 1357 TEST_F(IntegrityCheckTransformTest, CheckShouldProcessBlock) { |
| 1358 |
| 1359 } |
| 1360 |
| 1361 TEST_F(IntegrityCheckTransformTest, CheckProcessAllBlocks) { |
| 1362 |
| 1363 } |
| 1364 |
| 1365 TEST_F(IntegrityCheckTransformTest, CheckGenerateBasicBlockCombinations) { |
| 1366 |
| 1367 } |
| 1368 |
| 1369 TEST_F(IntegrityCheckTransformTest, CheckTransformBlockGraph) { |
| 1370 |
| 1371 } |
| 1372 } |
OLD | NEW |