backtrace-x86.c revision 5f83cf0bcf96fc58ca7314571ae264353cdee321
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 <cutils/log.h> 3510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 366b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#if defined(__BIONIC__) 376b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes 385f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru#if defined(__BIONIC_HAVE_UCONTEXT_T) 395f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru 406b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes// Bionic offers the Linux kernel headers. 416b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#include <asm/sigcontext.h> 426b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#include <asm/ucontext.h> 436b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughestypedef struct ucontext ucontext_t; 446b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes 455f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru#else /* __BIONIC_HAVE_UCONTEXT_T */ 465f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru 47b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner/* Old versions of the Android <signal.h> didn't define ucontext_t. */ 48b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner 49b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turnertypedef struct { 50b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner uint32_t gregs[32]; 51b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner void* fpregs; 52b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner uint32_t oldmask; 53b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner uint32_t cr2; 54b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner} mcontext_t; 55b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner 56b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turnerenum { 57b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner REG_GS = 0, REG_FS, REG_ES, REG_DS, 58b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner REG_EDI, REG_ESI, REG_EBP, REG_ESP, 59b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner REG_EBX, REG_EDX, REG_ECX, REG_EAX, 60b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner REG_TRAPNO, REG_ERR, REG_EIP, REG_CS, 61b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner REG_EFL, REG_UESP, REG_SS 62b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner}; 63b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner 6410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* Machine context at the time a signal was raised. */ 6510484a068412613aaf3924f63a0b2f61400c7d1eJeff Browntypedef struct ucontext { 6610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t uc_flags; 6710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown struct ucontext* uc_link; 6810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown stack_t uc_stack; 69b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner mcontext_t uc_mcontext; 7010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t uc_sigmask; 7110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} ucontext_t; 725f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru 735f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru#endif /* __BIONIC_HAVE_UCONTEXT_T */ 745f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru 755f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru#else /* __BIONIC__ */ 766b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes 776b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes// glibc has its own renaming of the Linux kernel's structures. 7871363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#define __USE_GNU // For REG_EBP, REG_ESP, and REG_EIP. 7971363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#include <ucontext.h> 8010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 815f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru#endif /* __ BIONIC__ */ 826b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes 8310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* Unwind state. */ 8410484a068412613aaf3924f63a0b2f61400c7d1eJeff Browntypedef struct { 8510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t ebp; 8610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t eip; 8710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t esp; 8810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} unwind_state_t; 8910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 9046beebea823878218fc0f14723829d83886af978Edwin Vaneuintptr_t rewind_pc_arch(const memory_t* memory __attribute__((unused)), uintptr_t pc) { 91f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown // TODO: Implement for x86. 92f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown return pc; 93f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown} 94f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown 95f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brownstatic ssize_t unwind_backtrace_common(const memory_t* memory, 9646beebea823878218fc0f14723829d83886af978Edwin Vane const map_info_t* map_info_list __attribute__((unused)), 9710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown unwind_state_t* state, backtrace_frame_t* backtrace, 9810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown size_t ignore_depth, size_t max_depth) { 9910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown size_t ignored_frames = 0; 10010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown size_t returned_frames = 0; 10110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 102f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown for (size_t index = 0; state->ebp && returned_frames < max_depth; index++) { 103f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown backtrace_frame_t* frame = add_backtrace_entry( 104f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown index ? rewind_pc_arch(memory, state->eip) : state->eip, 10510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown backtrace, ignore_depth, max_depth, 10610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown &ignored_frames, &returned_frames); 10710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t next_esp = state->ebp + 8; 10810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown if (frame) { 10910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown frame->stack_top = state->esp; 11010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown if (state->esp < next_esp) { 11110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown frame->stack_size = next_esp - state->esp; 11210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 11310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 11410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state->esp = next_esp; 115f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown if (!try_get_word(memory, state->ebp + 4, &state->eip) 116f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown || !try_get_word(memory, state->ebp, &state->ebp) 11710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown || !state->eip) { 11810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown break; 11910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 12010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 12110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 12210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown return returned_frames; 12310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} 12410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 12546beebea823878218fc0f14723829d83886af978Edwin Vanessize_t unwind_backtrace_signal_arch(siginfo_t* siginfo __attribute__((unused)), void* sigcontext, 126f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown const map_info_t* map_info_list, 12710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { 12810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown const ucontext_t* uc = (const ucontext_t*)sigcontext; 12910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 13010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown unwind_state_t state; 13171363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes state.ebp = uc->uc_mcontext.gregs[REG_EBP]; 13271363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes state.esp = uc->uc_mcontext.gregs[REG_ESP]; 13371363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes state.eip = uc->uc_mcontext.gregs[REG_EIP]; 13410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 135f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown memory_t memory; 136f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown init_memory(&memory, map_info_list); 137f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown return unwind_backtrace_common(&memory, map_info_list, 138f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown &state, backtrace, ignore_depth, max_depth); 13910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} 14010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 14110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brownssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context, 14210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { 14310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown pt_regs_x86_t regs; 14410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown if (ptrace(PTRACE_GETREGS, tid, 0, ®s)) { 14510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown return -1; 14610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 14710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 14810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown unwind_state_t state; 14910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state.ebp = regs.ebp; 15010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state.eip = regs.eip; 15110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown state.esp = regs.esp; 15210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 153f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown memory_t memory; 154f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown init_memory_ptrace(&memory, tid); 155f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown return unwind_backtrace_common(&memory, context->map_info_list, 156f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown &state, backtrace, ignore_depth, max_depth); 15710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} 158