blob: 4e94f887d3ce2413d1b9918a4176475cb3d8495d [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 Ferrisd226a512017-07-14 10:37:19 -070029#include "DwarfEncoding.h"
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070030#include "DwarfOp.h"
Christopher Ferrisd226a512017-07-14 10:37:19 -070031
Christopher Ferrisc9dee842017-11-03 14:50:27 -070032#include "DwarfDebugFrame.h"
33#include "DwarfEhFrame.h"
34
Christopher Ferrisd226a512017-07-14 10:37:19 -070035namespace unwindstack {
36
Christopher Ferris98984b42018-01-17 12:59:45 -080037constexpr uint64_t DEX_PC_REG = 0x20444558;
38
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080039DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {}
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070040
41const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
42 uint64_t fde_offset;
43 if (!GetFdeOffsetFromPc(pc, &fde_offset)) {
44 return nullptr;
45 }
46 const DwarfFde* fde = GetFdeFromOffset(fde_offset);
Christopher Ferris13b86652017-11-05 14:01:43 -080047 if (fde == nullptr) {
48 return nullptr;
49 }
50
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070051 // Guaranteed pc >= pc_start, need to check pc in the fde range.
52 if (pc < fde->pc_end) {
53 return fde;
54 }
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080055 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070056 return nullptr;
57}
58
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070059bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080060 last_error_.code = DWARF_ERROR_NONE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070061 const DwarfFde* fde = GetFdeFromPc(pc);
62 if (fde == nullptr || fde->cie == nullptr) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080063 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070064 return false;
65 }
66
67 // Now get the location information for this pc.
68 dwarf_loc_regs_t loc_regs;
69 if (!GetCfaLocationInfo(pc, fde, &loc_regs)) {
70 return false;
71 }
72
73 // Now eval the actual registers.
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070074 return Eval(fde->cie, process_memory, loc_regs, regs, finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070075}
76
77template <typename AddressType>
78bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uint8_t version,
79 Memory* regular_memory, AddressType* value) {
80 DwarfOp<AddressType> op(&memory_, regular_memory);
81
82 // Need to evaluate the op data.
83 uint64_t start = loc.values[1];
84 uint64_t end = start + loc.values[0];
85 if (!op.Eval(start, end, version)) {
86 last_error_ = op.last_error();
87 return false;
88 }
89 if (op.StackSize() == 0) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080090 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070091 return false;
92 }
93 // We don't support an expression that evaluates to a register number.
94 if (op.is_register()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080095 last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070096 return false;
97 }
98 *value = op.StackAt(0);
99 return true;
100}
101
102template <typename AddressType>
Christopher Ferris98984b42018-01-17 12:59:45 -0800103struct EvalInfo {
104 const dwarf_loc_regs_t* loc_regs;
105 const DwarfCie* cie;
106 RegsImpl<AddressType>* cur_regs;
107 Memory* regular_memory;
108 AddressType cfa;
109 bool return_address_undefined = false;
110 uint64_t reg_map = 0;
111 AddressType reg_values[64];
112};
113
114template <typename AddressType>
115bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg,
116 AddressType* reg_ptr, void* info) {
117 EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info);
118 Memory* regular_memory = eval_info->regular_memory;
119 switch (loc->type) {
120 case DWARF_LOCATION_OFFSET:
121 if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800122 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
123 last_error_.address = eval_info->cfa + loc->values[0];
Christopher Ferris98984b42018-01-17 12:59:45 -0800124 return false;
125 }
126 break;
127 case DWARF_LOCATION_VAL_OFFSET:
128 *reg_ptr = eval_info->cfa + loc->values[0];
129 break;
130 case DWARF_LOCATION_REGISTER: {
131 uint32_t cur_reg = loc->values[0];
132 if (cur_reg >= eval_info->cur_regs->total_regs()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800133 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris98984b42018-01-17 12:59:45 -0800134 return false;
135 }
136 AddressType* cur_reg_ptr = &(*eval_info->cur_regs)[cur_reg];
137 const auto& entry = eval_info->loc_regs->find(cur_reg);
138 if (entry != eval_info->loc_regs->end()) {
139 if (!(eval_info->reg_map & (1 << cur_reg))) {
140 eval_info->reg_map |= 1 << cur_reg;
141 eval_info->reg_values[cur_reg] = *cur_reg_ptr;
142 if (!EvalRegister(&entry->second, cur_reg, cur_reg_ptr, eval_info)) {
143 return false;
144 }
145 }
146
147 // Use the register value from before any evaluations.
148 *reg_ptr = eval_info->reg_values[cur_reg] + loc->values[1];
149 } else {
150 *reg_ptr = *cur_reg_ptr + loc->values[1];
151 }
152 break;
153 }
154 case DWARF_LOCATION_EXPRESSION:
155 case DWARF_LOCATION_VAL_EXPRESSION: {
156 AddressType value;
157 if (!EvalExpression(*loc, eval_info->cie->version, regular_memory, &value)) {
158 return false;
159 }
160 if (loc->type == DWARF_LOCATION_EXPRESSION) {
161 if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800162 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
163 last_error_.address = value;
Christopher Ferris98984b42018-01-17 12:59:45 -0800164 return false;
165 }
166 } else {
167 *reg_ptr = value;
168 }
169 break;
170 }
171 case DWARF_LOCATION_UNDEFINED:
172 if (reg == eval_info->cie->return_address_register) {
173 eval_info->return_address_undefined = true;
174 }
175 default:
176 break;
177 }
178
179 return true;
180}
181
182template <typename AddressType>
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700183bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700184 const dwarf_loc_regs_t& loc_regs, Regs* regs,
185 bool* finished) {
Christopher Ferris7b8e4672017-06-01 17:55:25 -0700186 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700187 if (cie->return_address_register >= cur_regs->total_regs()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800188 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700189 return false;
190 }
191
192 // Get the cfa value;
193 auto cfa_entry = loc_regs.find(CFA_REG);
194 if (cfa_entry == loc_regs.end()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800195 last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700196 return false;
197 }
198
Christopher Ferris98984b42018-01-17 12:59:45 -0800199 // Always set the dex pc to zero when evaluating.
200 cur_regs->set_dex_pc(0);
201
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700202 AddressType prev_cfa = regs->sp();
203
Christopher Ferris98984b42018-01-17 12:59:45 -0800204 EvalInfo<AddressType> eval_info{
205 .loc_regs = &loc_regs, .cie = cie, .regular_memory = regular_memory, .cur_regs = cur_regs};
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700206 const DwarfLocation* loc = &cfa_entry->second;
207 // Only a few location types are valid for the cfa.
208 switch (loc->type) {
209 case DWARF_LOCATION_REGISTER:
210 if (loc->values[0] >= cur_regs->total_regs()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800211 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700212 return false;
213 }
214 // If the stack pointer register is the CFA, and the stack
215 // pointer register does not have any associated location
216 // information, use the current cfa value.
217 if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) {
Christopher Ferris98984b42018-01-17 12:59:45 -0800218 eval_info.cfa = prev_cfa;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700219 } else {
Christopher Ferris98984b42018-01-17 12:59:45 -0800220 eval_info.cfa = (*cur_regs)[loc->values[0]];
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700221 }
Christopher Ferris98984b42018-01-17 12:59:45 -0800222 eval_info.cfa += loc->values[1];
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700223 break;
224 case DWARF_LOCATION_EXPRESSION:
225 case DWARF_LOCATION_VAL_EXPRESSION: {
226 AddressType value;
227 if (!EvalExpression(*loc, cie->version, regular_memory, &value)) {
228 return false;
229 }
230 if (loc->type == DWARF_LOCATION_EXPRESSION) {
Christopher Ferris98984b42018-01-17 12:59:45 -0800231 if (!regular_memory->ReadFully(value, &eval_info.cfa, sizeof(AddressType))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800232 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
233 last_error_.address = value;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700234 return false;
235 }
236 } else {
Christopher Ferris98984b42018-01-17 12:59:45 -0800237 eval_info.cfa = value;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700238 }
239 break;
240 }
241 default:
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800242 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700243 return false;
244 }
245
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700246 for (const auto& entry : loc_regs) {
Christopher Ferris98984b42018-01-17 12:59:45 -0800247 uint32_t reg = entry.first;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700248 // Already handled the CFA register.
249 if (reg == CFA_REG) continue;
250
Christopher Ferris98984b42018-01-17 12:59:45 -0800251 AddressType* reg_ptr;
252 AddressType dex_pc = 0;
253 if (reg == DEX_PC_REG) {
254 // Special register that indicates this is a dex pc.
255 dex_pc = 0;
256 reg_ptr = &dex_pc;
257 } else if (reg >= cur_regs->total_regs() || eval_info.reg_map & (1 << reg)) {
258 // Skip this unknown register, or a register that has already been
259 // processed.
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700260 continue;
Christopher Ferris98984b42018-01-17 12:59:45 -0800261 } else {
262 reg_ptr = &(*cur_regs)[reg];
263 eval_info.reg_map |= 1 << reg;
264 eval_info.reg_values[reg] = *reg_ptr;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700265 }
266
Christopher Ferris98984b42018-01-17 12:59:45 -0800267 if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
268 return false;
269 }
270
271 if (reg == DEX_PC_REG) {
272 cur_regs->set_dex_pc(dex_pc);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700273 }
274 }
275
276 // Find the return address location.
Christopher Ferris98984b42018-01-17 12:59:45 -0800277 if (eval_info.return_address_undefined) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700278 cur_regs->set_pc(0);
279 } else {
280 cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
281 }
Christopher Ferris2502a602017-10-23 13:51:54 -0700282
283 // If the pc was set to zero, consider this the final frame.
284 *finished = (cur_regs->pc() == 0) ? true : false;
285
Christopher Ferris98984b42018-01-17 12:59:45 -0800286 cur_regs->set_sp(eval_info.cfa);
Christopher Ferrisfda7edd2017-10-31 16:10:42 -0700287
288 return true;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700289}
290
291template <typename AddressType>
292const DwarfCie* DwarfSectionImpl<AddressType>::GetCie(uint64_t offset) {
293 auto cie_entry = cie_entries_.find(offset);
294 if (cie_entry != cie_entries_.end()) {
295 return &cie_entry->second;
296 }
297 DwarfCie* cie = &cie_entries_[offset];
298 memory_.set_cur_offset(offset);
299 if (!FillInCie(cie)) {
300 // Erase the cached entry.
301 cie_entries_.erase(offset);
302 return nullptr;
303 }
304 return cie;
305}
306
307template <typename AddressType>
308bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
309 uint32_t length32;
310 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800311 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
312 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700313 return false;
314 }
Christopher Ferrisd226a512017-07-14 10:37:19 -0700315 // Set the default for the lsda encoding.
316 cie->lsda_encoding = DW_EH_PE_omit;
317
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700318 if (length32 == static_cast<uint32_t>(-1)) {
319 // 64 bit Cie
320 uint64_t length64;
321 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800322 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
323 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700324 return false;
325 }
326
327 cie->cfa_instructions_end = memory_.cur_offset() + length64;
328 cie->fde_address_encoding = DW_EH_PE_sdata8;
329
330 uint64_t cie_id;
331 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800332 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
333 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700334 return false;
335 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700336 if (cie_id != cie64_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700337 // This is not a Cie, something has gone horribly wrong.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800338 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700339 return false;
340 }
341 } else {
342 // 32 bit Cie
343 cie->cfa_instructions_end = memory_.cur_offset() + length32;
344 cie->fde_address_encoding = DW_EH_PE_sdata4;
345
346 uint32_t cie_id;
347 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800348 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
349 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700350 return false;
351 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700352 if (cie_id != cie32_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700353 // This is not a Cie, something has gone horribly wrong.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800354 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700355 return false;
356 }
357 }
358
359 if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800360 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
361 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700362 return false;
363 }
364
365 if (cie->version != 1 && cie->version != 3 && cie->version != 4) {
366 // Unrecognized version.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800367 last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700368 return false;
369 }
370
371 // Read the augmentation string.
372 char aug_value;
373 do {
374 if (!memory_.ReadBytes(&aug_value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800375 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
376 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700377 return false;
378 }
379 cie->augmentation_string.push_back(aug_value);
380 } while (aug_value != '\0');
381
382 if (cie->version == 4) {
383 // Skip the Address Size field since we only use it for validation.
384 memory_.set_cur_offset(memory_.cur_offset() + 1);
385
386 // Segment Size
387 if (!memory_.ReadBytes(&cie->segment_size, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800388 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
389 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700390 return false;
391 }
392 }
393
394 // Code Alignment Factor
395 if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800396 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
397 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700398 return false;
399 }
400
401 // Data Alignment Factor
402 if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800403 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
404 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700405 return false;
406 }
407
408 if (cie->version == 1) {
409 // Return Address is a single byte.
410 uint8_t return_address_register;
411 if (!memory_.ReadBytes(&return_address_register, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800412 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
413 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700414 return false;
415 }
416 cie->return_address_register = return_address_register;
417 } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800418 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
419 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700420 return false;
421 }
422
423 if (cie->augmentation_string[0] != 'z') {
424 cie->cfa_instructions_offset = memory_.cur_offset();
425 return true;
426 }
427
428 uint64_t aug_length;
429 if (!memory_.ReadULEB128(&aug_length)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800430 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
431 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700432 return false;
433 }
434 cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
435
436 for (size_t i = 1; i < cie->augmentation_string.size(); i++) {
437 switch (cie->augmentation_string[i]) {
438 case 'L':
439 if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800440 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
441 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700442 return false;
443 }
444 break;
445 case 'P': {
446 uint8_t encoding;
447 if (!memory_.ReadBytes(&encoding, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800448 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
449 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700450 return false;
451 }
452 if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800453 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
454 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700455 return false;
456 }
457 } break;
458 case 'R':
459 if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
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 break;
465 }
466 }
467 return true;
468}
469
470template <typename AddressType>
471const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) {
472 auto fde_entry = fde_entries_.find(offset);
473 if (fde_entry != fde_entries_.end()) {
474 return &fde_entry->second;
475 }
476 DwarfFde* fde = &fde_entries_[offset];
477 memory_.set_cur_offset(offset);
478 if (!FillInFde(fde)) {
479 fde_entries_.erase(offset);
480 return nullptr;
481 }
482 return fde;
483}
484
485template <typename AddressType>
486bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
487 uint32_t length32;
488 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800489 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
490 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700491 return false;
492 }
493
494 if (length32 == static_cast<uint32_t>(-1)) {
495 // 64 bit Fde.
496 uint64_t length64;
497 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800498 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
499 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700500 return false;
501 }
502 fde->cfa_instructions_end = memory_.cur_offset() + length64;
503
504 uint64_t value64;
505 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800506 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
507 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700508 return false;
509 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700510 if (value64 == cie64_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700511 // This is a Cie, this means something has gone wrong.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800512 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700513 return false;
514 }
515
516 // Get the Cie pointer, which is necessary to properly read the rest of
517 // of the Fde information.
518 fde->cie_offset = GetCieOffsetFromFde64(value64);
519 } else {
520 // 32 bit Fde.
521 fde->cfa_instructions_end = memory_.cur_offset() + length32;
522
523 uint32_t value32;
524 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
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 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700529 if (value32 == cie32_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700530 // This is a Cie, this means something has gone wrong.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800531 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700532 return false;
533 }
534
535 // Get the Cie pointer, which is necessary to properly read the rest of
536 // of the Fde information.
537 fde->cie_offset = GetCieOffsetFromFde32(value32);
538 }
539 uint64_t cur_offset = memory_.cur_offset();
540
541 const DwarfCie* cie = GetCie(fde->cie_offset);
542 if (cie == nullptr) {
543 return false;
544 }
545 fde->cie = cie;
546
547 if (cie->segment_size != 0) {
548 // Skip over the segment selector for now.
549 cur_offset += cie->segment_size;
550 }
551 memory_.set_cur_offset(cur_offset);
552
553 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_start)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800554 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
555 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700556 return false;
557 }
558 fde->pc_start = AdjustPcFromFde(fde->pc_start);
559
560 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_end)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800561 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
562 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700563 return false;
564 }
565 fde->pc_end += fde->pc_start;
566 if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
567 // Augmentation Size
568 uint64_t aug_length;
569 if (!memory_.ReadULEB128(&aug_length)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800570 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
571 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700572 return false;
573 }
574 uint64_t cur_offset = memory_.cur_offset();
575
576 if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800577 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
578 last_error_.address = memory_.cur_offset();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700579 return false;
580 }
581
582 // Set our position to after all of the augmentation data.
583 memory_.set_cur_offset(cur_offset + aug_length);
584 }
585 fde->cfa_instructions_offset = memory_.cur_offset();
586
587 return true;
588}
589
590template <typename AddressType>
591bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
592 dwarf_loc_regs_t* loc_regs) {
593 DwarfCfa<AddressType> cfa(&memory_, fde);
594
595 // Look for the cached copy of the cie data.
596 auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
597 if (reg_entry == cie_loc_regs_.end()) {
598 if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end,
599 loc_regs)) {
600 last_error_ = cfa.last_error();
601 return false;
602 }
603 cie_loc_regs_[fde->cie_offset] = *loc_regs;
604 }
605 cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]);
606 if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) {
607 last_error_ = cfa.last_error();
608 return false;
609 }
610 return true;
611}
612
613template <typename AddressType>
614bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t load_bias,
615 const DwarfFde* fde) {
616 DwarfCfa<AddressType> cfa(&memory_, fde);
617
618 // Always print the cie information.
619 const DwarfCie* cie = fde->cie;
620 if (!cfa.Log(indent, pc, load_bias, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
621 last_error_ = cfa.last_error();
622 return false;
623 }
624 if (!cfa.Log(indent, pc, load_bias, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
625 last_error_ = cfa.last_error();
626 return false;
627 }
628 return true;
629}
630
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700631template <typename AddressType>
632bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size) {
633 entries_offset_ = offset;
634 entries_end_ = offset + size;
635
636 memory_.clear_func_offset();
637 memory_.clear_text_offset();
638 memory_.set_data_offset(offset);
639 memory_.set_cur_offset(offset);
640 memory_.set_pc_offset(offset);
641
642 return CreateSortedFdeList();
643}
644
645template <typename AddressType>
646bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) {
647 uint8_t version;
648 if (!memory_.ReadBytes(&version, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800649 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
650 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700651 return false;
652 }
653 // Read the augmentation string.
654 std::vector<char> aug_string;
655 char aug_value;
656 bool get_encoding = false;
657 do {
658 if (!memory_.ReadBytes(&aug_value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800659 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
660 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700661 return false;
662 }
663 if (aug_value == 'R') {
664 get_encoding = true;
665 }
666 aug_string.push_back(aug_value);
667 } while (aug_value != '\0');
668
669 if (version == 4) {
670 // Skip the Address Size field.
671 memory_.set_cur_offset(memory_.cur_offset() + 1);
672
673 // Read the segment size.
674 if (!memory_.ReadBytes(segment_size, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800675 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
676 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700677 return false;
678 }
679 } else {
680 *segment_size = 0;
681 }
682
683 if (aug_string[0] != 'z' || !get_encoding) {
684 // No encoding
685 return true;
686 }
687
688 // Skip code alignment factor
689 uint8_t value;
690 do {
691 if (!memory_.ReadBytes(&value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800692 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
693 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700694 return false;
695 }
696 } while (value & 0x80);
697
698 // Skip data alignment factor
699 do {
700 if (!memory_.ReadBytes(&value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800701 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
702 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700703 return false;
704 }
705 } while (value & 0x80);
706
707 if (version == 1) {
708 // Skip return address register.
709 memory_.set_cur_offset(memory_.cur_offset() + 1);
710 } else {
711 // Skip return address register.
712 do {
713 if (!memory_.ReadBytes(&value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800714 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
715 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700716 return false;
717 }
718 } while (value & 0x80);
719 }
720
721 // Skip the augmentation length.
722 do {
723 if (!memory_.ReadBytes(&value, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800724 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
725 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700726 return false;
727 }
728 } while (value & 0x80);
729
730 for (size_t i = 1; i < aug_string.size(); i++) {
731 if (aug_string[i] == 'R') {
732 if (!memory_.ReadBytes(encoding, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800733 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
734 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700735 return false;
736 }
737 // Got the encoding, that's all we are looking for.
738 return true;
739 } else if (aug_string[i] == 'L') {
740 memory_.set_cur_offset(memory_.cur_offset() + 1);
741 } else if (aug_string[i] == 'P') {
742 uint8_t encoding;
743 if (!memory_.ReadBytes(&encoding, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800744 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
745 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700746 return false;
747 }
748 uint64_t value;
749 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800750 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
751 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700752 return false;
753 }
754 }
755 }
756
757 // It should be impossible to get here.
758 abort();
759}
760
761template <typename AddressType>
762bool DwarfSectionImpl<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size,
763 uint8_t encoding) {
764 if (segment_size != 0) {
765 memory_.set_cur_offset(memory_.cur_offset() + 1);
766 }
767
768 uint64_t start;
769 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800770 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
771 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700772 return false;
773 }
774 start = AdjustPcFromFde(start);
775
776 uint64_t length;
777 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800778 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
779 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700780 return false;
781 }
782 if (length != 0) {
783 fdes_.emplace_back(entry_offset, start, length);
784 }
785
786 return true;
787}
788
789template <typename AddressType>
790bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
791 memory_.set_cur_offset(entries_offset_);
792
793 // Loop through all of the entries and read just enough to create
794 // a sorted list of pcs.
795 // This code assumes that first comes the cie, then the fdes that
796 // it applies to.
797 uint64_t cie_offset = 0;
798 uint8_t address_encoding;
799 uint8_t segment_size;
800 while (memory_.cur_offset() < entries_end_) {
801 uint64_t cur_entry_offset = memory_.cur_offset();
802
803 // Figure out the entry length and type.
804 uint32_t value32;
805 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800806 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
807 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700808 return false;
809 }
810
811 uint64_t next_entry_offset;
812 if (value32 == static_cast<uint32_t>(-1)) {
813 uint64_t value64;
814 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800815 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
816 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700817 return false;
818 }
819 next_entry_offset = memory_.cur_offset() + value64;
820
821 // Read the Cie Id of a Cie or the pointer of the Fde.
822 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800823 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
824 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700825 return false;
826 }
827
828 if (value64 == cie64_value_) {
829 // Cie 64 bit
830 address_encoding = DW_EH_PE_sdata8;
831 if (!GetCieInfo(&segment_size, &address_encoding)) {
832 return false;
833 }
834 cie_offset = cur_entry_offset;
835 } else {
836 uint64_t last_cie_offset = GetCieOffsetFromFde64(value64);
837 if (last_cie_offset != cie_offset) {
838 // This means that this Fde is not following the Cie.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800839 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700840 return false;
841 }
842
843 // Fde 64 bit
844 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
845 return false;
846 }
847 }
848 } else {
849 next_entry_offset = memory_.cur_offset() + value32;
850
851 // Read the Cie Id of a Cie or the pointer of the Fde.
852 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800853 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
854 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700855 return false;
856 }
857
858 if (value32 == cie32_value_) {
859 // Cie 32 bit
860 address_encoding = DW_EH_PE_sdata4;
861 if (!GetCieInfo(&segment_size, &address_encoding)) {
862 return false;
863 }
864 cie_offset = cur_entry_offset;
865 } else {
866 uint64_t last_cie_offset = GetCieOffsetFromFde32(value32);
867 if (last_cie_offset != cie_offset) {
868 // This means that this Fde is not following the Cie.
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800869 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700870 return false;
871 }
872
873 // Fde 32 bit
874 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
875 return false;
876 }
877 }
878 }
879
880 if (next_entry_offset < memory_.cur_offset()) {
Christopher Ferris1a141a02018-01-24 08:52:47 -0800881 // Simply consider the processing done in this case.
882 break;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700883 }
884 memory_.set_cur_offset(next_entry_offset);
885 }
886
887 // Sort the entries.
888 std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) {
889 if (a.start == b.start) return a.end < b.end;
890 return a.start < b.start;
891 });
892
893 fde_count_ = fdes_.size();
894
895 return true;
896}
897
898template <typename AddressType>
899bool DwarfSectionImpl<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
900 if (fde_count_ == 0) {
901 return false;
902 }
903
904 size_t first = 0;
905 size_t last = fde_count_;
906 while (first < last) {
907 size_t current = (first + last) / 2;
908 const FdeInfo* info = &fdes_[current];
909 if (pc >= info->start && pc <= info->end) {
910 *fde_offset = info->offset;
911 return true;
912 }
913
914 if (pc < info->start) {
915 last = current;
916 } else {
917 first = current + 1;
918 }
919 }
920 return false;
921}
922
923template <typename AddressType>
924const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromIndex(size_t index) {
925 if (index >= fdes_.size()) {
926 return nullptr;
927 }
928 return this->GetFdeFromOffset(fdes_[index].offset);
929}
930
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700931// Explicitly instantiate DwarfSectionImpl
932template class DwarfSectionImpl<uint32_t>;
933template class DwarfSectionImpl<uint64_t>;
Christopher Ferrisd226a512017-07-14 10:37:19 -0700934
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700935// Explicitly instantiate DwarfDebugFrame
936template class DwarfDebugFrame<uint32_t>;
937template class DwarfDebugFrame<uint64_t>;
938
939// Explicitly instantiate DwarfEhFrame
940template class DwarfEhFrame<uint32_t>;
941template class DwarfEhFrame<uint64_t>;
942
Christopher Ferrisd226a512017-07-14 10:37:19 -0700943} // namespace unwindstack