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 <inttypes.h> 18 #include <stdint.h> 19 20 #include <string> 21 #include <type_traits> 22 #include <vector> 23 24 #include <android-base/stringprintf.h> 25 26 #include <unwindstack/DwarfLocation.h> 27 #include <unwindstack/Log.h> 28 29 #include "DwarfCfa.h" 30 #include "DwarfEncoding.h" 31 #include "DwarfError.h" 32 #include "DwarfOp.h" 33 34 namespace unwindstack { 35 36 template <typename AddressType> 37 constexpr typename DwarfCfa<AddressType>::process_func DwarfCfa<AddressType>::kCallbackTable[64]; 38 39 template <typename AddressType> 40 bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset, uint64_t end_offset, 41 dwarf_loc_regs_t* loc_regs) { 42 if (cie_loc_regs_ != nullptr) { 43 for (const auto& entry : *cie_loc_regs_) { 44 (*loc_regs)[entry.first] = entry.second; 45 } 46 } 47 last_error_ = DWARF_ERROR_NONE; 48 49 memory_->set_cur_offset(start_offset); 50 uint64_t cfa_offset; 51 cur_pc_ = fde_->pc_start; 52 while ((cfa_offset = memory_->cur_offset()) < end_offset && cur_pc_ <= pc) { 53 operands_.clear(); 54 // Read the cfa information. 55 uint8_t cfa_value; 56 if (!memory_->ReadBytes(&cfa_value, 1)) { 57 last_error_ = DWARF_ERROR_MEMORY_INVALID; 58 return false; 59 } 60 uint8_t cfa_low = cfa_value & 0x3f; 61 // Check the 2 high bits. 62 switch (cfa_value >> 6) { 63 case 1: 64 cur_pc_ += cfa_low * fde_->cie->code_alignment_factor; 65 break; 66 case 2: { 67 uint64_t offset; 68 if (!memory_->ReadULEB128(&offset)) { 69 last_error_ = DWARF_ERROR_MEMORY_INVALID; 70 return false; 71 } 72 SignedType signed_offset = 73 static_cast<SignedType>(offset) * fde_->cie->data_alignment_factor; 74 (*loc_regs)[cfa_low] = {.type = DWARF_LOCATION_OFFSET, 75 .values = {static_cast<uint64_t>(signed_offset)}}; 76 break; 77 } 78 case 3: { 79 if (cie_loc_regs_ == nullptr) { 80 log(0, "restore while processing cie"); 81 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 82 return false; 83 } 84 85 auto reg_entry = cie_loc_regs_->find(cfa_low); 86 if (reg_entry == cie_loc_regs_->end()) { 87 loc_regs->erase(cfa_low); 88 } else { 89 (*loc_regs)[cfa_low] = reg_entry->second; 90 } 91 break; 92 } 93 case 0: { 94 const auto handle_func = DwarfCfa<AddressType>::kCallbackTable[cfa_low]; 95 if (handle_func == nullptr) { 96 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 97 return false; 98 } 99 100 const auto cfa = &DwarfCfaInfo::kTable[cfa_low]; 101 for (size_t i = 0; i < cfa->num_operands; i++) { 102 if (cfa->operands[i] == DW_EH_PE_block) { 103 uint64_t block_length; 104 if (!memory_->ReadULEB128(&block_length)) { 105 last_error_ = DWARF_ERROR_MEMORY_INVALID; 106 return false; 107 } 108 operands_.push_back(block_length); 109 memory_->set_cur_offset(memory_->cur_offset() + block_length); 110 continue; 111 } 112 uint64_t value; 113 if (!memory_->ReadEncodedValue<AddressType>(cfa->operands[i], &value)) { 114 last_error_ = DWARF_ERROR_MEMORY_INVALID; 115 return false; 116 } 117 operands_.push_back(value); 118 } 119 120 if (!(this->*handle_func)(loc_regs)) { 121 return false; 122 } 123 break; 124 } 125 } 126 } 127 return true; 128 } 129 130 template <typename AddressType> 131 std::string DwarfCfa<AddressType>::GetOperandString(uint8_t operand, uint64_t value, 132 uint64_t* cur_pc) { 133 std::string string; 134 switch (operand) { 135 case DwarfCfaInfo::DWARF_DISPLAY_REGISTER: 136 string = " register(" + std::to_string(value) + ")"; 137 break; 138 case DwarfCfaInfo::DWARF_DISPLAY_SIGNED_NUMBER: 139 string += " " + std::to_string(static_cast<SignedType>(value)); 140 break; 141 case DwarfCfaInfo::DWARF_DISPLAY_ADVANCE_LOC: 142 *cur_pc += value; 143 // Fall through to log the value. 144 case DwarfCfaInfo::DWARF_DISPLAY_NUMBER: 145 string += " " + std::to_string(value); 146 break; 147 case DwarfCfaInfo::DWARF_DISPLAY_SET_LOC: 148 *cur_pc = value; 149 // Fall through to log the value. 150 case DwarfCfaInfo::DWARF_DISPLAY_ADDRESS: 151 if (std::is_same<AddressType, uint32_t>::value) { 152 string += android::base::StringPrintf(" 0x%" PRIx32, static_cast<uint32_t>(value)); 153 } else { 154 string += android::base::StringPrintf(" 0x%" PRIx64, static_cast<uint64_t>(value)); 155 } 156 break; 157 default: 158 string = " unknown"; 159 } 160 return string; 161 } 162 163 template <typename AddressType> 164 bool DwarfCfa<AddressType>::LogOffsetRegisterString(uint32_t indent, uint64_t cfa_offset, 165 uint8_t reg) { 166 uint64_t offset; 167 if (!memory_->ReadULEB128(&offset)) { 168 return false; 169 } 170 uint64_t end_offset = memory_->cur_offset(); 171 memory_->set_cur_offset(cfa_offset); 172 173 std::string raw_data = "Raw Data:"; 174 for (uint64_t i = cfa_offset; i < end_offset; i++) { 175 uint8_t value; 176 if (!memory_->ReadBytes(&value, 1)) { 177 return false; 178 } 179 raw_data += android::base::StringPrintf(" 0x%02x", value); 180 } 181 log(indent, "DW_CFA_offset register(%d) %" PRId64, reg, offset); 182 log(indent, "%s", raw_data.c_str()); 183 return true; 184 } 185 186 template <typename AddressType> 187 bool DwarfCfa<AddressType>::LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op, 188 uint64_t* cur_pc) { 189 const auto* cfa = &DwarfCfaInfo::kTable[op]; 190 if (cfa->name == nullptr) { 191 log(indent, "Illegal"); 192 log(indent, "Raw Data: 0x%02x", op); 193 return true; 194 } 195 196 std::string log_string(cfa->name); 197 std::vector<std::string> expression_lines; 198 for (size_t i = 0; i < cfa->num_operands; i++) { 199 if (cfa->operands[i] == DW_EH_PE_block) { 200 // This is a Dwarf Expression. 201 uint64_t end_offset; 202 if (!memory_->ReadULEB128(&end_offset)) { 203 return false; 204 } 205 log_string += " " + std::to_string(end_offset); 206 end_offset += memory_->cur_offset(); 207 208 DwarfOp<AddressType> op(memory_, nullptr); 209 op.GetLogInfo(memory_->cur_offset(), end_offset, &expression_lines); 210 memory_->set_cur_offset(end_offset); 211 } else { 212 uint64_t value; 213 if (!memory_->ReadEncodedValue<AddressType>(cfa->operands[i], &value)) { 214 return false; 215 } 216 log_string += GetOperandString(cfa->display_operands[i], value, cur_pc); 217 } 218 } 219 log(indent, "%s", log_string.c_str()); 220 221 // Get the raw bytes of the data. 222 uint64_t end_offset = memory_->cur_offset(); 223 memory_->set_cur_offset(cfa_offset); 224 std::string raw_data("Raw Data:"); 225 for (uint64_t i = 0; i < end_offset - cfa_offset; i++) { 226 uint8_t value; 227 if (!memory_->ReadBytes(&value, 1)) { 228 return false; 229 } 230 231 // Only show 10 raw bytes per line. 232 if ((i % 10) == 0 && i != 0) { 233 log(indent, "%s", raw_data.c_str()); 234 raw_data.clear(); 235 } 236 if (raw_data.empty()) { 237 raw_data = "Raw Data:"; 238 } 239 raw_data += android::base::StringPrintf(" 0x%02x", value); 240 } 241 if (!raw_data.empty()) { 242 log(indent, "%s", raw_data.c_str()); 243 } 244 245 // Log any of the expression data. 246 for (const auto line : expression_lines) { 247 log(indent + 1, "%s", line.c_str()); 248 } 249 return true; 250 } 251 252 template <typename AddressType> 253 bool DwarfCfa<AddressType>::Log(uint32_t indent, uint64_t pc, uint64_t load_bias, 254 uint64_t start_offset, uint64_t end_offset) { 255 memory_->set_cur_offset(start_offset); 256 uint64_t cfa_offset; 257 uint64_t cur_pc = fde_->pc_start; 258 uint64_t old_pc = cur_pc; 259 while ((cfa_offset = memory_->cur_offset()) < end_offset && cur_pc <= pc) { 260 // Read the cfa information. 261 uint8_t cfa_value; 262 if (!memory_->ReadBytes(&cfa_value, 1)) { 263 return false; 264 } 265 266 // Check the 2 high bits. 267 uint8_t cfa_low = cfa_value & 0x3f; 268 switch (cfa_value >> 6) { 269 case 0: 270 if (!LogInstruction(indent, cfa_offset, cfa_low, &cur_pc)) { 271 return false; 272 } 273 break; 274 case 1: 275 log(indent, "DW_CFA_advance_loc %d", cfa_low); 276 log(indent, "Raw Data: 0x%02x", cfa_value); 277 cur_pc += cfa_low * fde_->cie->code_alignment_factor; 278 break; 279 case 2: 280 if (!LogOffsetRegisterString(indent, cfa_offset, cfa_low)) { 281 return false; 282 } 283 break; 284 case 3: 285 log(indent, "DW_CFA_restore register(%d)", cfa_low); 286 log(indent, "Raw Data: 0x%02x", cfa_value); 287 break; 288 } 289 if (cur_pc != old_pc) { 290 log(indent, ""); 291 log(indent, "PC 0x%" PRIx64, cur_pc + load_bias); 292 } 293 old_pc = cur_pc; 294 } 295 return true; 296 } 297 298 // Static data. 299 template <typename AddressType> 300 bool DwarfCfa<AddressType>::cfa_nop(dwarf_loc_regs_t*) { 301 return true; 302 } 303 304 template <typename AddressType> 305 bool DwarfCfa<AddressType>::cfa_set_loc(dwarf_loc_regs_t*) { 306 AddressType cur_pc = cur_pc_; 307 AddressType new_pc = operands_[0]; 308 if (new_pc < cur_pc) { 309 if (std::is_same<AddressType, uint32_t>::value) { 310 log(0, "Warning: PC is moving backwards: old 0x%" PRIx32 " new 0x%" PRIx32, cur_pc, new_pc); 311 } else { 312 log(0, "Warning: PC is moving backwards: old 0x%" PRIx64 " new 0x%" PRIx64, cur_pc, new_pc); 313 } 314 } 315 cur_pc_ = new_pc; 316 return true; 317 } 318 319 template <typename AddressType> 320 bool DwarfCfa<AddressType>::cfa_advance_loc(dwarf_loc_regs_t*) { 321 cur_pc_ += operands_[0] * fde_->cie->code_alignment_factor; 322 return true; 323 } 324 325 template <typename AddressType> 326 bool DwarfCfa<AddressType>::cfa_offset(dwarf_loc_regs_t* loc_regs) { 327 AddressType reg = operands_[0]; 328 (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {operands_[1]}}; 329 return true; 330 } 331 332 template <typename AddressType> 333 bool DwarfCfa<AddressType>::cfa_restore(dwarf_loc_regs_t* loc_regs) { 334 AddressType reg = operands_[0]; 335 if (cie_loc_regs_ == nullptr) { 336 log(0, "restore while processing cie"); 337 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 338 return false; 339 } 340 auto reg_entry = cie_loc_regs_->find(reg); 341 if (reg_entry == cie_loc_regs_->end()) { 342 loc_regs->erase(reg); 343 } else { 344 (*loc_regs)[reg] = reg_entry->second; 345 } 346 return true; 347 } 348 349 template <typename AddressType> 350 bool DwarfCfa<AddressType>::cfa_undefined(dwarf_loc_regs_t* loc_regs) { 351 AddressType reg = operands_[0]; 352 (*loc_regs)[reg] = {.type = DWARF_LOCATION_UNDEFINED}; 353 return true; 354 } 355 356 template <typename AddressType> 357 bool DwarfCfa<AddressType>::cfa_same_value(dwarf_loc_regs_t* loc_regs) { 358 AddressType reg = operands_[0]; 359 loc_regs->erase(reg); 360 return true; 361 } 362 363 template <typename AddressType> 364 bool DwarfCfa<AddressType>::cfa_register(dwarf_loc_regs_t* loc_regs) { 365 AddressType reg = operands_[0]; 366 AddressType reg_dst = operands_[1]; 367 (*loc_regs)[reg] = {.type = DWARF_LOCATION_REGISTER, .values = {reg_dst}}; 368 return true; 369 } 370 371 template <typename AddressType> 372 bool DwarfCfa<AddressType>::cfa_remember_state(dwarf_loc_regs_t* loc_regs) { 373 loc_reg_state_.push(*loc_regs); 374 return true; 375 } 376 377 template <typename AddressType> 378 bool DwarfCfa<AddressType>::cfa_restore_state(dwarf_loc_regs_t* loc_regs) { 379 if (loc_reg_state_.size() == 0) { 380 log(0, "Warning: Attempt to restore without remember."); 381 return true; 382 } 383 *loc_regs = loc_reg_state_.top(); 384 loc_reg_state_.pop(); 385 return true; 386 } 387 388 template <typename AddressType> 389 bool DwarfCfa<AddressType>::cfa_def_cfa(dwarf_loc_regs_t* loc_regs) { 390 (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {operands_[0], operands_[1]}}; 391 return true; 392 } 393 394 template <typename AddressType> 395 bool DwarfCfa<AddressType>::cfa_def_cfa_register(dwarf_loc_regs_t* loc_regs) { 396 auto cfa_location = loc_regs->find(CFA_REG); 397 if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) { 398 log(0, "Attempt to set new register, but cfa is not already set to a register."); 399 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 400 return false; 401 } 402 403 cfa_location->second.values[0] = operands_[0]; 404 return true; 405 } 406 407 template <typename AddressType> 408 bool DwarfCfa<AddressType>::cfa_def_cfa_offset(dwarf_loc_regs_t* loc_regs) { 409 // Changing the offset if this is not a register is illegal. 410 auto cfa_location = loc_regs->find(CFA_REG); 411 if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) { 412 log(0, "Attempt to set offset, but cfa is not set to a register."); 413 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 414 return false; 415 } 416 cfa_location->second.values[1] = operands_[0]; 417 return true; 418 } 419 420 template <typename AddressType> 421 bool DwarfCfa<AddressType>::cfa_def_cfa_expression(dwarf_loc_regs_t* loc_regs) { 422 (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_EXPRESSION, 423 .values = {operands_[0], memory_->cur_offset()}}; 424 return true; 425 } 426 427 template <typename AddressType> 428 bool DwarfCfa<AddressType>::cfa_expression(dwarf_loc_regs_t* loc_regs) { 429 AddressType reg = operands_[0]; 430 (*loc_regs)[reg] = {.type = DWARF_LOCATION_EXPRESSION, 431 .values = {operands_[1], memory_->cur_offset()}}; 432 return true; 433 } 434 435 template <typename AddressType> 436 bool DwarfCfa<AddressType>::cfa_offset_extended_sf(dwarf_loc_regs_t* loc_regs) { 437 AddressType reg = operands_[0]; 438 SignedType value = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor; 439 (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {static_cast<uint64_t>(value)}}; 440 return true; 441 } 442 443 template <typename AddressType> 444 bool DwarfCfa<AddressType>::cfa_def_cfa_sf(dwarf_loc_regs_t* loc_regs) { 445 SignedType offset = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor; 446 (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, 447 .values = {operands_[0], static_cast<uint64_t>(offset)}}; 448 return true; 449 } 450 451 template <typename AddressType> 452 bool DwarfCfa<AddressType>::cfa_def_cfa_offset_sf(dwarf_loc_regs_t* loc_regs) { 453 // Changing the offset if this is not a register is illegal. 454 auto cfa_location = loc_regs->find(CFA_REG); 455 if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) { 456 log(0, "Attempt to set offset, but cfa is not set to a register."); 457 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 458 return false; 459 } 460 SignedType offset = static_cast<SignedType>(operands_[0]) * fde_->cie->data_alignment_factor; 461 cfa_location->second.values[1] = static_cast<uint64_t>(offset); 462 return true; 463 } 464 465 template <typename AddressType> 466 bool DwarfCfa<AddressType>::cfa_val_offset(dwarf_loc_regs_t* loc_regs) { 467 AddressType reg = operands_[0]; 468 SignedType offset = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor; 469 (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_OFFSET, .values = {static_cast<uint64_t>(offset)}}; 470 return true; 471 } 472 473 template <typename AddressType> 474 bool DwarfCfa<AddressType>::cfa_val_offset_sf(dwarf_loc_regs_t* loc_regs) { 475 AddressType reg = operands_[0]; 476 SignedType offset = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor; 477 (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_OFFSET, .values = {static_cast<uint64_t>(offset)}}; 478 return true; 479 } 480 481 template <typename AddressType> 482 bool DwarfCfa<AddressType>::cfa_val_expression(dwarf_loc_regs_t* loc_regs) { 483 AddressType reg = operands_[0]; 484 (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_EXPRESSION, 485 .values = {operands_[1], memory_->cur_offset()}}; 486 return true; 487 } 488 489 template <typename AddressType> 490 bool DwarfCfa<AddressType>::cfa_gnu_negative_offset_extended(dwarf_loc_regs_t* loc_regs) { 491 AddressType reg = operands_[0]; 492 SignedType offset = -static_cast<SignedType>(operands_[1]); 493 (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {static_cast<uint64_t>(offset)}}; 494 return true; 495 } 496 497 const DwarfCfaInfo::Info DwarfCfaInfo::kTable[64] = { 498 { 499 // 0x00 DW_CFA_nop 500 "DW_CFA_nop", 501 2, 502 0, 503 {}, 504 {}, 505 }, 506 { 507 "DW_CFA_set_loc", // 0x01 DW_CFA_set_loc 508 2, 509 1, 510 {DW_EH_PE_absptr}, 511 {DWARF_DISPLAY_SET_LOC}, 512 }, 513 { 514 "DW_CFA_advance_loc1", // 0x02 DW_CFA_advance_loc1 515 2, 516 1, 517 {DW_EH_PE_udata1}, 518 {DWARF_DISPLAY_ADVANCE_LOC}, 519 }, 520 { 521 "DW_CFA_advance_loc2", // 0x03 DW_CFA_advance_loc2 522 2, 523 1, 524 {DW_EH_PE_udata2}, 525 {DWARF_DISPLAY_ADVANCE_LOC}, 526 }, 527 { 528 "DW_CFA_advance_loc4", // 0x04 DW_CFA_advance_loc4 529 2, 530 1, 531 {DW_EH_PE_udata4}, 532 {DWARF_DISPLAY_ADVANCE_LOC}, 533 }, 534 { 535 "DW_CFA_offset_extended", // 0x05 DW_CFA_offset_extended 536 2, 537 2, 538 {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, 539 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER}, 540 }, 541 { 542 "DW_CFA_restore_extended", // 0x06 DW_CFA_restore_extended 543 2, 544 1, 545 {DW_EH_PE_uleb128}, 546 {DWARF_DISPLAY_REGISTER}, 547 }, 548 { 549 "DW_CFA_undefined", // 0x07 DW_CFA_undefined 550 2, 551 1, 552 {DW_EH_PE_uleb128}, 553 {DWARF_DISPLAY_REGISTER}, 554 }, 555 { 556 "DW_CFA_same_value", // 0x08 DW_CFA_same_value 557 2, 558 1, 559 {DW_EH_PE_uleb128}, 560 {DWARF_DISPLAY_REGISTER}, 561 }, 562 { 563 "DW_CFA_register", // 0x09 DW_CFA_register 564 2, 565 2, 566 {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, 567 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_REGISTER}, 568 }, 569 { 570 "DW_CFA_remember_state", // 0x0a DW_CFA_remember_state 571 2, 572 0, 573 {}, 574 {}, 575 }, 576 { 577 "DW_CFA_restore_state", // 0x0b DW_CFA_restore_state 578 2, 579 0, 580 {}, 581 {}, 582 }, 583 { 584 "DW_CFA_def_cfa", // 0x0c DW_CFA_def_cfa 585 2, 586 2, 587 {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, 588 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER}, 589 }, 590 { 591 "DW_CFA_def_cfa_register", // 0x0d DW_CFA_def_cfa_register 592 2, 593 1, 594 {DW_EH_PE_uleb128}, 595 {DWARF_DISPLAY_REGISTER}, 596 }, 597 { 598 "DW_CFA_def_cfa_offset", // 0x0e DW_CFA_def_cfa_offset 599 2, 600 1, 601 {DW_EH_PE_uleb128}, 602 {DWARF_DISPLAY_NUMBER}, 603 }, 604 { 605 "DW_CFA_def_cfa_expression", // 0x0f DW_CFA_def_cfa_expression 606 2, 607 1, 608 {DW_EH_PE_block}, 609 {DWARF_DISPLAY_EVAL_BLOCK}, 610 }, 611 { 612 "DW_CFA_expression", // 0x10 DW_CFA_expression 613 2, 614 2, 615 {DW_EH_PE_uleb128, DW_EH_PE_block}, 616 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_EVAL_BLOCK}, 617 }, 618 { 619 "DW_CFA_offset_extended_sf", // 0x11 DW_CFA_offset_extend_sf 620 2, 621 2, 622 {DW_EH_PE_uleb128, DW_EH_PE_sleb128}, 623 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER}, 624 }, 625 { 626 "DW_CFA_def_cfa_sf", // 0x12 DW_CFA_def_cfa_sf 627 2, 628 2, 629 {DW_EH_PE_uleb128, DW_EH_PE_sleb128}, 630 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER}, 631 }, 632 { 633 "DW_CFA_def_cfa_offset_sf", // 0x13 DW_CFA_def_cfa_offset_sf 634 2, 635 1, 636 {DW_EH_PE_sleb128}, 637 {DWARF_DISPLAY_SIGNED_NUMBER}, 638 }, 639 { 640 "DW_CFA_val_offset", // 0x14 DW_CFA_val_offset 641 2, 642 2, 643 {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, 644 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER}, 645 }, 646 { 647 "DW_CFA_val_offset_sf", // 0x15 DW_CFA_val_offset_sf 648 2, 649 2, 650 {DW_EH_PE_uleb128, DW_EH_PE_sleb128}, 651 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER}, 652 }, 653 { 654 "DW_CFA_val_expression", // 0x16 DW_CFA_val_expression 655 2, 656 2, 657 {DW_EH_PE_uleb128, DW_EH_PE_block}, 658 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_EVAL_BLOCK}, 659 }, 660 {nullptr, 0, 0, {}, {}}, // 0x17 illegal cfa 661 {nullptr, 0, 0, {}, {}}, // 0x18 illegal cfa 662 {nullptr, 0, 0, {}, {}}, // 0x19 illegal cfa 663 {nullptr, 0, 0, {}, {}}, // 0x1a illegal cfa 664 {nullptr, 0, 0, {}, {}}, // 0x1b illegal cfa 665 {nullptr, 0, 0, {}, {}}, // 0x1c DW_CFA_lo_user (Treat as illegal) 666 {nullptr, 0, 0, {}, {}}, // 0x1d illegal cfa 667 {nullptr, 0, 0, {}, {}}, // 0x1e illegal cfa 668 {nullptr, 0, 0, {}, {}}, // 0x1f illegal cfa 669 {nullptr, 0, 0, {}, {}}, // 0x20 illegal cfa 670 {nullptr, 0, 0, {}, {}}, // 0x21 illegal cfa 671 {nullptr, 0, 0, {}, {}}, // 0x22 illegal cfa 672 {nullptr, 0, 0, {}, {}}, // 0x23 illegal cfa 673 {nullptr, 0, 0, {}, {}}, // 0x24 illegal cfa 674 {nullptr, 0, 0, {}, {}}, // 0x25 illegal cfa 675 {nullptr, 0, 0, {}, {}}, // 0x26 illegal cfa 676 {nullptr, 0, 0, {}, {}}, // 0x27 illegal cfa 677 {nullptr, 0, 0, {}, {}}, // 0x28 illegal cfa 678 {nullptr, 0, 0, {}, {}}, // 0x29 illegal cfa 679 {nullptr, 0, 0, {}, {}}, // 0x2a illegal cfa 680 {nullptr, 0, 0, {}, {}}, // 0x2b illegal cfa 681 {nullptr, 0, 0, {}, {}}, // 0x2c illegal cfa 682 {nullptr, 0, 0, {}, {}}, // 0x2d DW_CFA_GNU_window_save (Treat as illegal) 683 { 684 "DW_CFA_GNU_args_size", // 0x2e DW_CFA_GNU_args_size 685 2, 686 1, 687 {DW_EH_PE_uleb128}, 688 {DWARF_DISPLAY_NUMBER}, 689 }, 690 { 691 "DW_CFA_GNU_negative_offset_extended", // 0x2f DW_CFA_GNU_negative_offset_extended 692 2, 693 2, 694 {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, 695 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER}, 696 }, 697 {nullptr, 0, 0, {}, {}}, // 0x31 illegal cfa 698 {nullptr, 0, 0, {}, {}}, // 0x32 illegal cfa 699 {nullptr, 0, 0, {}, {}}, // 0x33 illegal cfa 700 {nullptr, 0, 0, {}, {}}, // 0x34 illegal cfa 701 {nullptr, 0, 0, {}, {}}, // 0x35 illegal cfa 702 {nullptr, 0, 0, {}, {}}, // 0x36 illegal cfa 703 {nullptr, 0, 0, {}, {}}, // 0x37 illegal cfa 704 {nullptr, 0, 0, {}, {}}, // 0x38 illegal cfa 705 {nullptr, 0, 0, {}, {}}, // 0x39 illegal cfa 706 {nullptr, 0, 0, {}, {}}, // 0x3a illegal cfa 707 {nullptr, 0, 0, {}, {}}, // 0x3b illegal cfa 708 {nullptr, 0, 0, {}, {}}, // 0x3c illegal cfa 709 {nullptr, 0, 0, {}, {}}, // 0x3d illegal cfa 710 {nullptr, 0, 0, {}, {}}, // 0x3e illegal cfa 711 {nullptr, 0, 0, {}, {}}, // 0x3f DW_CFA_hi_user (Treat as illegal) 712 }; 713 714 // Explicitly instantiate DwarfCfa. 715 template class DwarfCfa<uint32_t>; 716 template class DwarfCfa<uint64_t>; 717 718 } // namespace unwindstack 719