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