blob: 8b30b768dcf64801a169d4d66e6c3e3a763187b4 [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 Ferrisd226a512017-07-14 10:37:19 -070019#include <unwindstack/DwarfLocation.h>
20#include <unwindstack/DwarfMemory.h>
21#include <unwindstack/DwarfSection.h>
22#include <unwindstack/DwarfStructs.h>
23#include <unwindstack/Log.h>
24#include <unwindstack/Memory.h>
25#include <unwindstack/Regs.h>
26
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070027#include "DwarfCfa.h"
Christopher Ferrisd226a512017-07-14 10:37:19 -070028#include "DwarfEncoding.h"
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070029#include "DwarfError.h"
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070030#include "DwarfOp.h"
Christopher Ferrisd226a512017-07-14 10:37:19 -070031
32namespace unwindstack {
33
34DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {}
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070035
36const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
37 uint64_t fde_offset;
38 if (!GetFdeOffsetFromPc(pc, &fde_offset)) {
39 return nullptr;
40 }
41 const DwarfFde* fde = GetFdeFromOffset(fde_offset);
42 // Guaranteed pc >= pc_start, need to check pc in the fde range.
43 if (pc < fde->pc_end) {
44 return fde;
45 }
46 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
47 return nullptr;
48}
49
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070050bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
Christopher Ferrisd226a512017-07-14 10:37:19 -070051 last_error_ = DWARF_ERROR_NONE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070052 const DwarfFde* fde = GetFdeFromPc(pc);
53 if (fde == nullptr || fde->cie == nullptr) {
54 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
55 return false;
56 }
57
58 // Now get the location information for this pc.
59 dwarf_loc_regs_t loc_regs;
60 if (!GetCfaLocationInfo(pc, fde, &loc_regs)) {
61 return false;
62 }
63
64 // Now eval the actual registers.
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070065 return Eval(fde->cie, process_memory, loc_regs, regs, finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070066}
67
68template <typename AddressType>
69bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uint8_t version,
70 Memory* regular_memory, AddressType* value) {
71 DwarfOp<AddressType> op(&memory_, regular_memory);
72
73 // Need to evaluate the op data.
74 uint64_t start = loc.values[1];
75 uint64_t end = start + loc.values[0];
76 if (!op.Eval(start, end, version)) {
77 last_error_ = op.last_error();
78 return false;
79 }
80 if (op.StackSize() == 0) {
81 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
82 return false;
83 }
84 // We don't support an expression that evaluates to a register number.
85 if (op.is_register()) {
86 last_error_ = DWARF_ERROR_NOT_IMPLEMENTED;
87 return false;
88 }
89 *value = op.StackAt(0);
90 return true;
91}
92
93template <typename AddressType>
94bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070095 const dwarf_loc_regs_t& loc_regs, Regs* regs,
96 bool* finished) {
Christopher Ferris7b8e4672017-06-01 17:55:25 -070097 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070098 if (cie->return_address_register >= cur_regs->total_regs()) {
99 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
100 return false;
101 }
102
103 // Get the cfa value;
104 auto cfa_entry = loc_regs.find(CFA_REG);
105 if (cfa_entry == loc_regs.end()) {
106 last_error_ = DWARF_ERROR_CFA_NOT_DEFINED;
107 return false;
108 }
109
110 AddressType prev_pc = regs->pc();
111 AddressType prev_cfa = regs->sp();
112
113 AddressType cfa;
114 const DwarfLocation* loc = &cfa_entry->second;
115 // Only a few location types are valid for the cfa.
116 switch (loc->type) {
117 case DWARF_LOCATION_REGISTER:
118 if (loc->values[0] >= cur_regs->total_regs()) {
119 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
120 return false;
121 }
122 // If the stack pointer register is the CFA, and the stack
123 // pointer register does not have any associated location
124 // information, use the current cfa value.
125 if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) {
126 cfa = prev_cfa;
127 } else {
128 cfa = (*cur_regs)[loc->values[0]];
129 }
130 cfa += loc->values[1];
131 break;
132 case DWARF_LOCATION_EXPRESSION:
133 case DWARF_LOCATION_VAL_EXPRESSION: {
134 AddressType value;
135 if (!EvalExpression(*loc, cie->version, regular_memory, &value)) {
136 return false;
137 }
138 if (loc->type == DWARF_LOCATION_EXPRESSION) {
139 if (!regular_memory->Read(value, &cfa, sizeof(AddressType))) {
140 last_error_ = DWARF_ERROR_MEMORY_INVALID;
141 return false;
142 }
143 } else {
144 cfa = value;
145 }
146 break;
147 }
148 default:
149 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
150 return false;
151 }
152
153 // This code is not guaranteed to work in cases where a register location
154 // is a double indirection to the actual value. For example, if r3 is set
155 // to r5 + 4, and r5 is set to CFA + 4, then this won't necessarily work
156 // because it does not guarantee that r5 is evaluated before r3.
157 // Check that this case does not exist, and error if it does.
158 bool return_address_undefined = false;
159 for (const auto& entry : loc_regs) {
160 uint16_t reg = entry.first;
161 // Already handled the CFA register.
162 if (reg == CFA_REG) continue;
163
164 if (reg >= cur_regs->total_regs()) {
165 // Skip this unknown register.
166 continue;
167 }
168
169 const DwarfLocation* loc = &entry.second;
170 switch (loc->type) {
171 case DWARF_LOCATION_OFFSET:
172 if (!regular_memory->Read(cfa + loc->values[0], &(*cur_regs)[reg], sizeof(AddressType))) {
173 last_error_ = DWARF_ERROR_MEMORY_INVALID;
174 return false;
175 }
176 break;
177 case DWARF_LOCATION_VAL_OFFSET:
178 (*cur_regs)[reg] = cfa + loc->values[0];
179 break;
180 case DWARF_LOCATION_REGISTER: {
181 uint16_t cur_reg = loc->values[0];
182 if (cur_reg >= cur_regs->total_regs()) {
183 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
184 return false;
185 }
186 if (loc_regs.find(cur_reg) != loc_regs.end()) {
187 // This is a double indirection, a register definition references
188 // another register which is also defined as something other
189 // than a register.
190 log(0,
191 "Invalid indirection: register %d references register %d which is "
192 "not a plain register.\n",
193 reg, cur_reg);
194 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
195 return false;
196 }
197 (*cur_regs)[reg] = (*cur_regs)[cur_reg] + loc->values[1];
198 break;
199 }
200 case DWARF_LOCATION_EXPRESSION:
201 case DWARF_LOCATION_VAL_EXPRESSION: {
202 AddressType value;
203 if (!EvalExpression(*loc, cie->version, regular_memory, &value)) {
204 return false;
205 }
206 if (loc->type == DWARF_LOCATION_EXPRESSION) {
207 if (!regular_memory->Read(value, &(*cur_regs)[reg], sizeof(AddressType))) {
208 last_error_ = DWARF_ERROR_MEMORY_INVALID;
209 return false;
210 }
211 } else {
212 (*cur_regs)[reg] = value;
213 }
214 break;
215 }
216 case DWARF_LOCATION_UNDEFINED:
217 if (reg == cie->return_address_register) {
218 return_address_undefined = true;
219 }
220 default:
221 break;
222 }
223 }
224
225 // Find the return address location.
226 if (return_address_undefined) {
227 cur_regs->set_pc(0);
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700228 *finished = true;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700229 } else {
230 cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700231 *finished = false;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700232 }
233 cur_regs->set_sp(cfa);
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700234 // Return false if the unwind is not finished or the cfa and pc didn't change.
235 return *finished || prev_cfa != cfa || prev_pc != cur_regs->pc();
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700236}
237
238template <typename AddressType>
239const DwarfCie* DwarfSectionImpl<AddressType>::GetCie(uint64_t offset) {
240 auto cie_entry = cie_entries_.find(offset);
241 if (cie_entry != cie_entries_.end()) {
242 return &cie_entry->second;
243 }
244 DwarfCie* cie = &cie_entries_[offset];
245 memory_.set_cur_offset(offset);
246 if (!FillInCie(cie)) {
247 // Erase the cached entry.
248 cie_entries_.erase(offset);
249 return nullptr;
250 }
251 return cie;
252}
253
254template <typename AddressType>
255bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
256 uint32_t length32;
257 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
258 last_error_ = DWARF_ERROR_MEMORY_INVALID;
259 return false;
260 }
Christopher Ferrisd226a512017-07-14 10:37:19 -0700261 // Set the default for the lsda encoding.
262 cie->lsda_encoding = DW_EH_PE_omit;
263
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700264 if (length32 == static_cast<uint32_t>(-1)) {
265 // 64 bit Cie
266 uint64_t length64;
267 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
268 last_error_ = DWARF_ERROR_MEMORY_INVALID;
269 return false;
270 }
271
272 cie->cfa_instructions_end = memory_.cur_offset() + length64;
273 cie->fde_address_encoding = DW_EH_PE_sdata8;
274
275 uint64_t cie_id;
276 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
277 last_error_ = DWARF_ERROR_MEMORY_INVALID;
278 return false;
279 }
280 if (!IsCie64(cie_id)) {
281 // This is not a Cie, something has gone horribly wrong.
282 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
283 return false;
284 }
285 } else {
286 // 32 bit Cie
287 cie->cfa_instructions_end = memory_.cur_offset() + length32;
288 cie->fde_address_encoding = DW_EH_PE_sdata4;
289
290 uint32_t cie_id;
291 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
292 last_error_ = DWARF_ERROR_MEMORY_INVALID;
293 return false;
294 }
295 if (!IsCie32(cie_id)) {
296 // This is not a Cie, something has gone horribly wrong.
297 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
298 return false;
299 }
300 }
301
302 if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
303 last_error_ = DWARF_ERROR_MEMORY_INVALID;
304 return false;
305 }
306
307 if (cie->version != 1 && cie->version != 3 && cie->version != 4) {
308 // Unrecognized version.
309 last_error_ = DWARF_ERROR_UNSUPPORTED_VERSION;
310 return false;
311 }
312
313 // Read the augmentation string.
314 char aug_value;
315 do {
316 if (!memory_.ReadBytes(&aug_value, 1)) {
317 last_error_ = DWARF_ERROR_MEMORY_INVALID;
318 return false;
319 }
320 cie->augmentation_string.push_back(aug_value);
321 } while (aug_value != '\0');
322
323 if (cie->version == 4) {
324 // Skip the Address Size field since we only use it for validation.
325 memory_.set_cur_offset(memory_.cur_offset() + 1);
326
327 // Segment Size
328 if (!memory_.ReadBytes(&cie->segment_size, 1)) {
329 last_error_ = DWARF_ERROR_MEMORY_INVALID;
330 return false;
331 }
332 }
333
334 // Code Alignment Factor
335 if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
336 last_error_ = DWARF_ERROR_MEMORY_INVALID;
337 return false;
338 }
339
340 // Data Alignment Factor
341 if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
342 last_error_ = DWARF_ERROR_MEMORY_INVALID;
343 return false;
344 }
345
346 if (cie->version == 1) {
347 // Return Address is a single byte.
348 uint8_t return_address_register;
349 if (!memory_.ReadBytes(&return_address_register, 1)) {
350 last_error_ = DWARF_ERROR_MEMORY_INVALID;
351 return false;
352 }
353 cie->return_address_register = return_address_register;
354 } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
355 last_error_ = DWARF_ERROR_MEMORY_INVALID;
356 return false;
357 }
358
359 if (cie->augmentation_string[0] != 'z') {
360 cie->cfa_instructions_offset = memory_.cur_offset();
361 return true;
362 }
363
364 uint64_t aug_length;
365 if (!memory_.ReadULEB128(&aug_length)) {
366 last_error_ = DWARF_ERROR_MEMORY_INVALID;
367 return false;
368 }
369 cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
370
371 for (size_t i = 1; i < cie->augmentation_string.size(); i++) {
372 switch (cie->augmentation_string[i]) {
373 case 'L':
374 if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
375 last_error_ = DWARF_ERROR_MEMORY_INVALID;
376 return false;
377 }
378 break;
379 case 'P': {
380 uint8_t encoding;
381 if (!memory_.ReadBytes(&encoding, 1)) {
382 last_error_ = DWARF_ERROR_MEMORY_INVALID;
383 return false;
384 }
385 if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
386 last_error_ = DWARF_ERROR_MEMORY_INVALID;
387 return false;
388 }
389 } break;
390 case 'R':
391 if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
392 last_error_ = DWARF_ERROR_MEMORY_INVALID;
393 return false;
394 }
395 break;
396 }
397 }
398 return true;
399}
400
401template <typename AddressType>
402const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) {
403 auto fde_entry = fde_entries_.find(offset);
404 if (fde_entry != fde_entries_.end()) {
405 return &fde_entry->second;
406 }
407 DwarfFde* fde = &fde_entries_[offset];
408 memory_.set_cur_offset(offset);
409 if (!FillInFde(fde)) {
410 fde_entries_.erase(offset);
411 return nullptr;
412 }
413 return fde;
414}
415
416template <typename AddressType>
417bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
418 uint32_t length32;
419 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
420 last_error_ = DWARF_ERROR_MEMORY_INVALID;
421 return false;
422 }
423
424 if (length32 == static_cast<uint32_t>(-1)) {
425 // 64 bit Fde.
426 uint64_t length64;
427 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
428 last_error_ = DWARF_ERROR_MEMORY_INVALID;
429 return false;
430 }
431 fde->cfa_instructions_end = memory_.cur_offset() + length64;
432
433 uint64_t value64;
434 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
435 last_error_ = DWARF_ERROR_MEMORY_INVALID;
436 return false;
437 }
438 if (IsCie64(value64)) {
439 // This is a Cie, this means something has gone wrong.
440 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
441 return false;
442 }
443
444 // Get the Cie pointer, which is necessary to properly read the rest of
445 // of the Fde information.
446 fde->cie_offset = GetCieOffsetFromFde64(value64);
447 } else {
448 // 32 bit Fde.
449 fde->cfa_instructions_end = memory_.cur_offset() + length32;
450
451 uint32_t value32;
452 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
453 last_error_ = DWARF_ERROR_MEMORY_INVALID;
454 return false;
455 }
456 if (IsCie32(value32)) {
457 // This is a Cie, this means something has gone wrong.
458 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
459 return false;
460 }
461
462 // Get the Cie pointer, which is necessary to properly read the rest of
463 // of the Fde information.
464 fde->cie_offset = GetCieOffsetFromFde32(value32);
465 }
466 uint64_t cur_offset = memory_.cur_offset();
467
468 const DwarfCie* cie = GetCie(fde->cie_offset);
469 if (cie == nullptr) {
470 return false;
471 }
472 fde->cie = cie;
473
474 if (cie->segment_size != 0) {
475 // Skip over the segment selector for now.
476 cur_offset += cie->segment_size;
477 }
478 memory_.set_cur_offset(cur_offset);
479
480 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_start)) {
481 last_error_ = DWARF_ERROR_MEMORY_INVALID;
482 return false;
483 }
484 fde->pc_start = AdjustPcFromFde(fde->pc_start);
485
486 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_end)) {
487 last_error_ = DWARF_ERROR_MEMORY_INVALID;
488 return false;
489 }
490 fde->pc_end += fde->pc_start;
491 if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
492 // Augmentation Size
493 uint64_t aug_length;
494 if (!memory_.ReadULEB128(&aug_length)) {
495 last_error_ = DWARF_ERROR_MEMORY_INVALID;
496 return false;
497 }
498 uint64_t cur_offset = memory_.cur_offset();
499
500 if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
501 last_error_ = DWARF_ERROR_MEMORY_INVALID;
502 return false;
503 }
504
505 // Set our position to after all of the augmentation data.
506 memory_.set_cur_offset(cur_offset + aug_length);
507 }
508 fde->cfa_instructions_offset = memory_.cur_offset();
509
510 return true;
511}
512
513template <typename AddressType>
514bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
515 dwarf_loc_regs_t* loc_regs) {
516 DwarfCfa<AddressType> cfa(&memory_, fde);
517
518 // Look for the cached copy of the cie data.
519 auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
520 if (reg_entry == cie_loc_regs_.end()) {
521 if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end,
522 loc_regs)) {
523 last_error_ = cfa.last_error();
524 return false;
525 }
526 cie_loc_regs_[fde->cie_offset] = *loc_regs;
527 }
528 cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]);
529 if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) {
530 last_error_ = cfa.last_error();
531 return false;
532 }
533 return true;
534}
535
536template <typename AddressType>
537bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t load_bias,
538 const DwarfFde* fde) {
539 DwarfCfa<AddressType> cfa(&memory_, fde);
540
541 // Always print the cie information.
542 const DwarfCie* cie = fde->cie;
543 if (!cfa.Log(indent, pc, load_bias, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
544 last_error_ = cfa.last_error();
545 return false;
546 }
547 if (!cfa.Log(indent, pc, load_bias, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
548 last_error_ = cfa.last_error();
549 return false;
550 }
551 return true;
552}
553
554// Explicitly instantiate DwarfSectionImpl
555template class DwarfSectionImpl<uint32_t>;
556template class DwarfSectionImpl<uint64_t>;
Christopher Ferrisd226a512017-07-14 10:37:19 -0700557
558} // namespace unwindstack