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