backtrace-x86.c revision b4ef91b97513434a13d6d84a810512315ecf4768
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
37b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner#if !defined(__BIONIC_HAVE_UCONTEXT_T)
38b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner/* Old versions of the Android <signal.h> didn't define ucontext_t. */
39b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner
40b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turnertypedef struct {
41b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner  uint32_t  gregs[32];
42b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner  void*     fpregs;
43b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner  uint32_t  oldmask;
44b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner  uint32_t  cr2;
45b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner} mcontext_t;
46b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner
47b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turnerenum {
48b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner  REG_GS = 0, REG_FS, REG_ES, REG_DS,
49b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner  REG_EDI, REG_ESI, REG_EBP, REG_ESP,
50b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner  REG_EBX, REG_EDX, REG_ECX, REG_EAX,
51b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner  REG_TRAPNO, REG_ERR, REG_EIP, REG_CS,
52b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner  REG_EFL, REG_UESP, REG_SS
53b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner};
54b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner
5510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* Machine context at the time a signal was raised. */
5610484a068412613aaf3924f63a0b2f61400c7d1eJeff Browntypedef struct ucontext {
5710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    uint32_t uc_flags;
5810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    struct ucontext* uc_link;
5910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    stack_t uc_stack;
60b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner    mcontext_t uc_mcontext;
6110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    uint32_t uc_sigmask;
6210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} ucontext_t;
63b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner#endif /* !__BIONIC_HAVE_UCONTEXT_T */
6410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
6510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* Unwind state. */
6610484a068412613aaf3924f63a0b2f61400c7d1eJeff Browntypedef struct {
6710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    uint32_t ebp;
6810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    uint32_t eip;
6910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    uint32_t esp;
7010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} unwind_state_t;
7110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
72f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brownuintptr_t rewind_pc_arch(const memory_t* memory, uintptr_t pc) {
73f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    // TODO: Implement for x86.
74f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    return pc;
75f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown}
76f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown
77f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brownstatic ssize_t unwind_backtrace_common(const memory_t* memory,
78f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        const map_info_t* map_info_list,
7910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        unwind_state_t* state, backtrace_frame_t* backtrace,
8010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        size_t ignore_depth, size_t max_depth) {
8110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    size_t ignored_frames = 0;
8210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    size_t returned_frames = 0;
8310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
84f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    for (size_t index = 0; state->ebp && returned_frames < max_depth; index++) {
85f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        backtrace_frame_t* frame = add_backtrace_entry(
86f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown                index ? rewind_pc_arch(memory, state->eip) : state->eip,
8710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                backtrace, ignore_depth, max_depth,
8810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                &ignored_frames, &returned_frames);
8910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        uint32_t next_esp = state->ebp + 8;
9010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        if (frame) {
9110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            frame->stack_top = state->esp;
9210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            if (state->esp < next_esp) {
9310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                frame->stack_size = next_esp - state->esp;
9410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            }
9510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        }
9610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        state->esp = next_esp;
97f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        if (!try_get_word(memory, state->ebp + 4, &state->eip)
98f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown                || !try_get_word(memory, state->ebp, &state->ebp)
9910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                || !state->eip) {
10010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            break;
10110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        }
10210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    }
10310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
10410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    return returned_frames;
10510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown}
10610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
10710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brownssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo, void* sigcontext,
108f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        const map_info_t* map_info_list,
10910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
11010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    const ucontext_t* uc = (const ucontext_t*)sigcontext;
11110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
11210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    unwind_state_t state;
113b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner    state.ebp = uc->uc_mcontext.gregs[REG_EBP];
114b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner    state.eip = uc->uc_mcontext.gregs[REG_EIP];
115b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner    state.esp = uc->uc_mcontext.gregs[REG_ESP];
11610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
117f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    memory_t memory;
118f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    init_memory(&memory, map_info_list);
119f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    return unwind_backtrace_common(&memory, map_info_list,
120f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown            &state, backtrace, ignore_depth, max_depth);
12110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown}
12210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
12310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brownssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context,
12410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
12510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    pt_regs_x86_t regs;
12610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    if (ptrace(PTRACE_GETREGS, tid, 0, &regs)) {
12710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        return -1;
12810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    }
12910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
13010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    unwind_state_t state;
13110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.ebp = regs.ebp;
13210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.eip = regs.eip;
13310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.esp = regs.esp;
13410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
135f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    memory_t memory;
136f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    init_memory_ptrace(&memory, tid);
137f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    return unwind_backtrace_common(&memory, context->map_info_list,
138f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown            &state, backtrace, ignore_depth, max_depth);
13910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown}
140