Home | History | Annotate | Download | only in libunwindstack
      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