blob: 57cb324a638cba19250b9f7c58ed0b2640069e34 [file] [log] [blame]
Chris Dearman231e3c82012-08-10 17:06:20 -07001/*
2 * Copyright (C) 2012 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/*
18 * Backtracing functions for mips
19 */
20
21#define LOG_TAG "Corkscrew"
22//#define LOG_NDEBUG 0
23
24#include "../backtrace-arch.h"
25#include "../backtrace-helper.h"
Chris Dearman529985782013-12-06 04:29:37 -080026#include "../ptrace-arch.h"
Chris Dearman231e3c82012-08-10 17:06:20 -070027#include <corkscrew/ptrace.h>
Chris Dearman529985782013-12-06 04:29:37 -080028#include "dwarf.h"
Chris Dearman231e3c82012-08-10 17:06:20 -070029
30#include <stdlib.h>
31#include <signal.h>
32#include <stdbool.h>
33#include <limits.h>
34#include <errno.h>
Chris Dearman529985782013-12-06 04:29:37 -080035#include <string.h>
Chris Dearman231e3c82012-08-10 17:06:20 -070036#include <sys/ptrace.h>
Chris Dearman231e3c82012-08-10 17:06:20 -070037#include <cutils/log.h>
38
Chris Dearman529985782013-12-06 04:29:37 -080039#if defined(__BIONIC__)
40
41#if defined(__BIONIC_HAVE_UCONTEXT_T)
42
43// Bionic offers the Linux kernel headers.
44#include <asm/sigcontext.h>
45#include <asm/ucontext.h>
46typedef struct ucontext ucontext_t;
47
48#else /* __BIONIC_HAVE_UCONTEXT_T */
49
50/* Old versions of the Android <signal.h> didn't define ucontext_t. */
51
Chris Dearman231e3c82012-08-10 17:06:20 -070052/* For PTRACE_GETREGS */
53typedef struct {
Chris Dearman231e3c82012-08-10 17:06:20 -070054 uint64_t regs[32];
55 uint64_t lo;
56 uint64_t hi;
57 uint64_t epc;
58 uint64_t badvaddr;
59 uint64_t status;
60 uint64_t cause;
61} user_regs_struct;
62
Chris Dearman529985782013-12-06 04:29:37 -080063enum {
64 REG_ZERO = 0, REG_AT, REG_V0, REG_V1,
65 REG_A0, REG_A1, REG_A2, REG_A3,
66 REG_T0, REG_T1, REG_T2, REG_T3,
67 REG_T4, REG_T5, REG_T6, REG_T7,
68 REG_S0, REG_S1, REG_S2, REG_S3,
69 REG_S4, REG_S5, REG_S6, REG_S7,
70 REG_T8, REG_T9, REG_K0, REG_K1,
71 REG_GP, REG_SP, REG_S8, REG_RA,
72};
73
Chris Dearman231e3c82012-08-10 17:06:20 -070074/* Machine context at the time a signal was raised. */
75typedef struct ucontext {
Chris Dearman529985782013-12-06 04:29:37 -080076 unsigned int sc_regmask;
77 unsigned int sc_status;
78 unsigned long long sc_pc;
79 unsigned long long sc_regs[32];
80 unsigned long long sc_fpregs[32];
81 unsigned int sc_acx;
82 unsigned int sc_fpc_csr;
83 unsigned int sc_fpc_eir;
84 unsigned int sc_used_math;
85 unsigned int sc_dsp;
86 unsigned long long sc_mdhi;
87 unsigned long long sc_mdlo;
88 unsigned long sc_hi1;
89 unsigned long sc_lo1;
90 unsigned long sc_hi2;
91 unsigned long sc_lo2;
92 unsigned long sc_hi3;
93 unsigned long sc_lo3;
Chris Dearman231e3c82012-08-10 17:06:20 -070094} ucontext_t;
95
Chris Dearman529985782013-12-06 04:29:37 -080096#endif /* __BIONIC_HAVE_UCONTEXT_T */
97#endif
98
Chris Dearman231e3c82012-08-10 17:06:20 -070099/* Unwind state. */
100typedef struct {
Chris Dearman529985782013-12-06 04:29:37 -0800101 uint32_t reg[DWARF_REGISTERS];
Chris Dearman231e3c82012-08-10 17:06:20 -0700102} unwind_state_t;
103
Chris Dearman529985782013-12-06 04:29:37 -0800104uintptr_t rewind_pc_arch(const memory_t* memory __attribute__((unused)), uintptr_t pc) {
Chris Dearman231e3c82012-08-10 17:06:20 -0700105 if (pc == 0)
106 return pc;
107 if ((pc & 1) == 0)
108 return pc-8; /* jal/bal/jalr + branch delay slot */
109 return pc;
110}
111
Chris Dearman529985782013-12-06 04:29:37 -0800112/* Read byte through 4 byte cache. Usually we read byte by byte and updating cursor. */
113static bool try_get_byte(const memory_t* memory, uintptr_t ptr, uint8_t* out_value, uint32_t* cursor) {
114 static uintptr_t lastptr;
115 static uint32_t buf;
116
117 ptr += *cursor;
118
119 if (ptr < lastptr || lastptr + 3 < ptr) {
120 lastptr = (ptr >> 2) << 2;
121 if (!try_get_word(memory, lastptr, &buf)) {
122 return false;
123 }
124 }
125 *out_value = (uint8_t)((buf >> ((ptr & 3) * 8)) & 0xff);
126 ++*cursor;
127 return true;
128}
129
130/* Getting X bytes. 4 is maximum for now. */
131static bool try_get_xbytes(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint8_t bytes, uint32_t* cursor) {
132 uint32_t data = 0;
133 if (bytes > 4) {
134 ALOGE("can't read more than 4 bytes, trying to read %d", bytes);
135 return false;
136 }
137 for (int i = 0; i < bytes; i++) {
138 uint8_t buf;
139 if (!try_get_byte(memory, ptr, &buf, cursor)) {
140 return false;
141 }
142 data |= (uint32_t)buf << (i * 8);
143 }
144 *out_value = data;
145 return true;
146}
147
148/* Reads signed/unsigned LEB128 encoded data. From 1 to 4 bytes. */
149static bool try_get_leb128(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint32_t* cursor, bool sign_extend) {
150 uint8_t buf = 0;
151 uint32_t val = 0;
152 uint8_t c = 0;
153 do {
154 if (!try_get_byte(memory, ptr, &buf, cursor)) {
155 return false;
156 }
157 val |= ((uint32_t)buf & 0x7f) << (c * 7);
158 c++;
159 } while (buf & 0x80 && (c * 7) <= 32);
160 if (c * 7 > 32) {
161 ALOGE("%s: data exceeds expected 4 bytes maximum", __FUNCTION__);
162 return false;
163 }
164 if (sign_extend) {
165 if (buf & 0x40) {
166 val |= ((uint32_t)-1 << (c * 7));
167 }
168 }
169 *out_value = val;
170 return true;
171}
172
173/* Reads signed LEB128 encoded data. From 1 to 4 bytes. */
174static bool try_get_sleb128(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint32_t* cursor) {
175 return try_get_leb128(memory, ptr, out_value, cursor, true);
176}
177
178/* Reads unsigned LEB128 encoded data. From 1 to 4 bytes. */
179static bool try_get_uleb128(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint32_t* cursor) {
180 return try_get_leb128(memory, ptr, out_value, cursor, false);
181}
182
183/* Getting data encoded by dwarf encodings. */
184static bool read_dwarf(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint8_t encoding, uint32_t* cursor) {
185 uint32_t data = 0;
186 bool issigned = true;
187 uintptr_t addr = ptr + *cursor;
188 /* Lower 4 bits is data type/size */
189 /* TODO: add more encodings if it becomes necessary */
190 switch (encoding & 0xf) {
191 case DW_EH_PE_absptr:
192 if (!try_get_xbytes(memory, ptr, &data, 4, cursor)) {
193 return false;
194 }
195 *out_value = data;
196 return true;
197 case DW_EH_PE_udata4:
198 issigned = false;
199 case DW_EH_PE_sdata4:
200 if (!try_get_xbytes(memory, ptr, &data, 4, cursor)) {
201 return false;
202 }
203 break;
204 default:
205 ALOGE("unrecognized dwarf lower part encoding: 0x%x", encoding);
206 return false;
207 }
208 /* Higher 4 bits is modifier */
209 /* TODO: add more encodings if it becomes necessary */
210 switch (encoding & 0xf0) {
211 case 0:
212 *out_value = data;
213 break;
214 case DW_EH_PE_pcrel:
215 if (issigned) {
216 *out_value = addr + (int32_t)data;
217 } else {
218 *out_value = addr + data;
219 }
220 break;
221 /* Assuming ptr is correct base to calculate datarel */
222 case DW_EH_PE_datarel:
223 if (issigned) {
224 *out_value = ptr + (int32_t)data;
225 } else {
226 *out_value = ptr + data;
227 }
228 break;
229 default:
230 ALOGE("unrecognized dwarf higher part encoding: 0x%x", encoding);
231 return false;
232 }
233 return true;
234}
235
236/* Having PC find corresponding FDE by reading .eh_frame_hdr section data. */
237static uintptr_t find_fde(const memory_t* memory,
238 const map_info_t* map_info_list, uintptr_t pc) {
239 if (!pc) {
240 ALOGV("find_fde: pc is zero, no eh_frame");
241 return 0;
242 }
243 const map_info_t* mi = find_map_info(map_info_list, pc);
244 if (!mi) {
245 ALOGV("find_fde: no map info for pc:0x%x", pc);
246 return 0;
247 }
248 const map_info_data_t* midata = mi->data;
249 if (!midata) {
250 ALOGV("find_fde: no eh_frame_hdr for map: start=0x%x, end=0x%x", mi->start, mi->end);
251 return 0;
252 }
253
254 eh_frame_hdr_info_t eh_hdr_info;
255 memset(&eh_hdr_info, 0, sizeof(eh_frame_hdr_info_t));
256
257 /* Getting the first word of eh_frame_hdr:
258 1st byte is version;
259 2nd byte is encoding of pointer to eh_frames;
260 3rd byte is encoding of count of FDEs in lookup table;
261 4th byte is encoding of lookup table entries.
262 */
263 uintptr_t eh_frame_hdr = midata->eh_frame_hdr;
264 uint32_t c = 0;
265 if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.version, &c)) return 0;
266 if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.eh_frame_ptr_enc, &c)) return 0;
267 if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.fde_count_enc, &c)) return 0;
268 if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.fde_table_enc, &c)) return 0;
269
270 /* TODO: 3rd byte can be DW_EH_PE_omit, that means no lookup table available and we should
271 try to parse eh_frame instead. Not sure how often it may occur, skipping now.
272 */
273 if (eh_hdr_info.version != 1) {
274 ALOGV("find_fde: eh_frame_hdr version %d is not supported", eh_hdr_info.version);
275 return 0;
276 }
277 /* Getting the data:
278 2nd word is eh_frame pointer (normally not used, because lookup table has all we need);
279 3rd word is count of FDEs in the lookup table;
280 starting from 4 word there is FDE lookup table (pairs of PC and FDE pointer) sorted by PC;
281 */
282 if (!read_dwarf(memory, eh_frame_hdr, &eh_hdr_info.eh_frame_ptr, eh_hdr_info.eh_frame_ptr_enc, &c)) return 0;
283 if (!read_dwarf(memory, eh_frame_hdr, &eh_hdr_info.fde_count, eh_hdr_info.fde_count_enc, &c)) return 0;
284 ALOGV("find_fde: found %d FDEs", eh_hdr_info.fde_count);
285
286 int32_t low = 0;
287 int32_t high = eh_hdr_info.fde_count;
288 uintptr_t start = 0;
289 uintptr_t fde = 0;
290 /* eh_frame_hdr + c points to lookup table at this point. */
291 while (low <= high) {
292 uint32_t mid = (high + low)/2;
293 uint32_t entry = c + mid * 8;
294 if (!read_dwarf(memory, eh_frame_hdr, &start, eh_hdr_info.fde_table_enc, &entry)) return 0;
295 if (pc <= start) {
296 high = mid - 1;
297 } else {
298 low = mid + 1;
299 }
300 }
301 /* Value found is at high. */
302 if (high < 0) {
303 ALOGV("find_fde: pc %x is out of FDE bounds: %x", pc, start);
304 return 0;
305 }
306 c += high * 8;
307 if (!read_dwarf(memory, eh_frame_hdr, &start, eh_hdr_info.fde_table_enc, &c)) return 0;
308 if (!read_dwarf(memory, eh_frame_hdr, &fde, eh_hdr_info.fde_table_enc, &c)) return 0;
309 ALOGV("pc 0x%x, ENTRY %d: start=0x%x, fde=0x%x", pc, high, start, fde);
310 return fde;
311}
312
313/* Execute single dwarf instruction and update dwarf state accordingly. */
314static bool execute_dwarf(const memory_t* memory, uintptr_t ptr, cie_info_t* cie_info,
315 dwarf_state_t* dstate, uint32_t* cursor,
316 dwarf_state_t* stack, uint8_t* stack_ptr) {
317 uint8_t inst;
318 uint8_t op = 0;
319
320 if (!try_get_byte(memory, ptr, &inst, cursor)) {
321 return false;
322 }
323 ALOGV("DW_CFA inst: 0x%x", inst);
324
325 /* For some instructions upper 2 bits is opcode and lower 6 bits is operand. See dwarf-2.0 7.23. */
326 if (inst & 0xc0) {
327 op = inst & 0x3f;
328 inst &= 0xc0;
329 }
330
331 switch ((dwarf_CFA)inst) {
332 uint32_t reg = 0;
333 uint32_t offset = 0;
334 case DW_CFA_advance_loc:
335 dstate->loc += op * cie_info->code_align;
336 ALOGV("DW_CFA_advance_loc: %d to 0x%x", op, dstate->loc);
337 break;
338 case DW_CFA_offset:
339 if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false;
340 dstate->regs[op].rule = 'o';
341 dstate->regs[op].value = offset * cie_info->data_align;
342 ALOGV("DW_CFA_offset: r%d = o(%d)", op, dstate->regs[op].value);
343 break;
344 case DW_CFA_restore:
345 dstate->regs[op].rule = stack->regs[op].rule;
346 dstate->regs[op].value = stack->regs[op].value;
347 ALOGV("DW_CFA_restore: r%d = %c(%d)", op, dstate->regs[op].rule, dstate->regs[op].value);
348 break;
349 case DW_CFA_nop:
350 break;
351 case DW_CFA_set_loc: // probably we don't have it on mips.
352 if (!try_get_xbytes(memory, ptr, &offset, 4, cursor)) return false;
353 if (offset < dstate->loc) {
354 ALOGE("DW_CFA_set_loc: attempt to move location backward");
355 return false;
356 }
357 dstate->loc = offset * cie_info->code_align;
358 ALOGV("DW_CFA_set_loc: %d to 0x%x", offset * cie_info->code_align, dstate->loc);
359 break;
360 case DW_CFA_advance_loc1:
361 if (!try_get_byte(memory, ptr, (uint8_t*)&offset, cursor)) return false;
362 dstate->loc += (uint8_t)offset * cie_info->code_align;
363 ALOGV("DW_CFA_advance_loc1: %d to 0x%x", (uint8_t)offset * cie_info->code_align, dstate->loc);
364 break;
365 case DW_CFA_advance_loc2:
366 if (!try_get_xbytes(memory, ptr, &offset, 2, cursor)) return false;
367 dstate->loc += (uint16_t)offset * cie_info->code_align;
368 ALOGV("DW_CFA_advance_loc2: %d to 0x%x", (uint16_t)offset * cie_info->code_align, dstate->loc);
369 break;
370 case DW_CFA_advance_loc4:
371 if (!try_get_xbytes(memory, ptr, &offset, 4, cursor)) return false;
372 dstate->loc += offset * cie_info->code_align;
373 ALOGV("DW_CFA_advance_loc4: %d to 0x%x", offset * cie_info->code_align, dstate->loc);
374 break;
375 case DW_CFA_offset_extended: // probably we don't have it on mips.
376 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
377 if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false;
378 if (reg >= DWARF_REGISTERS) {
379 ALOGE("DW_CFA_offset_extended: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
380 return false;
381 }
382 dstate->regs[reg].rule = 'o';
383 dstate->regs[reg].value = offset * cie_info->data_align;
384 ALOGV("DW_CFA_offset_extended: r%d = o(%d)", reg, dstate->regs[reg].value);
385 break;
386 case DW_CFA_restore_extended: // probably we don't have it on mips.
387 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
388 if (reg >= DWARF_REGISTERS) {
389 ALOGE("DW_CFA_restore_extended: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
390 return false;
391 }
392 dstate->regs[reg].rule = stack->regs[reg].rule;
393 dstate->regs[reg].value = stack->regs[reg].value;
394 ALOGV("DW_CFA_restore: r%d = %c(%d)", reg, dstate->regs[reg].rule, dstate->regs[reg].value);
395 break;
396 case DW_CFA_undefined: // probably we don't have it on mips.
397 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
398 if (reg >= DWARF_REGISTERS) {
399 ALOGE("DW_CFA_undefined: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
400 return false;
401 }
402 dstate->regs[reg].rule = 'u';
403 dstate->regs[reg].value = 0;
404 ALOGV("DW_CFA_undefined: r%d", reg);
405 break;
406 case DW_CFA_same_value: // probably we don't have it on mips.
407 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
408 if (reg >= DWARF_REGISTERS) {
409 ALOGE("DW_CFA_undefined: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
410 return false;
411 }
412 dstate->regs[reg].rule = 's';
413 dstate->regs[reg].value = 0;
414 ALOGV("DW_CFA_same_value: r%d", reg);
415 break;
416 case DW_CFA_register: // probably we don't have it on mips.
417 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
418 /* that's new register actually, not offset */
419 if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false;
420 if (reg >= DWARF_REGISTERS || offset >= DWARF_REGISTERS) {
421 ALOGE("DW_CFA_register: r%d or r%d exceeds supported number of registers (%d)", reg, offset, DWARF_REGISTERS);
422 return false;
423 }
424 dstate->regs[reg].rule = 'r';
425 dstate->regs[reg].value = offset;
426 ALOGV("DW_CFA_register: r%d = r(%d)", reg, dstate->regs[reg].value);
427 break;
428 case DW_CFA_remember_state:
429 if (*stack_ptr == DWARF_STATES_STACK) {
430 ALOGE("DW_CFA_remember_state: states stack overflow %d", *stack_ptr);
431 return false;
432 }
433 stack[(*stack_ptr)++] = *dstate;
434 ALOGV("DW_CFA_remember_state: stacktop moves to %d", *stack_ptr);
435 break;
436 case DW_CFA_restore_state:
437 /* We have CIE state saved at 0 position. It's not supposed to be taken
438 by DW_CFA_restore_state. */
439 if (*stack_ptr == 1) {
440 ALOGE("DW_CFA_restore_state: states stack is empty");
441 return false;
442 }
443 /* Don't touch location on restore. */
444 uintptr_t saveloc = dstate->loc;
445 *dstate = stack[--*stack_ptr];
446 dstate->loc = saveloc;
447 ALOGV("DW_CFA_restore_state: stacktop moves to %d", *stack_ptr);
448 break;
449 case DW_CFA_def_cfa:
450 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
451 if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false;
452 dstate->cfa_reg = reg;
453 dstate->cfa_off = offset;
454 ALOGV("DW_CFA_def_cfa: %x(r%d)", offset, reg);
455 break;
456 case DW_CFA_def_cfa_register:
457 if (!try_get_uleb128(memory, ptr, &reg, cursor)) {
458 return false;
459 }
460 dstate->cfa_reg = reg;
461 ALOGV("DW_CFA_def_cfa_register: r%d", reg);
462 break;
463 case DW_CFA_def_cfa_offset:
464 if (!try_get_uleb128(memory, ptr, &offset, cursor)) {
465 return false;
466 }
467 dstate->cfa_off = offset;
468 ALOGV("DW_CFA_def_cfa_offset: %x", offset);
469 break;
470 default:
471 ALOGE("unrecognized DW_CFA_* instruction: 0x%x", inst);
472 return false;
473 }
474 return true;
475}
476
477/* Restoring particular register value based on dwarf state. */
478static bool get_old_register_value(const memory_t* memory, uint32_t cfa,
479 dwarf_state_t* dstate, uint8_t reg,
480 unwind_state_t* state, unwind_state_t* newstate) {
481 uint32_t addr;
482 switch (dstate->regs[reg].rule) {
483 case 0:
484 /* We don't have dstate updated for this register, so assuming value kept the same.
485 Normally we should look into state and return current value as the old one
486 but we don't have all registers in state to handle this properly */
487 ALOGV("get_old_register_value: value of r%d is the same", reg);
488 // for SP if it's not updated by dwarf rule we assume it's equal to CFA
489 // for PC if it's not updated by dwarf rule we assume it's equal to RA
490 if (reg == DWARF_SP) {
491 ALOGV("get_old_register_value: adjusting sp to CFA: 0x%x", cfa);
492 newstate->reg[reg] = cfa;
493 } else if (reg == DWARF_PC) {
494 ALOGV("get_old_register_value: adjusting PC to RA: 0x%x", newstate->reg[DWARF_RA]);
495 newstate->reg[reg] = newstate->reg[DWARF_RA];
496 } else {
497 newstate->reg[reg] = state->reg[reg];
498 }
499 break;
500 case 'o':
501 addr = cfa + (int32_t)dstate->regs[reg].value;
502 if (!try_get_word(memory, addr, &newstate->reg[reg])) {
503 ALOGE("get_old_register_value: can't read from 0x%x", addr);
504 return false;
505 }
506 ALOGV("get_old_register_value: r%d at 0x%x is 0x%x", reg, addr, newstate->reg[reg]);
507 break;
508 case 'r':
509 /* We don't have all registers in state so don't even try to look at 'r' */
510 ALOGE("get_old_register_value: register lookup not implemented yet");
511 break;
512 default:
513 ALOGE("get_old_register_value: unexpected rule:%c value:%d for register %d",
514 dstate->regs[reg].rule, (int32_t)dstate->regs[reg].value, reg);
515 return false;
516 }
517 return true;
518}
519
520/* Updaing state based on dwarf state. */
521static bool update_state(const memory_t* memory, unwind_state_t* state,
522 dwarf_state_t* dstate) {
523 unwind_state_t newstate;
524 /* We can restore more registers here if we need them. Meanwile doing minimal work here. */
525 /* Getting CFA. */
526 uintptr_t cfa = 0;
527 if (dstate->cfa_reg == DWARF_SP) {
528 cfa = state->reg[DWARF_SP] + dstate->cfa_off;
529 } else if (dstate->cfa_reg == DWARF_FP) {
530 cfa = state->reg[DWARF_FP] + dstate->cfa_off;
531 } else {
532 ALOGE("update_state: unexpected CFA register: %d", dstate->cfa_reg);
533 return false;
534 }
535 ALOGV("update_state: new CFA: 0x%x", cfa);
536
537 /* Update registers. Order is important to allow RA to propagate to PC */
538 /* Getting FP. */
539 if (!get_old_register_value(memory, cfa, dstate, DWARF_FP, state, &newstate)) return false;
540 /* Getting SP. */
541 if (!get_old_register_value(memory, cfa, dstate, DWARF_SP, state, &newstate)) return false;
542 /* Getting RA. */
543 if (!get_old_register_value(memory, cfa, dstate, DWARF_RA, state, &newstate)) return false;
544 /* Getting PC. */
545 if (!get_old_register_value(memory, cfa, dstate, DWARF_PC, state, &newstate)) return false;
546
547 ALOGV("update_state: PC: 0x%x; restore PC: 0x%x", state->reg[DWARF_PC], newstate.reg[DWARF_PC]);
548 ALOGV("update_state: RA: 0x%x; restore RA: 0x%x", state->reg[DWARF_RA], newstate.reg[DWARF_RA]);
549 ALOGV("update_state: FP: 0x%x; restore FP: 0x%x", state->reg[DWARF_FP], newstate.reg[DWARF_FP]);
550 ALOGV("update_state: SP: 0x%x; restore SP: 0x%x", state->reg[DWARF_SP], newstate.reg[DWARF_SP]);
551
552 if (newstate.reg[DWARF_PC] == 0)
553 return false;
554
555 /* End backtrace if registers do not change */
556 if ((state->reg[DWARF_PC] == newstate.reg[DWARF_PC]) &&
557 (state->reg[DWARF_RA] == newstate.reg[DWARF_RA]) &&
558 (state->reg[DWARF_FP] == newstate.reg[DWARF_FP]) &&
559 (state->reg[DWARF_SP] == newstate.reg[DWARF_SP]))
560 return false;
561
562 *state = newstate;
563 return true;
564}
565
566/* Execute CIE and FDE instructions for FDE found with find_fde. */
567static bool execute_fde(const memory_t* memory,
568 uintptr_t fde,
569 unwind_state_t* state) {
570 uint32_t fde_length = 0;
571 uint32_t cie_length = 0;
572 uintptr_t cie = 0;
573 uintptr_t cie_offset = 0;
574 cie_info_t cie_i;
575 cie_info_t* cie_info = &cie_i;
576 fde_info_t fde_i;
577 fde_info_t* fde_info = &fde_i;
578 dwarf_state_t dwarf_state;
579 dwarf_state_t* dstate = &dwarf_state;
580 dwarf_state_t stack[DWARF_STATES_STACK];
581 uint8_t stack_ptr = 0;
582
583 memset(dstate, 0, sizeof(dwarf_state_t));
584 memset(cie_info, 0, sizeof(cie_info_t));
585 memset(fde_info, 0, sizeof(fde_info_t));
586
587 /* Read common CIE or FDE area:
588 1st word is length;
589 2nd word is ID: 0 for CIE, CIE pointer for FDE.
590 */
591 if (!try_get_word(memory, fde, &fde_length)) {
592 return false;
593 }
594 if ((int32_t)fde_length == -1) {
595 ALOGV("execute_fde: 64-bit dwarf detected, not implemented yet");
596 return false;
597 }
598 if (!try_get_word(memory, fde + 4, &cie_offset)) {
599 return false;
600 }
601 if (cie_offset == 0) {
602 /* This is CIE. We shouldn't be here normally. */
603 cie = fde;
604 cie_length = fde_length;
605 } else {
606 /* Find CIE. */
607 /* Positive cie_offset goes backward from current field. */
608 cie = fde + 4 - cie_offset;
609 if (!try_get_word(memory, cie, &cie_length)) {
610 return false;
611 }
612 if ((int32_t)cie_length == -1) {
613 ALOGV("execute_fde: 64-bit dwarf detected, not implemented yet");
614 return false;
615 }
616 if (!try_get_word(memory, cie + 4, &cie_offset)) {
617 return false;
618 }
619 if (cie_offset != 0) {
620 ALOGV("execute_fde: can't find CIE");
621 return false;
622 }
623 }
624 ALOGV("execute_fde: FDE length: %d", fde_length);
625 ALOGV("execute_fde: CIE pointer: %x", cie);
626 ALOGV("execute_fde: CIE length: %d", cie_length);
627
628 /* Read CIE:
629 Augmentation independent:
630 1st byte is version;
631 next x bytes is /0 terminated augmentation string;
632 next x bytes is unsigned LEB128 encoded code alignment factor;
633 next x bytes is signed LEB128 encoded data alignment factor;
634 next 1 (CIE version 1) or x (CIE version 3 unsigned LEB128) bytes is return register column;
635 Augmentation dependent:
636 if 'z' next x bytes is unsigned LEB128 encoded augmentation data size;
637 if 'L' next 1 byte is LSDA encoding;
638 if 'R' next 1 byte is FDE encoding;
639 if 'S' CIE represents signal handler stack frame;
640 if 'P' next 1 byte is personality encoding folowed by personality function pointer;
641 Next x bytes is CIE program.
642 */
643
644 uint32_t c = 8;
645 if (!try_get_byte(memory, cie, &cie_info->version, &c)) {
646 return false;
647 }
648 ALOGV("execute_fde: CIE version: %d", cie_info->version);
649 uint8_t ch;
650 do {
651 if (!try_get_byte(memory, cie, &ch, &c)) {
652 return false;
653 }
654 switch (ch) {
655 case '\0': break;
656 case 'z': cie_info->aug_z = 1; break;
657 case 'L': cie_info->aug_L = 1; break;
658 case 'R': cie_info->aug_R = 1; break;
659 case 'S': cie_info->aug_S = 1; break;
660 case 'P': cie_info->aug_P = 1; break;
661 default:
662 ALOGV("execute_fde: Unrecognized CIE augmentation char: '%c'", ch);
663 return false;
664 break;
665 }
666 } while (ch);
667 if (!try_get_uleb128(memory, cie, &cie_info->code_align, &c)) {
668 return false;
669 }
670 if (!try_get_sleb128(memory, cie, &cie_info->data_align, &c)) {
671 return false;
672 }
673 if (cie_info->version >= 3) {
674 if (!try_get_uleb128(memory, cie, &cie_info->reg, &c)) {
675 return false;
676 }
677 } else {
678 if (!try_get_byte(memory, cie, (uint8_t*)&cie_info->reg, &c)) {
679 return false;
680 }
681 }
682 ALOGV("execute_fde: CIE code alignment factor: %d", cie_info->code_align);
683 ALOGV("execute_fde: CIE data alignment factor: %d", cie_info->data_align);
684 if (cie_info->aug_z) {
685 if (!try_get_uleb128(memory, cie, &cie_info->aug_z, &c)) {
686 return false;
687 }
688 }
689 if (cie_info->aug_L) {
690 if (!try_get_byte(memory, cie, &cie_info->aug_L, &c)) {
691 return false;
692 }
693 } else {
694 /* Default encoding. */
695 cie_info->aug_L = DW_EH_PE_absptr;
696 }
697 if (cie_info->aug_R) {
698 if (!try_get_byte(memory, cie, &cie_info->aug_R, &c)) {
699 return false;
700 }
701 } else {
702 /* Default encoding. */
703 cie_info->aug_R = DW_EH_PE_absptr;
704 }
705 if (cie_info->aug_P) {
706 /* Get encoding of personality routine pointer. We don't use it now. */
707 if (!try_get_byte(memory, cie, (uint8_t*)&cie_info->aug_P, &c)) {
708 return false;
709 }
710 /* Get routine pointer. */
711 if (!read_dwarf(memory, cie, &cie_info->aug_P, (uint8_t)cie_info->aug_P, &c)) {
712 return false;
713 }
714 }
715 /* CIE program. */
716 /* Length field itself (4 bytes) is not included into length. */
717 stack[0] = *dstate;
718 stack_ptr = 1;
719 while (c < cie_length + 4) {
720 if (!execute_dwarf(memory, cie, cie_info, dstate, &c, stack, &stack_ptr)) {
721 return false;
722 }
723 }
724
725 /* We went directly to CIE. Normally it shouldn't occur. */
726 if (cie == fde) return true;
727
728 /* Go back to FDE. */
729 c = 8;
730 /* Read FDE:
731 Augmentation independent:
732 next x bytes (encoded as specified in CIE) is FDE starting address;
733 next x bytes (encoded as specified in CIE) is FDE number of instructions covered;
734 Augmentation dependent:
735 if 'z' next x bytes is unsigned LEB128 encoded augmentation data size;
736 if 'L' next x bytes is LSDA pointer (encoded as specified in CIE);
737 Next x bytes is FDE program.
738 */
739 if (!read_dwarf(memory, fde, &fde_info->start, (uint8_t)cie_info->aug_R, &c)) {
740 return false;
741 }
742 dstate->loc = fde_info->start;
743 ALOGV("execute_fde: FDE start: %x", dstate->loc);
744 if (!read_dwarf(memory, fde, &fde_info->length, 0, &c)) {
745 return false;
746 }
747 ALOGV("execute_fde: FDE length: %x", fde_info->length);
748 if (cie_info->aug_z) {
749 if (!try_get_uleb128(memory, fde, &fde_info->aug_z, &c)) {
750 return false;
751 }
752 }
753 if (cie_info->aug_L && cie_info->aug_L != DW_EH_PE_omit) {
754 if (!read_dwarf(memory, fde, &fde_info->aug_L, cie_info->aug_L, &c)) {
755 return false;
756 }
757 }
758 /* FDE program. */
759 /* Length field itself (4 bytes) is not included into length. */
760 /* Save CIE state as 0 element of stack. Used by DW_CFA_restore. */
761 stack[0] = *dstate;
762 stack_ptr = 1;
763 while (c < fde_length + 4 && state->reg[DWARF_PC] >= dstate->loc) {
764 if (!execute_dwarf(memory, fde, cie_info, dstate, &c, stack, &stack_ptr)) {
765 return false;
766 }
767 ALOGV("PC: %x, LOC: %x", state->reg[DWARF_PC], dstate->loc);
768 }
769
770 return update_state(memory, state, dstate);
771}
772
773static bool heuristic_state_update(const memory_t* memory, unwind_state_t* state)
774{
775 bool found_start = false;
776 int maxcheck = 1024;
777 int32_t stack_size = 0;
778 int32_t ra_offset = 0;
779 dwarf_state_t dwarf_state;
780 dwarf_state_t* dstate = &dwarf_state;
781
782 static struct {
783 uint32_t insn;
784 uint32_t mask;
785 } frame0sig[] = {
786 {0x3c1c0000, 0xffff0000}, /* lui gp,xxxx */
787 {0x279c0000, 0xffff0000}, /* addiu gp,gp,xxxx */
788 {0x039fe021, 0xffffffff}, /* addu gp,gp,ra */
789 };
790 const int nframe0sig = sizeof(frame0sig)/sizeof(frame0sig[0]);
791 int f0 = nframe0sig;
792 memset(dstate, 0, sizeof(dwarf_state_t));
793
794 /* Search code backwards looking for function prologue */
795 for (uint32_t pc = state->reg[DWARF_PC]-4; maxcheck-- > 0 && !found_start; pc -= 4) {
796 uint32_t op;
797 int32_t immediate;
798
799 if (!try_get_word(memory, pc, &op))
800 return false;
801
802 // ALOGV("@0x%08x: 0x%08x\n", pc, op);
803
804 // Check for frame 0 signature
805 if ((op & frame0sig[f0].mask) == frame0sig[f0].insn) {
806 if (f0 == 0)
807 return false;
808 f0--;
809 }
810 else {
811 f0 = nframe0sig;
812 }
813
814 switch (op & 0xffff0000) {
815 case 0x27bd0000: // addiu sp, imm
816 // looking for stack being decremented
817 immediate = (((int32_t)op) << 16) >> 16;
818 if (immediate < 0) {
819 stack_size = -immediate;
820 ALOGV("@0x%08x: found stack adjustment=%d\n", pc, stack_size);
821 }
822 break;
823 case 0x039f0000: // e021
824
825 case 0xafbf0000: // sw ra, imm(sp)
826 ra_offset = (((int32_t)op) << 16) >> 16;
827 ALOGV("@0x%08x: found ra offset=%d\n", pc, ra_offset);
828 break;
829 case 0x3c1c0000: // lui gp
830 ALOGV("@0x%08x: found function boundary", pc);
831 found_start = true;
832 break;
833 default:
834 break;
835 }
836 }
837
838 dstate->cfa_reg = DWARF_SP;
839 dstate->cfa_off = stack_size;
840
841 if (ra_offset) {
842 dstate->regs[DWARF_RA].rule = 'o';
843 dstate->regs[DWARF_RA].value = -stack_size + ra_offset;
844 }
845
846 return update_state(memory, state, dstate);
847}
848
Chris Dearman231e3c82012-08-10 17:06:20 -0700849static ssize_t unwind_backtrace_common(const memory_t* memory,
850 const map_info_t* map_info_list,
851 unwind_state_t* state, backtrace_frame_t* backtrace,
852 size_t ignore_depth, size_t max_depth) {
Chris Dearman529985782013-12-06 04:29:37 -0800853
Chris Dearman231e3c82012-08-10 17:06:20 -0700854 size_t ignored_frames = 0;
855 size_t returned_frames = 0;
856
Chris Dearman529985782013-12-06 04:29:37 -0800857 ALOGV("Unwinding tid: %d", memory->tid);
858 ALOGV("PC: %x", state->reg[DWARF_PC]);
859 ALOGV("RA: %x", state->reg[DWARF_RA]);
860 ALOGV("FP: %x", state->reg[DWARF_FP]);
861 ALOGV("SP: %x", state->reg[DWARF_SP]);
862
Chris Dearman231e3c82012-08-10 17:06:20 -0700863 for (size_t index = 0; returned_frames < max_depth; index++) {
Chris Dearman529985782013-12-06 04:29:37 -0800864 uintptr_t fde = find_fde(memory, map_info_list, state->reg[DWARF_PC]);
865 backtrace_frame_t* frame = add_backtrace_entry(
866 index ? rewind_pc_arch(memory, state->reg[DWARF_PC]) : state->reg[DWARF_PC],
867 backtrace, ignore_depth, max_depth,
868 &ignored_frames, &returned_frames);
869 uint32_t stack_top = state->reg[DWARF_SP];
Chris Dearman231e3c82012-08-10 17:06:20 -0700870
Chris Dearman529985782013-12-06 04:29:37 -0800871 if (fde) {
872 /* Use FDE to update state */
873 if (!execute_fde(memory, fde, state))
874 break;
875 }
876 else {
877 /* FDE is not found, update state heuristically */
878 if (!heuristic_state_update(memory, state))
879 break;
880 }
Chris Dearman231e3c82012-08-10 17:06:20 -0700881
Chris Dearman529985782013-12-06 04:29:37 -0800882 if (frame) {
883 frame->stack_top = stack_top;
884 if (stack_top < state->reg[DWARF_SP]) {
885 frame->stack_size = state->reg[DWARF_SP] - stack_top;
Chris Dearman231e3c82012-08-10 17:06:20 -0700886 }
887 }
Chris Dearman529985782013-12-06 04:29:37 -0800888 ALOGV("Stack: 0x%x ... 0x%x - %d bytes", frame->stack_top, state->reg[DWARF_SP], frame->stack_size);
Chris Dearman231e3c82012-08-10 17:06:20 -0700889 }
Chris Dearman231e3c82012-08-10 17:06:20 -0700890 return returned_frames;
891}
892
Chris Dearman529985782013-12-06 04:29:37 -0800893ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo __attribute__((unused)), void* sigcontext,
Chris Dearman231e3c82012-08-10 17:06:20 -0700894 const map_info_t* map_info_list,
895 backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
896 const ucontext_t* uc = (const ucontext_t*)sigcontext;
897
898 unwind_state_t state;
Chris Dearman529985782013-12-06 04:29:37 -0800899 state.reg[DWARF_PC] = uc->sc_pc;
900 state.reg[DWARF_RA] = uc->sc_regs[REG_RA];
901 state.reg[DWARF_FP] = uc->sc_regs[REG_S8];
902 state.reg[DWARF_SP] = uc->sc_regs[REG_SP];
Chris Dearman231e3c82012-08-10 17:06:20 -0700903
Duane Sandaf3dd882012-09-24 09:24:45 -0700904 ALOGV("unwind_backtrace_signal_arch: "
905 "ignore_depth=%d max_depth=%d pc=0x%08x sp=0x%08x ra=0x%08x\n",
Chris Dearman529985782013-12-06 04:29:37 -0800906 ignore_depth, max_depth, state.reg[DWARF_PC], state.reg[DWARF_SP], state.reg[DWARF_RA]);
Chris Dearman231e3c82012-08-10 17:06:20 -0700907
908 memory_t memory;
909 init_memory(&memory, map_info_list);
910 return unwind_backtrace_common(&memory, map_info_list,
Chris Dearman529985782013-12-06 04:29:37 -0800911 &state, backtrace, ignore_depth, max_depth);
Chris Dearman231e3c82012-08-10 17:06:20 -0700912}
913
914ssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context,
915 backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
916
917 user_regs_struct regs;
918 if (ptrace(PTRACE_GETREGS, tid, 0, &regs)) {
919 return -1;
920 }
921
922 unwind_state_t state;
Chris Dearman529985782013-12-06 04:29:37 -0800923 state.reg[DWARF_PC] = regs.epc;
924 state.reg[DWARF_RA] = regs.regs[REG_RA];
925 state.reg[DWARF_FP] = regs.regs[REG_S8];
926 state.reg[DWARF_SP] = regs.regs[REG_SP];
Chris Dearman231e3c82012-08-10 17:06:20 -0700927
Duane Sandaf3dd882012-09-24 09:24:45 -0700928 ALOGV("unwind_backtrace_ptrace_arch: "
929 "ignore_depth=%d max_depth=%d pc=0x%08x sp=0x%08x ra=0x%08x\n",
Chris Dearman529985782013-12-06 04:29:37 -0800930 ignore_depth, max_depth, state.reg[DWARF_PC], state.reg[DWARF_SP], state.reg[DWARF_RA]);
Chris Dearman231e3c82012-08-10 17:06:20 -0700931
932 memory_t memory;
933 init_memory_ptrace(&memory, tid);
934 return unwind_backtrace_common(&memory, context->map_info_list,
Chris Dearman529985782013-12-06 04:29:37 -0800935 &state, backtrace, ignore_depth, max_depth);
Chris Dearman231e3c82012-08-10 17:06:20 -0700936}