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