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