| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -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 <memory> | 
 | 20 | #include <unordered_map> | 
 | 21 |  | 
 | 22 | #include <gtest/gtest.h> | 
 | 23 |  | 
| Christopher Ferris | 2fcf4cf | 2018-01-23 17:52:23 -0800 | [diff] [blame] | 24 | #include <unwindstack/DwarfError.h> | 
| Christopher Ferris | d226a51 | 2017-07-14 10:37:19 -0700 | [diff] [blame] | 25 | #include <unwindstack/DwarfLocation.h> | 
 | 26 | #include <unwindstack/DwarfMemory.h> | 
 | 27 | #include <unwindstack/DwarfStructs.h> | 
 | 28 | #include <unwindstack/Log.h> | 
 | 29 |  | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 30 | #include "DwarfCfa.h" | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 31 |  | 
 | 32 | #include "LogFake.h" | 
 | 33 | #include "MemoryFake.h" | 
 | 34 |  | 
| Christopher Ferris | d226a51 | 2017-07-14 10:37:19 -0700 | [diff] [blame] | 35 | namespace unwindstack { | 
 | 36 |  | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 37 | template <typename TypeParam> | 
 | 38 | class DwarfCfaTest : public ::testing::Test { | 
 | 39 |  protected: | 
 | 40 |   void SetUp() override { | 
 | 41 |     ResetLogs(); | 
 | 42 |     memory_.Clear(); | 
 | 43 |  | 
 | 44 |     dmem_.reset(new DwarfMemory(&memory_)); | 
 | 45 |  | 
 | 46 |     cie_.cfa_instructions_offset = 0x1000; | 
 | 47 |     cie_.cfa_instructions_end = 0x1030; | 
 | 48 |     // These two values should be different to distinguish between | 
 | 49 |     // operations that deal with code versus data. | 
 | 50 |     cie_.code_alignment_factor = 4; | 
 | 51 |     cie_.data_alignment_factor = 8; | 
 | 52 |  | 
 | 53 |     fde_.cfa_instructions_offset = 0x2000; | 
 | 54 |     fde_.cfa_instructions_end = 0x2030; | 
 | 55 |     fde_.pc_start = 0x2000; | 
 | 56 |     fde_.cie = &cie_; | 
 | 57 |  | 
 | 58 |     cfa_.reset(new DwarfCfa<TypeParam>(dmem_.get(), &fde_)); | 
 | 59 |   } | 
 | 60 |  | 
 | 61 |   MemoryFake memory_; | 
 | 62 |   std::unique_ptr<DwarfMemory> dmem_; | 
 | 63 |   std::unique_ptr<DwarfCfa<TypeParam>> cfa_; | 
| Christopher Ferris | 53a3c9b | 2017-05-10 18:34:15 -0700 | [diff] [blame] | 64 |   DwarfCie cie_; | 
 | 65 |   DwarfFde fde_; | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 66 | }; | 
 | 67 | TYPED_TEST_CASE_P(DwarfCfaTest); | 
 | 68 |  | 
 | 69 | // NOTE: All test class variables need to be referenced as this->. | 
 | 70 |  | 
 | 71 | TYPED_TEST_P(DwarfCfaTest, cfa_illegal) { | 
 | 72 |   for (uint8_t i = 0x17; i < 0x3f; i++) { | 
 | 73 |     if (i == 0x2e || i == 0x2f) { | 
 | 74 |       // Skip gnu extension ops. | 
 | 75 |       continue; | 
 | 76 |     } | 
 | 77 |     this->memory_.SetMemory(0x2000, std::vector<uint8_t>{i}); | 
 | 78 |     dwarf_loc_regs_t loc_regs; | 
 | 79 |  | 
 | 80 |     ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); | 
| Christopher Ferris | 2fcf4cf | 2018-01-23 17:52:23 -0800 | [diff] [blame] | 81 |     ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->LastErrorCode()); | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 82 |     ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); | 
 | 83 |  | 
 | 84 |     ASSERT_EQ("", GetFakeLogPrint()); | 
 | 85 |     ASSERT_EQ("", GetFakeLogBuf()); | 
 | 86 |   } | 
 | 87 | } | 
 | 88 |  | 
 | 89 | TYPED_TEST_P(DwarfCfaTest, cfa_nop) { | 
 | 90 |   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x00}); | 
 | 91 |   dwarf_loc_regs_t loc_regs; | 
 | 92 |  | 
 | 93 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); | 
 | 94 |   ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); | 
 | 95 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 96 |  | 
 | 97 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 98 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 99 | } | 
 | 100 |  | 
 | 101 | // This test needs to be examined. | 
 | 102 | TYPED_TEST_P(DwarfCfaTest, cfa_offset) { | 
 | 103 |   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x83, 0x04}); | 
 | 104 |   dwarf_loc_regs_t loc_regs; | 
 | 105 |  | 
 | 106 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2002, &loc_regs)); | 
 | 107 |   ASSERT_EQ(0x2002U, this->dmem_->cur_offset()); | 
 | 108 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 109 |   auto location = loc_regs.find(3); | 
 | 110 |   ASSERT_NE(loc_regs.end(), location); | 
 | 111 |   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); | 
 | 112 |   ASSERT_EQ(32U, location->second.values[0]); | 
 | 113 |  | 
 | 114 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 115 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 116 |  | 
 | 117 |   ResetLogs(); | 
 | 118 |   this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x83, 0x84, 0x01}); | 
 | 119 |   loc_regs.clear(); | 
 | 120 |  | 
 | 121 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2100, 0x2103, &loc_regs)); | 
 | 122 |   ASSERT_EQ(0x2103U, this->dmem_->cur_offset()); | 
 | 123 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 124 |   location = loc_regs.find(3); | 
 | 125 |   ASSERT_NE(loc_regs.end(), location); | 
 | 126 |   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); | 
 | 127 |   ASSERT_EQ(1056U, location->second.values[0]); | 
 | 128 |  | 
 | 129 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 130 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 131 | } | 
 | 132 |  | 
 | 133 | TYPED_TEST_P(DwarfCfaTest, cfa_offset_extended) { | 
 | 134 |   this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x05, 0x03, 0x02}); | 
 | 135 |   dwarf_loc_regs_t loc_regs; | 
 | 136 |  | 
 | 137 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs)); | 
 | 138 |   ASSERT_EQ(0x503U, this->dmem_->cur_offset()); | 
 | 139 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 140 |   auto location = loc_regs.find(3); | 
 | 141 |   ASSERT_NE(loc_regs.end(), location); | 
 | 142 |   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); | 
 | 143 |   ASSERT_EQ(2U, location->second.values[0]); | 
 | 144 |  | 
 | 145 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 146 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 147 |  | 
 | 148 |   ResetLogs(); | 
 | 149 |   loc_regs.clear(); | 
 | 150 |   this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x05, 0x81, 0x01, 0x82, 0x12}); | 
 | 151 |  | 
 | 152 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs)); | 
 | 153 |   ASSERT_EQ(0x1505U, this->dmem_->cur_offset()); | 
 | 154 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 155 |   location = loc_regs.find(129); | 
 | 156 |   ASSERT_NE(loc_regs.end(), location); | 
 | 157 |   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); | 
 | 158 |   ASSERT_EQ(2306U, location->second.values[0]); | 
 | 159 |  | 
 | 160 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 161 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 162 | } | 
 | 163 |  | 
 | 164 | TYPED_TEST_P(DwarfCfaTest, cfa_offset_extended_sf) { | 
 | 165 |   this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x11, 0x05, 0x10}); | 
 | 166 |   dwarf_loc_regs_t loc_regs; | 
 | 167 |  | 
 | 168 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs)); | 
 | 169 |   ASSERT_EQ(0x503U, this->dmem_->cur_offset()); | 
 | 170 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 171 |   auto location = loc_regs.find(5); | 
 | 172 |   ASSERT_NE(loc_regs.end(), location); | 
 | 173 |   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); | 
 | 174 |   ASSERT_EQ(0x80U, location->second.values[0]); | 
 | 175 |  | 
 | 176 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 177 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 178 |  | 
 | 179 |   // Check a negative value for the offset. | 
 | 180 |   ResetLogs(); | 
 | 181 |   loc_regs.clear(); | 
 | 182 |   this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x11, 0x86, 0x01, 0xff, 0x7f}); | 
 | 183 |  | 
 | 184 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs)); | 
 | 185 |   ASSERT_EQ(0x1505U, this->dmem_->cur_offset()); | 
 | 186 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 187 |   location = loc_regs.find(134); | 
 | 188 |   ASSERT_NE(loc_regs.end(), location); | 
 | 189 |   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); | 
 | 190 |   ASSERT_EQ(static_cast<uint64_t>(-8), location->second.values[0]); | 
 | 191 |  | 
 | 192 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 193 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 194 | } | 
 | 195 |  | 
 | 196 | TYPED_TEST_P(DwarfCfaTest, cfa_restore) { | 
 | 197 |   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0xc2}); | 
 | 198 |   dwarf_loc_regs_t loc_regs; | 
 | 199 |  | 
 | 200 |   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); | 
| Christopher Ferris | 2fcf4cf | 2018-01-23 17:52:23 -0800 | [diff] [blame] | 201 |   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 202 |   ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); | 
 | 203 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 204 |  | 
 | 205 |   ASSERT_EQ("4 unwind restore while processing cie\n", GetFakeLogPrint()); | 
 | 206 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 207 |  | 
 | 208 |   ResetLogs(); | 
 | 209 |   dwarf_loc_regs_t cie_loc_regs; | 
 | 210 |   cie_loc_regs[2] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}}; | 
 | 211 |   this->cfa_->set_cie_loc_regs(&cie_loc_regs); | 
 | 212 |   this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x82, 0x04, 0xc2}); | 
 | 213 |  | 
 | 214 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x3000, 0x3003, &loc_regs)); | 
 | 215 |   ASSERT_EQ(0x3003U, this->dmem_->cur_offset()); | 
 | 216 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 217 |   auto location = loc_regs.find(2); | 
 | 218 |   ASSERT_NE(loc_regs.end(), location); | 
 | 219 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type); | 
 | 220 |  | 
 | 221 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 222 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 223 | } | 
 | 224 |  | 
 | 225 | TYPED_TEST_P(DwarfCfaTest, cfa_restore_extended) { | 
 | 226 |   this->memory_.SetMemory(0x4000, std::vector<uint8_t>{0x06, 0x08}); | 
 | 227 |   dwarf_loc_regs_t loc_regs; | 
 | 228 |  | 
 | 229 |   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4000, 0x4002, &loc_regs)); | 
| Christopher Ferris | 2fcf4cf | 2018-01-23 17:52:23 -0800 | [diff] [blame] | 230 |   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 231 |   ASSERT_EQ(0x4002U, this->dmem_->cur_offset()); | 
 | 232 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 233 |  | 
 | 234 |   ASSERT_EQ("4 unwind restore while processing cie\n", GetFakeLogPrint()); | 
 | 235 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 236 |  | 
 | 237 |   ResetLogs(); | 
 | 238 |   loc_regs.clear(); | 
 | 239 |   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x05, 0x82, 0x02, 0x04, 0x06, 0x82, 0x02}); | 
 | 240 |   dwarf_loc_regs_t cie_loc_regs; | 
 | 241 |   cie_loc_regs[258] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}}; | 
 | 242 |   this->cfa_->set_cie_loc_regs(&cie_loc_regs); | 
 | 243 |  | 
 | 244 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x5000, 0x5007, &loc_regs)); | 
 | 245 |   ASSERT_EQ(0x5007U, this->dmem_->cur_offset()); | 
 | 246 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 247 |   auto location = loc_regs.find(258); | 
 | 248 |   ASSERT_NE(loc_regs.end(), location); | 
 | 249 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type); | 
 | 250 |  | 
 | 251 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 252 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 253 | } | 
 | 254 |  | 
 | 255 | TYPED_TEST_P(DwarfCfaTest, cfa_set_loc) { | 
 | 256 |   uint8_t buffer[1 + sizeof(TypeParam)]; | 
 | 257 |   buffer[0] = 0x1; | 
 | 258 |   TypeParam address; | 
 | 259 |   std::string raw_data("Raw Data: 0x01 "); | 
 | 260 |   std::string address_str; | 
 | 261 |   if (sizeof(TypeParam) == 4) { | 
 | 262 |     address = 0x81234578U; | 
 | 263 |     address_str = "0x81234578"; | 
 | 264 |     raw_data += "0x78 0x45 0x23 0x81"; | 
 | 265 |   } else { | 
 | 266 |     address = 0x8123456712345678ULL; | 
 | 267 |     address_str = "0x8123456712345678"; | 
 | 268 |     raw_data += "0x78 0x56 0x34 0x12 0x67 0x45 0x23 0x81"; | 
 | 269 |   } | 
 | 270 |   memcpy(&buffer[1], &address, sizeof(address)); | 
 | 271 |  | 
 | 272 |   this->memory_.SetMemory(0x50, buffer, sizeof(buffer)); | 
 | 273 |   ResetLogs(); | 
 | 274 |   dwarf_loc_regs_t loc_regs; | 
 | 275 |   ASSERT_TRUE( | 
 | 276 |       this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam), &loc_regs)); | 
 | 277 |   ASSERT_EQ(0x51 + sizeof(TypeParam), this->dmem_->cur_offset()); | 
 | 278 |   ASSERT_EQ(address, this->cfa_->cur_pc()); | 
 | 279 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 280 |  | 
 | 281 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 282 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 283 |  | 
 | 284 |   // Check for a set going back. | 
 | 285 |   ResetLogs(); | 
 | 286 |   loc_regs.clear(); | 
 | 287 |   this->fde_.pc_start = address + 0x10; | 
 | 288 |   ASSERT_TRUE( | 
 | 289 |       this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam), &loc_regs)); | 
 | 290 |   ASSERT_EQ(0x51 + sizeof(TypeParam), this->dmem_->cur_offset()); | 
 | 291 |   ASSERT_EQ(address, this->cfa_->cur_pc()); | 
 | 292 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 293 |  | 
 | 294 |   std::string cur_address_str(address_str); | 
 | 295 |   cur_address_str[cur_address_str.size() - 2] = '8'; | 
 | 296 |   std::string expected = "4 unwind Warning: PC is moving backwards: old " + cur_address_str + | 
 | 297 |                          " new " + address_str + "\n"; | 
 | 298 |   ASSERT_EQ(expected, GetFakeLogPrint()); | 
 | 299 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 300 | } | 
 | 301 |  | 
 | 302 | TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc1) { | 
 | 303 |   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x02, 0x04}); | 
 | 304 |   dwarf_loc_regs_t loc_regs; | 
 | 305 |  | 
 | 306 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x202, &loc_regs)); | 
 | 307 |   ASSERT_EQ(0x202U, this->dmem_->cur_offset()); | 
 | 308 |   ASSERT_EQ(this->fde_.pc_start + 0x10, this->cfa_->cur_pc()); | 
 | 309 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 310 |  | 
 | 311 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 312 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 313 | } | 
 | 314 |  | 
 | 315 | TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc2) { | 
 | 316 |   this->memory_.SetMemory(0x600, std::vector<uint8_t>{0x03, 0x04, 0x03}); | 
 | 317 |   dwarf_loc_regs_t loc_regs; | 
 | 318 |  | 
 | 319 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x600, 0x603, &loc_regs)); | 
 | 320 |   ASSERT_EQ(0x603U, this->dmem_->cur_offset()); | 
 | 321 |   ASSERT_EQ(this->fde_.pc_start + 0xc10U, this->cfa_->cur_pc()); | 
 | 322 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 323 |  | 
 | 324 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 325 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 326 | } | 
 | 327 |  | 
 | 328 | TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc4) { | 
 | 329 |   this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x04, 0x04, 0x03, 0x02, 0x01}); | 
 | 330 |   dwarf_loc_regs_t loc_regs; | 
 | 331 |  | 
 | 332 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x505, &loc_regs)); | 
 | 333 |   ASSERT_EQ(0x505U, this->dmem_->cur_offset()); | 
 | 334 |   ASSERT_EQ(this->fde_.pc_start + 0x4080c10, this->cfa_->cur_pc()); | 
 | 335 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 336 |  | 
 | 337 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 338 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 339 | } | 
 | 340 |  | 
 | 341 | TYPED_TEST_P(DwarfCfaTest, cfa_undefined) { | 
 | 342 |   this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x07, 0x09}); | 
 | 343 |   dwarf_loc_regs_t loc_regs; | 
 | 344 |  | 
 | 345 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xa02, &loc_regs)); | 
 | 346 |   ASSERT_EQ(0xa02U, this->dmem_->cur_offset()); | 
 | 347 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 348 |   auto location = loc_regs.find(9); | 
 | 349 |   ASSERT_NE(loc_regs.end(), location); | 
 | 350 |   ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location->second.type); | 
 | 351 |  | 
 | 352 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 353 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 354 |  | 
 | 355 |   ResetLogs(); | 
 | 356 |   loc_regs.clear(); | 
 | 357 |   this->memory_.SetMemory(0x1a00, std::vector<uint8_t>{0x07, 0x81, 0x01}); | 
 | 358 |  | 
 | 359 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1a00, 0x1a03, &loc_regs)); | 
 | 360 |   ASSERT_EQ(0x1a03U, this->dmem_->cur_offset()); | 
 | 361 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 362 |   location = loc_regs.find(129); | 
 | 363 |   ASSERT_NE(loc_regs.end(), location); | 
 | 364 |   ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location->second.type); | 
 | 365 |  | 
 | 366 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 367 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 368 | } | 
 | 369 |  | 
 | 370 | TYPED_TEST_P(DwarfCfaTest, cfa_same) { | 
 | 371 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x08, 0x7f}); | 
 | 372 |   dwarf_loc_regs_t loc_regs; | 
 | 373 |  | 
 | 374 |   loc_regs[127] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}}; | 
 | 375 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); | 
 | 376 |   ASSERT_EQ(0x102U, this->dmem_->cur_offset()); | 
 | 377 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 378 |   ASSERT_EQ(0U, loc_regs.count(127)); | 
 | 379 |  | 
 | 380 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 381 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 382 |  | 
 | 383 |   ResetLogs(); | 
 | 384 |   loc_regs.clear(); | 
 | 385 |   this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x08, 0xff, 0x01}); | 
 | 386 |  | 
 | 387 |   loc_regs[255] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}}; | 
 | 388 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2100, 0x2103, &loc_regs)); | 
 | 389 |   ASSERT_EQ(0x2103U, this->dmem_->cur_offset()); | 
 | 390 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 391 |   ASSERT_EQ(0U, loc_regs.count(255)); | 
 | 392 |  | 
 | 393 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 394 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 395 | } | 
 | 396 |  | 
 | 397 | TYPED_TEST_P(DwarfCfaTest, cfa_register) { | 
 | 398 |   this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01}); | 
 | 399 |   dwarf_loc_regs_t loc_regs; | 
 | 400 |  | 
 | 401 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x303, &loc_regs)); | 
 | 402 |   ASSERT_EQ(0x303U, this->dmem_->cur_offset()); | 
 | 403 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 404 |   auto location = loc_regs.find(2); | 
 | 405 |   ASSERT_NE(loc_regs.end(), location); | 
 | 406 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type); | 
 | 407 |   ASSERT_EQ(1U, location->second.values[0]); | 
 | 408 |  | 
 | 409 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 410 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 411 |  | 
 | 412 |   ResetLogs(); | 
 | 413 |   loc_regs.clear(); | 
 | 414 |   this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x09, 0xff, 0x01, 0xff, 0x03}); | 
 | 415 |  | 
 | 416 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4300, 0x4305, &loc_regs)); | 
 | 417 |   ASSERT_EQ(0x4305U, this->dmem_->cur_offset()); | 
 | 418 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 419 |   location = loc_regs.find(255); | 
 | 420 |   ASSERT_NE(loc_regs.end(), location); | 
 | 421 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type); | 
 | 422 |   ASSERT_EQ(511U, location->second.values[0]); | 
 | 423 |  | 
 | 424 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 425 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 426 | } | 
 | 427 |  | 
 | 428 | TYPED_TEST_P(DwarfCfaTest, cfa_state) { | 
 | 429 |   this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x0a}); | 
 | 430 |   dwarf_loc_regs_t loc_regs; | 
 | 431 |  | 
 | 432 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x301, &loc_regs)); | 
 | 433 |   ASSERT_EQ(0x301U, this->dmem_->cur_offset()); | 
 | 434 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 435 |  | 
 | 436 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 437 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 438 |  | 
 | 439 |   ResetLogs(); | 
 | 440 |   this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x0b}); | 
 | 441 |  | 
 | 442 |   loc_regs.clear(); | 
 | 443 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4300, 0x4301, &loc_regs)); | 
 | 444 |   ASSERT_EQ(0x4301U, this->dmem_->cur_offset()); | 
 | 445 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 446 |  | 
 | 447 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 448 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 449 |  | 
 | 450 |   ResetLogs(); | 
 | 451 |   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x85, 0x02, 0x0a, 0x86, 0x04, 0x0b}); | 
 | 452 |  | 
 | 453 |   loc_regs.clear(); | 
 | 454 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2005, &loc_regs)); | 
 | 455 |   ASSERT_EQ(0x2005U, this->dmem_->cur_offset()); | 
 | 456 |   ASSERT_EQ(2U, loc_regs.size()); | 
 | 457 |   ASSERT_NE(loc_regs.end(), loc_regs.find(5)); | 
 | 458 |   ASSERT_NE(loc_regs.end(), loc_regs.find(6)); | 
 | 459 |  | 
 | 460 |   loc_regs.clear(); | 
 | 461 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2006, &loc_regs)); | 
 | 462 |   ASSERT_EQ(0x2006U, this->dmem_->cur_offset()); | 
 | 463 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 464 |   ASSERT_NE(loc_regs.end(), loc_regs.find(5)); | 
 | 465 |  | 
 | 466 |   ResetLogs(); | 
 | 467 |   this->memory_.SetMemory( | 
 | 468 |       0x6000, std::vector<uint8_t>{0x0a, 0x85, 0x02, 0x0a, 0x86, 0x04, 0x0a, 0x87, 0x01, 0x0a, 0x89, | 
 | 469 |                                    0x05, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}); | 
 | 470 |  | 
 | 471 |   loc_regs.clear(); | 
 | 472 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600c, &loc_regs)); | 
 | 473 |   ASSERT_EQ(0x600cU, this->dmem_->cur_offset()); | 
 | 474 |   ASSERT_EQ(4U, loc_regs.size()); | 
 | 475 |   ASSERT_NE(loc_regs.end(), loc_regs.find(5)); | 
 | 476 |   ASSERT_NE(loc_regs.end(), loc_regs.find(6)); | 
 | 477 |   ASSERT_NE(loc_regs.end(), loc_regs.find(7)); | 
 | 478 |   ASSERT_NE(loc_regs.end(), loc_regs.find(9)); | 
 | 479 |  | 
 | 480 |   loc_regs.clear(); | 
 | 481 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600d, &loc_regs)); | 
 | 482 |   ASSERT_EQ(0x600dU, this->dmem_->cur_offset()); | 
 | 483 |   ASSERT_EQ(3U, loc_regs.size()); | 
 | 484 |   ASSERT_NE(loc_regs.end(), loc_regs.find(5)); | 
 | 485 |   ASSERT_NE(loc_regs.end(), loc_regs.find(6)); | 
 | 486 |   ASSERT_NE(loc_regs.end(), loc_regs.find(7)); | 
 | 487 |  | 
 | 488 |   loc_regs.clear(); | 
 | 489 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600e, &loc_regs)); | 
 | 490 |   ASSERT_EQ(0x600eU, this->dmem_->cur_offset()); | 
 | 491 |   ASSERT_EQ(2U, loc_regs.size()); | 
 | 492 |   ASSERT_NE(loc_regs.end(), loc_regs.find(5)); | 
 | 493 |   ASSERT_NE(loc_regs.end(), loc_regs.find(6)); | 
 | 494 |  | 
 | 495 |   loc_regs.clear(); | 
 | 496 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600f, &loc_regs)); | 
 | 497 |   ASSERT_EQ(0x600fU, this->dmem_->cur_offset()); | 
 | 498 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 499 |   ASSERT_NE(loc_regs.end(), loc_regs.find(5)); | 
 | 500 |  | 
 | 501 |   loc_regs.clear(); | 
 | 502 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x6010, &loc_regs)); | 
 | 503 |   ASSERT_EQ(0x6010U, this->dmem_->cur_offset()); | 
 | 504 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 505 |  | 
 | 506 |   loc_regs.clear(); | 
 | 507 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x6011, &loc_regs)); | 
 | 508 |   ASSERT_EQ(0x6011U, this->dmem_->cur_offset()); | 
 | 509 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 510 | } | 
 | 511 |  | 
 | 512 | // This test verifies that the cfa offset is saved and restored properly. | 
 | 513 | // Even though the spec is not clear about whether the offset is also | 
 | 514 | // restored, the gcc unwinder does, and libunwind does too. | 
 | 515 | TYPED_TEST_P(DwarfCfaTest, cfa_state_cfa_offset_restore) { | 
 | 516 |   this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x0a, 0x0e, 0x40, 0x0b}); | 
 | 517 |   dwarf_loc_regs_t loc_regs; | 
 | 518 |   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {5, 100}}; | 
 | 519 |  | 
 | 520 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x3000, 0x3004, &loc_regs)); | 
 | 521 |   ASSERT_EQ(0x3004U, this->dmem_->cur_offset()); | 
 | 522 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 523 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 524 |   ASSERT_EQ(5U, loc_regs[CFA_REG].values[0]); | 
 | 525 |   ASSERT_EQ(100U, loc_regs[CFA_REG].values[1]); | 
 | 526 |  | 
 | 527 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 528 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 529 | } | 
 | 530 |  | 
 | 531 | TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa) { | 
 | 532 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0c, 0x7f, 0x74}); | 
 | 533 |   dwarf_loc_regs_t loc_regs; | 
 | 534 |  | 
 | 535 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs)); | 
 | 536 |   ASSERT_EQ(0x103U, this->dmem_->cur_offset()); | 
 | 537 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 538 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 539 |   ASSERT_EQ(0x7fU, loc_regs[CFA_REG].values[0]); | 
 | 540 |   ASSERT_EQ(0x74U, loc_regs[CFA_REG].values[1]); | 
 | 541 |  | 
 | 542 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 543 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 544 |  | 
 | 545 |   ResetLogs(); | 
 | 546 |   loc_regs.clear(); | 
 | 547 |   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0c, 0xff, 0x02, 0xf4, 0x04}); | 
 | 548 |  | 
 | 549 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x205, &loc_regs)); | 
 | 550 |   ASSERT_EQ(0x205U, this->dmem_->cur_offset()); | 
 | 551 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 552 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 553 |   ASSERT_EQ(0x17fU, loc_regs[CFA_REG].values[0]); | 
 | 554 |   ASSERT_EQ(0x274U, loc_regs[CFA_REG].values[1]); | 
 | 555 |  | 
 | 556 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 557 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 558 | } | 
 | 559 |  | 
 | 560 | TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_sf) { | 
 | 561 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x12, 0x30, 0x25}); | 
 | 562 |   dwarf_loc_regs_t loc_regs; | 
 | 563 |  | 
 | 564 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs)); | 
 | 565 |   ASSERT_EQ(0x103U, this->dmem_->cur_offset()); | 
 | 566 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 567 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 568 |   ASSERT_EQ(0x30U, loc_regs[CFA_REG].values[0]); | 
 | 569 |   ASSERT_EQ(0x128U, loc_regs[CFA_REG].values[1]); | 
 | 570 |  | 
 | 571 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 572 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 573 |  | 
 | 574 |   // Test a negative value. | 
 | 575 |   ResetLogs(); | 
 | 576 |   loc_regs.clear(); | 
 | 577 |   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x12, 0xa3, 0x01, 0xfa, 0x7f}); | 
 | 578 |  | 
 | 579 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x205, &loc_regs)); | 
 | 580 |   ASSERT_EQ(0x205U, this->dmem_->cur_offset()); | 
 | 581 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 582 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 583 |   ASSERT_EQ(0xa3U, loc_regs[CFA_REG].values[0]); | 
 | 584 |   ASSERT_EQ(static_cast<uint64_t>(-48), loc_regs[CFA_REG].values[1]); | 
 | 585 |  | 
 | 586 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 587 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 588 | } | 
 | 589 |  | 
 | 590 | TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_register) { | 
 | 591 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0d, 0x72}); | 
 | 592 |   dwarf_loc_regs_t loc_regs; | 
 | 593 |  | 
 | 594 |   // This fails because the cfa is not defined as a register. | 
 | 595 |   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); | 
 | 596 |   ASSERT_EQ(0U, loc_regs.size()); | 
| Christopher Ferris | 2fcf4cf | 2018-01-23 17:52:23 -0800 | [diff] [blame] | 597 |   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 598 |  | 
 | 599 |   ASSERT_EQ("4 unwind Attempt to set new register, but cfa is not already set to a register.\n", | 
 | 600 |             GetFakeLogPrint()); | 
 | 601 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 602 |  | 
 | 603 |   ResetLogs(); | 
 | 604 |   loc_regs.clear(); | 
 | 605 |   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3, 20}}; | 
 | 606 |  | 
 | 607 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); | 
 | 608 |   ASSERT_EQ(0x102U, this->dmem_->cur_offset()); | 
 | 609 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 610 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 611 |   ASSERT_EQ(0x72U, loc_regs[CFA_REG].values[0]); | 
 | 612 |   ASSERT_EQ(20U, loc_regs[CFA_REG].values[1]); | 
 | 613 |  | 
 | 614 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 615 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 616 |  | 
 | 617 |   ResetLogs(); | 
 | 618 |   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0d, 0xf9, 0x20}); | 
 | 619 |   loc_regs.clear(); | 
 | 620 |   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3, 60}}; | 
 | 621 |  | 
 | 622 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs)); | 
 | 623 |   ASSERT_EQ(0x203U, this->dmem_->cur_offset()); | 
 | 624 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 625 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 626 |   ASSERT_EQ(0x1079U, loc_regs[CFA_REG].values[0]); | 
 | 627 |   ASSERT_EQ(60U, loc_regs[CFA_REG].values[1]); | 
 | 628 |  | 
 | 629 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 630 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 631 | } | 
 | 632 |  | 
 | 633 | TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_offset) { | 
 | 634 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0e, 0x59}); | 
 | 635 |   dwarf_loc_regs_t loc_regs; | 
 | 636 |  | 
 | 637 |   // This fails because the cfa is not defined as a register. | 
 | 638 |   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); | 
 | 639 |   ASSERT_EQ(0U, loc_regs.size()); | 
| Christopher Ferris | 2fcf4cf | 2018-01-23 17:52:23 -0800 | [diff] [blame] | 640 |   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 641 |  | 
 | 642 |   ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n", | 
 | 643 |             GetFakeLogPrint()); | 
 | 644 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 645 |  | 
 | 646 |   ResetLogs(); | 
 | 647 |   loc_regs.clear(); | 
 | 648 |   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}}; | 
 | 649 |  | 
 | 650 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); | 
 | 651 |   ASSERT_EQ(0x102U, this->dmem_->cur_offset()); | 
 | 652 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 653 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 654 |   ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]); | 
 | 655 |   ASSERT_EQ(0x59U, loc_regs[CFA_REG].values[1]); | 
 | 656 |  | 
 | 657 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 658 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 659 |  | 
 | 660 |   ResetLogs(); | 
 | 661 |   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0e, 0xd4, 0x0a}); | 
 | 662 |   loc_regs.clear(); | 
 | 663 |   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}}; | 
 | 664 |  | 
 | 665 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs)); | 
 | 666 |   ASSERT_EQ(0x203U, this->dmem_->cur_offset()); | 
 | 667 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 668 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 669 |   ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]); | 
 | 670 |   ASSERT_EQ(0x554U, loc_regs[CFA_REG].values[1]); | 
 | 671 |  | 
 | 672 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 673 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 674 | } | 
 | 675 |  | 
 | 676 | TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_offset_sf) { | 
 | 677 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x13, 0x23}); | 
 | 678 |   dwarf_loc_regs_t loc_regs; | 
 | 679 |  | 
 | 680 |   // This fails because the cfa is not defined as a register. | 
 | 681 |   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); | 
| Christopher Ferris | 2fcf4cf | 2018-01-23 17:52:23 -0800 | [diff] [blame] | 682 |   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 683 |  | 
 | 684 |   ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n", | 
 | 685 |             GetFakeLogPrint()); | 
 | 686 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 687 |  | 
 | 688 |   ResetLogs(); | 
 | 689 |   loc_regs.clear(); | 
 | 690 |   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}}; | 
 | 691 |  | 
 | 692 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); | 
 | 693 |   ASSERT_EQ(0x102U, this->dmem_->cur_offset()); | 
 | 694 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 695 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 696 |   ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]); | 
 | 697 |   ASSERT_EQ(0x118U, loc_regs[CFA_REG].values[1]); | 
 | 698 |  | 
 | 699 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 700 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 701 |  | 
 | 702 |   // Negative offset. | 
 | 703 |   ResetLogs(); | 
 | 704 |   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x13, 0xf6, 0x7f}); | 
 | 705 |   loc_regs.clear(); | 
 | 706 |   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}}; | 
 | 707 |  | 
 | 708 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs)); | 
 | 709 |   ASSERT_EQ(0x203U, this->dmem_->cur_offset()); | 
 | 710 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 711 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); | 
 | 712 |   ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]); | 
 | 713 |   ASSERT_EQ(static_cast<TypeParam>(-80), static_cast<TypeParam>(loc_regs[CFA_REG].values[1])); | 
 | 714 |  | 
 | 715 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 716 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 717 | } | 
 | 718 |  | 
 | 719 | TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_expression) { | 
 | 720 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0f, 0x04, 0x01, 0x02, 0x03, 0x04}); | 
 | 721 |   dwarf_loc_regs_t loc_regs; | 
 | 722 |  | 
 | 723 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x106, &loc_regs)); | 
 | 724 |   ASSERT_EQ(0x106U, this->dmem_->cur_offset()); | 
 | 725 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 726 |  | 
 | 727 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 728 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 729 |  | 
 | 730 |   ResetLogs(); | 
 | 731 |   std::vector<uint8_t> ops{0x0f, 0x81, 0x01}; | 
 | 732 |   for (uint8_t i = 3; i < 132; i++) { | 
 | 733 |     ops.push_back(i - 1); | 
 | 734 |   } | 
 | 735 |   this->memory_.SetMemory(0x200, ops); | 
 | 736 |   loc_regs.clear(); | 
 | 737 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x284, &loc_regs)); | 
 | 738 |   ASSERT_EQ(0x284U, this->dmem_->cur_offset()); | 
 | 739 |   ASSERT_EQ(1U, loc_regs.size()); | 
| David Srbecky | 3692f25 | 2018-03-08 16:57:19 +0000 | [diff] [blame] | 740 |   ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, loc_regs[CFA_REG].type); | 
 | 741 |   ASSERT_EQ(0x81U, loc_regs[CFA_REG].values[0]); | 
| Christopher Ferris | 8642fcb | 2017-04-24 11:14:39 -0700 | [diff] [blame] | 742 |  | 
 | 743 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 744 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 745 | } | 
 | 746 |  | 
 | 747 | TYPED_TEST_P(DwarfCfaTest, cfa_expression) { | 
 | 748 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x10, 0x04, 0x02, 0x40, 0x20}); | 
 | 749 |   dwarf_loc_regs_t loc_regs; | 
 | 750 |  | 
 | 751 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x105, &loc_regs)); | 
 | 752 |   ASSERT_EQ(0x105U, this->dmem_->cur_offset()); | 
 | 753 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 754 |   auto location = loc_regs.find(4); | 
 | 755 |   ASSERT_NE(loc_regs.end(), location); | 
 | 756 |   ASSERT_EQ(DWARF_LOCATION_EXPRESSION, location->second.type); | 
 | 757 |   ASSERT_EQ(2U, location->second.values[0]); | 
 | 758 |   ASSERT_EQ(0x105U, location->second.values[1]); | 
 | 759 |  | 
 | 760 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 761 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 762 |  | 
 | 763 |   ResetLogs(); | 
 | 764 |   std::vector<uint8_t> ops{0x10, 0xff, 0x01, 0x82, 0x01}; | 
 | 765 |   for (uint8_t i = 5; i < 135; i++) { | 
 | 766 |     ops.push_back(i - 4); | 
 | 767 |   } | 
 | 768 |  | 
 | 769 |   this->memory_.SetMemory(0x200, ops); | 
 | 770 |   loc_regs.clear(); | 
 | 771 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x287, &loc_regs)); | 
 | 772 |   ASSERT_EQ(0x287U, this->dmem_->cur_offset()); | 
 | 773 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 774 |   location = loc_regs.find(255); | 
 | 775 |   ASSERT_NE(loc_regs.end(), location); | 
 | 776 |   ASSERT_EQ(DWARF_LOCATION_EXPRESSION, location->second.type); | 
 | 777 |   ASSERT_EQ(130U, location->second.values[0]); | 
 | 778 |   ASSERT_EQ(0x287U, location->second.values[1]); | 
 | 779 |  | 
 | 780 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 781 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 782 | } | 
 | 783 |  | 
 | 784 | TYPED_TEST_P(DwarfCfaTest, cfa_val_offset) { | 
 | 785 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x14, 0x45, 0x54}); | 
 | 786 |   dwarf_loc_regs_t loc_regs; | 
 | 787 |  | 
 | 788 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs)); | 
 | 789 |   ASSERT_EQ(0x103U, this->dmem_->cur_offset()); | 
 | 790 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 791 |   auto location = loc_regs.find(69); | 
 | 792 |   ASSERT_NE(loc_regs.end(), location); | 
 | 793 |   ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type); | 
 | 794 |   ASSERT_EQ(0x2a0U, location->second.values[0]); | 
 | 795 |  | 
 | 796 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 797 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 798 |  | 
 | 799 |   ResetLogs(); | 
 | 800 |   loc_regs.clear(); | 
 | 801 |   this->memory_.SetMemory(0x400, std::vector<uint8_t>{0x14, 0xa2, 0x02, 0xb4, 0x05}); | 
 | 802 |  | 
 | 803 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x400, 0x405, &loc_regs)); | 
 | 804 |   ASSERT_EQ(0x405U, this->dmem_->cur_offset()); | 
 | 805 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 806 |   location = loc_regs.find(290); | 
 | 807 |   ASSERT_NE(loc_regs.end(), location); | 
 | 808 |   ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type); | 
 | 809 |   ASSERT_EQ(0x15a0U, location->second.values[0]); | 
 | 810 |  | 
 | 811 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 812 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 813 | } | 
 | 814 |  | 
 | 815 | TYPED_TEST_P(DwarfCfaTest, cfa_val_offset_sf) { | 
 | 816 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x15, 0x56, 0x12}); | 
 | 817 |   dwarf_loc_regs_t loc_regs; | 
 | 818 |  | 
 | 819 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs)); | 
 | 820 |   ASSERT_EQ(0x103U, this->dmem_->cur_offset()); | 
 | 821 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 822 |   auto location = loc_regs.find(86); | 
 | 823 |   ASSERT_NE(loc_regs.end(), location); | 
 | 824 |   ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type); | 
 | 825 |   ASSERT_EQ(0x90U, location->second.values[0]); | 
 | 826 |  | 
 | 827 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 828 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 829 |  | 
 | 830 |   // Negative value. | 
 | 831 |   ResetLogs(); | 
 | 832 |   loc_regs.clear(); | 
 | 833 |   this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x15, 0xff, 0x01, 0xc0, 0x7f}); | 
 | 834 |  | 
 | 835 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xa05, &loc_regs)); | 
 | 836 |   ASSERT_EQ(0xa05U, this->dmem_->cur_offset()); | 
 | 837 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 838 |   location = loc_regs.find(255); | 
 | 839 |   ASSERT_NE(loc_regs.end(), location); | 
 | 840 |   ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type); | 
 | 841 |   ASSERT_EQ(static_cast<uint64_t>(-512), location->second.values[0]); | 
 | 842 |  | 
 | 843 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 844 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 845 | } | 
 | 846 |  | 
 | 847 | TYPED_TEST_P(DwarfCfaTest, cfa_val_expression) { | 
 | 848 |   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x16, 0x05, 0x02, 0x10, 0x20}); | 
 | 849 |   dwarf_loc_regs_t loc_regs; | 
 | 850 |  | 
 | 851 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x105, &loc_regs)); | 
 | 852 |   ASSERT_EQ(0x105U, this->dmem_->cur_offset()); | 
 | 853 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 854 |   auto location = loc_regs.find(5); | 
 | 855 |   ASSERT_NE(loc_regs.end(), location); | 
 | 856 |   ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, location->second.type); | 
 | 857 |   ASSERT_EQ(2U, location->second.values[0]); | 
 | 858 |   ASSERT_EQ(0x105U, location->second.values[1]); | 
 | 859 |  | 
 | 860 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 861 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 862 |  | 
 | 863 |   ResetLogs(); | 
 | 864 |   std::vector<uint8_t> ops{0x16, 0x83, 0x10, 0xa8, 0x01}; | 
 | 865 |   for (uint8_t i = 0; i < 168; i++) { | 
 | 866 |     ops.push_back(i); | 
 | 867 |   } | 
 | 868 |  | 
 | 869 |   this->memory_.SetMemory(0xa00, ops); | 
 | 870 |   loc_regs.clear(); | 
 | 871 |  | 
 | 872 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xaad, &loc_regs)); | 
 | 873 |   ASSERT_EQ(0xaadU, this->dmem_->cur_offset()); | 
 | 874 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 875 |   location = loc_regs.find(2051); | 
 | 876 |   ASSERT_NE(loc_regs.end(), location); | 
 | 877 |   ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, location->second.type); | 
 | 878 |   ASSERT_EQ(168U, location->second.values[0]); | 
 | 879 |   ASSERT_EQ(0xaadU, location->second.values[1]); | 
 | 880 |  | 
 | 881 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 882 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 883 | } | 
 | 884 |  | 
 | 885 | TYPED_TEST_P(DwarfCfaTest, cfa_gnu_args_size) { | 
 | 886 |   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2e, 0x04}); | 
 | 887 |   dwarf_loc_regs_t loc_regs; | 
 | 888 |  | 
 | 889 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2002, &loc_regs)); | 
 | 890 |   ASSERT_EQ(0x2002U, this->dmem_->cur_offset()); | 
 | 891 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 892 |  | 
 | 893 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 894 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 895 |  | 
 | 896 |   ResetLogs(); | 
 | 897 |   loc_regs.clear(); | 
 | 898 |   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x2e, 0xa4, 0x80, 0x04}); | 
 | 899 |  | 
 | 900 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x5000, 0x5004, &loc_regs)); | 
 | 901 |   ASSERT_EQ(0x5004U, this->dmem_->cur_offset()); | 
 | 902 |   ASSERT_EQ(0U, loc_regs.size()); | 
 | 903 |  | 
 | 904 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 905 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 906 | } | 
 | 907 |  | 
 | 908 | TYPED_TEST_P(DwarfCfaTest, cfa_gnu_negative_offset_extended) { | 
 | 909 |   this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x2f, 0x08, 0x10}); | 
 | 910 |   dwarf_loc_regs_t loc_regs; | 
 | 911 |  | 
 | 912 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs)); | 
 | 913 |   ASSERT_EQ(0x503U, this->dmem_->cur_offset()); | 
 | 914 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 915 |   auto location = loc_regs.find(8); | 
 | 916 |   ASSERT_NE(loc_regs.end(), location); | 
 | 917 |   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); | 
 | 918 |   ASSERT_EQ(static_cast<uint64_t>(-16), location->second.values[0]); | 
 | 919 |  | 
 | 920 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 921 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 922 |  | 
 | 923 |   ResetLogs(); | 
 | 924 |   loc_regs.clear(); | 
 | 925 |   this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x2f, 0x81, 0x02, 0xff, 0x01}); | 
 | 926 |  | 
 | 927 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs)); | 
 | 928 |   ASSERT_EQ(0x1505U, this->dmem_->cur_offset()); | 
 | 929 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 930 |   location = loc_regs.find(257); | 
 | 931 |   ASSERT_NE(loc_regs.end(), location); | 
 | 932 |   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); | 
 | 933 |   ASSERT_EQ(static_cast<uint64_t>(-255), location->second.values[0]); | 
 | 934 |  | 
 | 935 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 936 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 937 | } | 
 | 938 |  | 
 | 939 | TYPED_TEST_P(DwarfCfaTest, cfa_register_override) { | 
 | 940 |   this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01, 0x09, 0x02, 0x04}); | 
 | 941 |   dwarf_loc_regs_t loc_regs; | 
 | 942 |  | 
 | 943 |   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x306, &loc_regs)); | 
 | 944 |   ASSERT_EQ(0x306U, this->dmem_->cur_offset()); | 
 | 945 |   ASSERT_EQ(1U, loc_regs.size()); | 
 | 946 |   auto location = loc_regs.find(2); | 
 | 947 |   ASSERT_NE(loc_regs.end(), location); | 
 | 948 |   ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type); | 
 | 949 |   ASSERT_EQ(4U, location->second.values[0]); | 
 | 950 |  | 
 | 951 |   ASSERT_EQ("", GetFakeLogPrint()); | 
 | 952 |   ASSERT_EQ("", GetFakeLogBuf()); | 
 | 953 | } | 
 | 954 |  | 
 | 955 | REGISTER_TYPED_TEST_CASE_P(DwarfCfaTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended, | 
 | 956 |                            cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc, | 
 | 957 |                            cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4, cfa_undefined, | 
 | 958 |                            cfa_same, cfa_register, cfa_state, cfa_state_cfa_offset_restore, | 
 | 959 |                            cfa_def_cfa, cfa_def_cfa_sf, cfa_def_cfa_register, cfa_def_cfa_offset, | 
 | 960 |                            cfa_def_cfa_offset_sf, cfa_def_cfa_expression, cfa_expression, | 
 | 961 |                            cfa_val_offset, cfa_val_offset_sf, cfa_val_expression, cfa_gnu_args_size, | 
 | 962 |                            cfa_gnu_negative_offset_extended, cfa_register_override); | 
 | 963 |  | 
 | 964 | typedef ::testing::Types<uint32_t, uint64_t> DwarfCfaTestTypes; | 
 | 965 | INSTANTIATE_TYPED_TEST_CASE_P(, DwarfCfaTest, DwarfCfaTestTypes); | 
| Christopher Ferris | d226a51 | 2017-07-14 10:37:19 -0700 | [diff] [blame] | 966 |  | 
 | 967 | }  // namespace unwindstack |