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