backtrace-x86.c revision 46beebea823878218fc0f14723829d83886af978
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
7646beebea823878218fc0f14723829d83886af978Edwin Vaneuintptr_t rewind_pc_arch(const memory_t* memory __attribute__((unused)), uintptr_t pc) {
77f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    // TODO: Implement for x86.
78f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    return pc;
79f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown}
80f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown
81f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brownstatic ssize_t unwind_backtrace_common(const memory_t* memory,
8246beebea823878218fc0f14723829d83886af978Edwin Vane        const map_info_t* map_info_list __attribute__((unused)),
8310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        unwind_state_t* state, backtrace_frame_t* backtrace,
8410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        size_t ignore_depth, size_t max_depth) {
8510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    size_t ignored_frames = 0;
8610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    size_t returned_frames = 0;
8710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
88f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    for (size_t index = 0; state->ebp && returned_frames < max_depth; index++) {
89f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        backtrace_frame_t* frame = add_backtrace_entry(
90f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown                index ? rewind_pc_arch(memory, state->eip) : state->eip,
9110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                backtrace, ignore_depth, max_depth,
9210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                &ignored_frames, &returned_frames);
9310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        uint32_t next_esp = state->ebp + 8;
9410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        if (frame) {
9510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            frame->stack_top = state->esp;
9610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            if (state->esp < next_esp) {
9710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                frame->stack_size = next_esp - state->esp;
9810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            }
9910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        }
10010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        state->esp = next_esp;
101f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        if (!try_get_word(memory, state->ebp + 4, &state->eip)
102f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown                || !try_get_word(memory, state->ebp, &state->ebp)
10310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                || !state->eip) {
10410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            break;
10510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        }
10610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    }
10710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
10810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    return returned_frames;
10910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown}
11010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
11146beebea823878218fc0f14723829d83886af978Edwin Vanessize_t unwind_backtrace_signal_arch(siginfo_t* siginfo __attribute__((unused)), void* sigcontext,
112f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        const map_info_t* map_info_list,
11310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
11410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    const ucontext_t* uc = (const ucontext_t*)sigcontext;
11510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
11610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    unwind_state_t state;
11710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.ebp = uc->uc_mcontext.ebp;
11810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.eip = uc->uc_mcontext.eip;
11910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.esp = uc->uc_mcontext.esp;
12010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
121f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    memory_t memory;
122f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    init_memory(&memory, map_info_list);
123f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    return unwind_backtrace_common(&memory, map_info_list,
124f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown            &state, backtrace, ignore_depth, max_depth);
12510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown}
12610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
12710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brownssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context,
12810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
12910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    pt_regs_x86_t regs;
13010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    if (ptrace(PTRACE_GETREGS, tid, 0, &regs)) {
13110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        return -1;
13210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    }
13310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
13410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    unwind_state_t state;
13510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.ebp = regs.ebp;
13610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.eip = regs.eip;
13710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.esp = regs.esp;
13810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
139f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    memory_t memory;
140f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    init_memory_ptrace(&memory, tid);
141f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    return unwind_backtrace_common(&memory, context->map_info_list,
142f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown            &state, backtrace, ignore_depth, max_depth);
14310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown}
144