backtrace-x86.c revision 10484a068412613aaf3924f63a0b2f61400c7d1e
110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* 210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * Copyright (C) 2011 The Android Open Source Project 310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * 410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * you may not use this file except in compliance with the License. 610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * You may obtain a copy of the License at 710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * 810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * 1010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * Unless required by applicable law or agreed to in writing, software 1110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * See the License for the specific language governing permissions and 1410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * limitations under the License. 1510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown */ 1610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 1710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* 1810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * Backtracing functions for x86. 1910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown */ 2010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 2110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#define LOG_TAG "Corkscrew" 2210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown//#define LOG_NDEBUG 0 2310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 2410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include "../backtrace-arch.h" 2510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include "../backtrace-helper.h" 2610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <corkscrew/ptrace.h> 2710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 2810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <stdlib.h> 2910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <signal.h> 3010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <stdbool.h> 3110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <limits.h> 3210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <errno.h> 3310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <sys/ptrace.h> 3410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <sys/exec_elf.h> 3510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <cutils/log.h> 3610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 3710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* Machine context at the time a signal was raised. */ 3810484a068412613aaf3924f63a0b2f61400c7d1eJeff Browntypedef struct ucontext { 3910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t uc_flags; 4010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown struct ucontext* uc_link; 4110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown stack_t uc_stack; 4210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown struct sigcontext { 4310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t gs; 4410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t fs; 4510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t es; 4610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t ds; 4710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t edi; 4810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t esi; 4910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t ebp; 5010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t esp; 5110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t ebx; 5210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t edx; 5310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t ecx; 5410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t eax; 5510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t trapno; 5610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t err; 5710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t eip; 5810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t cs; 5910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t efl; 6010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t uesp; 6110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t ss; 6210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown void* fpregs; 6310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t oldmask; 6410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t cr2; 6510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } uc_mcontext; 6610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t uc_sigmask; 6710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} ucontext_t; 6810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 6910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* Unwind state. */ 7010484a068412613aaf3924f63a0b2f61400c7d1eJeff Browntypedef struct { 7110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t ebp; 7210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t eip; 7310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t esp; 7410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} unwind_state_t; 7510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 7610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brownstatic ssize_t unwind_backtrace_common(pid_t tid, const ptrace_context_t* context, 7710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown unwind_state_t* state, backtrace_frame_t* backtrace, 7810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown size_t ignore_depth, size_t max_depth) { 7910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown size_t ignored_frames = 0; 8010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown size_t returned_frames = 0; 8110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 8210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown while (state->ebp && returned_frames < max_depth) { 8310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown backtrace_frame_t* frame = add_backtrace_entry(state->eip, 8410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown backtrace, ignore_depth, max_depth, 8510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown &ignored_frames, &returned_frames); 8610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t next_esp = state->ebp + 8; 8710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown if (frame) { 8810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown frame->stack_top = state->esp; 8910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown if (state->esp < next_esp) { 9010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown frame->stack_size = next_esp - state->esp; 9110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 9210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 9310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state->esp = next_esp; 9410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown if (!try_get_word(tid, state->ebp + 4, &state->eip) 9510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown || !try_get_word(tid, state->ebp, &state->ebp) 9610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown || !state->eip) { 9710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown break; 9810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 9910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 10010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 10110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown return returned_frames; 10210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} 10310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 10410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brownssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo, void* sigcontext, 10510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { 10610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown const ucontext_t* uc = (const ucontext_t*)sigcontext; 10710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 10810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown unwind_state_t state; 10910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state.ebp = uc->uc_mcontext.ebp; 11010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state.eip = uc->uc_mcontext.eip; 11110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state.esp = uc->uc_mcontext.esp; 11210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 11310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown return unwind_backtrace_common(-1, NULL, &state, backtrace, ignore_depth, max_depth); 11410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} 11510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 11610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brownssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context, 11710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { 11810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown pt_regs_x86_t regs; 11910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown if (ptrace(PTRACE_GETREGS, tid, 0, ®s)) { 12010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown return -1; 12110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 12210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 12310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown unwind_state_t state; 12410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state.ebp = regs.ebp; 12510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state.eip = regs.eip; 12610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state.esp = regs.esp; 12710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 12810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown return unwind_backtrace_common(tid, context, &state, backtrace, ignore_depth, max_depth); 12910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} 130