blob: 4fc95c76640b9dbdc9c08879a7da476ad21ab969 [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) {
427 (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_EXPRESSION,
428 .values = {operands_[0], memory_->cur_offset()}};
429 return true;
430}
431
432template <typename AddressType>
433bool DwarfCfa<AddressType>::cfa_expression(dwarf_loc_regs_t* loc_regs) {
434 AddressType reg = operands_[0];
435 (*loc_regs)[reg] = {.type = DWARF_LOCATION_EXPRESSION,
436 .values = {operands_[1], memory_->cur_offset()}};
437 return true;
438}
439
440template <typename AddressType>
441bool DwarfCfa<AddressType>::cfa_offset_extended_sf(dwarf_loc_regs_t* loc_regs) {
442 AddressType reg = operands_[0];
443 SignedType value = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor;
444 (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {static_cast<uint64_t>(value)}};
445 return true;
446}
447
448template <typename AddressType>
449bool DwarfCfa<AddressType>::cfa_def_cfa_sf(dwarf_loc_regs_t* loc_regs) {
450 SignedType offset = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor;
451 (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_REGISTER,
452 .values = {operands_[0], static_cast<uint64_t>(offset)}};
453 return true;
454}
455
456template <typename AddressType>
457bool DwarfCfa<AddressType>::cfa_def_cfa_offset_sf(dwarf_loc_regs_t* loc_regs) {
458 // Changing the offset if this is not a register is illegal.
459 auto cfa_location = loc_regs->find(CFA_REG);
460 if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) {
461 log(0, "Attempt to set offset, but cfa is not set to a register.");
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800462 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris8642fcb2017-04-24 11:14:39 -0700463 return false;
464 }
465 SignedType offset = static_cast<SignedType>(operands_[0]) * fde_->cie->data_alignment_factor;
466 cfa_location->second.values[1] = static_cast<uint64_t>(offset);
467 return true;
468}
469
470template <typename AddressType>
471bool DwarfCfa<AddressType>::cfa_val_offset(dwarf_loc_regs_t* loc_regs) {
472 AddressType reg = operands_[0];
473 SignedType offset = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor;
474 (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_OFFSET, .values = {static_cast<uint64_t>(offset)}};
475 return true;
476}
477
478template <typename AddressType>
479bool DwarfCfa<AddressType>::cfa_val_offset_sf(dwarf_loc_regs_t* loc_regs) {
480 AddressType reg = operands_[0];
481 SignedType offset = static_cast<SignedType>(operands_[1]) * fde_->cie->data_alignment_factor;
482 (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_OFFSET, .values = {static_cast<uint64_t>(offset)}};
483 return true;
484}
485
486template <typename AddressType>
487bool DwarfCfa<AddressType>::cfa_val_expression(dwarf_loc_regs_t* loc_regs) {
488 AddressType reg = operands_[0];
489 (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_EXPRESSION,
490 .values = {operands_[1], memory_->cur_offset()}};
491 return true;
492}
493
494template <typename AddressType>
495bool DwarfCfa<AddressType>::cfa_gnu_negative_offset_extended(dwarf_loc_regs_t* loc_regs) {
496 AddressType reg = operands_[0];
497 SignedType offset = -static_cast<SignedType>(operands_[1]);
498 (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {static_cast<uint64_t>(offset)}};
499 return true;
500}
501
502const DwarfCfaInfo::Info DwarfCfaInfo::kTable[64] = {
503 {
504 // 0x00 DW_CFA_nop
505 "DW_CFA_nop",
506 2,
507 0,
508 {},
509 {},
510 },
511 {
512 "DW_CFA_set_loc", // 0x01 DW_CFA_set_loc
513 2,
514 1,
515 {DW_EH_PE_absptr},
516 {DWARF_DISPLAY_SET_LOC},
517 },
518 {
519 "DW_CFA_advance_loc1", // 0x02 DW_CFA_advance_loc1
520 2,
521 1,
522 {DW_EH_PE_udata1},
523 {DWARF_DISPLAY_ADVANCE_LOC},
524 },
525 {
526 "DW_CFA_advance_loc2", // 0x03 DW_CFA_advance_loc2
527 2,
528 1,
529 {DW_EH_PE_udata2},
530 {DWARF_DISPLAY_ADVANCE_LOC},
531 },
532 {
533 "DW_CFA_advance_loc4", // 0x04 DW_CFA_advance_loc4
534 2,
535 1,
536 {DW_EH_PE_udata4},
537 {DWARF_DISPLAY_ADVANCE_LOC},
538 },
539 {
540 "DW_CFA_offset_extended", // 0x05 DW_CFA_offset_extended
541 2,
542 2,
543 {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
544 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER},
545 },
546 {
547 "DW_CFA_restore_extended", // 0x06 DW_CFA_restore_extended
548 2,
549 1,
550 {DW_EH_PE_uleb128},
551 {DWARF_DISPLAY_REGISTER},
552 },
553 {
554 "DW_CFA_undefined", // 0x07 DW_CFA_undefined
555 2,
556 1,
557 {DW_EH_PE_uleb128},
558 {DWARF_DISPLAY_REGISTER},
559 },
560 {
561 "DW_CFA_same_value", // 0x08 DW_CFA_same_value
562 2,
563 1,
564 {DW_EH_PE_uleb128},
565 {DWARF_DISPLAY_REGISTER},
566 },
567 {
568 "DW_CFA_register", // 0x09 DW_CFA_register
569 2,
570 2,
571 {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
572 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_REGISTER},
573 },
574 {
575 "DW_CFA_remember_state", // 0x0a DW_CFA_remember_state
576 2,
577 0,
578 {},
579 {},
580 },
581 {
582 "DW_CFA_restore_state", // 0x0b DW_CFA_restore_state
583 2,
584 0,
585 {},
586 {},
587 },
588 {
589 "DW_CFA_def_cfa", // 0x0c DW_CFA_def_cfa
590 2,
591 2,
592 {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
593 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER},
594 },
595 {
596 "DW_CFA_def_cfa_register", // 0x0d DW_CFA_def_cfa_register
597 2,
598 1,
599 {DW_EH_PE_uleb128},
600 {DWARF_DISPLAY_REGISTER},
601 },
602 {
603 "DW_CFA_def_cfa_offset", // 0x0e DW_CFA_def_cfa_offset
604 2,
605 1,
606 {DW_EH_PE_uleb128},
607 {DWARF_DISPLAY_NUMBER},
608 },
609 {
610 "DW_CFA_def_cfa_expression", // 0x0f DW_CFA_def_cfa_expression
611 2,
612 1,
613 {DW_EH_PE_block},
614 {DWARF_DISPLAY_EVAL_BLOCK},
615 },
616 {
617 "DW_CFA_expression", // 0x10 DW_CFA_expression
618 2,
619 2,
620 {DW_EH_PE_uleb128, DW_EH_PE_block},
621 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_EVAL_BLOCK},
622 },
623 {
624 "DW_CFA_offset_extended_sf", // 0x11 DW_CFA_offset_extend_sf
625 2,
626 2,
627 {DW_EH_PE_uleb128, DW_EH_PE_sleb128},
628 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER},
629 },
630 {
631 "DW_CFA_def_cfa_sf", // 0x12 DW_CFA_def_cfa_sf
632 2,
633 2,
634 {DW_EH_PE_uleb128, DW_EH_PE_sleb128},
635 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER},
636 },
637 {
638 "DW_CFA_def_cfa_offset_sf", // 0x13 DW_CFA_def_cfa_offset_sf
639 2,
640 1,
641 {DW_EH_PE_sleb128},
642 {DWARF_DISPLAY_SIGNED_NUMBER},
643 },
644 {
645 "DW_CFA_val_offset", // 0x14 DW_CFA_val_offset
646 2,
647 2,
648 {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
649 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER},
650 },
651 {
652 "DW_CFA_val_offset_sf", // 0x15 DW_CFA_val_offset_sf
653 2,
654 2,
655 {DW_EH_PE_uleb128, DW_EH_PE_sleb128},
656 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER},
657 },
658 {
659 "DW_CFA_val_expression", // 0x16 DW_CFA_val_expression
660 2,
661 2,
662 {DW_EH_PE_uleb128, DW_EH_PE_block},
663 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_EVAL_BLOCK},
664 },
665 {nullptr, 0, 0, {}, {}}, // 0x17 illegal cfa
666 {nullptr, 0, 0, {}, {}}, // 0x18 illegal cfa
667 {nullptr, 0, 0, {}, {}}, // 0x19 illegal cfa
668 {nullptr, 0, 0, {}, {}}, // 0x1a illegal cfa
669 {nullptr, 0, 0, {}, {}}, // 0x1b illegal cfa
670 {nullptr, 0, 0, {}, {}}, // 0x1c DW_CFA_lo_user (Treat as illegal)
671 {nullptr, 0, 0, {}, {}}, // 0x1d illegal cfa
672 {nullptr, 0, 0, {}, {}}, // 0x1e illegal cfa
673 {nullptr, 0, 0, {}, {}}, // 0x1f illegal cfa
674 {nullptr, 0, 0, {}, {}}, // 0x20 illegal cfa
675 {nullptr, 0, 0, {}, {}}, // 0x21 illegal cfa
676 {nullptr, 0, 0, {}, {}}, // 0x22 illegal cfa
677 {nullptr, 0, 0, {}, {}}, // 0x23 illegal cfa
678 {nullptr, 0, 0, {}, {}}, // 0x24 illegal cfa
679 {nullptr, 0, 0, {}, {}}, // 0x25 illegal cfa
680 {nullptr, 0, 0, {}, {}}, // 0x26 illegal cfa
681 {nullptr, 0, 0, {}, {}}, // 0x27 illegal cfa
682 {nullptr, 0, 0, {}, {}}, // 0x28 illegal cfa
683 {nullptr, 0, 0, {}, {}}, // 0x29 illegal cfa
684 {nullptr, 0, 0, {}, {}}, // 0x2a illegal cfa
685 {nullptr, 0, 0, {}, {}}, // 0x2b illegal cfa
686 {nullptr, 0, 0, {}, {}}, // 0x2c illegal cfa
687 {nullptr, 0, 0, {}, {}}, // 0x2d DW_CFA_GNU_window_save (Treat as illegal)
688 {
689 "DW_CFA_GNU_args_size", // 0x2e DW_CFA_GNU_args_size
690 2,
691 1,
692 {DW_EH_PE_uleb128},
693 {DWARF_DISPLAY_NUMBER},
694 },
695 {
696 "DW_CFA_GNU_negative_offset_extended", // 0x2f DW_CFA_GNU_negative_offset_extended
697 2,
698 2,
699 {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
700 {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER},
701 },
702 {nullptr, 0, 0, {}, {}}, // 0x31 illegal cfa
703 {nullptr, 0, 0, {}, {}}, // 0x32 illegal cfa
704 {nullptr, 0, 0, {}, {}}, // 0x33 illegal cfa
705 {nullptr, 0, 0, {}, {}}, // 0x34 illegal cfa
706 {nullptr, 0, 0, {}, {}}, // 0x35 illegal cfa
707 {nullptr, 0, 0, {}, {}}, // 0x36 illegal cfa
708 {nullptr, 0, 0, {}, {}}, // 0x37 illegal cfa
709 {nullptr, 0, 0, {}, {}}, // 0x38 illegal cfa
710 {nullptr, 0, 0, {}, {}}, // 0x39 illegal cfa
711 {nullptr, 0, 0, {}, {}}, // 0x3a illegal cfa
712 {nullptr, 0, 0, {}, {}}, // 0x3b illegal cfa
713 {nullptr, 0, 0, {}, {}}, // 0x3c illegal cfa
714 {nullptr, 0, 0, {}, {}}, // 0x3d illegal cfa
715 {nullptr, 0, 0, {}, {}}, // 0x3e illegal cfa
716 {nullptr, 0, 0, {}, {}}, // 0x3f DW_CFA_hi_user (Treat as illegal)
717};
718
719// Explicitly instantiate DwarfCfa.
720template class DwarfCfa<uint32_t>;
721template class DwarfCfa<uint64_t>;
Christopher Ferrisd226a512017-07-14 10:37:19 -0700722
723} // namespace unwindstack