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