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