blob: 837fd75faafed94222e962321805866326fe785b [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"
26#include <corkscrew/ptrace.h>
27
28#include <stdlib.h>
29#include <signal.h>
30#include <stdbool.h>
31#include <limits.h>
32#include <errno.h>
33#include <sys/ptrace.h>
34#include <sys/exec_elf.h>
35#include <cutils/log.h>
36
David 'Digit' Turnerb4ef91b2012-07-10 15:53:04 +020037#if !defined(__BIONIC_HAVE_UCONTEXT_T)
38/* Old versions of the Android <signal.h> didn't define ucontext_t. */
39
40typedef struct {
41 uint32_t gregs[32];
42 void* fpregs;
43 uint32_t oldmask;
44 uint32_t cr2;
45} mcontext_t;
46
47enum {
48 REG_GS = 0, REG_FS, REG_ES, REG_DS,
49 REG_EDI, REG_ESI, REG_EBP, REG_ESP,
50 REG_EBX, REG_EDX, REG_ECX, REG_EAX,
51 REG_TRAPNO, REG_ERR, REG_EIP, REG_CS,
52 REG_EFL, REG_UESP, REG_SS
53};
54
Jeff Brown10484a02011-10-21 12:07:49 -070055/* Machine context at the time a signal was raised. */
56typedef struct ucontext {
57 uint32_t uc_flags;
58 struct ucontext* uc_link;
59 stack_t uc_stack;
David 'Digit' Turnerb4ef91b2012-07-10 15:53:04 +020060 mcontext_t uc_mcontext;
Jeff Brown10484a02011-10-21 12:07:49 -070061 uint32_t uc_sigmask;
62} ucontext_t;
David 'Digit' Turnerb4ef91b2012-07-10 15:53:04 +020063#endif /* !__BIONIC_HAVE_UCONTEXT_T */
Jeff Brown10484a02011-10-21 12:07:49 -070064
65/* Unwind state. */
66typedef struct {
67 uint32_t ebp;
68 uint32_t eip;
69 uint32_t esp;
70} unwind_state_t;
71
Jeff Brownf0c58722011-11-03 17:58:44 -070072uintptr_t rewind_pc_arch(const memory_t* memory, uintptr_t pc) {
73 // TODO: Implement for x86.
74 return pc;
75}
76
77static ssize_t unwind_backtrace_common(const memory_t* memory,
78 const map_info_t* map_info_list,
Jeff Brown10484a02011-10-21 12:07:49 -070079 unwind_state_t* state, backtrace_frame_t* backtrace,
80 size_t ignore_depth, size_t max_depth) {
81 size_t ignored_frames = 0;
82 size_t returned_frames = 0;
83
Jeff Brownf0c58722011-11-03 17:58:44 -070084 for (size_t index = 0; state->ebp && returned_frames < max_depth; index++) {
85 backtrace_frame_t* frame = add_backtrace_entry(
86 index ? rewind_pc_arch(memory, state->eip) : state->eip,
Jeff Brown10484a02011-10-21 12:07:49 -070087 backtrace, ignore_depth, max_depth,
88 &ignored_frames, &returned_frames);
89 uint32_t next_esp = state->ebp + 8;
90 if (frame) {
91 frame->stack_top = state->esp;
92 if (state->esp < next_esp) {
93 frame->stack_size = next_esp - state->esp;
94 }
95 }
96 state->esp = next_esp;
Jeff Brownf0c58722011-11-03 17:58:44 -070097 if (!try_get_word(memory, state->ebp + 4, &state->eip)
98 || !try_get_word(memory, state->ebp, &state->ebp)
Jeff Brown10484a02011-10-21 12:07:49 -070099 || !state->eip) {
100 break;
101 }
102 }
103
104 return returned_frames;
105}
106
107ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo, void* sigcontext,
Jeff Brownf0c58722011-11-03 17:58:44 -0700108 const map_info_t* map_info_list,
Jeff Brown10484a02011-10-21 12:07:49 -0700109 backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
110 const ucontext_t* uc = (const ucontext_t*)sigcontext;
111
112 unwind_state_t state;
David 'Digit' Turnerb4ef91b2012-07-10 15:53:04 +0200113 state.ebp = uc->uc_mcontext.gregs[REG_EBP];
114 state.eip = uc->uc_mcontext.gregs[REG_EIP];
115 state.esp = uc->uc_mcontext.gregs[REG_ESP];
Jeff Brown10484a02011-10-21 12:07:49 -0700116
Jeff Brownf0c58722011-11-03 17:58:44 -0700117 memory_t memory;
118 init_memory(&memory, map_info_list);
119 return unwind_backtrace_common(&memory, map_info_list,
120 &state, backtrace, ignore_depth, max_depth);
Jeff Brown10484a02011-10-21 12:07:49 -0700121}
122
123ssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context,
124 backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
125 pt_regs_x86_t regs;
126 if (ptrace(PTRACE_GETREGS, tid, 0, &regs)) {
127 return -1;
128 }
129
130 unwind_state_t state;
131 state.ebp = regs.ebp;
132 state.eip = regs.eip;
133 state.esp = regs.esp;
134
Jeff Brownf0c58722011-11-03 17:58:44 -0700135 memory_t memory;
136 init_memory_ptrace(&memory, tid);
137 return unwind_backtrace_common(&memory, context->map_info_list,
138 &state, backtrace, ignore_depth, max_depth);
Jeff Brown10484a02011-10-21 12:07:49 -0700139}