blob: ef22821373689a62b6f4d3b03a45e845084d2367 [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;
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400383 if (reg >= DWARF_REGISTERS) {
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400384 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;
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400393 if (reg >= DWARF_REGISTERS) {
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400394 ALOGE("DW_CFA_restore_extended: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
395 return false;
396 }
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400397 dstate->regs[reg].rule = stack->regs[reg].rule;
398 dstate->regs[reg].value = stack->regs[reg].value;
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400399 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;
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400403 if (reg >= DWARF_REGISTERS) {
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400404 ALOGE("DW_CFA_undefined: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
405 return false;
406 }
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400407 dstate->regs[reg].rule = 'u';
408 dstate->regs[reg].value = 0;
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400409 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;
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400413 if (reg >= DWARF_REGISTERS) {
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400414 ALOGE("DW_CFA_undefined: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS);
415 return false;
416 }
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400417 dstate->regs[reg].rule = 's';
418 dstate->regs[reg].value = 0;
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400419 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;
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400425 if (reg >= DWARF_REGISTERS || offset >= DWARF_REGISTERS) {
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400426 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,
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400523 dwarf_state_t* dstate) {
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400524 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,
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400553 uintptr_t fde,
554 unwind_state_t* state) {
555 uint32_t fde_length = 0;
556 uint32_t cie_length = 0;
557 uintptr_t cie = 0;
558 uintptr_t cie_offset = 0;
559 cie_info_t cie_i;
560 cie_info_t* cie_info = &cie_i;
561 fde_info_t fde_i;
562 fde_info_t* fde_info = &fde_i;
563 dwarf_state_t dwarf_state;
564 dwarf_state_t* dstate = &dwarf_state;
565 dwarf_state_t stack[DWARF_STATES_STACK];
566 uint8_t stack_ptr = 0;
567
568 memset(dstate, 0, sizeof(dwarf_state_t));
569 memset(cie_info, 0, sizeof(cie_info_t));
570 memset(fde_info, 0, sizeof(fde_info_t));
571
572 /* Read common CIE or FDE area:
573 1st word is length;
574 2nd word is ID: 0 for CIE, CIE pointer for FDE.
575 */
576 if (!try_get_word(memory, fde, &fde_length)) {
577 return false;
578 }
579 if ((int32_t)fde_length == -1) {
580 ALOGV("execute_fde: 64-bit dwarf detected, not implemented yet");
581 return false;
582 }
583 if (!try_get_word(memory, fde + 4, &cie_offset)) {
584 return false;
585 }
586 if (cie_offset == 0) {
587 /* This is CIE. We shouldn't be here normally. */
588 cie = fde;
589 cie_length = fde_length;
590 } else {
591 /* Find CIE. */
592 /* Positive cie_offset goes backward from current field. */
593 cie = fde + 4 - cie_offset;
594 if (!try_get_word(memory, cie, &cie_length)) {
595 return false;
596 }
597 if ((int32_t)cie_length == -1) {
598 ALOGV("execute_fde: 64-bit dwarf detected, not implemented yet");
599 return false;
600 }
601 if (!try_get_word(memory, cie + 4, &cie_offset)) {
602 return false;
603 }
604 if (cie_offset != 0) {
605 ALOGV("execute_fde: can't find CIE");
606 return false;
607 }
608 }
609 ALOGV("execute_fde: FDE length: %d", fde_length);
610 ALOGV("execute_fde: CIE pointer: %x", cie);
611 ALOGV("execute_fde: CIE length: %d", cie_length);
612
613 /* Read CIE:
614 Augmentation independent:
615 1st byte is version;
616 next x bytes is /0 terminated augmentation string;
617 next x bytes is unsigned LEB128 encoded code alignment factor;
618 next x bytes is signed LEB128 encoded data alignment factor;
619 next 1 (CIE version 1) or x (CIE version 3 unsigned LEB128) bytes is return register column;
620 Augmentation dependent:
621 if 'z' next x bytes is unsigned LEB128 encoded augmentation data size;
622 if 'L' next 1 byte is LSDA encoding;
623 if 'R' next 1 byte is FDE encoding;
624 if 'S' CIE represents signal handler stack frame;
625 if 'P' next 1 byte is personality encoding folowed by personality function pointer;
626 Next x bytes is CIE program.
627 */
628
629 uint32_t c = 8;
630 if (!try_get_byte(memory, cie, &cie_info->version, &c)) {
631 return false;
632 }
633 ALOGV("execute_fde: CIE version: %d", cie_info->version);
634 uint8_t ch;
635 do {
636 if (!try_get_byte(memory, cie, &ch, &c)) {
637 return false;
638 }
639 switch (ch) {
640 case '\0': break;
641 case 'z': cie_info->aug_z = 1; break;
642 case 'L': cie_info->aug_L = 1; break;
643 case 'R': cie_info->aug_R = 1; break;
644 case 'S': cie_info->aug_S = 1; break;
645 case 'P': cie_info->aug_P = 1; break;
646 default:
647 ALOGV("execute_fde: Unrecognized CIE augmentation char: '%c'", ch);
648 return false;
649 break;
650 }
651 } while (ch);
652 if (!try_get_uleb128(memory, cie, &cie_info->code_align, &c)) {
653 return false;
654 }
655 if (!try_get_sleb128(memory, cie, &cie_info->data_align, &c)) {
656 return false;
657 }
658 if (cie_info->version >= 3) {
659 if (!try_get_uleb128(memory, cie, &cie_info->reg, &c)) {
660 return false;
661 }
662 } else {
663 if (!try_get_byte(memory, cie, (uint8_t*)&cie_info->reg, &c)) {
664 return false;
665 }
666 }
667 ALOGV("execute_fde: CIE code alignment factor: %d", cie_info->code_align);
668 ALOGV("execute_fde: CIE data alignment factor: %d", cie_info->data_align);
669 if (cie_info->aug_z) {
670 if (!try_get_uleb128(memory, cie, &cie_info->aug_z, &c)) {
671 return false;
672 }
673 }
674 if (cie_info->aug_L) {
675 if (!try_get_byte(memory, cie, &cie_info->aug_L, &c)) {
676 return false;
677 }
678 } else {
679 /* Default encoding. */
680 cie_info->aug_L = DW_EH_PE_absptr;
681 }
682 if (cie_info->aug_R) {
683 if (!try_get_byte(memory, cie, &cie_info->aug_R, &c)) {
684 return false;
685 }
686 } else {
687 /* Default encoding. */
688 cie_info->aug_R = DW_EH_PE_absptr;
689 }
690 if (cie_info->aug_P) {
691 /* Get encoding of personality routine pointer. We don't use it now. */
692 if (!try_get_byte(memory, cie, (uint8_t*)&cie_info->aug_P, &c)) {
693 return false;
694 }
695 /* Get routine pointer. */
696 if (!read_dwarf(memory, cie, &cie_info->aug_P, (uint8_t)cie_info->aug_P, &c)) {
697 return false;
698 }
699 }
700 /* CIE program. */
701 /* Length field itself (4 bytes) is not included into length. */
702 stack[0] = *dstate;
703 stack_ptr = 1;
704 while (c < cie_length + 4) {
705 if (!execute_dwarf(memory, cie, cie_info, dstate, &c, stack, &stack_ptr)) {
706 return false;
Jeff Brown10484a02011-10-21 12:07:49 -0700707 }
708 }
709
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400710 /* We went directly to CIE. Normally it shouldn't occur. */
711 if (cie == fde) return true;
712
713 /* Go back to FDE. */
714 c = 8;
715 /* Read FDE:
716 Augmentation independent:
717 next x bytes (encoded as specified in CIE) is FDE starting address;
718 next x bytes (encoded as specified in CIE) is FDE number of instructions covered;
719 Augmentation dependent:
720 if 'z' next x bytes is unsigned LEB128 encoded augmentation data size;
721 if 'L' next x bytes is LSDA pointer (encoded as specified in CIE);
722 Next x bytes is FDE program.
723 */
724 if (!read_dwarf(memory, fde, &fde_info->start, (uint8_t)cie_info->aug_R, &c)) {
725 return false;
726 }
727 dstate->loc = fde_info->start;
728 ALOGV("execute_fde: FDE start: %x", dstate->loc);
729 if (!read_dwarf(memory, fde, &fde_info->length, 0, &c)) {
730 return false;
731 }
732 ALOGV("execute_fde: FDE length: %x", fde_info->length);
733 if (cie_info->aug_z) {
734 if (!try_get_uleb128(memory, fde, &fde_info->aug_z, &c)) {
735 return false;
736 }
737 }
738 if (cie_info->aug_L && cie_info->aug_L != DW_EH_PE_omit) {
739 if (!read_dwarf(memory, fde, &fde_info->aug_L, cie_info->aug_L, &c)) {
740 return false;
741 }
742 }
743 /* FDE program. */
744 /* Length field itself (4 bytes) is not included into length. */
745 /* Save CIE state as 0 element of stack. Used by DW_CFA_restore. */
746 stack[0] = *dstate;
747 stack_ptr = 1;
748 while (c < fde_length + 4 && state->reg[DWARF_EIP] >= dstate->loc) {
749 if (!execute_dwarf(memory, fde, cie_info, dstate, &c, stack, &stack_ptr)) {
750 return false;
751 }
752 ALOGV("IP: %x, LOC: %x", state->reg[DWARF_EIP], dstate->loc);
753 }
754
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400755 return update_state(memory, state, dstate);
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400756}
757
758static ssize_t unwind_backtrace_common(const memory_t* memory,
759 const map_info_t* map_info_list,
760 unwind_state_t* state, backtrace_frame_t* backtrace,
761 size_t ignore_depth, size_t max_depth) {
762
763 size_t ignored_frames = 0;
764 size_t returned_frames = 0;
765
766 ALOGV("Unwinding tid: %d", memory->tid);
767 ALOGV("IP: %x", state->reg[DWARF_EIP]);
768 ALOGV("BP: %x", state->reg[DWARF_EBP]);
769 ALOGV("SP: %x", state->reg[DWARF_ESP]);
770
771 for (size_t index = 0; returned_frames < max_depth; index++) {
772 uintptr_t fde = find_fde(memory, map_info_list, state->reg[DWARF_EIP]);
773 /* FDE is not found, it may happen if stack is corrupted or calling wrong adress.
774 Getting return address from stack.
775 */
776 if (!fde) {
777 uint32_t ip;
778 ALOGV("trying to restore registers from stack");
779 if (!try_get_word(memory, state->reg[DWARF_EBP] + 4, &ip) ||
780 ip == state->reg[DWARF_EIP]) {
781 ALOGV("can't get IP from stack");
782 break;
783 }
784 /* We've been able to get IP from stack so recording the frame before continue. */
785 backtrace_frame_t* frame = add_backtrace_entry(
786 index ? rewind_pc_arch(memory, state->reg[DWARF_EIP]) : state->reg[DWARF_EIP],
787 backtrace, ignore_depth, max_depth,
788 &ignored_frames, &returned_frames);
789 state->reg[DWARF_EIP] = ip;
790 state->reg[DWARF_ESP] = state->reg[DWARF_EBP] + 8;
791 if (!try_get_word(memory, state->reg[DWARF_EBP], &state->reg[DWARF_EBP])) {
792 ALOGV("can't get EBP from stack");
793 break;
794 }
795 ALOGV("restore IP: %x", state->reg[DWARF_EIP]);
796 ALOGV("restore BP: %x", state->reg[DWARF_EBP]);
797 ALOGV("restore SP: %x", state->reg[DWARF_ESP]);
798 continue;
799 }
800 backtrace_frame_t* frame = add_backtrace_entry(
801 index ? rewind_pc_arch(memory, state->reg[DWARF_EIP]) : state->reg[DWARF_EIP],
802 backtrace, ignore_depth, max_depth,
803 &ignored_frames, &returned_frames);
804
805 uint32_t stack_top = state->reg[DWARF_ESP];
806
Pavel Chupin856b6cb2013-08-05 13:49:53 +0400807 if (!execute_fde(memory, fde, state)) break;
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400808
809 if (frame) {
810 frame->stack_top = stack_top;
811 if (stack_top < state->reg[DWARF_ESP]) {
812 frame->stack_size = state->reg[DWARF_ESP] - stack_top;
813 }
814 }
815 ALOGV("Stack: 0x%x ... 0x%x - %d bytes", frame->stack_top, state->reg[DWARF_ESP], frame->stack_size);
816 }
Jeff Brown10484a02011-10-21 12:07:49 -0700817 return returned_frames;
818}
819
Edwin Vane46beebe2012-07-26 14:18:23 -0400820ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo __attribute__((unused)), void* sigcontext,
Jeff Brownf0c58722011-11-03 17:58:44 -0700821 const map_info_t* map_info_list,
Jeff Brown10484a02011-10-21 12:07:49 -0700822 backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
823 const ucontext_t* uc = (const ucontext_t*)sigcontext;
824
825 unwind_state_t state;
Elliott Hughesbfec3a32012-05-24 19:03:07 -0700826#if defined(__APPLE__)
827 state.reg[DWARF_EBP] = uc->uc_mcontext->__ss.__ebp;
828 state.reg[DWARF_ESP] = uc->uc_mcontext->__ss.__esp;
829 state.reg[DWARF_EIP] = uc->uc_mcontext->__ss.__eip;
830#else
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400831 state.reg[DWARF_EBP] = uc->uc_mcontext.gregs[REG_EBP];
832 state.reg[DWARF_ESP] = uc->uc_mcontext.gregs[REG_ESP];
833 state.reg[DWARF_EIP] = uc->uc_mcontext.gregs[REG_EIP];
Elliott Hughesbfec3a32012-05-24 19:03:07 -0700834#endif
Jeff Brown10484a02011-10-21 12:07:49 -0700835
Jeff Brownf0c58722011-11-03 17:58:44 -0700836 memory_t memory;
837 init_memory(&memory, map_info_list);
838 return unwind_backtrace_common(&memory, map_info_list,
839 &state, backtrace, ignore_depth, max_depth);
Jeff Brown10484a02011-10-21 12:07:49 -0700840}
841
842ssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context,
843 backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
Elliott Hughesbfec3a32012-05-24 19:03:07 -0700844#if defined(__APPLE__)
845 return -1;
846#else
Jeff Brown10484a02011-10-21 12:07:49 -0700847 pt_regs_x86_t regs;
848 if (ptrace(PTRACE_GETREGS, tid, 0, &regs)) {
849 return -1;
850 }
851
852 unwind_state_t state;
Pavel Chupinaf2cb362013-03-08 13:17:35 +0400853 state.reg[DWARF_EBP] = regs.ebp;
854 state.reg[DWARF_EIP] = regs.eip;
855 state.reg[DWARF_ESP] = regs.esp;
Jeff Brown10484a02011-10-21 12:07:49 -0700856
Jeff Brownf0c58722011-11-03 17:58:44 -0700857 memory_t memory;
858 init_memory_ptrace(&memory, tid);
859 return unwind_backtrace_common(&memory, context->map_info_list,
860 &state, backtrace, ignore_depth, max_depth);
Elliott Hughesbfec3a32012-05-24 19:03:07 -0700861#endif
Jeff Brown10484a02011-10-21 12:07:49 -0700862}