backtrace-x86.c revision 10484a068412613aaf3924f63a0b2f61400c7d1e
1/* 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 37/* Machine context at the time a signal was raised. */ 38typedef struct ucontext { 39 uint32_t uc_flags; 40 struct ucontext* uc_link; 41 stack_t uc_stack; 42 struct sigcontext { 43 uint32_t gs; 44 uint32_t fs; 45 uint32_t es; 46 uint32_t ds; 47 uint32_t edi; 48 uint32_t esi; 49 uint32_t ebp; 50 uint32_t esp; 51 uint32_t ebx; 52 uint32_t edx; 53 uint32_t ecx; 54 uint32_t eax; 55 uint32_t trapno; 56 uint32_t err; 57 uint32_t eip; 58 uint32_t cs; 59 uint32_t efl; 60 uint32_t uesp; 61 uint32_t ss; 62 void* fpregs; 63 uint32_t oldmask; 64 uint32_t cr2; 65 } uc_mcontext; 66 uint32_t uc_sigmask; 67} ucontext_t; 68 69/* Unwind state. */ 70typedef struct { 71 uint32_t ebp; 72 uint32_t eip; 73 uint32_t esp; 74} unwind_state_t; 75 76static ssize_t unwind_backtrace_common(pid_t tid, const ptrace_context_t* context, 77 unwind_state_t* state, backtrace_frame_t* backtrace, 78 size_t ignore_depth, size_t max_depth) { 79 size_t ignored_frames = 0; 80 size_t returned_frames = 0; 81 82 while (state->ebp && returned_frames < max_depth) { 83 backtrace_frame_t* frame = add_backtrace_entry(state->eip, 84 backtrace, ignore_depth, max_depth, 85 &ignored_frames, &returned_frames); 86 uint32_t next_esp = state->ebp + 8; 87 if (frame) { 88 frame->stack_top = state->esp; 89 if (state->esp < next_esp) { 90 frame->stack_size = next_esp - state->esp; 91 } 92 } 93 state->esp = next_esp; 94 if (!try_get_word(tid, state->ebp + 4, &state->eip) 95 || !try_get_word(tid, state->ebp, &state->ebp) 96 || !state->eip) { 97 break; 98 } 99 } 100 101 return returned_frames; 102} 103 104ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo, void* sigcontext, 105 backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { 106 const ucontext_t* uc = (const ucontext_t*)sigcontext; 107 108 unwind_state_t state; 109 state.ebp = uc->uc_mcontext.ebp; 110 state.eip = uc->uc_mcontext.eip; 111 state.esp = uc->uc_mcontext.esp; 112 113 return unwind_backtrace_common(-1, NULL, &state, backtrace, ignore_depth, max_depth); 114} 115 116ssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context, 117 backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { 118 pt_regs_x86_t regs; 119 if (ptrace(PTRACE_GETREGS, tid, 0, ®s)) { 120 return -1; 121 } 122 123 unwind_state_t state; 124 state.ebp = regs.ebp; 125 state.eip = regs.eip; 126 state.esp = regs.esp; 127 128 return unwind_backtrace_common(tid, context, &state, backtrace, ignore_depth, max_depth); 129} 130