/* * Copyright (C) 2016 Michael Brown . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * You can also choose to distribute this program under the terms of * the Unmodified Binary Distribution Licence (as given in the file * COPYING.UBDL), provided that you have satisfied its requirements. */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * * GDB exception handlers * */ /* Size of a register */ #define SIZEOF_REG 8 /* POSIX signal numbers for reporting traps to GDB */ #define SIGILL 4 #define SIGTRAP 5 #define SIGFPE 8 #define SIGSTKFLT 16 .section ".text.gdbmach_interrupt", "ax", @progbits .code64 .struct 0 /* Register dump created for GDB stub */ regs: regs_rax: .space SIZEOF_REG regs_rbx: .space SIZEOF_REG regs_rcx: .space SIZEOF_REG regs_rdx: .space SIZEOF_REG regs_rsi: .space SIZEOF_REG regs_rdi: .space SIZEOF_REG regs_rbp: .space SIZEOF_REG regs_rsp: .space SIZEOF_REG regs_r8: .space SIZEOF_REG regs_r9: .space SIZEOF_REG regs_r10: .space SIZEOF_REG regs_r11: .space SIZEOF_REG regs_r12: .space SIZEOF_REG regs_r13: .space SIZEOF_REG regs_r14: .space SIZEOF_REG regs_r15: .space SIZEOF_REG regs_rip: .space SIZEOF_REG regs_rflags: .space SIZEOF_REG regs_cs: .space SIZEOF_REG regs_ss: .space SIZEOF_REG regs_ds: .space SIZEOF_REG regs_es: .space SIZEOF_REG regs_fs: .space SIZEOF_REG regs_gs: .space SIZEOF_REG regs_end: /* GDB signal code */ gdb: gdb_code: .space SIZEOF_REG gdb_end: /* Long-mode exception frame */ frame: frame_rip: .space SIZEOF_REG frame_cs: .space SIZEOF_REG frame_rflags: .space SIZEOF_REG frame_rsp: .space SIZEOF_REG frame_ss: .space SIZEOF_REG frame_end: .previous .globl gdbmach_sigfpe gdbmach_sigfpe: push $SIGFPE jmp gdbmach_interrupt .globl gdbmach_sigtrap gdbmach_sigtrap: push $SIGTRAP jmp gdbmach_interrupt .globl gdbmach_sigstkflt gdbmach_sigstkflt: push $SIGSTKFLT jmp gdbmach_interrupt .globl gdbmach_sigill gdbmach_sigill: push $SIGILL jmp gdbmach_interrupt gdbmach_interrupt: /* Create register dump */ pushq %gs pushq %fs pushq $0 /* %es unused in long mode */ pushq $0 /* %ds unused in long mode */ pushq ( frame_ss - regs_ss - SIZEOF_REG )(%rsp) pushq ( frame_cs - regs_cs - SIZEOF_REG )(%rsp) pushq ( frame_rflags - regs_rflags - SIZEOF_REG )(%rsp) pushq ( frame_rip - regs_rip - SIZEOF_REG )(%rsp) pushq %r15 pushq %r14 pushq %r13 pushq %r12 pushq %r11 pushq %r10 pushq %r9 pushq %r8 pushq ( frame_rsp - regs_rsp - SIZEOF_REG )(%rsp) pushq %rbp pushq %rdi pushq %rsi pushq %rdx pushq %rcx pushq %rbx pushq %rax /* Call GDB stub exception handler */ movq gdb_code(%rsp), %rdi movq %rsp, %rsi call gdbmach_handler /* Restore from register dump */ popq %rax popq %rbx popq %rcx popq %rdx popq %rsi popq %rdi popq %rbp popq ( frame_rsp - regs_rsp - SIZEOF_REG )(%rsp) popq %r8 popq %r9 popq %r10 popq %r11 popq %r12 popq %r13 popq %r14 popq %r15 popq ( frame_rip - regs_rip - SIZEOF_REG )(%rsp) popq ( frame_rflags - regs_rflags - SIZEOF_REG )(%rsp) popq ( frame_cs - regs_cs - SIZEOF_REG )(%rsp) popq ( frame_ss - regs_ss - SIZEOF_REG )(%rsp) addq $( regs_fs - regs_ds ), %rsp /* skip %ds, %es */ popq %fs popq %gs /* Skip code */ addq $( gdb_end - gdb_code ), %rsp /* skip code */ /* Return */ iretq