After these repairs, we must make two files, i.e. kgdb.c and its header, and place those in the directories of Nios Arch (kernel & include/asm). The samples are as follows
/*
* NIOS2 KGDB support
*
* Copyright (C) 2009 Nios Community Wiki
*
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/# include <linux/kgdb.h># include <linux/kdebug.h># include <linux/irq.h># include <linux/io.h># include <asm/cacheflush.h>
static int wait_for_remote_debugger;
/*
* Replace the instruction immediately after the current instruction
* (i.e. next in the expected flow of control) with a trap instruction,
* so that returning will cause only a single instruction to be executed.
* Note that this model is slightly broken for instructions with delay
* slots (e.g. BS, BSR, BRA etc), where both the branch and the
* instruction in the delay slot will be executed.
*/
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
gdb_regs = 0;
gdb_regs = regs->r1;
gdb_regs = regs->r2;
gdb_regs = regs->r3;
gdb_regs = regs->r4;
gdb_regs = regs->r5;
gdb_regs = regs->r6;
gdb_regs = regs->r7;
gdb_regs = regs->r8;
gdb_regs = regs->r9;
gdb_regs = regs->r10;
gdb_regs = regs->r11;
gdb_regs = regs->r12;
gdb_regs = regs->r13;
gdb_regs = regs->r14;
gdb_regs = regs->r15;
gdb_regs = regs->ra;
gdb_regs = regs->fp;
gdb_regs = regs->sp;
gdb_regs = regs->gp;
gdb_regs = regs->estatus;
gdb_regs = regs->ea;
gdb_regs = regs->ea;
}
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
regs->r1 = gdb_regs;
regs->r2 = gdb_regs;
regs->r3 = gdb_regs;
regs->r4 = gdb_regs;
regs->r5 = gdb_regs;
regs->r6 = gdb_regs;
regs->r7 = gdb_regs;
regs->r8 = gdb_regs;
regs->r9 = gdb_regs;
regs->r10 = gdb_regs;
regs->r11 = gdb_regs;
regs->r12 = gdb_regs;
regs->r13 = gdb_regs;
regs->r14 = gdb_regs;
regs->r15 = gdb_regs;
regs->ra = gdb_regs;
regs->fp = gdb_regs;
regs->sp = gdb_regs;
regs->gp = gdb_regs;
regs->estatus = gdb_regs;
regs->ea = gdb_regs;
}
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
gdb_regs = p->thread.kregs->sp;
gdb_regs = p->thread.kregs->ea;
}
int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
char *remcomInBuffer, char *remcomOutBuffer,
struct pt_regs *linux_regs)
{
unsigned long addr;
char *ptr;
int cpu = smp_processor_id();
switch (remcomInBuffer) {
case 's':
case 'c':
/* handle the optional parameter */
ptr = &remcomInBuffer;
if (kgdb_hex2long(&ptr, &addr))
linux_regs->ea = addr;
case 'D':
case 'k':
atomic_set(&kgdb_cpu_doing_single_step, -1);
if (remcomInBuffer == 's')
atomic_set(&kgdb_cpu_doing_single_step, cpu);
return 0;
}
/* this means that we do not want to exit from the handler: */
return -1;
}
/* KGDB Breakpoint handler */
asmlinkage void kgdb_breakpoint_c(struct pt_regs *fp)
{
/* The breakpoint entry code has moved the PC on by 4 bytes, so we must */
/* move it back. This could be done on the host but we do it here */
if (!wait_for_remote_debugger)
fp->ea -= 4;
else /* pass the first trap 0x1e code */
wait_for_remote_debugger = 0;
//printk("KGDB Breakpoint detected, instr=0x%08lx ea=0x%08lx ra=0x%08lx sp=0x%08lx\n", *(unsigned long*)fp->ea, fp->ea, fp->ra, fp->sp);
kgdb_handle_exception(30, SIGTRAP, 0, fp);
//printk("GOOD LUCK!! instr=0x%08lx ea=0x%08lx\n", *(volatile unsigned long*)fp->ea, (volatile unsigned long*)fp->ea);
}
int kgdb_arch_init(void)
{
wait_for_remote_debugger = 1;
return 0;
}
void kgdb_arch_exit(void)
{
}
struct kgdb_arch arch_kgdb_ops = {
/* Breakpoint instruction: trap# 0x1e */
.gdb_bpt_instr = { 0xba, 0x6f, 0x3b, 0x00 },
};
# ifndef __ASM_NIOS2_KGDB_H# define __ASM_NIOS2_KGDB_H
# include <asm/cacheflush.h># include <asm/ptrace.h>
enum regnames {
GDB_R0, GDB_AT, GDB_R2, GDB_R3, GDB_R4, GDB_R5, GDB_R6, GDB_R7,
GDB_R8, GDB_R9, GDB_R10, GDB_R11, GDB_R12, GDB_R13, GDB_R14, GDB_R15,
GDB_R16, GDB_R17, GDB_R18, GDB_R19, GDB_R20, GDB_R21, GDB_R22, GDB_R23,
GDB_ET, GDB_BT, GDB_GP, GDB_SP, GDB_FP, GDB_EA, GDB_BA, GDB_RA,
GDB_PC, GDB_ST, GDB_EST, GDB_BST, GDB_IE, GDB_IP, GDB_CID, GDB_CT6,
GDB_EX, GDB_PTE, GDB_TBA, GDB_TBM, GDB_CT11,GDB_BAD, GDB_CFG,
};
# define NUMREGBYTES ((GDB_CFG + 1) * 4)
static inline void arch_kgdb_breakpoint(void)
{
__asm__ __volatile__ (".word 0x003b6fba");
}
/* State info */
extern char in_nmi; /* Debounce flag to prevent NMI reentry*/
# define BUFMAX 2048
# define CACHE_FLUSH_IS_SAFE 1# define BREAK_INSTR_SIZE 4
# endif /* __ASM_NIOS2_KGDB_H */
And I'm using the code 'trap 30' as software break point ones, we must add some codes to '/home/***/nios2-linux/linux-2.6/arch/nios2/kernel/entry.S'
trap_table:
.word handle_system_call // 0
.word instruction_trap // 1
.word instruction_trap // 2
.word instruction_trap // 3
.word instruction_trap // 4
.word instruction_trap // 5
.word instruction_trap // 6
.word instruction_trap // 7
.word instruction_trap // 8
.word instruction_trap // 9
.word instruction_trap // 10
.word instruction_trap // 11
.word instruction_trap // 12
.word instruction_trap // 13
.word instruction_trap // 14
.word instruction_trap // 15
.word instruction_trap // 16
.word instruction_trap // 17
.word instruction_trap // 18
.word instruction_trap // 19
.word instruction_trap // 20
.word instruction_trap // 21
.word instruction_trap // 22
.word instruction_trap // 23
.word instruction_trap // 24
.word instruction_trap // 25
.word instruction_trap // 26
.word instruction_trap // 27
.word instruction_trap // 28
.word instruction_trap // 29# ifdef CONFIG_KGDB
.word handle_kgdb_breakpoint // 30 KGDB breakpoint# else
.word instruction_trap // 30# endif
.word handle_breakpoint // 31
and
handle_diverror:
call handle_illegal_c
br ret_from_exception
# ifdef CONFIG_KGDB
handle_kgdb_breakpoint:
call kgdb_breakpoint_c
br ret_from_exception# endif
/*
* Beware - when entering resume, prev (the current task) is
.
And repair the Kconfig file '/home/***/nios2-linux/linux-2.6/lib/Kconfig.kgdb' as
config HAVE_ARCH_KGDB
bool
menuconfig KGDB
bool "KGDB: kernel debugging with remote gdb"# depends on HAVE_ARCH_KGDB
depends on DEBUG_KERNEL && EXPERIMENTAL
help
If you say Y here, it will be possible to remotely debug the
kernel using gdb. It is recommended but not required, that
you also turn on the kernel config option
CONFIG_FRAME_POINTER to aid in producing more reliable stack
backtraces in the external debugger. Documentation of
kernel debugger is available at http://kgdb.sourceforge.net
as well as in DocBook form in Documentation/DocBook/. If
unsure, say N.
, you can select the item of 'kgdb' in the menuconfig. So select
Kernel hacking --->
[*] Kernel debugging
[*] Compile the kernel with debug info
[*] KGDB: kernel debugging with remote gdb ---> <*> KGDB: use kgdb over the serial console
(kgdboc=ttyS0, 115200 kgdbwait) Default kernel command string
and make your kernel again. (There is nothing that I'd forgotten to write, maybe... Opps, don't forget to add 'obj-$(CONFIG_KGDB) += kgdb.o' to the Makefile '/home/***/nios2-linux/linux-2.6/arch/nios2/kernel/Makefile'.:p)
After getting the kmsg
KGDB: Waiting for remote debugger
evoke 'gdb' by 'nios2-wrs-linux-gnu-gdb -b 115200' and we can connect the 'kgdb' to our PC with a command e.g. 'target remote /dev/ttyS*'. After the connection, by setting some breakpoints e.g.
symbol-file vmlinux
b load_elf_binary
continue
, we can make break at the first program loading.
Happy Debugging ! (and I shoud debug kgdb.c with KGDB.:D)
Kazu