blob: 65eec65b84a76b2919617c72467a4c4d09cf62b4 [file] [log] [blame]
Christopher Ferris53a3c9b2017-05-10 18:34:15 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdint.h>
18
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080019#include <unwindstack/DwarfError.h>
Christopher Ferrisd226a512017-07-14 10:37:19 -070020#include <unwindstack/DwarfLocation.h>
21#include <unwindstack/DwarfMemory.h>
22#include <unwindstack/DwarfSection.h>
23#include <unwindstack/DwarfStructs.h>
24#include <unwindstack/Log.h>
25#include <unwindstack/Memory.h>
26#include <unwindstack/Regs.h>
27
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070028#include "DwarfCfa.h"
Christopher Ferrisc9dee842017-11-03 14:50:27 -070029#include "DwarfDebugFrame.h"
30#include "DwarfEhFrame.h"
Christopher Ferris559c7f22018-02-12 20:18:03 -080031#include "DwarfEncoding.h"
32#include "DwarfOp.h"
33#include "RegsInfo.h"
Christopher Ferrisc9dee842017-11-03 14:50:27 -070034
Christopher Ferrisd226a512017-07-14 10:37:19 -070035namespace unwindstack {
36
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080037DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {}
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070038
39const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
40 uint64_t fde_offset;
41 if (!GetFdeOffsetFromPc(pc, &fde_offset)) {
42 return nullptr;
43 }
44 const DwarfFde* fde = GetFdeFromOffset(fde_offset);
Christopher Ferris13b86652017-11-05 14:01:43 -080045 if (fde == nullptr) {
46 return nullptr;
47 }
48
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070049 // Guaranteed pc >= pc_start, need to check pc in the fde range.
50 if (pc < fde->pc_end) {
51 return fde;
52 }
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080053 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070054 return nullptr;
55}
56
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070057bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
David Srbecky12d90292018-03-14 21:30:25 +000058 // Lookup the pc in the cache.
59 auto it = loc_regs_.upper_bound(pc);
60 if (it == loc_regs_.end() || pc < it->second.pc_start) {
61 last_error_.code = DWARF_ERROR_NONE;
62 const DwarfFde* fde = GetFdeFromPc(pc);
63 if (fde == nullptr || fde->cie == nullptr) {
64 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
65 return false;
66 }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070067
David Srbecky12d90292018-03-14 21:30:25 +000068 // Now get the location information for this pc.
69 dwarf_loc_regs_t loc_regs;
70 if (!GetCfaLocationInfo(pc, fde, &loc_regs)) {
71 return false;
72 }
73 loc_regs.cie = fde->cie;
74
75 // Store it in the cache.
76 it = loc_regs_.emplace(loc_regs.pc_end, std::move(loc_regs)).first;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070077 }
78
79 // Now eval the actual registers.
David Srbecky12d90292018-03-14 21:30:25 +000080 return Eval(it->second.cie, process_memory, it->second, regs, finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070081}
82
83template <typename AddressType>
Christopher Ferris559c7f22018-02-12 20:18:03 -080084bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory,
85 AddressType* value,
86 RegsInfo<AddressType>* regs_info,
87 bool* is_dex_pc) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070088 DwarfOp<AddressType> op(&memory_, regular_memory);
Christopher Ferris559c7f22018-02-12 20:18:03 -080089 op.set_regs_info(regs_info);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070090
91 // Need to evaluate the op data.
Christopher Ferris559c7f22018-02-12 20:18:03 -080092 uint64_t end = loc.values[1];
93 uint64_t start = end - loc.values[0];
94 if (!op.Eval(start, end)) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070095 last_error_ = op.last_error();
96 return false;
97 }
98 if (op.StackSize() == 0) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080099 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700100 return false;
101 }
102 // We don't support an expression that evaluates to a register number.
103 if (op.is_register()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800104 last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700105 return false;
106 }
107 *value = op.StackAt(0);
Christopher Ferris559c7f22018-02-12 20:18:03 -0800108 if (is_dex_pc != nullptr && op.dex_pc_set()) {
109 *is_dex_pc = true;
110 }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700111 return true;
112}
113
114template <typename AddressType>
Christopher Ferris98984b42018-01-17 12:59:45 -0800115struct EvalInfo {
116 const dwarf_loc_regs_t* loc_regs;
117 const DwarfCie* cie;
Christopher Ferris98984b42018-01-17 12:59:45 -0800118 Memory* regular_memory;
119 AddressType cfa;
120 bool return_address_undefined = false;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800121 RegsInfo<AddressType> regs_info;
Christopher Ferris98984b42018-01-17 12:59:45 -0800122};
123
124template <typename AddressType>
125bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg,
126 AddressType* reg_ptr, void* info) {
127 EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info);
128 Memory* regular_memory = eval_info->regular_memory;
129 switch (loc->type) {
130 case DWARF_LOCATION_OFFSET:
131 if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800132 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
133 last_error_.address = eval_info->cfa + loc->values[0];
Christopher Ferris98984b42018-01-17 12:59:45 -0800134 return false;
135 }
136 break;
137 case DWARF_LOCATION_VAL_OFFSET:
138 *reg_ptr = eval_info->cfa + loc->values[0];
139 break;
140 case DWARF_LOCATION_REGISTER: {
141 uint32_t cur_reg = loc->values[0];
Christopher Ferris559c7f22018-02-12 20:18:03 -0800142 if (cur_reg >= eval_info->regs_info.Total()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800143 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris98984b42018-01-17 12:59:45 -0800144 return false;
145 }
Christopher Ferris559c7f22018-02-12 20:18:03 -0800146 *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1];
Christopher Ferris98984b42018-01-17 12:59:45 -0800147 break;
148 }
149 case DWARF_LOCATION_EXPRESSION:
150 case DWARF_LOCATION_VAL_EXPRESSION: {
151 AddressType value;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800152 bool is_dex_pc = false;
153 if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) {
Christopher Ferris98984b42018-01-17 12:59:45 -0800154 return false;
155 }
156 if (loc->type == DWARF_LOCATION_EXPRESSION) {
157 if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800158 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
159 last_error_.address = value;
Christopher Ferris98984b42018-01-17 12:59:45 -0800160 return false;
161 }
162 } else {
163 *reg_ptr = value;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800164 if (is_dex_pc) {
165 eval_info->regs_info.regs->set_dex_pc(value);
166 }
Christopher Ferris98984b42018-01-17 12:59:45 -0800167 }
168 break;
169 }
170 case DWARF_LOCATION_UNDEFINED:
171 if (reg == eval_info->cie->return_address_register) {
172 eval_info->return_address_undefined = true;
173 }
174 default:
175 break;
176 }
177
178 return true;
179}
180
181template <typename AddressType>
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700182bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700183 const dwarf_loc_regs_t& loc_regs, Regs* regs,
184 bool* finished) {
Christopher Ferris7b8e4672017-06-01 17:55:25 -0700185 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700186 if (cie->return_address_register >= cur_regs->total_regs()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800187 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700188 return false;
189 }
190
191 // Get the cfa value;
192 auto cfa_entry = loc_regs.find(CFA_REG);
193 if (cfa_entry == loc_regs.end()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800194 last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700195 return false;
196 }
197
Christopher Ferris98984b42018-01-17 12:59:45 -0800198 // Always set the dex pc to zero when evaluating.
199 cur_regs->set_dex_pc(0);
200
Christopher Ferris559c7f22018-02-12 20:18:03 -0800201 EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
202 .cie = cie,
203 .regular_memory = regular_memory,
204 .regs_info = RegsInfo<AddressType>(cur_regs)};
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700205 const DwarfLocation* loc = &cfa_entry->second;
206 // Only a few location types are valid for the cfa.
207 switch (loc->type) {
208 case DWARF_LOCATION_REGISTER:
209 if (loc->values[0] >= cur_regs->total_regs()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800210 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700211 return false;
212 }
Yabin Cui414df3e2018-03-14 18:16:22 -0700213 eval_info.cfa = (*cur_regs)[loc->values[0]];
Christopher Ferris98984b42018-01-17 12:59:45 -0800214 eval_info.cfa += loc->values[1];
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700215 break;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700216 case DWARF_LOCATION_VAL_EXPRESSION: {
217 AddressType value;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800218 if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700219 return false;
220 }
David Srbeckyc4772ae2018-03-08 16:57:19 +0000221 // There is only one type of valid expression for CFA evaluation.
222 eval_info.cfa = value;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700223 break;
224 }
225 default:
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800226 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700227 return false;
228 }
229
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700230 for (const auto& entry : loc_regs) {
Christopher Ferris98984b42018-01-17 12:59:45 -0800231 uint32_t reg = entry.first;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700232 // Already handled the CFA register.
233 if (reg == CFA_REG) continue;
234
Christopher Ferris98984b42018-01-17 12:59:45 -0800235 AddressType* reg_ptr;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800236 if (reg >= cur_regs->total_regs()) {
237 // Skip this unknown register.
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700238 continue;
239 }
240
Christopher Ferris559c7f22018-02-12 20:18:03 -0800241 reg_ptr = eval_info.regs_info.Save(reg);
Christopher Ferris98984b42018-01-17 12:59:45 -0800242 if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
243 return false;
244 }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700245 }
246
247 // Find the return address location.
Christopher Ferris98984b42018-01-17 12:59:45 -0800248 if (eval_info.return_address_undefined) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700249 cur_regs->set_pc(0);
250 } else {
251 cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
252 }
Christopher Ferris2502a602017-10-23 13:51:54 -0700253
254 // If the pc was set to zero, consider this the final frame.
255 *finished = (cur_regs->pc() == 0) ? true : false;
256
Christopher Ferris98984b42018-01-17 12:59:45 -0800257 cur_regs->set_sp(eval_info.cfa);
Christopher Ferrisfda7edd2017-10-31 16:10:42 -0700258
259 return true;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700260}
261
262template <typename AddressType>
263const DwarfCie* DwarfSectionImpl<AddressType>::GetCie(uint64_t offset) {
264 auto cie_entry = cie_entries_.find(offset);
265 if (cie_entry != cie_entries_.end()) {
266 return &cie_entry->second;
267 }
268 DwarfCie* cie = &cie_entries_[offset];
269 memory_.set_cur_offset(offset);
270 if (!FillInCie(cie)) {
271 // Erase the cached entry.
272 cie_entries_.erase(offset);
273 return nullptr;
274 }
275 return cie;
276}
277
278template <typename AddressType>
279bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
280 uint32_t length32;
281 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800282 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
283 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700284 return false;
285 }
Christopher Ferrisd226a512017-07-14 10:37:19 -0700286 // Set the default for the lsda encoding.
287 cie->lsda_encoding = DW_EH_PE_omit;
288
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700289 if (length32 == static_cast<uint32_t>(-1)) {
290 // 64 bit Cie
291 uint64_t length64;
292 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800293 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
294 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700295 return false;
296 }
297
298 cie->cfa_instructions_end = memory_.cur_offset() + length64;
299 cie->fde_address_encoding = DW_EH_PE_sdata8;
300
301 uint64_t cie_id;
302 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800303 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
304 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700305 return false;
306 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700307 if (cie_id != cie64_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700308 // This is not a Cie, something has gone horribly wrong.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800309 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700310 return false;
311 }
312 } else {
313 // 32 bit Cie
314 cie->cfa_instructions_end = memory_.cur_offset() + length32;
315 cie->fde_address_encoding = DW_EH_PE_sdata4;
316
317 uint32_t cie_id;
318 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800319 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
320 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700321 return false;
322 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700323 if (cie_id != cie32_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700324 // This is not a Cie, something has gone horribly wrong.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800325 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700326 return false;
327 }
328 }
329
330 if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800331 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
332 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700333 return false;
334 }
335
336 if (cie->version != 1 && cie->version != 3 && cie->version != 4) {
337 // Unrecognized version.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800338 last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700339 return false;
340 }
341
342 // Read the augmentation string.
343 char aug_value;
344 do {
345 if (!memory_.ReadBytes(&aug_value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800346 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
347 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700348 return false;
349 }
350 cie->augmentation_string.push_back(aug_value);
351 } while (aug_value != '\0');
352
353 if (cie->version == 4) {
354 // Skip the Address Size field since we only use it for validation.
355 memory_.set_cur_offset(memory_.cur_offset() + 1);
356
357 // Segment Size
358 if (!memory_.ReadBytes(&cie->segment_size, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800359 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
360 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700361 return false;
362 }
363 }
364
365 // Code Alignment Factor
366 if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800367 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
368 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700369 return false;
370 }
371
372 // Data Alignment Factor
373 if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800374 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
375 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700376 return false;
377 }
378
379 if (cie->version == 1) {
380 // Return Address is a single byte.
381 uint8_t return_address_register;
382 if (!memory_.ReadBytes(&return_address_register, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800383 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
384 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700385 return false;
386 }
387 cie->return_address_register = return_address_register;
388 } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800389 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
390 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700391 return false;
392 }
393
394 if (cie->augmentation_string[0] != 'z') {
395 cie->cfa_instructions_offset = memory_.cur_offset();
396 return true;
397 }
398
399 uint64_t aug_length;
400 if (!memory_.ReadULEB128(&aug_length)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800401 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
402 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700403 return false;
404 }
405 cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
406
407 for (size_t i = 1; i < cie->augmentation_string.size(); i++) {
408 switch (cie->augmentation_string[i]) {
409 case 'L':
410 if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800411 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
412 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700413 return false;
414 }
415 break;
416 case 'P': {
417 uint8_t encoding;
418 if (!memory_.ReadBytes(&encoding, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800419 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
420 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700421 return false;
422 }
423 if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800424 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
425 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700426 return false;
427 }
428 } break;
429 case 'R':
430 if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800431 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
432 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700433 return false;
434 }
435 break;
436 }
437 }
438 return true;
439}
440
441template <typename AddressType>
442const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) {
443 auto fde_entry = fde_entries_.find(offset);
444 if (fde_entry != fde_entries_.end()) {
445 return &fde_entry->second;
446 }
447 DwarfFde* fde = &fde_entries_[offset];
448 memory_.set_cur_offset(offset);
449 if (!FillInFde(fde)) {
450 fde_entries_.erase(offset);
451 return nullptr;
452 }
453 return fde;
454}
455
456template <typename AddressType>
457bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
458 uint32_t length32;
459 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800460 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
461 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700462 return false;
463 }
464
465 if (length32 == static_cast<uint32_t>(-1)) {
466 // 64 bit Fde.
467 uint64_t length64;
468 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800469 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
470 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700471 return false;
472 }
473 fde->cfa_instructions_end = memory_.cur_offset() + length64;
474
475 uint64_t value64;
476 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800477 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
478 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700479 return false;
480 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700481 if (value64 == cie64_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700482 // This is a Cie, this means something has gone wrong.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800483 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700484 return false;
485 }
486
487 // Get the Cie pointer, which is necessary to properly read the rest of
488 // of the Fde information.
489 fde->cie_offset = GetCieOffsetFromFde64(value64);
490 } else {
491 // 32 bit Fde.
492 fde->cfa_instructions_end = memory_.cur_offset() + length32;
493
494 uint32_t value32;
495 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800496 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
497 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700498 return false;
499 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700500 if (value32 == cie32_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700501 // This is a Cie, this means something has gone wrong.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800502 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700503 return false;
504 }
505
506 // Get the Cie pointer, which is necessary to properly read the rest of
507 // of the Fde information.
508 fde->cie_offset = GetCieOffsetFromFde32(value32);
509 }
510 uint64_t cur_offset = memory_.cur_offset();
511
512 const DwarfCie* cie = GetCie(fde->cie_offset);
513 if (cie == nullptr) {
514 return false;
515 }
516 fde->cie = cie;
517
518 if (cie->segment_size != 0) {
519 // Skip over the segment selector for now.
520 cur_offset += cie->segment_size;
521 }
522 memory_.set_cur_offset(cur_offset);
523
524 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_start)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800525 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
526 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700527 return false;
528 }
529 fde->pc_start = AdjustPcFromFde(fde->pc_start);
530
531 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_end)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800532 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
533 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700534 return false;
535 }
536 fde->pc_end += fde->pc_start;
537 if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
538 // Augmentation Size
539 uint64_t aug_length;
540 if (!memory_.ReadULEB128(&aug_length)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800541 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
542 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700543 return false;
544 }
545 uint64_t cur_offset = memory_.cur_offset();
546
547 if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800548 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
549 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700550 return false;
551 }
552
553 // Set our position to after all of the augmentation data.
554 memory_.set_cur_offset(cur_offset + aug_length);
555 }
556 fde->cfa_instructions_offset = memory_.cur_offset();
557
558 return true;
559}
560
561template <typename AddressType>
562bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
563 dwarf_loc_regs_t* loc_regs) {
564 DwarfCfa<AddressType> cfa(&memory_, fde);
565
566 // Look for the cached copy of the cie data.
567 auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
568 if (reg_entry == cie_loc_regs_.end()) {
569 if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end,
570 loc_regs)) {
571 last_error_ = cfa.last_error();
572 return false;
573 }
574 cie_loc_regs_[fde->cie_offset] = *loc_regs;
575 }
576 cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]);
577 if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) {
578 last_error_ = cfa.last_error();
579 return false;
580 }
581 return true;
582}
583
584template <typename AddressType>
585bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t load_bias,
586 const DwarfFde* fde) {
587 DwarfCfa<AddressType> cfa(&memory_, fde);
588
589 // Always print the cie information.
590 const DwarfCie* cie = fde->cie;
591 if (!cfa.Log(indent, pc, load_bias, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
592 last_error_ = cfa.last_error();
593 return false;
594 }
595 if (!cfa.Log(indent, pc, load_bias, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
596 last_error_ = cfa.last_error();
597 return false;
598 }
599 return true;
600}
601
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700602template <typename AddressType>
603bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size) {
604 entries_offset_ = offset;
605 entries_end_ = offset + size;
606
607 memory_.clear_func_offset();
608 memory_.clear_text_offset();
609 memory_.set_data_offset(offset);
610 memory_.set_cur_offset(offset);
611 memory_.set_pc_offset(offset);
612
613 return CreateSortedFdeList();
614}
615
616template <typename AddressType>
617bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) {
618 uint8_t version;
619 if (!memory_.ReadBytes(&version, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800620 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
621 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700622 return false;
623 }
624 // Read the augmentation string.
625 std::vector<char> aug_string;
626 char aug_value;
627 bool get_encoding = false;
628 do {
629 if (!memory_.ReadBytes(&aug_value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800630 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
631 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700632 return false;
633 }
634 if (aug_value == 'R') {
635 get_encoding = true;
636 }
637 aug_string.push_back(aug_value);
638 } while (aug_value != '\0');
639
640 if (version == 4) {
641 // Skip the Address Size field.
642 memory_.set_cur_offset(memory_.cur_offset() + 1);
643
644 // Read the segment size.
645 if (!memory_.ReadBytes(segment_size, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800646 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
647 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700648 return false;
649 }
650 } else {
651 *segment_size = 0;
652 }
653
654 if (aug_string[0] != 'z' || !get_encoding) {
655 // No encoding
656 return true;
657 }
658
659 // Skip code alignment factor
660 uint8_t value;
661 do {
662 if (!memory_.ReadBytes(&value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800663 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
664 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700665 return false;
666 }
667 } while (value & 0x80);
668
669 // Skip data alignment factor
670 do {
671 if (!memory_.ReadBytes(&value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800672 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
673 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700674 return false;
675 }
676 } while (value & 0x80);
677
678 if (version == 1) {
679 // Skip return address register.
680 memory_.set_cur_offset(memory_.cur_offset() + 1);
681 } else {
682 // Skip return address register.
683 do {
684 if (!memory_.ReadBytes(&value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800685 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
686 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700687 return false;
688 }
689 } while (value & 0x80);
690 }
691
692 // Skip the augmentation length.
693 do {
694 if (!memory_.ReadBytes(&value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800695 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
696 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700697 return false;
698 }
699 } while (value & 0x80);
700
701 for (size_t i = 1; i < aug_string.size(); i++) {
702 if (aug_string[i] == 'R') {
703 if (!memory_.ReadBytes(encoding, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800704 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
705 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700706 return false;
707 }
708 // Got the encoding, that's all we are looking for.
709 return true;
710 } else if (aug_string[i] == 'L') {
711 memory_.set_cur_offset(memory_.cur_offset() + 1);
712 } else if (aug_string[i] == 'P') {
713 uint8_t encoding;
714 if (!memory_.ReadBytes(&encoding, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800715 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
716 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700717 return false;
718 }
719 uint64_t value;
720 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800721 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
722 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700723 return false;
724 }
725 }
726 }
727
728 // It should be impossible to get here.
729 abort();
730}
731
732template <typename AddressType>
733bool DwarfSectionImpl<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size,
734 uint8_t encoding) {
735 if (segment_size != 0) {
736 memory_.set_cur_offset(memory_.cur_offset() + 1);
737 }
738
739 uint64_t start;
740 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800741 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
742 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700743 return false;
744 }
745 start = AdjustPcFromFde(start);
746
747 uint64_t length;
748 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800749 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
750 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700751 return false;
752 }
753 if (length != 0) {
754 fdes_.emplace_back(entry_offset, start, length);
755 }
756
757 return true;
758}
759
760template <typename AddressType>
761bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
762 memory_.set_cur_offset(entries_offset_);
763
764 // Loop through all of the entries and read just enough to create
765 // a sorted list of pcs.
766 // This code assumes that first comes the cie, then the fdes that
767 // it applies to.
768 uint64_t cie_offset = 0;
769 uint8_t address_encoding;
770 uint8_t segment_size;
771 while (memory_.cur_offset() < entries_end_) {
772 uint64_t cur_entry_offset = memory_.cur_offset();
773
774 // Figure out the entry length and type.
775 uint32_t value32;
776 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800777 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
778 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700779 return false;
780 }
781
782 uint64_t next_entry_offset;
783 if (value32 == static_cast<uint32_t>(-1)) {
784 uint64_t value64;
785 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800786 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
787 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700788 return false;
789 }
790 next_entry_offset = memory_.cur_offset() + value64;
791
792 // Read the Cie Id of a Cie or the pointer of the Fde.
793 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800794 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
795 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700796 return false;
797 }
798
799 if (value64 == cie64_value_) {
800 // Cie 64 bit
801 address_encoding = DW_EH_PE_sdata8;
802 if (!GetCieInfo(&segment_size, &address_encoding)) {
803 return false;
804 }
805 cie_offset = cur_entry_offset;
806 } else {
807 uint64_t last_cie_offset = GetCieOffsetFromFde64(value64);
808 if (last_cie_offset != cie_offset) {
809 // This means that this Fde is not following the Cie.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800810 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700811 return false;
812 }
813
814 // Fde 64 bit
815 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
816 return false;
817 }
818 }
819 } else {
820 next_entry_offset = memory_.cur_offset() + value32;
821
822 // Read the Cie Id of a Cie or the pointer of the Fde.
823 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800824 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
825 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700826 return false;
827 }
828
829 if (value32 == cie32_value_) {
830 // Cie 32 bit
831 address_encoding = DW_EH_PE_sdata4;
832 if (!GetCieInfo(&segment_size, &address_encoding)) {
833 return false;
834 }
835 cie_offset = cur_entry_offset;
836 } else {
837 uint64_t last_cie_offset = GetCieOffsetFromFde32(value32);
838 if (last_cie_offset != cie_offset) {
839 // This means that this Fde is not following the Cie.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800840 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700841 return false;
842 }
843
844 // Fde 32 bit
845 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
846 return false;
847 }
848 }
849 }
850
851 if (next_entry_offset < memory_.cur_offset()) {
Christopher Ferris1a141a02018-01-24 08:52:47 -0800852 // Simply consider the processing done in this case.
853 break;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700854 }
855 memory_.set_cur_offset(next_entry_offset);
856 }
857
858 // Sort the entries.
859 std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) {
860 if (a.start == b.start) return a.end < b.end;
861 return a.start < b.start;
862 });
863
864 fde_count_ = fdes_.size();
865
866 return true;
867}
868
869template <typename AddressType>
870bool DwarfSectionImpl<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
871 if (fde_count_ == 0) {
872 return false;
873 }
874
875 size_t first = 0;
876 size_t last = fde_count_;
877 while (first < last) {
878 size_t current = (first + last) / 2;
879 const FdeInfo* info = &fdes_[current];
880 if (pc >= info->start && pc <= info->end) {
881 *fde_offset = info->offset;
882 return true;
883 }
884
885 if (pc < info->start) {
886 last = current;
887 } else {
888 first = current + 1;
889 }
890 }
891 return false;
892}
893
894template <typename AddressType>
895const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromIndex(size_t index) {
896 if (index >= fdes_.size()) {
897 return nullptr;
898 }
899 return this->GetFdeFromOffset(fdes_[index].offset);
900}
901
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700902// Explicitly instantiate DwarfSectionImpl
903template class DwarfSectionImpl<uint32_t>;
904template class DwarfSectionImpl<uint64_t>;
Christopher Ferrisd226a512017-07-14 10:37:19 -0700905
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700906// Explicitly instantiate DwarfDebugFrame
907template class DwarfDebugFrame<uint32_t>;
908template class DwarfDebugFrame<uint64_t>;
909
910// Explicitly instantiate DwarfEhFrame
911template class DwarfEhFrame<uint32_t>;
912template class DwarfEhFrame<uint64_t>;
913
Christopher Ferrisd226a512017-07-14 10:37:19 -0700914} // namespace unwindstack