blob: e133ab6ff5d3d86988b5626b70238eb7350f0c82 [file] [log] [blame]
Jeff Brown10484a02011-10-21 12:07:49 -07001/*
2 * Copyright (C) 2011 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 x86.
19 */
20
21#define LOG_TAG "Corkscrew"
22//#define LOG_NDEBUG 0
23
24#include "../backtrace-arch.h"
25#include "../backtrace-helper.h"
Pavel Chupinaf2cb362013-03-08 13:17:35 +040026#include "../ptrace-arch.h"
Jeff Brown10484a02011-10-21 12:07:49 -070027#include <corkscrew/ptrace.h>
Pavel Chupinaf2cb362013-03-08 13:17:35 +040028#include "dwarf.h"
Jeff Brown10484a02011-10-21 12:07:49 -070029
30#include <stdlib.h>
31#include <signal.h>
32#include <stdbool.h>
33#include <limits.h>
34#include <errno.h>
Pavel Chupinaf2cb362013-03-08 13:17:35 +040035#include <string.h>
Jeff Brown10484a02011-10-21 12:07:49 -070036#include <sys/ptrace.h>
Jeff Brown10484a02011-10-21 12:07:49 -070037#include <cutils/log.h>
38
Elliott Hughes6b3bab32012-05-21 13:59:52 -070039#if defined(__BIONIC__)
40
Jean-Baptiste Queru5f83cf02012-08-22 13:45:10 -070041#if defined(__BIONIC_HAVE_UCONTEXT_T)
42
Elliott Hughes6b3bab32012-05-21 13:59:52 -070043// Bionic offers the Linux kernel headers.
44#include <asm/sigcontext.h>
45#include <asm/ucontext.h>
46typedef struct ucontext ucontext_t;
47
Jean-Baptiste Queru5f83cf02012-08-22 13:45:10 -070048#else /* __BIONIC_HAVE_UCONTEXT_T */
49
David 'Digit' Turnerb4ef91b2012-07-10 15:53:04 +020050/* Old versions of the Android <signal.h> didn't define ucontext_t. */
51
52typedef struct {
53 uint32_t gregs[32];
54 void* fpregs;
55 uint32_t oldmask;
56 uint32_t cr2;
57} mcontext_t;
58
59enum {
60 REG_GS = 0, REG_FS, REG_ES, REG_DS,
61 REG_EDI, REG_ESI, REG_EBP, REG_ESP,
62 REG_EBX, REG_EDX, REG_ECX, REG_EAX,
63 REG_TRAPNO, REG_ERR, REG_EIP, REG_CS,
64 REG_EFL, REG_UESP, REG_SS
65};
66
Jeff Brown10484a02011-10-21 12:07:49 -070067/* Machine context at the time a signal was raised. */
68typedef struct ucontext {
69 uint32_t uc_flags;
70 struct ucontext* uc_link;
71 stack_t uc_stack;
David 'Digit' Turnerb4ef91b2012-07-10 15:53:04 +020072 mcontext_t uc_mcontext;
Jeff Brown10484a02011-10-21 12:07:49 -070073 uint32_t uc_sigmask;
74} ucontext_t;
Jean-Baptiste Queru5f83cf02012-08-22 13:45:10 -070075
76#endif /* __BIONIC_HAVE_UCONTEXT_T */
77
Elliott Hughesbfec3a32012-05-24 19:03:07 -070078#elif defined(__APPLE__)
79
80#define _XOPEN_SOURCE
81#include <ucontext.h>
82
83#else
Elliott Hughes6b3bab32012-05-21 13:59:52 -070084
85// glibc has its own renaming of the Linux kernel's structures.
Elliott Hughes71363a82012-05-18 11:56:17 -070086#define __USE_GNU // For REG_EBP, REG_ESP, and REG_EIP.
87#include <ucontext.h>
Jeff Brown10484a02011-10-21 12:07:49 -070088
Elliott Hughesbfec3a32012-05-24 19:03:07 -070089#endif
Elliott Hughes6b3bab32012-05-21 13:59:52 -070090
Jeff Brown10484a02011-10-21 12:07:49 -070091/* Unwind state. */
92typedef struct {
Pavel Chupinaf2cb362013-03-08 13:17:35 +040093 uint32_t reg[DWARF_REGISTERS];
Jeff Brown10484a02011-10-21 12:07:49 -070094} unwind_state_t;
95
Pavel Chupinaf2cb362013-03-08 13:17:35 +040096typedef struct {
97 backtrace_frame_t* backtrace;
98 size_t ignore_depth;
99 size_t max_depth;
100 size_t ignored_frames;
101 size_t returned_frames;
102 memory_t memory;
103} backtrace_state_t;
104
Edwin Vane46beebe2012-07-26 14:18:23 -0400105uintptr_t rewind_pc_arch(const memory_t* memory __attribute__((unused)), uintptr_t pc) {
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400106 /* TODO: x86 instructions are 1-16 bytes, to define exact size of previous instruction
107 we have to disassemble from the function entry point up to pc.
108 Returning pc-1 is probably enough for now, the only drawback is that
109 it points somewhere between the first byte of instruction we are looking for and
110 the first byte of the next instruction. */
111
112 return pc-1;
113 /* TODO: We should adjust that for the signal frames and return pc for them instead of pc-1.
114 To recognize signal frames we should read cie_info property. */
Jeff Brownf0c58722011-11-03 17:58:44 -0700115}
116
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400117/* Read byte through 4 byte cache. Usually we read byte by byte and updating cursor. */
118static bool try_get_byte(const memory_t* memory, uintptr_t ptr, uint8_t* out_value, uint32_t* cursor) {
119 static uintptr_t lastptr;
120 static uint32_t buf;
Jeff Brown10484a02011-10-21 12:07:49 -0700121
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400122 ptr += *cursor;
123
124 if (ptr < lastptr || lastptr + 3 < ptr) {
125 lastptr = (ptr >> 2) << 2;
126 if (!try_get_word(memory, lastptr, &buf)) {
127 return false;
Jeff Brown10484a02011-10-21 12:07:49 -0700128 }
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400129 }
130 *out_value = (uint8_t)((buf >> ((ptr & 3) * 8)) & 0xff);
131 ++*cursor;
132 return true;
133}
134
135/* Getting X bytes. 4 is maximum for now. */
136static bool try_get_xbytes(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint8_t bytes, uint32_t* cursor) {
137 uint32_t data = 0;
138 if (bytes > 4) {
139 ALOGE("can't read more than 4 bytes, trying to read %d", bytes);
140 return false;
141 }
142 for (int i = 0; i < bytes; i++) {
143 uint8_t buf;
144 if (!try_get_byte(memory, ptr, &buf, cursor)) {
145 return false;
146 }
147 data |= (uint32_t)buf << (i * 8);
148 }
149 *out_value = data;
150 return true;
151}
152
153/* Reads signed/unsigned LEB128 encoded data. From 1 to 4 bytes. */
154static bool try_get_leb128(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint32_t* cursor, bool sign_extend) {
155 uint8_t buf = 0;
156 uint32_t val = 0;
157 uint8_t c = 0;
158 do {
159 if (!try_get_byte(memory, ptr, &buf, cursor)) {
160 return false;
161 }
162 val |= ((uint32_t)buf & 0x7f) << (c * 7);
163 c++;
164 } while (buf & 0x80 && (c * 7) <= 32);
165 if (c * 7 > 32) {
166 ALOGE("%s: data exceeds expected 4 bytes maximum", __FUNCTION__);
167 return false;
168 }
169 if (sign_extend) {
170 if (buf & 0x40) {
171 val |= ((uint32_t)-1 << (c * 7));
172 }
173 }
174 *out_value = val;
175 return true;
176}
177
178/* Reads signed LEB128 encoded data. From 1 to 4 bytes. */
179static bool try_get_sleb128(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint32_t* cursor) {
180 return try_get_leb128(memory, ptr, out_value, cursor, true);
181}
182
183/* Reads unsigned LEB128 encoded data. From 1 to 4 bytes. */
184static bool try_get_uleb128(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint32_t* cursor) {
185 return try_get_leb128(memory, ptr, out_value, cursor, false);
186}
187
188/* Getting data encoded by dwarf encodings. */
189static bool read_dwarf(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint8_t encoding, uint32_t* cursor) {
190 uint32_t data = 0;
191 bool issigned = true;
192 uintptr_t addr = ptr + *cursor;
193 /* Lower 4 bits is data type/size */
194 /* TODO: add more encodings if it becomes necessary */
195 switch (encoding & 0xf) {
196 case DW_EH_PE_absptr:
197 if (!try_get_xbytes(memory, ptr, &data, 4, cursor)) {
198 return false;
199 }
200 *out_value = data;
201 return true;
202 case DW_EH_PE_udata4:
203 issigned = false;
204 case DW_EH_PE_sdata4:
205 if (!try_get_xbytes(memory, ptr, &data, 4, cursor)) {
206 return false;
207 }
Jeff Brown10484a02011-10-21 12:07:49 -0700208 break;
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400209 default:
210 ALOGE("unrecognized dwarf lower part encoding: 0x%x", encoding);
211 return false;
212 }
213 /* Higher 4 bits is modifier */
214 /* TODO: add more encodings if it becomes necessary */
215 switch (encoding & 0xf0) {
216 case 0:
217 *out_value = data;
218 break;
219 case DW_EH_PE_pcrel:
220 if (issigned) {
221 *out_value = addr + (int32_t)data;
222 } else {
223 *out_value = addr + data;
224 }
225 break;
226 /* Assuming ptr is correct base to calculate datarel */
227 case DW_EH_PE_datarel:
228 if (issigned) {
229 *out_value = ptr + (int32_t)data;
230 } else {
231 *out_value = ptr + data;
232 }
233 break;
234 default:
235 ALOGE("unrecognized dwarf higher part encoding: 0x%x", encoding);
236 return false;
237 }
238 return true;
239}
240
241/* Having PC find corresponding FDE by reading .eh_frame_hdr section data. */
242static uintptr_t find_fde(const memory_t* memory,
243 const map_info_t* map_info_list, uintptr_t pc) {
244 if (!pc) {
245 ALOGV("find_fde: pc is zero, no eh_frame");
246 return 0;
247 }
248 const map_info_t* mi = find_map_info(map_info_list, pc);
249 if (!mi) {
250 ALOGV("find_fde: no map info for pc:0x%x", pc);
251 return 0;
252 }
253 const map_info_data_t* midata = mi->data;
254 if (!midata) {
255 ALOGV("find_fde: no eh_frame_hdr for map: start=0x%x, end=0x%x", mi->start, mi->end);
256 return 0;
257 }
258
259 eh_frame_hdr_info_t eh_hdr_info;
260 memset(&eh_hdr_info, 0, sizeof(eh_frame_hdr_info_t));
261
262 /* Getting the first word of eh_frame_hdr:
263 1st byte is version;
264 2nd byte is encoding of pointer to eh_frames;
265 3rd byte is encoding of count of FDEs in lookup table;
266 4th byte is encoding of lookup table entries.
267 */
268 uintptr_t eh_frame_hdr = midata->eh_frame_hdr;
269 uint32_t c = 0;
270 if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.version, &c)) return 0;
271 if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.eh_frame_ptr_enc, &c)) return 0;
272 if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.fde_count_enc, &c)) return 0;
273 if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.fde_table_enc, &c)) return 0;
274
275 /* TODO: 3rd byte can be DW_EH_PE_omit, that means no lookup table available and we should
276 try to parse eh_frame instead. Not sure how often it may occur, skipping now.
277 */
278 if (eh_hdr_info.version != 1) {
279 ALOGV("find_fde: eh_frame_hdr version %d is not supported", eh_hdr_info.version);
280 return 0;
281 }
282 /* Getting the data:
283 2nd word is eh_frame pointer (normally not used, because lookup table has all we need);
284 3rd word is count of FDEs in the lookup table;
285 starting from 4 word there is FDE lookup table (pairs of PC and FDE pointer) sorted by PC;
286 */
287 if (!read_dwarf(memory, eh_frame_hdr, &eh_hdr_info.eh_frame_ptr, eh_hdr_info.eh_frame_ptr_enc, &c)) return 0;
288 if (!read_dwarf(memory, eh_frame_hdr, &eh_hdr_info.fde_count, eh_hdr_info.fde_count_enc, &c)) return 0;
289 ALOGV("find_fde: found %d FDEs", eh_hdr_info.fde_count);
290
291 int32_t low = 0;
292 int32_t high = eh_hdr_info.fde_count;
293 uintptr_t start = 0;
294 uintptr_t fde = 0;
295 /* eh_frame_hdr + c points to lookup table at this point. */
296 while (low <= high) {
297 uint32_t mid = (high + low)/2;
298 uint32_t entry = c + mid * 8;
299 if (!read_dwarf(memory, eh_frame_hdr, &start, eh_hdr_info.fde_table_enc, &entry)) return 0;
300 if (pc <= start) {
301 high = mid - 1;
302 } else {
303 low = mid + 1;
304 }
305 }
306 /* Value found is at high. */
307 if (high < 0) {
308 ALOGV("find_fde: pc %x is out of FDE bounds: %x", pc, start);
309 return 0;
310 }
311 c += high * 8;
312 if (!read_dwarf(memory, eh_frame_hdr, &start, eh_hdr_info.fde_table_enc, &c)) return 0;
313 if (!read_dwarf(memory, eh_frame_hdr, &fde, eh_hdr_info.fde_table_enc, &c)) return 0;
314 ALOGV("pc 0x%x, ENTRY %d: start=0x%x, fde=0x%x", pc, high, start, fde);
315 return fde;
316}
317
318/* Execute single dwarf instruction and update dwarf state accordingly. */
319static bool execute_dwarf(const memory_t* memory, uintptr_t ptr, cie_info_t* cie_info,
320 dwarf_state_t* dstate, uint32_t* cursor,
321 dwarf_state_t* stack, uint8_t* stack_ptr) {
322 uint8_t inst;
323 uint8_t op = 0;
324
325 if (!try_get_byte(memory, ptr, &inst, cursor)) {
326 return false;
327 }
328 ALOGV("DW_CFA inst: 0x%x", inst);
329
330 /* For some instructions upper 2 bits is opcode and lower 6 bits is operand. See dwarf-2.0 7.23. */
331 if (inst & 0xc0) {
332 op = inst & 0x3f;
333 inst &= 0xc0;
334 }
335
336 switch ((dwarf_CFA)inst) {
337 uint32_t reg = 0;
338 uint32_t offset = 0;
339 case DW_CFA_advance_loc:
340 dstate->loc += op * cie_info->code_align;
341 ALOGV("DW_CFA_advance_loc: %d to 0x%x", op, dstate->loc);
342 break;
343 case DW_CFA_offset:
344 if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false;
345 dstate->regs[op].rule = 'o';
346 dstate->regs[op].value = offset * cie_info->data_align;
347 ALOGV("DW_CFA_offset: r%d = o(%d)", op, dstate->regs[op].value);
348 break;
349 case DW_CFA_restore:
350 dstate->regs[op].rule = stack->regs[op].rule;
351 dstate->regs[op].value = stack->regs[op].value;
352 ALOGV("DW_CFA_restore: r%d = %c(%d)", op, dstate->regs[op].rule, dstate->regs[op].value);
353 break;
354 case DW_CFA_nop:
355 break;
356 case DW_CFA_set_loc: // probably we don't have it on x86.
357 if (!try_get_xbytes(memory, ptr, &offset, 4, cursor)) return false;
358 if (offset < dstate->loc) {
359 ALOGE("DW_CFA_set_loc: attempt to move location backward");
360 return false;
361 }
362 dstate->loc = offset * cie_info->code_align;
363 ALOGV("DW_CFA_set_loc: %d to 0x%x", offset * cie_info->code_align, dstate->loc);
364 break;
365 case DW_CFA_advance_loc1:
366 if (!try_get_byte(memory, ptr, (uint8_t*)&offset, cursor)) return false;
367 dstate->loc += (uint8_t)offset * cie_info->code_align;
368 ALOGV("DW_CFA_advance_loc1: %d to 0x%x", (uint8_t)offset * cie_info->code_align, dstate->loc);
369 break;
370 case DW_CFA_advance_loc2:
371 if (!try_get_xbytes(memory, ptr, &offset, 2, cursor)) return false;
372 dstate->loc += (uint16_t)offset * cie_info->code_align;
373 ALOGV("DW_CFA_advance_loc2: %d to 0x%x", (uint16_t)offset * cie_info->code_align, dstate->loc);
374 break;
375 case DW_CFA_advance_loc4:
376 if (!try_get_xbytes(memory, ptr, &offset, 4, cursor)) return false;
377 dstate->loc += offset * cie_info->code_align;
378 ALOGV("DW_CFA_advance_loc4: %d to 0x%x", offset * cie_info->code_align, dstate->loc);
379 break;
380 case DW_CFA_offset_extended: // probably we don't have it on x86.
381 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
382 if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false;
383 if (reg > DWARF_REGISTERS) {
384 ALOGE("DW_CFA_offset_extended: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
385 return false;
386 }
387 dstate->regs[reg].rule = 'o';
388 dstate->regs[reg].value = offset * cie_info->data_align;
389 ALOGV("DW_CFA_offset_extended: r%d = o(%d)", reg, dstate->regs[reg].value);
390 break;
391 case DW_CFA_restore_extended: // probably we don't have it on x86.
392 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
393 dstate->regs[reg].rule = stack->regs[reg].rule;
394 dstate->regs[reg].value = stack->regs[reg].value;
395 if (reg > DWARF_REGISTERS) {
396 ALOGE("DW_CFA_restore_extended: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
397 return false;
398 }
399 ALOGV("DW_CFA_restore: r%d = %c(%d)", reg, dstate->regs[reg].rule, dstate->regs[reg].value);
400 break;
401 case DW_CFA_undefined: // probably we don't have it on x86.
402 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
403 dstate->regs[reg].rule = 'u';
404 dstate->regs[reg].value = 0;
405 if (reg > DWARF_REGISTERS) {
406 ALOGE("DW_CFA_undefined: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
407 return false;
408 }
409 ALOGV("DW_CFA_undefined: r%d", reg);
410 break;
411 case DW_CFA_same_value: // probably we don't have it on x86.
412 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
413 dstate->regs[reg].rule = 's';
414 dstate->regs[reg].value = 0;
415 if (reg > DWARF_REGISTERS) {
416 ALOGE("DW_CFA_undefined: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
417 return false;
418 }
419 ALOGV("DW_CFA_same_value: r%d", reg);
420 break;
421 case DW_CFA_register: // probably we don't have it on x86.
422 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
423 /* that's new register actually, not offset */
424 if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false;
425 if (reg > DWARF_REGISTERS || offset > DWARF_REGISTERS) {
426 ALOGE("DW_CFA_register: r%d or r%d exceeds supported number of registers (%d)", reg, offset, DWARF_REGISTERS);
427 return false;
428 }
429 dstate->regs[reg].rule = 'r';
430 dstate->regs[reg].value = offset;
431 ALOGV("DW_CFA_register: r%d = r(%d)", reg, dstate->regs[reg].value);
432 break;
433 case DW_CFA_remember_state:
434 if (*stack_ptr == DWARF_STATES_STACK) {
435 ALOGE("DW_CFA_remember_state: states stack overflow %d", *stack_ptr);
436 return false;
437 }
438 stack[(*stack_ptr)++] = *dstate;
439 ALOGV("DW_CFA_remember_state: stacktop moves to %d", *stack_ptr);
440 break;
441 case DW_CFA_restore_state:
442 /* We have CIE state saved at 0 position. It's not supposed to be taken
443 by DW_CFA_restore_state. */
444 if (*stack_ptr == 1) {
445 ALOGE("DW_CFA_restore_state: states stack is empty");
446 return false;
447 }
448 /* Don't touch location on restore. */
449 uintptr_t saveloc = dstate->loc;
450 *dstate = stack[--*stack_ptr];
451 dstate->loc = saveloc;
452 ALOGV("DW_CFA_restore_state: stacktop moves to %d", *stack_ptr);
453 break;
454 case DW_CFA_def_cfa:
455 if (!try_get_uleb128(memory, ptr, &reg, cursor)) return false;
456 if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false;
457 dstate->cfa_reg = reg;
458 dstate->cfa_off = offset;
459 ALOGV("DW_CFA_def_cfa: %x(r%d)", offset, reg);
460 break;
461 case DW_CFA_def_cfa_register:
462 if (!try_get_uleb128(memory, ptr, &reg, cursor)) {
463 return false;
464 }
465 dstate->cfa_reg = reg;
466 ALOGV("DW_CFA_def_cfa_register: r%d", reg);
467 break;
468 case DW_CFA_def_cfa_offset:
469 if (!try_get_uleb128(memory, ptr, &offset, cursor)) {
470 return false;
471 }
472 dstate->cfa_off = offset;
473 ALOGV("DW_CFA_def_cfa_offset: %x", offset);
474 break;
475 default:
476 ALOGE("unrecognized DW_CFA_* instruction: 0x%x", inst);
477 return false;
478 }
479 return true;
480}
481
482/* Restoring particular register value based on dwarf state. */
483static bool get_old_register_value(const memory_t* memory, uint32_t cfa,
484 dwarf_state_t* dstate, uint8_t reg,
485 unwind_state_t* state, unwind_state_t* newstate) {
486 uint32_t addr;
487 switch (dstate->regs[reg].rule) {
488 case 0:
489 /* We don't have dstate updated for this register, so assuming value kept the same.
490 Normally we should look into state and return current value as the old one
491 but we don't have all registers in state to handle this properly */
492 ALOGV("get_old_register_value: value of r%d is the same", reg);
493 // for ESP if it's not updated by dwarf rule we assume it's equal to CFA
494 if (reg == DWARF_ESP) {
495 ALOGV("get_old_register_value: adjusting esp to CFA: 0x%x", cfa);
496 newstate->reg[reg] = cfa;
497 } else {
498 newstate->reg[reg] = state->reg[reg];
499 }
500 break;
501 case 'o':
502 addr = cfa + (int32_t)dstate->regs[reg].value;
503 if (!try_get_word(memory, addr, &newstate->reg[reg])) {
504 ALOGE("get_old_register_value: can't read from 0x%x", addr);
505 return false;
506 }
507 ALOGV("get_old_register_value: r%d at 0x%x is 0x%x", reg, addr, newstate->reg[reg]);
508 break;
509 case 'r':
510 /* We don't have all registers in state so don't even try to look at 'r' */
511 ALOGE("get_old_register_value: register lookup not implemented yet");
512 break;
513 default:
514 ALOGE("get_old_register_value: unexpected rule:%c value:%d for register %d",
515 dstate->regs[reg].rule, (int32_t)dstate->regs[reg].value, reg);
516 return false;
517 }
518 return true;
519}
520
521/* Updaing state based on dwarf state. */
522static bool update_state(const memory_t* memory, unwind_state_t* state,
523 dwarf_state_t* dstate, cie_info_t* cie_info) {
524 unwind_state_t newstate;
525 /* We can restore more registers here if we need them. Meanwile doing minimal work here. */
526 /* Getting CFA. */
527 uintptr_t cfa = 0;
528 if (dstate->cfa_reg == DWARF_ESP) {
529 cfa = state->reg[DWARF_ESP] + dstate->cfa_off;
530 } else if (dstate->cfa_reg == DWARF_EBP) {
531 cfa = state->reg[DWARF_EBP] + dstate->cfa_off;
532 } else {
533 ALOGE("update_state: unexpected CFA register: %d", dstate->cfa_reg);
534 return false;
535 }
536 ALOGV("update_state: new CFA: 0x%x", cfa);
537 /* Getting EIP. */
538 if (!get_old_register_value(memory, cfa, dstate, DWARF_EIP, state, &newstate)) return false;
539 /* Getting EBP. */
540 if (!get_old_register_value(memory, cfa, dstate, DWARF_EBP, state, &newstate)) return false;
541 /* Getting ESP. */
542 if (!get_old_register_value(memory, cfa, dstate, DWARF_ESP, state, &newstate)) return false;
543
544 ALOGV("update_state: IP: 0x%x; restore IP: 0x%x", state->reg[DWARF_EIP], newstate.reg[DWARF_EIP]);
545 ALOGV("update_state: EBP: 0x%x; restore EBP: 0x%x", state->reg[DWARF_EBP], newstate.reg[DWARF_EBP]);
546 ALOGV("update_state: ESP: 0x%x; restore ESP: 0x%x", state->reg[DWARF_ESP], newstate.reg[DWARF_ESP]);
547 *state = newstate;
548 return true;
549}
550
551/* Execute CIE and FDE instructions for FDE found with find_fde. */
552static bool execute_fde(const memory_t* memory,
553 const map_info_t* map_info_list,
554 uintptr_t fde,
555 unwind_state_t* state) {
556 uint32_t fde_length = 0;
557 uint32_t cie_length = 0;
558 uintptr_t cie = 0;
559 uintptr_t cie_offset = 0;
560 cie_info_t cie_i;
561 cie_info_t* cie_info = &cie_i;
562 fde_info_t fde_i;
563 fde_info_t* fde_info = &fde_i;
564 dwarf_state_t dwarf_state;
565 dwarf_state_t* dstate = &dwarf_state;
566 dwarf_state_t stack[DWARF_STATES_STACK];
567 uint8_t stack_ptr = 0;
568
569 memset(dstate, 0, sizeof(dwarf_state_t));
570 memset(cie_info, 0, sizeof(cie_info_t));
571 memset(fde_info, 0, sizeof(fde_info_t));
572
573 /* Read common CIE or FDE area:
574 1st word is length;
575 2nd word is ID: 0 for CIE, CIE pointer for FDE.
576 */
577 if (!try_get_word(memory, fde, &fde_length)) {
578 return false;
579 }
580 if ((int32_t)fde_length == -1) {
581 ALOGV("execute_fde: 64-bit dwarf detected, not implemented yet");
582 return false;
583 }
584 if (!try_get_word(memory, fde + 4, &cie_offset)) {
585 return false;
586 }
587 if (cie_offset == 0) {
588 /* This is CIE. We shouldn't be here normally. */
589 cie = fde;
590 cie_length = fde_length;
591 } else {
592 /* Find CIE. */
593 /* Positive cie_offset goes backward from current field. */
594 cie = fde + 4 - cie_offset;
595 if (!try_get_word(memory, cie, &cie_length)) {
596 return false;
597 }
598 if ((int32_t)cie_length == -1) {
599 ALOGV("execute_fde: 64-bit dwarf detected, not implemented yet");
600 return false;
601 }
602 if (!try_get_word(memory, cie + 4, &cie_offset)) {
603 return false;
604 }
605 if (cie_offset != 0) {
606 ALOGV("execute_fde: can't find CIE");
607 return false;
608 }
609 }
610 ALOGV("execute_fde: FDE length: %d", fde_length);
611 ALOGV("execute_fde: CIE pointer: %x", cie);
612 ALOGV("execute_fde: CIE length: %d", cie_length);
613
614 /* Read CIE:
615 Augmentation independent:
616 1st byte is version;
617 next x bytes is /0 terminated augmentation string;
618 next x bytes is unsigned LEB128 encoded code alignment factor;
619 next x bytes is signed LEB128 encoded data alignment factor;
620 next 1 (CIE version 1) or x (CIE version 3 unsigned LEB128) bytes is return register column;
621 Augmentation dependent:
622 if 'z' next x bytes is unsigned LEB128 encoded augmentation data size;
623 if 'L' next 1 byte is LSDA encoding;
624 if 'R' next 1 byte is FDE encoding;
625 if 'S' CIE represents signal handler stack frame;
626 if 'P' next 1 byte is personality encoding folowed by personality function pointer;
627 Next x bytes is CIE program.
628 */
629
630 uint32_t c = 8;
631 if (!try_get_byte(memory, cie, &cie_info->version, &c)) {
632 return false;
633 }
634 ALOGV("execute_fde: CIE version: %d", cie_info->version);
635 uint8_t ch;
636 do {
637 if (!try_get_byte(memory, cie, &ch, &c)) {
638 return false;
639 }
640 switch (ch) {
641 case '\0': break;
642 case 'z': cie_info->aug_z = 1; break;
643 case 'L': cie_info->aug_L = 1; break;
644 case 'R': cie_info->aug_R = 1; break;
645 case 'S': cie_info->aug_S = 1; break;
646 case 'P': cie_info->aug_P = 1; break;
647 default:
648 ALOGV("execute_fde: Unrecognized CIE augmentation char: '%c'", ch);
649 return false;
650 break;
651 }
652 } while (ch);
653 if (!try_get_uleb128(memory, cie, &cie_info->code_align, &c)) {
654 return false;
655 }
656 if (!try_get_sleb128(memory, cie, &cie_info->data_align, &c)) {
657 return false;
658 }
659 if (cie_info->version >= 3) {
660 if (!try_get_uleb128(memory, cie, &cie_info->reg, &c)) {
661 return false;
662 }
663 } else {
664 if (!try_get_byte(memory, cie, (uint8_t*)&cie_info->reg, &c)) {
665 return false;
666 }
667 }
668 ALOGV("execute_fde: CIE code alignment factor: %d", cie_info->code_align);
669 ALOGV("execute_fde: CIE data alignment factor: %d", cie_info->data_align);
670 if (cie_info->aug_z) {
671 if (!try_get_uleb128(memory, cie, &cie_info->aug_z, &c)) {
672 return false;
673 }
674 }
675 if (cie_info->aug_L) {
676 if (!try_get_byte(memory, cie, &cie_info->aug_L, &c)) {
677 return false;
678 }
679 } else {
680 /* Default encoding. */
681 cie_info->aug_L = DW_EH_PE_absptr;
682 }
683 if (cie_info->aug_R) {
684 if (!try_get_byte(memory, cie, &cie_info->aug_R, &c)) {
685 return false;
686 }
687 } else {
688 /* Default encoding. */
689 cie_info->aug_R = DW_EH_PE_absptr;
690 }
691 if (cie_info->aug_P) {
692 /* Get encoding of personality routine pointer. We don't use it now. */
693 if (!try_get_byte(memory, cie, (uint8_t*)&cie_info->aug_P, &c)) {
694 return false;
695 }
696 /* Get routine pointer. */
697 if (!read_dwarf(memory, cie, &cie_info->aug_P, (uint8_t)cie_info->aug_P, &c)) {
698 return false;
699 }
700 }
701 /* CIE program. */
702 /* Length field itself (4 bytes) is not included into length. */
703 stack[0] = *dstate;
704 stack_ptr = 1;
705 while (c < cie_length + 4) {
706 if (!execute_dwarf(memory, cie, cie_info, dstate, &c, stack, &stack_ptr)) {
707 return false;
Jeff Brown10484a02011-10-21 12:07:49 -0700708 }
709 }
710
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400711 /* We went directly to CIE. Normally it shouldn't occur. */
712 if (cie == fde) return true;
713
714 /* Go back to FDE. */
715 c = 8;
716 /* Read FDE:
717 Augmentation independent:
718 next x bytes (encoded as specified in CIE) is FDE starting address;
719 next x bytes (encoded as specified in CIE) is FDE number of instructions covered;
720 Augmentation dependent:
721 if 'z' next x bytes is unsigned LEB128 encoded augmentation data size;
722 if 'L' next x bytes is LSDA pointer (encoded as specified in CIE);
723 Next x bytes is FDE program.
724 */
725 if (!read_dwarf(memory, fde, &fde_info->start, (uint8_t)cie_info->aug_R, &c)) {
726 return false;
727 }
728 dstate->loc = fde_info->start;
729 ALOGV("execute_fde: FDE start: %x", dstate->loc);
730 if (!read_dwarf(memory, fde, &fde_info->length, 0, &c)) {
731 return false;
732 }
733 ALOGV("execute_fde: FDE length: %x", fde_info->length);
734 if (cie_info->aug_z) {
735 if (!try_get_uleb128(memory, fde, &fde_info->aug_z, &c)) {
736 return false;
737 }
738 }
739 if (cie_info->aug_L && cie_info->aug_L != DW_EH_PE_omit) {
740 if (!read_dwarf(memory, fde, &fde_info->aug_L, cie_info->aug_L, &c)) {
741 return false;
742 }
743 }
744 /* FDE program. */
745 /* Length field itself (4 bytes) is not included into length. */
746 /* Save CIE state as 0 element of stack. Used by DW_CFA_restore. */
747 stack[0] = *dstate;
748 stack_ptr = 1;
749 while (c < fde_length + 4 && state->reg[DWARF_EIP] >= dstate->loc) {
750 if (!execute_dwarf(memory, fde, cie_info, dstate, &c, stack, &stack_ptr)) {
751 return false;
752 }
753 ALOGV("IP: %x, LOC: %x", state->reg[DWARF_EIP], dstate->loc);
754 }
755
756 return update_state(memory, state, dstate, cie_info);
757}
758
759static ssize_t unwind_backtrace_common(const memory_t* memory,
760 const map_info_t* map_info_list,
761 unwind_state_t* state, backtrace_frame_t* backtrace,
762 size_t ignore_depth, size_t max_depth) {
763
764 size_t ignored_frames = 0;
765 size_t returned_frames = 0;
766
767 ALOGV("Unwinding tid: %d", memory->tid);
768 ALOGV("IP: %x", state->reg[DWARF_EIP]);
769 ALOGV("BP: %x", state->reg[DWARF_EBP]);
770 ALOGV("SP: %x", state->reg[DWARF_ESP]);
771
772 for (size_t index = 0; returned_frames < max_depth; index++) {
773 uintptr_t fde = find_fde(memory, map_info_list, state->reg[DWARF_EIP]);
774 /* FDE is not found, it may happen if stack is corrupted or calling wrong adress.
775 Getting return address from stack.
776 */
777 if (!fde) {
778 uint32_t ip;
779 ALOGV("trying to restore registers from stack");
780 if (!try_get_word(memory, state->reg[DWARF_EBP] + 4, &ip) ||
781 ip == state->reg[DWARF_EIP]) {
782 ALOGV("can't get IP from stack");
783 break;
784 }
785 /* We've been able to get IP from stack so recording the frame before continue. */
786 backtrace_frame_t* frame = add_backtrace_entry(
787 index ? rewind_pc_arch(memory, state->reg[DWARF_EIP]) : state->reg[DWARF_EIP],
788 backtrace, ignore_depth, max_depth,
789 &ignored_frames, &returned_frames);
790 state->reg[DWARF_EIP] = ip;
791 state->reg[DWARF_ESP] = state->reg[DWARF_EBP] + 8;
792 if (!try_get_word(memory, state->reg[DWARF_EBP], &state->reg[DWARF_EBP])) {
793 ALOGV("can't get EBP from stack");
794 break;
795 }
796 ALOGV("restore IP: %x", state->reg[DWARF_EIP]);
797 ALOGV("restore BP: %x", state->reg[DWARF_EBP]);
798 ALOGV("restore SP: %x", state->reg[DWARF_ESP]);
799 continue;
800 }
801 backtrace_frame_t* frame = add_backtrace_entry(
802 index ? rewind_pc_arch(memory, state->reg[DWARF_EIP]) : state->reg[DWARF_EIP],
803 backtrace, ignore_depth, max_depth,
804 &ignored_frames, &returned_frames);
805
806 uint32_t stack_top = state->reg[DWARF_ESP];
807
808 if (!execute_fde(memory, map_info_list, fde, state)) break;
809
810 if (frame) {
811 frame->stack_top = stack_top;
812 if (stack_top < state->reg[DWARF_ESP]) {
813 frame->stack_size = state->reg[DWARF_ESP] - stack_top;
814 }
815 }
816 ALOGV("Stack: 0x%x ... 0x%x - %d bytes", frame->stack_top, state->reg[DWARF_ESP], frame->stack_size);
817 }
Jeff Brown10484a02011-10-21 12:07:49 -0700818 return returned_frames;
819}
820
Edwin Vane46beebe2012-07-26 14:18:23 -0400821ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo __attribute__((unused)), void* sigcontext,
Jeff Brownf0c58722011-11-03 17:58:44 -0700822 const map_info_t* map_info_list,
Jeff Brown10484a02011-10-21 12:07:49 -0700823 backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
824 const ucontext_t* uc = (const ucontext_t*)sigcontext;
825
826 unwind_state_t state;
Elliott Hughesbfec3a32012-05-24 19:03:07 -0700827#if defined(__APPLE__)
828 state.reg[DWARF_EBP] = uc->uc_mcontext->__ss.__ebp;
829 state.reg[DWARF_ESP] = uc->uc_mcontext->__ss.__esp;
830 state.reg[DWARF_EIP] = uc->uc_mcontext->__ss.__eip;
831#else
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400832 state.reg[DWARF_EBP] = uc->uc_mcontext.gregs[REG_EBP];
833 state.reg[DWARF_ESP] = uc->uc_mcontext.gregs[REG_ESP];
834 state.reg[DWARF_EIP] = uc->uc_mcontext.gregs[REG_EIP];
Elliott Hughesbfec3a32012-05-24 19:03:07 -0700835#endif
Jeff Brown10484a02011-10-21 12:07:49 -0700836
Jeff Brownf0c58722011-11-03 17:58:44 -0700837 memory_t memory;
838 init_memory(&memory, map_info_list);
839 return unwind_backtrace_common(&memory, map_info_list,
840 &state, backtrace, ignore_depth, max_depth);
Jeff Brown10484a02011-10-21 12:07:49 -0700841}
842
843ssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context,
844 backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
Elliott Hughesbfec3a32012-05-24 19:03:07 -0700845#if defined(__APPLE__)
846 return -1;
847#else
Jeff Brown10484a02011-10-21 12:07:49 -0700848 pt_regs_x86_t regs;
849 if (ptrace(PTRACE_GETREGS, tid, 0, &regs)) {
850 return -1;
851 }
852
853 unwind_state_t state;
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400854 state.reg[DWARF_EBP] = regs.ebp;
855 state.reg[DWARF_EIP] = regs.eip;
856 state.reg[DWARF_ESP] = regs.esp;
Jeff Brown10484a02011-10-21 12:07:49 -0700857
Jeff Brownf0c58722011-11-03 17:58:44 -0700858 memory_t memory;
859 init_memory_ptrace(&memory, tid);
860 return unwind_backtrace_common(&memory, context->map_info_list,
861 &state, backtrace, ignore_depth, max_depth);
Elliott Hughesbfec3a32012-05-24 19:03:07 -0700862#endif
Jeff Brown10484a02011-10-21 12:07:49 -0700863}