gdb_server: Remove leftover testing and x86 parts
gdb_server was removed in commit 0f669132a0
("kernel: remove
gdb_server"), but still has a testcase that sets CONFIG_GDB_SERVER=y,
and some code in arch/x86/debug.
Remove the leftover parts. This also gets gets rid of undefined
references to the CONFIG_GDB_SERVER symbol.
Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
This commit is contained in:
parent
d154060a64
commit
5b20350a72
5 changed files with 1 additions and 883 deletions
|
@ -62,10 +62,8 @@ add_custom_command(
|
|||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_subdirectory_ifdef(CONFIG_GDB_SERVER debug)
|
||||
add_subdirectory(soc/${SOC_PATH})
|
||||
# Must be last so that debug/ or soc/ can override default exception
|
||||
# handlers
|
||||
# Must be last so that soc/ can override default exception handlers
|
||||
add_subdirectory(core)
|
||||
|
||||
get_property(OUTPUT_ARCH GLOBAL PROPERTY PROPERTY_OUTPUT_ARCH)
|
||||
|
|
|
@ -1,689 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2016 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* x86 part of the GDB server
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <string.h>
|
||||
#include <debug/gdb_arch.h>
|
||||
#include <debug/gdb_server.h>
|
||||
|
||||
#define TRACE_FLAG 0x0100 /* EFLAGS:TF */
|
||||
#define INT_FLAG 0x0200 /* EFLAGS:IF */
|
||||
|
||||
#define INSTRUCTION_HLT 0xf4
|
||||
#define INSTRUCTION_STI 0xfb
|
||||
#define INSTRUCTION_CLI 0xfa
|
||||
|
||||
#ifdef GDB_ARCH_HAS_RUNCONTROL
|
||||
#ifdef GDB_ARCH_HAS_HW_BP
|
||||
static int gdb_hw_bp_find(struct gdb_debug_regs *regs,
|
||||
enum gdb_bp_type *bp_type,
|
||||
long *address);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize GDB server architecture part
|
||||
*
|
||||
* This routine initializes the architecture part of the GDB server.
|
||||
*
|
||||
* Does nothing currently.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_arch_init(void)
|
||||
{
|
||||
/* currently empty */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill a GDB register set from a given ESF register set
|
||||
*
|
||||
* This routine fills the provided GDB register set with values from given
|
||||
* NANO_ESF register set.
|
||||
*
|
||||
* @param regs Destination GDB register set to fill
|
||||
* @param esf Source exception stack frame
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_arch_regs_from_esf(struct gdb_reg_set *regs, NANO_ESF *esf)
|
||||
{
|
||||
regs->regs.eax = esf->eax;
|
||||
regs->regs.ecx = esf->ecx;
|
||||
regs->regs.edx = esf->edx;
|
||||
regs->regs.ebx = esf->ebx;
|
||||
regs->regs.esp = esf->esp;
|
||||
regs->regs.ebp = esf->ebp;
|
||||
regs->regs.esi = esf->esi;
|
||||
regs->regs.edi = esf->edi;
|
||||
regs->regs.eip = esf->eip;
|
||||
regs->regs.eflags = esf->eflags;
|
||||
regs->regs.cs = esf->cs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill a GDB register set from a given ISF register set
|
||||
*
|
||||
* This routine fills the provided GDB register set with values from given
|
||||
* NANO_ISF register set.
|
||||
*
|
||||
* @param regs Destination GDB register set to fill
|
||||
* @param isf Source interrupt stack frame
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_arch_regs_from_isf(struct gdb_reg_set *regs, NANO_ISF *isf)
|
||||
{
|
||||
memcpy(®s->regs, isf, sizeof(regs->regs));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill an ESF register set from a given GDB register set
|
||||
*
|
||||
* This routine fills the provided NANO_ESF register set with values
|
||||
* from given GDB register set.
|
||||
*
|
||||
* @param regs Source GDB register set
|
||||
* @param esf Destination exception stack frame to fill
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_arch_regs_to_esf(struct gdb_reg_set *regs, NANO_ESF *esf)
|
||||
{
|
||||
esf->eax = regs->regs.eax;
|
||||
esf->ecx = regs->regs.ecx;
|
||||
esf->edx = regs->regs.edx;
|
||||
esf->ebx = regs->regs.ebx;
|
||||
esf->esp = regs->regs.esp;
|
||||
esf->ebp = regs->regs.ebp;
|
||||
esf->esi = regs->regs.esi;
|
||||
esf->edi = regs->regs.edi;
|
||||
esf->eip = regs->regs.eip;
|
||||
esf->eflags = regs->regs.eflags;
|
||||
esf->cs = regs->regs.cs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill an ISF register set from a given GDB register set
|
||||
*
|
||||
* This routine fills the provided NANO_ISF register set with values
|
||||
* from given GDB register set.
|
||||
*
|
||||
* @param regs Source GDB register set
|
||||
* @param isf Destination interrupt stack frame to fill
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_arch_regs_to_isf(struct gdb_reg_set *regs, NANO_ISF *isf)
|
||||
{
|
||||
memcpy(isf, ®s->regs, sizeof(NANO_ISF));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill given buffer from given register set
|
||||
*
|
||||
* This routine fills the provided buffer with values from given register set.
|
||||
*
|
||||
* The provided buffer must be large enough to store all register values.
|
||||
* It is up to the caller to do this check.
|
||||
*
|
||||
* @param regs Source GDB register set
|
||||
* @param esf Destination buffer to fill
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_arch_regs_get(struct gdb_reg_set *regs, char *buffer)
|
||||
{
|
||||
*((u32_t *) buffer) = regs->regs.eax;
|
||||
buffer += 4;
|
||||
*((u32_t *) buffer) = regs->regs.ecx;
|
||||
buffer += 4;
|
||||
*((u32_t *) buffer) = regs->regs.edx;
|
||||
buffer += 4;
|
||||
*((u32_t *) buffer) = regs->regs.ebx;
|
||||
buffer += 4;
|
||||
*((u32_t *) buffer) = regs->regs.esp;
|
||||
buffer += 4;
|
||||
*((u32_t *) buffer) = regs->regs.ebp;
|
||||
buffer += 4;
|
||||
*((u32_t *) buffer) = regs->regs.esi;
|
||||
buffer += 4;
|
||||
*((u32_t *) buffer) = regs->regs.edi;
|
||||
buffer += 4;
|
||||
*((u32_t *) buffer) = (u32_t) regs->regs.eip;
|
||||
buffer += 4;
|
||||
*((u32_t *) buffer) = regs->regs.eflags;
|
||||
buffer += 4;
|
||||
*((u32_t *) buffer) = regs->regs.cs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write given registers buffer to GDB register set
|
||||
*
|
||||
* This routine fills given register set with value from provided buffer.
|
||||
* The provided buffer must be large enough to contain all register values.
|
||||
* It is up to the caller to do this check.
|
||||
*
|
||||
* @param regs Destination GDB register set to fill
|
||||
* @param esf Source buffer
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_arch_regs_set(struct gdb_reg_set *regs, char *buffer)
|
||||
{
|
||||
regs->regs.eax = *((u32_t *)buffer);
|
||||
buffer += 4;
|
||||
regs->regs.ecx = *((u32_t *)buffer);
|
||||
buffer += 4;
|
||||
regs->regs.edx = *((u32_t *)buffer);
|
||||
buffer += 4;
|
||||
regs->regs.ebx = *((u32_t *)buffer);
|
||||
buffer += 4;
|
||||
regs->regs.esp = *((u32_t *)buffer);
|
||||
buffer += 4;
|
||||
regs->regs.ebp = *((u32_t *)buffer);
|
||||
buffer += 4;
|
||||
regs->regs.esi = *((u32_t *)buffer);
|
||||
buffer += 4;
|
||||
regs->regs.edi = *((u32_t *)buffer);
|
||||
buffer += 4;
|
||||
regs->regs.eip = *((u32_t *)buffer);
|
||||
buffer += 4;
|
||||
regs->regs.eflags = *((u32_t *)buffer);
|
||||
buffer += 4;
|
||||
regs->regs.cs = *((u32_t *)buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get size and offset of given register
|
||||
*
|
||||
* This routine returns size and offset of given register.
|
||||
*
|
||||
* @param reg_id Register identifier
|
||||
* @param size Container to return size of register, in bytes
|
||||
* @param offset Container to return offset of register, in bytes
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_arch_reg_info_get(int reg_id, int *size, int *offset)
|
||||
{
|
||||
/* Determine register size and offset */
|
||||
if (reg_id >= 0 && reg_id < GDB_NUM_REGS) {
|
||||
*size = 4;
|
||||
*offset = 4 * reg_id;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GDB_ARCH_HAS_RUNCONTROL
|
||||
#ifdef GDB_ARCH_HAS_HW_BP
|
||||
/**
|
||||
* @brief Get the HW breakpoint architecture type for a common GDB type
|
||||
*
|
||||
* This routine gets the specific architecture value that corresponds to a
|
||||
* common hardware breakpoint type.
|
||||
*
|
||||
* The values accepted for the @a type are GDB_HW_INST_BP,
|
||||
* GDB_HW_DATA_WRITE_BP, GDB_HW_DATA_ACCESS_BP and GDB_HW_DATA_READ_BP.
|
||||
*
|
||||
* @param type Common GDB breakpoint type
|
||||
* @param len Data length
|
||||
* @param err Error code on failure (return value of -1)
|
||||
*
|
||||
* @return The architecture type, -1 on failure
|
||||
*/
|
||||
|
||||
static char gdb_hw_bp_type_get(enum gdb_bp_type type, int len,
|
||||
enum gdb_error_code *err)
|
||||
{
|
||||
char hw_type = -1;
|
||||
|
||||
switch (type) {
|
||||
/* Following combinations are supported on IA */
|
||||
case GDB_HW_INST_BP:
|
||||
hw_type = 0;
|
||||
break;
|
||||
case GDB_HW_DATA_WRITE_BP:
|
||||
if (len == 1) {
|
||||
hw_type = 0x1;
|
||||
} else if (len == 2) {
|
||||
hw_type = 0x5;
|
||||
} else if (len == 4) {
|
||||
hw_type = 0xd;
|
||||
} else if (len == 8) {
|
||||
hw_type = 0x9;
|
||||
}
|
||||
break;
|
||||
case GDB_HW_DATA_ACCESS_BP:
|
||||
if (len == 1) {
|
||||
hw_type = 0x3;
|
||||
} else if (len == 2) {
|
||||
hw_type = 0x7;
|
||||
} else if (len == 4) {
|
||||
hw_type = 0xf;
|
||||
} else if (len == 8) {
|
||||
hw_type = 0xb;
|
||||
}
|
||||
break;
|
||||
case GDB_HW_DATA_READ_BP:
|
||||
/* Data read not supported on IA */
|
||||
/*
|
||||
* NOTE: Read only watchpoints are not supported by IA debug
|
||||
* registers, but it could be possible to use RW watchpoints
|
||||
* and ignore the RW watchpoint if it has been hit by a write
|
||||
* operation.
|
||||
*/
|
||||
*err = GDB_ERROR_HW_BP_NOT_SUP;
|
||||
return -1;
|
||||
default:
|
||||
/* Unknown type */
|
||||
*err = GDB_ERROR_HW_BP_INVALID_TYPE;
|
||||
return -1;
|
||||
}
|
||||
return hw_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the debug registers for a specific HW BP.
|
||||
*
|
||||
* This routine sets the @a regs debug registers according to the HW breakpoint
|
||||
* description.
|
||||
*
|
||||
* @param regs Debug registers to set
|
||||
* @param addr Address of the breakpoint
|
||||
* @param type Common GDB breakpoint type
|
||||
* @param len Data length
|
||||
* @param err Error code on failure (return value of -1)
|
||||
*
|
||||
* @return 0 if debug registers have been modified, -1 on error
|
||||
*/
|
||||
|
||||
int gdb_hw_bp_set(struct gdb_debug_regs *regs, long addr,
|
||||
enum gdb_bp_type type,
|
||||
int len, enum gdb_error_code *err)
|
||||
{
|
||||
char hw_type;
|
||||
|
||||
hw_type = gdb_hw_bp_type_get(type, len, err);
|
||||
if (hw_type < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (regs->db0 == 0) {
|
||||
regs->db0 = addr;
|
||||
regs->db7 |= (hw_type << 16) | 0x02;
|
||||
} else if (regs->db1 == 0) {
|
||||
regs->db1 = addr;
|
||||
regs->db7 |= (hw_type << 20) | 0x08;
|
||||
} else if (regs->db2 == 0) {
|
||||
regs->db2 = addr;
|
||||
regs->db7 |= (hw_type << 24) | 0x20;
|
||||
} else if (regs->db3 == 0) {
|
||||
regs->db3 = addr;
|
||||
regs->db7 |= (hw_type << 28) | 0x80;
|
||||
} else {
|
||||
*err = GDB_ERROR_HW_BP_DBG_REGS_FULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set GE bit if it is data breakpoint */
|
||||
if (hw_type != 0) {
|
||||
regs->db7 |= 0x200;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the debug registers for a specific HW BP.
|
||||
*
|
||||
* This routine updates the @a regs debug registers to remove a HW breakpoint.
|
||||
*
|
||||
* @param regs Debug registers to clear
|
||||
* @param addr Address of the breakpoint
|
||||
* @param type Common GDB breakpoint type
|
||||
* @param len Data length
|
||||
* @param err Error code on failure (return value of -1)
|
||||
*
|
||||
* @return 0 if debug registers have been modified, -1 on error
|
||||
*/
|
||||
|
||||
int gdb_hw_bp_clear(struct gdb_debug_regs *regs, long addr,
|
||||
enum gdb_bp_type type, int len,
|
||||
enum gdb_error_code *err)
|
||||
{
|
||||
char hw_type;
|
||||
|
||||
hw_type = gdb_hw_bp_type_get(type, len, err);
|
||||
if (hw_type < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((regs->db0 == addr) && (((regs->db7 >> 16) & 0xf) == hw_type)) {
|
||||
regs->db0 = 0;
|
||||
regs->db7 &= ~((hw_type << 16) | 0x02);
|
||||
} else if ((regs->db1 == addr)
|
||||
&& (((regs->db7 >> 20) & 0xf) == hw_type)) {
|
||||
regs->db1 = 0;
|
||||
regs->db7 &= ~((hw_type << 20) | 0x08);
|
||||
} else if ((regs->db2 == addr)
|
||||
&& (((regs->db7 >> 24) & 0xf) == hw_type)) {
|
||||
regs->db2 = 0;
|
||||
regs->db7 &= ~((hw_type << 24) | 0x20);
|
||||
} else if ((regs->db3 == addr)
|
||||
&& (((regs->db7 >> 28) & 0xf) == hw_type)) {
|
||||
regs->db3 = 0;
|
||||
regs->db7 &= ~((hw_type << 28) | 0x80);
|
||||
} else {
|
||||
/* Unknown breakpoint */
|
||||
*err = GDB_ERROR_INVALID_BP;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Look for a Hardware breakpoint
|
||||
*
|
||||
* This routine checks from the @a regs debug register set if a hardware
|
||||
* breakpoint has been hit.
|
||||
*
|
||||
* @param regs Debug registers to check
|
||||
* @param bp_type Common GDB breakpoint type
|
||||
* @param address Address of the breakpoint
|
||||
*
|
||||
* @return 0 if a HW BP has been found, -1 otherwise
|
||||
*/
|
||||
|
||||
static int gdb_hw_bp_find(struct gdb_debug_regs *regs,
|
||||
enum gdb_bp_type *bp_type,
|
||||
long *address)
|
||||
{
|
||||
int ix;
|
||||
unsigned char type = 0;
|
||||
long addr = 0;
|
||||
int status_bit;
|
||||
int enable_bit;
|
||||
|
||||
/* get address and type of breakpoint from DR6 and DR7 */
|
||||
for (ix = 0; ix < 4; ix++) {
|
||||
status_bit = 1 << ix;
|
||||
enable_bit = 2 << (ix << 1);
|
||||
|
||||
if ((regs->db6 & status_bit) && (regs->db7 & enable_bit)) {
|
||||
switch (ix) {
|
||||
case 0:
|
||||
addr = regs->db0;
|
||||
type = (regs->db7 & 0x000f0000) >> 16;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
addr = regs->db1;
|
||||
type = (regs->db7 & 0x00f00000) >> 20;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
addr = regs->db2;
|
||||
type = (regs->db7 & 0x0f000000) >> 24;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
addr = regs->db3;
|
||||
type = (regs->db7 & 0xf0000000) >> 28;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((addr == 0) && (type == 0))
|
||||
return -1;
|
||||
|
||||
*address = addr;
|
||||
switch (type) {
|
||||
case 0x1:
|
||||
case 0x5:
|
||||
case 0xd:
|
||||
case 0x9:
|
||||
*bp_type = GDB_HW_DATA_WRITE_BP;
|
||||
break;
|
||||
case 0x3:
|
||||
case 0x7:
|
||||
case 0xf:
|
||||
case 0xb:
|
||||
*bp_type = GDB_HW_DATA_ACCESS_BP;
|
||||
break;
|
||||
default:
|
||||
*bp_type = GDB_HW_INST_BP;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear all debug registers.
|
||||
*
|
||||
* This routine clears all debug registers
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_dbg_regs_clear(void)
|
||||
{
|
||||
struct gdb_debug_regs regs;
|
||||
|
||||
regs.db0 = 0;
|
||||
regs.db1 = 0;
|
||||
regs.db2 = 0;
|
||||
regs.db3 = 0;
|
||||
regs.db6 = 0;
|
||||
regs.db7 = 0;
|
||||
gdb_dbg_regs_set(®s);
|
||||
}
|
||||
#endif /* GDB_ARCH_HAS_HW_BP */
|
||||
|
||||
/**
|
||||
* @brief Clear trace mode
|
||||
*
|
||||
* This routine makes CPU trace-disabled.
|
||||
*
|
||||
* @param regs GDB register set to modify.
|
||||
* @param arg Interrupt locking key
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_trace_mode_clear(struct gdb_reg_set *regs, int arg)
|
||||
{
|
||||
regs->regs.eflags &= ~INT_FLAG;
|
||||
regs->regs.eflags |= (arg & INT_FLAG);
|
||||
regs->regs.eflags &= ~TRACE_FLAG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test if single stepping is possible for current program counter
|
||||
*
|
||||
* @param regs GDB register set to fetch PC from.
|
||||
*
|
||||
* @return 1 if it is possible to step the instruction, 0 otherwise
|
||||
*/
|
||||
|
||||
int gdb_arch_can_step(struct gdb_reg_set *regs)
|
||||
{
|
||||
unsigned char *pc = (unsigned char *)regs->regs.eip;
|
||||
|
||||
if (*pc == INSTRUCTION_HLT) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set trace mode
|
||||
*
|
||||
* This routine makes CPU trace-enabled.
|
||||
*
|
||||
* In the event that the program counter currently points to a sti or a cli
|
||||
* instruction, the returned eflags will contain an IF bit as if that
|
||||
* instruction had executed (set for sti, cleared for cli).
|
||||
*
|
||||
* @param regs GDB register set to modify.
|
||||
*
|
||||
* @return eflags with IF bit possibly modified by current sti/cli instruction.
|
||||
*/
|
||||
|
||||
int gdb_trace_mode_set(struct gdb_reg_set *regs)
|
||||
{
|
||||
unsigned char *pc = (unsigned char *)regs->regs.eip;
|
||||
int simulated_eflags = regs->regs.eflags;
|
||||
|
||||
if (*pc == INSTRUCTION_STI) {
|
||||
simulated_eflags |= INT_FLAG;
|
||||
}
|
||||
|
||||
if (*pc == INSTRUCTION_CLI) {
|
||||
simulated_eflags &= ~INT_FLAG;
|
||||
}
|
||||
|
||||
regs->regs.eflags &= ~INT_FLAG;
|
||||
regs->regs.eflags |= TRACE_FLAG;
|
||||
|
||||
return simulated_eflags;
|
||||
}
|
||||
|
||||
#ifdef GDB_ARCH_HAS_HW_BP
|
||||
/**
|
||||
* @brief Implementation of GDB trace handler for HW breakpoint support
|
||||
*
|
||||
* @param esf Exception stack frame when taking the exception
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
static void _do_gdb_trace_handler(NANO_ESF *esf)
|
||||
{
|
||||
struct gdb_debug_regs regs;
|
||||
|
||||
gdb_dbg_regs_get(®s);
|
||||
if ((regs.db6 & 0x00004000) == 0x00004000) {
|
||||
gdb_handler(GDB_EXC_TRACE, esf, GDB_SIG_TRAP);
|
||||
} else {
|
||||
int type;
|
||||
long addr;
|
||||
|
||||
gdb_dbg_regs_clear();
|
||||
(void)gdb_hw_bp_find(®s, &type, &addr);
|
||||
gdb_cpu_stop_hw_bp_addr = addr;
|
||||
gdb_cpu_stop_bp_type = type;
|
||||
gdb_debug_status = DEBUGGING;
|
||||
gdb_handler(GDB_EXC_BP, esf, GDB_SIG_TRAP);
|
||||
}
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* @brief Implementation of GDB trace handler for SW breakpoint support
|
||||
*
|
||||
* @param esf Exception stack frame when taking the exception
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
static void _do_gdb_trace_handler(NANO_ESF *esf)
|
||||
{
|
||||
gdb_handler(GDB_EXC_TRACE, esf, GDB_SIG_TRAP);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GDB trace handler
|
||||
*
|
||||
* The GDB trace handler is used to catch and handle the trace mode exceptions
|
||||
* (single step).
|
||||
*
|
||||
* @param esf Exception stack frame when taking the exception
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_trace_handler(NANO_ESF *esf)
|
||||
{
|
||||
(void)irq_lock();
|
||||
_do_gdb_trace_handler(esf);
|
||||
}
|
||||
_EXCEPTION_CONNECT_NOCODE(gdb_trace_handler, IV_DEBUG);
|
||||
|
||||
/**
|
||||
* @brief GDB breakpoint handler
|
||||
*
|
||||
* The GDB breakpoint handler is used to catch and handle the breakpoint
|
||||
* exceptions.
|
||||
*
|
||||
* @param esf Exception stack frame when taking the exception
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_bp_handler(NANO_ESF *esf)
|
||||
{
|
||||
(void)irq_lock();
|
||||
|
||||
gdb_debug_status = DEBUGGING;
|
||||
GDB_SET_STOP_BP_TYPE_SOFT(GDB_SOFT_BP);
|
||||
esf->eip -= sizeof(gdb_instr_t);
|
||||
|
||||
gdb_handler(GDB_EXC_BP, esf, GDB_SIG_TRAP);
|
||||
}
|
||||
_EXCEPTION_CONNECT_NOCODE(gdb_bp_handler, IV_BREAKPOINT);
|
||||
|
||||
/**
|
||||
* @brief GDB division-by-zero handler
|
||||
*
|
||||
* This GDB handler is used to catch and handle the division-by-zero exception.
|
||||
*
|
||||
* @param esf Exception stack frame when taking the exception
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_div_by_zero_handler(NANO_ESF *esf)
|
||||
{
|
||||
(void)irq_lock();
|
||||
gdb_debug_status = DEBUGGING;
|
||||
gdb_handler(GDB_EXC_OTHER, esf, GDB_SIG_FPE);
|
||||
}
|
||||
_EXCEPTION_CONNECT_NOCODE(gdb_div_by_zero_handler, IV_DIVIDE_ERROR);
|
||||
|
||||
/**
|
||||
* @brief GDB page fault handler
|
||||
*
|
||||
* This GDB handler is used to catch and handle the page fault exceptions.
|
||||
*
|
||||
* @param esf Exception stack frame when taking the exception
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void gdb_pfault_handler(NANO_ESF *esf)
|
||||
{
|
||||
(void)irq_lock();
|
||||
gdb_debug_status = DEBUGGING;
|
||||
gdb_handler(GDB_EXC_OTHER, esf, GDB_SIG_SIGSEGV);
|
||||
}
|
||||
_EXCEPTION_CONNECT_CODE(gdb_pfault_handler, IV_PAGE_FAULT);
|
||||
|
||||
#endif /* GDB_ARCH_HAS_RUNCONTROL */
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* This module provides the implementation of the gdb_dbg_regs_set/get()
|
||||
* utilities.
|
||||
*/
|
||||
|
||||
#include <arch/x86/asm.h>
|
||||
|
||||
/* exports (internal APIs) */
|
||||
|
||||
GTEXT(gdb_dbg_regs_set)
|
||||
GTEXT(gdb_dbg_regs_get)
|
||||
|
||||
/**
|
||||
* @brief Write debug registers
|
||||
*
|
||||
* This function is used to write to debug registers
|
||||
*
|
||||
* C function prototype:
|
||||
*
|
||||
* void gdb_dbg_regs_set (struct gdb_debug_regs * regs);
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, gdb_dbg_regs_set)
|
||||
movl SP_ARG1(%esp),%edx
|
||||
movl 0(%edx),%eax
|
||||
movl %eax,%db0
|
||||
movl 4(%edx),%eax
|
||||
movl %eax,%db1
|
||||
movl 8(%edx),%eax
|
||||
movl %eax,%db2
|
||||
movl 12(%edx),%eax
|
||||
movl %eax,%db3
|
||||
movl 16(%edx),%eax
|
||||
movl %eax,%db6
|
||||
movl 20(%edx),%eax
|
||||
movl %eax,%db7
|
||||
ret
|
||||
|
||||
/**
|
||||
* @brief Read debug registers
|
||||
*
|
||||
* This function is used to read debug registers
|
||||
*
|
||||
* C function prototype:
|
||||
*
|
||||
* void gdb_dbg_regs_get (struct gdb_debug_regs * regs);
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, gdb_dbg_regs_get)
|
||||
movl SP_ARG1(%esp),%edx
|
||||
movl %db0,%eax
|
||||
movl %eax,0(%edx)
|
||||
movl %db1,%eax
|
||||
movl %eax,4(%edx)
|
||||
movl %db2,%eax
|
||||
movl %eax,8(%edx)
|
||||
movl %db3,%eax
|
||||
movl %eax,12(%edx)
|
||||
movl %db6,%eax
|
||||
movl %eax,16(%edx)
|
||||
movl %db7,%eax
|
||||
movl %eax,20(%edx)
|
||||
ret
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _GDB_ARCH__H_
|
||||
#define _GDB_ARCH__H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <kernel_structs.h>
|
||||
#include <debug/gdb_server.h>
|
||||
|
||||
#define GDB_ARCH_HAS_ALL_REGS
|
||||
|
||||
#ifndef CONFIG_GDB_SERVER_BOOTLOADER
|
||||
#undef GDB_ARCH_HAS_HW_BP
|
||||
#define GDB_ARCH_HAS_REMOTE_SERIAL_EXT_USING_NOTIF_PACKETS
|
||||
#define GDB_ARCH_HAS_RUNCONTROL
|
||||
#define GDB_ARCH_CAN_STEP gdb_arch_can_step
|
||||
#endif
|
||||
|
||||
#ifndef GDB_RAM_SIZE
|
||||
#define GDB_RAM_SIZE (CONFIG_RAM_SIZE * 1024)
|
||||
#endif
|
||||
#ifndef CONFIG_GDB_RAM_ADDRESS
|
||||
#define CONFIG_GDB_RAM_ADDRESS 0x100000
|
||||
#endif
|
||||
|
||||
/* Default GDB buffer size */
|
||||
#ifdef CONFIG_GDB_SERVER_BOOTLOADER
|
||||
#define GDB_BUF_SIZE 8192
|
||||
#else
|
||||
#define GDB_BUF_SIZE 600
|
||||
#endif
|
||||
|
||||
#define GDB_TGT_ARCH "i386"
|
||||
|
||||
#define GDB_NUM_REGS 16
|
||||
#define GDB_NUM_REG_BYTES (GDB_NUM_REGS * 4)
|
||||
|
||||
#define GDB_PC_REG 8
|
||||
|
||||
#define GDB_BREAK_INSTRUCTION 0xcc /* 'int3' opcode */
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
typedef unsigned char gdb_instr_t;
|
||||
|
||||
struct gdb_reg_set {
|
||||
NANO_ISF regs;
|
||||
unsigned int pad1; /* padding for ss register */
|
||||
unsigned int pad2; /* padding for ds register */
|
||||
unsigned int pad3; /* padding for es register */
|
||||
unsigned int pad4; /* padding for fs register */
|
||||
unsigned int pad5; /* padding for gs register */
|
||||
};
|
||||
|
||||
struct gdb_debug_regs {
|
||||
unsigned int db0; /* debug register 0 */
|
||||
unsigned int db1; /* debug register 1 */
|
||||
unsigned int db2; /* debug register 2 */
|
||||
unsigned int db3; /* debug register 3 */
|
||||
unsigned int db6; /* debug register 6 */
|
||||
unsigned int db7; /* debug register 7 */
|
||||
};
|
||||
|
||||
#if defined(GDB_ARCH_HAS_RUNCONTROL) && defined(GDB_ARCH_HAS_HW_BP)
|
||||
extern volatile int gdb_cpu_stop_bp_type;
|
||||
extern long gdb_cpu_stop_hw_bp_addr;
|
||||
#define GDB_SET_STOP_BP_TYPE_SOFT(x) \
|
||||
do { gdb_cpu_stop_bp_type = (x); } while ((0))
|
||||
#else
|
||||
#define GDB_SET_STOP_BP_TYPE_SOFT(x)
|
||||
#endif
|
||||
|
||||
extern void gdb_arch_init(void);
|
||||
extern void gdb_arch_regs_from_esf(struct gdb_reg_set *regs,
|
||||
NANO_ESF *esf);
|
||||
extern void gdb_arch_regs_to_esf(struct gdb_reg_set *regs,
|
||||
NANO_ESF *esf);
|
||||
extern void gdb_arch_regs_from_isf(struct gdb_reg_set *regs,
|
||||
NANO_ISF *esf);
|
||||
extern void gdb_arch_regs_to_isf(struct gdb_reg_set *regs,
|
||||
NANO_ISF *esf);
|
||||
extern void gdb_arch_regs_get(struct gdb_reg_set *regs, char *buffer);
|
||||
extern void gdb_arch_regs_set(struct gdb_reg_set *regs, char *buffer);
|
||||
extern void gdb_arch_reg_info_get(int reg_id, int *size, int *offset);
|
||||
extern void gdb_trace_mode_clear(struct gdb_reg_set *regs, int arg);
|
||||
extern int gdb_trace_mode_set(struct gdb_reg_set *regs);
|
||||
extern int gdb_arch_can_step(struct gdb_reg_set *regs);
|
||||
#ifdef GDB_ARCH_HAS_HW_BP
|
||||
extern int gdb_hw_bp_set(struct gdb_debug_regs *regs, long addr,
|
||||
enum gdb_bp_type type, int length,
|
||||
enum gdb_error_code *err);
|
||||
extern int gdb_hw_bp_clear(struct gdb_debug_regs *regs, long addr,
|
||||
enum gdb_bp_type type, int length,
|
||||
enum gdb_error_code *err);
|
||||
extern void gdb_dbg_regs_set(struct gdb_debug_regs *regs);
|
||||
extern void gdb_dbg_regs_get(struct gdb_debug_regs *regs);
|
||||
extern void gdb_dbg_regs_clear(void);
|
||||
#endif
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _GDB_ARCH__H_ */
|
|
@ -12,10 +12,6 @@ tests:
|
|||
build_only: true
|
||||
extra_args: CONF_FILE=runtime_nmi.conf
|
||||
tags: apps
|
||||
test_gdb_server:
|
||||
build_only: true
|
||||
extra_configs:
|
||||
- CONFIG_GDB_SERVER=y
|
||||
test_mcuboot_bootloader:
|
||||
build_only: true
|
||||
platform_whitelist: nrf51_pca10028 nrf52_pca10040
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue