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, &regs)) {
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