blob: 6ecedce38fc9835e56f0baf317d67bf3b0643382 [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;
David Srbecky12d90292018-03-14 21:30:25 +000053 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_;
Christopher Ferris8642fcb2017-04-24 11:14:39 -070064 operands_.clear();
65 // Read the cfa information.
66 uint8_t cfa_value;
67 if (!memory_->ReadBytes(&cfa_value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080068 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
69 last_error_.address = memory_->cur_offset();
Christopher Ferris8642fcb2017-04-24 11:14:39 -070070 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)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080081 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
82 last_error_.address = memory_->cur_offset();
Christopher Ferris8642fcb2017-04-24 11:14:39 -070083 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");
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080094 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris8642fcb2017-04-24 11:14:39 -070095 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) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800109 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris8642fcb2017-04-24 11:14:39 -0700110 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)) {
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(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)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800128 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
129 last_error_.address = memory_->cur_offset();
Christopher Ferris8642fcb2017-04-24 11:14:39 -0700130 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 }
Christopher Ferris8642fcb2017-04-24 11:14:39 -0700142}
143
144template <typename AddressType>
145std::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
177template <typename AddressType>
178bool 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
200template <typename AddressType>
201bool 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
266template <typename AddressType>
267bool 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.
313template <typename AddressType>
314bool DwarfCfa<AddressType>::cfa_nop(dwarf_loc_regs_t*) {
315 return true;
316}
317
318template <typename AddressType>
319bool 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
333template <typename AddressType>
334bool DwarfCfa<AddressType>::cfa_advance_loc(dwarf_loc_regs_t*) {
335 cur_pc_ += operands_[0] * fde_->cie->code_alignment_factor;
336 return true;
337}
338
339template <typename AddressType>
340bool 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
346template <typename AddressType>
347bool 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");
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800351 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris8642fcb2017-04-24 11:14:39 -0700352 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
363template <typename AddressType>
364bool 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
370template <typename AddressType>
371bool 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
377template <typename AddressType>
378bool 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
385template <typename AddressType>
386bool DwarfCfa<AddressType>::cfa_remember_state(dwarf_loc_regs_t* loc_regs) {
387 loc_reg_state_.push(*loc_regs);
388 return true;
389}
390
391template <typename AddressType>
392bool 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
402template <typename AddressType>
403bool 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
408template <typename AddressType>
409bool 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.");
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800413 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris8642fcb2017-04-24 11:14:39 -0700414 return false;
415 }
416
417 cfa_location->second.values[0] = operands_[0];
418 return true;
419}
420
421template <typename AddressType>
422bool 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.");
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800427 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris8642fcb2017-04-24 11:14:39 -0700428 return false;
429 }
430 cfa_location->second.values[1] = operands_[0];
431 return true;
432}
433
434template <typename AddressType>
435bool DwarfCfa<AddressType>::cfa_def_cfa_expression(dwarf_loc_regs_t* loc_regs) {
David Srbeckyc4772ae2018-03-08 16:57:19 +0000436 // 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,
Christopher Ferris8642fcb2017-04-24 11:14:39 -0700440 .values = {operands_[0], memory_->cur_offset()}};
441 return true;
442}
443
444template <typename AddressType>
445bool 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
452template <typename AddressType>
453bool 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
460template <typename AddressType>
461bool 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
468template <typename AddressType>
469bool 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.");
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800474 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris8642fcb2017-04-24 11:14:39 -0700475 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
482template <typename AddressType>
483bool 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
490template <typename AddressType>
491bool 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
498template <typename AddressType>
499bool 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
506template <typename AddressType>
507bool 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
514const 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.
732template class DwarfCfa<uint32_t>;
733template class DwarfCfa<uint64_t>;
Christopher Ferrisd226a512017-07-14 10:37:19 -0700734
735} // namespace unwindstack