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