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