| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2016 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | #include <stdint.h> | 
 | 18 |  | 
 | 19 | #include <gmock/gmock.h> | 
 | 20 | #include <gtest/gtest.h> | 
 | 21 |  | 
| Christopher Ferris | d226a51 | 2017-07-14 10:37:19 -0700 | [diff] [blame] | 22 | #include <unwindstack/DwarfSection.h> | 
 | 23 |  | 
 | 24 | #include "DwarfEncoding.h" | 
 | 25 | #include "DwarfError.h" | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 26 |  | 
 | 27 | #include "LogFake.h" | 
 | 28 | #include "MemoryFake.h" | 
 | 29 | #include "RegsFake.h" | 
 | 30 |  | 
| Christopher Ferris | d226a51 | 2017-07-14 10:37:19 -0700 | [diff] [blame] | 31 | namespace unwindstack { | 
 | 32 |  | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 33 | template <typename TypeParam> | 
 | 34 | class MockDwarfSectionImpl : public DwarfSectionImpl<TypeParam> { | 
 | 35 |  public: | 
 | 36 |   MockDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {} | 
 | 37 |   virtual ~MockDwarfSectionImpl() = default; | 
 | 38 |  | 
 | 39 |   MOCK_METHOD2(Init, bool(uint64_t, uint64_t)); | 
 | 40 |  | 
 | 41 |   MOCK_METHOD2(GetFdeOffsetFromPc, bool(uint64_t, uint64_t*)); | 
 | 42 |  | 
 | 43 |   MOCK_METHOD1(GetFdeFromIndex, const DwarfFde*(size_t)); | 
 | 44 |  | 
 | 45 |   MOCK_METHOD1(IsCie32, bool(uint32_t)); | 
 | 46 |  | 
 | 47 |   MOCK_METHOD1(IsCie64, bool(uint64_t)); | 
 | 48 |  | 
 | 49 |   MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t)); | 
 | 50 |  | 
 | 51 |   MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t)); | 
 | 52 |  | 
 | 53 |   MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t)); | 
 | 54 |  | 
 | 55 |   void TestSetCachedCieEntry(uint64_t offset, const DwarfCie& cie) { | 
 | 56 |     this->cie_entries_[offset] = cie; | 
 | 57 |   } | 
 | 58 |   void TestClearCachedCieEntry() { this->cie_entries_.clear(); } | 
 | 59 |  | 
 | 60 |   void TestSetCachedFdeEntry(uint64_t offset, const DwarfFde& fde) { | 
 | 61 |     this->fde_entries_[offset] = fde; | 
 | 62 |   } | 
 | 63 |   void TestClearCachedFdeEntry() { this->fde_entries_.clear(); } | 
 | 64 |  | 
 | 65 |   void TestSetCachedCieLocRegs(uint64_t offset, const dwarf_loc_regs_t& loc_regs) { | 
 | 66 |     this->cie_loc_regs_[offset] = loc_regs; | 
 | 67 |   } | 
 | 68 |   void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); } | 
 | 69 |  | 
 | 70 |   void TestClearError() { this->last_error_ = DWARF_ERROR_NONE; } | 
 | 71 | }; | 
 | 72 |  | 
 | 73 | template <typename TypeParam> | 
 | 74 | class DwarfSectionImplTest : public ::testing::Test { | 
 | 75 |  protected: | 
 | 76 |   void SetUp() override { | 
 | 77 |     memory_.Clear(); | 
 | 78 |     section_ = new MockDwarfSectionImpl<TypeParam>(&memory_); | 
 | 79 |     ResetLogs(); | 
 | 80 |   } | 
 | 81 |  | 
 | 82 |   void TearDown() override { delete section_; } | 
 | 83 |  | 
 | 84 |   MemoryFake memory_; | 
 | 85 |   MockDwarfSectionImpl<TypeParam>* section_ = nullptr; | 
 | 86 | }; | 
 | 87 | TYPED_TEST_CASE_P(DwarfSectionImplTest); | 
 | 88 |  | 
 | 89 | // NOTE: All test class variables need to be referenced as this->. | 
 | 90 |  | 
 | 91 | TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) { | 
 | 92 |   DwarfCie cie{.version = 3, .return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 93 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 94 |   dwarf_loc_regs_t loc_regs; | 
 | 95 |  | 
 | 96 |   regs.set_pc(0x100); | 
 | 97 |   regs.set_sp(0x2000); | 
 | 98 |   regs[5] = 0x20; | 
 | 99 |   regs[9] = 0x3000; | 
 | 100 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 101 |   bool finished; | 
 | 102 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 103 |   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); | 
 | 104 | } | 
 | 105 |  | 
 | 106 | TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) { | 
 | 107 |   DwarfCie cie{.version = 3, .return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 108 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 109 |   dwarf_loc_regs_t loc_regs; | 
 | 110 |  | 
 | 111 |   regs.set_pc(0x100); | 
 | 112 |   regs.set_sp(0x2000); | 
 | 113 |   regs[5] = 0x20; | 
 | 114 |   regs[9] = 0x3000; | 
 | 115 |   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96}); | 
 | 116 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 117 |   bool finished; | 
 | 118 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 119 |   EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error()); | 
 | 120 | } | 
 | 121 |  | 
 | 122 | TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) { | 
 | 123 |   DwarfCie cie{.version = 3, .return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 124 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 125 |   dwarf_loc_regs_t loc_regs; | 
 | 126 |  | 
 | 127 |   regs.set_pc(0x100); | 
 | 128 |   regs.set_sp(0x2000); | 
 | 129 |   regs[5] = 0x20; | 
 | 130 |   regs[9] = 0x3000; | 
 | 131 |   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80}); | 
 | 132 |   TypeParam cfa_value = 0x12345; | 
 | 133 |   this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value)); | 
 | 134 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 135 |   bool finished; | 
 | 136 |   ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
 | 137 |   EXPECT_FALSE(finished); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 138 |   EXPECT_EQ(0x12345U, regs.sp()); | 
 | 139 |   EXPECT_EQ(0x20U, regs.pc()); | 
 | 140 | } | 
 | 141 |  | 
 | 142 | TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) { | 
 | 143 |   DwarfCie cie{.version = 3, .return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 144 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 145 |   dwarf_loc_regs_t loc_regs; | 
 | 146 |  | 
 | 147 |   regs.set_pc(0x100); | 
 | 148 |   regs.set_sp(0x2000); | 
 | 149 |   regs[5] = 0x20; | 
 | 150 |   regs[9] = 0x3000; | 
 | 151 |   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80}); | 
 | 152 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 153 |   bool finished; | 
 | 154 |   ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
 | 155 |   ASSERT_FALSE(finished); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 156 |   EXPECT_EQ(0x80000000U, regs.sp()); | 
 | 157 |   EXPECT_EQ(0x20U, regs.pc()); | 
 | 158 | } | 
 | 159 |  | 
 | 160 | TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) { | 
 | 161 |   DwarfCie cie{.version = 3, .return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 162 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 163 |   dwarf_loc_regs_t loc_regs; | 
 | 164 |  | 
 | 165 |   regs.set_pc(0x100); | 
 | 166 |   regs.set_sp(0x2000); | 
 | 167 |   regs[5] = 0x20; | 
 | 168 |   regs[9] = 0x3000; | 
 | 169 |   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96}); | 
 | 170 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 171 |   bool finished; | 
 | 172 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 173 |   EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->last_error()); | 
 | 174 | } | 
 | 175 |  | 
 | 176 | TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) { | 
 | 177 |   DwarfCie cie{.return_address_register = 60}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 178 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 179 |   dwarf_loc_regs_t loc_regs; | 
 | 180 |  | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 181 |   bool finished; | 
 | 182 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 183 |   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); | 
 | 184 | } | 
 | 185 |  | 
 | 186 | TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) { | 
 | 187 |   DwarfCie cie{.return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 188 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 189 |   dwarf_loc_regs_t loc_regs; | 
 | 190 |  | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 191 |   bool finished; | 
 | 192 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 193 |   EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->last_error()); | 
 | 194 | } | 
 | 195 |  | 
 | 196 | TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) { | 
 | 197 |   DwarfCie cie{.return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 198 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 199 |   dwarf_loc_regs_t loc_regs; | 
 | 200 |  | 
 | 201 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 202 |   bool finished; | 
 | 203 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 204 |   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); | 
 | 205 |  | 
 | 206 |   this->section_->TestClearError(); | 
 | 207 |   loc_regs.erase(CFA_REG); | 
 | 208 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 209 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 210 |   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); | 
 | 211 |  | 
 | 212 |   this->section_->TestClearError(); | 
 | 213 |   loc_regs.erase(CFA_REG); | 
 | 214 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 215 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 216 |   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); | 
 | 217 |  | 
 | 218 |   this->section_->TestClearError(); | 
 | 219 |   loc_regs.erase(CFA_REG); | 
 | 220 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 221 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 222 |   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); | 
 | 223 | } | 
 | 224 |  | 
 | 225 | TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) { | 
 | 226 |   DwarfCie cie{.return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 227 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 228 |   dwarf_loc_regs_t loc_regs; | 
 | 229 |  | 
 | 230 |   regs.set_pc(0x100); | 
 | 231 |   regs.set_sp(0x2000); | 
 | 232 |   regs[5] = 0x20; | 
 | 233 |   regs[9] = 0x3000; | 
 | 234 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 235 |   bool finished; | 
 | 236 |   ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
 | 237 |   EXPECT_FALSE(finished); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 238 |   EXPECT_EQ(0x20U, regs.pc()); | 
 | 239 |   EXPECT_EQ(0x2000U, regs.sp()); | 
 | 240 | } | 
 | 241 |  | 
 | 242 | TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) { | 
 | 243 |   DwarfCie cie{.return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 244 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 245 |   dwarf_loc_regs_t loc_regs; | 
 | 246 |  | 
 | 247 |   regs.set_pc(0x100); | 
 | 248 |   regs.set_sp(0x2000); | 
 | 249 |   regs[5] = 0x20; | 
 | 250 |   regs[6] = 0x4000; | 
 | 251 |   regs[9] = 0x3000; | 
 | 252 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 253 |   bool finished; | 
 | 254 |   ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
 | 255 |   EXPECT_FALSE(finished); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 256 |   EXPECT_EQ(0x20U, regs.pc()); | 
 | 257 |   EXPECT_EQ(0x4000U, regs.sp()); | 
 | 258 | } | 
 | 259 |  | 
 | 260 | TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) { | 
 | 261 |   DwarfCie cie{.return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 262 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 263 |   dwarf_loc_regs_t loc_regs; | 
 | 264 |  | 
 | 265 |   regs.set_pc(0x100); | 
 | 266 |   regs.set_sp(0x2000); | 
 | 267 |   regs[8] = 0x10; | 
 | 268 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; | 
 | 269 |   loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 0}}; | 
 | 270 |   loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 271 |   bool finished; | 
 | 272 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 273 |   EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error()); | 
 | 274 | } | 
 | 275 |  | 
 | 276 | TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) { | 
 | 277 |   DwarfCie cie{.return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 278 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 279 |   dwarf_loc_regs_t loc_regs; | 
 | 280 |  | 
 | 281 |   regs.set_pc(0x100); | 
 | 282 |   regs.set_sp(0x2000); | 
 | 283 |   regs[8] = 0x10; | 
 | 284 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; | 
 | 285 |   loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 286 |   bool finished; | 
 | 287 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 288 |   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); | 
 | 289 | } | 
 | 290 |  | 
 | 291 | TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) { | 
 | 292 |   DwarfCie cie{.return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 293 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 294 |   dwarf_loc_regs_t loc_regs; | 
 | 295 |  | 
 | 296 |   if (sizeof(TypeParam) == sizeof(uint64_t)) { | 
 | 297 |     this->memory_.SetData64(0x2150, 0x12345678abcdef00ULL); | 
 | 298 |   } else { | 
 | 299 |     this->memory_.SetData32(0x2150, 0x12345678); | 
 | 300 |   } | 
 | 301 |  | 
 | 302 |   regs.set_pc(0x100); | 
 | 303 |   regs.set_sp(0x2000); | 
 | 304 |   regs[3] = 0x234; | 
 | 305 |   regs[5] = 0x10; | 
 | 306 |   regs[8] = 0x2100; | 
 | 307 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; | 
 | 308 |   loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}}; | 
 | 309 |   loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}}; | 
 | 310 |   loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 311 |   bool finished; | 
 | 312 |   ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
 | 313 |   EXPECT_FALSE(finished); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 314 |   EXPECT_EQ(0x10U, regs.pc()); | 
 | 315 |   EXPECT_EQ(0x2100U, regs.sp()); | 
 | 316 |   EXPECT_EQ(0x2200U, regs[1]); | 
 | 317 |   EXPECT_EQ(0x234U, regs[3]); | 
 | 318 |   if (sizeof(TypeParam) == sizeof(uint64_t)) { | 
 | 319 |     EXPECT_EQ(0x12345678abcdef00ULL, regs[2]); | 
 | 320 |   } else { | 
 | 321 |     EXPECT_EQ(0x12345678U, regs[2]); | 
 | 322 |   } | 
 | 323 | } | 
 | 324 |  | 
 | 325 | TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) { | 
 | 326 |   DwarfCie cie{.return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 327 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 328 |   dwarf_loc_regs_t loc_regs; | 
 | 329 |  | 
 | 330 |   regs.set_pc(0x100); | 
 | 331 |   regs.set_sp(0x2000); | 
 | 332 |   regs[5] = 0x20; | 
 | 333 |   regs[8] = 0x10; | 
 | 334 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; | 
 | 335 |   loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 336 |   bool finished; | 
 | 337 |   ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
 | 338 |   EXPECT_TRUE(finished); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 339 |   EXPECT_EQ(0U, regs.pc()); | 
 | 340 |   EXPECT_EQ(0x10U, regs.sp()); | 
 | 341 | } | 
 | 342 |  | 
 | 343 | TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) { | 
 | 344 |   DwarfCie cie{.return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 345 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 346 |   dwarf_loc_regs_t loc_regs; | 
 | 347 |  | 
 | 348 |   regs.set_pc(0x100); | 
 | 349 |   regs.set_sp(0x2000); | 
 | 350 |   regs[5] = 0x20; | 
 | 351 |   regs[8] = 0x10; | 
 | 352 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 353 |   bool finished; | 
 | 354 |   ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
 | 355 |   EXPECT_FALSE(finished); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 356 |   EXPECT_EQ(0x20U, regs.pc()); | 
 | 357 |   EXPECT_EQ(0x10U, regs.sp()); | 
 | 358 | } | 
 | 359 |  | 
 | 360 | TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) { | 
 | 361 |   DwarfCie cie{.return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 362 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 363 |   dwarf_loc_regs_t loc_regs; | 
 | 364 |  | 
 | 365 |   regs.set_pc(0x100); | 
 | 366 |   regs.set_sp(0x2000); | 
 | 367 |   regs[5] = 0x20; | 
 | 368 |   regs[8] = 0x10; | 
 | 369 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; | 
 | 370 |   // This should not result in any errors. | 
 | 371 |   loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 372 |   bool finished; | 
 | 373 |   ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
 | 374 |   EXPECT_FALSE(finished); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 375 |   EXPECT_EQ(0x20U, regs.pc()); | 
 | 376 |   EXPECT_EQ(0x10U, regs.sp()); | 
 | 377 | } | 
 | 378 |  | 
 | 379 | TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) { | 
 | 380 |   DwarfCie cie{.version = 3, .return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 381 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 382 |   dwarf_loc_regs_t loc_regs; | 
 | 383 |  | 
 | 384 |   regs.set_pc(0x100); | 
 | 385 |   regs.set_sp(0x2000); | 
 | 386 |   regs[8] = 0x3000; | 
 | 387 |   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80}); | 
 | 388 |   TypeParam cfa_value = 0x12345; | 
 | 389 |   this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value)); | 
 | 390 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; | 
 | 391 |   loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 392 |   bool finished; | 
 | 393 |   ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
 | 394 |   EXPECT_FALSE(finished); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 395 |   EXPECT_EQ(0x3000U, regs.sp()); | 
 | 396 |   EXPECT_EQ(0x12345U, regs.pc()); | 
 | 397 | } | 
 | 398 |  | 
 | 399 | TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) { | 
 | 400 |   DwarfCie cie{.version = 3, .return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 401 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 402 |   dwarf_loc_regs_t loc_regs; | 
 | 403 |  | 
 | 404 |   regs.set_pc(0x100); | 
 | 405 |   regs.set_sp(0x2000); | 
 | 406 |   regs[8] = 0x3000; | 
 | 407 |   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80}); | 
 | 408 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; | 
 | 409 |   loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 410 |   bool finished; | 
 | 411 |   ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
 | 412 |   EXPECT_FALSE(finished); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 413 |   EXPECT_EQ(0x3000U, regs.sp()); | 
 | 414 |   EXPECT_EQ(0x80000000U, regs.pc()); | 
 | 415 | } | 
 | 416 |  | 
 | 417 | TYPED_TEST_P(DwarfSectionImplTest, Eval_same_cfa_same_pc) { | 
 | 418 |   DwarfCie cie{.version = 3, .return_address_register = 5}; | 
| Christopher Ferris | f6f691b | 2017-09-25 19:23:07 -0700 | [diff] [blame] | 419 |   RegsImplFake<TypeParam> regs(10, 9); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 420 |   dwarf_loc_regs_t loc_regs; | 
 | 421 |  | 
 | 422 |   regs.set_pc(0x100); | 
 | 423 |   regs.set_sp(0x2000); | 
 | 424 |   regs[5] = 0x100; | 
 | 425 |   regs[8] = 0x2000; | 
 | 426 |   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; | 
| Christopher Ferris | b9de87f | 2017-09-20 13:37:24 -0700 | [diff] [blame] | 427 |   bool finished; | 
 | 428 |   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 429 |   EXPECT_EQ(0x2000U, regs.sp()); | 
 | 430 |   EXPECT_EQ(0x100U, regs.pc()); | 
 | 431 | } | 
 | 432 |  | 
 | 433 | TYPED_TEST_P(DwarfSectionImplTest, GetCie_fail_should_not_cache) { | 
 | 434 |   ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr); | 
 | 435 |   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); | 
 | 436 |   this->section_->TestClearError(); | 
 | 437 |   ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr); | 
 | 438 |   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); | 
 | 439 | } | 
 | 440 |  | 
 | 441 | TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) { | 
 | 442 |   this->memory_.SetData32(0x5000, 0x100); | 
 | 443 |   this->memory_.SetData32(0x5004, 0xffffffff); | 
 | 444 |   this->memory_.SetData8(0x5008, 0x1); | 
 | 445 |   this->memory_.SetData8(0x5009, '\0'); | 
 | 446 |   this->memory_.SetData8(0x500a, 4); | 
 | 447 |   this->memory_.SetData8(0x500b, 8); | 
 | 448 |   this->memory_.SetData8(0x500c, 0x20); | 
 | 449 |  | 
 | 450 |   EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true)); | 
 | 451 |  | 
 | 452 |   const DwarfCie* cie = this->section_->GetCie(0x5000); | 
 | 453 |   ASSERT_TRUE(cie != nullptr); | 
 | 454 |   EXPECT_EQ(1U, cie->version); | 
 | 455 |   EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding); | 
 | 456 |   EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding); | 
 | 457 |   EXPECT_EQ(0U, cie->segment_size); | 
 | 458 |   EXPECT_EQ(1U, cie->augmentation_string.size()); | 
 | 459 |   EXPECT_EQ('\0', cie->augmentation_string[0]); | 
 | 460 |   EXPECT_EQ(0U, cie->personality_handler); | 
 | 461 |   EXPECT_EQ(0x500dU, cie->cfa_instructions_offset); | 
 | 462 |   EXPECT_EQ(0x5104U, cie->cfa_instructions_end); | 
 | 463 |   EXPECT_EQ(4U, cie->code_alignment_factor); | 
 | 464 |   EXPECT_EQ(8, cie->data_alignment_factor); | 
 | 465 |   EXPECT_EQ(0x20U, cie->return_address_register); | 
 | 466 |   EXPECT_EQ(DWARF_ERROR_NONE, this->section_->last_error()); | 
 | 467 |  | 
 | 468 |   this->section_->TestClearCachedCieEntry(); | 
 | 469 |   // Set version to 0, 2, 5 and verify we fail. | 
 | 470 |   this->memory_.SetData8(0x5008, 0x0); | 
 | 471 |   this->section_->TestClearError(); | 
 | 472 |   ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr); | 
 | 473 |   EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error()); | 
 | 474 |  | 
 | 475 |   this->memory_.SetData8(0x5008, 0x2); | 
 | 476 |   this->section_->TestClearError(); | 
 | 477 |   ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr); | 
 | 478 |   EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error()); | 
 | 479 |  | 
 | 480 |   this->memory_.SetData8(0x5008, 0x5); | 
 | 481 |   this->section_->TestClearError(); | 
 | 482 |   ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr); | 
 | 483 |   EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error()); | 
 | 484 | } | 
 | 485 |  | 
 | 486 | TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) { | 
 | 487 |   this->memory_.SetData32(0x5000, 0x100); | 
 | 488 |   this->memory_.SetData32(0x5004, 0xffffffff); | 
 | 489 |   this->memory_.SetData8(0x5008, 0x1); | 
 | 490 |   this->memory_.SetData8(0x5009, '\0'); | 
 | 491 |   this->memory_.SetData8(0x500a, 4); | 
 | 492 |   this->memory_.SetMemory(0x500b, std::vector<uint8_t>{0xfc, 0xff, 0xff, 0xff, 0x7f}); | 
 | 493 |   this->memory_.SetData8(0x5010, 0x20); | 
 | 494 |  | 
 | 495 |   EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true)); | 
 | 496 |  | 
 | 497 |   const DwarfCie* cie = this->section_->GetCie(0x5000); | 
 | 498 |   ASSERT_TRUE(cie != nullptr); | 
 | 499 |   EXPECT_EQ(1U, cie->version); | 
 | 500 |   EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding); | 
 | 501 |   EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding); | 
 | 502 |   EXPECT_EQ(0U, cie->segment_size); | 
 | 503 |   EXPECT_EQ(1U, cie->augmentation_string.size()); | 
 | 504 |   EXPECT_EQ('\0', cie->augmentation_string[0]); | 
 | 505 |   EXPECT_EQ(0U, cie->personality_handler); | 
 | 506 |   EXPECT_EQ(0x5011U, cie->cfa_instructions_offset); | 
 | 507 |   EXPECT_EQ(0x5104U, cie->cfa_instructions_end); | 
 | 508 |   EXPECT_EQ(4U, cie->code_alignment_factor); | 
 | 509 |   EXPECT_EQ(-4, cie->data_alignment_factor); | 
 | 510 |   EXPECT_EQ(0x20U, cie->return_address_register); | 
 | 511 | } | 
 | 512 |  | 
 | 513 | TYPED_TEST_P(DwarfSectionImplTest, GetCie_64_no_augment) { | 
 | 514 |   this->memory_.SetData32(0x8000, 0xffffffff); | 
 | 515 |   this->memory_.SetData64(0x8004, 0x200); | 
 | 516 |   this->memory_.SetData64(0x800c, 0xffffffff); | 
 | 517 |   this->memory_.SetData8(0x8014, 0x1); | 
 | 518 |   this->memory_.SetData8(0x8015, '\0'); | 
 | 519 |   this->memory_.SetData8(0x8016, 4); | 
 | 520 |   this->memory_.SetData8(0x8017, 8); | 
 | 521 |   this->memory_.SetData8(0x8018, 0x20); | 
 | 522 |  | 
 | 523 |   EXPECT_CALL(*this->section_, IsCie64(0xffffffff)).WillRepeatedly(::testing::Return(true)); | 
 | 524 |  | 
 | 525 |   const DwarfCie* cie = this->section_->GetCie(0x8000); | 
 | 526 |   ASSERT_TRUE(cie != nullptr); | 
 | 527 |   EXPECT_EQ(1U, cie->version); | 
 | 528 |   EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding); | 
 | 529 |   EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding); | 
 | 530 |   EXPECT_EQ(0U, cie->segment_size); | 
 | 531 |   EXPECT_EQ(1U, cie->augmentation_string.size()); | 
 | 532 |   EXPECT_EQ('\0', cie->augmentation_string[0]); | 
 | 533 |   EXPECT_EQ(0U, cie->personality_handler); | 
 | 534 |   EXPECT_EQ(0x8019U, cie->cfa_instructions_offset); | 
 | 535 |   EXPECT_EQ(0x820cU, cie->cfa_instructions_end); | 
 | 536 |   EXPECT_EQ(4U, cie->code_alignment_factor); | 
 | 537 |   EXPECT_EQ(8, cie->data_alignment_factor); | 
 | 538 |   EXPECT_EQ(0x20U, cie->return_address_register); | 
 | 539 | } | 
 | 540 |  | 
 | 541 | TYPED_TEST_P(DwarfSectionImplTest, GetCie_augment) { | 
 | 542 |   this->memory_.SetData32(0x5000, 0x100); | 
 | 543 |   this->memory_.SetData32(0x5004, 0xffffffff); | 
 | 544 |   this->memory_.SetData8(0x5008, 0x1); | 
 | 545 |   this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'}); | 
 | 546 |   this->memory_.SetData8(0x500e, 4); | 
 | 547 |   this->memory_.SetData8(0x500f, 8); | 
 | 548 |   this->memory_.SetData8(0x5010, 0x10); | 
 | 549 |   // Augment length. | 
 | 550 |   this->memory_.SetData8(0x5011, 0xf); | 
 | 551 |   // L data. | 
 | 552 |   this->memory_.SetData8(0x5012, DW_EH_PE_textrel | DW_EH_PE_udata2); | 
 | 553 |   // P data. | 
 | 554 |   this->memory_.SetData8(0x5013, DW_EH_PE_udata4); | 
 | 555 |   this->memory_.SetData32(0x5014, 0x12345678); | 
 | 556 |   // R data. | 
 | 557 |   this->memory_.SetData8(0x5018, DW_EH_PE_udata2); | 
 | 558 |  | 
 | 559 |   EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true)); | 
 | 560 |  | 
 | 561 |   const DwarfCie* cie = this->section_->GetCie(0x5000); | 
 | 562 |   ASSERT_TRUE(cie != nullptr); | 
 | 563 |   EXPECT_EQ(1U, cie->version); | 
 | 564 |   EXPECT_EQ(DW_EH_PE_udata2, cie->fde_address_encoding); | 
 | 565 |   EXPECT_EQ(DW_EH_PE_textrel | DW_EH_PE_udata2, cie->lsda_encoding); | 
 | 566 |   EXPECT_EQ(0U, cie->segment_size); | 
 | 567 |   EXPECT_EQ(5U, cie->augmentation_string.size()); | 
 | 568 |   EXPECT_EQ('z', cie->augmentation_string[0]); | 
 | 569 |   EXPECT_EQ('L', cie->augmentation_string[1]); | 
 | 570 |   EXPECT_EQ('P', cie->augmentation_string[2]); | 
 | 571 |   EXPECT_EQ('R', cie->augmentation_string[3]); | 
 | 572 |   EXPECT_EQ('\0', cie->augmentation_string[4]); | 
 | 573 |   EXPECT_EQ(0x12345678U, cie->personality_handler); | 
 | 574 |   EXPECT_EQ(0x5021U, cie->cfa_instructions_offset); | 
 | 575 |   EXPECT_EQ(0x5104U, cie->cfa_instructions_end); | 
 | 576 |   EXPECT_EQ(4U, cie->code_alignment_factor); | 
 | 577 |   EXPECT_EQ(8, cie->data_alignment_factor); | 
 | 578 |   EXPECT_EQ(0x10U, cie->return_address_register); | 
 | 579 | } | 
 | 580 |  | 
 | 581 | TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_3) { | 
 | 582 |   this->memory_.SetData32(0x5000, 0x100); | 
 | 583 |   this->memory_.SetData32(0x5004, 0xffffffff); | 
 | 584 |   this->memory_.SetData8(0x5008, 0x3); | 
 | 585 |   this->memory_.SetData8(0x5009, '\0'); | 
 | 586 |   this->memory_.SetData8(0x500a, 4); | 
 | 587 |   this->memory_.SetData8(0x500b, 8); | 
 | 588 |   this->memory_.SetMemory(0x500c, std::vector<uint8_t>{0x81, 0x03}); | 
 | 589 |  | 
 | 590 |   EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true)); | 
 | 591 |  | 
 | 592 |   const DwarfCie* cie = this->section_->GetCie(0x5000); | 
 | 593 |   ASSERT_TRUE(cie != nullptr); | 
 | 594 |   EXPECT_EQ(3U, cie->version); | 
 | 595 |   EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding); | 
 | 596 |   EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding); | 
 | 597 |   EXPECT_EQ(0U, cie->segment_size); | 
 | 598 |   EXPECT_EQ(1U, cie->augmentation_string.size()); | 
 | 599 |   EXPECT_EQ('\0', cie->augmentation_string[0]); | 
 | 600 |   EXPECT_EQ(0U, cie->personality_handler); | 
 | 601 |   EXPECT_EQ(0x500eU, cie->cfa_instructions_offset); | 
 | 602 |   EXPECT_EQ(0x5104U, cie->cfa_instructions_end); | 
 | 603 |   EXPECT_EQ(4U, cie->code_alignment_factor); | 
 | 604 |   EXPECT_EQ(8, cie->data_alignment_factor); | 
 | 605 |   EXPECT_EQ(0x181U, cie->return_address_register); | 
 | 606 | } | 
 | 607 |  | 
 | 608 | TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_4) { | 
 | 609 |   this->memory_.SetData32(0x5000, 0x100); | 
 | 610 |   this->memory_.SetData32(0x5004, 0xffffffff); | 
 | 611 |   this->memory_.SetData8(0x5008, 0x4); | 
 | 612 |   this->memory_.SetData8(0x5009, '\0'); | 
 | 613 |   this->memory_.SetData8(0x500a, 4); | 
 | 614 |   this->memory_.SetData8(0x500b, 0x13); | 
 | 615 |   this->memory_.SetData8(0x500c, 4); | 
 | 616 |   this->memory_.SetData8(0x500d, 8); | 
 | 617 |   this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x81, 0x03}); | 
 | 618 |  | 
 | 619 |   EXPECT_CALL(*this->section_, IsCie32(0xffffffff)).WillRepeatedly(::testing::Return(true)); | 
 | 620 |  | 
 | 621 |   const DwarfCie* cie = this->section_->GetCie(0x5000); | 
 | 622 |   ASSERT_TRUE(cie != nullptr); | 
 | 623 |   EXPECT_EQ(4U, cie->version); | 
 | 624 |   EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding); | 
 | 625 |   EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding); | 
 | 626 |   EXPECT_EQ(0x13U, cie->segment_size); | 
 | 627 |   EXPECT_EQ(1U, cie->augmentation_string.size()); | 
 | 628 |   EXPECT_EQ('\0', cie->augmentation_string[0]); | 
 | 629 |   EXPECT_EQ(0U, cie->personality_handler); | 
 | 630 |   EXPECT_EQ(0x5010U, cie->cfa_instructions_offset); | 
 | 631 |   EXPECT_EQ(0x5104U, cie->cfa_instructions_end); | 
 | 632 |   EXPECT_EQ(4U, cie->code_alignment_factor); | 
 | 633 |   EXPECT_EQ(8, cie->data_alignment_factor); | 
 | 634 |   EXPECT_EQ(0x181U, cie->return_address_register); | 
 | 635 | } | 
 | 636 |  | 
 | 637 | TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) { | 
 | 638 |   ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr); | 
 | 639 |   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); | 
 | 640 |   this->section_->TestClearError(); | 
 | 641 |   ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr); | 
 | 642 |   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); | 
 | 643 | } | 
 | 644 |  | 
 | 645 | TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) { | 
 | 646 |   this->memory_.SetData32(0x4000, 0x20); | 
 | 647 |   this->memory_.SetData32(0x4004, 0x8000); | 
 | 648 |   this->memory_.SetData32(0x4008, 0x5000); | 
 | 649 |   this->memory_.SetData32(0x400c, 0x100); | 
 | 650 |  | 
 | 651 |   EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false)); | 
 | 652 |   EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000)); | 
 | 653 |   DwarfCie cie{}; | 
 | 654 |   cie.fde_address_encoding = DW_EH_PE_udata4; | 
 | 655 |   this->section_->TestSetCachedCieEntry(0x8000, cie); | 
 | 656 |   EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000)); | 
 | 657 |  | 
 | 658 |   const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000); | 
 | 659 |   ASSERT_TRUE(fde != nullptr); | 
 | 660 |   ASSERT_TRUE(fde->cie != nullptr); | 
 | 661 |   EXPECT_EQ(0x4010U, fde->cfa_instructions_offset); | 
 | 662 |   EXPECT_EQ(0x4024U, fde->cfa_instructions_end); | 
 | 663 |   EXPECT_EQ(0x5000U, fde->pc_start); | 
 | 664 |   EXPECT_EQ(0x5100U, fde->pc_end); | 
 | 665 |   EXPECT_EQ(0x8000U, fde->cie_offset); | 
 | 666 |   EXPECT_EQ(0U, fde->lsda_address); | 
 | 667 | } | 
 | 668 |  | 
 | 669 | TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment_non_zero_segment_size) { | 
 | 670 |   this->memory_.SetData32(0x4000, 0x30); | 
 | 671 |   this->memory_.SetData32(0x4004, 0x8000); | 
 | 672 |   this->memory_.SetData32(0x4018, 0x5000); | 
 | 673 |   this->memory_.SetData32(0x401c, 0x100); | 
 | 674 |  | 
 | 675 |   EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false)); | 
 | 676 |   EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000)); | 
 | 677 |   DwarfCie cie{}; | 
 | 678 |   cie.fde_address_encoding = DW_EH_PE_udata4; | 
 | 679 |   cie.segment_size = 0x10; | 
 | 680 |   this->section_->TestSetCachedCieEntry(0x8000, cie); | 
 | 681 |   EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000)); | 
 | 682 |  | 
 | 683 |   const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000); | 
 | 684 |   ASSERT_TRUE(fde != nullptr); | 
 | 685 |   ASSERT_TRUE(fde->cie != nullptr); | 
 | 686 |   EXPECT_EQ(0x4020U, fde->cfa_instructions_offset); | 
 | 687 |   EXPECT_EQ(0x4034U, fde->cfa_instructions_end); | 
 | 688 |   EXPECT_EQ(0x5000U, fde->pc_start); | 
 | 689 |   EXPECT_EQ(0x5100U, fde->pc_end); | 
 | 690 |   EXPECT_EQ(0x8000U, fde->cie_offset); | 
 | 691 |   EXPECT_EQ(0U, fde->lsda_address); | 
 | 692 | } | 
 | 693 |  | 
 | 694 | TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_augment) { | 
 | 695 |   this->memory_.SetData32(0x4000, 0x100); | 
 | 696 |   this->memory_.SetData32(0x4004, 0x8000); | 
 | 697 |   this->memory_.SetData32(0x4008, 0x5000); | 
 | 698 |   this->memory_.SetData32(0x400c, 0x100); | 
 | 699 |   this->memory_.SetMemory(0x4010, std::vector<uint8_t>{0x82, 0x01}); | 
 | 700 |   this->memory_.SetData16(0x4012, 0x1234); | 
 | 701 |  | 
 | 702 |   EXPECT_CALL(*this->section_, IsCie32(0x8000)).WillOnce(::testing::Return(false)); | 
 | 703 |   EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000)); | 
 | 704 |   DwarfCie cie{}; | 
 | 705 |   cie.fde_address_encoding = DW_EH_PE_udata4; | 
 | 706 |   cie.augmentation_string.push_back('z'); | 
 | 707 |   cie.lsda_encoding = DW_EH_PE_udata2; | 
 | 708 |   this->section_->TestSetCachedCieEntry(0x8000, cie); | 
 | 709 |   EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000)); | 
 | 710 |  | 
 | 711 |   const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000); | 
 | 712 |   ASSERT_TRUE(fde != nullptr); | 
 | 713 |   ASSERT_TRUE(fde->cie != nullptr); | 
 | 714 |   EXPECT_EQ(0x4094U, fde->cfa_instructions_offset); | 
 | 715 |   EXPECT_EQ(0x4104U, fde->cfa_instructions_end); | 
 | 716 |   EXPECT_EQ(0x5000U, fde->pc_start); | 
 | 717 |   EXPECT_EQ(0x5100U, fde->pc_end); | 
 | 718 |   EXPECT_EQ(0x8000U, fde->cie_offset); | 
 | 719 |   EXPECT_EQ(0x1234U, fde->lsda_address); | 
 | 720 | } | 
 | 721 |  | 
 | 722 | TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_64_no_augment) { | 
 | 723 |   this->memory_.SetData32(0x4000, 0xffffffff); | 
 | 724 |   this->memory_.SetData64(0x4004, 0x100); | 
 | 725 |   this->memory_.SetData64(0x400c, 0x12345678); | 
 | 726 |   this->memory_.SetData32(0x4014, 0x5000); | 
 | 727 |   this->memory_.SetData32(0x4018, 0x100); | 
 | 728 |  | 
 | 729 |   EXPECT_CALL(*this->section_, IsCie64(0x12345678)).WillOnce(::testing::Return(false)); | 
 | 730 |   EXPECT_CALL(*this->section_, GetCieOffsetFromFde64(0x12345678)) | 
 | 731 |       .WillOnce(::testing::Return(0x12345678)); | 
 | 732 |   DwarfCie cie{}; | 
 | 733 |   cie.fde_address_encoding = DW_EH_PE_udata4; | 
 | 734 |   this->section_->TestSetCachedCieEntry(0x12345678, cie); | 
 | 735 |   EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000)); | 
 | 736 |  | 
 | 737 |   const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000); | 
 | 738 |   ASSERT_TRUE(fde != nullptr); | 
 | 739 |   ASSERT_TRUE(fde->cie != nullptr); | 
 | 740 |   EXPECT_EQ(0x401cU, fde->cfa_instructions_offset); | 
 | 741 |   EXPECT_EQ(0x410cU, fde->cfa_instructions_end); | 
 | 742 |   EXPECT_EQ(0x5000U, fde->pc_start); | 
 | 743 |   EXPECT_EQ(0x5100U, fde->pc_end); | 
 | 744 |   EXPECT_EQ(0x12345678U, fde->cie_offset); | 
 | 745 |   EXPECT_EQ(0U, fde->lsda_address); | 
 | 746 | } | 
 | 747 |  | 
 | 748 | TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_cached) { | 
 | 749 |   DwarfCie cie{}; | 
 | 750 |   cie.fde_address_encoding = DW_EH_PE_udata4; | 
 | 751 |   cie.augmentation_string.push_back('z'); | 
 | 752 |   cie.lsda_encoding = DW_EH_PE_udata2; | 
 | 753 |  | 
 | 754 |   DwarfFde fde_cached{}; | 
 | 755 |   fde_cached.cfa_instructions_offset = 0x1000; | 
 | 756 |   fde_cached.cfa_instructions_end = 0x1100; | 
 | 757 |   fde_cached.pc_start = 0x9000; | 
 | 758 |   fde_cached.pc_end = 0x9400; | 
 | 759 |   fde_cached.cie_offset = 0x30000; | 
 | 760 |   fde_cached.cie = &cie; | 
 | 761 |   this->section_->TestSetCachedFdeEntry(0x6000, fde_cached); | 
 | 762 |  | 
 | 763 |   const DwarfFde* fde = this->section_->GetFdeFromOffset(0x6000); | 
 | 764 |   ASSERT_TRUE(fde != nullptr); | 
 | 765 |   ASSERT_EQ(&cie, fde->cie); | 
 | 766 |   EXPECT_EQ(0x1000U, fde->cfa_instructions_offset); | 
 | 767 |   EXPECT_EQ(0x1100U, fde->cfa_instructions_end); | 
 | 768 |   EXPECT_EQ(0x9000U, fde->pc_start); | 
 | 769 |   EXPECT_EQ(0x9400U, fde->pc_end); | 
 | 770 |   EXPECT_EQ(0x30000U, fde->cie_offset); | 
 | 771 | } | 
 | 772 |  | 
 | 773 | TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) { | 
 | 774 |   DwarfCie cie{}; | 
 | 775 |   cie.cfa_instructions_offset = 0x3000; | 
 | 776 |   cie.cfa_instructions_end = 0x3002; | 
 | 777 |   DwarfFde fde{}; | 
 | 778 |   fde.cie = &cie; | 
 | 779 |   fde.cie_offset = 0x8000; | 
 | 780 |   fde.cfa_instructions_offset = 0x6000; | 
 | 781 |   fde.cfa_instructions_end = 0x6002; | 
 | 782 |  | 
 | 783 |   this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x09, 0x02, 0x01}); | 
 | 784 |   this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03}); | 
 | 785 |  | 
 | 786 |   dwarf_loc_regs_t loc_regs; | 
 | 787 |   ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs)); | 
 | 788 |   ASSERT_EQ(2U, loc_regs.size()); | 
 | 789 |  | 
 | 790 |   auto entry = loc_regs.find(2); | 
 | 791 |   ASSERT_NE(entry, loc_regs.end()); | 
 | 792 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type); | 
 | 793 |   ASSERT_EQ(1U, entry->second.values[0]); | 
 | 794 |  | 
 | 795 |   entry = loc_regs.find(4); | 
 | 796 |   ASSERT_NE(entry, loc_regs.end()); | 
 | 797 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type); | 
 | 798 |   ASSERT_EQ(3U, entry->second.values[0]); | 
 | 799 | } | 
 | 800 |  | 
 | 801 | TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) { | 
 | 802 |   DwarfCie cie{}; | 
 | 803 |   cie.cfa_instructions_offset = 0x3000; | 
 | 804 |   cie.cfa_instructions_end = 0x3002; | 
 | 805 |   DwarfFde fde{}; | 
 | 806 |   fde.cie = &cie; | 
 | 807 |   fde.cie_offset = 0x8000; | 
 | 808 |   fde.cfa_instructions_offset = 0x6000; | 
 | 809 |   fde.cfa_instructions_end = 0x6002; | 
 | 810 |  | 
 | 811 |   dwarf_loc_regs_t cie_loc_regs{{6, {DWARF_LOCATION_REGISTER, {4, 0}}}}; | 
 | 812 |   this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs); | 
 | 813 |   this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03}); | 
 | 814 |  | 
 | 815 |   dwarf_loc_regs_t loc_regs; | 
 | 816 |   ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs)); | 
 | 817 |   ASSERT_EQ(2U, loc_regs.size()); | 
 | 818 |  | 
 | 819 |   auto entry = loc_regs.find(6); | 
 | 820 |   ASSERT_NE(entry, loc_regs.end()); | 
 | 821 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type); | 
 | 822 |   ASSERT_EQ(4U, entry->second.values[0]); | 
 | 823 |  | 
 | 824 |   entry = loc_regs.find(4); | 
 | 825 |   ASSERT_NE(entry, loc_regs.end()); | 
 | 826 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type); | 
 | 827 |   ASSERT_EQ(3U, entry->second.values[0]); | 
 | 828 | } | 
 | 829 |  | 
 | 830 | TYPED_TEST_P(DwarfSectionImplTest, Log) { | 
 | 831 |   DwarfCie cie{}; | 
 | 832 |   cie.cfa_instructions_offset = 0x5000; | 
 | 833 |   cie.cfa_instructions_end = 0x5001; | 
 | 834 |   DwarfFde fde{}; | 
 | 835 |   fde.cie = &cie; | 
 | 836 |   fde.cfa_instructions_offset = 0x6000; | 
 | 837 |   fde.cfa_instructions_end = 0x6001; | 
 | 838 |  | 
 | 839 |   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00}); | 
 | 840 |   this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2}); | 
 | 841 |   ASSERT_TRUE(this->section_->Log(2, 0x1000, 0x1000, &fde)); | 
 | 842 |  | 
 | 843 |   ASSERT_EQ( | 
 | 844 |       "4 unwind     DW_CFA_nop\n" | 
 | 845 |       "4 unwind     Raw Data: 0x00\n" | 
 | 846 |       "4 unwind     DW_CFA_restore register(2)\n" | 
 | 847 |       "4 unwind     Raw Data: 0xc2\n", | 
 | 848 |       GetFakeLogPrint()); | 
 | 849 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 850 | } | 
 | 851 |  | 
 | 852 | REGISTER_TYPED_TEST_CASE_P( | 
 | 853 |     DwarfSectionImplTest, Eval_cfa_expr_eval_fail, Eval_cfa_expr_no_stack, | 
 | 854 |     Eval_cfa_expr_is_register, Eval_cfa_expr, Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, | 
 | 855 |     Eval_cfa_bad, Eval_cfa_register_prev, Eval_cfa_register_from_value, Eval_double_indirection, | 
 | 856 |     Eval_invalid_register, Eval_different_reg_locations, Eval_return_address_undefined, | 
 | 857 |     Eval_return_address, Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr, | 
 | 858 |     Eval_same_cfa_same_pc, GetCie_fail_should_not_cache, GetCie_32_version_check, | 
 | 859 |     GetCie_negative_data_alignment_factor, GetCie_64_no_augment, GetCie_augment, GetCie_version_3, | 
 | 860 |     GetCie_version_4, GetFdeFromOffset_fail_should_not_cache, GetFdeFromOffset_32_no_augment, | 
 | 861 |     GetFdeFromOffset_32_no_augment_non_zero_segment_size, GetFdeFromOffset_32_augment, | 
 | 862 |     GetFdeFromOffset_64_no_augment, GetFdeFromOffset_cached, GetCfaLocationInfo_cie_not_cached, | 
 | 863 |     GetCfaLocationInfo_cie_cached, Log); | 
 | 864 |  | 
 | 865 | typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes; | 
 | 866 | INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes); | 
| Christopher Ferris | d226a51 | 2017-07-14 10:37:19 -0700 | [diff] [blame] | 867 |  | 
 | 868 | }  // namespace unwindstack |