backtrace-x86.c revision 6b3bab39d128947bf51deefe6a28c247cafd7bae
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
386b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes// Bionic offers the Linux kernel headers.
396b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#include <asm/sigcontext.h>
406b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#include <asm/ucontext.h>
416b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughestypedef struct ucontext ucontext_t;
426b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes
436b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#else
446b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes
456b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes// glibc has its own renaming of the Linux kernel's structures.
4671363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#define __USE_GNU // For REG_EBP, REG_ESP, and REG_EIP.
4771363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#include <ucontext.h>
4810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
496b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#endif
506b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes
5110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* Unwind state. */
5210484a068412613aaf3924f63a0b2f61400c7d1eJeff Browntypedef struct {
5310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    uint32_t ebp;
5410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    uint32_t eip;
5510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    uint32_t esp;
5610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} unwind_state_t;
5710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
58f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brownuintptr_t rewind_pc_arch(const memory_t* memory, uintptr_t pc) {
59f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    // TODO: Implement for x86.
60f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    return pc;
61f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown}
62f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown
63f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brownstatic ssize_t unwind_backtrace_common(const memory_t* memory,
64f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        const map_info_t* map_info_list,
6510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        unwind_state_t* state, backtrace_frame_t* backtrace,
6610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        size_t ignore_depth, size_t max_depth) {
6710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    size_t ignored_frames = 0;
6810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    size_t returned_frames = 0;
6910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
70f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    for (size_t index = 0; state->ebp && returned_frames < max_depth; index++) {
71f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        backtrace_frame_t* frame = add_backtrace_entry(
72f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown                index ? rewind_pc_arch(memory, state->eip) : state->eip,
7310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                backtrace, ignore_depth, max_depth,
7410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                &ignored_frames, &returned_frames);
7510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        uint32_t next_esp = state->ebp + 8;
7610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        if (frame) {
7710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            frame->stack_top = state->esp;
7810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            if (state->esp < next_esp) {
7910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                frame->stack_size = next_esp - state->esp;
8010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            }
8110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        }
8210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        state->esp = next_esp;
83f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        if (!try_get_word(memory, state->ebp + 4, &state->eip)
84f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown                || !try_get_word(memory, state->ebp, &state->ebp)
8510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown                || !state->eip) {
8610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown            break;
8710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        }
8810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    }
8910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
9010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    return returned_frames;
9110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown}
9210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
9310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brownssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo, void* sigcontext,
94f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown        const map_info_t* map_info_list,
9510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
9610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    const ucontext_t* uc = (const ucontext_t*)sigcontext;
9710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
9810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    unwind_state_t state;
996b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#if defined(__BIONIC__)
1006b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes    state.ebp = uc->uc_mcontext.ebp;
1016b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes    state.esp = uc->uc_mcontext.esp;
1026b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes    state.eip = uc->uc_mcontext.eip;
1036b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#else
10471363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes    state.ebp = uc->uc_mcontext.gregs[REG_EBP];
10571363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes    state.esp = uc->uc_mcontext.gregs[REG_ESP];
10671363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes    state.eip = uc->uc_mcontext.gregs[REG_EIP];
1076b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#endif
10810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
109f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    memory_t memory;
110f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    init_memory(&memory, map_info_list);
111f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    return unwind_backtrace_common(&memory, map_info_list,
112f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown            &state, backtrace, ignore_depth, max_depth);
11310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown}
11410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
11510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brownssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context,
11610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
11710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    pt_regs_x86_t regs;
11810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    if (ptrace(PTRACE_GETREGS, tid, 0, &regs)) {
11910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown        return -1;
12010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    }
12110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
12210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    unwind_state_t state;
12310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.ebp = regs.ebp;
12410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.eip = regs.eip;
12510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown    state.esp = regs.esp;
12610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown
127f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    memory_t memory;
128f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    init_memory_ptrace(&memory, tid);
129f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown    return unwind_backtrace_common(&memory, context->map_info_list,
130f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown            &state, backtrace, ignore_depth, max_depth);
13110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown}
132