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