16d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// Copyright (c) 2010, Google Inc. 26d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// All rights reserved. 36d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// 46d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// Redistribution and use in source and binary forms, with or without 56d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// modification, are permitted provided that the following conditions are 66d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// met: 76d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// 86d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// * Redistributions of source code must retain the above copyright 96d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// notice, this list of conditions and the following disclaimer. 106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// * Redistributions in binary form must reproduce the above 116d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// copyright notice, this list of conditions and the following disclaimer 126d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// in the documentation and/or other materials provided with the 136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// distribution. 146d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// * Neither the name of Google Inc. nor the names of its 156d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// contributors may be used to endorse or promote products derived from 166d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// this software without specific prior written permission. 176d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// 186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 196d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 206d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 246d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 296d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 306d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 316d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 326d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// cfi_frame_info_unittest.cc: Unit tests for CFIFrameInfo, 336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// CFIRuleParser, CFIFrameInfoParseHandler, and SimpleCFIWalker. 346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy#include <string.h> 366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy#include "breakpad_googletest_includes.h" 384e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com#include "common/using_std_string.h" 396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy#include "processor/cfi_frame_info.h" 406d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy#include "google_breakpad/processor/memory_region.h" 416d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 426d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing google_breakpad::CFIFrameInfo; 436d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing google_breakpad::CFIFrameInfoParseHandler; 446d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing google_breakpad::CFIRuleParser; 456d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing google_breakpad::MemoryRegion; 466d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing google_breakpad::SimpleCFIWalker; 476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing testing::_; 486d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing testing::A; 496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing testing::AtMost; 506d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing testing::DoAll; 516d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing testing::Return; 526d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing testing::SetArgumentPointee; 536d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyusing testing::Test; 546d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 556d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass MockMemoryRegion: public MemoryRegion { 566d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy public: 576162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com MOCK_CONST_METHOD0(GetBase, uint64_t()); 586162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com MOCK_CONST_METHOD0(GetSize, uint32_t()); 596162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint8_t *)); 606162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint16_t *)); 616162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint32_t *)); 626162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint64_t *)); 63c5e242b8cd4280db5162e5a3084f2dc9e16e8ffbmmandlis@chromium.org MOCK_CONST_METHOD0(Print, void()); 646d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}; 656d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 666d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// Handy definitions for all tests. 676d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandystruct CFIFixture { 686d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 696d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Set up the mock memory object to expect no references. 706d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy void ExpectNoMemoryReferences() { 716d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(memory, GetBase()).Times(0); 726d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(memory, GetSize()).Times(0); 736162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint8_t *>())).Times(0); 746162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint16_t *>())).Times(0); 756162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint32_t *>())).Times(0); 766162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint64_t *>())).Times(0); 776d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy } 786d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 796d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CFIFrameInfo cfi; 806d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy MockMemoryRegion memory; 816162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com CFIFrameInfo::RegisterValueMap<uint64_t> registers, caller_registers; 826d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}; 836d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 846d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass Simple: public CFIFixture, public Test { }; 856d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 866d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// FindCallerRegs should fail if no .cfa rule is provided. 876d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Simple, NoCFA) { 886d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 896d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 906d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("0"); 916162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, 926d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 93b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek ASSERT_EQ(".ra: 0", cfi.Serialize()); 946d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 956d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 966d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// FindCallerRegs should fail if no .ra rule is provided. 976d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Simple, NoRA) { 986d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 996d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1006d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("0"); 1016162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1026d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 103b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek ASSERT_EQ(".cfa: 0", cfi.Serialize()); 1046d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 1056d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1066d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Simple, SetCFAAndRARule) { 1076d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 1086d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1096d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("330903416631436410"); 1106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("5870666104170902211"); 1116162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1126d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 1136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(2U, caller_registers.size()); 1146d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(330903416631436410ULL, caller_registers[".cfa"]); 1156d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]); 116b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek 117b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211", 118b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek cfi.Serialize()); 1196d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 1206d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Simple, SetManyRules) { 1226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 1236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1246d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("$temp1 68737028 = $temp2 61072337 = $temp1 $temp2 -"); 1256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule(".cfa 99804755 +"); 1266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRegisterRule("register1", ".cfa 54370437 *"); 1276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRegisterRule("vodkathumbscrewingly", "24076308 .cfa +"); 1286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRegisterRule("pubvexingfjordschmaltzy", ".cfa 29801007 -"); 1296d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRegisterRule("uncopyrightables", "92642917 .cfa /"); 1306162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1316d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 1326d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(6U, caller_registers.size()); 1336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(7664691U, caller_registers[".cfa"]); 1346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(107469446U, caller_registers[".ra"]); 1356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(416732599139967ULL, caller_registers["register1"]); 1366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(31740999U, caller_registers["vodkathumbscrewingly"]); 1376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(-22136316ULL, caller_registers["pubvexingfjordschmaltzy"]); 1386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(12U, caller_registers["uncopyrightables"]); 139b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - " 140b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek ".ra: .cfa 99804755 + " 141b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek "pubvexingfjordschmaltzy: .cfa 29801007 - " 142b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek "register1: .cfa 54370437 * " 143b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek "uncopyrightables: 92642917 .cfa / " 144b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek "vodkathumbscrewingly: 24076308 .cfa +", 145b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek cfi.Serialize()); 1466d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 1476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1486d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Simple, RulesOverride) { 1496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 1506d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1516d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("330903416631436410"); 1526d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("5870666104170902211"); 1536d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("2828089117179001"); 1546162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1556d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 1566d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(2U, caller_registers.size()); 1576d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(2828089117179001ULL, caller_registers[".cfa"]); 1586d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]); 159b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211", 160b223627d81c083a64f2ccecf2651a18111421280ted.mielczarek cfi.Serialize()); 1616d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 1626d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1636d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass Scope: public CFIFixture, public Test { }; 1646d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1656d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// There should be no value for .cfa in scope when evaluating the CFA rule. 1666d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Scope, CFALacksCFA) { 1676d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 1686d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1696d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule(".cfa"); 1706d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("0"); 1716162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1726d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 1736d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 1746d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1756d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// There should be no value for .ra in scope when evaluating the CFA rule. 1766d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Scope, CFALacksRA) { 1776d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 1786d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1796d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule(".ra"); 1806d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("0"); 1816162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1826d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 1836d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 1846d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1856d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// The current frame's registers should be in scope when evaluating 1866d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// the CFA rule. 1876d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Scope, CFASeesCurrentRegs) { 1886d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 1896d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1906d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers[".baraminology"] = 0x06a7bc63e4f13893ULL; 1916d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers[".ornithorhynchus"] = 0x5e0bf850bafce9d2ULL; 1926d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule(".baraminology .ornithorhynchus +"); 1936d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("0"); 1946162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 1956d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 1966d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(2U, caller_registers.size()); 1976d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(0x06a7bc63e4f13893ULL + 0x5e0bf850bafce9d2ULL, 1986d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy caller_registers[".cfa"]); 1996d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 2006d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2016d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// .cfa should be in scope in the return address expression. 2026d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Scope, RASeesCFA) { 2036d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 2046d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2056d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("48364076"); 2066d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule(".cfa"); 2076162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 2086d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 2096d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(2U, caller_registers.size()); 2106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(48364076U, caller_registers[".ra"]); 2116d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 2126d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// There should be no value for .ra in scope when evaluating the CFA rule. 2146d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Scope, RALacksRA) { 2156d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 2166d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2176d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("0"); 2186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule(".ra"); 2196162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, 2206d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 2216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 2226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// The current frame's registers should be in scope in the return 2246d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// address expression. 2256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Scope, RASeesCurrentRegs) { 2266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 2276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers["noachian"] = 0x54dc4a5d8e5eb503ULL; 2296d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("10359370"); 2306d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("noachian"); 2316162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 2326d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 2336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(2U, caller_registers.size()); 2346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[".ra"]); 2356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 2366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// .cfa should be in scope for register rules. 2386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Scope, RegistersSeeCFA) { 2396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 2406d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2416d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("6515179"); 2426d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule(".cfa"); 2436d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRegisterRule("rogerian", ".cfa"); 2446162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 2456d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 2466d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(3U, caller_registers.size()); 2476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(6515179U, caller_registers["rogerian"]); 2486d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 2496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2506d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// The return address should not be in scope for register rules. 2516d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Scope, RegsLackRA) { 2526d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 2536d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2546d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("42740329"); 2556d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("27045204"); 2566d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRegisterRule("$r1", ".ra"); 2576162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, 2586d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 2596d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 2606d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2616d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// Register rules can see the current frame's register values. 2626d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Scope, RegsSeeRegs) { 2636d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 2646d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2656d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers["$r1"] = 0x6ed3582c4bedb9adULL; 2666d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers["$r2"] = 0xd27d9e742b8df6d0ULL; 2676d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("88239303"); 2686d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("30503835"); 2696d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRegisterRule("$r1", "$r1 42175211 = $r2"); 2706d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRegisterRule("$r2", "$r2 21357221 = $r1"); 2716162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 2726d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 2736d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(4U, caller_registers.size()); 2746d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers["$r1"]); 2756d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers["$r2"]); 2766d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 2776d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2786d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// Each rule's temporaries are separate. 2796d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Scope, SeparateTempsRA) { 2806d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ExpectNoMemoryReferences(); 2816d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2826d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("$temp1 76569129 = $temp1"); 2836d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("0"); 2846162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 2856d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 2866d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2876d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetCFARule("$temp1 76569129 = $temp1"); 2886d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy cfi.SetRARule("$temp1"); 2896162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, 2906d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 2916d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 2926d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 2936d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass MockCFIRuleParserHandler: public CFIRuleParser::Handler { 2946d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy public: 2956d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy MOCK_METHOD1(CFARule, void(const string &)); 2966d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy MOCK_METHOD1(RARule, void(const string &)); 2976d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy MOCK_METHOD2(RegisterRule, void(const string &, const string &)); 2986d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}; 2996d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3006d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// A fixture class for testing CFIRuleParser. 3016d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass CFIParserFixture { 3026d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy public: 3036d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CFIParserFixture() : parser(&mock_handler) { 3046d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Expect no parsing results to be reported to mock_handler. Individual 3056d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // tests can override this. 3066d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, CFARule(_)).Times(0); 3076d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RARule(_)).Times(0); 3086d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RegisterRule(_, _)).Times(0); 3096d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy } 3106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3116d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy MockCFIRuleParserHandler mock_handler; 3126d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CFIRuleParser parser; 3136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}; 3146d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3156d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass Parser: public CFIParserFixture, public Test { }; 3166d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3176d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, Empty) { 3186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse("")); 3196d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3206d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, LoneColon) { 3226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse(":")); 3236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3246d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, CFANoExpr) { 3266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse(".cfa:")); 3276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3296d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, CFANoColonNoExpr) { 3306d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse(".cfa")); 3316d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3326d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, RANoExpr) { 3346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse(".ra:")); 3356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, RANoColonNoExpr) { 3386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse(".ra")); 3396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3406d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3416d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, RegNoExpr) { 3426d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse("reg:")); 3436d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3446d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3456d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, NoName) { 3466d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse("expr")); 3476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3486d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, NoNameTwo) { 3506d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse("expr1 expr2")); 3516d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3526d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3536d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, StartsWithExpr) { 3546d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse("expr1 reg: expr2")); 3556d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3566d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3576d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, CFA) { 3586d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, CFARule("spleen")).WillOnce(Return()); 3596d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_TRUE(parser.Parse(".cfa: spleen")); 3606d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3616d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3626d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, RA) { 3636d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RARule("notoriety")).WillOnce(Return()); 3646d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_TRUE(parser.Parse(".ra: notoriety")); 3656d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3666d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3676d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, Reg) { 3686d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RegisterRule("nemo", "mellifluous")) 3696d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .WillOnce(Return()); 3706d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_TRUE(parser.Parse("nemo: mellifluous")); 3716d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3726d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3736d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, CFARARegs) { 3746d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, CFARule("cfa expression")).WillOnce(Return()); 3756d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RARule("ra expression")).WillOnce(Return()); 3766d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RegisterRule("galba", "praetorian")) 3776d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .WillOnce(Return()); 3786d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RegisterRule("otho", "vitellius")) 3796d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .WillOnce(Return()); 3806d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_TRUE(parser.Parse(".cfa: cfa expression .ra: ra expression " 3816d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "galba: praetorian otho: vitellius")); 3826d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3836d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3846d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, Whitespace) { 3856d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RegisterRule("r1", "r1 expression")) 3866d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .WillOnce(Return()); 3876d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RegisterRule("r2", "r2 expression")) 3886d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .WillOnce(Return()); 3896d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_TRUE(parser.Parse(" r1:\tr1\nexpression \tr2:\t\rr2\r\n " 3906d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy "expression \n")); 3916d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3926d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3936d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, WhitespaceLoneColon) { 3946d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse(" \n:\t ")); 3956d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 3966d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 3976d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, EmptyName) { 3986d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RegisterRule("reg", _)) 3996d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Times(AtMost(1)) 4006d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .WillRepeatedly(Return()); 4016d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse("reg: expr1 : expr2")); 4026d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 4036d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4046d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, RuleLoneColon) { 4056d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RegisterRule("r1", "expr")) 4066d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Times(AtMost(1)) 4076d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .WillRepeatedly(Return()); 4086d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse(" r1: expr :")); 4096d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 4106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4116d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(Parser, RegNoExprRule) { 4126d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(mock_handler, RegisterRule("r1", "expr")) 4136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .Times(AtMost(1)) 4146d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .WillRepeatedly(Return()); 4156d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_FALSE(parser.Parse("r0: r1: expr")); 4166d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 4176d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass ParseHandlerFixture: public CFIFixture { 4196d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy public: 4206d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ParseHandlerFixture() : CFIFixture(), handler(&cfi) { } 4216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CFIFrameInfoParseHandler handler; 4226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}; 4236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4246d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass ParseHandler: public ParseHandlerFixture, public Test { }; 4256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(ParseHandler, CFARARule) { 4276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy handler.CFARule("reg-for-cfa"); 4286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy handler.RARule("reg-for-ra"); 4296d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL; 4306d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers["reg-for-ra"] = 0x6301b475b8b91c02ULL; 4316162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 4326d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 4336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]); 4346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]); 4356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 4366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(ParseHandler, RegisterRules) { 4386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy handler.CFARule("reg-for-cfa"); 4396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy handler.RARule("reg-for-ra"); 4406d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy handler.RegisterRule("reg1", "reg-for-reg1"); 4416d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy handler.RegisterRule("reg2", "reg-for-reg2"); 4426d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL; 4436d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers["reg-for-ra"] = 0x6301b475b8b91c02ULL; 4446d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers["reg-for-reg1"] = 0x06cde8e2ff062481ULL; 4456d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy registers["reg-for-reg2"] = 0xff0c4f76403173e2ULL; 4466162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, 4476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)); 4486d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]); 4496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]); 4506d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers["reg1"]); 4516d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers["reg2"]); 4526d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 4536d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4546d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandystruct SimpleCFIWalkerFixture { 4556d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy struct RawContext { 4566162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com uint64_t r0, r1, r2, r3, r4, sp, pc; 4576d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy }; 4586d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy enum Validity { 4596d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy R0_VALID = 0x01, 4606d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy R1_VALID = 0x02, 4616d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy R2_VALID = 0x04, 4626d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy R3_VALID = 0x08, 4636d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy R4_VALID = 0x10, 4646d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy SP_VALID = 0x20, 4656d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy PC_VALID = 0x40 4666d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy }; 4676162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com typedef SimpleCFIWalker<uint64_t, RawContext> CFIWalker; 4686d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4696d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy SimpleCFIWalkerFixture() 4706d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy : walker(register_map, 4716d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy sizeof(register_map) / sizeof(register_map[0])) { } 4726d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4736d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy static CFIWalker::RegisterSet register_map[7]; 4746d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CFIFrameInfo call_frame_info; 4756d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy CFIWalker walker; 4766d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy MockMemoryRegion memory; 4776d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy RawContext callee_context, caller_context; 4786d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}; 4796d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4806d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandySimpleCFIWalkerFixture::CFIWalker::RegisterSet 4816d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandySimpleCFIWalkerFixture::register_map[7] = { 4826d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy { "r0", NULL, true, R0_VALID, &RawContext::r0 }, 4836d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy { "r1", NULL, true, R1_VALID, &RawContext::r1 }, 4846d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy { "r2", NULL, false, R2_VALID, &RawContext::r2 }, 4856d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy { "r3", NULL, false, R3_VALID, &RawContext::r3 }, 4866d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy { "r4", NULL, true, R4_VALID, &RawContext::r4 }, 4876d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy { "sp", ".cfa", true, SP_VALID, &RawContext::sp }, 4886d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy { "pc", ".ra", true, PC_VALID, &RawContext::pc }, 4896d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy}; 4906d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4916d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyclass SimpleWalker: public SimpleCFIWalkerFixture, public Test { }; 4926d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 4936d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandyTEST_F(SimpleWalker, Walk) { 4946d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Stack_top is the current stack pointer, pointing to the lowest 4956d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // address of a frame that looks like this (all 64-bit words): 4966d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // 4976d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // sp -> saved r0 4986d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // garbage 4996d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // return address 5006d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // cfa -> 5016d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // 5026d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // r0 has been saved on the stack. 5036d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // r1 has been saved in r2. 5046d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // r2 and r3 are not recoverable. 5056d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // r4 is not recoverable, even though it is a callee-saves register. 5066d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Some earlier frame's unwinder must have failed to recover it. 5076d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 5086162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com uint64_t stack_top = 0x83254944b20d5512ULL; 5096d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 5106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Saved r0. 5116d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(memory, 5126162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com GetMemoryAtAddress(stack_top, A<uint64_t *>())) 5136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .WillRepeatedly(DoAll(SetArgumentPointee<1>(0xdc1975eba8602302ULL), 5146d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy Return(true))); 5156d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Saved return address. 5166d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_CALL(memory, 5176162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com GetMemoryAtAddress(stack_top + 16, A<uint64_t *>())) 5186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy .WillRepeatedly(DoAll(SetArgumentPointee<1>(0xba5ad6d9acce28deULL), 5196d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy Return(true))); 5206d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 5216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy call_frame_info.SetCFARule("sp 24 +"); 5226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy call_frame_info.SetRARule(".cfa 8 - ^"); 5236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy call_frame_info.SetRegisterRule("r0", ".cfa 24 - ^"); 5246d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy call_frame_info.SetRegisterRule("r1", "r2"); 5256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 5266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy callee_context.r0 = 0x94e030ca79edd119ULL; 5276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy callee_context.r1 = 0x937b4d7e95ce52d9ULL; 5286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy callee_context.r2 = 0x5fe0027416b8b62aULL; // caller's r1 5296d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // callee_context.r3 is not valid in callee. 5306d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // callee_context.r4 is not valid in callee. 5316d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy callee_context.sp = stack_top; 5326d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy callee_context.pc = 0x25b21b224311d280ULL; 5336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy int callee_validity = R0_VALID | R1_VALID | R2_VALID | SP_VALID | PC_VALID; 5346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 5356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy memset(&caller_context, 0, sizeof(caller_context)); 5366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 5376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy int caller_validity; 5386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_TRUE(walker.FindCallerRegisters(memory, call_frame_info, 5396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy callee_context, callee_validity, 5406d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_context, &caller_validity)); 5416d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_EQ(R0_VALID | R1_VALID | SP_VALID | PC_VALID, caller_validity); 5426d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_EQ(0xdc1975eba8602302ULL, caller_context.r0); 5436d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_EQ(0x5fe0027416b8b62aULL, caller_context.r1); 5446d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_EQ(stack_top + 24, caller_context.sp); 5456d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy EXPECT_EQ(0xba5ad6d9acce28deULL, caller_context.pc); 5466d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 547