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