2004-01-21 16:53:29

by Amit S. Kale

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Hi,

Here it is: ppc kgdb from timesys kernel is available at
http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2

This is my attempt at extracting kgdb from TimeSys kernel. It works well in
TimeSys kernel, so blame me if above patch doesn't work.

ChangeLog:
2004-01-21 TimeSys Corporation
* kgdb on powerpc.

2004-01-21 Pavel Machek <[email protected]>
* Changes for coding conventions

2004-01-21 Tom Rini <[email protected]>
* Added a prototype for kgdb8250_add_port.


On Wednesday 21 Jan 2004 9:00 pm, Tom Rini wrote:
> On Wed, Jan 21, 2004 at 07:46:17PM +0530, Amit S. Kale wrote:
> > Hi Tom,
> >
> > Yes. Software breakpoints have been tested in the TimeSys ppc kernel
> > source. They work quite well!! I'll be releasing that code soon.
>
> Any chance you can give me what they gave you? I can try and merge
> and test things.
>
> > Here are a couple of questions from a quick look at this code. I may have
> > more when I do a merge this code with what I have.
> >
> > > - bl schedule
> > > + bl user_schedule
> >
> > I still have #ifdef CONFIG_KGDB_THREAD here. Threads listing is a
> > necessary feature, agreed. Do you have any ideas on reducing the overhead
> > of the code added by having to push all registers when doing a switch_to?
> >
> > if (kgdb enabled) do a full push of registers else go to usual switch_to
> >
> > Does this sound good?
>
> From what I recall of starting on this around kgdb 2.0.2, I couldn't
> link the kernel w/o this change (KGDB=n).
>
> > > + */
> > > +#if 0
> > > + extern atomic_t kgdb_setting_breakpoint;
> > > + if (atomic_read(&kgdb_setting_breakpoint))
> > > + regs->nip += 4;
> > > +#else
> > > + if (linux_regs->nip == 0x7d821008 )
> > > + /* Skip over breakpoint trap insn */
> > > + linux_regs->nip += 4;
> > > +#endif
> >
> > Why is kgdb_setting_breakpoint a bad idea?
> > My guess - problems on an smp board.
>
> I don't know how well the current kgdb stub is tested on SMP, but it
> doesn't need any extra locking here.
>
> > Hardcoded nip is worse.
> > Any ideas for a better code?
>
> I've got a feeling that the nip is always the trap instruction, so we
> could always do what the TimeSys code (and before that, the current
> stub) does of skipping over it. I used the hard-coded value there since
> I hadn't gotten around to re-arranging the code so I could do *(uint
> *)kgdb_ops->gdb_bpt_instr or so.
>
> > In following code, gdb packets and their responses appear correct. kgdb
> > is supposed handle software breakpoints.
> >
> > The breakpoint 0xc0000000 placed by gdb is _evil_ It may clobber data.
> > The gdb at kgdb.sourceforge.net places it correctly at module_event.
>
> I'm not quite sure what you're getting at. The gdb binary I'm using is
> a good one (It's happy w/ the current kgdb stub, working in tandem w/ a
> BDI2000, etc). If the breakpoints being set aren't right, I suspect
> that it's related to the other problems I'm seeing.
>
> > Where is the other breakpoint placed? While you would have certainly done
> > that, please confirm that kgdb actually inserts a breakpoint where you
> > have asked it to: a simple printk at the address where the breakpoint is
> > placed should be sufficient. printing from gdb will not work as gdb
> > removes all breakpoints before giving control to a user.
>
> The thing is the kernel gets into an infinite loop of stopping, as far
> as gdb can tell, at the initial breakpoint.

--
Amit Kale
EmSysSoft (http://www.emsyssoft.com)
KGDB: Linux Kernel Source Level Debugger (http://kgdb.sourceforge.net)


2004-01-21 18:42:27

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:

> Hi,
>
> Here it is: ppc kgdb from timesys kernel is available at
> http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
>
> This is my attempt at extracting kgdb from TimeSys kernel. It works well in
> TimeSys kernel, so blame me if above patch doesn't work.

Okay, here's my first patch against this.
===== kernel/kgdbstub.c 1.1 vs edited =====
--- 1.1/kernel/kgdbstub.c Wed Jan 21 10:13:17 2004
+++ edited/kernel/kgdbstub.c Wed Jan 21 10:53:38 2004
@@ -1058,9 +1058,6 @@
kgdb_serial->write_char('+');

linux_debug_hook = kgdb_handle_exception;
-
- if (kgdb_ops->kgdb_init)
- kgdb_ops->kgdb_init();

/* We can't do much if this fails */
register_module_notifier(&kgdb_module_load_nb);
@@ -1104,6 +1101,11 @@
if (!kgdb_enter) {
return;
}
+
+ /* Let the arch do any initalization it needs to */
+ if (kgdb_ops->kgdb_init)
+ kgdb_ops->kgdb_init();
+
if (!kgdb_serial) {
printk("KGDB: no gdb interface available.\n"
"kgdb can't be enabled\n");

I'm not sure why you were calling the arch-specific init so late in the
process, but since it's a nop on both i386 and x86_64 (so perhaps it
should be removed for both of these?), this change doesn't matter to
them. But it does make the PPC code cleaner, IMHO.

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-21 19:21:51

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Wed, Jan 21, 2004 at 11:42:17AM -0700, Tom Rini wrote:
> On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
>
> > Hi,
> >
> > Here it is: ppc kgdb from timesys kernel is available at
> > http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
> >
> > This is my attempt at extracting kgdb from TimeSys kernel. It works well in
> > TimeSys kernel, so blame me if above patch doesn't work.
>
> Okay, here's my first patch against this.

And dependant upon this is a patch to fixup the rest of the common PPC
code, as follows:
- Add FRAME_POINTER
- Put the bits of kgdbppc_init into ppc_kgdb_init.
- None of the gen550 stuffs depend on CONFIG_8250_SERIAL directly,
remove that constraint.
- Add missing bits like debuggerinfo, BREAKPOINT, etc.
- Add a kgdb_map_scc machdep pointer.

--- 1.48/arch/ppc/Kconfig Wed Jan 21 10:13:13 2004
+++ edited/arch/ppc/Kconfig Wed Jan 21 12:18:32 2004
@@ -1405,6 +1405,14 @@
Say Y here only if you plan to use some sort of debugger to
debug the kernel.
If you don't debug the kernel, you can say N.
+
+config FRAME_POINTER
+ bool "Compile the kernel with frame pointers"
+ help
+ If you say Y here the resulting kernel image will be slightly larger
+ and slower, but it will give very useful debugging information.
+ If you don't debug the kernel, you can say N, but we may not be able
+ to solve problems without frame pointers.

config BOOTX_TEXT
bool "Support for early boot text console (BootX or OpenFirmware only)"
--- 1.12/arch/ppc/kernel/ppc-stub.c Wed Jan 21 10:13:13 2004
+++ edited/arch/ppc/kernel/ppc-stub.c Wed Jan 21 12:17:34 2004
@@ -20,9 +20,11 @@
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/kgdb.h>
+
#include <asm/current.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
+#include <asm/machdep.h>

/*
* Forward prototypes
@@ -81,18 +83,6 @@
return 1;
}

-static int ppc_kgdb_init (void)
-{
- debugger = kgdb_debugger;
- debugger_bpt = kgdb_breakpoint;
- debugger_sstep = kgdb_singlestep;
- debugger_iabr_match = kgdb_iabr_match;
- debugger_dabr_match = kgdb_dabr_match;
-
- return 0;
-
-}
-
static void ppc_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
int reg;
@@ -258,9 +248,10 @@
return getDebugChar();
}

-int kgdbppc_hook(void)
+static int kgdbppc_hook(void)
{
- kgdb_map_scc();
+ if (ppc_md.kgdb_map_scc)
+ ppc_md.kgdb_map_scc();
return 0;
}

@@ -270,7 +261,16 @@
.hook = kgdbppc_hook
};

-void kgdbppc_init(void)
+static int ppc_kgdb_init (void)
{
+ debugger = kgdb_debugger;
+ debugger_bpt = kgdb_breakpoint;
+ debugger_sstep = kgdb_singlestep;
+ debugger_iabr_match = kgdb_iabr_match;
+ debugger_dabr_match = kgdb_dabr_match;
+
kgdb_serial = &kgdbppc_serial;
+
+ return 0;
+
}
--- 1.50/arch/ppc/kernel/setup.c Wed Jan 21 10:13:13 2004
+++ edited/arch/ppc/kernel/setup.c Wed Jan 21 12:17:34 2004
@@ -37,10 +37,6 @@
#include <asm/sections.h>
#include <asm/xmon.h>

-#if defined CONFIG_KGDB
-#include <asm/kgdb.h>
-#endif
-
extern void platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7);
extern void bootx_init(unsigned long r4, unsigned long phys);
@@ -48,11 +44,6 @@
extern void do_cpu_ftr_fixups(unsigned long offset);
extern void reloc_got2(unsigned long offset);

-
-#ifdef CONFIG_KGDB
-extern void kgdb_map_scc(void);
-#endif
-
extern void ppc6xx_idle(void);
extern void power4_idle(void);

@@ -631,10 +622,6 @@
#endif /* CONFIG_XMON */
if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);

-#if defined(CONFIG_KGDB)
- kgdbppc_init();
-#endif
-
/*
* Set cache line size based on type of cpu as a default.
* Systems with OF can look in the properties on the cpu node(s)
--- 1.10/arch/ppc/syslib/Makefile Wed Sep 3 05:16:34 2003
+++ edited/arch/ppc/syslib/Makefile Wed Jan 21 12:17:34 2004
@@ -66,7 +66,7 @@
obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \
todc_time.o
obj-$(CONFIG_8260) += m8260_setup.o ppc8260_pic.o
-ifeq ($(CONFIG_SERIAL_8250)$(CONFIG_PPC_GEN550),yy)
+ifeq ($(CONFIG_PPC_GEN550),y)
obj-$(CONFIG_KGDB) += gen550_kgdb.o gen550_dbg.o
obj-$(CONFIG_SERIAL_TEXT_DEBUG) += gen550_dbg.o
endif
--- 1.1/arch/ppc/syslib/gen550_dbg.c Tue Jul 1 08:34:08 2003
+++ edited/arch/ppc/syslib/gen550_dbg.c Wed Jan 21 12:17:34 2004
@@ -17,6 +17,8 @@
*/

#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/serial.h>
#include <linux/tty.h> /* For linux/serial_core.h */
#include <linux/serial_core.h>
#include <linux/serialP.h>
--- 1.2/arch/ppc/syslib/gen550_kgdb.c Fri Sep 12 09:26:55 2003
+++ edited/arch/ppc/syslib/gen550_kgdb.c Wed Jan 21 12:17:34 2004
@@ -74,10 +74,10 @@

/*
* Note: gen550_init() must be called already on the port we are going
- * to use.
+ * to use, or <asm/serial.h> must provide static definitions.
*/
void
-kgdb_map_scc(void)
+gen550_kgdb_map_scc(void)
{
printk(KERN_DEBUG "kgdb init\n");
kgdb_debugport = serial_init(KGDB_PORT, NULL);
--- 1.4/include/asm-ppc/kgdb.h Sun Sep 15 21:52:04 2002
+++ edited/include/asm-ppc/kgdb.h Wed Jan 21 12:17:34 2004
@@ -2,6 +2,8 @@
* kgdb.h: Defines and declarations for serial line source level
* remote debugging of the Linux kernel using gdb.
*
+ * PPC Mods (C) 2004 Tom Rini ([email protected])
+ * PPC Mods (C) 2003 John Whitney ([email protected])
* PPC Mods (C) 1998 Michael Tesch ([email protected])
*
* Copyright (C) 1995 David S. Miller ([email protected])
@@ -11,10 +13,23 @@
#define _PPC_KGDB_H

#ifndef __ASSEMBLY__
-/* To initialize the serial, first thing called */
+
+#define BREAK_INSTR_SIZE 4
+#define MAXREG (PT_FPSCR+1)
+#define NUMREGBYTES (MAXREG * sizeof(int))
+#define BUFMAX ((NUMREGBYTES * 2) + 512)
+#define OUTBUFMAX ((NUMREGBYTES * 2) + 512)
+#define BREAKPOINT() asm(".long 0x7d821008") /* twge r2, r2 */
+
+/* Things specific to the gen550 backend. */
+struct uart_port;
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_kgdb_map_scc(void);
+extern void gen550_init(int, struct uart_port *);
+
+/* Things specific to the pmac backend. */
extern void zs_kgdb_hook(int tty_num);
-/* To init the kgdb engine. (called by serial hook)*/
-extern void set_debug_traps(void);

/* To enter the debugger explicitly. */
extern void breakpoint(void);
--- 1.16/include/asm-ppc/machdep.h Wed Apr 23 00:49:34 2003
+++ edited/include/asm-ppc/machdep.h Wed Jan 21 12:17:34 2004
@@ -53,6 +53,7 @@
void (*setup_io_mappings)(void);

void (*progress)(char *, unsigned short);
+ void (*kgdb_map_scc)(void);

unsigned char (*nvram_read_val)(int addr);
void (*nvram_write_val)(int addr, unsigned char val);
--- 1.39/include/asm-ppc/processor.h Fri Sep 26 16:31:59 2003
+++ edited/include/asm-ppc/processor.h Wed Jan 21 12:17:34 2004
@@ -119,6 +119,9 @@
unsigned long vrsave;
int used_vr; /* set if process has used altivec */
#endif /* CONFIG_ALTIVEC */
+#ifdef CONFIG_KGDB
+ void *debuggerinfo;
+#endif
};

#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-21 19:24:36

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Wed, Jan 21, 2004 at 12:21:28PM -0700, Tom Rini wrote:
> On Wed, Jan 21, 2004 at 11:42:17AM -0700, Tom Rini wrote:
> > On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
> >
> > > Hi,
> > >
> > > Here it is: ppc kgdb from timesys kernel is available at
> > > http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
> > >
> > > This is my attempt at extracting kgdb from TimeSys kernel. It works well in
> > > TimeSys kernel, so blame me if above patch doesn't work.
> >
> > Okay, here's my first patch against this.
>
> And dependant upon this is a patch to fixup the rest of the common PPC
> code, as follows:

And on top of all of that is the following, which allows KGDB to work on
the Motorola LoPEC.

--- 1.48/arch/ppc/Kconfig Wed Jan 21 10:13:13 2004
+++ edited/arch/ppc/Kconfig Wed Jan 21 10:33:55 2004
@@ -583,11 +583,6 @@
depends on PPC_MULTIPLATFORM
default y

-config PPC_GEN550
- bool
- depends on SANDPOINT
- default y
-
config PPC_PMAC
bool
depends on PPC_MULTIPLATFORM
@@ -603,6 +598,11 @@
depends on PPC_PMAC || PPC_CHRP
default y

+config PPC_GEN550
+ bool
+ depends on SANDPOINT || MCPN765 || LOPEC
+ default y
+
config FORCE
bool
depends on 6xx && (PCORE || POWERPMC250)
--- 1.20/arch/ppc/platforms/lopec_setup.c Fri Sep 12 09:26:53 2003
+++ edited/arch/ppc/platforms/lopec_setup.c Wed Jan 21 10:32:15 2004
@@ -32,6 +32,7 @@
#include <asm/mpc10x.h>
#include <asm/hw_irq.h>
#include <asm/prep_nvram.h>
+#include <asm/kgdb.h>

extern char saved_command_line[];
extern void lopec_find_bridges(void);
@@ -261,44 +262,6 @@
: "=r" (batu), "=r" (batl));
}

-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
- SERIAL_PORT_DFNS /* Defined in <asm/serial.h> */
-};
-
-volatile unsigned char *com_port;
-volatile unsigned char *com_port_lsr;
-
-static void
-serial_writechar(char c)
-{
- while ((*com_port_lsr & UART_LSR_THRE) == 0)
- ;
- *com_port = c;
-}
-
-void
-lopec_progress(char *s, unsigned short hex)
-{
- volatile char c;
-
- com_port = (volatile unsigned char *) rs_table[0].port;
- com_port_lsr = com_port + UART_LSR;
-
- while ((c = *s++) != 0)
- serial_writechar(c);
-
- /* Most messages don't have a newline in them */
- serial_writechar('\n');
- serial_writechar('\r');
-}
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-
TODC_ALLOC();

static void __init
@@ -383,7 +346,10 @@
ppc_ide_md.default_io_base = lopec_ide_default_io_base;
ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports;
#endif
+#ifdef CONFIG_KGDB
+ ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
#ifdef CONFIG_SERIAL_TEXT_DEBUG
- ppc_md.progress = lopec_progress;
+ ppc_md.progress = gen550_progress;
#endif
}

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-21 22:03:52

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Wed, Jan 21, 2004 at 12:21:28PM -0700, Tom Rini wrote:
> On Wed, Jan 21, 2004 at 11:42:17AM -0700, Tom Rini wrote:
> > On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
> >
> > > Hi,
> > >
> > > Here it is: ppc kgdb from timesys kernel is available at
> > > http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
> > >
> > > This is my attempt at extracting kgdb from TimeSys kernel. It works well in
> > > TimeSys kernel, so blame me if above patch doesn't work.
> >
> > Okay, here's my first patch against this.
>
> And dependant upon this is a patch to fixup the rest of the common PPC
> code, as follows:

And this should have also been in this patch:

--- 1.49/arch/ppc/Kconfig Wed Jan 21 12:21:23 2004
+++ edited/arch/ppc/Kconfig Wed Jan 21 12:47:52 2004
@@ -1374,12 +1374,11 @@
this option if you do not want to compromise on speed.

config KGDB_CONSOLE
- bool "Enable serial console thru kgdb port"
- depends on KGDB && 8xx || 8260
+ bool "KGDB: Console messages through gdb"
+ depends on KGDB
help
- If you enable this, all serial console messages will be sent
- over the gdb stub.
- If unsure, say N.
+ If you say Y here, console messages will appear through gdb.
+ Other consoles such as tty or ttyS will continue to work as usual.

config XMON
bool "Include xmon kernel debugger"

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-21 23:06:26

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Tom Rini wrote:
> On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
>
>
>>Hi,
>>
>>Here it is: ppc kgdb from timesys kernel is available at
>>http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
>>
>>This is my attempt at extracting kgdb from TimeSys kernel. It works well in
>>TimeSys kernel, so blame me if above patch doesn't work.
>
>
> Okay, here's my first patch against this.
> ===== kernel/kgdbstub.c 1.1 vs edited =====
> --- 1.1/kernel/kgdbstub.c Wed Jan 21 10:13:17 2004
> +++ edited/kernel/kgdbstub.c Wed Jan 21 10:53:38 2004
> @@ -1058,9 +1058,6 @@
> kgdb_serial->write_char('+');
>
> linux_debug_hook = kgdb_handle_exception;
> -
> - if (kgdb_ops->kgdb_init)
> - kgdb_ops->kgdb_init();
>
> /* We can't do much if this fails */
> register_module_notifier(&kgdb_module_load_nb);
> @@ -1104,6 +1101,11 @@
> if (!kgdb_enter) {
> return;
> }
> +
> + /* Let the arch do any initalization it needs to */
> + if (kgdb_ops->kgdb_init)
> + kgdb_ops->kgdb_init();
> +
> if (!kgdb_serial) {
> printk("KGDB: no gdb interface available.\n"
> "kgdb can't be enabled\n");
>
> I'm not sure why you were calling the arch-specific init so late in the
> process, but since it's a nop on both i386 and x86_64 (so perhaps it
> should be removed for both of these?), this change doesn't matter to
> them. But it does make the PPC code cleaner, IMHO.

I agree. Lets dump all the init calls/code. I have not seen anything yet that
can not be done as a side effect of the first call, or better yet, at compile time.

I am willing to be shown a valid case, however. Remember, I want to be able to
do a breakpoint() as the first line of C code in the kernel. (works with the mm
kgdb).
>

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-01-21 23:13:24

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Tom Rini wrote:
> On Wed, Jan 21, 2004 at 11:42:17AM -0700, Tom Rini wrote:
>
>>On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
>>
>>
>>>Hi,
>>>
>>>Here it is: ppc kgdb from timesys kernel is available at
>>>http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
>>>
>>>This is my attempt at extracting kgdb from TimeSys kernel. It works well in
>>>TimeSys kernel, so blame me if above patch doesn't work.
>>
>>Okay, here's my first patch against this.
>
>
> And dependant upon this is a patch to fixup the rest of the common PPC
> code, as follows:
> - Add FRAME_POINTER
> - Put the bits of kgdbppc_init into ppc_kgdb_init.
> - None of the gen550 stuffs depend on CONFIG_8250_SERIAL directly,
> remove that constraint.
> - Add missing bits like debuggerinfo, BREAKPOINT, etc.
> - Add a kgdb_map_scc machdep pointer.
>
> --- 1.48/arch/ppc/Kconfig Wed Jan 21 10:13:13 2004
> +++ edited/arch/ppc/Kconfig Wed Jan 21 12:18:32 2004
> @@ -1405,6 +1405,14 @@
> Say Y here only if you plan to use some sort of debugger to
> debug the kernel.
> If you don't debug the kernel, you can say N.
> +
> +config FRAME_POINTER
> + bool "Compile the kernel with frame pointers"
> + help
> + If you say Y here the resulting kernel image will be slightly larger
> + and slower, but it will give very useful debugging information.
> + If you don't debug the kernel, you can say N, but we may not be able
> + to solve problems without frame pointers.

This is fast becoming old hat. If you compile with dwarf debug info, you not
only get more reliable frame info, but you do not need frame pointers. Gdb is
almost there. The languages have already arrived.

A question I have been meaning to ask: Why is the arch/common connection via a
structure of addresses instead of just calls? I seems to me that just calling
is a far cleaner way to do things here. All the struct seems to offer is a way
to change the backend on the fly. I don't thing we ever want to do that. Am I
missing something?

-g

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-01-22 15:07:28

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Wed, Jan 21, 2004 at 03:12:25PM -0800, George Anzinger wrote:
> Tom Rini wrote:
> >On Wed, Jan 21, 2004 at 11:42:17AM -0700, Tom Rini wrote:
> >
> >>On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
> >>
> >>
> >>>Hi,
> >>>
> >>>Here it is: ppc kgdb from timesys kernel is available at
> >>>http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
> >>>
> >>>This is my attempt at extracting kgdb from TimeSys kernel. It works well
> >>>in TimeSys kernel, so blame me if above patch doesn't work.
> >>
> >>Okay, here's my first patch against this.
> >
> >
> >And dependant upon this is a patch to fixup the rest of the common PPC
> >code, as follows:
> >- Add FRAME_POINTER
> >- Put the bits of kgdbppc_init into ppc_kgdb_init.
> >- None of the gen550 stuffs depend on CONFIG_8250_SERIAL directly,
> > remove that constraint.
> >- Add missing bits like debuggerinfo, BREAKPOINT, etc.
> >- Add a kgdb_map_scc machdep pointer.
> >
> >--- 1.48/arch/ppc/Kconfig Wed Jan 21 10:13:13 2004
> >+++ edited/arch/ppc/Kconfig Wed Jan 21 12:18:32 2004
> >@@ -1405,6 +1405,14 @@
> > Say Y here only if you plan to use some sort of debugger to
> > debug the kernel.
> > If you don't debug the kernel, you can say N.
> >+
> >+config FRAME_POINTER
> >+ bool "Compile the kernel with frame pointers"
> >+ help
> >+ If you say Y here the resulting kernel image will be slightly
> >larger
> >+ and slower, but it will give very useful debugging information.
> >+ If you don't debug the kernel, you can say N, but we may not be
> >able
> >+ to solve problems without frame pointers.
>
> This is fast becoming old hat. If you compile with dwarf debug info, you
> not only get more reliable frame info, but you do not need frame pointers.
> Gdb is almost there. The languages have already arrived.

My guess would be the miniumum toolchain requirements for i386/ppc (I
don't know x86_64) aren't all that new, so while gcc-3.3 probably gives
everything you describe, gcc-3.0 (which is valid for PPC, iirc) probably
doesn't.

> A question I have been meaning to ask: Why is the arch/common connection
> via a structure of addresses instead of just calls? I seems to me that
> just calling is a far cleaner way to do things here. All the struct seems
> to offer is a way to change the backend on the fly. I don't thing we ever
> want to do that. Am I missing something?

I imagine it's a style thing. I don't have a preference either way.

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-22 16:06:34

by Amit S. Kale

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Thursday 22 Jan 2004 9:15 pm, Tom Rini wrote:
> On Thu, Jan 22, 2004 at 09:25:19AM -0600, Hollis Blanchard wrote:
> > On Jan 22, 2004, at 9:07 AM, Tom Rini wrote:
> > >On Wed, Jan 21, 2004 at 03:12:25PM -0800, George Anzinger wrote:
> > >>A question I have been meaning to ask: Why is the arch/common
> > >>connection
> > >>via a structure of addresses instead of just calls? I seems to me
> > >>that
> > >>just calling is a far cleaner way to do things here. All the struct
> > >>seems
> > >>to offer is a way to change the backend on the fly. I don't thing we
> > >>ever
> > >>want to do that. Am I missing something?
> > >
> > >I imagine it's a style thing. I don't have a preference either way.
> >
> > I think we in PPC land have gotten used to that "style" because we have
> > one kernel that supports different "platforms", i.e. it selects the
> > appropriate code at runtime as George says. In general that's a little
> > bit slower and a little bit bigger.
> >
> > Unless you need to choose among PPC KGDB functions at runtime, which I
> > don't think you do, you don't need it...
>
> That's certainly true, so if (and if I understand Georges question
> right) Amit wants to change kgdb_arch into a set of required functions,
> with stubs in, say, kernel/kgdbdummy.c, (and just keep the flags / etc
> in the struct), that's fine with me.

The penalty of keeping them consolidated in a structure isn't so high. I
prefer to keep them that way. I'll work on reducing number of initialization
functions, though.

I have to do something about early connect though. Powerpc kgdb on 8260 is
definitely capable of starting debugging right at architecture setup time.
It's just that kgdbstub.c isn't ready yet.

How about changing the code in kgdbstub to allow kgdb to be configured in one
of the following ways:
Late kgdb - kgdb comes up after smp_init in the kernel boot sequence. kgdb8250
can be used with more flexibility through kernel command line options. One
can boot a kgdb kernel without activating kgdb. Works with the interface
chosen by kernel command line (kgdb8250 and kgdbeth for the moment).

Command line flexibilty is of great help if you have to test on 2-3 servers (I
used to do that a lot at Veritas). The same kernel can be compiled with
drivers needed by all of them plus kgdb. Command line options choose port no
and speeds depending on machine hardware connections. I guess it's of little
use on embedded systems where usually a new kernel has to be compiled for
each board.

Early kgdb - kgdb comes up right at the begining of start_kernel at the cost
of flexibility. It doesn't show any messages such as "waiting for gdb". All
configurations have to be compiled in through menuconfig. Once a kernel is
built, it'll always run with kgdb and with 8250 at a fixed port and speed.

i386 architecture will support both kgdb configuration.
KGDB in powerpc 8260 will be of early kgdb type. Other powerpc arches (550 etc
will depend on whether the interface can be initialized early or later)
--
Amit Kale
EmSysSoft (http://www.emsyssoft.com)
KGDB: Linux Kernel Source Level Debugger (http://kgdb.sourceforge.net)

2004-01-22 17:44:39

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Wed, Jan 21, 2004 at 12:22:30PM -0700, Tom Rini wrote:
> On Wed, Jan 21, 2004 at 12:21:28PM -0700, Tom Rini wrote:
> > On Wed, Jan 21, 2004 at 11:42:17AM -0700, Tom Rini wrote:
> > > On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
> > >
> > > > Hi,
> > > >
> > > > Here it is: ppc kgdb from timesys kernel is available at
> > > > http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
> > > >
> > > > This is my attempt at extracting kgdb from TimeSys kernel. It works well in
> > > > TimeSys kernel, so blame me if above patch doesn't work.
> > >
> > > Okay, here's my first patch against this.
> >
> > And dependant upon this is a patch to fixup the rest of the common PPC
> > code, as follows:
>
> And on top of all of that is the following, which allows KGDB to work on
> the Motorola LoPEC.

On top of everything from yesterday, here's:

Cleanup ppc-stub.c
- Lindent
- Redo boilerplate to match most other PPC files.
- Rearrange code so that we don't need forward declarations.

arch/ppc/kernel/ppc-stub.c | 184 ++++++++++++++++++++-------------------------
1 files changed, 83 insertions(+), 101 deletions(-)
--- 1.13/arch/ppc/kernel/ppc-stub.c Wed Jan 21 12:21:23 2004
+++ edited/arch/ppc/kernel/ppc-stub.c Thu Jan 22 10:40:55 2004
@@ -1,20 +1,13 @@
/*
+ * arch/ppc/kernel/ppc-stub.c
*
- * 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, or (at your option) 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.
+ * PowerPC-specific bits to work with the common KGDB stub.
*
- */
-
-/*
- * Copyright (C) 2003 Timesys Corporation.
- * KGDB for the PowerPC processor
+ * 2003 (c) TimeSys Corporation
+ * 2004 (c) MontaVista Software, Inc.
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
*/

#include <linux/kernel.h>
@@ -27,68 +20,56 @@
#include <asm/machdep.h>

/*
- * Forward prototypes
- */
-static void kgdb_debugger (struct pt_regs *regs);
-static int kgdb_breakpoint (struct pt_regs *regs);
-static int kgdb_singlestep (struct pt_regs *regs);
-static int ppc_kgdb_init (void);
-static void ppc_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs);
-static void ppc_sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p);
-static void ppc_gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs);
-void ppc_handler_exit (void);
-static int ppc_handle_exception (int vector,
- int signo,
- int err_code,
- char *remcomInBuffer,
- char *remcomOutBuffer,
- struct pt_regs *linux_regs);
-
-/*
* Routines
*/
-static void kgdb_debugger (struct pt_regs *regs)
+static void
+kgdb_debugger(struct pt_regs *regs)
{
(*linux_debug_hook) (0, 0, 0, regs);
return;
}

-static int kgdb_breakpoint (struct pt_regs *regs)
+static int
+kgdb_breakpoint(struct pt_regs *regs)
{
extern atomic_t kgdb_setting_breakpoint;

(*linux_debug_hook) (0, SIGTRAP, 0, regs);

- if (atomic_read (&kgdb_setting_breakpoint))
+ if (atomic_read(&kgdb_setting_breakpoint))
regs->nip += 4;

return 1;
}

-static int kgdb_singlestep (struct pt_regs *regs)
+static int
+kgdb_singlestep(struct pt_regs *regs)
{
(*linux_debug_hook) (0, SIGTRAP, 0, regs);
return 1;
}

-int kgdb_iabr_match(struct pt_regs *regs)
+int
+kgdb_iabr_match(struct pt_regs *regs)
{
(*linux_debug_hook) (0, 0, 0, regs);
return 1;
}

-int kgdb_dabr_match(struct pt_regs *regs)
+int
+kgdb_dabr_match(struct pt_regs *regs)
{
(*linux_debug_hook) (0, 0, 0, regs);
return 1;
}

-static void ppc_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+static void
+ppc_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
int reg;
unsigned long *ptr = gdb_regs;

- memset(gdb_regs, 0, MAXREG*4);
+ memset(gdb_regs, 0, MAXREG * 4);

for (reg = 0; reg < 32; reg++)
*(ptr++) = regs->gpr[reg];
@@ -104,16 +85,17 @@
*(ptr++) = regs->xer;

return;
-} /* regs_to_gdb_regs */
+} /* regs_to_gdb_regs */

-static void ppc_sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+static void
+ppc_sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
struct pt_regs *regs = (struct pt_regs *) (p->thread.ksp +
- STACK_FRAME_OVERHEAD);
+ STACK_FRAME_OVERHEAD);
int reg;
unsigned long *ptr = gdb_regs;

- memset(gdb_regs, 0, MAXREG*4);
+ memset(gdb_regs, 0, MAXREG * 4);

/* Regs GPR0-2 */
for (reg = 0; reg < 3; reg++)
@@ -140,7 +122,8 @@
return;
}

-static void ppc_gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+static void
+ppc_gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
int reg;
unsigned long *ptr = gdb_regs;
@@ -159,96 +142,81 @@
regs->xer = *(ptr++);

return;
-} /* gdb_regs_to_regs */
-
+} /* gdb_regs_to_regs */

/* exit_handler:
*
* This is called by the generic layer when it is about to return from
* the exception handler
*/
-void ppc_handler_exit (void)
+void
+ppc_handler_exit(void)
{
-// flush_instruction_cache ();
+// flush_instruction_cache ();
return;
}

-
/*
* This function does PoerPC specific procesing for interfacing to gdb.
*/
-static int ppc_handle_exception (int vector,
- int signo,
- int err_code,
- char *remcomInBuffer,
- char *remcomOutBuffer,
- struct pt_regs *linux_regs)
+static int
+ppc_handle_exception(int vector,
+ int signo,
+ int err_code,
+ char *remcomInBuffer,
+ char *remcomOutBuffer, struct pt_regs *linux_regs)
{
char *ptr;
unsigned long addr;
-
- switch (remcomInBuffer[0])
- {
+
+ switch (remcomInBuffer[0]) {
/*
* sAA..AA Step one instruction from AA..AA
* This will return an error to gdb ..
*/
- case 's':
- case 'c':
- if (kgdb_contthread && kgdb_contthread != current)
- {
- strcpy(remcomOutBuffer, "E00");
- break;
- }
-
- kgdb_contthread = NULL;
-
- /* handle the optional parameter */
- ptr = &remcomInBuffer[1];
- if (kgdb_hexToLong (&ptr, &addr))
- linux_regs->nip = addr;
-
- /* set the trace bit if we're stepping */
- if (remcomInBuffer[0] == 's')
- {
+ case 's':
+ case 'c':
+ if (kgdb_contthread && kgdb_contthread != current) {
+ strcpy(remcomOutBuffer, "E00");
+ break;
+ }
+
+ kgdb_contthread = NULL;
+
+ /* handle the optional parameter */
+ ptr = &remcomInBuffer[1];
+ if (kgdb_hexToLong(&ptr, &addr))
+ linux_regs->nip = addr;
+
+ /* set the trace bit if we're stepping */
+ if (remcomInBuffer[0] == 's') {
#if defined (CONFIG_4xx)
- linux_regs->msr |= MSR_DE;
- current->thread.dbcr0 |= (DBCR_IDM | DBCR_IC);
+ linux_regs->msr |= MSR_DE;
+ current->thread.dbcr0 |= (DBCR_IDM | DBCR_IC);
#else
- linux_regs->msr |= MSR_SE;
+ linux_regs->msr |= MSR_SE;
#endif
- }
- return 0;
+ }
+ return 0;
}

return -1;
}

-/*
- * Global data
- */
-struct kgdb_arch arch_kgdb_ops =
-{
- .gdb_bpt_instr = { 0x7d, 0x82, 0x10, 0x08 },
- .kgdb_init = ppc_kgdb_init,
- .regs_to_gdb_regs = ppc_regs_to_gdb_regs,
- .sleeping_thread_to_gdb_regs = ppc_sleeping_thread_to_gdb_regs,
- .gdb_regs_to_regs = ppc_gdb_regs_to_regs,
- .handle_exception = ppc_handle_exception,
- .handler_exit = ppc_handler_exit,
-};
-
-static void kgdbppc_write_char(int chr)
+static void
+kgdbppc_write_char(int chr)
{
putDebugChar(chr);
}

-static int kgdbppc_read_char(void)
+static int
+kgdbppc_read_char(void)
{
return getDebugChar();
}

-static int kgdbppc_hook(void)
+static int
+kgdbppc_hook(void)
{
if (ppc_md.kgdb_map_scc)
ppc_md.kgdb_map_scc();
@@ -261,7 +229,8 @@
.hook = kgdbppc_hook
};

-static int ppc_kgdb_init (void)
+static int
+ppc_kgdb_init(void)
{
debugger = kgdb_debugger;
debugger_bpt = kgdb_breakpoint;
@@ -272,5 +241,18 @@
kgdb_serial = &kgdbppc_serial;

return 0;
-
+
}
+
+/*
+ * Global data
+ */
+struct kgdb_arch arch_kgdb_ops = {
+ .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
+ .kgdb_init = ppc_kgdb_init,
+ .regs_to_gdb_regs = ppc_regs_to_gdb_regs,
+ .sleeping_thread_to_gdb_regs = ppc_sleeping_thread_to_gdb_regs,
+ .gdb_regs_to_regs = ppc_gdb_regs_to_regs,
+ .handle_exception = ppc_handle_exception,
+ .handler_exit = ppc_handler_exit,
+};

I'll have some functional changes that apply on top of this soon.

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-22 15:45:42

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Thu, Jan 22, 2004 at 09:25:19AM -0600, Hollis Blanchard wrote:
> On Jan 22, 2004, at 9:07 AM, Tom Rini wrote:
> >
> >On Wed, Jan 21, 2004 at 03:12:25PM -0800, George Anzinger wrote:
> >
> >>A question I have been meaning to ask: Why is the arch/common
> >>connection
> >>via a structure of addresses instead of just calls? I seems to me
> >>that
> >>just calling is a far cleaner way to do things here. All the struct
> >>seems
> >>to offer is a way to change the backend on the fly. I don't thing we
> >>ever
> >>want to do that. Am I missing something?
> >
> >I imagine it's a style thing. I don't have a preference either way.
>
> I think we in PPC land have gotten used to that "style" because we have
> one kernel that supports different "platforms", i.e. it selects the
> appropriate code at runtime as George says. In general that's a little
> bit slower and a little bit bigger.
>
> Unless you need to choose among PPC KGDB functions at runtime, which I
> don't think you do, you don't need it...

That's certainly true, so if (and if I understand Georges question
right) Amit wants to change kgdb_arch into a set of required functions,
with stubs in, say, kernel/kgdbdummy.c, (and just keep the flags / etc
in the struct), that's fine with me.

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-22 16:45:35

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Thu, Jan 22, 2004 at 09:36:10PM +0530, Amit S. Kale wrote:
> On Thursday 22 Jan 2004 9:15 pm, Tom Rini wrote:
> > On Thu, Jan 22, 2004 at 09:25:19AM -0600, Hollis Blanchard wrote:
> > > On Jan 22, 2004, at 9:07 AM, Tom Rini wrote:
> > > >On Wed, Jan 21, 2004 at 03:12:25PM -0800, George Anzinger wrote:
> > > >>A question I have been meaning to ask: Why is the arch/common
> > > >>connection
> > > >>via a structure of addresses instead of just calls? I seems to me
> > > >>that
> > > >>just calling is a far cleaner way to do things here. All the struct
> > > >>seems
> > > >>to offer is a way to change the backend on the fly. I don't thing we
> > > >>ever
> > > >>want to do that. Am I missing something?
> > > >
> > > >I imagine it's a style thing. I don't have a preference either way.
> > >
> > > I think we in PPC land have gotten used to that "style" because we have
> > > one kernel that supports different "platforms", i.e. it selects the
> > > appropriate code at runtime as George says. In general that's a little
> > > bit slower and a little bit bigger.
> > >
> > > Unless you need to choose among PPC KGDB functions at runtime, which I
> > > don't think you do, you don't need it...
> >
> > That's certainly true, so if (and if I understand Georges question
> > right) Amit wants to change kgdb_arch into a set of required functions,
> > with stubs in, say, kernel/kgdbdummy.c, (and just keep the flags / etc
> > in the struct), that's fine with me.
>
> The penalty of keeping them consolidated in a structure isn't so high. I
> prefer to keep them that way. I'll work on reducing number of initialization
> functions, though.
>
> I have to do something about early connect though. Powerpc kgdb on 8260 is
> definitely capable of starting debugging right at architecture setup time.
> It's just that kgdbstub.c isn't ready yet.

FWIW, this is true of KGDB on all PPCs. IIRC, so long as the serial
definitions are filled out statically, the stub currently in kernel.org
for PPC can do first-line-of-C already.

> How about changing the code in kgdbstub to allow kgdb to be configured in one
> of the following ways:
> Late kgdb - kgdb comes up after smp_init in the kernel boot sequence. kgdb8250
> can be used with more flexibility through kernel command line options. One
> can boot a kgdb kernel without activating kgdb. Works with the interface
> chosen by kernel command line (kgdb8250 and kgdbeth for the moment).

Which is basically how it goes now, right?

> Early kgdb - kgdb comes up right at the begining of start_kernel at the cost
> of flexibility. It doesn't show any messages such as "waiting for gdb". All
> configurations have to be compiled in through menuconfig. Once a kernel is
> built, it'll always run with kgdb and with 8250 at a fixed port and speed.
>
> i386 architecture will support both kgdb configuration.
> KGDB in powerpc 8260 will be of early kgdb type. Other powerpc arches (550 etc
> will depend on whether the interface can be initialized early or later)

Again, there is nothing special about KGDB on 82xx (or 8xx for that
matter) over classic PPCs (which tend to have a 550, but this is not
always the case) or 4xx.

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-22 15:27:58

by Hollis Blanchard

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Jan 22, 2004, at 9:07 AM, Tom Rini wrote:
>
> On Wed, Jan 21, 2004 at 03:12:25PM -0800, George Anzinger wrote:
>
>> A question I have been meaning to ask: Why is the arch/common
>> connection
>> via a structure of addresses instead of just calls? I seems to me
>> that
>> just calling is a far cleaner way to do things here. All the struct
>> seems
>> to offer is a way to change the backend on the fly. I don't thing we
>> ever
>> want to do that. Am I missing something?
>
> I imagine it's a style thing. I don't have a preference either way.

I think we in PPC land have gotten used to that "style" because we have
one kernel that supports different "platforms", i.e. it selects the
appropriate code at runtime as George says. In general that's a little
bit slower and a little bit bigger.

Unless you need to choose among PPC KGDB functions at runtime, which I
don't think you do, you don't need it...

--
Hollis Blanchard
IBM Linux Technology Center

2004-01-22 23:09:59

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Tom Rini wrote:
> On Thu, Jan 22, 2004 at 02:46:41PM -0800, George Anzinger wrote:
>
>>Tom Rini wrote:
>>
>>>
>>>FWIW, this is true of KGDB on all PPCs. IIRC, so long as the serial
>>>definitions are filled out statically, the stub currently in kernel.org
>>>for PPC can do first-line-of-C already.
>>>
>>>
>>>
>>>>How about changing the code in kgdbstub to allow kgdb to be configured in
>>>>one of the following ways:
>>>>Late kgdb - kgdb comes up after smp_init in the kernel boot sequence.
>>>>kgdb8250 can be used with more flexibility through kernel command line
>>>>options. One can boot a kgdb kernel without activating kgdb. Works with
>>>>the interface chosen by kernel command line (kgdb8250 and kgdbeth for the
>>>>moment).
>>
>>A further thought on this. I think kgdb should take control on oops, panic
>>and other bad news things. This without being anthing but configured in.
>>Thus the command line options to set up the interface, etc, should not
>>automatically connect to gdb.
>
>
> *confused look* it doesn't do this already on i386? I'm fairly certain
> that it does on PPC, regardless of the stub (since I've got this wierd
> panic happening on my testbox right now, but kgdb is kicking in..)
>
Oh, I think it does, but I have seen code that I thought (possibly incorrectly)
tried to connect to gdb as part of configuring the interface. This is what I
don't want to see.

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-01-22 22:52:22

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Thu, Jan 22, 2004 at 02:46:41PM -0800, George Anzinger wrote:
> Tom Rini wrote:
> >
> >
> >FWIW, this is true of KGDB on all PPCs. IIRC, so long as the serial
> >definitions are filled out statically, the stub currently in kernel.org
> >for PPC can do first-line-of-C already.
> >
> >
> >>How about changing the code in kgdbstub to allow kgdb to be configured in
> >>one of the following ways:
> >>Late kgdb - kgdb comes up after smp_init in the kernel boot sequence.
> >>kgdb8250 can be used with more flexibility through kernel command line
> >>options. One can boot a kgdb kernel without activating kgdb. Works with
> >>the interface chosen by kernel command line (kgdb8250 and kgdbeth for the
> >>moment).
>
> A further thought on this. I think kgdb should take control on oops, panic
> and other bad news things. This without being anthing but configured in.
> Thus the command line options to set up the interface, etc, should not
> automatically connect to gdb.

*confused look* it doesn't do this already on i386? I'm fairly certain
that it does on PPC, regardless of the stub (since I've got this wierd
panic happening on my testbox right now, but kgdb is kicking in..)

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-22 15:03:57

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Wed, Jan 21, 2004 at 03:05:54PM -0800, George Anzinger wrote:
> Tom Rini wrote:
> >On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
> >
> >
> >>Hi,
> >>
> >>Here it is: ppc kgdb from timesys kernel is available at
> >>http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
> >>
> >>This is my attempt at extracting kgdb from TimeSys kernel. It works well
> >>in TimeSys kernel, so blame me if above patch doesn't work.
> >
> >
> >Okay, here's my first patch against this.
> >===== kernel/kgdbstub.c 1.1 vs edited =====
> >--- 1.1/kernel/kgdbstub.c Wed Jan 21 10:13:17 2004
> >+++ edited/kernel/kgdbstub.c Wed Jan 21 10:53:38 2004
> >@@ -1058,9 +1058,6 @@
> > kgdb_serial->write_char('+');
> >
> > linux_debug_hook = kgdb_handle_exception;
> >-
> >- if (kgdb_ops->kgdb_init)
> >- kgdb_ops->kgdb_init();
> >
> > /* We can't do much if this fails */
> > register_module_notifier(&kgdb_module_load_nb);
> >@@ -1104,6 +1101,11 @@
> > if (!kgdb_enter) {
> > return;
> > }
> >+
> >+ /* Let the arch do any initalization it needs to */
> >+ if (kgdb_ops->kgdb_init)
> >+ kgdb_ops->kgdb_init();
> >+
> > if (!kgdb_serial) {
> > printk("KGDB: no gdb interface available.\n"
> > "kgdb can't be enabled\n");
> >
> >I'm not sure why you were calling the arch-specific init so late in the
> >process, but since it's a nop on both i386 and x86_64 (so perhaps it
> >should be removed for both of these?), this change doesn't matter to
> >them. But it does make the PPC code cleaner, IMHO.
>
> I agree. Lets dump all the init calls/code. I have not seen anything yet
> that can not be done as a side effect of the first call, or better yet, at
> compile time.
>
> I am willing to be shown a valid case, however. Remember, I want to be
> able to do a breakpoint() as the first line of C code in the kernel.
> (works with the mm kgdb).

How would you propose handling what's done in ppc_kgdb_init ? I could
make it a __setup, ala how kgdb_8250.c works, but that too won't allow
for 'first line of C'. OTOH, if breakpoint did:
if (!kgdb_initalized) {
... work of kgdb_entry() ...
}
... normal breakpoint() code ...

PPC would be fine, as would other arches which need to do some setup.

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-22 21:55:35

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Tom Rini wrote:
> On Thu, Jan 22, 2004 at 09:25:19AM -0600, Hollis Blanchard wrote:
>
>>On Jan 22, 2004, at 9:07 AM, Tom Rini wrote:
>>
>>>On Wed, Jan 21, 2004 at 03:12:25PM -0800, George Anzinger wrote:
>>>
>>>
>>>>A question I have been meaning to ask: Why is the arch/common
>>>>connection
>>>>via a structure of addresses instead of just calls? I seems to me
>>>>that
>>>>just calling is a far cleaner way to do things here. All the struct
>>>>seems
>>>>to offer is a way to change the backend on the fly. I don't thing we
>>>>ever
>>>>want to do that. Am I missing something?
>>>
>>>I imagine it's a style thing. I don't have a preference either way.
>>
>>I think we in PPC land have gotten used to that "style" because we have
>>one kernel that supports different "platforms", i.e. it selects the
>>appropriate code at runtime as George says. In general that's a little
>>bit slower and a little bit bigger.
>>
>>Unless you need to choose among PPC KGDB functions at runtime, which I
>>don't think you do, you don't need it...
>
>
> That's certainly true, so if (and if I understand Georges question
> right) Amit wants to change kgdb_arch into a set of required functions,
> with stubs in, say, kernel/kgdbdummy.c, (and just keep the flags / etc
> in the struct), that's fine with me.

Something like that. I would make use of the weak external to handle the stub
connection, i.e. the common code would define the stubs as weak functions. The
linker will choose a normal over a weak so it makes the right connection.
>

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-01-22 22:36:22

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Amit S. Kale wrote:
> On Thursday 22 Jan 2004 9:15 pm, Tom Rini wrote:
>
>>On Thu, Jan 22, 2004 at 09:25:19AM -0600, Hollis Blanchard wrote:
>>
>>>On Jan 22, 2004, at 9:07 AM, Tom Rini wrote:
>>>
>>>>On Wed, Jan 21, 2004 at 03:12:25PM -0800, George Anzinger wrote:
>>>>
>>>>>A question I have been meaning to ask: Why is the arch/common
>>>>>connection
>>>>>via a structure of addresses instead of just calls? I seems to me
>>>>>that
>>>>>just calling is a far cleaner way to do things here. All the struct
>>>>>seems
>>>>>to offer is a way to change the backend on the fly. I don't thing we
>>>>>ever
>>>>>want to do that. Am I missing something?
>>>>
>>>>I imagine it's a style thing. I don't have a preference either way.
>>>
>>>I think we in PPC land have gotten used to that "style" because we have
>>>one kernel that supports different "platforms", i.e. it selects the
>>>appropriate code at runtime as George says. In general that's a little
>>>bit slower and a little bit bigger.
>>>
>>>Unless you need to choose among PPC KGDB functions at runtime, which I
>>>don't think you do, you don't need it...
>>
>>That's certainly true, so if (and if I understand Georges question
>>right) Amit wants to change kgdb_arch into a set of required functions,
>>with stubs in, say, kernel/kgdbdummy.c, (and just keep the flags / etc
>>in the struct), that's fine with me.
>
>
> The penalty of keeping them consolidated in a structure isn't so high. I
> prefer to keep them that way. I'll work on reducing number of initialization
> functions, though.
>
> I have to do something about early connect though. Powerpc kgdb on 8260 is
> definitely capable of starting debugging right at architecture setup time.
> It's just that kgdbstub.c isn't ready yet.
>
> How about changing the code in kgdbstub to allow kgdb to be configured in one
> of the following ways:
> Late kgdb - kgdb comes up after smp_init in the kernel boot sequence. kgdb8250
> can be used with more flexibility through kernel command line options. One
> can boot a kgdb kernel without activating kgdb. Works with the interface
> chosen by kernel command line (kgdb8250 and kgdbeth for the moment).

If we get to kgdb via a command line, we should be able to have all the command
line options. I do recommend that we choose where we put the code, however.
Some command line options are looked at FAR later in the boot. The order of the
command line option dispatch is the same as the link order. This is why mm kgdb
has the command line stuff in include/asm/bugs.h (actually this file is only
included by one .c file). This, by the way, is way before the console starts
spewing boot stuff (or is available) so no messages here. Usually one would
only do this by hand so it is real clear what is happening.

Any thing earlier than this should, IMHO, only happen if the user hard codes a
breakpoint() (which by the way, is not the same as BREAKPOINT, which is an
instruction, while breakpoint() is a function). In the x86 kernel with the mm
kgdb all that this function needs to do is to set up the trap vector for single
steps and breakpoint instructions. I think I also set up one or two others just
to be safe. This code can be redone, so no test is made to see if it has
already been done.

I reading some of the comments here, I get the impression that some kgdbs try to
connect when nothing is wrong and no command line request has been made to do
so. I think this should not be done.
>
> Command line flexibilty is of great help if you have to test on 2-3 servers (I
> used to do that a lot at Veritas). The same kernel can be compiled with
> drivers needed by all of them plus kgdb. Command line options choose port no
> and speeds depending on machine hardware connections. I guess it's of little
> use on embedded systems where usually a new kernel has to be compiled for
> each board.
>
> Early kgdb - kgdb comes up right at the begining of start_kernel at the cost
> of flexibility. It doesn't show any messages such as "waiting for gdb". All
> configurations have to be compiled in through menuconfig. Once a kernel is
> built, it'll always run with kgdb and with 8250 at a fixed port and speed.

But this would only be used if the user hard coded a break point. It is useful,
but early command line is, most of the time, good enough. I guess the concern I
have here is that you are saying either or and I want both from the same
configuration.
>
> i386 architecture will support both kgdb configuration.
> KGDB in powerpc 8260 will be of early kgdb type. Other powerpc arches (550 etc
> will depend on whether the interface can be initialized early or later)

I would hope that there will always be something we can use. Most cards have
serial ports...


--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-01-22 18:06:26

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Thu, Jan 22, 2004 at 10:44:16AM -0700, Tom Rini wrote:
> On Wed, Jan 21, 2004 at 12:22:30PM -0700, Tom Rini wrote:
> > On Wed, Jan 21, 2004 at 12:21:28PM -0700, Tom Rini wrote:
> > > On Wed, Jan 21, 2004 at 11:42:17AM -0700, Tom Rini wrote:
> > > > On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
> > > >
> > > > > Hi,
> > > > >
> > > > > Here it is: ppc kgdb from timesys kernel is available at
> > > > > http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
> > > > >
> > > > > This is my attempt at extracting kgdb from TimeSys kernel. It works well in
> > > > > TimeSys kernel, so blame me if above patch doesn't work.
> > > >
> > > > Okay, here's my first patch against this.
> > >
> > > And dependant upon this is a patch to fixup the rest of the common PPC
> > > code, as follows:
> >
> > And on top of all of that is the following, which allows KGDB to work on
> > the Motorola LoPEC.
>
> On top of everything from yesterday, here's:

First up:
We need to call flush_instruction_cache() on a 'c' or 's' command.
arch/ppc/kernel/ppc-stub.c | 19 ++++++-------------
1 files changed, 6 insertions(+), 13 deletions(-)
--- 1.14/arch/ppc/kernel/ppc-stub.c Thu Jan 22 10:41:58 2004
+++ edited/arch/ppc/kernel/ppc-stub.c Thu Jan 22 10:49:30 2004
@@ -144,18 +144,6 @@
return;
} /* gdb_regs_to_regs */

-/* exit_handler:
- *
- * This is called by the generic layer when it is about to return from
- * the exception handler
- */
-void
-ppc_handler_exit(void)
-{
-// flush_instruction_cache ();
- return;
-}
-
/*
* This function does PoerPC specific procesing for interfacing to gdb.
*/
@@ -188,6 +176,12 @@
if (kgdb_hexToLong(&ptr, &addr))
linux_regs->nip = addr;

+/* Need to flush the instruction cache here, as we may have deposited a
+ * breakpoint, and the icache probably has no way of knowing that a data ref to
+ * some location may have changed something that is in the instruction cache.
+ */
+ flush_instruction_cache();
+
/* set the trace bit if we're stepping */
if (remcomInBuffer[0] == 's') {
#if defined (CONFIG_4xx)
@@ -254,5 +248,4 @@
.sleeping_thread_to_gdb_regs = ppc_sleeping_thread_to_gdb_regs,
.gdb_regs_to_regs = ppc_gdb_regs_to_regs,
.handle_exception = ppc_handle_exception,
- .handler_exit = ppc_handler_exit,
};

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-22 22:47:12

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Tom Rini wrote:
>
>
> FWIW, this is true of KGDB on all PPCs. IIRC, so long as the serial
> definitions are filled out statically, the stub currently in kernel.org
> for PPC can do first-line-of-C already.
>
>
>>How about changing the code in kgdbstub to allow kgdb to be configured in one
>>of the following ways:
>>Late kgdb - kgdb comes up after smp_init in the kernel boot sequence. kgdb8250
>>can be used with more flexibility through kernel command line options. One
>>can boot a kgdb kernel without activating kgdb. Works with the interface
>>chosen by kernel command line (kgdb8250 and kgdbeth for the moment).
>
A further thought on this. I think kgdb should take control on oops, panic and
other bad news things. This without being anthing but configured in. Thus the
command line options to set up the interface, etc, should not automatically
connect to gdb.
>
> Which is basically how it goes now, right?
>
>
>>Early kgdb - kgdb comes up right at the begining of start_kernel at the cost
>>of flexibility. It doesn't show any messages such as "waiting for gdb".

I question the utility of ever using this message. Either the user has asked
for the connection, either via a ^C or the command line or a breakpoint was hit.
If he asked, why tell him? If it is a breakpoint, it is foolish and dangerous
to call any outside function, such as printk.

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-01-23 17:08:39

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Thu, Jan 22, 2004 at 09:36:10PM +0530, Amit S. Kale wrote:

> On Thursday 22 Jan 2004 9:15 pm, Tom Rini wrote:
> > On Thu, Jan 22, 2004 at 09:25:19AM -0600, Hollis Blanchard wrote:
> > > On Jan 22, 2004, at 9:07 AM, Tom Rini wrote:
> > > >On Wed, Jan 21, 2004 at 03:12:25PM -0800, George Anzinger wrote:
> > > >>A question I have been meaning to ask: Why is the arch/common
> > > >>connection
> > > >>via a structure of addresses instead of just calls? I seems to me
> > > >>that
> > > >>just calling is a far cleaner way to do things here. All the struct
> > > >>seems
> > > >>to offer is a way to change the backend on the fly. I don't thing we
> > > >>ever
> > > >>want to do that. Am I missing something?
> > > >
> > > >I imagine it's a style thing. I don't have a preference either way.
> > >
> > > I think we in PPC land have gotten used to that "style" because we have
> > > one kernel that supports different "platforms", i.e. it selects the
> > > appropriate code at runtime as George says. In general that's a little
> > > bit slower and a little bit bigger.
> > >
> > > Unless you need to choose among PPC KGDB functions at runtime, which I
> > > don't think you do, you don't need it...
> >
> > That's certainly true, so if (and if I understand Georges question
> > right) Amit wants to change kgdb_arch into a set of required functions,
> > with stubs in, say, kernel/kgdbdummy.c, (and just keep the flags / etc
> > in the struct), that's fine with me.
>
> The penalty of keeping them consolidated in a structure isn't so high. I
> prefer to keep them that way. I'll work on reducing number of initialization
> functions, though.

Ok. After talking with George off-list, I think most of ppc_kgdb_init
can go. The only remaining part is the serial plugin, which could be
done ala the kgdb_8250 driver. But I've got a different idea:

arch/ppc/kernel/ppc-stub.c | 3 +--
drivers/serial/kgdb_8250.c | 4 +---
kernel/kgdbstub.c | 2 +-
3 files changed, 3 insertions(+), 6 deletions(-)
--- kernel/kgdbstub.c 2004-01-23 10:03:48.000000000 -0700
+++ kernel/kgdbstub.c 2004-01-23 10:06:19.000000000 -0700
@@ -61,7 +61,7 @@
gdb_breakpoint_t kgdb_break[MAX_BREAKPOINTS];
extern int pid_max;

-struct kgdb_serial *kgdb_serial;
+struct kgdb_serial *kgdb_serial = &kgdb_serial_driver;

int kgdb_initialized = 0;
int kgdb_enter = 0;
--- drivers/serial/kgdb_8250.c 2004-01-23 10:04:57.000000000 -0700
+++ drivers/serial/kgdb_8250.c 2004-01-23 09:57:26.000000000 -0700
@@ -370,7 +370,7 @@
rs_table[i].regshift = serial_req->regshift;
}

-struct kgdb_serial kgdb8250_serial = {
+struct kgdb_serial kgdb_serial_driver = {
.read_char = kgdb8250_read_char,
.write_char = kgdb8250_write_char,
.hook = kgdb8250_hook
@@ -396,8 +396,6 @@
kgdb8250_baud != 115200)
goto errout;

- kgdb_serial = &kgdb8250_serial;
-
return 1;

errout:
--- arch/ppc/kernel/ppc-stub.c 2004-01-23 10:04:46.000000000 -0700
+++ arch/ppc/kernel/ppc-stub.c 2004-01-23 09:57:47.000000000 -0700
@@ -264,7 +264,7 @@
return 0;
}

-struct kgdb_serial kgdbppc_serial = {
+struct kgdb_serial kgdb_serial_driver = {
.read_char = kgdbppc_read_char,
.write_char = kgdbppc_write_char,
.hook = kgdbppc_hook
@@ -272,5 +272,4 @@

void kgdbppc_init(void)
{
- kgdb_serial = &kgdbppc_serial;
}

This does mean that we can only have one serial driver per kernel, but I
don't see this as a problem. This also means that i386 would need
something like PPC's CONFIG_KGDB_TTYSx to pick something other than
ttyS0/115200 to use kgdb on, this early. But, IMHO, that's a small
price to pay.

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-23 22:46:24

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Thu, Jan 22, 2004 at 11:05:55AM -0700, Tom Rini wrote:
[snip]
> First up:
> We need to call flush_instruction_cache() on a 'c' or 's' command.
> arch/ppc/kernel/ppc-stub.c | 19 ++++++-------------
> 1 files changed, 6 insertions(+), 13 deletions(-)

On tpo of this patch, there's the following:
Put back some code to figure out what signal we're dealing with.

arch/ppc/kernel/ppc-stub.c | 63 ++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 60 insertions(+), 3 deletions(-)
--- 1.15/arch/ppc/kernel/ppc-stub.c Thu Jan 22 10:53:06 2004
+++ edited/arch/ppc/kernel/ppc-stub.c Fri Jan 23 15:43:10 2004
@@ -3,6 +3,7 @@
*
* PowerPC-specific bits to work with the common KGDB stub.
*
+ * 1998 (c) Michael AK Tesch ([email protected])
* 2003 (c) TimeSys Corporation
* 2004 (c) MontaVista Software, Inc.
* This file is licensed under the terms of the GNU General Public License
@@ -19,13 +20,69 @@
#include <asm/processor.h>
#include <asm/machdep.h>

+/* Convert the hardware trap type code to a unix signal number. */
+/*
+ * This table contains the mapping between PowerPC hardware trap types, and
+ * signals, which are primarily what GDB understands.
+ */
+static struct hard_trap_info
+{
+ unsigned int tt; /* Trap type code for powerpc */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+#if defined(CONFIG_40x)
+ { 0x100, SIGINT }, /* critical input interrupt */
+ { 0x200, SIGSEGV }, /* machine check */
+ { 0x300, SIGSEGV }, /* data storage */
+ { 0x400, SIGBUS }, /* instruction storage */
+ { 0x500, SIGINT }, /* interrupt */
+ { 0x600, SIGBUS }, /* alignment */
+ { 0x700, SIGILL }, /* program */
+ { 0x800, SIGILL }, /* reserved */
+ { 0x900, SIGILL }, /* reserved */
+ { 0xa00, SIGILL }, /* reserved */
+ { 0xb00, SIGILL }, /* reserved */
+ { 0xc00, SIGCHLD }, /* syscall */
+ { 0xd00, SIGILL }, /* reserved */
+ { 0xe00, SIGILL }, /* reserved */
+ { 0xf00, SIGILL }, /* reserved */
+ { 0x2000, SIGTRAP}, /* debug */
+#else
+ { 0x200, SIGSEGV }, /* machine check */
+ { 0x300, SIGSEGV }, /* address error (store) */
+ { 0x400, SIGBUS }, /* instruction bus error */
+ { 0x500, SIGINT }, /* interrupt */
+ { 0x600, SIGBUS }, /* alingment */
+ { 0x700, SIGTRAP }, /* breakpoint trap */
+ { 0x800, SIGFPE }, /* fpu unavail */
+ { 0x900, SIGALRM }, /* decrementer */
+ { 0xa00, SIGILL }, /* reserved */
+ { 0xb00, SIGILL }, /* reserved */
+ { 0xc00, SIGCHLD }, /* syscall */
+ { 0xd00, SIGTRAP }, /* single-step/watch */
+ { 0xe00, SIGFPE }, /* fp assist */
+#endif
+ { 0, 0} /* Must be last */
+};
+
+static int computeSignal(unsigned int tt)
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
/*
* Routines
*/
static void
kgdb_debugger(struct pt_regs *regs)
{
- (*linux_debug_hook) (0, 0, 0, regs);
+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
return;
}

@@ -52,14 +109,14 @@
int
kgdb_iabr_match(struct pt_regs *regs)
{
- (*linux_debug_hook) (0, 0, 0, regs);
+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
return 1;
}

int
kgdb_dabr_match(struct pt_regs *regs)
{
- (*linux_debug_hook) (0, 0, 0, regs);
+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
return 1;
}


Now, not being as well versed in all of the debugging infos that can be
passed around, it sounds like this patch could be dropped in the future
for a cleaner method using some of the dwarf2 bits being talked about.
But I don't know, and clarification and pointers (if so) to how to do
this would be appreciated.

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-23 23:39:23

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Tom Rini wrote:
> On Thu, Jan 22, 2004 at 11:05:55AM -0700, Tom Rini wrote:
> [snip]
>
>>First up:
>>We need to call flush_instruction_cache() on a 'c' or 's' command.
>> arch/ppc/kernel/ppc-stub.c | 19 ++++++-------------
>> 1 files changed, 6 insertions(+), 13 deletions(-)
>
>
> On tpo of this patch, there's the following:
> Put back some code to figure out what signal we're dealing with.
>
> arch/ppc/kernel/ppc-stub.c | 63 ++++++++++++++++++++++++++++++++++++++++++---
> 1 files changed, 60 insertions(+), 3 deletions(-)
> --- 1.15/arch/ppc/kernel/ppc-stub.c Thu Jan 22 10:53:06 2004
> +++ edited/arch/ppc/kernel/ppc-stub.c Fri Jan 23 15:43:10 2004
> @@ -3,6 +3,7 @@
> *
> * PowerPC-specific bits to work with the common KGDB stub.
> *
> + * 1998 (c) Michael AK Tesch ([email protected])
> * 2003 (c) TimeSys Corporation
> * 2004 (c) MontaVista Software, Inc.
> * This file is licensed under the terms of the GNU General Public License
> @@ -19,13 +20,69 @@
> #include <asm/processor.h>
> #include <asm/machdep.h>
>
> +/* Convert the hardware trap type code to a unix signal number. */
> +/*
> + * This table contains the mapping between PowerPC hardware trap types, and
> + * signals, which are primarily what GDB understands.
> + */
> +static struct hard_trap_info
> +{
> + unsigned int tt; /* Trap type code for powerpc */
> + unsigned char signo; /* Signal that we map this trap into */
> +} hard_trap_info[] = {
> +#if defined(CONFIG_40x)
> + { 0x100, SIGINT }, /* critical input interrupt */
> + { 0x200, SIGSEGV }, /* machine check */
> + { 0x300, SIGSEGV }, /* data storage */
> + { 0x400, SIGBUS }, /* instruction storage */
> + { 0x500, SIGINT }, /* interrupt */
> + { 0x600, SIGBUS }, /* alignment */
> + { 0x700, SIGILL }, /* program */
> + { 0x800, SIGILL }, /* reserved */
> + { 0x900, SIGILL }, /* reserved */
> + { 0xa00, SIGILL }, /* reserved */
> + { 0xb00, SIGILL }, /* reserved */
> + { 0xc00, SIGCHLD }, /* syscall */
> + { 0xd00, SIGILL }, /* reserved */
> + { 0xe00, SIGILL }, /* reserved */
> + { 0xf00, SIGILL }, /* reserved */
> + { 0x2000, SIGTRAP}, /* debug */
> +#else
> + { 0x200, SIGSEGV }, /* machine check */
> + { 0x300, SIGSEGV }, /* address error (store) */
> + { 0x400, SIGBUS }, /* instruction bus error */
> + { 0x500, SIGINT }, /* interrupt */
> + { 0x600, SIGBUS }, /* alingment */
> + { 0x700, SIGTRAP }, /* breakpoint trap */
> + { 0x800, SIGFPE }, /* fpu unavail */
> + { 0x900, SIGALRM }, /* decrementer */
> + { 0xa00, SIGILL }, /* reserved */
> + { 0xb00, SIGILL }, /* reserved */
> + { 0xc00, SIGCHLD }, /* syscall */
> + { 0xd00, SIGTRAP }, /* single-step/watch */
> + { 0xe00, SIGFPE }, /* fp assist */
> +#endif
> + { 0, 0} /* Must be last */
> +};
> +
> +static int computeSignal(unsigned int tt)
> +{
> + struct hard_trap_info *ht;
> +
> + for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
> + if (ht->tt == tt)
> + return ht->signo;
> +
> + return SIGHUP; /* default for things we don't know about */
> +}
> +
> /*
> * Routines
> */
> static void
> kgdb_debugger(struct pt_regs *regs)
> {
> - (*linux_debug_hook) (0, 0, 0, regs);
> + (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
> return;
> }
>
> @@ -52,14 +109,14 @@
> int
> kgdb_iabr_match(struct pt_regs *regs)
> {
> - (*linux_debug_hook) (0, 0, 0, regs);
> + (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
> return 1;
> }
>
> int
> kgdb_dabr_match(struct pt_regs *regs)
> {
> - (*linux_debug_hook) (0, 0, 0, regs);
> + (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
> return 1;
> }
>
>
> Now, not being as well versed in all of the debugging infos that can be
> passed around, it sounds like this patch could be dropped in the future
> for a cleaner method using some of the dwarf2 bits being talked about.
> But I don't know, and clarification and pointers (if so) to how to do
> this would be appreciated.

I am not sure what this buys you. I don't think dwarf2 will help here.

There is a real danger of passing signal info back to gdb as it will want to try
to deliver the signal which is a non-compute in most kgdbs in the field. I did
put code in the mm-kgdb to do just this, but usually the arrival of such a
signal (other than SIGTRAP) is the end of the kernel. All that is left is to
read the tea leaves.

On occasion, because there are traps in a lot of places, one gets to kgdb and
wants to know just how it happened. The way I like to do this is with the "l"
command on the call to the kgdb handler. In the above case, it would be on the
return address of the appropiate one of the three functions. To make this
information available I defined a global structure (kdgd_info) which the stub
updates on entry. From this point of view and looking at the above code, I
wonder a) why you need three functions, and b) why not just use what ever
linux_debug_hook points to and let it do the signal decoding.

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-01-24 00:55:00

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/Makefile linux/Makefile
--- linux-2.6.0-akgdb/Makefile 2004-01-08 15:36:35.000000000 -0800
+++ linux/Makefile 2004-01-22 13:01:31.000000000 -0800
@@ -1025,5 +1025,7 @@
descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2)

endif # skip-makefile
+include/linux/dwarf2-defs.h: include/linux/dwarf2.h scripts/dwarfh.awk
+ awk -f scripts/dwarfh.awk include/linux/dwarf2.h > include/linux/dwarf2-defs.h

-FORCE:
+FORCE: include/linux/dwarf2-defs.h
Binary files linux-2.6.0-akgdb/a.out and linux/a.out differ
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/arch/i386/Kconfig linux/arch/i386/Kconfig
--- linux-2.6.0-akgdb/arch/i386/Kconfig 2004-01-08 15:39:58.000000000 -0800
+++ linux/arch/i386/Kconfig 2004-01-09 14:50:07.000000000 -0800
@@ -1196,7 +1196,7 @@

config DEBUG_INFO
bool "Compile the kernel with debug info"
- depends on DEBUG_KERNEL
+ depends on DEBUG_KERNEL && !KGDB
help
If you say Y here the resulting kernel image will include
debugging info resulting in a larger kernel image.
@@ -1227,7 +1227,7 @@
will then break as soon as it looks at the boot options. This
option also installs a breakpoint in panic and sends any
kernel faults to the debugger. For more information see the
- Documentation/i386/kgdb.txt file.
+ Documentation/i386/kgdb/kgdb.txt file.

choice
depends on KGDB
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/arch/i386/Makefile linux/arch/i386/Makefile
--- linux-2.6.0-akgdb/arch/i386/Makefile 2004-01-08 15:39:58.000000000 -0800
+++ linux/arch/i386/Makefile 2004-01-13 16:04:02.000000000 -0800
@@ -100,7 +100,9 @@
drivers-$(CONFIG_PM) += arch/i386/power/

CFLAGS += $(mflags-y)
-AFLAGS += $(mflags-y)
+aflags-y = $(mflags-y)
+aflags-$(CONFIG_KGDB) += -save-temps
+AFLAGS += $(aflags-y)

boot := arch/i386/boot

diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.6.0-akgdb/arch/i386/kernel/entry.S 2004-01-13 15:53:06.000000000 -0800
+++ linux/arch/i386/kernel/entry.S 2004-01-23 16:03:00.000000000 -0800
@@ -910,3 +910,116 @@
.long sys_ni_syscall /* sys_vserver */

syscall_table_size=(.-sys_call_table)
+
+# Here we do call frames. We cheat a bit as we only really need
+# correct frames at locations we can actually look at from a
+# debugger. Since the break instruction trap actually goes thru
+# some of this code, we don't really need info on those areas, but
+# only after the fact. I.e. if we can not step or break in a
+# location or end up with a return address pointing at the
+# location, we don't need a correct call frame for it.
+
+#ifdef CONFIG_KGDB
+
+#include <linux/dwarf2-lang.h>
+/*
+ * The register numbers as known by gdb
+ */
+cfa_one: .long 1
+
+#define _EAX 0
+#define _ECX 1
+#define _EDX 2
+#define _EBX 3
+#define _ESP 4
+#define _EBP 5
+#define _ESI 6
+#define _EDI 7
+#define _PC 8
+#define _EIP 8
+#define _PS 9
+#define _EFLAGS 9
+#define _CS 10
+#define _SS 11
+#define _DS 12
+#define _ES 13
+#define _FS 14
+#define _GS 15
+
+ CFI_preamble(c1,_PC,1,1)
+ CFA_def_cfa_expression
+ CFA_exp_OP_breg(_ESP,OLDESP) /* push the stack & adjust */
+ CFA_exp_OP_dup /* save that */
+ CFA_exp_OP_consts(-8) /* offset to CS address */
+ CFA_exp_OP_plus /* should be CS address */
+ CFA_exp_OP_deref /* get the CS */
+ CFA_exp_OP_const4s(VM_MASK|3) /* prepare to mask it */
+ CFA_exp_OP_and /* mask it, zero means kernel */
+ CFA_exp_OP_bra(cfa_user_rtn) /* branch if user (TOS--) */
+ CFA_exp_OP_skip(cfa_end) /* done if kernel, skip out */
+cfa_user_rtn:
+ CFA_exp_OP_constu(0) /* user space, set exp to 0 */
+cfa_end:
+ CFA_expression_end
+ CFA_expression(_EIP)
+ CFA_exp_OP_dup /* copy old esp */
+ CFA_exp_OP_bra(eip_kernel_rtn) /* non-zero means kernel */
+ CFA_exp_OP_addr(cfa_one) /* for user, pass 1 */
+ CFA_exp_OP_skip(eip_end) /* done if kernel, skip out */
+eip_kernel_rtn:
+ CFA_exp_OP_const4s(EIP-OLDESP) /* offset to return address */
+ CFA_exp_OP_plus
+eip_end:
+ CFA_expression_end
+ CFA_define_offset(_EBX,EBX-OLDESP)
+ CFA_define_offset(_ECX,ECX-OLDESP)
+ CFA_define_offset(_EDX,EDX-OLDESP)
+ CFA_define_offset(_ESI,ESI-OLDESP)
+ CFA_define_offset(_EDI,EDI-OLDESP)
+ CFA_define_offset(_EBP,EBP-OLDESP)
+ CFA_define_offset(_EAX,EAX-OLDESP)
+ CFA_define_offset(_EFLAGS,EFLAGS-OLDESP)
+ CFI_postamble()
+
+/*
+ * This is an attempt to provide an unwind for location 0 which is
+ * identical to the prior frame. Should stop the unwind. Note that gdb
+ * uses the pc-1 to look for FDEs so the correct pc is 1 not 0 which,
+ * because of addresses being unsigned, can not be used by man nor beast.
+ */
+ CFI_preamble(c2,_PC,1,1)
+ CFA_def_cfa_expression
+ CFA_exp_OP_constu(0) /* stack end, set exp to 0 */
+ CFA_expression_end
+ CFI_postamble()
+
+ FDE_preamble(c2,0,10)
+ FDE_postamble()
+ /*
+ * This is VERY sloppy. At this point all we want to do is get
+ * the frame right for back tracing. It will not be good if
+ * you try to single step. We use already defined labels.
+ * We want to cover all call outs.
+ * We could also recode this as just one FDE, but this works and
+ * I want to get it out.
+ */
+ FDE_preamble(c1,do_lcall,(ret_from_fork - do_lcall))
+ CFA_define_cfa_offset(OLDESP+8)
+ FDE_postamble()
+ FDE_preamble(c1,ret_from_fork,(ret_from_exception - ret_from_fork))
+ CFA_define_cfa_offset(OLDESP+4)
+ FDE_postamble()
+ FDE_preamble(c1,ret_from_exception,(divide_error - ret_from_exception))
+ FDE_postamble()
+ FDE_preamble(c1,error_code,(device_not_available_emulate - error_code))
+ CFA_define_cfa_offset(OLDESP+8)
+ FDE_postamble()
+ FDE_preamble(c1,device_not_available_emulate,(debug - device_not_available_emulate))
+ CFA_define_cfa_offset(OLDESP+4)
+ FDE_postamble()
+ FDE_preamble(c1,nmi,(int3 - nmi))
+ CFA_define_cfa_offset(OLDESP+8)
+ FDE_postamble()
+
+#
+#endif
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- linux-2.6.0-akgdb/arch/i386/kernel/head.S 2003-09-08 14:15:17.000000000 -0700
+++ linux/arch/i386/kernel/head.S 2004-01-23 16:19:21.000000000 -0800
@@ -278,6 +278,16 @@
# just in case, we know what happens.

ready: .byte 0
+#ifdef CONFIG_KGDB
+#include <linux/dwarf2-lang.h>
+
+ /* This dwarf code tells gdb that this is the end of the unwind */
+ /* This uses the CFA set up for pc=1 located in entry.S */
+
+ FDE_preamble(c2,is386,(L6-is386))
+ FDE_postamble()
+
+#endif

/*
* We depend on ET to be correct. This checks for 287/387.
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- linux-2.6.0-akgdb/arch/i386/kernel/smpboot.c 2003-11-10 15:59:40.000000000 -0800
+++ linux/arch/i386/kernel/smpboot.c 2004-01-18 00:33:32.000000000 -0800
@@ -476,6 +476,9 @@

asm volatile(
"movl %0,%%esp\n\t"
+#ifdef CONFIG_KGDB
+ "pushl $1\n\t"
+#endif
"jmp *%1"
:
:"r" (current->thread.esp),"r" (current->thread.eip));
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/include/linux/dwarf2-lang.h linux/include/linux/dwarf2-lang.h
--- linux-2.6.0-akgdb/include/linux/dwarf2-lang.h 1969-12-31 16:00:00.000000000 -0800
+++ linux/include/linux/dwarf2-lang.h 2004-01-22 13:06:43.000000000 -0800
@@ -0,0 +1,286 @@
+#ifndef DWARF2_LANG
+#define DWARF2_LANG
+
+/*
+ * This 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, or (at your option) any later
+ * version.
+ */
+/*
+ * This file defines macros that allow generation of DWARF debug records
+ * for asm files. This file is platform independent. Register numbers
+ * (which are about the only thing that is platform dependent) are to be
+ * supplied by a platform defined file.
+ */
+/*
+ * We need this to work for both asm and C. In asm we are using the
+ * old comment trick to concatenate while C uses the new ANSI thing.
+ * Here we have concat macro... The multi level thing is to allow and
+ * macros used in the names to be resolved prior to the cat (at which
+ * time they are no longer the same string).
+ */
+#define CAT3(a,b,c) _CAT3(a,b,c)
+#define _CAT3(a,b,c) __CAT3(a,b,c)
+#ifdef __ASSEMBLY__
+#define __CAT3(a,b,c) a/**/b/**/c
+#define IFC(a)
+#define IFN_C(a) a
+#define NL ;
+#define QUOTE_THIS(a) a
+#define DWARF_preamble .section .debug_frame,"",@progbits;
+#else
+#define __CAT3(a,b,c) a ## b ## c
+#define IFC(a) a
+#define IFN_C(a)
+#define NL \n\t
+#define QUOTE_THIS(a) _QUOTE_THIS(a)
+#define _QUOTE_THIS(a) #a
+/* Don't let CPP see the " and , \042=" \054=, */
+#define DWARF_preamble .section .debug_frame \054\042\042\054@progbits
+
+#endif
+#include <linux/dwarf2-defs.h>
+/*
+ * This macro starts a debug frame section. The debug_frame describes
+ * where to find the registers that the enclosing function saved on
+ * entry.
+ *
+ * ORD is use by the label generator and should be the same as what is
+ * passed to CFI_postamble.
+ *
+ * pc, pc register gdb ordinal.
+ *
+ * code_align this is the factor used to define locations or regions
+ * where the given definitions apply. If you use labels to define these
+ * this should be 1.
+ *
+ * data_align this is the factor used to define register offsets. If
+ * you use struct offset, this should be the size of the register in
+ * bytes or the negative of that. This is how it is used: you will
+ * define a register as the reference register, say the stack pointer,
+ * then you will say where a register is located relative to this
+ * reference registers value, say 40 for register 3 (the gdb register
+ * number). The <40> will be multiplied by <data_align> to define the
+ * byte offset of the given register (3, in this example). So if your
+ * <40> is the byte offset and the reference register points at the
+ * begining, you would want 1 for the data_offset. If <40> was the 40th
+ * 4-byte element in that structure you would want 4. And if your
+ * reference register points at the end of the structure you would want
+ * a negative data_align value(and you would have to do other math as
+ * well).
+ */
+
+#define CFI_preamble(ORD, pc, code_align, data_align) \
+ DWARF_preamble NL \
+ .align 4 NL \
+ .globl CAT3(frame,_,ORD) NL \
+CAT3(frame,_,ORD): NL \
+ .long 7f-6f NL \
+6: \
+ .long DW_CIE_ID NL \
+ .byte DW_CIE_VERSION NL \
+ .byte 0 NL \
+ .uleb128 code_align NL \
+ .sleb128 data_align NL \
+ .byte pc NL
+
+/*
+ * After the above macro and prior to the CFI_postamble, you need to
+ * define the initial state. This starts with defining the reference
+ * register and, usually the pc. Here are some helper macros:
+ */
+
+#define CFA_define_reference(reg, offset) \
+ .byte DW_CFA_def_cfa NL \
+ .uleb128 reg NL \
+ .uleb128 (offset) NL
+
+#define CFA_define_offset(reg, offset) \
+ .byte (DW_CFA_offset + reg) NL \
+ .uleb128 (offset) NL
+
+#define CFA_restore(reg) \
+ .byte (DW_CFA_restore + reg) NL
+
+#define CFI_postamble() \
+ .align 4 NL \
+7: NL \
+.previous NL
+/*
+ * So now your code pushs stuff on the stack, you need a new location
+ * and the rules for what to do. This starts a running description of
+ * the call frame. You need to describe what changes with respect to
+ * the call registers as the location of the pc moves through the code.
+ * The following builds an FDE (fram descriptor entry?). Like the
+ * above, it has a preamble and a postamble. It also is tied to the CFI
+ * above.
+ * The preamble macro is tied to the CFI thru the first parameter. The
+ * second is the code start address and then the code length.
+ */
+// DWARF_preamble() NL
+#define FDE_preamble(ORD, initial_address, length) \
+ DWARF_preamble NL \
+ .align 4 NL \
+ .long 9f-8f NL \
+8: \
+ .long CAT3(frame,_,ORD) NL \
+ .long initial_address NL \
+ .long length NL
+
+#define FDE_postamble() \
+ .align 4 NL \
+9: NL \
+.previous NL
+/*
+ * That done, you can now add registers, subtract registers, move the
+ * reference and even change the reference. You can also define a new
+ * area of code the info applies to. For discontinuous bits you should
+ * start a new FDE. You may have as many as you like.
+ */
+
+/*
+ * To advance the stack address by <bytes> (0x3f max)
+ */
+
+#define CFA_advance_loc(bytes) \
+ .byte DW_CFA_advance_loc+bytes NL
+
+/*
+ * This one is good for 0xff or 255
+ */
+#define CFA_advance_loc1(bytes) \
+ .byte DW_CFA_advance_loc1 NL \
+ .byte bytes NL
+
+
+/*
+ * With the above you can define all the register locations. But
+ * suppose the reference register moves... Takes the new offset NOT an
+ * increment. This is how esp is tracked if it is not saved.
+ */
+
+#define CFA_define_cfa_offset(offset) \
+ .byte DW_CFA_def_cfa_offset NL \
+ .uleb128 (offset) NL
+/*
+ * Or suppose you want to use a different reference register...
+ */
+#define CFA_define_cfa_register(reg) \
+ .byte DW_CFA_def_cfa_register NL \
+ .uleb128 reg NL
+
+/*
+ * If you want to mess with the stack pointer, here is the expression.
+ * The stack starts empty.
+ */
+#define CFA_def_cfa_expression \
+ .byte DW_CFA_def_cfa_expression NL \
+ .uleb128 20f-10f NL \
+10: NL
+/*
+ * This expression is to be used for other regs. The stack starts with the
+ * stack address.
+ */
+
+#define CFA_expression(reg) \
+ .byte DW_CFA_expression NL \
+ .uleb128 reg NL \
+ .uleb128 20f-10f NL \
+10: NL
+/*
+ * Here we do the expression stuff. You should code the above followed
+ * by expression OPs followed by CFA_expression_end.
+ */
+
+
+#define CFA_expression_end \
+20: NL
+
+#define CFA_exp_OP_const4s(a) \
+ .byte DW_OP_const4s NL \
+ .long a NL
+
+#define CFA_exp_OP_swap .byte DW_OP_swap NL
+#define CFA_exp_OP_dup .byte DW_OP_dup NL
+#define CFA_exp_OP_drop .byte DW_OP_drop NL
+/*
+ * All these work on the top two elements on the stack, replacing them
+ * with the result. Top comes first where it matters. True is 1, false 0.
+ */
+#define CFA_exp_OP_deref .byte DW_OP_deref NL
+#define CFA_exp_OP_and .byte DW_OP_and NL
+#define CFA_exp_OP_div .byte DW_OP_div NL
+#define CFA_exp_OP_minus .byte DW_OP_minus NL
+#define CFA_exp_OP_mod .byte DW_OP_mod NL
+#define CFA_exp_OP_neg .byte DW_OP_neg NL
+#define CFA_exp_OP_plus .byte DW_OP_plus NL
+#define CFA_exp_OP_not .byte DW_OP_not NL
+#define CFA_exp_OP_or .byte DW_OP_or NL
+#define CFA_exp_OP_xor .byte DW_OP_xor NL
+#define CFA_exp_OP_le .byte DW_OP_le NL
+#define CFA_exp_OP_ge .byte DW_OP_ge NL
+#define CFA_exp_OP_eq .byte DW_OP_eq NL
+#define CFA_exp_OP_lt .byte DW_OP_lt NL
+#define CFA_exp_OP_gt .byte DW_OP_gt NL
+#define CFA_exp_OP_ne .byte DW_OP_ne NL
+/*
+ * These take a parameter as noted
+ */
+/*
+ * Unconditional skip to loc. loc is a label (loc:)
+ */
+#define CFA_exp_OP_skip(loc) \
+ .byte DW_OP_skip NL \
+ .hword loc-.-2 NL
+/*
+ * Conditional skip to loc (TOS != 0, TOS--) (loc is a label)
+ */
+#define CFA_exp_OP_bra(loc) \
+ .byte DW_OP_bra NL \
+ .hword loc-.-2 NL
+
+/*
+ * TOS += no (an unsigned number)
+ */
+#define CFA_exp_OP_plus_uconst(no) \
+ .byte DW_OP_plus_uconst NL \
+ .uleb128 no NL
+
+/*
+ * ++TOS = no (a unsigned number)
+ */
+#define CFA_exp_OP_constu(no) \
+ .byte DW_OP_constu NL \
+ .uleb128 no NL
+/*
+ * ++TOS = no (a signed number)
+ */
+#define CFA_exp_OP_consts(no) \
+ .byte DW_OP_consts NL \
+ .sleb128 no NL
+/*
+ * ++TOS = no (an unsigned byte)
+ */
+#define CFA_exp_OP_const1u(no) \
+ .byte DW_OP_const1u NL \
+ .byte no NL
+
+
+/*
+ * ++TOS = no (a address)
+ */
+#define CFA_exp_OP_addr(no) \
+ .byte DW_OP_addr NL \
+ .long no NL
+
+/*
+ * Push current frames value for "reg" + offset
+ * We take advantage of the opcode assignments to make this a litteral reg
+ * rather than use the DW_OP_bregx opcode.
+ */
+
+#define CFA_exp_OP_breg(reg,offset) \
+ .byte DW_OP_breg0+reg NL \
+ .sleb128 offset NL
+#endif
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/include/linux/dwarf2.h linux/include/linux/dwarf2.h
--- linux-2.6.0-akgdb/include/linux/dwarf2.h 1969-12-31 16:00:00.000000000 -0800
+++ linux/include/linux/dwarf2.h 2004-01-15 00:26:12.000000000 -0800
@@ -0,0 +1,775 @@
+/* Declarations and definitions of codes relating to the DWARF2 symbolic
+ debugging information format.
+ Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
+ 2003 Free Software Foundation, Inc.
+
+ Written by Gary Funck ([email protected]) The Ada Joint Program
+ Office (AJPO), Florida State Unviversity and Silicon Graphics Inc.
+ provided support for this effort -- June 21, 1995.
+
+ Derived from the DWARF 1 implementation written by Ron Guilmette
+ ([email protected]), November 1990.
+
+ This file is part of GCC.
+
+ GCC 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, or (at your option) any later
+ version.
+
+ GCC 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 GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* This file is derived from the DWARF specification (a public document)
+ Revision 2.0.0 (July 27, 1993) developed by the UNIX International
+ Programming Languages Special Interest Group (UI/PLSIG) and distributed
+ by UNIX International. Copies of this specification are available from
+ UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.
+
+ This file also now contains definitions from the DWARF 3 specification. */
+
+/* This file is shared between GCC and GDB, and should not contain
+ prototypes. */
+
+#ifndef _ELF_DWARF2_H
+#define _ELF_DWARF2_H
+
+/* Structure found in the .debug_line section. */
+typedef struct
+{
+ unsigned char li_length [4];
+ unsigned char li_version [2];
+ unsigned char li_prologue_length [4];
+ unsigned char li_min_insn_length [1];
+ unsigned char li_default_is_stmt [1];
+ unsigned char li_line_base [1];
+ unsigned char li_line_range [1];
+ unsigned char li_opcode_base [1];
+}
+DWARF2_External_LineInfo;
+
+typedef struct
+{
+ unsigned long li_length;
+ unsigned short li_version;
+ unsigned int li_prologue_length;
+ unsigned char li_min_insn_length;
+ unsigned char li_default_is_stmt;
+ int li_line_base;
+ unsigned char li_line_range;
+ unsigned char li_opcode_base;
+}
+DWARF2_Internal_LineInfo;
+
+/* Structure found in .debug_pubnames section. */
+typedef struct
+{
+ unsigned char pn_length [4];
+ unsigned char pn_version [2];
+ unsigned char pn_offset [4];
+ unsigned char pn_size [4];
+}
+DWARF2_External_PubNames;
+
+typedef struct
+{
+ unsigned long pn_length;
+ unsigned short pn_version;
+ unsigned long pn_offset;
+ unsigned long pn_size;
+}
+DWARF2_Internal_PubNames;
+
+/* Structure found in .debug_info section. */
+typedef struct
+{
+ unsigned char cu_length [4];
+ unsigned char cu_version [2];
+ unsigned char cu_abbrev_offset [4];
+ unsigned char cu_pointer_size [1];
+}
+DWARF2_External_CompUnit;
+
+typedef struct
+{
+ unsigned long cu_length;
+ unsigned short cu_version;
+ unsigned long cu_abbrev_offset;
+ unsigned char cu_pointer_size;
+}
+DWARF2_Internal_CompUnit;
+
+typedef struct
+{
+ unsigned char ar_length [4];
+ unsigned char ar_version [2];
+ unsigned char ar_info_offset [4];
+ unsigned char ar_pointer_size [1];
+ unsigned char ar_segment_size [1];
+}
+DWARF2_External_ARange;
+
+typedef struct
+{
+ unsigned long ar_length;
+ unsigned short ar_version;
+ unsigned long ar_info_offset;
+ unsigned char ar_pointer_size;
+ unsigned char ar_segment_size;
+}
+DWARF2_Internal_ARange;
+
+
+/* Tag names and codes. */
+enum dwarf_tag
+ {
+ DW_TAG_padding = 0x00,
+ DW_TAG_array_type = 0x01,
+ DW_TAG_class_type = 0x02,
+ DW_TAG_entry_point = 0x03,
+ DW_TAG_enumeration_type = 0x04,
+ DW_TAG_formal_parameter = 0x05,
+ DW_TAG_imported_declaration = 0x08,
+ DW_TAG_label = 0x0a,
+ DW_TAG_lexical_block = 0x0b,
+ DW_TAG_member = 0x0d,
+ DW_TAG_pointer_type = 0x0f,
+ DW_TAG_reference_type = 0x10,
+ DW_TAG_compile_unit = 0x11,
+ DW_TAG_string_type = 0x12,
+ DW_TAG_structure_type = 0x13,
+ DW_TAG_subroutine_type = 0x15,
+ DW_TAG_typedef = 0x16,
+ DW_TAG_union_type = 0x17,
+ DW_TAG_unspecified_parameters = 0x18,
+ DW_TAG_variant = 0x19,
+ DW_TAG_common_block = 0x1a,
+ DW_TAG_common_inclusion = 0x1b,
+ DW_TAG_inheritance = 0x1c,
+ DW_TAG_inlined_subroutine = 0x1d,
+ DW_TAG_module = 0x1e,
+ DW_TAG_ptr_to_member_type = 0x1f,
+ DW_TAG_set_type = 0x20,
+ DW_TAG_subrange_type = 0x21,
+ DW_TAG_with_stmt = 0x22,
+ DW_TAG_access_declaration = 0x23,
+ DW_TAG_base_type = 0x24,
+ DW_TAG_catch_block = 0x25,
+ DW_TAG_const_type = 0x26,
+ DW_TAG_constant = 0x27,
+ DW_TAG_enumerator = 0x28,
+ DW_TAG_file_type = 0x29,
+ DW_TAG_friend = 0x2a,
+ DW_TAG_namelist = 0x2b,
+ DW_TAG_namelist_item = 0x2c,
+ DW_TAG_packed_type = 0x2d,
+ DW_TAG_subprogram = 0x2e,
+ DW_TAG_template_type_param = 0x2f,
+ DW_TAG_template_value_param = 0x30,
+ DW_TAG_thrown_type = 0x31,
+ DW_TAG_try_block = 0x32,
+ DW_TAG_variant_part = 0x33,
+ DW_TAG_variable = 0x34,
+ DW_TAG_volatile_type = 0x35,
+ /* DWARF 3. */
+ DW_TAG_dwarf_procedure = 0x36,
+ DW_TAG_restrict_type = 0x37,
+ DW_TAG_interface_type = 0x38,
+ DW_TAG_namespace = 0x39,
+ DW_TAG_imported_module = 0x3a,
+ DW_TAG_unspecified_type = 0x3b,
+ DW_TAG_partial_unit = 0x3c,
+ DW_TAG_imported_unit = 0x3d,
+ /* SGI/MIPS Extensions. */
+ DW_TAG_MIPS_loop = 0x4081,
+ /* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */
+ DW_TAG_HP_array_descriptor = 0x4090,
+ /* GNU extensions. */
+ DW_TAG_format_label = 0x4101, /* For FORTRAN 77 and Fortran 90. */
+ DW_TAG_function_template = 0x4102, /* For C++. */
+ DW_TAG_class_template = 0x4103, /* For C++. */
+ DW_TAG_GNU_BINCL = 0x4104,
+ DW_TAG_GNU_EINCL = 0x4105,
+ /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */
+ DW_TAG_upc_shared_type = 0x8765,
+ DW_TAG_upc_strict_type = 0x8766,
+ DW_TAG_upc_relaxed_type = 0x8767,
+ /* PGI (STMicroelectronics) extensions. No documentation available. */
+ DW_TAG_PGI_kanji_type = 0xA000,
+ DW_TAG_PGI_interface_block = 0xA020
+ };
+
+#define DW_TAG_lo_user 0x4080
+#define DW_TAG_hi_user 0xffff
+
+/* Flag that tells whether entry has a child or not. */
+#define DW_children_no 0
+#define DW_children_yes 1
+
+/* Form names and codes. */
+enum dwarf_form
+ {
+ DW_FORM_addr = 0x01,
+ DW_FORM_block2 = 0x03,
+ DW_FORM_block4 = 0x04,
+ DW_FORM_data2 = 0x05,
+ DW_FORM_data4 = 0x06,
+ DW_FORM_data8 = 0x07,
+ DW_FORM_string = 0x08,
+ DW_FORM_block = 0x09,
+ DW_FORM_block1 = 0x0a,
+ DW_FORM_data1 = 0x0b,
+ DW_FORM_flag = 0x0c,
+ DW_FORM_sdata = 0x0d,
+ DW_FORM_strp = 0x0e,
+ DW_FORM_udata = 0x0f,
+ DW_FORM_ref_addr = 0x10,
+ DW_FORM_ref1 = 0x11,
+ DW_FORM_ref2 = 0x12,
+ DW_FORM_ref4 = 0x13,
+ DW_FORM_ref8 = 0x14,
+ DW_FORM_ref_udata = 0x15,
+ DW_FORM_indirect = 0x16
+ };
+
+/* Attribute names and codes. */
+enum dwarf_attribute
+ {
+ DW_AT_sibling = 0x01,
+ DW_AT_location = 0x02,
+ DW_AT_name = 0x03,
+ DW_AT_ordering = 0x09,
+ DW_AT_subscr_data = 0x0a,
+ DW_AT_byte_size = 0x0b,
+ DW_AT_bit_offset = 0x0c,
+ DW_AT_bit_size = 0x0d,
+ DW_AT_element_list = 0x0f,
+ DW_AT_stmt_list = 0x10,
+ DW_AT_low_pc = 0x11,
+ DW_AT_high_pc = 0x12,
+ DW_AT_language = 0x13,
+ DW_AT_member = 0x14,
+ DW_AT_discr = 0x15,
+ DW_AT_discr_value = 0x16,
+ DW_AT_visibility = 0x17,
+ DW_AT_import = 0x18,
+ DW_AT_string_length = 0x19,
+ DW_AT_common_reference = 0x1a,
+ DW_AT_comp_dir = 0x1b,
+ DW_AT_const_value = 0x1c,
+ DW_AT_containing_type = 0x1d,
+ DW_AT_default_value = 0x1e,
+ DW_AT_inline = 0x20,
+ DW_AT_is_optional = 0x21,
+ DW_AT_lower_bound = 0x22,
+ DW_AT_producer = 0x25,
+ DW_AT_prototyped = 0x27,
+ DW_AT_return_addr = 0x2a,
+ DW_AT_start_scope = 0x2c,
+ DW_AT_stride_size = 0x2e,
+ DW_AT_upper_bound = 0x2f,
+ DW_AT_abstract_origin = 0x31,
+ DW_AT_accessibility = 0x32,
+ DW_AT_address_class = 0x33,
+ DW_AT_artificial = 0x34,
+ DW_AT_base_types = 0x35,
+ DW_AT_calling_convention = 0x36,
+ DW_AT_count = 0x37,
+ DW_AT_data_member_location = 0x38,
+ DW_AT_decl_column = 0x39,
+ DW_AT_decl_file = 0x3a,
+ DW_AT_decl_line = 0x3b,
+ DW_AT_declaration = 0x3c,
+ DW_AT_discr_list = 0x3d,
+ DW_AT_encoding = 0x3e,
+ DW_AT_external = 0x3f,
+ DW_AT_frame_base = 0x40,
+ DW_AT_friend = 0x41,
+ DW_AT_identifier_case = 0x42,
+ DW_AT_macro_info = 0x43,
+ DW_AT_namelist_items = 0x44,
+ DW_AT_priority = 0x45,
+ DW_AT_segment = 0x46,
+ DW_AT_specification = 0x47,
+ DW_AT_static_link = 0x48,
+ DW_AT_type = 0x49,
+ DW_AT_use_location = 0x4a,
+ DW_AT_variable_parameter = 0x4b,
+ DW_AT_virtuality = 0x4c,
+ DW_AT_vtable_elem_location = 0x4d,
+ /* DWARF 3 values. */
+ DW_AT_allocated = 0x4e,
+ DW_AT_associated = 0x4f,
+ DW_AT_data_location = 0x50,
+ DW_AT_stride = 0x51,
+ DW_AT_entry_pc = 0x52,
+ DW_AT_use_UTF8 = 0x53,
+ DW_AT_extension = 0x54,
+ DW_AT_ranges = 0x55,
+ DW_AT_trampoline = 0x56,
+ DW_AT_call_column = 0x57,
+ DW_AT_call_file = 0x58,
+ DW_AT_call_line = 0x59,
+ /* SGI/MIPS extensions. */
+ DW_AT_MIPS_fde = 0x2001,
+ DW_AT_MIPS_loop_begin = 0x2002,
+ DW_AT_MIPS_tail_loop_begin = 0x2003,
+ DW_AT_MIPS_epilog_begin = 0x2004,
+ DW_AT_MIPS_loop_unroll_factor = 0x2005,
+ DW_AT_MIPS_software_pipeline_depth = 0x2006,
+ DW_AT_MIPS_linkage_name = 0x2007,
+ DW_AT_MIPS_stride = 0x2008,
+ DW_AT_MIPS_abstract_name = 0x2009,
+ DW_AT_MIPS_clone_origin = 0x200a,
+ DW_AT_MIPS_has_inlines = 0x200b,
+ /* HP extensions. */
+ DW_AT_HP_block_index = 0x2000,
+ DW_AT_HP_unmodifiable = 0x2001, /* Same as DW_AT_MIPS_fde. */
+ DW_AT_HP_actuals_stmt_list = 0x2010,
+ DW_AT_HP_proc_per_section = 0x2011,
+ DW_AT_HP_raw_data_ptr = 0x2012,
+ DW_AT_HP_pass_by_reference = 0x2013,
+ DW_AT_HP_opt_level = 0x2014,
+ DW_AT_HP_prof_version_id = 0x2015,
+ DW_AT_HP_opt_flags = 0x2016,
+ DW_AT_HP_cold_region_low_pc = 0x2017,
+ DW_AT_HP_cold_region_high_pc = 0x2018,
+ DW_AT_HP_all_variables_modifiable = 0x2019,
+ DW_AT_HP_linkage_name = 0x201a,
+ DW_AT_HP_prof_flags = 0x201b, /* In comp unit of procs_info for -g. */
+ /* GNU extensions. */
+ DW_AT_sf_names = 0x2101,
+ DW_AT_src_info = 0x2102,
+ DW_AT_mac_info = 0x2103,
+ DW_AT_src_coords = 0x2104,
+ DW_AT_body_begin = 0x2105,
+ DW_AT_body_end = 0x2106,
+ DW_AT_GNU_vector = 0x2107,
+ /* VMS extensions. */
+ DW_AT_VMS_rtnbeg_pd_address = 0x2201,
+ /* UPC extension. */
+ DW_AT_upc_threads_scaled = 0x3210,
+ /* PGI (STMicroelectronics) extensions. */
+ DW_AT_PGI_lbase = 0x3a00,
+ DW_AT_PGI_soffset = 0x3a01,
+ DW_AT_PGI_lstride = 0x3a02
+ };
+
+#define DW_AT_lo_user 0x2000 /* Implementation-defined range start. */
+#define DW_AT_hi_user 0x3ff0 /* Implementation-defined range end. */
+
+/* Location atom names and codes. */
+enum dwarf_location_atom
+ {
+ DW_OP_addr = 0x03,
+ DW_OP_deref = 0x06,
+ DW_OP_const1u = 0x08,
+ DW_OP_const1s = 0x09,
+ DW_OP_const2u = 0x0a,
+ DW_OP_const2s = 0x0b,
+ DW_OP_const4u = 0x0c,
+ DW_OP_const4s = 0x0d,
+ DW_OP_const8u = 0x0e,
+ DW_OP_const8s = 0x0f,
+ DW_OP_constu = 0x10,
+ DW_OP_consts = 0x11,
+ DW_OP_dup = 0x12,
+ DW_OP_drop = 0x13,
+ DW_OP_over = 0x14,
+ DW_OP_pick = 0x15,
+ DW_OP_swap = 0x16,
+ DW_OP_rot = 0x17,
+ DW_OP_xderef = 0x18,
+ DW_OP_abs = 0x19,
+ DW_OP_and = 0x1a,
+ DW_OP_div = 0x1b,
+ DW_OP_minus = 0x1c,
+ DW_OP_mod = 0x1d,
+ DW_OP_mul = 0x1e,
+ DW_OP_neg = 0x1f,
+ DW_OP_not = 0x20,
+ DW_OP_or = 0x21,
+ DW_OP_plus = 0x22,
+ DW_OP_plus_uconst = 0x23,
+ DW_OP_shl = 0x24,
+ DW_OP_shr = 0x25,
+ DW_OP_shra = 0x26,
+ DW_OP_xor = 0x27,
+ DW_OP_bra = 0x28,
+ DW_OP_eq = 0x29,
+ DW_OP_ge = 0x2a,
+ DW_OP_gt = 0x2b,
+ DW_OP_le = 0x2c,
+ DW_OP_lt = 0x2d,
+ DW_OP_ne = 0x2e,
+ DW_OP_skip = 0x2f,
+ DW_OP_lit0 = 0x30,
+ DW_OP_lit1 = 0x31,
+ DW_OP_lit2 = 0x32,
+ DW_OP_lit3 = 0x33,
+ DW_OP_lit4 = 0x34,
+ DW_OP_lit5 = 0x35,
+ DW_OP_lit6 = 0x36,
+ DW_OP_lit7 = 0x37,
+ DW_OP_lit8 = 0x38,
+ DW_OP_lit9 = 0x39,
+ DW_OP_lit10 = 0x3a,
+ DW_OP_lit11 = 0x3b,
+ DW_OP_lit12 = 0x3c,
+ DW_OP_lit13 = 0x3d,
+ DW_OP_lit14 = 0x3e,
+ DW_OP_lit15 = 0x3f,
+ DW_OP_lit16 = 0x40,
+ DW_OP_lit17 = 0x41,
+ DW_OP_lit18 = 0x42,
+ DW_OP_lit19 = 0x43,
+ DW_OP_lit20 = 0x44,
+ DW_OP_lit21 = 0x45,
+ DW_OP_lit22 = 0x46,
+ DW_OP_lit23 = 0x47,
+ DW_OP_lit24 = 0x48,
+ DW_OP_lit25 = 0x49,
+ DW_OP_lit26 = 0x4a,
+ DW_OP_lit27 = 0x4b,
+ DW_OP_lit28 = 0x4c,
+ DW_OP_lit29 = 0x4d,
+ DW_OP_lit30 = 0x4e,
+ DW_OP_lit31 = 0x4f,
+ DW_OP_reg0 = 0x50,
+ DW_OP_reg1 = 0x51,
+ DW_OP_reg2 = 0x52,
+ DW_OP_reg3 = 0x53,
+ DW_OP_reg4 = 0x54,
+ DW_OP_reg5 = 0x55,
+ DW_OP_reg6 = 0x56,
+ DW_OP_reg7 = 0x57,
+ DW_OP_reg8 = 0x58,
+ DW_OP_reg9 = 0x59,
+ DW_OP_reg10 = 0x5a,
+ DW_OP_reg11 = 0x5b,
+ DW_OP_reg12 = 0x5c,
+ DW_OP_reg13 = 0x5d,
+ DW_OP_reg14 = 0x5e,
+ DW_OP_reg15 = 0x5f,
+ DW_OP_reg16 = 0x60,
+ DW_OP_reg17 = 0x61,
+ DW_OP_reg18 = 0x62,
+ DW_OP_reg19 = 0x63,
+ DW_OP_reg20 = 0x64,
+ DW_OP_reg21 = 0x65,
+ DW_OP_reg22 = 0x66,
+ DW_OP_reg23 = 0x67,
+ DW_OP_reg24 = 0x68,
+ DW_OP_reg25 = 0x69,
+ DW_OP_reg26 = 0x6a,
+ DW_OP_reg27 = 0x6b,
+ DW_OP_reg28 = 0x6c,
+ DW_OP_reg29 = 0x6d,
+ DW_OP_reg30 = 0x6e,
+ DW_OP_reg31 = 0x6f,
+ DW_OP_breg0 = 0x70,
+ DW_OP_breg1 = 0x71,
+ DW_OP_breg2 = 0x72,
+ DW_OP_breg3 = 0x73,
+ DW_OP_breg4 = 0x74,
+ DW_OP_breg5 = 0x75,
+ DW_OP_breg6 = 0x76,
+ DW_OP_breg7 = 0x77,
+ DW_OP_breg8 = 0x78,
+ DW_OP_breg9 = 0x79,
+ DW_OP_breg10 = 0x7a,
+ DW_OP_breg11 = 0x7b,
+ DW_OP_breg12 = 0x7c,
+ DW_OP_breg13 = 0x7d,
+ DW_OP_breg14 = 0x7e,
+ DW_OP_breg15 = 0x7f,
+ DW_OP_breg16 = 0x80,
+ DW_OP_breg17 = 0x81,
+ DW_OP_breg18 = 0x82,
+ DW_OP_breg19 = 0x83,
+ DW_OP_breg20 = 0x84,
+ DW_OP_breg21 = 0x85,
+ DW_OP_breg22 = 0x86,
+ DW_OP_breg23 = 0x87,
+ DW_OP_breg24 = 0x88,
+ DW_OP_breg25 = 0x89,
+ DW_OP_breg26 = 0x8a,
+ DW_OP_breg27 = 0x8b,
+ DW_OP_breg28 = 0x8c,
+ DW_OP_breg29 = 0x8d,
+ DW_OP_breg30 = 0x8e,
+ DW_OP_breg31 = 0x8f,
+ DW_OP_regx = 0x90,
+ DW_OP_fbreg = 0x91,
+ DW_OP_bregx = 0x92,
+ DW_OP_piece = 0x93,
+ DW_OP_deref_size = 0x94,
+ DW_OP_xderef_size = 0x95,
+ DW_OP_nop = 0x96,
+ /* DWARF 3 extensions. */
+ DW_OP_push_object_address = 0x97,
+ DW_OP_call2 = 0x98,
+ DW_OP_call4 = 0x99,
+ DW_OP_call_ref = 0x9a,
+ /* GNU extensions. */
+ DW_OP_GNU_push_tls_address = 0xe0,
+ /* HP extensions. */
+ DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */
+ DW_OP_HP_is_value = 0xe1,
+ DW_OP_HP_fltconst4 = 0xe2,
+ DW_OP_HP_fltconst8 = 0xe3,
+ DW_OP_HP_mod_range = 0xe4,
+ DW_OP_HP_unmod_range = 0xe5,
+ DW_OP_HP_tls = 0xe6
+ };
+
+#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */
+#define DW_OP_hi_user 0xff /* Implementation-defined range end. */
+
+/* Type encodings. */
+enum dwarf_type
+ {
+ DW_ATE_void = 0x0,
+ DW_ATE_address = 0x1,
+ DW_ATE_boolean = 0x2,
+ DW_ATE_complex_float = 0x3,
+ DW_ATE_float = 0x4,
+ DW_ATE_signed = 0x5,
+ DW_ATE_signed_char = 0x6,
+ DW_ATE_unsigned = 0x7,
+ DW_ATE_unsigned_char = 0x8,
+ /* DWARF 3. */
+ DW_ATE_imaginary_float = 0x9,
+ /* HP extensions. */
+ DW_ATE_HP_float80 = 0x80, /* Floating-point (80 bit). */
+ DW_ATE_HP_complex_float80 = 0x81, /* Complex floating-point (80 bit). */
+ DW_ATE_HP_float128 = 0x82, /* Floating-point (128 bit). */
+ DW_ATE_HP_complex_float128 = 0x83, /* Complex floating-point (128 bit). */
+ DW_ATE_HP_floathpintel = 0x84, /* Floating-point (82 bit IA64). */
+ DW_ATE_HP_imaginary_float80 = 0x85,
+ DW_ATE_HP_imaginary_float128 = 0x86
+ };
+
+#define DW_ATE_lo_user 0x80
+#define DW_ATE_hi_user 0xff
+
+/* Array ordering names and codes. */
+enum dwarf_array_dim_ordering
+ {
+ DW_ORD_row_major = 0,
+ DW_ORD_col_major = 1
+ };
+
+/* Access attribute. */
+enum dwarf_access_attribute
+ {
+ DW_ACCESS_public = 1,
+ DW_ACCESS_protected = 2,
+ DW_ACCESS_private = 3
+ };
+
+/* Visibility. */
+enum dwarf_visibility_attribute
+ {
+ DW_VIS_local = 1,
+ DW_VIS_exported = 2,
+ DW_VIS_qualified = 3
+ };
+
+/* Virtuality. */
+enum dwarf_virtuality_attribute
+ {
+ DW_VIRTUALITY_none = 0,
+ DW_VIRTUALITY_virtual = 1,
+ DW_VIRTUALITY_pure_virtual = 2
+ };
+
+/* Case sensitivity. */
+enum dwarf_id_case
+ {
+ DW_ID_case_sensitive = 0,
+ DW_ID_up_case = 1,
+ DW_ID_down_case = 2,
+ DW_ID_case_insensitive = 3
+ };
+
+/* Calling convention. */
+enum dwarf_calling_convention
+ {
+ DW_CC_normal = 0x1,
+ DW_CC_program = 0x2,
+ DW_CC_nocall = 0x3
+ };
+
+#define DW_CC_lo_user 0x40
+#define DW_CC_hi_user 0xff
+
+/* Inline attribute. */
+enum dwarf_inline_attribute
+ {
+ DW_INL_not_inlined = 0,
+ DW_INL_inlined = 1,
+ DW_INL_declared_not_inlined = 2,
+ DW_INL_declared_inlined = 3
+ };
+
+/* Discriminant lists. */
+enum dwarf_discrim_list
+ {
+ DW_DSC_label = 0,
+ DW_DSC_range = 1
+ };
+
+/* Line number opcodes. */
+enum dwarf_line_number_ops
+ {
+ DW_LNS_extended_op = 0,
+ DW_LNS_copy = 1,
+ DW_LNS_advance_pc = 2,
+ DW_LNS_advance_line = 3,
+ DW_LNS_set_file = 4,
+ DW_LNS_set_column = 5,
+ DW_LNS_negate_stmt = 6,
+ DW_LNS_set_basic_block = 7,
+ DW_LNS_const_add_pc = 8,
+ DW_LNS_fixed_advance_pc = 9,
+ /* DWARF 3. */
+ DW_LNS_set_prologue_end = 10,
+ DW_LNS_set_epilogue_begin = 11,
+ DW_LNS_set_isa = 12
+ };
+
+/* Line number extended opcodes. */
+enum dwarf_line_number_x_ops
+ {
+ DW_LNE_end_sequence = 1,
+ DW_LNE_set_address = 2,
+ DW_LNE_define_file = 3,
+ /* HP extensions. */
+ DW_LNE_HP_negate_is_UV_update = 0x11,
+ DW_LNE_HP_push_context = 0x12,
+ DW_LNE_HP_pop_context = 0x13,
+ DW_LNE_HP_set_file_line_column = 0x14,
+ DW_LNE_HP_set_routine_name = 0x15,
+ DW_LNE_HP_set_sequence = 0x16,
+ DW_LNE_HP_negate_post_semantics = 0x17,
+ DW_LNE_HP_negate_function_exit = 0x18,
+ DW_LNE_HP_negate_front_end_logical = 0x19,
+ DW_LNE_HP_define_proc = 0x20
+ };
+
+/* Call frame information. */
+enum dwarf_call_frame_info
+ {
+ DW_CFA_advance_loc = 0x40,
+ DW_CFA_offset = 0x80,
+ DW_CFA_restore = 0xc0,
+ DW_CFA_nop = 0x00,
+ DW_CFA_set_loc = 0x01,
+ DW_CFA_advance_loc1 = 0x02,
+ DW_CFA_advance_loc2 = 0x03,
+ DW_CFA_advance_loc4 = 0x04,
+ DW_CFA_offset_extended = 0x05,
+ DW_CFA_restore_extended = 0x06,
+ DW_CFA_undefined = 0x07,
+ DW_CFA_same_value = 0x08,
+ DW_CFA_register = 0x09,
+ DW_CFA_remember_state = 0x0a,
+ DW_CFA_restore_state = 0x0b,
+ DW_CFA_def_cfa = 0x0c,
+ DW_CFA_def_cfa_register = 0x0d,
+ DW_CFA_def_cfa_offset = 0x0e,
+ /* DWARF 3. */
+ DW_CFA_def_cfa_expression = 0x0f,
+ DW_CFA_expression = 0x10,
+ DW_CFA_offset_extended_sf = 0x11,
+ DW_CFA_def_cfa_sf = 0x12,
+ DW_CFA_def_cfa_offset_sf = 0x13,
+ /* SGI/MIPS specific. */
+ DW_CFA_MIPS_advance_loc8 = 0x1d,
+ /* GNU extensions. */
+ DW_CFA_GNU_window_save = 0x2d,
+ DW_CFA_GNU_args_size = 0x2e,
+ DW_CFA_GNU_negative_offset_extended = 0x2f
+ };
+
+#define DW_CIE_ID 0xffffffff
+#define DW_CIE_VERSION 1
+
+#define DW_CFA_extended 0
+#define DW_CFA_lo_user 0x1c
+#define DW_CFA_hi_user 0x3f
+
+#define DW_CHILDREN_no 0x00
+#define DW_CHILDREN_yes 0x01
+
+#define DW_ADDR_none 0
+
+/* Source language names and codes. */
+enum dwarf_source_language
+ {
+ DW_LANG_C89 = 0x0001,
+ DW_LANG_C = 0x0002,
+ DW_LANG_Ada83 = 0x0003,
+ DW_LANG_C_plus_plus = 0x0004,
+ DW_LANG_Cobol74 = 0x0005,
+ DW_LANG_Cobol85 = 0x0006,
+ DW_LANG_Fortran77 = 0x0007,
+ DW_LANG_Fortran90 = 0x0008,
+ DW_LANG_Pascal83 = 0x0009,
+ DW_LANG_Modula2 = 0x000a,
+ DW_LANG_Java = 0x000b,
+ /* DWARF 3. */
+ DW_LANG_C99 = 0x000c,
+ DW_LANG_Ada95 = 0x000d,
+ DW_LANG_Fortran95 = 0x000e,
+ /* MIPS. */
+ DW_LANG_Mips_Assembler = 0x8001,
+ /* UPC. */
+ DW_LANG_Upc = 0x8765
+ };
+
+#define DW_LANG_lo_user 0x8000 /* Implementation-defined range start. */
+#define DW_LANG_hi_user 0xffff /* Implementation-defined range start. */
+
+/* Names and codes for macro information. */
+enum dwarf_macinfo_record_type
+ {
+ DW_MACINFO_define = 1,
+ DW_MACINFO_undef = 2,
+ DW_MACINFO_start_file = 3,
+ DW_MACINFO_end_file = 4,
+ DW_MACINFO_vendor_ext = 255
+ };
+
+/* @@@ For use with GNU frame unwind information. */
+
+#define DW_EH_PE_absptr 0x00
+#define DW_EH_PE_omit 0xff
+
+#define DW_EH_PE_uleb128 0x01
+#define DW_EH_PE_udata2 0x02
+#define DW_EH_PE_udata4 0x03
+#define DW_EH_PE_udata8 0x04
+#define DW_EH_PE_sleb128 0x09
+#define DW_EH_PE_sdata2 0x0A
+#define DW_EH_PE_sdata4 0x0B
+#define DW_EH_PE_sdata8 0x0C
+#define DW_EH_PE_signed 0x08
+
+#define DW_EH_PE_pcrel 0x10
+#define DW_EH_PE_textrel 0x20
+#define DW_EH_PE_datarel 0x30
+#define DW_EH_PE_funcrel 0x40
+#define DW_EH_PE_aligned 0x50
+
+#define DW_EH_PE_indirect 0x80
+
+#endif /* _ELF_DWARF2_H */
Binary files linux-2.6.0-akgdb/scripts/bin2c and linux/scripts/bin2c differ
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/scripts/dwarfh.awk linux/scripts/dwarfh.awk
--- linux-2.6.0-akgdb/scripts/dwarfh.awk 1969-12-31 16:00:00.000000000 -0800
+++ linux/scripts/dwarfh.awk 2004-01-22 12:58:07.000000000 -0800
@@ -0,0 +1,19 @@
+BEGIN {
+ print "#ifndef _ELF_DWARF_H"
+ print "/* Machine generated from dwarf2.h by scripts/dwarfh.awk */"
+}
+$2 == "=" {
+ gsub(/,/, "", $3)
+ print "#define " $1 "\t " $3
+}
+$1 == "#define" {
+ print $0
+ while( index($0,"\\") == length($0)){
+ getline
+ print $0
+ }
+}
+/.*/ {}
+END {
+ print "#endif"
+}


Attachments:
kgdb-dwarf2-2.6.0-1.0.patch (38.94 kB)

2004-01-24 03:48:46

by George Anzinger

[permalink] [raw]
Subject: [PATCH] Kgdb dwarf2 for asm

diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/Makefile linux/Makefile
--- linux-2.6.0-akgdb/Makefile 2004-01-08 15:36:35.000000000 -0800
+++ linux/Makefile 2004-01-22 13:01:31.000000000 -0800
@@ -1025,5 +1025,7 @@
descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2)

endif # skip-makefile
+include/linux/dwarf2-defs.h: include/linux/dwarf2.h scripts/dwarfh.awk
+ awk -f scripts/dwarfh.awk include/linux/dwarf2.h > include/linux/dwarf2-defs.h

-FORCE:
+FORCE: include/linux/dwarf2-defs.h
Binary files linux-2.6.0-akgdb/a.out and linux/a.out differ
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/arch/i386/Kconfig linux/arch/i386/Kconfig
--- linux-2.6.0-akgdb/arch/i386/Kconfig 2004-01-08 15:39:58.000000000 -0800
+++ linux/arch/i386/Kconfig 2004-01-09 14:50:07.000000000 -0800
@@ -1196,7 +1196,7 @@

config DEBUG_INFO
bool "Compile the kernel with debug info"
- depends on DEBUG_KERNEL
+ depends on DEBUG_KERNEL && !KGDB
help
If you say Y here the resulting kernel image will include
debugging info resulting in a larger kernel image.
@@ -1227,7 +1227,7 @@
will then break as soon as it looks at the boot options. This
option also installs a breakpoint in panic and sends any
kernel faults to the debugger. For more information see the
- Documentation/i386/kgdb.txt file.
+ Documentation/i386/kgdb/kgdb.txt file.

choice
depends on KGDB
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/arch/i386/Makefile linux/arch/i386/Makefile
--- linux-2.6.0-akgdb/arch/i386/Makefile 2004-01-08 15:39:58.000000000 -0800
+++ linux/arch/i386/Makefile 2004-01-13 16:04:02.000000000 -0800
@@ -100,7 +100,9 @@
drivers-$(CONFIG_PM) += arch/i386/power/

CFLAGS += $(mflags-y)
-AFLAGS += $(mflags-y)
+aflags-y = $(mflags-y)
+aflags-$(CONFIG_KGDB) += -save-temps
+AFLAGS += $(aflags-y)

boot := arch/i386/boot

diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.6.0-akgdb/arch/i386/kernel/entry.S 2004-01-13 15:53:06.000000000 -0800
+++ linux/arch/i386/kernel/entry.S 2004-01-23 16:03:00.000000000 -0800
@@ -910,3 +910,116 @@
.long sys_ni_syscall /* sys_vserver */

syscall_table_size=(.-sys_call_table)
+
+# Here we do call frames. We cheat a bit as we only really need
+# correct frames at locations we can actually look at from a
+# debugger. Since the break instruction trap actually goes thru
+# some of this code, we don't really need info on those areas, but
+# only after the fact. I.e. if we can not step or break in a
+# location or end up with a return address pointing at the
+# location, we don't need a correct call frame for it.
+
+#ifdef CONFIG_KGDB
+
+#include <linux/dwarf2-lang.h>
+/*
+ * The register numbers as known by gdb
+ */
+cfa_one: .long 1
+
+#define _EAX 0
+#define _ECX 1
+#define _EDX 2
+#define _EBX 3
+#define _ESP 4
+#define _EBP 5
+#define _ESI 6
+#define _EDI 7
+#define _PC 8
+#define _EIP 8
+#define _PS 9
+#define _EFLAGS 9
+#define _CS 10
+#define _SS 11
+#define _DS 12
+#define _ES 13
+#define _FS 14
+#define _GS 15
+
+ CFI_preamble(c1,_PC,1,1)
+ CFA_def_cfa_expression
+ CFA_exp_OP_breg(_ESP,OLDESP) /* push the stack & adjust */
+ CFA_exp_OP_dup /* save that */
+ CFA_exp_OP_consts(-8) /* offset to CS address */
+ CFA_exp_OP_plus /* should be CS address */
+ CFA_exp_OP_deref /* get the CS */
+ CFA_exp_OP_const4s(VM_MASK|3) /* prepare to mask it */
+ CFA_exp_OP_and /* mask it, zero means kernel */
+ CFA_exp_OP_bra(cfa_user_rtn) /* branch if user (TOS--) */
+ CFA_exp_OP_skip(cfa_end) /* done if kernel, skip out */
+cfa_user_rtn:
+ CFA_exp_OP_constu(0) /* user space, set exp to 0 */
+cfa_end:
+ CFA_expression_end
+ CFA_expression(_EIP)
+ CFA_exp_OP_dup /* copy old esp */
+ CFA_exp_OP_bra(eip_kernel_rtn) /* non-zero means kernel */
+ CFA_exp_OP_addr(cfa_one) /* for user, pass 1 */
+ CFA_exp_OP_skip(eip_end) /* done if kernel, skip out */
+eip_kernel_rtn:
+ CFA_exp_OP_const4s(EIP-OLDESP) /* offset to return address */
+ CFA_exp_OP_plus
+eip_end:
+ CFA_expression_end
+ CFA_define_offset(_EBX,EBX-OLDESP)
+ CFA_define_offset(_ECX,ECX-OLDESP)
+ CFA_define_offset(_EDX,EDX-OLDESP)
+ CFA_define_offset(_ESI,ESI-OLDESP)
+ CFA_define_offset(_EDI,EDI-OLDESP)
+ CFA_define_offset(_EBP,EBP-OLDESP)
+ CFA_define_offset(_EAX,EAX-OLDESP)
+ CFA_define_offset(_EFLAGS,EFLAGS-OLDESP)
+ CFI_postamble()
+
+/*
+ * This is an attempt to provide an unwind for location 0 which is
+ * identical to the prior frame. Should stop the unwind. Note that gdb
+ * uses the pc-1 to look for FDEs so the correct pc is 1 not 0 which,
+ * because of addresses being unsigned, can not be used by man nor beast.
+ */
+ CFI_preamble(c2,_PC,1,1)
+ CFA_def_cfa_expression
+ CFA_exp_OP_constu(0) /* stack end, set exp to 0 */
+ CFA_expression_end
+ CFI_postamble()
+
+ FDE_preamble(c2,0,10)
+ FDE_postamble()
+ /*
+ * This is VERY sloppy. At this point all we want to do is get
+ * the frame right for back tracing. It will not be good if
+ * you try to single step. We use already defined labels.
+ * We want to cover all call outs.
+ * We could also recode this as just one FDE, but this works and
+ * I want to get it out.
+ */
+ FDE_preamble(c1,do_lcall,(ret_from_fork - do_lcall))
+ CFA_define_cfa_offset(OLDESP+8)
+ FDE_postamble()
+ FDE_preamble(c1,ret_from_fork,(ret_from_exception - ret_from_fork))
+ CFA_define_cfa_offset(OLDESP+4)
+ FDE_postamble()
+ FDE_preamble(c1,ret_from_exception,(divide_error - ret_from_exception))
+ FDE_postamble()
+ FDE_preamble(c1,error_code,(device_not_available_emulate - error_code))
+ CFA_define_cfa_offset(OLDESP+8)
+ FDE_postamble()
+ FDE_preamble(c1,device_not_available_emulate,(debug - device_not_available_emulate))
+ CFA_define_cfa_offset(OLDESP+4)
+ FDE_postamble()
+ FDE_preamble(c1,nmi,(int3 - nmi))
+ CFA_define_cfa_offset(OLDESP+8)
+ FDE_postamble()
+
+#
+#endif
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- linux-2.6.0-akgdb/arch/i386/kernel/head.S 2003-09-08 14:15:17.000000000 -0700
+++ linux/arch/i386/kernel/head.S 2004-01-23 16:19:21.000000000 -0800
@@ -278,6 +278,16 @@
# just in case, we know what happens.

ready: .byte 0
+#ifdef CONFIG_KGDB
+#include <linux/dwarf2-lang.h>
+
+ /* This dwarf code tells gdb that this is the end of the unwind */
+ /* This uses the CFA set up for pc=1 located in entry.S */
+
+ FDE_preamble(c2,is386,(L6-is386))
+ FDE_postamble()
+
+#endif

/*
* We depend on ET to be correct. This checks for 287/387.
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- linux-2.6.0-akgdb/arch/i386/kernel/smpboot.c 2003-11-10 15:59:40.000000000 -0800
+++ linux/arch/i386/kernel/smpboot.c 2004-01-18 00:33:32.000000000 -0800
@@ -476,6 +476,9 @@

asm volatile(
"movl %0,%%esp\n\t"
+#ifdef CONFIG_KGDB
+ "pushl $1\n\t"
+#endif
"jmp *%1"
:
:"r" (current->thread.esp),"r" (current->thread.eip));
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/include/linux/dwarf2-lang.h linux/include/linux/dwarf2-lang.h
--- linux-2.6.0-akgdb/include/linux/dwarf2-lang.h 1969-12-31 16:00:00.000000000 -0800
+++ linux/include/linux/dwarf2-lang.h 2004-01-22 13:06:43.000000000 -0800
@@ -0,0 +1,286 @@
+#ifndef DWARF2_LANG
+#define DWARF2_LANG
+
+/*
+ * This 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, or (at your option) any later
+ * version.
+ */
+/*
+ * This file defines macros that allow generation of DWARF debug records
+ * for asm files. This file is platform independent. Register numbers
+ * (which are about the only thing that is platform dependent) are to be
+ * supplied by a platform defined file.
+ */
+/*
+ * We need this to work for both asm and C. In asm we are using the
+ * old comment trick to concatenate while C uses the new ANSI thing.
+ * Here we have concat macro... The multi level thing is to allow and
+ * macros used in the names to be resolved prior to the cat (at which
+ * time they are no longer the same string).
+ */
+#define CAT3(a,b,c) _CAT3(a,b,c)
+#define _CAT3(a,b,c) __CAT3(a,b,c)
+#ifdef __ASSEMBLY__
+#define __CAT3(a,b,c) a/**/b/**/c
+#define IFC(a)
+#define IFN_C(a) a
+#define NL ;
+#define QUOTE_THIS(a) a
+#define DWARF_preamble .section .debug_frame,"",@progbits;
+#else
+#define __CAT3(a,b,c) a ## b ## c
+#define IFC(a) a
+#define IFN_C(a)
+#define NL \n\t
+#define QUOTE_THIS(a) _QUOTE_THIS(a)
+#define _QUOTE_THIS(a) #a
+/* Don't let CPP see the " and , \042=" \054=, */
+#define DWARF_preamble .section .debug_frame \054\042\042\054@progbits
+
+#endif
+#include <linux/dwarf2-defs.h>
+/*
+ * This macro starts a debug frame section. The debug_frame describes
+ * where to find the registers that the enclosing function saved on
+ * entry.
+ *
+ * ORD is use by the label generator and should be the same as what is
+ * passed to CFI_postamble.
+ *
+ * pc, pc register gdb ordinal.
+ *
+ * code_align this is the factor used to define locations or regions
+ * where the given definitions apply. If you use labels to define these
+ * this should be 1.
+ *
+ * data_align this is the factor used to define register offsets. If
+ * you use struct offset, this should be the size of the register in
+ * bytes or the negative of that. This is how it is used: you will
+ * define a register as the reference register, say the stack pointer,
+ * then you will say where a register is located relative to this
+ * reference registers value, say 40 for register 3 (the gdb register
+ * number). The <40> will be multiplied by <data_align> to define the
+ * byte offset of the given register (3, in this example). So if your
+ * <40> is the byte offset and the reference register points at the
+ * begining, you would want 1 for the data_offset. If <40> was the 40th
+ * 4-byte element in that structure you would want 4. And if your
+ * reference register points at the end of the structure you would want
+ * a negative data_align value(and you would have to do other math as
+ * well).
+ */
+
+#define CFI_preamble(ORD, pc, code_align, data_align) \
+ DWARF_preamble NL \
+ .align 4 NL \
+ .globl CAT3(frame,_,ORD) NL \
+CAT3(frame,_,ORD): NL \
+ .long 7f-6f NL \
+6: \
+ .long DW_CIE_ID NL \
+ .byte DW_CIE_VERSION NL \
+ .byte 0 NL \
+ .uleb128 code_align NL \
+ .sleb128 data_align NL \
+ .byte pc NL
+
+/*
+ * After the above macro and prior to the CFI_postamble, you need to
+ * define the initial state. This starts with defining the reference
+ * register and, usually the pc. Here are some helper macros:
+ */
+
+#define CFA_define_reference(reg, offset) \
+ .byte DW_CFA_def_cfa NL \
+ .uleb128 reg NL \
+ .uleb128 (offset) NL
+
+#define CFA_define_offset(reg, offset) \
+ .byte (DW_CFA_offset + reg) NL \
+ .uleb128 (offset) NL
+
+#define CFA_restore(reg) \
+ .byte (DW_CFA_restore + reg) NL
+
+#define CFI_postamble() \
+ .align 4 NL \
+7: NL \
+.previous NL
+/*
+ * So now your code pushs stuff on the stack, you need a new location
+ * and the rules for what to do. This starts a running description of
+ * the call frame. You need to describe what changes with respect to
+ * the call registers as the location of the pc moves through the code.
+ * The following builds an FDE (fram descriptor entry?). Like the
+ * above, it has a preamble and a postamble. It also is tied to the CFI
+ * above.
+ * The preamble macro is tied to the CFI thru the first parameter. The
+ * second is the code start address and then the code length.
+ */
+// DWARF_preamble() NL
+#define FDE_preamble(ORD, initial_address, length) \
+ DWARF_preamble NL \
+ .align 4 NL \
+ .long 9f-8f NL \
+8: \
+ .long CAT3(frame,_,ORD) NL \
+ .long initial_address NL \
+ .long length NL
+
+#define FDE_postamble() \
+ .align 4 NL \
+9: NL \
+.previous NL
+/*
+ * That done, you can now add registers, subtract registers, move the
+ * reference and even change the reference. You can also define a new
+ * area of code the info applies to. For discontinuous bits you should
+ * start a new FDE. You may have as many as you like.
+ */
+
+/*
+ * To advance the stack address by <bytes> (0x3f max)
+ */
+
+#define CFA_advance_loc(bytes) \
+ .byte DW_CFA_advance_loc+bytes NL
+
+/*
+ * This one is good for 0xff or 255
+ */
+#define CFA_advance_loc1(bytes) \
+ .byte DW_CFA_advance_loc1 NL \
+ .byte bytes NL
+
+
+/*
+ * With the above you can define all the register locations. But
+ * suppose the reference register moves... Takes the new offset NOT an
+ * increment. This is how esp is tracked if it is not saved.
+ */
+
+#define CFA_define_cfa_offset(offset) \
+ .byte DW_CFA_def_cfa_offset NL \
+ .uleb128 (offset) NL
+/*
+ * Or suppose you want to use a different reference register...
+ */
+#define CFA_define_cfa_register(reg) \
+ .byte DW_CFA_def_cfa_register NL \
+ .uleb128 reg NL
+
+/*
+ * If you want to mess with the stack pointer, here is the expression.
+ * The stack starts empty.
+ */
+#define CFA_def_cfa_expression \
+ .byte DW_CFA_def_cfa_expression NL \
+ .uleb128 20f-10f NL \
+10: NL
+/*
+ * This expression is to be used for other regs. The stack starts with the
+ * stack address.
+ */
+
+#define CFA_expression(reg) \
+ .byte DW_CFA_expression NL \
+ .uleb128 reg NL \
+ .uleb128 20f-10f NL \
+10: NL
+/*
+ * Here we do the expression stuff. You should code the above followed
+ * by expression OPs followed by CFA_expression_end.
+ */
+
+
+#define CFA_expression_end \
+20: NL
+
+#define CFA_exp_OP_const4s(a) \
+ .byte DW_OP_const4s NL \
+ .long a NL
+
+#define CFA_exp_OP_swap .byte DW_OP_swap NL
+#define CFA_exp_OP_dup .byte DW_OP_dup NL
+#define CFA_exp_OP_drop .byte DW_OP_drop NL
+/*
+ * All these work on the top two elements on the stack, replacing them
+ * with the result. Top comes first where it matters. True is 1, false 0.
+ */
+#define CFA_exp_OP_deref .byte DW_OP_deref NL
+#define CFA_exp_OP_and .byte DW_OP_and NL
+#define CFA_exp_OP_div .byte DW_OP_div NL
+#define CFA_exp_OP_minus .byte DW_OP_minus NL
+#define CFA_exp_OP_mod .byte DW_OP_mod NL
+#define CFA_exp_OP_neg .byte DW_OP_neg NL
+#define CFA_exp_OP_plus .byte DW_OP_plus NL
+#define CFA_exp_OP_not .byte DW_OP_not NL
+#define CFA_exp_OP_or .byte DW_OP_or NL
+#define CFA_exp_OP_xor .byte DW_OP_xor NL
+#define CFA_exp_OP_le .byte DW_OP_le NL
+#define CFA_exp_OP_ge .byte DW_OP_ge NL
+#define CFA_exp_OP_eq .byte DW_OP_eq NL
+#define CFA_exp_OP_lt .byte DW_OP_lt NL
+#define CFA_exp_OP_gt .byte DW_OP_gt NL
+#define CFA_exp_OP_ne .byte DW_OP_ne NL
+/*
+ * These take a parameter as noted
+ */
+/*
+ * Unconditional skip to loc. loc is a label (loc:)
+ */
+#define CFA_exp_OP_skip(loc) \
+ .byte DW_OP_skip NL \
+ .hword loc-.-2 NL
+/*
+ * Conditional skip to loc (TOS != 0, TOS--) (loc is a label)
+ */
+#define CFA_exp_OP_bra(loc) \
+ .byte DW_OP_bra NL \
+ .hword loc-.-2 NL
+
+/*
+ * TOS += no (an unsigned number)
+ */
+#define CFA_exp_OP_plus_uconst(no) \
+ .byte DW_OP_plus_uconst NL \
+ .uleb128 no NL
+
+/*
+ * ++TOS = no (a unsigned number)
+ */
+#define CFA_exp_OP_constu(no) \
+ .byte DW_OP_constu NL \
+ .uleb128 no NL
+/*
+ * ++TOS = no (a signed number)
+ */
+#define CFA_exp_OP_consts(no) \
+ .byte DW_OP_consts NL \
+ .sleb128 no NL
+/*
+ * ++TOS = no (an unsigned byte)
+ */
+#define CFA_exp_OP_const1u(no) \
+ .byte DW_OP_const1u NL \
+ .byte no NL
+
+
+/*
+ * ++TOS = no (a address)
+ */
+#define CFA_exp_OP_addr(no) \
+ .byte DW_OP_addr NL \
+ .long no NL
+
+/*
+ * Push current frames value for "reg" + offset
+ * We take advantage of the opcode assignments to make this a litteral reg
+ * rather than use the DW_OP_bregx opcode.
+ */
+
+#define CFA_exp_OP_breg(reg,offset) \
+ .byte DW_OP_breg0+reg NL \
+ .sleb128 offset NL
+#endif
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/include/linux/dwarf2.h linux/include/linux/dwarf2.h
--- linux-2.6.0-akgdb/include/linux/dwarf2.h 1969-12-31 16:00:00.000000000 -0800
+++ linux/include/linux/dwarf2.h 2004-01-15 00:26:12.000000000 -0800
@@ -0,0 +1,775 @@
+/* Declarations and definitions of codes relating to the DWARF2 symbolic
+ debugging information format.
+ Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
+ 2003 Free Software Foundation, Inc.
+
+ Written by Gary Funck ([email protected]) The Ada Joint Program
+ Office (AJPO), Florida State Unviversity and Silicon Graphics Inc.
+ provided support for this effort -- June 21, 1995.
+
+ Derived from the DWARF 1 implementation written by Ron Guilmette
+ ([email protected]), November 1990.
+
+ This file is part of GCC.
+
+ GCC 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, or (at your option) any later
+ version.
+
+ GCC 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 GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* This file is derived from the DWARF specification (a public document)
+ Revision 2.0.0 (July 27, 1993) developed by the UNIX International
+ Programming Languages Special Interest Group (UI/PLSIG) and distributed
+ by UNIX International. Copies of this specification are available from
+ UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.
+
+ This file also now contains definitions from the DWARF 3 specification. */
+
+/* This file is shared between GCC and GDB, and should not contain
+ prototypes. */
+
+#ifndef _ELF_DWARF2_H
+#define _ELF_DWARF2_H
+
+/* Structure found in the .debug_line section. */
+typedef struct
+{
+ unsigned char li_length [4];
+ unsigned char li_version [2];
+ unsigned char li_prologue_length [4];
+ unsigned char li_min_insn_length [1];
+ unsigned char li_default_is_stmt [1];
+ unsigned char li_line_base [1];
+ unsigned char li_line_range [1];
+ unsigned char li_opcode_base [1];
+}
+DWARF2_External_LineInfo;
+
+typedef struct
+{
+ unsigned long li_length;
+ unsigned short li_version;
+ unsigned int li_prologue_length;
+ unsigned char li_min_insn_length;
+ unsigned char li_default_is_stmt;
+ int li_line_base;
+ unsigned char li_line_range;
+ unsigned char li_opcode_base;
+}
+DWARF2_Internal_LineInfo;
+
+/* Structure found in .debug_pubnames section. */
+typedef struct
+{
+ unsigned char pn_length [4];
+ unsigned char pn_version [2];
+ unsigned char pn_offset [4];
+ unsigned char pn_size [4];
+}
+DWARF2_External_PubNames;
+
+typedef struct
+{
+ unsigned long pn_length;
+ unsigned short pn_version;
+ unsigned long pn_offset;
+ unsigned long pn_size;
+}
+DWARF2_Internal_PubNames;
+
+/* Structure found in .debug_info section. */
+typedef struct
+{
+ unsigned char cu_length [4];
+ unsigned char cu_version [2];
+ unsigned char cu_abbrev_offset [4];
+ unsigned char cu_pointer_size [1];
+}
+DWARF2_External_CompUnit;
+
+typedef struct
+{
+ unsigned long cu_length;
+ unsigned short cu_version;
+ unsigned long cu_abbrev_offset;
+ unsigned char cu_pointer_size;
+}
+DWARF2_Internal_CompUnit;
+
+typedef struct
+{
+ unsigned char ar_length [4];
+ unsigned char ar_version [2];
+ unsigned char ar_info_offset [4];
+ unsigned char ar_pointer_size [1];
+ unsigned char ar_segment_size [1];
+}
+DWARF2_External_ARange;
+
+typedef struct
+{
+ unsigned long ar_length;
+ unsigned short ar_version;
+ unsigned long ar_info_offset;
+ unsigned char ar_pointer_size;
+ unsigned char ar_segment_size;
+}
+DWARF2_Internal_ARange;
+
+
+/* Tag names and codes. */
+enum dwarf_tag
+ {
+ DW_TAG_padding = 0x00,
+ DW_TAG_array_type = 0x01,
+ DW_TAG_class_type = 0x02,
+ DW_TAG_entry_point = 0x03,
+ DW_TAG_enumeration_type = 0x04,
+ DW_TAG_formal_parameter = 0x05,
+ DW_TAG_imported_declaration = 0x08,
+ DW_TAG_label = 0x0a,
+ DW_TAG_lexical_block = 0x0b,
+ DW_TAG_member = 0x0d,
+ DW_TAG_pointer_type = 0x0f,
+ DW_TAG_reference_type = 0x10,
+ DW_TAG_compile_unit = 0x11,
+ DW_TAG_string_type = 0x12,
+ DW_TAG_structure_type = 0x13,
+ DW_TAG_subroutine_type = 0x15,
+ DW_TAG_typedef = 0x16,
+ DW_TAG_union_type = 0x17,
+ DW_TAG_unspecified_parameters = 0x18,
+ DW_TAG_variant = 0x19,
+ DW_TAG_common_block = 0x1a,
+ DW_TAG_common_inclusion = 0x1b,
+ DW_TAG_inheritance = 0x1c,
+ DW_TAG_inlined_subroutine = 0x1d,
+ DW_TAG_module = 0x1e,
+ DW_TAG_ptr_to_member_type = 0x1f,
+ DW_TAG_set_type = 0x20,
+ DW_TAG_subrange_type = 0x21,
+ DW_TAG_with_stmt = 0x22,
+ DW_TAG_access_declaration = 0x23,
+ DW_TAG_base_type = 0x24,
+ DW_TAG_catch_block = 0x25,
+ DW_TAG_const_type = 0x26,
+ DW_TAG_constant = 0x27,
+ DW_TAG_enumerator = 0x28,
+ DW_TAG_file_type = 0x29,
+ DW_TAG_friend = 0x2a,
+ DW_TAG_namelist = 0x2b,
+ DW_TAG_namelist_item = 0x2c,
+ DW_TAG_packed_type = 0x2d,
+ DW_TAG_subprogram = 0x2e,
+ DW_TAG_template_type_param = 0x2f,
+ DW_TAG_template_value_param = 0x30,
+ DW_TAG_thrown_type = 0x31,
+ DW_TAG_try_block = 0x32,
+ DW_TAG_variant_part = 0x33,
+ DW_TAG_variable = 0x34,
+ DW_TAG_volatile_type = 0x35,
+ /* DWARF 3. */
+ DW_TAG_dwarf_procedure = 0x36,
+ DW_TAG_restrict_type = 0x37,
+ DW_TAG_interface_type = 0x38,
+ DW_TAG_namespace = 0x39,
+ DW_TAG_imported_module = 0x3a,
+ DW_TAG_unspecified_type = 0x3b,
+ DW_TAG_partial_unit = 0x3c,
+ DW_TAG_imported_unit = 0x3d,
+ /* SGI/MIPS Extensions. */
+ DW_TAG_MIPS_loop = 0x4081,
+ /* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */
+ DW_TAG_HP_array_descriptor = 0x4090,
+ /* GNU extensions. */
+ DW_TAG_format_label = 0x4101, /* For FORTRAN 77 and Fortran 90. */
+ DW_TAG_function_template = 0x4102, /* For C++. */
+ DW_TAG_class_template = 0x4103, /* For C++. */
+ DW_TAG_GNU_BINCL = 0x4104,
+ DW_TAG_GNU_EINCL = 0x4105,
+ /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */
+ DW_TAG_upc_shared_type = 0x8765,
+ DW_TAG_upc_strict_type = 0x8766,
+ DW_TAG_upc_relaxed_type = 0x8767,
+ /* PGI (STMicroelectronics) extensions. No documentation available. */
+ DW_TAG_PGI_kanji_type = 0xA000,
+ DW_TAG_PGI_interface_block = 0xA020
+ };
+
+#define DW_TAG_lo_user 0x4080
+#define DW_TAG_hi_user 0xffff
+
+/* Flag that tells whether entry has a child or not. */
+#define DW_children_no 0
+#define DW_children_yes 1
+
+/* Form names and codes. */
+enum dwarf_form
+ {
+ DW_FORM_addr = 0x01,
+ DW_FORM_block2 = 0x03,
+ DW_FORM_block4 = 0x04,
+ DW_FORM_data2 = 0x05,
+ DW_FORM_data4 = 0x06,
+ DW_FORM_data8 = 0x07,
+ DW_FORM_string = 0x08,
+ DW_FORM_block = 0x09,
+ DW_FORM_block1 = 0x0a,
+ DW_FORM_data1 = 0x0b,
+ DW_FORM_flag = 0x0c,
+ DW_FORM_sdata = 0x0d,
+ DW_FORM_strp = 0x0e,
+ DW_FORM_udata = 0x0f,
+ DW_FORM_ref_addr = 0x10,
+ DW_FORM_ref1 = 0x11,
+ DW_FORM_ref2 = 0x12,
+ DW_FORM_ref4 = 0x13,
+ DW_FORM_ref8 = 0x14,
+ DW_FORM_ref_udata = 0x15,
+ DW_FORM_indirect = 0x16
+ };
+
+/* Attribute names and codes. */
+enum dwarf_attribute
+ {
+ DW_AT_sibling = 0x01,
+ DW_AT_location = 0x02,
+ DW_AT_name = 0x03,
+ DW_AT_ordering = 0x09,
+ DW_AT_subscr_data = 0x0a,
+ DW_AT_byte_size = 0x0b,
+ DW_AT_bit_offset = 0x0c,
+ DW_AT_bit_size = 0x0d,
+ DW_AT_element_list = 0x0f,
+ DW_AT_stmt_list = 0x10,
+ DW_AT_low_pc = 0x11,
+ DW_AT_high_pc = 0x12,
+ DW_AT_language = 0x13,
+ DW_AT_member = 0x14,
+ DW_AT_discr = 0x15,
+ DW_AT_discr_value = 0x16,
+ DW_AT_visibility = 0x17,
+ DW_AT_import = 0x18,
+ DW_AT_string_length = 0x19,
+ DW_AT_common_reference = 0x1a,
+ DW_AT_comp_dir = 0x1b,
+ DW_AT_const_value = 0x1c,
+ DW_AT_containing_type = 0x1d,
+ DW_AT_default_value = 0x1e,
+ DW_AT_inline = 0x20,
+ DW_AT_is_optional = 0x21,
+ DW_AT_lower_bound = 0x22,
+ DW_AT_producer = 0x25,
+ DW_AT_prototyped = 0x27,
+ DW_AT_return_addr = 0x2a,
+ DW_AT_start_scope = 0x2c,
+ DW_AT_stride_size = 0x2e,
+ DW_AT_upper_bound = 0x2f,
+ DW_AT_abstract_origin = 0x31,
+ DW_AT_accessibility = 0x32,
+ DW_AT_address_class = 0x33,
+ DW_AT_artificial = 0x34,
+ DW_AT_base_types = 0x35,
+ DW_AT_calling_convention = 0x36,
+ DW_AT_count = 0x37,
+ DW_AT_data_member_location = 0x38,
+ DW_AT_decl_column = 0x39,
+ DW_AT_decl_file = 0x3a,
+ DW_AT_decl_line = 0x3b,
+ DW_AT_declaration = 0x3c,
+ DW_AT_discr_list = 0x3d,
+ DW_AT_encoding = 0x3e,
+ DW_AT_external = 0x3f,
+ DW_AT_frame_base = 0x40,
+ DW_AT_friend = 0x41,
+ DW_AT_identifier_case = 0x42,
+ DW_AT_macro_info = 0x43,
+ DW_AT_namelist_items = 0x44,
+ DW_AT_priority = 0x45,
+ DW_AT_segment = 0x46,
+ DW_AT_specification = 0x47,
+ DW_AT_static_link = 0x48,
+ DW_AT_type = 0x49,
+ DW_AT_use_location = 0x4a,
+ DW_AT_variable_parameter = 0x4b,
+ DW_AT_virtuality = 0x4c,
+ DW_AT_vtable_elem_location = 0x4d,
+ /* DWARF 3 values. */
+ DW_AT_allocated = 0x4e,
+ DW_AT_associated = 0x4f,
+ DW_AT_data_location = 0x50,
+ DW_AT_stride = 0x51,
+ DW_AT_entry_pc = 0x52,
+ DW_AT_use_UTF8 = 0x53,
+ DW_AT_extension = 0x54,
+ DW_AT_ranges = 0x55,
+ DW_AT_trampoline = 0x56,
+ DW_AT_call_column = 0x57,
+ DW_AT_call_file = 0x58,
+ DW_AT_call_line = 0x59,
+ /* SGI/MIPS extensions. */
+ DW_AT_MIPS_fde = 0x2001,
+ DW_AT_MIPS_loop_begin = 0x2002,
+ DW_AT_MIPS_tail_loop_begin = 0x2003,
+ DW_AT_MIPS_epilog_begin = 0x2004,
+ DW_AT_MIPS_loop_unroll_factor = 0x2005,
+ DW_AT_MIPS_software_pipeline_depth = 0x2006,
+ DW_AT_MIPS_linkage_name = 0x2007,
+ DW_AT_MIPS_stride = 0x2008,
+ DW_AT_MIPS_abstract_name = 0x2009,
+ DW_AT_MIPS_clone_origin = 0x200a,
+ DW_AT_MIPS_has_inlines = 0x200b,
+ /* HP extensions. */
+ DW_AT_HP_block_index = 0x2000,
+ DW_AT_HP_unmodifiable = 0x2001, /* Same as DW_AT_MIPS_fde. */
+ DW_AT_HP_actuals_stmt_list = 0x2010,
+ DW_AT_HP_proc_per_section = 0x2011,
+ DW_AT_HP_raw_data_ptr = 0x2012,
+ DW_AT_HP_pass_by_reference = 0x2013,
+ DW_AT_HP_opt_level = 0x2014,
+ DW_AT_HP_prof_version_id = 0x2015,
+ DW_AT_HP_opt_flags = 0x2016,
+ DW_AT_HP_cold_region_low_pc = 0x2017,
+ DW_AT_HP_cold_region_high_pc = 0x2018,
+ DW_AT_HP_all_variables_modifiable = 0x2019,
+ DW_AT_HP_linkage_name = 0x201a,
+ DW_AT_HP_prof_flags = 0x201b, /* In comp unit of procs_info for -g. */
+ /* GNU extensions. */
+ DW_AT_sf_names = 0x2101,
+ DW_AT_src_info = 0x2102,
+ DW_AT_mac_info = 0x2103,
+ DW_AT_src_coords = 0x2104,
+ DW_AT_body_begin = 0x2105,
+ DW_AT_body_end = 0x2106,
+ DW_AT_GNU_vector = 0x2107,
+ /* VMS extensions. */
+ DW_AT_VMS_rtnbeg_pd_address = 0x2201,
+ /* UPC extension. */
+ DW_AT_upc_threads_scaled = 0x3210,
+ /* PGI (STMicroelectronics) extensions. */
+ DW_AT_PGI_lbase = 0x3a00,
+ DW_AT_PGI_soffset = 0x3a01,
+ DW_AT_PGI_lstride = 0x3a02
+ };
+
+#define DW_AT_lo_user 0x2000 /* Implementation-defined range start. */
+#define DW_AT_hi_user 0x3ff0 /* Implementation-defined range end. */
+
+/* Location atom names and codes. */
+enum dwarf_location_atom
+ {
+ DW_OP_addr = 0x03,
+ DW_OP_deref = 0x06,
+ DW_OP_const1u = 0x08,
+ DW_OP_const1s = 0x09,
+ DW_OP_const2u = 0x0a,
+ DW_OP_const2s = 0x0b,
+ DW_OP_const4u = 0x0c,
+ DW_OP_const4s = 0x0d,
+ DW_OP_const8u = 0x0e,
+ DW_OP_const8s = 0x0f,
+ DW_OP_constu = 0x10,
+ DW_OP_consts = 0x11,
+ DW_OP_dup = 0x12,
+ DW_OP_drop = 0x13,
+ DW_OP_over = 0x14,
+ DW_OP_pick = 0x15,
+ DW_OP_swap = 0x16,
+ DW_OP_rot = 0x17,
+ DW_OP_xderef = 0x18,
+ DW_OP_abs = 0x19,
+ DW_OP_and = 0x1a,
+ DW_OP_div = 0x1b,
+ DW_OP_minus = 0x1c,
+ DW_OP_mod = 0x1d,
+ DW_OP_mul = 0x1e,
+ DW_OP_neg = 0x1f,
+ DW_OP_not = 0x20,
+ DW_OP_or = 0x21,
+ DW_OP_plus = 0x22,
+ DW_OP_plus_uconst = 0x23,
+ DW_OP_shl = 0x24,
+ DW_OP_shr = 0x25,
+ DW_OP_shra = 0x26,
+ DW_OP_xor = 0x27,
+ DW_OP_bra = 0x28,
+ DW_OP_eq = 0x29,
+ DW_OP_ge = 0x2a,
+ DW_OP_gt = 0x2b,
+ DW_OP_le = 0x2c,
+ DW_OP_lt = 0x2d,
+ DW_OP_ne = 0x2e,
+ DW_OP_skip = 0x2f,
+ DW_OP_lit0 = 0x30,
+ DW_OP_lit1 = 0x31,
+ DW_OP_lit2 = 0x32,
+ DW_OP_lit3 = 0x33,
+ DW_OP_lit4 = 0x34,
+ DW_OP_lit5 = 0x35,
+ DW_OP_lit6 = 0x36,
+ DW_OP_lit7 = 0x37,
+ DW_OP_lit8 = 0x38,
+ DW_OP_lit9 = 0x39,
+ DW_OP_lit10 = 0x3a,
+ DW_OP_lit11 = 0x3b,
+ DW_OP_lit12 = 0x3c,
+ DW_OP_lit13 = 0x3d,
+ DW_OP_lit14 = 0x3e,
+ DW_OP_lit15 = 0x3f,
+ DW_OP_lit16 = 0x40,
+ DW_OP_lit17 = 0x41,
+ DW_OP_lit18 = 0x42,
+ DW_OP_lit19 = 0x43,
+ DW_OP_lit20 = 0x44,
+ DW_OP_lit21 = 0x45,
+ DW_OP_lit22 = 0x46,
+ DW_OP_lit23 = 0x47,
+ DW_OP_lit24 = 0x48,
+ DW_OP_lit25 = 0x49,
+ DW_OP_lit26 = 0x4a,
+ DW_OP_lit27 = 0x4b,
+ DW_OP_lit28 = 0x4c,
+ DW_OP_lit29 = 0x4d,
+ DW_OP_lit30 = 0x4e,
+ DW_OP_lit31 = 0x4f,
+ DW_OP_reg0 = 0x50,
+ DW_OP_reg1 = 0x51,
+ DW_OP_reg2 = 0x52,
+ DW_OP_reg3 = 0x53,
+ DW_OP_reg4 = 0x54,
+ DW_OP_reg5 = 0x55,
+ DW_OP_reg6 = 0x56,
+ DW_OP_reg7 = 0x57,
+ DW_OP_reg8 = 0x58,
+ DW_OP_reg9 = 0x59,
+ DW_OP_reg10 = 0x5a,
+ DW_OP_reg11 = 0x5b,
+ DW_OP_reg12 = 0x5c,
+ DW_OP_reg13 = 0x5d,
+ DW_OP_reg14 = 0x5e,
+ DW_OP_reg15 = 0x5f,
+ DW_OP_reg16 = 0x60,
+ DW_OP_reg17 = 0x61,
+ DW_OP_reg18 = 0x62,
+ DW_OP_reg19 = 0x63,
+ DW_OP_reg20 = 0x64,
+ DW_OP_reg21 = 0x65,
+ DW_OP_reg22 = 0x66,
+ DW_OP_reg23 = 0x67,
+ DW_OP_reg24 = 0x68,
+ DW_OP_reg25 = 0x69,
+ DW_OP_reg26 = 0x6a,
+ DW_OP_reg27 = 0x6b,
+ DW_OP_reg28 = 0x6c,
+ DW_OP_reg29 = 0x6d,
+ DW_OP_reg30 = 0x6e,
+ DW_OP_reg31 = 0x6f,
+ DW_OP_breg0 = 0x70,
+ DW_OP_breg1 = 0x71,
+ DW_OP_breg2 = 0x72,
+ DW_OP_breg3 = 0x73,
+ DW_OP_breg4 = 0x74,
+ DW_OP_breg5 = 0x75,
+ DW_OP_breg6 = 0x76,
+ DW_OP_breg7 = 0x77,
+ DW_OP_breg8 = 0x78,
+ DW_OP_breg9 = 0x79,
+ DW_OP_breg10 = 0x7a,
+ DW_OP_breg11 = 0x7b,
+ DW_OP_breg12 = 0x7c,
+ DW_OP_breg13 = 0x7d,
+ DW_OP_breg14 = 0x7e,
+ DW_OP_breg15 = 0x7f,
+ DW_OP_breg16 = 0x80,
+ DW_OP_breg17 = 0x81,
+ DW_OP_breg18 = 0x82,
+ DW_OP_breg19 = 0x83,
+ DW_OP_breg20 = 0x84,
+ DW_OP_breg21 = 0x85,
+ DW_OP_breg22 = 0x86,
+ DW_OP_breg23 = 0x87,
+ DW_OP_breg24 = 0x88,
+ DW_OP_breg25 = 0x89,
+ DW_OP_breg26 = 0x8a,
+ DW_OP_breg27 = 0x8b,
+ DW_OP_breg28 = 0x8c,
+ DW_OP_breg29 = 0x8d,
+ DW_OP_breg30 = 0x8e,
+ DW_OP_breg31 = 0x8f,
+ DW_OP_regx = 0x90,
+ DW_OP_fbreg = 0x91,
+ DW_OP_bregx = 0x92,
+ DW_OP_piece = 0x93,
+ DW_OP_deref_size = 0x94,
+ DW_OP_xderef_size = 0x95,
+ DW_OP_nop = 0x96,
+ /* DWARF 3 extensions. */
+ DW_OP_push_object_address = 0x97,
+ DW_OP_call2 = 0x98,
+ DW_OP_call4 = 0x99,
+ DW_OP_call_ref = 0x9a,
+ /* GNU extensions. */
+ DW_OP_GNU_push_tls_address = 0xe0,
+ /* HP extensions. */
+ DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */
+ DW_OP_HP_is_value = 0xe1,
+ DW_OP_HP_fltconst4 = 0xe2,
+ DW_OP_HP_fltconst8 = 0xe3,
+ DW_OP_HP_mod_range = 0xe4,
+ DW_OP_HP_unmod_range = 0xe5,
+ DW_OP_HP_tls = 0xe6
+ };
+
+#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */
+#define DW_OP_hi_user 0xff /* Implementation-defined range end. */
+
+/* Type encodings. */
+enum dwarf_type
+ {
+ DW_ATE_void = 0x0,
+ DW_ATE_address = 0x1,
+ DW_ATE_boolean = 0x2,
+ DW_ATE_complex_float = 0x3,
+ DW_ATE_float = 0x4,
+ DW_ATE_signed = 0x5,
+ DW_ATE_signed_char = 0x6,
+ DW_ATE_unsigned = 0x7,
+ DW_ATE_unsigned_char = 0x8,
+ /* DWARF 3. */
+ DW_ATE_imaginary_float = 0x9,
+ /* HP extensions. */
+ DW_ATE_HP_float80 = 0x80, /* Floating-point (80 bit). */
+ DW_ATE_HP_complex_float80 = 0x81, /* Complex floating-point (80 bit). */
+ DW_ATE_HP_float128 = 0x82, /* Floating-point (128 bit). */
+ DW_ATE_HP_complex_float128 = 0x83, /* Complex floating-point (128 bit). */
+ DW_ATE_HP_floathpintel = 0x84, /* Floating-point (82 bit IA64). */
+ DW_ATE_HP_imaginary_float80 = 0x85,
+ DW_ATE_HP_imaginary_float128 = 0x86
+ };
+
+#define DW_ATE_lo_user 0x80
+#define DW_ATE_hi_user 0xff
+
+/* Array ordering names and codes. */
+enum dwarf_array_dim_ordering
+ {
+ DW_ORD_row_major = 0,
+ DW_ORD_col_major = 1
+ };
+
+/* Access attribute. */
+enum dwarf_access_attribute
+ {
+ DW_ACCESS_public = 1,
+ DW_ACCESS_protected = 2,
+ DW_ACCESS_private = 3
+ };
+
+/* Visibility. */
+enum dwarf_visibility_attribute
+ {
+ DW_VIS_local = 1,
+ DW_VIS_exported = 2,
+ DW_VIS_qualified = 3
+ };
+
+/* Virtuality. */
+enum dwarf_virtuality_attribute
+ {
+ DW_VIRTUALITY_none = 0,
+ DW_VIRTUALITY_virtual = 1,
+ DW_VIRTUALITY_pure_virtual = 2
+ };
+
+/* Case sensitivity. */
+enum dwarf_id_case
+ {
+ DW_ID_case_sensitive = 0,
+ DW_ID_up_case = 1,
+ DW_ID_down_case = 2,
+ DW_ID_case_insensitive = 3
+ };
+
+/* Calling convention. */
+enum dwarf_calling_convention
+ {
+ DW_CC_normal = 0x1,
+ DW_CC_program = 0x2,
+ DW_CC_nocall = 0x3
+ };
+
+#define DW_CC_lo_user 0x40
+#define DW_CC_hi_user 0xff
+
+/* Inline attribute. */
+enum dwarf_inline_attribute
+ {
+ DW_INL_not_inlined = 0,
+ DW_INL_inlined = 1,
+ DW_INL_declared_not_inlined = 2,
+ DW_INL_declared_inlined = 3
+ };
+
+/* Discriminant lists. */
+enum dwarf_discrim_list
+ {
+ DW_DSC_label = 0,
+ DW_DSC_range = 1
+ };
+
+/* Line number opcodes. */
+enum dwarf_line_number_ops
+ {
+ DW_LNS_extended_op = 0,
+ DW_LNS_copy = 1,
+ DW_LNS_advance_pc = 2,
+ DW_LNS_advance_line = 3,
+ DW_LNS_set_file = 4,
+ DW_LNS_set_column = 5,
+ DW_LNS_negate_stmt = 6,
+ DW_LNS_set_basic_block = 7,
+ DW_LNS_const_add_pc = 8,
+ DW_LNS_fixed_advance_pc = 9,
+ /* DWARF 3. */
+ DW_LNS_set_prologue_end = 10,
+ DW_LNS_set_epilogue_begin = 11,
+ DW_LNS_set_isa = 12
+ };
+
+/* Line number extended opcodes. */
+enum dwarf_line_number_x_ops
+ {
+ DW_LNE_end_sequence = 1,
+ DW_LNE_set_address = 2,
+ DW_LNE_define_file = 3,
+ /* HP extensions. */
+ DW_LNE_HP_negate_is_UV_update = 0x11,
+ DW_LNE_HP_push_context = 0x12,
+ DW_LNE_HP_pop_context = 0x13,
+ DW_LNE_HP_set_file_line_column = 0x14,
+ DW_LNE_HP_set_routine_name = 0x15,
+ DW_LNE_HP_set_sequence = 0x16,
+ DW_LNE_HP_negate_post_semantics = 0x17,
+ DW_LNE_HP_negate_function_exit = 0x18,
+ DW_LNE_HP_negate_front_end_logical = 0x19,
+ DW_LNE_HP_define_proc = 0x20
+ };
+
+/* Call frame information. */
+enum dwarf_call_frame_info
+ {
+ DW_CFA_advance_loc = 0x40,
+ DW_CFA_offset = 0x80,
+ DW_CFA_restore = 0xc0,
+ DW_CFA_nop = 0x00,
+ DW_CFA_set_loc = 0x01,
+ DW_CFA_advance_loc1 = 0x02,
+ DW_CFA_advance_loc2 = 0x03,
+ DW_CFA_advance_loc4 = 0x04,
+ DW_CFA_offset_extended = 0x05,
+ DW_CFA_restore_extended = 0x06,
+ DW_CFA_undefined = 0x07,
+ DW_CFA_same_value = 0x08,
+ DW_CFA_register = 0x09,
+ DW_CFA_remember_state = 0x0a,
+ DW_CFA_restore_state = 0x0b,
+ DW_CFA_def_cfa = 0x0c,
+ DW_CFA_def_cfa_register = 0x0d,
+ DW_CFA_def_cfa_offset = 0x0e,
+ /* DWARF 3. */
+ DW_CFA_def_cfa_expression = 0x0f,
+ DW_CFA_expression = 0x10,
+ DW_CFA_offset_extended_sf = 0x11,
+ DW_CFA_def_cfa_sf = 0x12,
+ DW_CFA_def_cfa_offset_sf = 0x13,
+ /* SGI/MIPS specific. */
+ DW_CFA_MIPS_advance_loc8 = 0x1d,
+ /* GNU extensions. */
+ DW_CFA_GNU_window_save = 0x2d,
+ DW_CFA_GNU_args_size = 0x2e,
+ DW_CFA_GNU_negative_offset_extended = 0x2f
+ };
+
+#define DW_CIE_ID 0xffffffff
+#define DW_CIE_VERSION 1
+
+#define DW_CFA_extended 0
+#define DW_CFA_lo_user 0x1c
+#define DW_CFA_hi_user 0x3f
+
+#define DW_CHILDREN_no 0x00
+#define DW_CHILDREN_yes 0x01
+
+#define DW_ADDR_none 0
+
+/* Source language names and codes. */
+enum dwarf_source_language
+ {
+ DW_LANG_C89 = 0x0001,
+ DW_LANG_C = 0x0002,
+ DW_LANG_Ada83 = 0x0003,
+ DW_LANG_C_plus_plus = 0x0004,
+ DW_LANG_Cobol74 = 0x0005,
+ DW_LANG_Cobol85 = 0x0006,
+ DW_LANG_Fortran77 = 0x0007,
+ DW_LANG_Fortran90 = 0x0008,
+ DW_LANG_Pascal83 = 0x0009,
+ DW_LANG_Modula2 = 0x000a,
+ DW_LANG_Java = 0x000b,
+ /* DWARF 3. */
+ DW_LANG_C99 = 0x000c,
+ DW_LANG_Ada95 = 0x000d,
+ DW_LANG_Fortran95 = 0x000e,
+ /* MIPS. */
+ DW_LANG_Mips_Assembler = 0x8001,
+ /* UPC. */
+ DW_LANG_Upc = 0x8765
+ };
+
+#define DW_LANG_lo_user 0x8000 /* Implementation-defined range start. */
+#define DW_LANG_hi_user 0xffff /* Implementation-defined range start. */
+
+/* Names and codes for macro information. */
+enum dwarf_macinfo_record_type
+ {
+ DW_MACINFO_define = 1,
+ DW_MACINFO_undef = 2,
+ DW_MACINFO_start_file = 3,
+ DW_MACINFO_end_file = 4,
+ DW_MACINFO_vendor_ext = 255
+ };
+
+/* @@@ For use with GNU frame unwind information. */
+
+#define DW_EH_PE_absptr 0x00
+#define DW_EH_PE_omit 0xff
+
+#define DW_EH_PE_uleb128 0x01
+#define DW_EH_PE_udata2 0x02
+#define DW_EH_PE_udata4 0x03
+#define DW_EH_PE_udata8 0x04
+#define DW_EH_PE_sleb128 0x09
+#define DW_EH_PE_sdata2 0x0A
+#define DW_EH_PE_sdata4 0x0B
+#define DW_EH_PE_sdata8 0x0C
+#define DW_EH_PE_signed 0x08
+
+#define DW_EH_PE_pcrel 0x10
+#define DW_EH_PE_textrel 0x20
+#define DW_EH_PE_datarel 0x30
+#define DW_EH_PE_funcrel 0x40
+#define DW_EH_PE_aligned 0x50
+
+#define DW_EH_PE_indirect 0x80
+
+#endif /* _ELF_DWARF2_H */
Binary files linux-2.6.0-akgdb/scripts/bin2c and linux/scripts/bin2c differ
diff -urP -I '\$Id:.*Exp \$' -X /usr/src/patch.exclude linux-2.6.0-akgdb/scripts/dwarfh.awk linux/scripts/dwarfh.awk
--- linux-2.6.0-akgdb/scripts/dwarfh.awk 1969-12-31 16:00:00.000000000 -0800
+++ linux/scripts/dwarfh.awk 2004-01-22 12:58:07.000000000 -0800
@@ -0,0 +1,19 @@
+BEGIN {
+ print "#ifndef _ELF_DWARF_H"
+ print "/* Machine generated from dwarf2.h by scripts/dwarfh.awk */"
+}
+$2 == "=" {
+ gsub(/,/, "", $3)
+ print "#define " $1 "\t " $3
+}
+$1 == "#define" {
+ print $0
+ while( index($0,"\\") == length($0)){
+ getline
+ print $0
+ }
+}
+/.*/ {}
+END {
+ print "#endif"
+}


Attachments:
kgdb-dwarf2-2.6.0-1.0.patch (38.95 kB)

2004-01-26 20:46:48

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Fri, Jan 23, 2004 at 03:38:39PM -0800, George Anzinger wrote:
> Tom Rini wrote:
> >On Thu, Jan 22, 2004 at 11:05:55AM -0700, Tom Rini wrote:
> >[snip]
> >
> >>First up:
> >>We need to call flush_instruction_cache() on a 'c' or 's' command.
> >>arch/ppc/kernel/ppc-stub.c | 19 ++++++-------------
> >>1 files changed, 6 insertions(+), 13 deletions(-)
> >
> >
> >On tpo of this patch, there's the following:
> >Put back some code to figure out what signal we're dealing with.
> >
> > arch/ppc/kernel/ppc-stub.c | 63
> > ++++++++++++++++++++++++++++++++++++++++++---
> > 1 files changed, 60 insertions(+), 3 deletions(-)
> >--- 1.15/arch/ppc/kernel/ppc-stub.c Thu Jan 22 10:53:06 2004
> >+++ edited/arch/ppc/kernel/ppc-stub.c Fri Jan 23 15:43:10 2004
> >@@ -3,6 +3,7 @@
> > *
> > * PowerPC-specific bits to work with the common KGDB stub.
> > *
> >+ * 1998 (c) Michael AK Tesch ([email protected])
> > * 2003 (c) TimeSys Corporation
> > * 2004 (c) MontaVista Software, Inc.
> > * This file is licensed under the terms of the GNU General Public License
> >@@ -19,13 +20,69 @@
> > #include <asm/processor.h>
> > #include <asm/machdep.h>
> >
> >+/* Convert the hardware trap type code to a unix signal number. */
> >+/*
> >+ * This table contains the mapping between PowerPC hardware trap types,
> >and
> >+ * signals, which are primarily what GDB understands.
> >+ */
> >+static struct hard_trap_info
> >+{
> >+ unsigned int tt; /* Trap type code for powerpc */
> >+ unsigned char signo; /* Signal that we map this trap into
> >*/
> >+} hard_trap_info[] = {
> >+#if defined(CONFIG_40x)
> >+ { 0x100, SIGINT }, /* critical input interrupt */
> >+ { 0x200, SIGSEGV }, /* machine check */
> >+ { 0x300, SIGSEGV }, /* data storage */
> >+ { 0x400, SIGBUS }, /* instruction storage */
> >+ { 0x500, SIGINT }, /* interrupt */
> >+ { 0x600, SIGBUS }, /* alignment */
> >+ { 0x700, SIGILL }, /* program */
> >+ { 0x800, SIGILL }, /* reserved */
> >+ { 0x900, SIGILL }, /* reserved */
> >+ { 0xa00, SIGILL }, /* reserved */
> >+ { 0xb00, SIGILL }, /* reserved */
> >+ { 0xc00, SIGCHLD }, /* syscall */
> >+ { 0xd00, SIGILL }, /* reserved */
> >+ { 0xe00, SIGILL }, /* reserved */
> >+ { 0xf00, SIGILL }, /* reserved */
> >+ { 0x2000, SIGTRAP}, /* debug */
> >+#else
> >+ { 0x200, SIGSEGV }, /* machine check */
> >+ { 0x300, SIGSEGV }, /* address error (store) */
> >+ { 0x400, SIGBUS }, /* instruction bus error */
> >+ { 0x500, SIGINT }, /* interrupt */
> >+ { 0x600, SIGBUS }, /* alingment */
> >+ { 0x700, SIGTRAP }, /* breakpoint trap */
> >+ { 0x800, SIGFPE }, /* fpu unavail */
> >+ { 0x900, SIGALRM }, /* decrementer */
> >+ { 0xa00, SIGILL }, /* reserved */
> >+ { 0xb00, SIGILL }, /* reserved */
> >+ { 0xc00, SIGCHLD }, /* syscall */
> >+ { 0xd00, SIGTRAP }, /* single-step/watch */
> >+ { 0xe00, SIGFPE }, /* fp assist */
> >+#endif
> >+ { 0, 0} /* Must be last */
> >+};
> >+
> >+static int computeSignal(unsigned int tt)
> >+{
> >+ struct hard_trap_info *ht;
> >+
> >+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
> >+ if (ht->tt == tt)
> >+ return ht->signo;
> >+
> >+ return SIGHUP; /* default for things we don't know about */
> >+}
> >+
> > /*
> > * Routines
> > */
> > static void
> > kgdb_debugger(struct pt_regs *regs)
> > {
> >- (*linux_debug_hook) (0, 0, 0, regs);
> >+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
> > return;
> > }
> >
> >@@ -52,14 +109,14 @@
> > int
> > kgdb_iabr_match(struct pt_regs *regs)
> > {
> >- (*linux_debug_hook) (0, 0, 0, regs);
> >+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
> > return 1;
> > }
> >
> > int
> > kgdb_dabr_match(struct pt_regs *regs)
> > {
> >- (*linux_debug_hook) (0, 0, 0, regs);
> >+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
> > return 1;
> > }
> >
> >
> >Now, not being as well versed in all of the debugging infos that can be
> >passed around, it sounds like this patch could be dropped in the future
> >for a cleaner method using some of the dwarf2 bits being talked about.
> >But I don't know, and clarification and pointers (if so) to how to do
> >this would be appreciated.
>
> I am not sure what this buys you. I don't think dwarf2 will help here.

OK.

> There is a real danger of passing signal info back to gdb as it will want
> to try to deliver the signal which is a non-compute in most kgdbs in the
> field. I did put code in the mm-kgdb to do just this, but usually the
> arrival of such a signal (other than SIGTRAP) is the end of the kernel.
> All that is left is to read the tea leaves.

The gdb I've been testing this with knows better than to try and send a
singal back, so that's not a worry. The motivation behind doing this
however is along the lines of "if it ain't broke, don't remove it". The
original stub was getting all of this information correctly, so why stop
doing it?

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-26 21:33:39

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Wed, Jan 21, 2004 at 12:21:28PM -0700, Tom Rini wrote:

> On Wed, Jan 21, 2004 at 11:42:17AM -0700, Tom Rini wrote:
> > On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
> >
> > > Hi,
> > >
> > > Here it is: ppc kgdb from timesys kernel is available at
> > > http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
> > >
> > > This is my attempt at extracting kgdb from TimeSys kernel. It works well in
> > > TimeSys kernel, so blame me if above patch doesn't work.
> >
> > Okay, here's my first patch against this.
>
> And dependant upon this is a patch to fixup the rest of the common PPC
> code, as follows:

Relative to this, due to the PPC changes is the following:

- In kgdb_handle_exception, memset remcomOutBuffer twice, instead of
continiously throwing in NULLs around.
- Remove a KERN_CRIT from the printk while waiting for kgdb to connect
(it's not needed there).
- Switch the initial packet from an 'S' packet (followed by a p for the
thread ID) to a 'T' packet.

This is tested on PPC and i386 (lightly).

include/asm-i386/kgdb.h | 4 ++
include/asm-ppc/kgdb.h | 3 +
include/asm-x86_64/kgdb.h | 4 ++
kernel/kgdbstub.c | 70 ++++++++++++++++++++++------------------------
4 files changed, 45 insertions(+), 36 deletions(-)

--- 1.1/include/asm-i386/kgdb.h Wed Jan 21 10:13:15 2004
+++ edited/include/asm-i386/kgdb.h Mon Jan 26 12:15:22 2004
@@ -43,6 +43,10 @@
_GS /* 15 */
};

+#define PC_REGNUM _PC /* Program Counter */
+#define SP_REGNUM _ESP /* Stack Pointer */
+#define PTRACE_PC eip /* Program Counter, in ptrace regs. */
+
#define BREAKPOINT() asm(" int $3");
#define BREAK_INSTR_SIZE 1

--- 1.5/include/asm-ppc/kgdb.h Wed Jan 21 12:21:23 2004
+++ edited/include/asm-ppc/kgdb.h Mon Jan 26 12:16:39 2004
@@ -19,6 +19,9 @@
#define NUMREGBYTES (MAXREG * sizeof(int))
#define BUFMAX ((NUMREGBYTES * 2) + 512)
#define OUTBUFMAX ((NUMREGBYTES * 2) + 512)
+#define PC_REGNUM 64
+#define SP_REGNUM 1
+#define PTRACE_PC nip /* Program Counter, in ptrace regs. */
#define BREAKPOINT() asm(".long 0x7d821008") /* twge r2, r2 */

/* Things specific to the gen550 backend. */
--- 1.1/include/asm-x86_64/kgdb.h Wed Jan 21 10:13:16 2004
+++ edited/include/asm-x86_64/kgdb.h Mon Jan 26 12:16:15 2004
@@ -44,6 +44,10 @@
_PS,
_LASTREG=_PS };

+#define PC_REGNUM _PC /* Program Counter */
+#define SP_REGNUM _RSP /* Stack Pointer */
+#define PTRACE_PC rip /* Program Counter, in ptrace regs. */
+
/* Number of bytes of registers. */
#define NUMREGBYTES (_LASTREG*8)

--- 1.2/kernel/kgdbstub.c Wed Jan 21 12:21:23 2004
+++ edited/kernel/kgdbstub.c Mon Jan 26 12:17:02 2004
@@ -615,6 +615,9 @@
* need one here */
procindebug[smp_processor_id()] = 1;

+ /* Clear the out buffer. */
+ memset(remcomOutBuffer, 0, sizeof(remcomOutBuffer));
+
/* Master processor is completely in the debugger */
if (kgdb_ops->post_master_code)
kgdb_ops->post_master_code(linux_regs, exVector, err_code);
@@ -624,9 +627,7 @@
if(remcomInBuffer[0] == 'H' && remcomInBuffer[1] =='c') {
remove_all_break();
atomic_set(&kgdb_killed_or_detached, 0);
- remcomOutBuffer[0] = 'O';
- remcomOutBuffer[1] = 'K';
- remcomOutBuffer[2] = 0;
+ strcpy(remcomOutBuffer, "OK");
}
else
return 1;
@@ -634,13 +635,25 @@
else {

/* reply to host that an exception has occurred */
- remcomOutBuffer[0] = 'S';
- remcomOutBuffer[1] = hexchars[signo >> 4];
- remcomOutBuffer[2] = hexchars[signo % 16];
- remcomOutBuffer[3] = 'p';
-
+ ptr = remcomOutBuffer;
+ *ptr++ = 'T';
+ *ptr++ = hexchars[(signo >> 4) % 16];
+ *ptr++ = hexchars[signo % 16];
+ *ptr++ = hexchars[(PC_REGNUM >> 4) % 16];
+ *ptr++ = hexchars[PC_REGNUM % 16];
+ *ptr++ = ':';
+ ptr = kgdb_mem2hex((char *)&linux_regs->PTRACE_PC, ptr, 4, 0);
+ *ptr++ = ';';
+ *ptr++ = hexchars[SP_REGNUM >> 4];
+ *ptr++ = hexchars[SP_REGNUM & 0xf];
+ *ptr++ = ':';
+ ptr = kgdb_mem2hex(((char *)linux_regs) + SP_REGNUM * 4, ptr,
+ 4, 0);
+ *ptr++ = ';';
+ ptr += strlen(strcpy(ptr, "thread:"));
int_to_threadref(&thref, shadow_pid(current->pid));
- *pack_threadid(remcomOutBuffer + 4, &thref) = 0;
+ ptr = pack_threadid(ptr, &thref);
+ *ptr++ = ';';
}
putpacket(remcomOutBuffer, 0);
kgdb_connected = 1;
@@ -651,8 +664,10 @@
while (1) {
int bpt_type = 0;
error = 0;
- remcomOutBuffer[0] = 0;
- remcomOutBuffer[1] = 0;
+
+ /* Clear the out buffer. */
+ memset(remcomOutBuffer, 0, sizeof(remcomOutBuffer));
+
getpacket(remcomInBuffer);

#if KGDB_DEBUG
@@ -666,7 +681,6 @@
remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[signo >> 4];
remcomOutBuffer[2] = hexchars[signo % 16];
- remcomOutBuffer[3] = 0;
break;

case 'g': /* return the value of the CPU registers */
@@ -764,9 +778,7 @@
* continue.
*/
case 'D':
- remcomOutBuffer[0] = 'O';
- remcomOutBuffer[1] = 'K';
- remcomOutBuffer[2] = '\0';
+ strcpy(remcomOutBuffer, "OK");
remove_all_break();
putpacket(remcomOutBuffer, 0);
kgdb_connected = 0;
@@ -804,19 +816,16 @@
i++;
}
}
- *(--ptr) = '\0';
break;

case 'C':
/* Current thread id */
- remcomOutBuffer[0] = 'Q';
- remcomOutBuffer[1] = 'C';
+ strcpy(remcomOutBuffer, "QC");

threadid = shadow_pid(current->pid);

int_to_threadref(&thref, threadid);
pack_threadid(remcomOutBuffer + 2, &thref);
- remcomOutBuffer[18] = '\0';
break;

case 'E':
@@ -829,7 +838,6 @@
case 'T':
if (memcmp(remcomInBuffer+1, "ThreadExtraInfo,",16))
{
- remcomOutBuffer[0] = 0;
strcpy(remcomOutBuffer, "E05");
break;
}
@@ -872,14 +880,11 @@
thread = getthread(linux_regs, threadid);
if (!thread && threadid > 0) {
remcomOutBuffer[0] = 'E';
- remcomOutBuffer[1] = '\0';
break;
}
kgdb_usethread = thread;
kgdb_usethreadid = threadid;
- remcomOutBuffer[0] = 'O';
- remcomOutBuffer[1] = 'K';
- remcomOutBuffer[2] = '\0';
+ strcpy(remcomOutBuffer, "OK");
break;

case 'c':
@@ -892,14 +897,11 @@
thread = getthread(linux_regs, threadid);
if (!thread && threadid > 0) {
remcomOutBuffer[0] = 'E';
- remcomOutBuffer[1] = '\0';
break;
}
kgdb_contthread = thread;
}
- remcomOutBuffer[0] = 'O';
- remcomOutBuffer[1] = 'K';
- remcomOutBuffer[2] = '\0';
+ strcpy(remcomOutBuffer, "OK");
break;
}
break;
@@ -909,14 +911,10 @@
ptr = &remcomInBuffer[1];
kgdb_hexToLong(&ptr, &threadid);
thread = getthread(linux_regs, threadid);
- if (thread) {
- remcomOutBuffer[0] = 'O';
- remcomOutBuffer[1] = 'K';
- remcomOutBuffer[2] = '\0';
- } else {
+ if (thread)
+ strcpy(remcomOutBuffer, "OK");
+ else
remcomOutBuffer[0] = 'E';
- remcomOutBuffer[1] = '\0';
- }
break;
case 'z':
case 'Z':
@@ -1127,7 +1125,7 @@
*/
printk(KERN_CRIT "Waiting for connection from remote gdb... ");
breakpoint() ;
- printk(KERN_CRIT "Connected.\n");
+ printk("Connected.\n");
}

#ifdef CONFIG_KGDB_CONSOLE

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-26 21:28:17

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Tom Rini wrote:
> On Fri, Jan 23, 2004 at 03:38:39PM -0800, George Anzinger wrote:
>
>>Tom Rini wrote:
>>
>>>On Thu, Jan 22, 2004 at 11:05:55AM -0700, Tom Rini wrote:
>>>[snip]
>>>
>>>
>>>>First up:
>>>>We need to call flush_instruction_cache() on a 'c' or 's' command.
>>>>arch/ppc/kernel/ppc-stub.c | 19 ++++++-------------
>>>>1 files changed, 6 insertions(+), 13 deletions(-)
>>>
>>>
>>>On tpo of this patch, there's the following:
>>>Put back some code to figure out what signal we're dealing with.
>>>
>>>arch/ppc/kernel/ppc-stub.c | 63
>>>++++++++++++++++++++++++++++++++++++++++++---
>>>1 files changed, 60 insertions(+), 3 deletions(-)
>>>--- 1.15/arch/ppc/kernel/ppc-stub.c Thu Jan 22 10:53:06 2004
>>>+++ edited/arch/ppc/kernel/ppc-stub.c Fri Jan 23 15:43:10 2004
>>>@@ -3,6 +3,7 @@
>>> *
>>> * PowerPC-specific bits to work with the common KGDB stub.
>>> *
>>>+ * 1998 (c) Michael AK Tesch ([email protected])
>>> * 2003 (c) TimeSys Corporation
>>> * 2004 (c) MontaVista Software, Inc.
>>> * This file is licensed under the terms of the GNU General Public License
>>>@@ -19,13 +20,69 @@
>>>#include <asm/processor.h>
>>>#include <asm/machdep.h>
>>>
>>>+/* Convert the hardware trap type code to a unix signal number. */
>>>+/*
>>>+ * This table contains the mapping between PowerPC hardware trap types,
>>>and
>>>+ * signals, which are primarily what GDB understands.
>>>+ */
>>>+static struct hard_trap_info
>>>+{
>>>+ unsigned int tt; /* Trap type code for powerpc */
>>>+ unsigned char signo; /* Signal that we map this trap into
>>>*/
>>>+} hard_trap_info[] = {
>>>+#if defined(CONFIG_40x)
>>>+ { 0x100, SIGINT }, /* critical input interrupt */
>>>+ { 0x200, SIGSEGV }, /* machine check */
>>>+ { 0x300, SIGSEGV }, /* data storage */
>>>+ { 0x400, SIGBUS }, /* instruction storage */
>>>+ { 0x500, SIGINT }, /* interrupt */
>>>+ { 0x600, SIGBUS }, /* alignment */
>>>+ { 0x700, SIGILL }, /* program */
>>>+ { 0x800, SIGILL }, /* reserved */
>>>+ { 0x900, SIGILL }, /* reserved */
>>>+ { 0xa00, SIGILL }, /* reserved */
>>>+ { 0xb00, SIGILL }, /* reserved */
>>>+ { 0xc00, SIGCHLD }, /* syscall */
>>>+ { 0xd00, SIGILL }, /* reserved */
>>>+ { 0xe00, SIGILL }, /* reserved */
>>>+ { 0xf00, SIGILL }, /* reserved */
>>>+ { 0x2000, SIGTRAP}, /* debug */
>>>+#else
>>>+ { 0x200, SIGSEGV }, /* machine check */
>>>+ { 0x300, SIGSEGV }, /* address error (store) */
>>>+ { 0x400, SIGBUS }, /* instruction bus error */
>>>+ { 0x500, SIGINT }, /* interrupt */
>>>+ { 0x600, SIGBUS }, /* alingment */
>>>+ { 0x700, SIGTRAP }, /* breakpoint trap */
>>>+ { 0x800, SIGFPE }, /* fpu unavail */
>>>+ { 0x900, SIGALRM }, /* decrementer */
>>>+ { 0xa00, SIGILL }, /* reserved */
>>>+ { 0xb00, SIGILL }, /* reserved */
>>>+ { 0xc00, SIGCHLD }, /* syscall */
>>>+ { 0xd00, SIGTRAP }, /* single-step/watch */
>>>+ { 0xe00, SIGFPE }, /* fp assist */
>>>+#endif
>>>+ { 0, 0} /* Must be last */
>>>+};
>>>+
>>>+static int computeSignal(unsigned int tt)
>>>+{
>>>+ struct hard_trap_info *ht;
>>>+
>>>+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
>>>+ if (ht->tt == tt)
>>>+ return ht->signo;
>>>+
>>>+ return SIGHUP; /* default for things we don't know about */
>>>+}
>>>+
>>>/*
>>> * Routines
>>> */
>>>static void
>>>kgdb_debugger(struct pt_regs *regs)
>>>{
>>>- (*linux_debug_hook) (0, 0, 0, regs);
>>>+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
>>> return;
>>>}
>>>
>>>@@ -52,14 +109,14 @@
>>>int
>>>kgdb_iabr_match(struct pt_regs *regs)
>>>{
>>>- (*linux_debug_hook) (0, 0, 0, regs);
>>>+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
>>> return 1;
>>>}
>>>
>>>int
>>>kgdb_dabr_match(struct pt_regs *regs)
>>>{
>>>- (*linux_debug_hook) (0, 0, 0, regs);
>>>+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
>>> return 1;
>>>}
>>>
>>>
>>>Now, not being as well versed in all of the debugging infos that can be
>>>passed around, it sounds like this patch could be dropped in the future
>>>for a cleaner method using some of the dwarf2 bits being talked about.
>>>But I don't know, and clarification and pointers (if so) to how to do
>>>this would be appreciated.
>>
>>I am not sure what this buys you. I don't think dwarf2 will help here.
>
>
> OK.
>
>
>>There is a real danger of passing signal info back to gdb as it will want
>>to try to deliver the signal which is a non-compute in most kgdbs in the
>>field. I did put code in the mm-kgdb to do just this, but usually the
>>arrival of such a signal (other than SIGTRAP) is the end of the kernel.
>>All that is left is to read the tea leaves.
>
>
> The gdb I've been testing this with knows better than to try and send a
> singal back, so that's not a worry. The motivation behind doing this
> however is along the lines of "if it ain't broke, don't remove it". The
> original stub was getting all of this information correctly, so why stop
> doing it?
>
OK, but I still don't like losing the return address. Tell me again, why do you
need three different functions all doing the same thing?


--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-01-26 21:46:21

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Tom Rini wrote:
>
>>There is a real danger of passing signal info back to gdb as it will want
>>to try to deliver the signal which is a non-compute in most kgdbs in the
>>field. I did put code in the mm-kgdb to do just this, but usually the
>>arrival of such a signal (other than SIGTRAP) is the end of the kernel.
>>All that is left is to read the tea leaves.
>
>
> The gdb I've been testing this with knows better than to try and send a
> singal back, so that's not a worry. The motivation behind doing this
> however is along the lines of "if it ain't broke, don't remove it". The
> original stub was getting all of this information correctly, so why stop
> doing it?
>
You sure. If so what gdb? And how does it know? I suppose you could tell it
with a script, but then what if one forgets?

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-01-26 21:43:17

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Mon, Jan 26, 2004 at 01:27:35PM -0800, George Anzinger wrote:
> Tom Rini wrote:
> >On Fri, Jan 23, 2004 at 03:38:39PM -0800, George Anzinger wrote:
> >
> >>Tom Rini wrote:
> >>
> >>>On Thu, Jan 22, 2004 at 11:05:55AM -0700, Tom Rini wrote:
> >>>[snip]
> >>>
> >>>
> >>>>First up:
> >>>>We need to call flush_instruction_cache() on a 'c' or 's' command.
> >>>>arch/ppc/kernel/ppc-stub.c | 19 ++++++-------------
> >>>>1 files changed, 6 insertions(+), 13 deletions(-)
> >>>
> >>>
> >>>On tpo of this patch, there's the following:
> >>>Put back some code to figure out what signal we're dealing with.
> >>>
> >>>arch/ppc/kernel/ppc-stub.c | 63
> >>>++++++++++++++++++++++++++++++++++++++++++---
> >>>1 files changed, 60 insertions(+), 3 deletions(-)
> >>>--- 1.15/arch/ppc/kernel/ppc-stub.c Thu Jan 22 10:53:06 2004
> >>>+++ edited/arch/ppc/kernel/ppc-stub.c Fri Jan 23 15:43:10 2004
> >>>@@ -3,6 +3,7 @@
> >>>*
> >>>* PowerPC-specific bits to work with the common KGDB stub.
> >>>*
> >>>+ * 1998 (c) Michael AK Tesch ([email protected])
> >>>* 2003 (c) TimeSys Corporation
> >>>* 2004 (c) MontaVista Software, Inc.
> >>>* This file is licensed under the terms of the GNU General Public License
> >>>@@ -19,13 +20,69 @@
> >>>#include <asm/processor.h>
> >>>#include <asm/machdep.h>
> >>>
> >>>+/* Convert the hardware trap type code to a unix signal number. */
> >>>+/*
> >>>+ * This table contains the mapping between PowerPC hardware trap types,
> >>>and
> >>>+ * signals, which are primarily what GDB understands.
> >>>+ */
> >>>+static struct hard_trap_info
> >>>+{
> >>>+ unsigned int tt; /* Trap type code for powerpc */
> >>>+ unsigned char signo; /* Signal that we map this trap into
> >>>*/
> >>>+} hard_trap_info[] = {
> >>>+#if defined(CONFIG_40x)
> >>>+ { 0x100, SIGINT }, /* critical input interrupt */
> >>>+ { 0x200, SIGSEGV }, /* machine check */
> >>>+ { 0x300, SIGSEGV }, /* data storage */
> >>>+ { 0x400, SIGBUS }, /* instruction storage */
> >>>+ { 0x500, SIGINT }, /* interrupt */
> >>>+ { 0x600, SIGBUS }, /* alignment */
> >>>+ { 0x700, SIGILL }, /* program */
> >>>+ { 0x800, SIGILL }, /* reserved */
> >>>+ { 0x900, SIGILL }, /* reserved */
> >>>+ { 0xa00, SIGILL }, /* reserved */
> >>>+ { 0xb00, SIGILL }, /* reserved */
> >>>+ { 0xc00, SIGCHLD }, /* syscall */
> >>>+ { 0xd00, SIGILL }, /* reserved */
> >>>+ { 0xe00, SIGILL }, /* reserved */
> >>>+ { 0xf00, SIGILL }, /* reserved */
> >>>+ { 0x2000, SIGTRAP}, /* debug */
> >>>+#else
> >>>+ { 0x200, SIGSEGV }, /* machine check */
> >>>+ { 0x300, SIGSEGV }, /* address error (store) */
> >>>+ { 0x400, SIGBUS }, /* instruction bus error */
> >>>+ { 0x500, SIGINT }, /* interrupt */
> >>>+ { 0x600, SIGBUS }, /* alingment */
> >>>+ { 0x700, SIGTRAP }, /* breakpoint trap */
> >>>+ { 0x800, SIGFPE }, /* fpu unavail */
> >>>+ { 0x900, SIGALRM }, /* decrementer */
> >>>+ { 0xa00, SIGILL }, /* reserved */
> >>>+ { 0xb00, SIGILL }, /* reserved */
> >>>+ { 0xc00, SIGCHLD }, /* syscall */
> >>>+ { 0xd00, SIGTRAP }, /* single-step/watch */
> >>>+ { 0xe00, SIGFPE }, /* fp assist */
> >>>+#endif
> >>>+ { 0, 0} /* Must be last */
> >>>+};
> >>>+
> >>>+static int computeSignal(unsigned int tt)
> >>>+{
> >>>+ struct hard_trap_info *ht;
> >>>+
> >>>+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
> >>>+ if (ht->tt == tt)
> >>>+ return ht->signo;
> >>>+
> >>>+ return SIGHUP; /* default for things we don't know about */
> >>>+}
> >>>+
> >>>/*
> >>>* Routines
> >>>*/
> >>>static void
> >>>kgdb_debugger(struct pt_regs *regs)
> >>>{
> >>>- (*linux_debug_hook) (0, 0, 0, regs);
> >>>+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
> >>> return;
> >>>}
> >>>
> >>>@@ -52,14 +109,14 @@
> >>>int
> >>>kgdb_iabr_match(struct pt_regs *regs)
> >>>{
> >>>- (*linux_debug_hook) (0, 0, 0, regs);
> >>>+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
> >>> return 1;
> >>>}
> >>>
> >>>int
> >>>kgdb_dabr_match(struct pt_regs *regs)
> >>>{
> >>>- (*linux_debug_hook) (0, 0, 0, regs);
> >>>+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
> >>> return 1;
> >>>}
> >>>
> >>>
> >>>Now, not being as well versed in all of the debugging infos that can be
> >>>passed around, it sounds like this patch could be dropped in the future
> >>>for a cleaner method using some of the dwarf2 bits being talked about.
> >>>But I don't know, and clarification and pointers (if so) to how to do
> >>>this would be appreciated.
> >>
> >>I am not sure what this buys you. I don't think dwarf2 will help here.
> >
> >
> >OK.
> >
> >
> >>There is a real danger of passing signal info back to gdb as it will want
> >>to try to deliver the signal which is a non-compute in most kgdbs in the
> >>field. I did put code in the mm-kgdb to do just this, but usually the
> >>arrival of such a signal (other than SIGTRAP) is the end of the kernel.
> >>All that is left is to read the tea leaves.
> >
> >
> >The gdb I've been testing this with knows better than to try and send a
> >singal back, so that's not a worry. The motivation behind doing this
> >however is along the lines of "if it ain't broke, don't remove it". The
> >original stub was getting all of this information correctly, so why stop
> >doing it?
> >
> OK, but I still don't like losing the return address. Tell me again, why
> do you need three different functions all doing the same thing?

You get:
- kgdb_breakpoint => debugger_bpt : This is how the various PPC codes
drop you into KGDB.
- kgdb_iabr_match => debugger_iabr_match : Called from
InstructionBreakpoint, exception.
- kgdb_dabr_match => debugger_dabr_match : Called from do_page_fault,
this is a Data Access Breakpoint Register match.

So we need at least 2 for the KGDB side of things (prototypes) and 3
just to make it clear.

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-26 22:07:25

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Mon, Jan 26, 2004 at 01:45:44PM -0800, George Anzinger wrote:

> Tom Rini wrote:
> >
> >>There is a real danger of passing signal info back to gdb as it will want
> >>to try to deliver the signal which is a non-compute in most kgdbs in the
> >>field. I did put code in the mm-kgdb to do just this, but usually the
> >>arrival of such a signal (other than SIGTRAP) is the end of the kernel.
> >>All that is left is to read the tea leaves.
> >
> >
> >The gdb I've been testing this with knows better than to try and send a
> >singal back, so that's not a worry. The motivation behind doing this
> >however is along the lines of "if it ain't broke, don't remove it". The
> >original stub was getting all of this information correctly, so why stop
> >doing it?
> >
> You sure. If so what gdb? And how does it know? I suppose you could tell
> it with a script, but then what if one forgets?

GNU gdb 6.0 (MontaVista 6.0-8.0.4.0300532 2003-12-24)
Copyright 2003 Free Software Foundation, Inc.
[snip]

[New Thread 289]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 289]
0x00000000 in ?? ()
(gdb) c
Continuing.
Can't send signals to this remote system. SIGSEGV not sent.

Noting that 0x0 is correct as the code that triggered this was:
static void (*dummy)(struct pt_regs *regs);
int drop_kgdb(void) {
struct pt_regs regs;
memset(&regs, 0, sizeof(regs));
dummy(&regs);

return 0;
}
module_init(drop_kgdb);

--
Tom Rini
http://gate.crashing.org/~trini/

2004-01-26 22:35:56

by George Anzinger

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

Tom Rini wrote:
>>>>>+
>>>>>/*
>>>>>* Routines
>>>>>*/
>>>>>static void
>>>>>kgdb_debugger(struct pt_regs *regs)
>>>>>{
>>>>>- (*linux_debug_hook) (0, 0, 0, regs);
>>>>>+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
>>>>> return;
>>>>>}
>>>>>
>>>>>@@ -52,14 +109,14 @@
>>>>>int
>>>>>kgdb_iabr_match(struct pt_regs *regs)
>>>>>{
>>>>>- (*linux_debug_hook) (0, 0, 0, regs);
>>>>>+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
>>>>> return 1;
>>>>>}
>>>>>
>>>>>int
>>>>>kgdb_dabr_match(struct pt_regs *regs)
>>>>>{
>>>>>- (*linux_debug_hook) (0, 0, 0, regs);
>>>>>+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
>>>>> return 1;
>>>>>}
>>>>>
>>>>>
>>>>>Now, not being as well versed in all of the debugging infos that can be
>>>>>passed around, it sounds like this patch could be dropped in the future
>>>>>for a cleaner method using some of the dwarf2 bits being talked about.
>>>>>But I don't know, and clarification and pointers (if so) to how to do
>>>>>this would be appreciated.
>>>>
>>>>I am not sure what this buys you. I don't think dwarf2 will help here.
>>>
>>>
>>>OK.
>>>
>>>
>>>
>>>>There is a real danger of passing signal info back to gdb as it will want
>>>>to try to deliver the signal which is a non-compute in most kgdbs in the
>>>>field. I did put code in the mm-kgdb to do just this, but usually the
>>>>arrival of such a signal (other than SIGTRAP) is the end of the kernel.
>>>>All that is left is to read the tea leaves.
>>>
>>>
>>>The gdb I've been testing this with knows better than to try and send a
>>>singal back, so that's not a worry. The motivation behind doing this
>>>however is along the lines of "if it ain't broke, don't remove it". The
>>>original stub was getting all of this information correctly, so why stop
>>>doing it?
>>>
>>
>>OK, but I still don't like losing the return address. Tell me again, why
>>do you need three different functions all doing the same thing?
>
>
> You get:
> - kgdb_breakpoint => debugger_bpt : This is how the various PPC codes
> drop you into KGDB.
> - kgdb_iabr_match => debugger_iabr_match : Called from
> InstructionBreakpoint, exception.
> - kgdb_dabr_match => debugger_dabr_match : Called from do_page_fault,
> this is a Data Access Breakpoint Register match.
>
> So we need at least 2 for the KGDB side of things (prototypes) and 3
> just to make it clear.

But they all end up at the exact same place with the same set of parameters.
The only difference I can see is that some return 1 while the other is void. It
seems to me that you could send them all to one of the ones that returns 1.
Once that is done, then you could just send them all to where ever
linux_debug_hook points and have it do the signal resolution and return the 1.
That way that code could look at its return address and see something useful.
>

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-01-27 08:59:45

by Amit S. Kale

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Tuesday 27 Jan 2004 3:02 am, Tom Rini wrote:
> On Wed, Jan 21, 2004 at 12:21:28PM -0700, Tom Rini wrote:
> > On Wed, Jan 21, 2004 at 11:42:17AM -0700, Tom Rini wrote:
> > > On Wed, Jan 21, 2004 at 10:23:12PM +0530, Amit S. Kale wrote:
> > > > Hi,
> > > >
> > > > Here it is: ppc kgdb from timesys kernel is available at
> > > > http://kgdb.sourceforge.net/kgdb-2/linux-2.6.1-kgdb-2.1.0.tar.bz2
> > > >
> > > > This is my attempt at extracting kgdb from TimeSys kernel. It works
> > > > well in TimeSys kernel, so blame me if above patch doesn't work.
> > >
> > > Okay, here's my first patch against this.
> >
> > And dependant upon this is a patch to fixup the rest of the common PPC
> > code, as follows:
>
> Relative to this, due to the PPC changes is the following:
>
> - In kgdb_handle_exception, memset remcomOutBuffer twice, instead of
> continiously throwing in NULLs around.

Good.

> - Remove a KERN_CRIT from the printk while waiting for kgdb to connect
> (it's not needed there).

It's needed for kgdb over ethernet. At present the ethernet comes up really
late. At that point syslogd has taken over printing of kernel messages,
KERN_CRIT ensures that a user sees that message regardless of the syslogd
configuratio.

> - Switch the initial packet from an 'S' packet (followed by a p for the
> thread ID) to a 'T' packet.

That's also good.

>
> This is tested on PPC and i386 (lightly).
>
> include/asm-i386/kgdb.h | 4 ++
> include/asm-ppc/kgdb.h | 3 +
> include/asm-x86_64/kgdb.h | 4 ++
> kernel/kgdbstub.c | 70
> ++++++++++++++++++++++------------------------ 4 files changed, 45
> insertions(+), 36 deletions(-)
>
> --- 1.1/include/asm-i386/kgdb.h Wed Jan 21 10:13:15 2004
> +++ edited/include/asm-i386/kgdb.h Mon Jan 26 12:15:22 2004
> @@ -43,6 +43,10 @@
> _GS /* 15 */
> };
>
> +#define PC_REGNUM _PC /* Program Counter */
> +#define SP_REGNUM _ESP /* Stack Pointer */
> +#define PTRACE_PC eip /* Program Counter, in ptrace regs. */
> +
> #define BREAKPOINT() asm(" int $3");
> #define BREAK_INSTR_SIZE 1
>
> --- 1.5/include/asm-ppc/kgdb.h Wed Jan 21 12:21:23 2004
> +++ edited/include/asm-ppc/kgdb.h Mon Jan 26 12:16:39 2004
> @@ -19,6 +19,9 @@
> #define NUMREGBYTES (MAXREG * sizeof(int))
> #define BUFMAX ((NUMREGBYTES * 2) + 512)
> #define OUTBUFMAX ((NUMREGBYTES * 2) + 512)
> +#define PC_REGNUM 64
> +#define SP_REGNUM 1
> +#define PTRACE_PC nip /* Program Counter, in ptrace regs. */
> #define BREAKPOINT() asm(".long 0x7d821008") /* twge r2, r2 */
>
> /* Things specific to the gen550 backend. */
> --- 1.1/include/asm-x86_64/kgdb.h Wed Jan 21 10:13:16 2004
> +++ edited/include/asm-x86_64/kgdb.h Mon Jan 26 12:16:15 2004
> @@ -44,6 +44,10 @@
> _PS,
> _LASTREG=_PS };
>
> +#define PC_REGNUM _PC /* Program Counter */
> +#define SP_REGNUM _RSP /* Stack Pointer */
> +#define PTRACE_PC rip /* Program Counter, in ptrace regs. */
> +
> /* Number of bytes of registers. */
> #define NUMREGBYTES (_LASTREG*8)
>
> --- 1.2/kernel/kgdbstub.c Wed Jan 21 12:21:23 2004
> +++ edited/kernel/kgdbstub.c Mon Jan 26 12:17:02 2004
> @@ -615,6 +615,9 @@
> * need one here */
> procindebug[smp_processor_id()] = 1;
>
> + /* Clear the out buffer. */
> + memset(remcomOutBuffer, 0, sizeof(remcomOutBuffer));
> +
> /* Master processor is completely in the debugger */
> if (kgdb_ops->post_master_code)
> kgdb_ops->post_master_code(linux_regs, exVector, err_code);
> @@ -624,9 +627,7 @@
> if(remcomInBuffer[0] == 'H' && remcomInBuffer[1] =='c') {
> remove_all_break();
> atomic_set(&kgdb_killed_or_detached, 0);
> - remcomOutBuffer[0] = 'O';
> - remcomOutBuffer[1] = 'K';
> - remcomOutBuffer[2] = 0;
> + strcpy(remcomOutBuffer, "OK");
> }
> else
> return 1;
> @@ -634,13 +635,25 @@
> else {
>
> /* reply to host that an exception has occurred */
> - remcomOutBuffer[0] = 'S';
> - remcomOutBuffer[1] = hexchars[signo >> 4];
> - remcomOutBuffer[2] = hexchars[signo % 16];
> - remcomOutBuffer[3] = 'p';
> -
> + ptr = remcomOutBuffer;
> + *ptr++ = 'T';
> + *ptr++ = hexchars[(signo >> 4) % 16];
> + *ptr++ = hexchars[signo % 16];
> + *ptr++ = hexchars[(PC_REGNUM >> 4) % 16];
> + *ptr++ = hexchars[PC_REGNUM % 16];
> + *ptr++ = ':';
> + ptr = kgdb_mem2hex((char *)&linux_regs->PTRACE_PC, ptr, 4, 0);
> + *ptr++ = ';';
> + *ptr++ = hexchars[SP_REGNUM >> 4];
> + *ptr++ = hexchars[SP_REGNUM & 0xf];
> + *ptr++ = ':';
> + ptr = kgdb_mem2hex(((char *)linux_regs) + SP_REGNUM * 4, ptr,
> + 4, 0);
> + *ptr++ = ';';
> + ptr += strlen(strcpy(ptr, "thread:"));
> int_to_threadref(&thref, shadow_pid(current->pid));
> - *pack_threadid(remcomOutBuffer + 4, &thref) = 0;
> + ptr = pack_threadid(ptr, &thref);
> + *ptr++ = ';';
> }
> putpacket(remcomOutBuffer, 0);
> kgdb_connected = 1;
> @@ -651,8 +664,10 @@
> while (1) {
> int bpt_type = 0;
> error = 0;
> - remcomOutBuffer[0] = 0;
> - remcomOutBuffer[1] = 0;
> +
> + /* Clear the out buffer. */
> + memset(remcomOutBuffer, 0, sizeof(remcomOutBuffer));
> +
> getpacket(remcomInBuffer);
>
> #if KGDB_DEBUG
> @@ -666,7 +681,6 @@
> remcomOutBuffer[0] = 'S';
> remcomOutBuffer[1] = hexchars[signo >> 4];
> remcomOutBuffer[2] = hexchars[signo % 16];
> - remcomOutBuffer[3] = 0;
> break;
>
> case 'g': /* return the value of the CPU registers */
> @@ -764,9 +778,7 @@
> * continue.
> */
> case 'D':
> - remcomOutBuffer[0] = 'O';
> - remcomOutBuffer[1] = 'K';
> - remcomOutBuffer[2] = '\0';
> + strcpy(remcomOutBuffer, "OK");
> remove_all_break();
> putpacket(remcomOutBuffer, 0);
> kgdb_connected = 0;
> @@ -804,19 +816,16 @@
> i++;
> }
> }
> - *(--ptr) = '\0';
> break;
>
> case 'C':
> /* Current thread id */
> - remcomOutBuffer[0] = 'Q';
> - remcomOutBuffer[1] = 'C';
> + strcpy(remcomOutBuffer, "QC");
>
> threadid = shadow_pid(current->pid);
>
> int_to_threadref(&thref, threadid);
> pack_threadid(remcomOutBuffer + 2, &thref);
> - remcomOutBuffer[18] = '\0';
> break;
>
> case 'E':
> @@ -829,7 +838,6 @@
> case 'T':
> if (memcmp(remcomInBuffer+1, "ThreadExtraInfo,",16))
> {
> - remcomOutBuffer[0] = 0;
> strcpy(remcomOutBuffer, "E05");
> break;
> }
> @@ -872,14 +880,11 @@
> thread = getthread(linux_regs, threadid);
> if (!thread && threadid > 0) {
> remcomOutBuffer[0] = 'E';
> - remcomOutBuffer[1] = '\0';
> break;
> }
> kgdb_usethread = thread;
> kgdb_usethreadid = threadid;
> - remcomOutBuffer[0] = 'O';
> - remcomOutBuffer[1] = 'K';
> - remcomOutBuffer[2] = '\0';
> + strcpy(remcomOutBuffer, "OK");
> break;
>
> case 'c':
> @@ -892,14 +897,11 @@
> thread = getthread(linux_regs, threadid);
> if (!thread && threadid > 0) {
> remcomOutBuffer[0] = 'E';
> - remcomOutBuffer[1] = '\0';
> break;
> }
> kgdb_contthread = thread;
> }
> - remcomOutBuffer[0] = 'O';
> - remcomOutBuffer[1] = 'K';
> - remcomOutBuffer[2] = '\0';
> + strcpy(remcomOutBuffer, "OK");
> break;
> }
> break;
> @@ -909,14 +911,10 @@
> ptr = &remcomInBuffer[1];
> kgdb_hexToLong(&ptr, &threadid);
> thread = getthread(linux_regs, threadid);
> - if (thread) {
> - remcomOutBuffer[0] = 'O';
> - remcomOutBuffer[1] = 'K';
> - remcomOutBuffer[2] = '\0';
> - } else {
> + if (thread)
> + strcpy(remcomOutBuffer, "OK");
> + else
> remcomOutBuffer[0] = 'E';
> - remcomOutBuffer[1] = '\0';
> - }
> break;
> case 'z':
> case 'Z':
> @@ -1127,7 +1125,7 @@
> */
> printk(KERN_CRIT "Waiting for connection from remote gdb... ");
> breakpoint() ;
> - printk(KERN_CRIT "Connected.\n");
> + printk("Connected.\n");
> }
>
> #ifdef CONFIG_KGDB_CONSOLE
>
> --
> Tom Rini
> http://gate.crashing.org/~trini/
>
> ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

--
Amit Kale
EmSysSoft (http://www.emsyssoft.com)
KGDB: Linux Kernel Source Level Debugger (http://kgdb.sourceforge.net)

2004-01-27 09:05:57

by Amit S. Kale

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Tuesday 27 Jan 2004 3:36 am, Tom Rini wrote:
> On Mon, Jan 26, 2004 at 01:45:44PM -0800, George Anzinger wrote:
> > Tom Rini wrote:
> > >>There is a real danger of passing signal info back to gdb as it will
> > >> want to try to deliver the signal which is a non-compute in most kgdbs
> > >> in the field. I did put code in the mm-kgdb to do just this, but
> > >> usually the arrival of such a signal (other than SIGTRAP) is the end
> > >> of the kernel. All that is left is to read the tea leaves.
> > >
> > >The gdb I've been testing this with knows better than to try and send a
> > >singal back, so that's not a worry. The motivation behind doing this
> > >however is along the lines of "if it ain't broke, don't remove it". The
> > >original stub was getting all of this information correctly, so why stop
> > >doing it?
> >
> > You sure. If so what gdb? And how does it know? I suppose you could
> > tell it with a script, but then what if one forgets?
>
> GNU gdb 6.0 (MontaVista 6.0-8.0.4.0300532 2003-12-24)
> Copyright 2003 Free Software Foundation, Inc.
> [snip]
>
> [New Thread 289]
>
> Program received signal SIGSEGV, Segmentation fault.
> [Switching to Thread 289]
> 0x00000000 in ?? ()
> (gdb) c
> Continuing.
> Can't send signals to this remote system. SIGSEGV not sent.

This is because gdb tries packet "C" first. If that fails, which is the case
with kgdb, it falls back to packet "c". It doesn't need packet "C" for
SIGTRAP as it's used for breakpoints and single stepping and shouldn't be
delivered to a debuggee.

SIGSEGV has to be actually delivered to an application for it to die. A user
has a choice of correcting a bug on the fly and let the application continue
without segfaulting. It can tell gdb to continue the debugee without a
signal. It doesn't apply in case of kernel, so it's not a bug. Kernel anyway
"delivers" the signal, that is, continues with a panic once kgdb returns. We
don't offer a user the choice of correcting a segfault on the fly.

>
> Noting that 0x0 is correct as the code that triggered this was:
> static void (*dummy)(struct pt_regs *regs);
> int drop_kgdb(void) {
> struct pt_regs regs;
> memset(&regs, 0, sizeof(regs));
> dummy(&regs);
>
> return 0;
> }
> module_init(drop_kgdb);
>
> --
> Tom Rini
> http://gate.crashing.org/~trini/
>
> ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

--
Amit Kale
EmSysSoft (http://www.emsyssoft.com)
KGDB: Linux Kernel Source Level Debugger (http://kgdb.sourceforge.net)

2004-01-27 18:22:49

by Tom Rini

[permalink] [raw]
Subject: Re: PPC KGDB changes and some help?

On Fri, Jan 23, 2004 at 03:46:05PM -0700, Tom Rini wrote:

> On Thu, Jan 22, 2004 at 11:05:55AM -0700, Tom Rini wrote:
> [snip]
> > First up:
> > We need to call flush_instruction_cache() on a 'c' or 's' command.
> > arch/ppc/kernel/ppc-stub.c | 19 ++++++-------------
> > 1 files changed, 6 insertions(+), 13 deletions(-)
>
> On tpo of this patch, there's the following:
> Put back some code to figure out what signal we're dealing with.

And here's a version that with some help from Daniel always passes the
correct information back to GDB (the original code did not).

arch/ppc/kernel/ppc-stub.c | 63 ++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 60 insertions(+), 3 deletions(-)
--- 1.15/arch/ppc/kernel/ppc-stub.c Thu Jan 22 10:53:06 2004
+++ edited/arch/ppc/kernel/ppc-stub.c Tue Jan 27 11:08:25 2004
@@ -3,6 +3,7 @@
*
* PowerPC-specific bits to work with the common KGDB stub.
*
+ * 1998 (c) Michael AK Tesch ([email protected])
* 2003 (c) TimeSys Corporation
* 2004 (c) MontaVista Software, Inc.
* This file is licensed under the terms of the GNU General Public License
@@ -19,13 +20,69 @@
#include <asm/processor.h>
#include <asm/machdep.h>

+/* Convert the hardware trap type code to a unix signal number. */
+/*
+ * This table contains the mapping between PowerPC hardware trap types, and
+ * signals, which are primarily what GDB understands.
+ */
+static struct hard_trap_info
+{
+ unsigned int tt; /* Trap type code for powerpc */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+#if defined(CONFIG_40x)
+ { 0x0100, 0x02 /* SIGINT */ }, /* critical input interrupt */
+ { 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */
+ { 0x0300, 0x0b /* SIGSEGV */ }, /* data storage */
+ { 0x0400, 0x0a /* SIGBUS */ }, /* instruction storage */
+ { 0x0500, 0x02 /* SIGINT */ }, /* interrupt */
+ { 0x0600, 0x0a /* SIGBUS */ }, /* alignment */
+ { 0x0700, 0x04 /* SIGILL */ }, /* program */
+ { 0x0800, 0x04 /* SIGILL */ }, /* reserved */
+ { 0x0900, 0x04 /* SIGILL */ }, /* reserved */
+ { 0x0a00, 0x04 /* SIGILL */ }, /* reserved */
+ { 0x0b00, 0x04 /* SIGILL */ }, /* reserved */
+ { 0x0c00, 0x14 /* SIGCHLD */ }, /* syscall */
+ { 0x0d00, 0x04 /* SIGILL */ }, /* reserved */
+ { 0x0e00, 0x04 /* SIGILL */ }, /* reserved */
+ { 0x0f00, 0x04 /* SIGILL */ }, /* reserved */
+ { 0x2000, 0x05 /* SIGTRAP */}, /* debug */
+#else
+ { 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */
+ { 0x0300, 0x0b /* SIGSEGV */ }, /* address error (store) */
+ { 0x0400, 0x0a /* SIGBUS */ }, /* instruction bus error */
+ { 0x0500, 0x02 /* SIGINT */ }, /* interrupt */
+ { 0x0600, 0x0a /* SIGBUS */ }, /* alingment */
+ { 0x0700, 0x05 /* SIGTRAP */ }, /* breakpoint trap */
+ { 0x0800, 0x08 /* SIGFPE */}, /* fpu unavail */
+ { 0x0900, 0x0e /* SIGALRM */ }, /* decrementer */
+ { 0x0a00, 0x04 /* SIGILL */ }, /* reserved */
+ { 0x0b00, 0x04 /* SIGILL */ }, /* reserved */
+ { 0x0c00, 0x14 /* SIGCHLD */ }, /* syscall */
+ { 0x0d00, 0x05 /* SIGTRAP */ }, /* single-step/watch */
+ { 0x0e00, 0x08 /* SIGFPE */ }, /* fp assist */
+#endif
+ { 0x0000, 0x000 } /* Must be last */
+};
+
+static int computeSignal(unsigned int tt)
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
/*
* Routines
*/
static void
kgdb_debugger(struct pt_regs *regs)
{
- (*linux_debug_hook) (0, 0, 0, regs);
+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
return;
}

@@ -52,14 +109,14 @@
int
kgdb_iabr_match(struct pt_regs *regs)
{
- (*linux_debug_hook) (0, 0, 0, regs);
+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
return 1;
}

int
kgdb_dabr_match(struct pt_regs *regs)
{
- (*linux_debug_hook) (0, 0, 0, regs);
+ (*linux_debug_hook) (0, computeSignal(regs->trap), 0, regs);
return 1;
}


--
Tom Rini
http://gate.crashing.org/~trini/