coredump: add support for x86 and x86_64
This adds the necessary bits to enable coredump for x86 and x86_64. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
49206a86ff
commit
8fbb14ef50
14 changed files with 581 additions and 3 deletions
|
@ -40,6 +40,7 @@ config X86
|
|||
select ATOMIC_OPERATIONS_BUILTIN
|
||||
select HAS_DTS
|
||||
select ARCH_HAS_CUSTOM_SWAP_TO_MAIN if !X86_64
|
||||
select ARCH_SUPPORTS_COREDUMP
|
||||
select CPU_HAS_MMU
|
||||
help
|
||||
x86 architecture
|
||||
|
|
|
@ -357,6 +357,10 @@ static const struct z_exc_handle exceptions[] = {
|
|||
|
||||
void z_x86_page_fault_handler(z_arch_esf_t *esf)
|
||||
{
|
||||
#if !defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_COREDUMP)
|
||||
z_x86_exception_vector = IV_PAGE_FAULT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
int i;
|
||||
|
||||
|
|
|
@ -23,5 +23,7 @@ zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD ia32/irq_offload.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_X86_USERSPACE ia32/userspace.S)
|
||||
zephyr_library_sources_ifdef(CONFIG_LAZY_FPU_SHARING ia32/float.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP ia32/coredump.c)
|
||||
|
||||
# Last since we declare default exception handlers here
|
||||
zephyr_library_sources(ia32/fatal.c)
|
||||
|
|
82
arch/x86/core/ia32/coredump.c
Normal file
82
arch/x86/core/ia32/coredump.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <debug/coredump.h>
|
||||
|
||||
#define ARCH_HDR_VER 1
|
||||
|
||||
struct x86_arch_block {
|
||||
uint32_t vector;
|
||||
uint32_t code;
|
||||
|
||||
struct {
|
||||
uint32_t eax;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
uint32_t ebx;
|
||||
uint32_t esp;
|
||||
uint32_t ebp;
|
||||
uint32_t esi;
|
||||
uint32_t edi;
|
||||
uint32_t eip;
|
||||
uint32_t eflags;
|
||||
uint32_t cs;
|
||||
} r;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This might be too large for stack space if defined
|
||||
* inside function. So do it here.
|
||||
*/
|
||||
static struct x86_arch_block arch_blk;
|
||||
|
||||
void arch_coredump_info_dump(const z_arch_esf_t *esf)
|
||||
{
|
||||
struct z_coredump_arch_hdr_t hdr = {
|
||||
.id = Z_COREDUMP_ARCH_HDR_ID,
|
||||
.hdr_version = ARCH_HDR_VER,
|
||||
.num_bytes = sizeof(arch_blk),
|
||||
};
|
||||
|
||||
/* Nothing to process */
|
||||
if (esf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)memset(&arch_blk, 0, sizeof(arch_blk));
|
||||
|
||||
arch_blk.vector = z_x86_exception_vector;
|
||||
arch_blk.code = esf->errorCode;
|
||||
|
||||
/*
|
||||
* 16 registers expected by GDB.
|
||||
* Not all are in ESF but the GDB stub
|
||||
* will need to send all 16 as one packet.
|
||||
* The stub will need to send undefined
|
||||
* for registers not presented in coredump.
|
||||
*/
|
||||
arch_blk.r.eax = esf->eax;
|
||||
arch_blk.r.ebx = esf->ebx;
|
||||
arch_blk.r.ecx = esf->ecx;
|
||||
arch_blk.r.edx = esf->edx;
|
||||
arch_blk.r.esp = esf->esp;
|
||||
arch_blk.r.ebp = esf->ebp;
|
||||
arch_blk.r.esi = esf->esi;
|
||||
arch_blk.r.edi = esf->edi;
|
||||
arch_blk.r.eip = esf->eip;
|
||||
arch_blk.r.eflags = esf->eflags;
|
||||
arch_blk.r.cs = esf->cs & 0xFFFFU;
|
||||
|
||||
/* Send for output */
|
||||
z_coredump_buffer_output((uint8_t *)&hdr, sizeof(hdr));
|
||||
z_coredump_buffer_output((uint8_t *)&arch_blk, sizeof(arch_blk));
|
||||
}
|
||||
|
||||
uint16_t arch_coredump_tgt_code_get(void)
|
||||
{
|
||||
return COREDUMP_TGT_X86;
|
||||
}
|
|
@ -20,6 +20,10 @@
|
|||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(os);
|
||||
|
||||
#ifdef CONFIG_DEBUG_COREDUMP
|
||||
unsigned int z_x86_exception_vector;
|
||||
#endif
|
||||
|
||||
__weak void z_debug_fatal_hook(const z_arch_esf_t *esf) { ARG_UNUSED(esf); }
|
||||
|
||||
void z_x86_spurious_irq(const z_arch_esf_t *esf)
|
||||
|
@ -58,6 +62,10 @@ NANO_CPU_INT_REGISTER(_kernel_oops_handler, NANO_SOFT_IRQ,
|
|||
FUNC_NORETURN static void generic_exc_handle(unsigned int vector,
|
||||
const z_arch_esf_t *pEsf)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_COREDUMP
|
||||
z_x86_exception_vector = vector;
|
||||
#endif
|
||||
|
||||
z_x86_unhandled_cpu_exception(vector, pEsf);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,3 +17,5 @@ zephyr_library_sources(
|
|||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE intel64/userspace.S)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP intel64/coredump.c)
|
||||
|
|
108
arch/x86/core/intel64/coredump.c
Normal file
108
arch/x86/core/intel64/coredump.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <debug/coredump.h>
|
||||
|
||||
#define ARCH_HDR_VER 1
|
||||
|
||||
struct x86_64_arch_block {
|
||||
uint64_t vector;
|
||||
uint64_t code;
|
||||
|
||||
struct {
|
||||
uint64_t rax;
|
||||
uint64_t rcx;
|
||||
uint64_t rdx;
|
||||
uint64_t rsi;
|
||||
uint64_t rdi;
|
||||
uint64_t rsp;
|
||||
uint64_t r8;
|
||||
uint64_t r9;
|
||||
uint64_t r10;
|
||||
uint64_t r11;
|
||||
uint64_t rip;
|
||||
uint64_t eflags;
|
||||
uint64_t cs;
|
||||
uint64_t ss;
|
||||
uint64_t rbp;
|
||||
|
||||
#ifdef CONFIG_EXCEPTION_DEBUG
|
||||
uint64_t rbx;
|
||||
uint64_t r12;
|
||||
uint64_t r13;
|
||||
uint64_t r14;
|
||||
uint64_t r15;
|
||||
#endif
|
||||
} r;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Register block takes up too much stack space
|
||||
* if defined within function. So define it here.
|
||||
*/
|
||||
static struct x86_64_arch_block arch_blk;
|
||||
|
||||
void arch_coredump_info_dump(const z_arch_esf_t *esf)
|
||||
{
|
||||
struct z_coredump_arch_hdr_t hdr = {
|
||||
.id = Z_COREDUMP_ARCH_HDR_ID,
|
||||
.hdr_version = ARCH_HDR_VER,
|
||||
.num_bytes = sizeof(arch_blk),
|
||||
};
|
||||
|
||||
/* Nothing to process */
|
||||
if (esf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)memset(&arch_blk, 0, sizeof(arch_blk));
|
||||
|
||||
arch_blk.vector = esf->vector;
|
||||
arch_blk.code = esf->code;
|
||||
|
||||
/*
|
||||
* 34 registers expected by GDB.
|
||||
* Not all are in ESF but the GDB stub
|
||||
* will need to send all 34 as one packet.
|
||||
* The stub will need to send undefined
|
||||
* for registers not presented in coredump.
|
||||
*/
|
||||
arch_blk.r.rax = esf->rax;
|
||||
arch_blk.r.rcx = esf->rcx;
|
||||
arch_blk.r.rdx = esf->rdx;
|
||||
arch_blk.r.rsi = esf->rsi;
|
||||
arch_blk.r.rdi = esf->rdi;
|
||||
arch_blk.r.rsp = esf->rsp;
|
||||
arch_blk.r.rip = esf->rip;
|
||||
arch_blk.r.r8 = esf->r8;
|
||||
arch_blk.r.r9 = esf->r9;
|
||||
arch_blk.r.r10 = esf->r10;
|
||||
arch_blk.r.r11 = esf->r11;
|
||||
|
||||
arch_blk.r.eflags = esf->rflags;
|
||||
arch_blk.r.cs = esf->cs & 0xFFFFU;
|
||||
arch_blk.r.ss = esf->ss;
|
||||
|
||||
arch_blk.r.rbp = esf->rbp;
|
||||
|
||||
#ifdef CONFIG_EXCEPTION_DEBUG
|
||||
arch_blk.r.rbx = esf->rbx;
|
||||
arch_blk.r.r12 = esf->r12;
|
||||
arch_blk.r.r13 = esf->r13;
|
||||
arch_blk.r.r14 = esf->r14;
|
||||
arch_blk.r.r15 = esf->r15;
|
||||
#endif
|
||||
|
||||
/* Send for output */
|
||||
z_coredump_buffer_output((uint8_t *)&hdr, sizeof(hdr));
|
||||
z_coredump_buffer_output((uint8_t *)&arch_blk, sizeof(arch_blk));
|
||||
}
|
||||
|
||||
uint16_t arch_coredump_tgt_code_get(void)
|
||||
{
|
||||
return COREDUMP_TGT_X86_64;
|
||||
}
|
|
@ -480,13 +480,13 @@ except: /*
|
|||
pushq %rdx
|
||||
pushq %rcx
|
||||
pushq %rax
|
||||
pushq %rbp
|
||||
#ifdef CONFIG_EXCEPTION_DEBUG
|
||||
/* Callee saved regs */
|
||||
pushq %r15
|
||||
pushq %r14
|
||||
pushq %r13
|
||||
pushq %r12
|
||||
pushq %rbp
|
||||
pushq %rbx
|
||||
#endif /* CONFIG_EXCEPTION_DEBUG */
|
||||
movq %rsp, %rdi
|
||||
|
@ -498,12 +498,12 @@ except: /*
|
|||
*/
|
||||
#ifdef CONFIG_EXCEPTION_DEBUG
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
#endif /* CONFIG_EXCEPTION_DEBUG */
|
||||
popq %rbp
|
||||
popq %rax
|
||||
popq %rcx
|
||||
popq %rdx
|
||||
|
|
|
@ -343,6 +343,7 @@ typedef struct nanoEsf {
|
|||
unsigned int eflags;
|
||||
} z_arch_esf_t;
|
||||
|
||||
extern unsigned int z_x86_exception_vector;
|
||||
|
||||
struct _x86_syscall_stack_frame {
|
||||
uint32_t eip;
|
||||
|
|
|
@ -35,12 +35,12 @@ struct x86_esf {
|
|||
#ifdef CONFIG_EXCEPTION_DEBUG
|
||||
/* callee-saved */
|
||||
unsigned long rbx;
|
||||
unsigned long rbp;
|
||||
unsigned long r12;
|
||||
unsigned long r13;
|
||||
unsigned long r14;
|
||||
unsigned long r15;
|
||||
#endif /* CONFIG_EXCEPTION_DEBUG */
|
||||
unsigned long rbp;
|
||||
|
||||
/* Caller-saved regs */
|
||||
unsigned long rax;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
/* Target code */
|
||||
enum z_coredump_tgt_code {
|
||||
COREDUMP_TGT_UNKNOWN = 0,
|
||||
COREDUMP_TGT_X86,
|
||||
COREDUMP_TGT_X86_64,
|
||||
};
|
||||
|
||||
/* Coredump header */
|
||||
|
|
|
@ -4,12 +4,22 @@
|
|||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
from gdbstubs.arch.x86 import GdbStub_x86
|
||||
from gdbstubs.arch.x86_64 import GdbStub_x86_64
|
||||
|
||||
class TgtCode:
|
||||
UNKNOWN = 0
|
||||
X86 = 1
|
||||
X86_64 = 2
|
||||
|
||||
def get_gdbstub(logfile, elffile):
|
||||
stub = None
|
||||
|
||||
tgt_code = logfile.log_hdr['tgt_code']
|
||||
|
||||
if tgt_code == TgtCode.X86:
|
||||
stub = GdbStub_x86(logfile=logfile, elffile=elffile)
|
||||
elif tgt_code == TgtCode.X86_64:
|
||||
stub = GdbStub_x86_64(logfile=logfile, elffile=elffile)
|
||||
|
||||
return stub
|
||||
|
|
157
scripts/coredump/gdbstubs/arch/x86.py
Normal file
157
scripts/coredump/gdbstubs/arch/x86.py
Normal file
|
@ -0,0 +1,157 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import binascii
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from gdbstubs.gdbstub import GdbStub
|
||||
|
||||
|
||||
logger = logging.getLogger("gdbstub")
|
||||
|
||||
|
||||
class RegNum():
|
||||
# Matches the enum i386_regnum in GDB
|
||||
EAX = 0
|
||||
ECX = 1
|
||||
EDX = 2
|
||||
EBX = 3
|
||||
ESP = 4
|
||||
EBP = 5
|
||||
ESI = 6
|
||||
EDI = 7
|
||||
EIP = 8
|
||||
EFLAGS = 9
|
||||
CS = 10
|
||||
SS = 11
|
||||
DS = 12
|
||||
ES = 13
|
||||
FS = 14
|
||||
GS = 15
|
||||
|
||||
|
||||
class ExceptionVectors():
|
||||
# Matches arch/x86/include/kernel_arch_data.h
|
||||
IV_DIVIDE_ERROR = 0
|
||||
IV_DEBUG = 1
|
||||
IV_NON_MASKABLE_INTERRUPT = 2
|
||||
IV_BREAKPOINT = 3
|
||||
IV_OVERFLOW = 4
|
||||
IV_BOUND_RANGE = 5
|
||||
IV_INVALID_OPCODE = 6
|
||||
IV_DEVICE_NOT_AVAILABLE = 7
|
||||
IV_DOUBLE_FAULT = 8
|
||||
IV_COPROC_SEGMENT_OVERRUN = 9
|
||||
IV_INVALID_TSS = 10
|
||||
IV_SEGMENT_NOT_PRESENT = 11
|
||||
IV_STACK_FAULT = 12
|
||||
IV_GENERAL_PROTECTION = 13
|
||||
IV_PAGE_FAULT = 14
|
||||
IV_RESERVED = 15
|
||||
IV_X87_FPU_FP_ERROR = 16
|
||||
IV_ALIGNMENT_CHECK = 17
|
||||
IV_MACHINE_CHECK = 18
|
||||
IV_SIMD_FP = 19
|
||||
IV_VIRT_EXCEPTION = 20
|
||||
IV_SECURITY_EXCEPTION = 30
|
||||
|
||||
|
||||
class GdbStub_x86(GdbStub):
|
||||
ARCH_DATA_BLK_STRUCT = "<IIIIIIIIIIIII"
|
||||
|
||||
GDB_SIGNAL_DEFAULT = 7
|
||||
|
||||
# Mapping is from GDB's gdb/i386-stubs.c
|
||||
GDB_SIGNAL_MAPPING = {
|
||||
ExceptionVectors.IV_DIVIDE_ERROR: 8,
|
||||
ExceptionVectors.IV_DEBUG: 5,
|
||||
ExceptionVectors.IV_BREAKPOINT: 5,
|
||||
ExceptionVectors.IV_OVERFLOW: 16,
|
||||
ExceptionVectors.IV_BOUND_RANGE: 16,
|
||||
ExceptionVectors.IV_INVALID_OPCODE: 4,
|
||||
ExceptionVectors.IV_DEVICE_NOT_AVAILABLE: 8,
|
||||
ExceptionVectors.IV_DOUBLE_FAULT: 7,
|
||||
ExceptionVectors.IV_COPROC_SEGMENT_OVERRUN: 11,
|
||||
ExceptionVectors.IV_INVALID_TSS: 11,
|
||||
ExceptionVectors.IV_SEGMENT_NOT_PRESENT: 11,
|
||||
ExceptionVectors.IV_STACK_FAULT: 11,
|
||||
ExceptionVectors.IV_GENERAL_PROTECTION: 11,
|
||||
ExceptionVectors.IV_PAGE_FAULT: 11,
|
||||
ExceptionVectors.IV_X87_FPU_FP_ERROR: 7,
|
||||
}
|
||||
|
||||
GDB_G_PKT_NUM_REGS = 16
|
||||
|
||||
def __init__(self, logfile, elffile):
|
||||
super().__init__(logfile=logfile, elffile=elffile)
|
||||
self.registers = None
|
||||
self.exception_vector = None
|
||||
self.exception_code = None
|
||||
self.gdb_signal = self.GDB_SIGNAL_DEFAULT
|
||||
|
||||
self.parse_arch_data_block()
|
||||
self.compute_signal()
|
||||
|
||||
def parse_arch_data_block(self):
|
||||
arch_data_blk = self.logfile.get_arch_data()['data']
|
||||
tu = struct.unpack(self.ARCH_DATA_BLK_STRUCT, arch_data_blk)
|
||||
|
||||
self.registers = dict()
|
||||
|
||||
self.exception_vector = tu[0]
|
||||
self.exception_code = tu[1]
|
||||
|
||||
self.registers[RegNum.EAX] = tu[2]
|
||||
self.registers[RegNum.ECX] = tu[3]
|
||||
self.registers[RegNum.EDX] = tu[4]
|
||||
self.registers[RegNum.EBX] = tu[5]
|
||||
self.registers[RegNum.ESP] = tu[6]
|
||||
self.registers[RegNum.EBP] = tu[7]
|
||||
self.registers[RegNum.ESI] = tu[8]
|
||||
self.registers[RegNum.EDI] = tu[9]
|
||||
self.registers[RegNum.EIP] = tu[10]
|
||||
self.registers[RegNum.EFLAGS] = tu[11]
|
||||
self.registers[RegNum.CS] = tu[12]
|
||||
|
||||
def compute_signal(self):
|
||||
sig = self.GDB_SIGNAL_DEFAULT
|
||||
vector = self.exception_vector
|
||||
|
||||
if vector is None:
|
||||
sig = self.GDB_SIGNAL_DEFAULT
|
||||
|
||||
# Map vector number to GDB signal number
|
||||
if vector in self.GDB_SIGNAL_MAPPING:
|
||||
sig = self.GDB_SIGNAL_MAPPING[vector]
|
||||
|
||||
self.gdb_signal = sig
|
||||
|
||||
def handle_register_group_read_packet(self):
|
||||
reg_fmt = "<I"
|
||||
|
||||
idx = 0
|
||||
pkt = b''
|
||||
|
||||
while idx < self.GDB_G_PKT_NUM_REGS:
|
||||
if idx in self.registers:
|
||||
bval = struct.pack(reg_fmt, self.registers[idx])
|
||||
pkt += binascii.hexlify(bval)
|
||||
else:
|
||||
# Register not in coredump -> unknown value
|
||||
# Send in "xxxxxxxx"
|
||||
pkt += b'x' * 8
|
||||
|
||||
idx += 1
|
||||
|
||||
self.put_gdb_packet(pkt)
|
||||
|
||||
def handle_register_single_read_packet(self, pkt):
|
||||
# Mark registers as "<unavailable>".
|
||||
# 'p' packets are usually used for registers
|
||||
# other than the general ones (e.g. eax, ebx)
|
||||
# so we can safely reply "xxxxxxxx" here.
|
||||
self.put_gdb_packet(b'x' * 8)
|
201
scripts/coredump/gdbstubs/arch/x86_64.py
Normal file
201
scripts/coredump/gdbstubs/arch/x86_64.py
Normal file
|
@ -0,0 +1,201 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import binascii
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from gdbstubs.gdbstub import GdbStub
|
||||
|
||||
|
||||
logger = logging.getLogger("gdbstub")
|
||||
|
||||
|
||||
class RegNum():
|
||||
# Matches the enum amd64_regnum in GDB
|
||||
RAX = 0
|
||||
RBX = 1
|
||||
RCX = 2
|
||||
RDX = 3
|
||||
RSI = 4
|
||||
RDI = 5
|
||||
RBP = 6
|
||||
RSP = 7
|
||||
R8 = 8
|
||||
R9 = 9
|
||||
R10 = 10
|
||||
R11 = 11
|
||||
R12 = 12
|
||||
R13 = 13
|
||||
R14 = 14
|
||||
R15 = 15
|
||||
RIP = 16
|
||||
EFLAGS = 17
|
||||
CS = 18
|
||||
SS = 19
|
||||
DS = 20
|
||||
ES = 21
|
||||
FS = 22
|
||||
GS = 23
|
||||
FS_BASE = 24
|
||||
GS_BASE = 25
|
||||
K_GS_BASE = 26
|
||||
|
||||
|
||||
class ExceptionVectors():
|
||||
# Matches arch/x86/include/kernel_arch_data.h
|
||||
IV_DIVIDE_ERROR = 0
|
||||
IV_DEBUG = 1
|
||||
IV_NON_MASKABLE_INTERRUPT = 2
|
||||
IV_BREAKPOINT = 3
|
||||
IV_OVERFLOW = 4
|
||||
IV_BOUND_RANGE = 5
|
||||
IV_INVALID_OPCODE = 6
|
||||
IV_DEVICE_NOT_AVAILABLE = 7
|
||||
IV_DOUBLE_FAULT = 8
|
||||
IV_COPROC_SEGMENT_OVERRUN = 9
|
||||
IV_INVALID_TSS = 10
|
||||
IV_SEGMENT_NOT_PRESENT = 11
|
||||
IV_STACK_FAULT = 12
|
||||
IV_GENERAL_PROTECTION = 13
|
||||
IV_PAGE_FAULT = 14
|
||||
IV_RESERVED = 15
|
||||
IV_X87_FPU_FP_ERROR = 16
|
||||
IV_ALIGNMENT_CHECK = 17
|
||||
IV_MACHINE_CHECK = 18
|
||||
IV_SIMD_FP = 19
|
||||
IV_VIRT_EXCEPTION = 20
|
||||
IV_SECURITY_EXCEPTION = 30
|
||||
|
||||
|
||||
class GdbStub_x86_64(GdbStub):
|
||||
GDB_SIGNAL_DEFAULT = 7
|
||||
|
||||
# Mapping is from GDB's gdb/i386-stubs.c
|
||||
GDB_SIGNAL_MAPPING = {
|
||||
ExceptionVectors.IV_DIVIDE_ERROR: 8,
|
||||
ExceptionVectors.IV_DEBUG: 5,
|
||||
ExceptionVectors.IV_BREAKPOINT: 5,
|
||||
ExceptionVectors.IV_OVERFLOW: 16,
|
||||
ExceptionVectors.IV_BOUND_RANGE: 16,
|
||||
ExceptionVectors.IV_INVALID_OPCODE: 4,
|
||||
ExceptionVectors.IV_DEVICE_NOT_AVAILABLE: 8,
|
||||
ExceptionVectors.IV_DOUBLE_FAULT: 7,
|
||||
ExceptionVectors.IV_COPROC_SEGMENT_OVERRUN: 11,
|
||||
ExceptionVectors.IV_INVALID_TSS: 11,
|
||||
ExceptionVectors.IV_SEGMENT_NOT_PRESENT: 11,
|
||||
ExceptionVectors.IV_STACK_FAULT: 11,
|
||||
ExceptionVectors.IV_GENERAL_PROTECTION: 11,
|
||||
ExceptionVectors.IV_PAGE_FAULT: 11,
|
||||
ExceptionVectors.IV_X87_FPU_FP_ERROR: 7,
|
||||
}
|
||||
|
||||
GDB_G_PKT_NUM_REGS = 34
|
||||
|
||||
GDB_32BIT_REGS = {
|
||||
RegNum.EFLAGS,
|
||||
RegNum.CS,
|
||||
RegNum.SS,
|
||||
RegNum.DS,
|
||||
RegNum.ES,
|
||||
RegNum.FS,
|
||||
RegNum.GS,
|
||||
}
|
||||
|
||||
def __init__(self, logfile, elffile):
|
||||
super().__init__(logfile=logfile, elffile=elffile)
|
||||
self.registers = None
|
||||
self.exception_vector = None
|
||||
self.exception_code = None
|
||||
self.gdb_signal = self.GDB_SIGNAL_DEFAULT
|
||||
|
||||
self.parse_arch_data_block()
|
||||
self.compute_signal()
|
||||
|
||||
def parse_arch_data_block(self):
|
||||
arch_data_blk = self.logfile.get_arch_data()['data']
|
||||
|
||||
arch_data_blk_struct = "<QQQQQQQQQQQQQQQQQQQQQQ"
|
||||
cfg_exception_debug = True
|
||||
if len(arch_data_blk) != struct.calcsize(arch_data_blk_struct):
|
||||
# There are fewer registers dumped
|
||||
# when CONFIG_EXCEPTION_DEBUG=n
|
||||
arch_data_blk_struct = "<QQQQQQQQQQQQQQQQQ"
|
||||
cfg_exception_debug = False
|
||||
|
||||
tu = struct.unpack(arch_data_blk_struct, arch_data_blk)
|
||||
|
||||
self.registers = dict()
|
||||
|
||||
self.exception_vector = tu[0]
|
||||
self.exception_code = tu[1]
|
||||
|
||||
self.registers[RegNum.RAX] = tu[2]
|
||||
self.registers[RegNum.RCX] = tu[3]
|
||||
self.registers[RegNum.RDX] = tu[4]
|
||||
self.registers[RegNum.RSI] = tu[5]
|
||||
self.registers[RegNum.RDI] = tu[6]
|
||||
self.registers[RegNum.RSP] = tu[7]
|
||||
self.registers[RegNum.R8 ] = tu[8]
|
||||
self.registers[RegNum.R9 ] = tu[9]
|
||||
self.registers[RegNum.R10] = tu[10]
|
||||
self.registers[RegNum.R11] = tu[11]
|
||||
self.registers[RegNum.RIP] = tu[12]
|
||||
self.registers[RegNum.EFLAGS] = tu[13]
|
||||
self.registers[RegNum.CS] = tu[14]
|
||||
self.registers[RegNum.SS] = tu[15]
|
||||
self.registers[RegNum.RBP] = tu[16]
|
||||
|
||||
if cfg_exception_debug:
|
||||
self.registers[RegNum.RBX] = tu[17]
|
||||
self.registers[RegNum.R12] = tu[18]
|
||||
self.registers[RegNum.R13] = tu[19]
|
||||
self.registers[RegNum.R14] = tu[20]
|
||||
self.registers[RegNum.R15] = tu[21]
|
||||
|
||||
def compute_signal(self):
|
||||
sig = self.GDB_SIGNAL_DEFAULT
|
||||
vector = self.exception_vector
|
||||
|
||||
if vector is None:
|
||||
sig = self.GDB_SIGNAL_DEFAULT
|
||||
|
||||
# Map vector number to GDB signal number
|
||||
if vector in self.GDB_SIGNAL_MAPPING:
|
||||
sig = self.GDB_SIGNAL_MAPPING[vector]
|
||||
|
||||
self.gdb_signal = sig
|
||||
|
||||
def handle_register_group_read_packet(self):
|
||||
idx = 0
|
||||
pkt = b''
|
||||
|
||||
while idx < self.GDB_G_PKT_NUM_REGS:
|
||||
if idx in self.GDB_32BIT_REGS:
|
||||
reg_fmt = "<I"
|
||||
reg_bytes = 4
|
||||
else:
|
||||
reg_fmt = "<Q"
|
||||
reg_bytes = 8
|
||||
|
||||
if idx in self.registers:
|
||||
bval = struct.pack(reg_fmt, self.registers[idx])
|
||||
pkt += binascii.hexlify(bval)
|
||||
else:
|
||||
# Register not in coredump -> unknown value
|
||||
# Send in "xxxxxxxx"
|
||||
pkt += b'x' * (reg_bytes * 2)
|
||||
|
||||
idx += 1
|
||||
|
||||
self.put_gdb_packet(pkt)
|
||||
|
||||
def handle_register_single_read_packet(self, pkt):
|
||||
# Mark registers as "<unavailable>".
|
||||
# 'p' packets are usually used for registers
|
||||
# other than the general ones (e.g. eax, ebx)
|
||||
# so we can safely reply "xxxxxxxx" here.
|
||||
self.put_gdb_packet(b'x' * 16)
|
Loading…
Add table
Add a link
Reference in a new issue