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 24 #include <unwindstack/DwarfError.h> 25 #include <unwindstack/DwarfLocation.h> 26 #include <unwindstack/DwarfMemory.h> 27 #include <unwindstack/DwarfStructs.h> 28 #include <unwindstack/Log.h> 29 30 #include "DwarfCfa.h" 31 32 #include "LogFake.h" 33 #include "MemoryFake.h" 34 35 namespace unwindstack { 36 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_; 64 DwarfCie cie_; 65 DwarfFde fde_; 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)); 81 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->LastErrorCode()); 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)); 201 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); 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)); 230 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); 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()); 597 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); 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()); 640 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); 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)); 682 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); 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()); 740 ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, loc_regs[CFA_REG].type); 741 ASSERT_EQ(0x81U, loc_regs[CFA_REG].values[0]); 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); 966 967 } // namespace unwindstack 968