Hi!
No real code changes, but cleanups all over the place. What about
applying?
Ouch and arch-dependend code is moved to kernel/kgdb.c. I'll probably
do x86-64 version so that is rather important.
Pavel
--- tmp/linux/Documentation/i386/kgdb/kgdb.txt 2004-01-09 19:04:43.000000000 +0100
+++ linux/Documentation/i386/kgdb/kgdb.txt 2003-12-25 15:11:19.000000000 +0100
@@ -1,242 +1,9 @@
-Last edit: <20030806.1637.12>
-This file has information specific to the i386 kgdb option. Other
-platforms with the kgdb option may behave in a similar fashion.
-
-New features:
-============
-20030806.1557.37
-This version was made against the 2.6.0-test2 kernel. We have made the
-following changes:
-
-- The getthread() code in the stub calls find_task_by_pid(). It fails
- if we are early in the bring up such that the pid arrays have yet to
- be allocated. We have added a line to kernel/pid.c to make
- "kgdb_pid_init_done" true once the arrays are allocated. This way the
- getthread() code knows not to call. This is only used by the thread
- debugging stuff and threads will not yet exist at this point in the
- boot.
-
-- For some reason, gdb was not asking for a new thread list when the
- "info thread" command was given. We changed to the newer version of
- the thread info command and gdb now seems to ask when needed. Result,
- we now get all threads in the thread list.
-
-- We now respond to the ThreadExtraInfo request from gdb with the thread
- name from task_struct .comm. This then appears in the thread list.
- Thoughts on additional options for this are welcome. Things such as
- "has BKL" and "Preempted" come to mind. I think we could have a flag
- word that could enable different bits of info here.
-
-- We now honor, sort of, the C and S commands. These are continue and
- single set after delivering a signal. We ignore the signal and do the
- requested action. This only happens when we told gdb that a signal
- was the reason for entry, which is only done on memory faults. The
- result is that you can now continue into the Oops.
-
-- We changed the -g to -gdwarf-2. This seems to be the same as -ggdb,
- but it is more exact on what language to use.
-
-- We added two dwarf2 include files and a bit of code at the end of
- entry.S. This does not yet work, so it is disabled. Still we want to
- keep track of the code and "maybe" someone out there can fix it.
-
-- Randy Dunlap sent some fix ups for this file which are now merged.
-
-- Hugh Dickins sent a fix to a bit of code in traps.c that prevents a
- compiler warning if CONFIG_KGDB is off (now who would do that :).
-
-- Andrew Morton sent a fix for the serial driver which is now merged.
-
-- Andrew also sent a change to the stub around the cpu managment code
- which is also merged.
-
-- Andrew also sent a patch to make "f" as well as "g" work as SysRq
- commands to enter kgdb, merged.
-
-- If CONFIG_KGDB and CONFIG_DEBUG_SPINLOCKS are both set we added a
- "who" field to the spinlock data struct. This is filled with
- "current" when ever the spinlock suceeds. Useful if you want to know
- who has the lock.
-
-_ And last, but not least, we fixed the "get_cu" macro to properly get
- the current value of "current".
-
-New features:
-============
-20030505.1827.27
-We are starting to align with the sourceforge version, at least in
-commands. To this end, the boot command string to start kgdb at
-boot time has been changed from "kgdb" to "gdb".
-
-Andrew Morton sent a couple of patches which are now included as follows:
-1.) We now return a flag to the interrupt handler.
-2.) We no longer use smp_num_cpus (a conflict with the lock meter).
-3.) And from William Lee Irwin III <[email protected]> code to make
- sure high-mem is set up before we attempt to register our interrupt
- handler.
-We now include asm/kgdb.h from config.h so you will most likely never
-have to include it. It also 'NULLS' the kgdb macros you might have in
-your code when CONFIG_KGDB is not defined. This allows you to just
-turn off CONFIG_KGDB to turn off all the kgdb_ts() calls and such.
-This include is conditioned on the machine being an x86 so as to not
-mess with other archs.
-
-20020801.1129.03
-This is currently the version for the 2.4.18 (and beyond?) kernel.
-
-We have several new "features" beginning with this version:
-
-1.) Kgdb now syncs the "other" CPUs with a cross-CPU NMI. No more
- waiting and it will pull that guy out of an IRQ off spin lock :)
-
-2.) We doctored up the code that tells where a task is waiting and
- included it so that the "info thread" command will show a bit more
- than "schedule()". Try it...
-
-3.) Added the ability to call a function from gdb. All the standard gdb
- issues apply, i.e. if you hit a breakpoint in the function, you are
- not allowed to call another (gdb limitation, not kgdb). To help
- this capability we added a memory allocation function. Gdb does not
- return this memory (it is used for strings that you pass to that function
- you are calling from gdb) so we fixed up a way to allow you to
- manually return the memory (see below).
-
-4.) Kgdb time stamps (kgdb_ts()) are enhanced to expand what was the
- interrupt flag to now also include the preemption count and the
- "in_interrupt" info. The flag is now called "with_pif" to indicate
- the order, preempt_count, in_interrupt, flag. The preempt_count is
- shifted left by 4 bits so you can read the count in hex by dropping
- the low order digit. In_interrupt is in bit 1, and the flag is in
- bit 0.
-
-5.) The command: "p kgdb_info" is now expanded and prints something
- like:
-(gdb) p kgdb_info
-$2 = {used_malloc = 0, called_from = 0xc0107506, entry_tsc = 67468627259,
- errcode = 0, vector = 3, print_debug_info = 0, hold_on_sstep = 1,
- cpus_waiting = {{task = 0xc027a000, pid = 32768, hold = 0,
- regs = 0xc027bf84}, {task = 0x0, pid = 0, hold = 0, regs = 0x0}}}
-
- Things to note here: a.) used_malloc is the amount of memory that
- has been malloc'ed to do calls from gdb. You can reclaim this
- memory like this: "p kgdb_info.used_malloc=0" Cool, huh? b.)
- cpus_waiting is now "sized" by the number of CPUs you enter at
- configure time in the kgdb configure section. This is NOT used
- anywhere else in the system, but it is "nice" here. c.) The task's
- "pid" is now in the structure. This is the pid you will need to use
- to decode to the thread id to get gdb to look at that thread.
- Remember that the "info thread" command prints a list of threads
- wherein it numbers each thread with its reference number followed
- by the thread's pid. Note that the per-CPU idle threads actually
- have pids of 0 (yes, there is more than one pid 0 in an SMP system).
- To avoid confusion, kgdb numbers these threads with numbers beyond
- the MAX_PID. That is why you see 32768 and above.
-
-6.) A subtle change, we now provide the complete register set for tasks
- that are active on the other CPUs. This allows better trace back on
- those tasks.
-
- And, let's mention what we could not fix. Back-trace from all but the
- thread that we trapped will, most likely, have a bogus entry in it.
- The problem is that gdb does not recognize the entry code for
- functions that use "current" near (at all?) the entry. The compiler
- is putting the "current" decode as the first two instructions of the
- function where gdb expects to find %ebp changing code. Back trace
- also has trouble with interrupt frames. I am talking with Daniel
- Jacobowitz about some way to fix this, but don't hold your breath.
-
-20011220.0050.35
-Major enhancement with this version is the ability to hold one or more
-CPUs in an SMP system while allowing the others to continue. Also, by
-default only the current CPU is enabled on single-step commands (please
-note that gdb issues single-step commands at times other than when you
-use the si command).
-
-Another change is to collect some useful information in
-a global structure called "kgdb_info". You should be able to just:
-
-p kgdb_info
-
-although I have seen cases where the first time this is done gdb just
-prints the first member but prints the whole structure if you then enter
-CR (carriage return or enter). This also works:
-
-p *&kgdb_info
-
-Here is a sample:
-(gdb) p kgdb_info
-$4 = {called_from = 0xc010732c, entry_tsc = 32804123790856, errcode = 0,
- vector = 3, print_debug_info = 0}
-
-"Called_from" is the return address from the current entry into kgdb.
-Sometimes it is useful to know why you are in kgdb, for example, was
-it an NMI or a real breakpoint? The simple way to interrogate this
-return address is:
-
-l *0xc010732c
-
-which will print the surrounding few lines of source code.
-
-"Entry_tsc" is the CPU TSC on entry to kgdb (useful to compare to the
-kgdb_ts entries).
-
-"errcode" and "vector" are other entry parameters which may be helpful on
-some traps.
-
-"print_debug_info" is the internal debugging kgdb print enable flag. Yes,
-you can modify it.
-
-In SMP systems kgdb_info also includes the "cpus_waiting" structure and
-"hold_on_step":
-
-(gdb) p kgdb_info
-$7 = {called_from = 0xc0112739, entry_tsc = 1034936624074, errcode = 0,
- vector = 2, print_debug_info = 0, hold_on_sstep = 1, cpus_waiting = {{
- task = 0x0, hold = 0, regs = 0x0}, {task = 0xc71b8000, hold = 0,
- regs = 0xc71b9f70}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0,
- hold = 0, regs = 0x0}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0,
- hold = 0, regs = 0x0}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0,
- hold = 0, regs = 0x0}}}
-
-"Cpus_waiting" has an entry for each CPU other than the current one that
-has been stopped. Each entry contains the task_struct address for that
-CPU, the address of the regs for that task and a hold flag. All these
-have the proper typing so that, for example:
-
-p *kgdb_info.cpus_waiting[1].regs
-
-will print the registers for CPU 1.
-
-"Hold_on_sstep" is a new feature with this version and comes up set or
-true. What this means is that whenever kgdb is asked to single-step all
-other CPUs are held (i.e. not allowed to execute). The flag applies to
-all but the current CPU and, again, can be changed:
-
-p kgdb_info.hold_on_sstep=0
-
-restores the old behavior of letting all CPUs run during single-stepping.
-
-Likewise, each CPU has a "hold" flag, which if set, locks that CPU out
-of execution. Note that this has some risk in cases where the CPUs need
-to communicate with each other. If kgdb finds no CPU available on exit,
-it will push a message thru gdb and stay in kgdb. Note that it is legal
-to hold the current CPU as long as at least one CPU can execute.
-
-20010621.1117.09
-This version implements an event queue. Events are signaled by calling
-a function in the kgdb stub and may be examined from gdb. See EVENTS
-below for details. This version also tightens up the interrupt and SMP
-handling to not allow interrupts on the way to kgdb from a breakpoint
-trap. It is fine to allow these interrupts for user code, but not
-system debugging.
-
Version
=======
-This version of the kgdb package was developed and tested on
-kernel version 2.4.16. It will not install on any earlier kernels.
-It is possible that it will continue to work on later versions
-of 2.4 and then versions of 2.5 (I hope).
+This version of the kgdb package was developed and tested on kernel
+version 2.6.0. It is possible that it will continue to work on later
+versions of 2.6.
Debugging Setup
@@ -314,7 +81,7 @@
set up after any serial drivers, it is possible that this command will
work when the control-C will not.
-Save and exit the Xconfig program. Then do "make clean" , "make dep"
+Save and exit the Xconfig program. Then do "make clean"
and "make bzImage" (or whatever target you want to make). This gets the
kernel compiled with the "-g" option set -- necessary for debugging.
diff -ur -x '.dep*' -x '.hdep*' -x '*.[oas]' -x '*~' -x '#*' -x '*CVS*' -x '*.orig' -x '*.rej' -x '*.old' -x '.menu*' -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinux -x vmlinuz -x TAGS -x bootsect -x '*RCS*' -x conmakehash -x map -x build -x build -x configure -x '*target*' -x '*.flags' -x '*.bak' -x '*.cmd' tmp/linux/Documentation/i386/kgdb/kgdbeth.txt linux/Documentation/i386/kgdb/kgdbeth.txt
--- tmp/linux/Documentation/i386/kgdb/kgdbeth.txt 2004-01-09 19:04:43.000000000 +0100
+++ linux/Documentation/i386/kgdb/kgdbeth.txt 2003-12-25 14:55:58.000000000 +0100
@@ -33,8 +33,8 @@
gdbeth=DEVICENUM
gdbeth_remoteip=HOSTIPADDR
- gdbeth_remotemac=REMOTEMAC
- gdbeth_localmac=LOCALMAC
+ gdbeth_remotemac=HOSTMAC
+ gdbeth_localmac=TARGETMAC
kgdbeth=DEVICENUM sets the ethernet device number to listen on for
debugging packets. e.g. kgdbeth=0 listens on eth0.
@@ -43,10 +43,10 @@
Only packets originating from this IP address will be accepted by the
debugger. e.g. kgdbeth_remoteip=192.168.2.2
-kgdbeth_remotemac=REMOTEMAC sets the ethernet address of the HOST machine.
+kgdbeth_remotemac=HOSTMAC sets the ethernet address of the HOST machine.
e.g. kgdbeth_remotemac=00:07:70:12:4E:F5
-kgdbeth_localmac=LOCALMAC sets the ethernet address of the TARGET machine.
+kgdbeth_localmac=TARGETMAC sets the ethernet address of the TARGET machine.
e.g. kgdbeth_localmac=00:10:9F:18:21:3C
You can also set the following command-line option on the TARGET kernel:
--- tmp/linux/arch/i386/kernel/entry.S 2004-01-09 19:04:43.000000000 +0100
+++ linux/arch/i386/kernel/entry.S 2003-12-27 17:08:29.000000000 +0100
@@ -71,51 +71,6 @@
# location or end up with a return address pointing at the
# location, we don't need a correct call frame for it.
-#if 0
-
-#include <linux/dwarf2-lang.h>
-/*
- * The register numbers as known by gdb
- */
-#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_define_reference(_ESP,OLDESP)
- CFA_define_offset(_EIP,EIP)
- CFA_define_offset(_EBX,EBX)
- CFA_define_offset(_ECX,ECX)
- CFA_define_offset(_EDX,EDX)
- CFA_define_offset(_ESI,ESI)
- CFA_define_offset(_EDI,EDI)
- CFA_define_offset(_EBP,EBP)
- CFA_define_offset(_EAX,EAX)
- CFA_define_offset(_EFLAGS,EFLAGS)
- CFA_define_offset(_CS,CS)
- CFA_define_offset(_DS,DS)
- CFA_define_offset(_ES,ES)
- CFI_postamble(c1)
-
- FDE_preamble(c1,f1,ret_from_intr,(divide_error - ret_from_intr))
- FDE_postamble(f1)
-#endif
-
EBX = 0x00
ECX = 0x04
EDX = 0x08
@@ -366,19 +321,6 @@
testw $_TIF_ALLWORK_MASK, %cx # current->work
jne syscall_exit_work
restore_all:
-#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS
- movl EFLAGS(%esp), %eax # mix EFLAGS and CS
- movb CS(%esp), %al
- testl $(VM_MASK | 3), %eax
- jz resume_kernelX # returning to kernel or vm86-space
-
- cmpl $0,TI_PRE_COUNT(%ebx) # non-zero preempt_count ?
- jz resume_kernelX
-
- int $3
-
-resume_kernelX:
-#endif
RESTORE_ALL
# perform work that needs to be done immediately before resumption
--- tmp/linux/arch/i386/kernel/kgdb_stub.c 2004-01-09 19:04:43.000000000 +0100
+++ linux/arch/i386/kernel/kgdb_stub.c 2003-12-28 21:40:20.000000000 +0100
@@ -1,4 +1,8 @@
/*
+ * Kernel gdb stub, arch-dependend part
+ *
+ * Copyright (c) 2000 VERITAS Software Corporation.
+ * Copyright (c) 2003 Pavel Machek <[email protected]>
*
* 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
@@ -12,98 +16,7 @@
*
*/
-/*
- * Copyright (c) 2000 VERITAS Software Corporation.
- *
- */
-/****************************************************************************
- * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
- *
- * Module name: remcom.c $
- * Revision: 1.34 $
- * Date: 91/03/09 12:29:49 $
- * Contributor: Lake Stevens Instrument Division$
- *
- * Description: low level support for gdb debugger. $
- *
- * Considerations: only works on target hardware $
- *
- * Written by: Glenn Engel $
- * Updated by: David Grothe <[email protected]>
- * Updated by: Robert Walsh <[email protected]>
- * Updated by: wangdi <[email protected]>
- * ModuleState: Experimental $
- *
- * NOTES: See Below $
- *
- * Modified for 386 by Jim Kingdon, Cygnus Support.
- * Compatibility with 2.1.xx kernel by David Grothe <[email protected]>
- *
- * Changes to allow auto initilization. All that is needed is that it
- * be linked with the kernel and a break point (int 3) be executed.
- * The header file <asm/kgdb.h> defines BREAKPOINT to allow one to do
- * this. It should also be possible, once the interrupt system is up, to
- * call putDebugChar("+"). Once this is done, the remote debugger should
- * get our attention by sending a ^C in a packet. George Anzinger
- * <[email protected]>
- * Integrated into 2.2.5 kernel by Tigran Aivazian <[email protected]>
- * Added thread support, support for multiple processors,
- * support for ia-32(x86) hardware debugging.
- * Amit S. Kale ( [email protected] )
- *
- * Modified to support debugging over ethernet by Robert Walsh
- * <[email protected]> and wangdi <[email protected]>, based on
- * code by San Mehat.
- *
- *
- * To enable debugger support, two things need to happen. One, a
- * call to set_debug_traps() is necessary in order to allow any breakpoints
- * or error conditions to be properly intercepted and reported to gdb.
- * Two, a breakpoint needs to be generated to begin communication. This
- * is most easily accomplished by a call to breakpoint(). Breakpoint()
- * simulates a breakpoint by executing an int 3.
- *
- *************
- *
- * The following gdb commands are supported:
- *
- * command function Return value
- *
- * g return the value of the CPU registers hex data or ENN
- * G set the value of the CPU registers OK or ENN
- *
- * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
- * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
- *
- * c Resume at current address SNN ( signal NN)
- * cAA..AA Continue at address AA..AA SNN
- *
- * s Step one instruction SNN
- * sAA..AA Step one instruction from AA..AA SNN
- *
- * k kill
- *
- * ? What was the last sigval ? SNN (signal NN)
- *
- * All commands and responses are sent with a packet which includes a
- * checksum. A packet consists of
- *
- * $<packet info>#<checksum>.
- *
- * where
- * <packet info> :: <characters representing the command or response>
- * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
- *
- * When a packet is received, it is first acknowledged with either '+' or '-'.
- * '+' indicates a successful transfer. '-' indicates a failed transfer.
- *
- * Example:
- *
- * Host: Reply:
- * $m0,10#2a +$00010203040506070809101112131415#42
- *
- ****************************************************************************/
-#define KGDB_VERSION "<20030915.1651.33>"
+#define KGDB_VERSION "2.6.0"
#include <linux/config.h>
#include <linux/types.h>
#include <asm/string.h> /* for strcpy */
@@ -121,41 +34,11 @@
#include <linux/inet.h>
#include <linux/kallsyms.h>
-/************************************************************************
- *
- * external low-level support routines
- */
-typedef void (*Function) (void); /* pointer to a function */
-
-/* Thread reference */
-typedef unsigned char threadref[8];
-
-extern int tty_putDebugChar(int); /* write a single character */
-extern int tty_getDebugChar(void); /* read and return a single char */
-extern void tty_flushDebugChar(void); /* flush pending characters */
-extern int eth_putDebugChar(int); /* write a single character */
-extern int eth_getDebugChar(void); /* read and return a single char */
-extern void eth_flushDebugChar(void); /* flush pending characters */
-extern void kgdb_eth_set_trapmode(int);
-extern void kgdb_eth_reply_arp(void); /*send arp request */
-extern volatile int kgdb_eth_is_initializing;
-
-
-/************************************************************************/
-/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
-/* at least NUMREGBYTES*2 are needed for register packets */
-/* Longer buffer is needed to list all threads */
-#define BUFMAX 400
-
-char *kgdb_version = KGDB_VERSION;
-
-/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
-int debug_regs = 0; /* set to non-zero to print registers */
-
-/* filled in by an external module */
-char *gdb_module_offsets;
+#if __GNUC__ < 3
+#error Sorry, your GCC is too old to work with kgdb. (It works with 3.3.2)
+#endif
-static const char hexchars[] = "0123456789abcdef";
+#include "../../../kernel/kgdb.c"
/* Number of bytes of registers. */
#define NUMREGBYTES 64
@@ -184,135 +67,11 @@
_GS /* 15 */
};
-/*************************** ASSEMBLY CODE MACROS *************************/
-/*
- * Put the error code here just in case the user cares.
- * Likewise, the vector number here (since GDB only gets the signal
- * number through the usual means, and that's not very specific).
- * The called_from is the return address so he can tell how we entered kgdb.
- * This will allow him to seperate out the various possible entries.
- */
-#define REMOTE_DEBUG 0 /* set != to turn on printing (also available in info) */
-
-#define PID_MAX PID_MAX_DEFAULT
-
-#ifdef CONFIG_SMP
-void smp_send_nmi_allbutself(void);
-#define IF_SMP(x) x
-#undef MAX_NO_CPUS
-#ifndef CONFIG_NO_KGDB_CPUS
-#define CONFIG_NO_KGDB_CPUS 2
-#endif
-#if CONFIG_NO_KGDB_CPUS > NR_CPUS
-#define MAX_NO_CPUS NR_CPUS
-#else
-#define MAX_NO_CPUS CONFIG_NO_KGDB_CPUS
-#endif
-#define hold_init hold_on_sstep: 1,
-#define MAX_CPU_MASK (unsigned long)((1LL << MAX_NO_CPUS) - 1LL)
-#define NUM_CPUS num_online_cpus()
-#else
-#define IF_SMP(x)
-#define hold_init
-#undef MAX_NO_CPUS
-#define MAX_NO_CPUS 1
-#define NUM_CPUS 1
-#endif
-#define NOCPU (struct task_struct *)0xbad1fbad
-/* *INDENT-OFF* */
-struct kgdb_info {
- int used_malloc;
- void *called_from;
- long long entry_tsc;
- int errcode;
- int vector;
- int print_debug_info;
-#ifdef CONFIG_SMP
- int hold_on_sstep;
- struct {
- volatile struct task_struct *task;
- int pid;
- int hold;
- struct pt_regs *regs;
- } cpus_waiting[MAX_NO_CPUS];
-#endif
-} kgdb_info = {hold_init print_debug_info:REMOTE_DEBUG, vector:-1};
-
-/* *INDENT-ON* */
-
-#define used_m kgdb_info.used_malloc
-/*
- * This is little area we set aside to contain the stack we
- * need to build to allow gdb to call functions. We use one
- * per cpu to avoid locking issues. We will do all this work
- * with interrupts off so that should take care of the protection
- * issues.
- */
-#define LOOKASIDE_SIZE 200 /* should be more than enough */
-#define MALLOC_MAX 200 /* Max malloc size */
-struct {
- unsigned int esp;
- int array[LOOKASIDE_SIZE];
-} fn_call_lookaside[MAX_NO_CPUS];
-
-static int trap_cpu;
static unsigned int OLD_esp;
-#define END_OF_LOOKASIDE &fn_call_lookaside[trap_cpu].array[LOOKASIDE_SIZE]
#define IF_BIT 0x200
#define TF_BIT 0x100
-#define MALLOC_ROUND 8-1
-
-static char malloc_array[MALLOC_MAX];
-IF_SMP(static void to_gdb(const char *mess));
-void *
-malloc(int size)
-{
-
- if (size <= (MALLOC_MAX - used_m)) {
- int old_used = used_m;
- used_m += ((size + MALLOC_ROUND) & (~MALLOC_ROUND));
- return &malloc_array[old_used];
- } else {
- return NULL;
- }
-}
-
-/*
- * I/O dispatch functions...
- * Based upon kgdb_eth, either call the ethernet
- * handler or the serial one..
- */
-void
-putDebugChar(int c)
-{
- if (kgdb_eth == -1) {
- tty_putDebugChar(c);
- } else {
- eth_putDebugChar(c);
- }
-}
-
-int
-getDebugChar(void)
-{
- if (kgdb_eth == -1) {
- return tty_getDebugChar();
- } else {
- return eth_getDebugChar();
- }
-}
-
-void
-flushDebugChar(void)
-{
- if (kgdb_eth == -1) {
- tty_flushDebugChar();
- } else {
- eth_flushDebugChar();
- }
-}
/*
* Gdb calls functions by pushing agruments, including a return address
@@ -345,7 +104,7 @@
*/
extern asmlinkage void fn_call_stub(void);
extern asmlinkage void fn_rtn_stub(void);
-/* *INDENT-OFF* */
+
__asm__("fn_rtn_stub:\n\t"
"movl %eax,%esp\n\t"
"fn_call_stub:\n\t"
@@ -359,213 +118,11 @@
"popl %ebx\n\t"
"popl %ecx\n\t"
"iret \n\t");
-/* *INDENT-ON* */
+
#define gdb_i386vector kgdb_info.vector
#define gdb_i386errcode kgdb_info.errcode
-#define waiting_cpus kgdb_info.cpus_waiting
-#define remote_debug kgdb_info.print_debug_info
-#define hold_cpu(cpu) kgdb_info.cpus_waiting[cpu].hold
-/* gdb locks */
-
-#ifdef CONFIG_SMP
-static int in_kgdb_called;
-static spinlock_t waitlocks[MAX_NO_CPUS] =
- {[0 ... MAX_NO_CPUS - 1] = SPIN_LOCK_UNLOCKED };
-/*
- * The following array has the thread pointer of each of the "other"
- * cpus. We make it global so it can be seen by gdb.
- */
-volatile int in_kgdb_entry_log[MAX_NO_CPUS];
-volatile struct pt_regs *in_kgdb_here_log[MAX_NO_CPUS];
-/*
-static spinlock_t continuelocks[MAX_NO_CPUS];
-*/
-spinlock_t kgdb_spinlock = SPIN_LOCK_UNLOCKED;
-/* waiters on our spinlock plus us */
-static atomic_t spinlock_waiters = ATOMIC_INIT(1);
-static int spinlock_count = 0;
-static int spinlock_cpu = 0;
-/*
- * Note we use nested spin locks to account for the case where a break
- * point is encountered when calling a function by user direction from
- * kgdb. Also there is the memory exception recursion to account for.
- * Well, yes, but this lets other cpus thru too. Lets add a
- * cpu id to the lock.
- */
-#define KGDB_SPIN_LOCK(x) if( spinlock_count == 0 || \
- spinlock_cpu != smp_processor_id()){\
- atomic_inc(&spinlock_waiters); \
- while (! spin_trylock(x)) {\
- in_kgdb(®s);\
- }\
- atomic_dec(&spinlock_waiters); \
- spinlock_count = 1; \
- spinlock_cpu = smp_processor_id(); \
- }else{ \
- spinlock_count++; \
- }
-#define KGDB_SPIN_UNLOCK(x) if( --spinlock_count == 0) spin_unlock(x)
-#else
-unsigned kgdb_spinlock = 0;
-#define KGDB_SPIN_LOCK(x) --*x
-#define KGDB_SPIN_UNLOCK(x) ++*x
-#endif
-
-int
-hex(char ch)
-{
- if ((ch >= 'a') && (ch <= 'f'))
- return (ch - 'a' + 10);
- if ((ch >= '0') && (ch <= '9'))
- return (ch - '0');
- if ((ch >= 'A') && (ch <= 'F'))
- return (ch - 'A' + 10);
- return (-1);
-}
-/* scan for the sequence $<data>#<checksum> */
-void
-getpacket(char *buffer)
-{
- unsigned char checksum;
- unsigned char xmitcsum;
- int i;
- int count;
- char ch;
- do {
- /* wait around for the start character, ignore all other characters */
- while ((ch = (getDebugChar() & 0x7f)) != '$') ;
- checksum = 0;
- xmitcsum = -1;
-
- count = 0;
-
- /* now, read until a # or end of buffer is found */
- while (count < BUFMAX) {
- ch = getDebugChar() & 0x7f;
- if (ch == '#')
- break;
- checksum = checksum + ch;
- buffer[count] = ch;
- count = count + 1;
- }
- buffer[count] = 0;
-
- if (ch == '#') {
- xmitcsum = hex(getDebugChar() & 0x7f) << 4;
- xmitcsum += hex(getDebugChar() & 0x7f);
- if ((remote_debug) && (checksum != xmitcsum)) {
- printk
- ("bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
- checksum, xmitcsum, buffer);
- }
-
- if (checksum != xmitcsum)
- putDebugChar('-'); /* failed checksum */
- else {
- putDebugChar('+'); /* successful transfer */
- /* if a sequence char is present, reply the sequence ID */
- if (buffer[2] == ':') {
- putDebugChar(buffer[0]);
- putDebugChar(buffer[1]);
- /* remove sequence chars from buffer */
- count = strlen(buffer);
- for (i = 3; i <= count; i++)
- buffer[i - 3] = buffer[i];
- }
- }
- }
- } while (checksum != xmitcsum);
-
- if (remote_debug)
- printk("R:%s\n", buffer);
- flushDebugChar();
-}
-
-/* send the packet in buffer. */
-
-void
-putpacket(char *buffer)
-{
- unsigned char checksum;
- int count;
- char ch;
-
- /* $<packet info>#<checksum>. */
-
- if (kgdb_eth == -1) {
- do {
- if (remote_debug)
- printk("T:%s\n", buffer);
- putDebugChar('$');
- checksum = 0;
- count = 0;
-
- while ((ch = buffer[count])) {
- putDebugChar(ch);
- checksum += ch;
- count += 1;
- }
-
- putDebugChar('#');
- putDebugChar(hexchars[checksum >> 4]);
- putDebugChar(hexchars[checksum % 16]);
- flushDebugChar();
-
- } while ((getDebugChar() & 0x7f) != '+');
- } else {
- /*
- * For udp, we can not transfer too much bytes once.
- * We only transfer MAX_SEND_COUNT size bytes each time
- */
-
-#define MAX_SEND_COUNT 30
-
- int send_count = 0, i = 0;
- char send_buf[MAX_SEND_COUNT];
-
- do {
- if (remote_debug)
- printk("T:%s\n", buffer);
- putDebugChar('$');
- checksum = 0;
- count = 0;
- send_count = 0;
- while ((ch = buffer[count])) {
- if (send_count >= MAX_SEND_COUNT) {
- for(i = 0; i < MAX_SEND_COUNT; i++) {
- putDebugChar(send_buf[i]);
- }
- flushDebugChar();
- send_count = 0;
- } else {
- send_buf[send_count] = ch;
- checksum += ch;
- count ++;
- send_count++;
- }
- }
- for(i = 0; i < send_count; i++)
- putDebugChar(send_buf[i]);
- putDebugChar('#');
- putDebugChar(hexchars[checksum >> 4]);
- putDebugChar(hexchars[checksum % 16]);
- flushDebugChar();
- } while ((getDebugChar() & 0x7f) != '+');
- }
-}
-
-static char remcomInBuffer[BUFMAX];
-static char remcomOutBuffer[BUFMAX];
-static short error;
-
-void
-debug_error(char *format, char *parm)
-{
- if (remote_debug)
- printk(format, parm);
-}
static void
print_regs(struct pt_regs *regs)
@@ -658,14 +215,10 @@
#endif
} /* gdb_regs_to_regs */
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-#define first_sched ((unsigned long) scheduling_functions_start_here)
-#define last_sched ((unsigned long) scheduling_functions_end_here)
int thread_list = 0;
-void
+static void
get_gdb_regs(struct task_struct *p, struct pt_regs *regs, int *gdb_regs)
{
unsigned long stack_page;
@@ -727,20 +280,7 @@
return;
}
-/* Indicate to caller of mem2hex or hex2mem that there has been an
- error. */
-static volatile int mem_err = 0;
-static volatile int mem_err_expected = 0;
-static volatile int mem_err_cnt = 0;
-static int garbage_loc = -1;
-
-int
-get_char(char *addr)
-{
- return *addr;
-}
-
-void
+static void
set_char(char *addr, int val, int may_fault)
{
/*
@@ -756,260 +296,7 @@
*addr = val;
}
-/* convert the memory pointed to by mem into hex, placing result in buf */
-/* return a pointer to the last char put in buf (null) */
-/* If MAY_FAULT is non-zero, then we should set mem_err in response to
- a fault; if zero treat a fault like any other fault in the stub. */
-char *
-mem2hex(char *mem, char *buf, int count, int may_fault)
-{
- int i;
- unsigned char ch;
-
- if (may_fault) {
- mem_err_expected = 1;
- mem_err = 0;
- }
- for (i = 0; i < count; i++) {
- /* printk("%lx = ", mem) ; */
-
- ch = get_char(mem++);
-
- /* printk("%02x\n", ch & 0xFF) ; */
- if (may_fault && mem_err) {
- if (remote_debug)
- printk("Mem fault fetching from addr %lx\n",
- (long) (mem - 1));
- *buf = 0; /* truncate buffer */
- return (buf);
- }
- *buf++ = hexchars[ch >> 4];
- *buf++ = hexchars[ch % 16];
- }
- *buf = 0;
- if (may_fault)
- mem_err_expected = 0;
- return (buf);
-}
-
-/* convert the hex array pointed to by buf into binary to be placed in mem */
-/* return a pointer to the character AFTER the last byte written */
-/* NOTE: We use the may fault flag to also indicate if the write is to
- * the registers (0) or "other" memory (!=0)
- */
-char *
-hex2mem(char *buf, char *mem, int count, int may_fault)
-{
- int i;
- unsigned char ch;
-
- if (may_fault) {
- mem_err_expected = 1;
- mem_err = 0;
- }
- for (i = 0; i < count; i++) {
- ch = hex(*buf++) << 4;
- ch = ch + hex(*buf++);
- set_char(mem++, ch, may_fault);
-
- if (may_fault && mem_err) {
- if (remote_debug)
- printk("Mem fault storing to addr %lx\n",
- (long) (mem - 1));
- return (mem);
- }
- }
- if (may_fault)
- mem_err_expected = 0;
- return (mem);
-}
-
-/**********************************************/
-/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
-/* RETURN NUMBER OF CHARS PROCESSED */
-/**********************************************/
-int
-hexToInt(char **ptr, int *intValue)
-{
- int numChars = 0;
- int hexValue;
- *intValue = 0;
-
- while (**ptr) {
- hexValue = hex(**ptr);
- if (hexValue >= 0) {
- *intValue = (*intValue << 4) | hexValue;
- numChars++;
- } else
- break;
-
- (*ptr)++;
- }
-
- return (numChars);
-}
-
-#define stubhex(h) hex(h)
-#ifdef old_thread_list
-
-static int
-stub_unpack_int(char *buff, int fieldlength)
-{
- int nibble;
- int retval = 0;
-
- while (fieldlength) {
- nibble = stubhex(*buff++);
- retval |= nibble;
- fieldlength--;
- if (fieldlength)
- retval = retval << 4;
- }
- return retval;
-}
-#endif
-static char *
-pack_hex_byte(char *pkt, int byte)
-{
- *pkt++ = hexchars[(byte >> 4) & 0xf];
- *pkt++ = hexchars[(byte & 0xf)];
- return pkt;
-}
-
-#define BUF_THREAD_ID_SIZE 16
-
-static char *
-pack_threadid(char *pkt, threadref * id)
-{
- char *limit;
- unsigned char *altid;
-
- altid = (unsigned char *) id;
- limit = pkt + BUF_THREAD_ID_SIZE;
- while (pkt < limit)
- pkt = pack_hex_byte(pkt, *altid++);
- return pkt;
-}
-
-#ifdef old_thread_list
-static char *
-unpack_byte(char *buf, int *value)
-{
- *value = stub_unpack_int(buf, 2);
- return buf + 2;
-}
-
-static char *
-unpack_threadid(char *inbuf, threadref * id)
-{
- char *altref;
- char *limit = inbuf + BUF_THREAD_ID_SIZE;
- int x, y;
-
- altref = (char *) id;
-
- while (inbuf < limit) {
- x = stubhex(*inbuf++);
- y = stubhex(*inbuf++);
- *altref++ = (x << 4) | y;
- }
- return inbuf;
-}
-#endif
-void
-int_to_threadref(threadref * id, int value)
-{
- unsigned char *scan;
-
- scan = (unsigned char *) id;
- {
- int i = 4;
- while (i--)
- *scan++ = 0;
- }
- *scan++ = (value >> 24) & 0xff;
- *scan++ = (value >> 16) & 0xff;
- *scan++ = (value >> 8) & 0xff;
- *scan++ = (value & 0xff);
-}
-int
-int_to_hex_v(unsigned char * id, int value)
-{
- unsigned char *start = id;
- int shift;
- int ch;
-
- for (shift = 28; shift >= 0; shift -= 4) {
- if ((ch = (value >> shift) & 0xf) || (id != start)) {
- *id = hexchars[ch];
- id++;
- }
- }
- if (id == start)
- *id++ = '0';
- return id - start;
-}
-#ifdef old_thread_list
-
-static int
-threadref_to_int(threadref * ref)
-{
- int i, value = 0;
- unsigned char *scan;
-
- scan = (char *) ref;
- scan += 4;
- i = 4;
- while (i-- > 0)
- value = (value << 8) | ((*scan++) & 0xff);
- return value;
-}
-#endif
-static int
-cmp_str(char *s1, char *s2, int count)
-{
- while (count--) {
- if (*s1++ != *s2++)
- return 0;
- }
- return 1;
-}
-
-#if 1 /* this is a hold over from 2.4 where O(1) was "sometimes" */
-extern struct task_struct *kgdb_get_idle(int cpu);
-#define idle_task(cpu) kgdb_get_idle(cpu)
-#else
-#define idle_task(cpu) init_tasks[cpu]
-#endif
-
-extern int kgdb_pid_init_done;
-
-struct task_struct *
-getthread(int pid)
-{
- struct task_struct *thread;
- if (pid >= PID_MAX && pid <= (PID_MAX + MAX_NO_CPUS)) {
-
- return idle_task(pid - PID_MAX);
- } else {
- /*
- * find_task_by_pid is relatively safe all the time
- * Other pid functions require lock downs which imply
- * that we may be interrupting them (as we get here
- * in the middle of most any lock down).
- * Still we don't want to call until the table exists!
- */
- if (kgdb_pid_init_done){
- thread = find_task_by_pid(pid);
- if (thread) {
- return thread;
- }
- }
- }
- return NULL;
-}
-/* *INDENT-OFF* */
struct hw_breakpoint {
unsigned enabled;
unsigned type;
@@ -1019,7 +306,7 @@
{enabled:0},
{enabled:0},
{enabled:0}};
-/* *INDENT-ON* */
+
unsigned hw_breakpoint_status;
void
correct_hw_break(void)
@@ -1031,7 +318,7 @@
asm volatile ("movl %%db7, %0\n":"=r" (dr7)
:);
- /* *INDENT-OFF* */
+
do {
unsigned addr0, addr1, addr2, addr3;
asm volatile ("movl %%db0, %0\n"
@@ -1042,7 +329,7 @@
"=r"(addr2), "=r"(addr3)
:);
} while (0);
- /* *INDENT-ON* */
+
correctit = 0;
for (breakno = 0; breakno < 3; breakno++) {
breakbit = 2 << (breakno << 1);
@@ -1095,7 +382,7 @@
return 0;
}
-int
+static int
set_hw_break(unsigned breakno, unsigned type, unsigned len, unsigned addr)
{
if (breakinfo[breakno].enabled) {
@@ -1174,9 +461,6 @@
in_kgdb_here_log[cpu] = 0;
kgdb_local_irq_restore(flags);
return 1;
- /*
- spin_unlock(continuelocks + smp_processor_id());
- */
}
void
@@ -1298,16 +582,6 @@
* released.
*/
#ifdef CONFIG_SMP
-
-#if 0
- if (cpu_callout_map & ~MAX_CPU_MASK) {
- printk("kgdb : too many cpus, possibly not mapped"
- " in contiguous space, change MAX_NO_CPUS"
- " in kgdb_stub and make new kernel.\n"
- " cpu_callout_map is %lx\n", cpu_callout_map);
- goto exit_just_unlock;
- }
-#endif
if (spinlock_count == 1) {
int time, end_time, dum;
int i;
@@ -1388,25 +662,7 @@
if (i < num_online_cpus()) {
printk
("kgdb : time out, proceeding without sync\n");
-#if 0
- printk("kgdb : Waiting_cpus: 0 = %d, 1 = %d\n",
- waiting_cpus[0].task != 0,
- waiting_cpus[1].task != 0);
- printk("kgdb : Cpu_logged in: 0 = %d, 1 = %d\n",
- cpu_logged_in[0], cpu_logged_in[1]);
- printk
- ("kgdb : in_kgdb_here_log in: 0 = %d, 1 = %d\n",
- in_kgdb_here_log[0] != 0,
- in_kgdb_here_log[1] != 0);
-#endif
entry_state = NO_SYNC;
- } else {
-#if 0
- int ent =
- in_kgdb_entry_log[smp_processor_id()] -
- me_in_kgdb;
- printk("kgdb : sync after %d entries\n", ent);
-#endif
}
} else {
if (remote_debug) {
@@ -1434,7 +690,7 @@
/* Disable hardware debugging while we are in kgdb */
/* Get the debug register status register */
-/* *INDENT-OFF* */
+
__asm__("movl %0,%%db7"
: /* no output */
:"r"(0));
@@ -1443,7 +699,6 @@
:"=r" (hw_breakpoint_status)
:);
-/* *INDENT-ON* */
switch (exceptionVector) {
case 0: /* divide error */
case 1: /* debug exception */
@@ -1533,7 +788,7 @@
}
kgdb_eth_reply_arp();
- while (1 == 1) {
+ while (1) {
error = 0;
remcomOutBuffer[0] = 0;
getpacket(remcomInBuffer);
@@ -1989,11 +1244,8 @@
/* reply to the request */
putpacket(remcomOutBuffer);
- } /* while(1==1) */
- /*
- * reached by goto only.
- */
- exit_kgdb:
+ } /* while(1) */
+exit_kgdb: /* reached by goto only. */
/*
* Here is where we set up to trap a gdb function call. NEW_esp
* will be changed if we are trying to do this. We handle both
@@ -2072,9 +1324,6 @@
kgdb_local_irq_restore(flags);
return (0);
}
-#if 0
-exit_just_unlock:
-#endif
#endif
/* Release kgdb spinlock */
KGDB_SPIN_UNLOCK(&kgdb_spinlock);
@@ -2106,7 +1355,7 @@
/* In case GDB is started before us, ack any packets (presumably
"$?#xx") sitting there.
- putDebugChar ('+');
+ put_debug_char ('+');
initialized = 1;
*/
@@ -2119,27 +1368,7 @@
/* But really, just use the BREAKPOINT macro. We will handle the int stuff
*/
-#ifdef later
-/*
- * possibly we should not go thru the traps.c code at all? Someday.
- */
-void
-do_kgdb_int3(struct pt_regs *regs, long error_code)
-{
- kgdb_handle_exception(3, 5, error_code, regs);
- return;
-}
-#endif
#undef regs
-#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS
-asmlinkage void
-bad_sys_call_exit(int stuff)
-{
- struct pt_regs *regs = (struct pt_regs *) &stuff;
- printk("Sys call %d return with %x preempt_count\n",
- (int) regs->orig_eax, preempt_count());
-}
-#endif
#ifdef CONFIG_STACK_OVERFLOW_TEST
#include <asm/kgdb.h>
asmlinkage void
@@ -2150,8 +1379,7 @@
#else
printk("Kernel stack overflow, looping forever\n");
#endif
- while (1) {
- }
+ while (1) ;
}
#endif
@@ -2420,9 +1648,6 @@
kgdb_and_then = &kgdb_data[++kgdb_and_then_count & INDEX_MASK];
spin_unlock(&ts_spin);
kgdb_local_irq_restore(flags);
-#ifdef CONFIG_PREEMPT
-
-#endif
return;
}
#endif
@@ -2483,7 +1708,6 @@
return parse_hw_addr(str, kgdb_localmac);
}
-
__setup("gdbeth=", kgdb_opt_kgdbeth);
__setup("gdbeth_remoteip=", kgdb_opt_kgdbeth_remoteip);
__setup("gdbeth_listenport=", kgdb_opt_kgdbeth_listenport);
--- tmp/linux/drivers/net/kgdb_eth.c 2004-01-09 19:04:43.000000000 +0100
+++ linux/drivers/net/kgdb_eth.c 2003-12-28 21:00:24.000000000 +0100
@@ -39,12 +39,12 @@
#define GDB_BUF_SIZE 512 /* power of 2, please */
-static char kgdb_buf[GDB_BUF_SIZE] ;
-static int kgdb_buf_in_inx ;
-static atomic_t kgdb_buf_in_cnt ;
-static int kgdb_buf_out_inx ;
+static char kgdb_buf[GDB_BUF_SIZE];
+static int kgdb_buf_in_inx;
+static atomic_t kgdb_buf_in_cnt;
+static int kgdb_buf_out_inx;
-extern void set_debug_traps(void) ; /* GDB routine */
+extern void set_debug_traps(void); /* GDB routine */
extern void breakpoint(void);
unsigned int kgdb_remoteip = 0;
@@ -479,8 +479,7 @@
put_char_on_queue(int chr)
{
eth_queue[outgoing_queue++] = chr;
- if(outgoing_queue == ETH_QUEUE_SIZE)
- {
+ if(outgoing_queue == ETH_QUEUE_SIZE) {
eth_flushDebugChar();
}
}
--- tmp/linux/include/asm-i386/kgdb_local.h 2004-01-09 19:04:44.000000000 +0100
+++ linux/include/asm-i386/kgdb_local.h 2003-12-28 21:21:55.000000000 +0100
@@ -83,7 +83,7 @@
tty: (struct tty_struct *)&state, \
IER: SB_IER, \
MCR: SB_MCR}
-extern void putDebugChar(int);
+extern void put_debug_char(int);
/* RTAI support needs us to really stop/start interrupts */
#define kgdb_sti() __asm__ __volatile__("sti": : :"memory")
@@ -98,5 +98,5 @@
#ifdef CONFIG_SERIAL
extern void shutdown_for_kgdb(struct async_struct *info);
#endif
-#define INIT_KDEBUG putDebugChar("+");
+#define INIT_KDEBUG put_debug_char("+"); /* WTF is this? it expects integer! */
#endif /* __KGDB_LOCAL */
--- tmp/linux/include/linux/dwarf2-lang.h 2004-01-09 19:04:44.000000000 +0100
+++ linux/include/linux/dwarf2-lang.h 2003-12-27 17:12:38.000000000 +0100
@@ -1,132 +0,0 @@
-#ifndef DWARF2_LANG
-#define DWARF2_LANG
-#include <linux/dwarf2.h>
-
-/*
- * 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.
- */
-#define DWARF_preamble() .section .debug_frame,"",@progbits
-/*
- * 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) \
-.section .debug_frame,"",@progbits ; \
-frame/**/_/**/ORD: \
- .long end/**/_/**/ORD-start/**/_/**/ORD; \
-start/**/_/**/ORD: \
- .long DW_CIE_ID; \
- .byte DW_CIE_VERSION; \
- .byte 0 ; \
- .uleb128 code_align; \
- .sleb128 data_align; \
- .byte pc;
-
-/*
- * 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; \
- .uleb128 reg; \
- .uleb128 (offset);
-
-#define CFA_define_offset(reg, offset) \
- .byte (DW_CFA_offset + reg); \
- .uleb128 (offset);
-
-#define CFI_postamble(ORD) \
- .align 4; \
-end/**/_/**/ORD:
-/*
- * 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 first entry after the preamble must be the location in the code
- * that the call frame is being described for.
- */
-#define FDE_preamble(ORD, fde_no, initial_address, length) \
- .long FDE_end/**/_/**/fde_no-FDE_start/**/_/**/fde_no; \
-FDE_start/**/_/**/fde_no: \
- .long frame/**/_/**/ORD; \
- .long initial_address; \
- .long length;
-
-#define FDE_postamble(fde_no) \
- .align 4; \
-FDE_end/**/_/**/fde_no:
-/*
- * 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 address by <bytes>
- */
-
-#define FDE_advance(bytes) \
- .byte DW_CFA_advance_loc4 \
- .long bytes
-
-
-
-/*
- * 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; \
- .uleb128 (offset);
-/*
- * Or suppose you want to use a different reference register...
- */
-#define CFA_define_cfa_register(reg) \
- .byte DW_CFA_def_cfa_register; \
- .uleb128 reg;
-
-#endif
--- tmp/linux/include/linux/dwarf2.h 2004-01-09 19:04:44.000000000 +0100
+++ linux/include/linux/dwarf2.h 2003-12-27 17:12:40.000000000 +0100
@@ -1,738 +0,0 @@
-/* Declarations and definitions of codes relating to the DWARF2 symbolic
- debugging information format.
- Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002
- 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. */
-#ifndef __ASSEMBLY__
-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;
-
-#define ENUM(name) enum name {
-#define IF_NOT_ASM(a) a
-#define COMMA ,
-#else
-#define ENUM(name)
-#define IF_NOT_ASM(a)
-#define COMMA
-
-#endif
-
-/* Tag names and codes. */
-ENUM(dwarf_tag)
-
- DW_TAG_padding = 0x00 COMMA
- DW_TAG_array_type = 0x01 COMMA
- DW_TAG_class_type = 0x02 COMMA
- DW_TAG_entry_point = 0x03 COMMA
- DW_TAG_enumeration_type = 0x04 COMMA
- DW_TAG_formal_parameter = 0x05 COMMA
- DW_TAG_imported_declaration = 0x08 COMMA
- DW_TAG_label = 0x0a COMMA
- DW_TAG_lexical_block = 0x0b COMMA
- DW_TAG_member = 0x0d COMMA
- DW_TAG_pointer_type = 0x0f COMMA
- DW_TAG_reference_type = 0x10 COMMA
- DW_TAG_compile_unit = 0x11 COMMA
- DW_TAG_string_type = 0x12 COMMA
- DW_TAG_structure_type = 0x13 COMMA
- DW_TAG_subroutine_type = 0x15 COMMA
- DW_TAG_typedef = 0x16 COMMA
- DW_TAG_union_type = 0x17 COMMA
- DW_TAG_unspecified_parameters = 0x18 COMMA
- DW_TAG_variant = 0x19 COMMA
- DW_TAG_common_block = 0x1a COMMA
- DW_TAG_common_inclusion = 0x1b COMMA
- DW_TAG_inheritance = 0x1c COMMA
- DW_TAG_inlined_subroutine = 0x1d COMMA
- DW_TAG_module = 0x1e COMMA
- DW_TAG_ptr_to_member_type = 0x1f COMMA
- DW_TAG_set_type = 0x20 COMMA
- DW_TAG_subrange_type = 0x21 COMMA
- DW_TAG_with_stmt = 0x22 COMMA
- DW_TAG_access_declaration = 0x23 COMMA
- DW_TAG_base_type = 0x24 COMMA
- DW_TAG_catch_block = 0x25 COMMA
- DW_TAG_const_type = 0x26 COMMA
- DW_TAG_constant = 0x27 COMMA
- DW_TAG_enumerator = 0x28 COMMA
- DW_TAG_file_type = 0x29 COMMA
- DW_TAG_friend = 0x2a COMMA
- DW_TAG_namelist = 0x2b COMMA
- DW_TAG_namelist_item = 0x2c COMMA
- DW_TAG_packed_type = 0x2d COMMA
- DW_TAG_subprogram = 0x2e COMMA
- DW_TAG_template_type_param = 0x2f COMMA
- DW_TAG_template_value_param = 0x30 COMMA
- DW_TAG_thrown_type = 0x31 COMMA
- DW_TAG_try_block = 0x32 COMMA
- DW_TAG_variant_part = 0x33 COMMA
- DW_TAG_variable = 0x34 COMMA
- DW_TAG_volatile_type = 0x35 COMMA
- /* DWARF 3. */
- DW_TAG_dwarf_procedure = 0x36 COMMA
- DW_TAG_restrict_type = 0x37 COMMA
- DW_TAG_interface_type = 0x38 COMMA
- DW_TAG_namespace = 0x39 COMMA
- DW_TAG_imported_module = 0x3a COMMA
- DW_TAG_unspecified_type = 0x3b COMMA
- DW_TAG_partial_unit = 0x3c COMMA
- DW_TAG_imported_unit = 0x3d COMMA
- /* SGI/MIPS Extensions. */
- DW_TAG_MIPS_loop = 0x4081 COMMA
- /* GNU extensions. */
- DW_TAG_format_label = 0x4101 COMMA /* For FORTRAN 77 and Fortran 90. */
- DW_TAG_function_template = 0x4102 COMMA /* For C++. */
- DW_TAG_class_template = 0x4103 COMMA /* For C++. */
- DW_TAG_GNU_BINCL = 0x4104 COMMA
- DW_TAG_GNU_EINCL = 0x4105 COMMA
- /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */
- DW_TAG_upc_shared_type = 0x8765 COMMA
- DW_TAG_upc_strict_type = 0x8766 COMMA
- DW_TAG_upc_relaxed_type = 0x8767
-IF_NOT_ASM(};)
-
-#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 COMMA
- DW_FORM_block2 = 0x03 COMMA
- DW_FORM_block4 = 0x04 COMMA
- DW_FORM_data2 = 0x05 COMMA
- DW_FORM_data4 = 0x06 COMMA
- DW_FORM_data8 = 0x07 COMMA
- DW_FORM_string = 0x08 COMMA
- DW_FORM_block = 0x09 COMMA
- DW_FORM_block1 = 0x0a COMMA
- DW_FORM_data1 = 0x0b COMMA
- DW_FORM_flag = 0x0c COMMA
- DW_FORM_sdata = 0x0d COMMA
- DW_FORM_strp = 0x0e COMMA
- DW_FORM_udata = 0x0f COMMA
- DW_FORM_ref_addr = 0x10 COMMA
- DW_FORM_ref1 = 0x11 COMMA
- DW_FORM_ref2 = 0x12 COMMA
- DW_FORM_ref4 = 0x13 COMMA
- DW_FORM_ref8 = 0x14 COMMA
- DW_FORM_ref_udata = 0x15 COMMA
- DW_FORM_indirect = 0x16
-IF_NOT_ASM(};)
-
-/* Attribute names and codes. */
-
-ENUM(dwarf_attribute)
-
- DW_AT_sibling = 0x01 COMMA
- DW_AT_location = 0x02 COMMA
- DW_AT_name = 0x03 COMMA
- DW_AT_ordering = 0x09 COMMA
- DW_AT_subscr_data = 0x0a COMMA
- DW_AT_byte_size = 0x0b COMMA
- DW_AT_bit_offset = 0x0c COMMA
- DW_AT_bit_size = 0x0d COMMA
- DW_AT_element_list = 0x0f COMMA
- DW_AT_stmt_list = 0x10 COMMA
- DW_AT_low_pc = 0x11 COMMA
- DW_AT_high_pc = 0x12 COMMA
- DW_AT_language = 0x13 COMMA
- DW_AT_member = 0x14 COMMA
- DW_AT_discr = 0x15 COMMA
- DW_AT_discr_value = 0x16 COMMA
- DW_AT_visibility = 0x17 COMMA
- DW_AT_import = 0x18 COMMA
- DW_AT_string_length = 0x19 COMMA
- DW_AT_common_reference = 0x1a COMMA
- DW_AT_comp_dir = 0x1b COMMA
- DW_AT_const_value = 0x1c COMMA
- DW_AT_containing_type = 0x1d COMMA
- DW_AT_default_value = 0x1e COMMA
- DW_AT_inline = 0x20 COMMA
- DW_AT_is_optional = 0x21 COMMA
- DW_AT_lower_bound = 0x22 COMMA
- DW_AT_producer = 0x25 COMMA
- DW_AT_prototyped = 0x27 COMMA
- DW_AT_return_addr = 0x2a COMMA
- DW_AT_start_scope = 0x2c COMMA
- DW_AT_stride_size = 0x2e COMMA
- DW_AT_upper_bound = 0x2f COMMA
- DW_AT_abstract_origin = 0x31 COMMA
- DW_AT_accessibility = 0x32 COMMA
- DW_AT_address_class = 0x33 COMMA
- DW_AT_artificial = 0x34 COMMA
- DW_AT_base_types = 0x35 COMMA
- DW_AT_calling_convention = 0x36 COMMA
- DW_AT_count = 0x37 COMMA
- DW_AT_data_member_location = 0x38 COMMA
- DW_AT_decl_column = 0x39 COMMA
- DW_AT_decl_file = 0x3a COMMA
- DW_AT_decl_line = 0x3b COMMA
- DW_AT_declaration = 0x3c COMMA
- DW_AT_discr_list = 0x3d COMMA
- DW_AT_encoding = 0x3e COMMA
- DW_AT_external = 0x3f COMMA
- DW_AT_frame_base = 0x40 COMMA
- DW_AT_friend = 0x41 COMMA
- DW_AT_identifier_case = 0x42 COMMA
- DW_AT_macro_info = 0x43 COMMA
- DW_AT_namelist_items = 0x44 COMMA
- DW_AT_priority = 0x45 COMMA
- DW_AT_segment = 0x46 COMMA
- DW_AT_specification = 0x47 COMMA
- DW_AT_static_link = 0x48 COMMA
- DW_AT_type = 0x49 COMMA
- DW_AT_use_location = 0x4a COMMA
- DW_AT_variable_parameter = 0x4b COMMA
- DW_AT_virtuality = 0x4c COMMA
- DW_AT_vtable_elem_location = 0x4d COMMA
- /* DWARF 3 values. */
- DW_AT_allocated = 0x4e COMMA
- DW_AT_associated = 0x4f COMMA
- DW_AT_data_location = 0x50 COMMA
- DW_AT_stride = 0x51 COMMA
- DW_AT_entry_pc = 0x52 COMMA
- DW_AT_use_UTF8 = 0x53 COMMA
- DW_AT_extension = 0x54 COMMA
- DW_AT_ranges = 0x55 COMMA
- DW_AT_trampoline = 0x56 COMMA
- DW_AT_call_column = 0x57 COMMA
- DW_AT_call_file = 0x58 COMMA
- DW_AT_call_line = 0x59 COMMA
- /* SGI/MIPS extensions. */
- DW_AT_MIPS_fde = 0x2001 COMMA
- DW_AT_MIPS_loop_begin = 0x2002 COMMA
- DW_AT_MIPS_tail_loop_begin = 0x2003 COMMA
- DW_AT_MIPS_epilog_begin = 0x2004 COMMA
- DW_AT_MIPS_loop_unroll_factor = 0x2005 COMMA
- DW_AT_MIPS_software_pipeline_depth = 0x2006 COMMA
- DW_AT_MIPS_linkage_name = 0x2007 COMMA
- DW_AT_MIPS_stride = 0x2008 COMMA
- DW_AT_MIPS_abstract_name = 0x2009 COMMA
- DW_AT_MIPS_clone_origin = 0x200a COMMA
- DW_AT_MIPS_has_inlines = 0x200b COMMA
- /* GNU extensions. */
- DW_AT_sf_names = 0x2101 COMMA
- DW_AT_src_info = 0x2102 COMMA
- DW_AT_mac_info = 0x2103 COMMA
- DW_AT_src_coords = 0x2104 COMMA
- DW_AT_body_begin = 0x2105 COMMA
- DW_AT_body_end = 0x2106 COMMA
- DW_AT_GNU_vector = 0x2107 COMMA
- /* VMS extensions. */
- DW_AT_VMS_rtnbeg_pd_address = 0x2201 COMMA
- /* UPC extension. */
- DW_AT_upc_threads_scaled = 0x3210
-IF_NOT_ASM(};)
-
-#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 COMMA
- DW_OP_deref = 0x06 COMMA
- DW_OP_const1u = 0x08 COMMA
- DW_OP_const1s = 0x09 COMMA
- DW_OP_const2u = 0x0a COMMA
- DW_OP_const2s = 0x0b COMMA
- DW_OP_const4u = 0x0c COMMA
- DW_OP_const4s = 0x0d COMMA
- DW_OP_const8u = 0x0e COMMA
- DW_OP_const8s = 0x0f COMMA
- DW_OP_constu = 0x10 COMMA
- DW_OP_consts = 0x11 COMMA
- DW_OP_dup = 0x12 COMMA
- DW_OP_drop = 0x13 COMMA
- DW_OP_over = 0x14 COMMA
- DW_OP_pick = 0x15 COMMA
- DW_OP_swap = 0x16 COMMA
- DW_OP_rot = 0x17 COMMA
- DW_OP_xderef = 0x18 COMMA
- DW_OP_abs = 0x19 COMMA
- DW_OP_and = 0x1a COMMA
- DW_OP_div = 0x1b COMMA
- DW_OP_minus = 0x1c COMMA
- DW_OP_mod = 0x1d COMMA
- DW_OP_mul = 0x1e COMMA
- DW_OP_neg = 0x1f COMMA
- DW_OP_not = 0x20 COMMA
- DW_OP_or = 0x21 COMMA
- DW_OP_plus = 0x22 COMMA
- DW_OP_plus_uconst = 0x23 COMMA
- DW_OP_shl = 0x24 COMMA
- DW_OP_shr = 0x25 COMMA
- DW_OP_shra = 0x26 COMMA
- DW_OP_xor = 0x27 COMMA
- DW_OP_bra = 0x28 COMMA
- DW_OP_eq = 0x29 COMMA
- DW_OP_ge = 0x2a COMMA
- DW_OP_gt = 0x2b COMMA
- DW_OP_le = 0x2c COMMA
- DW_OP_lt = 0x2d COMMA
- DW_OP_ne = 0x2e COMMA
- DW_OP_skip = 0x2f COMMA
- DW_OP_lit0 = 0x30 COMMA
- DW_OP_lit1 = 0x31 COMMA
- DW_OP_lit2 = 0x32 COMMA
- DW_OP_lit3 = 0x33 COMMA
- DW_OP_lit4 = 0x34 COMMA
- DW_OP_lit5 = 0x35 COMMA
- DW_OP_lit6 = 0x36 COMMA
- DW_OP_lit7 = 0x37 COMMA
- DW_OP_lit8 = 0x38 COMMA
- DW_OP_lit9 = 0x39 COMMA
- DW_OP_lit10 = 0x3a COMMA
- DW_OP_lit11 = 0x3b COMMA
- DW_OP_lit12 = 0x3c COMMA
- DW_OP_lit13 = 0x3d COMMA
- DW_OP_lit14 = 0x3e COMMA
- DW_OP_lit15 = 0x3f COMMA
- DW_OP_lit16 = 0x40 COMMA
- DW_OP_lit17 = 0x41 COMMA
- DW_OP_lit18 = 0x42 COMMA
- DW_OP_lit19 = 0x43 COMMA
- DW_OP_lit20 = 0x44 COMMA
- DW_OP_lit21 = 0x45 COMMA
- DW_OP_lit22 = 0x46 COMMA
- DW_OP_lit23 = 0x47 COMMA
- DW_OP_lit24 = 0x48 COMMA
- DW_OP_lit25 = 0x49 COMMA
- DW_OP_lit26 = 0x4a COMMA
- DW_OP_lit27 = 0x4b COMMA
- DW_OP_lit28 = 0x4c COMMA
- DW_OP_lit29 = 0x4d COMMA
- DW_OP_lit30 = 0x4e COMMA
- DW_OP_lit31 = 0x4f COMMA
- DW_OP_reg0 = 0x50 COMMA
- DW_OP_reg1 = 0x51 COMMA
- DW_OP_reg2 = 0x52 COMMA
- DW_OP_reg3 = 0x53 COMMA
- DW_OP_reg4 = 0x54 COMMA
- DW_OP_reg5 = 0x55 COMMA
- DW_OP_reg6 = 0x56 COMMA
- DW_OP_reg7 = 0x57 COMMA
- DW_OP_reg8 = 0x58 COMMA
- DW_OP_reg9 = 0x59 COMMA
- DW_OP_reg10 = 0x5a COMMA
- DW_OP_reg11 = 0x5b COMMA
- DW_OP_reg12 = 0x5c COMMA
- DW_OP_reg13 = 0x5d COMMA
- DW_OP_reg14 = 0x5e COMMA
- DW_OP_reg15 = 0x5f COMMA
- DW_OP_reg16 = 0x60 COMMA
- DW_OP_reg17 = 0x61 COMMA
- DW_OP_reg18 = 0x62 COMMA
- DW_OP_reg19 = 0x63 COMMA
- DW_OP_reg20 = 0x64 COMMA
- DW_OP_reg21 = 0x65 COMMA
- DW_OP_reg22 = 0x66 COMMA
- DW_OP_reg23 = 0x67 COMMA
- DW_OP_reg24 = 0x68 COMMA
- DW_OP_reg25 = 0x69 COMMA
- DW_OP_reg26 = 0x6a COMMA
- DW_OP_reg27 = 0x6b COMMA
- DW_OP_reg28 = 0x6c COMMA
- DW_OP_reg29 = 0x6d COMMA
- DW_OP_reg30 = 0x6e COMMA
- DW_OP_reg31 = 0x6f COMMA
- DW_OP_breg0 = 0x70 COMMA
- DW_OP_breg1 = 0x71 COMMA
- DW_OP_breg2 = 0x72 COMMA
- DW_OP_breg3 = 0x73 COMMA
- DW_OP_breg4 = 0x74 COMMA
- DW_OP_breg5 = 0x75 COMMA
- DW_OP_breg6 = 0x76 COMMA
- DW_OP_breg7 = 0x77 COMMA
- DW_OP_breg8 = 0x78 COMMA
- DW_OP_breg9 = 0x79 COMMA
- DW_OP_breg10 = 0x7a COMMA
- DW_OP_breg11 = 0x7b COMMA
- DW_OP_breg12 = 0x7c COMMA
- DW_OP_breg13 = 0x7d COMMA
- DW_OP_breg14 = 0x7e COMMA
- DW_OP_breg15 = 0x7f COMMA
- DW_OP_breg16 = 0x80 COMMA
- DW_OP_breg17 = 0x81 COMMA
- DW_OP_breg18 = 0x82 COMMA
- DW_OP_breg19 = 0x83 COMMA
- DW_OP_breg20 = 0x84 COMMA
- DW_OP_breg21 = 0x85 COMMA
- DW_OP_breg22 = 0x86 COMMA
- DW_OP_breg23 = 0x87 COMMA
- DW_OP_breg24 = 0x88 COMMA
- DW_OP_breg25 = 0x89 COMMA
- DW_OP_breg26 = 0x8a COMMA
- DW_OP_breg27 = 0x8b COMMA
- DW_OP_breg28 = 0x8c COMMA
- DW_OP_breg29 = 0x8d COMMA
- DW_OP_breg30 = 0x8e COMMA
- DW_OP_breg31 = 0x8f COMMA
- DW_OP_regx = 0x90 COMMA
- DW_OP_fbreg = 0x91 COMMA
- DW_OP_bregx = 0x92 COMMA
- DW_OP_piece = 0x93 COMMA
- DW_OP_deref_size = 0x94 COMMA
- DW_OP_xderef_size = 0x95 COMMA
- DW_OP_nop = 0x96 COMMA
- /* DWARF 3 extensions. */
- DW_OP_push_object_address = 0x97 COMMA
- DW_OP_call2 = 0x98 COMMA
- DW_OP_call4 = 0x99 COMMA
- DW_OP_call_ref = 0x9a COMMA
- /* GNU extensions. */
- DW_OP_GNU_push_tls_address = 0xe0
-IF_NOT_ASM(};)
-
-#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 COMMA
- DW_ATE_address = 0x1 COMMA
- DW_ATE_boolean = 0x2 COMMA
- DW_ATE_complex_float = 0x3 COMMA
- DW_ATE_float = 0x4 COMMA
- DW_ATE_signed = 0x5 COMMA
- DW_ATE_signed_char = 0x6 COMMA
- DW_ATE_unsigned = 0x7 COMMA
- DW_ATE_unsigned_char = 0x8 COMMA
- /* DWARF 3. */
- DW_ATE_imaginary_float = 0x9
-IF_NOT_ASM(};)
-
-#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 COMMA
- DW_ORD_col_major = 1
-IF_NOT_ASM(};)
-
-/* Access attribute. */
-ENUM(dwarf_access_attribute)
-
- DW_ACCESS_public = 1 COMMA
- DW_ACCESS_protected = 2 COMMA
- DW_ACCESS_private = 3
-IF_NOT_ASM(};)
-
-/* Visibility. */
-ENUM(dwarf_visibility_attribute)
-
- DW_VIS_local = 1 COMMA
- DW_VIS_exported = 2 COMMA
- DW_VIS_qualified = 3
-IF_NOT_ASM(};)
-
-/* Virtuality. */
-ENUM(dwarf_virtuality_attribute)
-
- DW_VIRTUALITY_none = 0 COMMA
- DW_VIRTUALITY_virtual = 1 COMMA
- DW_VIRTUALITY_pure_virtual = 2
-IF_NOT_ASM(};)
-
-/* Case sensitivity. */
-ENUM(dwarf_id_case)
-
- DW_ID_case_sensitive = 0 COMMA
- DW_ID_up_case = 1 COMMA
- DW_ID_down_case = 2 COMMA
- DW_ID_case_insensitive = 3
-IF_NOT_ASM(};)
-
-/* Calling convention. */
-ENUM(dwarf_calling_convention)
-
- DW_CC_normal = 0x1 COMMA
- DW_CC_program = 0x2 COMMA
- DW_CC_nocall = 0x3
-IF_NOT_ASM(};)
-
-#define DW_CC_lo_user 0x40
-#define DW_CC_hi_user 0xff
-
-/* Inline attribute. */
-ENUM(dwarf_inline_attribute)
-
- DW_INL_not_inlined = 0 COMMA
- DW_INL_inlined = 1 COMMA
- DW_INL_declared_not_inlined = 2 COMMA
- DW_INL_declared_inlined = 3
-IF_NOT_ASM(};)
-
-/* Discriminant lists. */
-ENUM(dwarf_discrim_list)
-
- DW_DSC_label = 0 COMMA
- DW_DSC_range = 1
-IF_NOT_ASM(};)
-
-/* Line number opcodes. */
-ENUM(dwarf_line_number_ops)
-
- DW_LNS_extended_op = 0 COMMA
- DW_LNS_copy = 1 COMMA
- DW_LNS_advance_pc = 2 COMMA
- DW_LNS_advance_line = 3 COMMA
- DW_LNS_set_file = 4 COMMA
- DW_LNS_set_column = 5 COMMA
- DW_LNS_negate_stmt = 6 COMMA
- DW_LNS_set_basic_block = 7 COMMA
- DW_LNS_const_add_pc = 8 COMMA
- DW_LNS_fixed_advance_pc = 9 COMMA
- /* DWARF 3. */
- DW_LNS_set_prologue_end = 10 COMMA
- DW_LNS_set_epilogue_begin = 11 COMMA
- DW_LNS_set_isa = 12
-IF_NOT_ASM(};)
-
-/* Line number extended opcodes. */
-ENUM(dwarf_line_number_x_ops)
-
- DW_LNE_end_sequence = 1 COMMA
- DW_LNE_set_address = 2 COMMA
- DW_LNE_define_file = 3
-IF_NOT_ASM(};)
-
-/* Call frame information. */
-ENUM(dwarf_call_frame_info)
-
- DW_CFA_advance_loc = 0x40 COMMA
- DW_CFA_offset = 0x80 COMMA
- DW_CFA_restore = 0xc0 COMMA
- DW_CFA_nop = 0x00 COMMA
- DW_CFA_set_loc = 0x01 COMMA
- DW_CFA_advance_loc1 = 0x02 COMMA
- DW_CFA_advance_loc2 = 0x03 COMMA
- DW_CFA_advance_loc4 = 0x04 COMMA
- DW_CFA_offset_extended = 0x05 COMMA
- DW_CFA_restore_extended = 0x06 COMMA
- DW_CFA_undefined = 0x07 COMMA
- DW_CFA_same_value = 0x08 COMMA
- DW_CFA_register = 0x09 COMMA
- DW_CFA_remember_state = 0x0a COMMA
- DW_CFA_restore_state = 0x0b COMMA
- DW_CFA_def_cfa = 0x0c COMMA
- DW_CFA_def_cfa_register = 0x0d COMMA
- DW_CFA_def_cfa_offset = 0x0e COMMA
-
- /* DWARF 3. */
- DW_CFA_def_cfa_expression = 0x0f COMMA
- DW_CFA_expression = 0x10 COMMA
- DW_CFA_offset_extended_sf = 0x11 COMMA
- DW_CFA_def_cfa_sf = 0x12 COMMA
- DW_CFA_def_cfa_offset_sf = 0x13 COMMA
-
- /* SGI/MIPS specific. */
- DW_CFA_MIPS_advance_loc8 = 0x1d COMMA
-
- /* GNU extensions. */
- DW_CFA_GNU_window_save = 0x2d COMMA
- DW_CFA_GNU_args_size = 0x2e COMMA
- DW_CFA_GNU_negative_offset_extended = 0x2f
-IF_NOT_ASM(};)
-
-#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 COMMA
- DW_LANG_C = 0x0002 COMMA
- DW_LANG_Ada83 = 0x0003 COMMA
- DW_LANG_C_plus_plus = 0x0004 COMMA
- DW_LANG_Cobol74 = 0x0005 COMMA
- DW_LANG_Cobol85 = 0x0006 COMMA
- DW_LANG_Fortran77 = 0x0007 COMMA
- DW_LANG_Fortran90 = 0x0008 COMMA
- DW_LANG_Pascal83 = 0x0009 COMMA
- DW_LANG_Modula2 = 0x000a COMMA
- DW_LANG_Java = 0x000b COMMA
- /* DWARF 3. */
- DW_LANG_C99 = 0x000c COMMA
- DW_LANG_Ada95 = 0x000d COMMA
- DW_LANG_Fortran95 = 0x000e COMMA
- /* MIPS. */
- DW_LANG_Mips_Assembler = 0x8001 COMMA
- /* UPC. */
- DW_LANG_Upc = 0x8765
-IF_NOT_ASM(};)
-
-#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 COMMA
- DW_MACINFO_undef = 2 COMMA
- DW_MACINFO_start_file = 3 COMMA
- DW_MACINFO_end_file = 4 COMMA
- DW_MACINFO_vendor_ext = 255
-IF_NOT_ASM(};)
-
-/* @@@ 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 */
--- tmp/linux/kernel/kgdb.c 2003-12-28 21:06:03.000000000 +0100
+++ linux/kernel/kgdb.c 2003-12-28 21:40:19.000000000 +0100
@@ -0,0 +1,750 @@
+/*
+ * Kernel gdb stub, arch-independend part
+ *
+ * Copyright (c) 2000 VERITAS Software Corporation.
+ * Copyright (c) 2003 Pavel Machek <[email protected]>
+ *
+ * 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.
+ *
+ */
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * Updated by: David Grothe <[email protected]>
+ * Updated by: Robert Walsh <[email protected]>
+ * Updated by: wangdi <[email protected]>
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * Modified for 386 by Jim Kingdon, Cygnus Support.
+ * Compatibility with 2.1.xx kernel by David Grothe <[email protected]>
+ *
+ * Changes to allow auto initilization. All that is needed is that it
+ * be linked with the kernel and a break point (int 3) be executed.
+ * The header file <asm/kgdb.h> defines BREAKPOINT to allow one to do
+ * this. It should also be possible, once the interrupt system is up, to
+ * call putDebugChar("+"). Once this is done, the remote debugger should
+ * get our attention by sending a ^C in a packet. George Anzinger
+ * <[email protected]>
+ * Integrated into 2.2.5 kernel by Tigran Aivazian <[email protected]>
+ * Added thread support, support for multiple processors,
+ * support for ia-32(x86) hardware debugging.
+ * Amit S. Kale ( [email protected] )
+ *
+ * Modified to support debugging over ethernet by Robert Walsh
+ * <[email protected]> and wangdi <[email protected]>, based on
+ * code by San Mehat.
+ *
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing an int 3.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+/*
+ * external low-level support routines
+ */
+typedef void (*Function) (void); /* pointer to a function */
+
+/* Thread reference */
+typedef unsigned char threadref[8];
+
+extern int tty_putDebugChar(int); /* write a single character */
+extern int tty_getDebugChar(void); /* read and return a single char */
+extern void tty_flushDebugChar(void); /* flush pending characters */
+extern int eth_putDebugChar(int); /* write a single character */
+extern int eth_getDebugChar(void); /* read and return a single char */
+extern void eth_flushDebugChar(void); /* flush pending characters */
+extern void kgdb_eth_set_trapmode(int);
+extern void kgdb_eth_reply_arp(void); /* send arp request */
+extern volatile int kgdb_eth_is_initializing;
+
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+/* Longer buffer is needed to list all threads */
+#define BUFMAX 400
+
+char *kgdb_version = KGDB_VERSION;
+
+/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
+int debug_regs = 0; /* set to non-zero to print registers */
+
+/* filled in by an external module */
+char *gdb_module_offsets;
+
+static const char hexchars[] = "0123456789abcdef";
+
+
+/*************************** ASSEMBLY CODE MACROS *************************/
+/*
+ * Put the error code here just in case the user cares.
+ * Likewise, the vector number here (since GDB only gets the signal
+ * number through the usual means, and that's not very specific).
+ * The called_from is the return address so he can tell how we entered kgdb.
+ * This will allow him to seperate out the various possible entries.
+ */
+#define REMOTE_DEBUG 0 /* set != to turn on printing (also available in info) */
+
+#define PID_MAX PID_MAX_DEFAULT
+
+#ifdef CONFIG_SMP
+void smp_send_nmi_allbutself(void);
+#define IF_SMP(x) x
+#undef MAX_NO_CPUS
+#ifndef CONFIG_NO_KGDB_CPUS
+#define CONFIG_NO_KGDB_CPUS 2
+#endif
+#if CONFIG_NO_KGDB_CPUS > NR_CPUS
+#define MAX_NO_CPUS NR_CPUS
+#else
+#define MAX_NO_CPUS CONFIG_NO_KGDB_CPUS
+#endif
+#define hold_init hold_on_sstep: 1,
+#define MAX_CPU_MASK (unsigned long)((1LL << MAX_NO_CPUS) - 1LL)
+#define NUM_CPUS num_online_cpus()
+#else
+#define IF_SMP(x)
+#define hold_init
+#undef MAX_NO_CPUS
+#define MAX_NO_CPUS 1
+#define NUM_CPUS 1
+#endif
+#define NOCPU (struct task_struct *)0xbad1fbad
+
+struct kgdb_info {
+ int used_malloc;
+ void *called_from;
+ long long entry_tsc;
+ int errcode;
+ int vector;
+ int print_debug_info;
+#ifdef CONFIG_SMP
+ int hold_on_sstep;
+ struct {
+ volatile struct task_struct *task;
+ int pid;
+ int hold;
+ struct pt_regs *regs;
+ } cpus_waiting[MAX_NO_CPUS];
+#endif
+} kgdb_info = { hold_init print_debug_info:REMOTE_DEBUG, vector:-1 };
+
+/*
+ * This is little area we set aside to contain the stack we
+ * need to build to allow gdb to call functions. We use one
+ * per cpu to avoid locking issues. We will do all this work
+ * with interrupts off so that should take care of the protection
+ * issues.
+ */
+#define LOOKASIDE_SIZE 200 /* should be more than enough */
+#define MALLOC_MAX 200 /* Max malloc size */
+struct {
+ unsigned int esp;
+ int array[LOOKASIDE_SIZE];
+} fn_call_lookaside[MAX_NO_CPUS];
+
+static int trap_cpu;
+
+#define END_OF_LOOKASIDE &fn_call_lookaside[trap_cpu].array[LOOKASIDE_SIZE]
+
+
+#define MALLOC_ROUND 8-1
+
+static char malloc_array[MALLOC_MAX];
+IF_SMP(static void to_gdb(const char *mess));
+
+/*
+ * Ouch. Apparently, gdb sometimes want to do malloc. It is not used
+ * by the kernel, but do not kill it.
+ */
+void *
+malloc(int size)
+{
+ if (size <= (MALLOC_MAX - kgdb_info.used_malloc)) {
+ int old_used = kgdb_info.used_malloc;
+ kgdb_info.used_malloc += ((size + MALLOC_ROUND) & (~MALLOC_ROUND));
+ return &malloc_array[old_used];
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ * I/O dispatch functions...
+ * Based upon kgdb_eth, either call the ethernet
+ * handler or the serial one..
+ */
+void
+put_debug_char(int c)
+{
+ if (kgdb_eth == -1) {
+ tty_putDebugChar(c);
+ } else {
+ eth_putDebugChar(c);
+ }
+}
+
+static int
+get_debug_char(void)
+{
+ if (kgdb_eth == -1) {
+ return tty_getDebugChar();
+ } else {
+ return eth_getDebugChar();
+ }
+}
+
+static void
+flush_debug_char(void)
+{
+ if (kgdb_eth == -1) {
+ tty_flushDebugChar();
+ } else {
+ eth_flushDebugChar();
+ }
+}
+
+#define waiting_cpus kgdb_info.cpus_waiting
+#define remote_debug kgdb_info.print_debug_info
+#define hold_cpu(cpu) kgdb_info.cpus_waiting[cpu].hold
+/* gdb locks */
+
+#ifdef CONFIG_SMP
+static int in_kgdb_called;
+static spinlock_t waitlocks[MAX_NO_CPUS] =
+ {[0 ... MAX_NO_CPUS - 1] = SPIN_LOCK_UNLOCKED };
+/*
+ * The following array has the thread pointer of each of the "other"
+ * cpus. We make it global so it can be seen by gdb.
+ */
+volatile int in_kgdb_entry_log[MAX_NO_CPUS];
+volatile struct pt_regs *in_kgdb_here_log[MAX_NO_CPUS];
+/*
+static spinlock_t continuelocks[MAX_NO_CPUS];
+*/
+spinlock_t kgdb_spinlock = SPIN_LOCK_UNLOCKED;
+/* waiters on our spinlock plus us */
+static atomic_t spinlock_waiters = ATOMIC_INIT(1);
+static int spinlock_count = 0;
+static int spinlock_cpu = 0;
+/*
+ * Note we use nested spin locks to account for the case where a break
+ * point is encountered when calling a function by user direction from
+ * kgdb. Also there is the memory exception recursion to account for.
+ * Well, yes, but this lets other cpus thru too. Lets add a
+ * cpu id to the lock.
+ */
+#define KGDB_SPIN_LOCK(x) if (spinlock_count == 0 || \
+ spinlock_cpu != smp_processor_id()) {\
+ atomic_inc(&spinlock_waiters); \
+ while (! spin_trylock(x)) {\
+ in_kgdb(®s);\
+ }\
+ atomic_dec(&spinlock_waiters); \
+ spinlock_count = 1; \
+ spinlock_cpu = smp_processor_id(); \
+ }else{ \
+ spinlock_count++; \
+ }
+#define KGDB_SPIN_UNLOCK(x) if (--spinlock_count == 0) spin_unlock(x)
+#else
+unsigned kgdb_spinlock = 0;
+#define KGDB_SPIN_LOCK(x) --*x
+#define KGDB_SPIN_UNLOCK(x) ++*x
+#endif
+
+static int
+hex(char ch)
+{
+ if ((ch >= 'a') && (ch <= 'f'))
+ return (ch - 'a' + 10);
+ if ((ch >= '0') && (ch <= '9'))
+ return (ch - '0');
+ if ((ch >= 'A') && (ch <= 'F'))
+ return (ch - 'A' + 10);
+ return (-1);
+}
+
+/* scan for the sequence $<data>#<checksum> */
+static void
+getpacket(char *buffer)
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ char ch;
+
+ do {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = (get_debug_char() & 0x7f)) != '$') ;
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX) {
+ ch = get_debug_char() & 0x7f;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#') {
+ xmitcsum = hex(get_debug_char() & 0x7f) << 4;
+ xmitcsum += hex(get_debug_char() & 0x7f);
+ if ((remote_debug) && (checksum != xmitcsum)) {
+ printk
+ ("bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
+ checksum, xmitcsum, buffer);
+ }
+
+ if (checksum != xmitcsum)
+ put_debug_char('-'); /* failed checksum */
+ else {
+ put_debug_char('+'); /* successful transfer */
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':') {
+ put_debug_char(buffer[0]);
+ put_debug_char(buffer[1]);
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i = 3; i <= count; i++)
+ buffer[i - 3] = buffer[i];
+ }
+ }
+ }
+ } while (checksum != xmitcsum);
+
+ if (remote_debug)
+ printk("R:%s\n", buffer);
+ flush_debug_char();
+}
+
+/* send the packet in buffer. */
+
+static void
+putpacket(char *buffer)
+{
+ unsigned char checksum;
+ int count;
+ char ch;
+
+ /* $<packet info>#<checksum>. */
+
+ if (kgdb_eth == -1) {
+ do {
+ if (remote_debug)
+ printk("T:%s\n", buffer);
+ put_debug_char('$');
+ checksum = 0;
+ count = 0;
+
+ while ((ch = buffer[count])) {
+ put_debug_char(ch);
+ checksum += ch;
+ count += 1;
+ }
+
+ put_debug_char('#');
+ put_debug_char(hexchars[checksum >> 4]);
+ put_debug_char(hexchars[checksum % 16]);
+ flush_debug_char();
+
+ } while ((get_debug_char() & 0x7f) != '+');
+ } else {
+ /*
+ * For udp, we can not transfer too much bytes once.
+ * We only transfer MAX_SEND_COUNT size bytes each time
+ */
+
+#define MAX_SEND_COUNT 30
+
+ int send_count = 0, i = 0;
+ char send_buf[MAX_SEND_COUNT];
+
+ do {
+ if (remote_debug)
+ printk("T:%s\n", buffer);
+ put_debug_char('$');
+ checksum = 0;
+ count = 0;
+ send_count = 0;
+ while ((ch = buffer[count])) {
+ if (send_count >= MAX_SEND_COUNT) {
+ for(i = 0; i < MAX_SEND_COUNT; i++) {
+ put_debug_char(send_buf[i]);
+ }
+ flush_debug_char();
+ send_count = 0;
+ } else {
+ send_buf[send_count] = ch;
+ checksum += ch;
+ count ++;
+ send_count++;
+ }
+ }
+ for(i = 0; i < send_count; i++)
+ put_debug_char(send_buf[i]);
+ put_debug_char('#');
+ put_debug_char(hexchars[checksum >> 4]);
+ put_debug_char(hexchars[checksum % 16]);
+ flush_debug_char();
+ } while ((get_debug_char() & 0x7f) != '+');
+ }
+}
+
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+static short error;
+
+static void
+debug_error(char *format, char *parm)
+{
+ if (remote_debug)
+ printk(format, parm);
+}
+
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched ((unsigned long) scheduling_functions_start_here)
+#define last_sched ((unsigned long) scheduling_functions_end_here)
+
+/* Indicate to caller of mem2hex or hex2mem that there has been an
+ error. */
+static volatile int mem_err = 0;
+static volatile int mem_err_expected = 0;
+static volatile int mem_err_cnt = 0;
+static int garbage_loc = -1;
+
+/* FIXME: WTF? */
+static int
+get_char(char *addr)
+{
+ return *addr;
+}
+
+static void set_char(char *addr, int val, int may_fault);
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+/* If MAY_FAULT is non-zero, then we should set mem_err in response to
+ a fault; if zero treat a fault like any other fault in the stub. */
+static char *
+mem2hex(char *mem, char *buf, int count, int may_fault)
+{
+ int i;
+ unsigned char ch;
+
+ if (may_fault) {
+ mem_err_expected = 1;
+ mem_err = 0;
+ }
+ for (i = 0; i < count; i++) {
+ /* printk("%lx = ", mem) ; */
+
+ ch = get_char(mem++);
+
+ /* printk("%02x\n", ch & 0xFF) ; */
+ if (may_fault && mem_err) {
+ if (remote_debug)
+ printk("Mem fault fetching from addr %lx\n",
+ (long) (mem - 1));
+ *buf = 0; /* truncate buffer */
+ return (buf);
+ }
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch % 16];
+ }
+ *buf = 0;
+ if (may_fault)
+ mem_err_expected = 0;
+ return (buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+/* NOTE: We use the may fault flag to also indicate if the write is to
+ * the registers (0) or "other" memory (!=0)
+ */
+static char *
+hex2mem(char *buf, char *mem, int count, int may_fault)
+{
+ int i;
+ unsigned char ch;
+
+ if (may_fault) {
+ mem_err_expected = 1;
+ mem_err = 0;
+ }
+ for (i = 0; i < count; i++) {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ set_char(mem++, ch, may_fault);
+
+ if (may_fault && mem_err) {
+ if (remote_debug)
+ printk("Mem fault storing to addr %lx\n",
+ (long) (mem - 1));
+ return (mem);
+ }
+ }
+ if (may_fault)
+ mem_err_expected = 0;
+ return (mem);
+}
+
+/*
+ * While we find nice hex chars, build an int
+ * return number of chars processed
+ */
+int
+hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr) {
+ hexValue = hex(**ptr);
+ if (hexValue >= 0) {
+ *intValue = (*intValue << 4) | hexValue;
+ numChars++;
+ } else
+ break;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+#define stubhex(h) hex(h)
+#ifdef old_thread_list
+
+static int
+stub_unpack_int(char *buff, int fieldlength)
+{
+ int nibble;
+ int retval = 0;
+
+ while (fieldlength) {
+ nibble = stubhex(*buff++);
+ retval |= nibble;
+ fieldlength--;
+ if (fieldlength)
+ retval = retval << 4;
+ }
+ return retval;
+}
+#endif
+static char *
+pack_hex_byte(char *pkt, int byte)
+{
+ *pkt++ = hexchars[(byte >> 4) & 0xf];
+ *pkt++ = hexchars[(byte & 0xf)];
+ return pkt;
+}
+
+#define BUF_THREAD_ID_SIZE 16
+
+static char *
+pack_threadid(char *pkt, threadref * id)
+{
+ char *limit;
+ unsigned char *altid;
+
+ altid = (unsigned char *) id;
+ limit = pkt + BUF_THREAD_ID_SIZE;
+ while (pkt < limit)
+ pkt = pack_hex_byte(pkt, *altid++);
+ return pkt;
+}
+
+#ifdef old_thread_list
+static char *
+unpack_byte(char *buf, int *value)
+{
+ *value = stub_unpack_int(buf, 2);
+ return buf + 2;
+}
+
+static char *
+unpack_threadid(char *inbuf, threadref * id)
+{
+ char *altref;
+ char *limit = inbuf + BUF_THREAD_ID_SIZE;
+ int x, y;
+
+ altref = (char *) id;
+
+ while (inbuf < limit) {
+ x = stubhex(*inbuf++);
+ y = stubhex(*inbuf++);
+ *altref++ = (x << 4) | y;
+ }
+ return inbuf;
+}
+#endif
+
+static void
+int_to_threadref(threadref * id, int value)
+{
+ unsigned char *scan;
+
+ scan = (unsigned char *) id;
+ {
+ int i = 4;
+ while (i--)
+ *scan++ = 0;
+ }
+ *scan++ = (value >> 24) & 0xff;
+ *scan++ = (value >> 16) & 0xff;
+ *scan++ = (value >> 8) & 0xff;
+ *scan++ = (value & 0xff);
+}
+
+static int
+int_to_hex_v(unsigned char * id, int value)
+{
+ unsigned char *start = id;
+ int shift;
+ int ch;
+
+ for (shift = 28; shift >= 0; shift -= 4) {
+ if ((ch = (value >> shift) & 0xf) || (id != start)) {
+ *id = hexchars[ch];
+ id++;
+ }
+ }
+ if (id == start)
+ *id++ = '0';
+ return id - start;
+}
+
+
+#ifdef old_thread_list
+static int
+threadref_to_int(threadref * ref)
+{
+ int i, value = 0;
+ unsigned char *scan;
+
+ scan = (char *) ref;
+ scan += 4;
+ i = 4;
+ while (i-- > 0)
+ value = (value << 8) | ((*scan++) & 0xff);
+ return value;
+}
+#endif
+
+/* FIXME: WTF?! */
+static int
+cmp_str(char *s1, char *s2, int count)
+{
+ while (count--) {
+ if (*s1++ != *s2++)
+ return 0;
+ }
+ return 1;
+}
+
+extern struct task_struct *kgdb_get_idle(int cpu);
+#define idle_task(cpu) kgdb_get_idle(cpu)
+
+extern int kgdb_pid_init_done;
+
+struct task_struct *
+getthread(int pid)
+{
+ struct task_struct *thread;
+ if (pid >= PID_MAX && pid <= (PID_MAX + MAX_NO_CPUS)) {
+
+ return idle_task(pid - PID_MAX);
+ } else {
+ /*
+ * find_task_by_pid is relatively safe all the time
+ * Other pid functions require lock downs which imply
+ * that we may be interrupting them (as we get here
+ * in the middle of most any lock down).
+ * Still we don't want to call until the table exists!
+ */
+ if (kgdb_pid_init_done) {
+ thread = find_task_by_pid(pid);
+ if (thread) {
+ return thread;
+ }
+ }
+ }
+ return NULL;
+}
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
Pavel Machek <[email protected]> wrote:
>
> No real code changes, but cleanups all over the place. What about
> applying?
>
> Ouch and arch-dependend code is moved to kernel/kgdb.c. I'll probably
> do x86-64 version so that is rather important.
Could you please work this with the kgdb developers?
Jim Houston <[email protected]>
george anzinger <[email protected]>
"Amit S. Kale" <[email protected]>
Because merging this might stomp all over work which they have in progress.
(But thanks: kgdb does need a cleanup)
Pavel Machek wrote:
> Hi!
>
> No real code changes, but cleanups all over the place. What about
> applying?
>
> Ouch and arch-dependend code is moved to kernel/kgdb.c. I'll probably
> do x86-64 version so that is rather important.
>
> Pavel
A few comments:
I like the code seperation. Does it follow what Amit is doing? It would be
nice if Amit's version and this one could come together around this.
I don't think we want to merge the eth and regular kgdb just yet. I would,
however, like to keep eth completly out of the stub. Possibly a new module
which just takes care of steering the I/O to the correct place.
I think we might want to try the bad sys call one more time. If it triggers, a
kernel fix is in order. I don't see the point of removing it. After all, the
disable/enable on preempt really should be paired such that we never leave the
kernel with a preempt count.
I have new dwarft stuff. I actually have debug records that allow bt through
interrupt code. Working on the spin lock loops. It is fine to drop these at
this point as the new ones will replace them anyway.
--
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
On Fri, Jan 09, 2004 at 01:54:12PM -0800, George Anzinger wrote:
> Pavel Machek wrote:
> >Hi!
> >
> >No real code changes, but cleanups all over the place. What about
> >applying?
> >
> >Ouch and arch-dependend code is moved to kernel/kgdb.c. I'll probably
> >do x86-64 version so that is rather important.
> >
> > Pavel
> A few comments:
>
> I like the code seperation. Does it follow what Amit is doing? It would
> be nice if Amit's version and this one could come together around this.
>
> I don't think we want to merge the eth and regular kgdb just yet. I would,
> however, like to keep eth completly out of the stub. Possibly a new module
> which just takes care of steering the I/O to the correct place.
I've sent Amit the start of an plug interface for abstracting the
communication layer. Should be relatively painless and allow for
starting sessions on the interface of your choice.
--
Matt Mackall : http://www.selenic.com : Linux development and consulting
Matt Mackall wrote:
> On Fri, Jan 09, 2004 at 01:54:12PM -0800, George Anzinger wrote:
>
>>Pavel Machek wrote:
>>
>>>Hi!
>>>
>>>No real code changes, but cleanups all over the place. What about
>>>applying?
>>>
>>>Ouch and arch-dependend code is moved to kernel/kgdb.c. I'll probably
>>>do x86-64 version so that is rather important.
>>>
>>> Pavel
>>
>>A few comments:
>>
>>I like the code seperation. Does it follow what Amit is doing? It would
>>be nice if Amit's version and this one could come together around this.
>>
>>I don't think we want to merge the eth and regular kgdb just yet. I would,
>>however, like to keep eth completly out of the stub. Possibly a new module
>>which just takes care of steering the I/O to the correct place.
>
>
> I've sent Amit the start of an plug interface for abstracting the
> communication layer. Should be relatively painless and allow for
> starting sessions on the interface of your choice.
>
May I 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
Hi!
> >No real code changes, but cleanups all over the place. What about
> >applying?
> >
> >Ouch and arch-dependend code is moved to kernel/kgdb.c. I'll probably
> >do x86-64 version so that is rather important.
> >
> > Pavel
> A few comments:
>
> I like the code seperation. Does it follow what Amit is doing? It would
> be nice if Amit's version and this one could come together around
> >this.
No, it does not follow Amit's work.
...and that's a problem because Amit's work looks way better than
this. I guess I need to start again, relative to Amit's patches this
time.
Pavel
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
On Sat, Jan 10, 2004 at 12:12:06AM -0800, George Anzinger wrote:
> Matt Mackall wrote:
> >On Fri, Jan 09, 2004 at 01:54:12PM -0800, George Anzinger wrote:
> >
> >>Pavel Machek wrote:
> >>
> >>>Hi!
> >>>
> >>>No real code changes, but cleanups all over the place. What about
> >>>applying?
> >>>
> >>>Ouch and arch-dependend code is moved to kernel/kgdb.c. I'll probably
> >>>do x86-64 version so that is rather important.
> >>>
> >>> Pavel
> >>
> >>A few comments:
> >>
> >>I like the code seperation. Does it follow what Amit is doing? It would
> >>be nice if Amit's version and this one could come together around this.
> >>
> >>I don't think we want to merge the eth and regular kgdb just yet. I
> >>would, however, like to keep eth completly out of the stub. Possibly a
> >>new module which just takes care of steering the I/O to the correct place.
> >
> >
> >I've sent Amit the start of an plug interface for abstracting the
> >communication layer. Should be relatively painless and allow for
> >starting sessions on the interface of your choice.
> >
> May I see?
Here's the interface plus the eth side of it:
tiny-mpm/arch/i386/kernel/kgdb_stub.c | 59 +++++++++-------------------------
tiny-mpm/drivers/net/kgdb_eth.c | 26 +++++++++-----
tiny-mpm/include/asm-i386/kgdb.h | 14 +++++---
3 files changed, 44 insertions(+), 55 deletions(-)
diff -puN include/asm-i386/kgdb.h~kgdb-plug include/asm-i386/kgdb.h
--- tiny/include/asm-i386/kgdb.h~kgdb-plug 2003-12-27 12:18:47.000000000 -0600
+++ tiny-mpm/include/asm-i386/kgdb.h 2003-12-27 13:19:16.000000000 -0600
@@ -19,13 +19,19 @@ extern void breakpoint(void);
#define BREAKPOINT asm(" int $3")
#endif
+struct kgdb_hook {
+ char *sendbuf;
+ int maxsend;
+ int (*getchar)(void);
+ void (*putchar)(int chr);
+ void (*flush)(void);
+ void (*trap)(int enable);
+};
+
+extern void kgdb_attach(struct kgdb_hook *hook);
extern void kgdb_schedule_breakpoint(void);
extern void kgdb_process_breakpoint(void);
-extern int kgdb_tty_hook(void);
-extern int kgdb_eth_hook(void);
-extern int kgdboe;
-
/*
* GDB debug stub (or any debug stub) can point the 'linux_debug_hook'
* pointer to its routine and it will be entered as the first thing
diff -puN arch/i386/kernel/kgdb_stub.c~kgdb-plug arch/i386/kernel/kgdb_stub.c
--- tiny/arch/i386/kernel/kgdb_stub.c~kgdb-plug 2003-12-27 12:18:47.000000000 -0600
+++ tiny-mpm/arch/i386/kernel/kgdb_stub.c 2003-12-27 13:19:19.000000000 -0600
@@ -130,12 +130,7 @@ typedef void (*Function) (void); /* poin
/* Thread reference */
typedef unsigned char threadref[8];
-extern int tty_putDebugChar(int); /* write a single character */
-extern int tty_getDebugChar(void); /* read and return a single char */
-extern void tty_flushDebugChar(void); /* flush pending characters */
-extern int eth_putDebugChar(int); /* write a single character */
-extern int eth_getDebugChar(void); /* read and return a single char */
-extern void eth_flushDebugChar(void); /* flush pending characters */
+struct kgdb_hook *kh = 0;
/************************************************************************/
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
@@ -275,39 +270,25 @@ malloc(int size)
}
}
-/*
- * I/O dispatch functions...
- * Based upon kgdboe, either call the ethernet
- * handler or the serial one..
- */
void
putDebugChar(int c)
{
- if (!kgdboe) {
- tty_putDebugChar(c);
- } else {
- eth_putDebugChar(c);
- }
+ if (kh)
+ kh->putchar(c);
}
int
getDebugChar(void)
{
- if (!kgdboe) {
- return tty_getDebugChar();
- } else {
- return eth_getDebugChar();
- }
+ if (kh)
+ return kh->getchar();
}
void
flushDebugChar(void)
{
- if (!kgdboe) {
- tty_flushDebugChar();
- } else {
- eth_flushDebugChar();
- }
+ if (kh)
+ kh->flush();
}
/*
@@ -490,7 +471,7 @@ putpacket(char *buffer)
/* $<packet info>#<checksum>. */
- if (!kgdboe) {
+ if (kh && !kh->sendbuf) {
do {
if (remote_debug)
printk("T:%s\n", buffer);
@@ -516,10 +497,7 @@ putpacket(char *buffer)
* We only transfer MAX_SEND_COUNT size bytes each time
*/
-#define MAX_SEND_COUNT 30
-
int send_count = 0, i = 0;
- char send_buf[MAX_SEND_COUNT];
do {
if (remote_debug)
@@ -529,21 +507,21 @@ putpacket(char *buffer)
count = 0;
send_count = 0;
while ((ch = buffer[count])) {
- if (send_count >= MAX_SEND_COUNT) {
- for(i = 0; i < MAX_SEND_COUNT; i++) {
- putDebugChar(send_buf[i]);
+ if (send_count >= kh->maxsend) {
+ for(i = 0; i < kh->maxsend; i++) {
+ putDebugChar(kh->sendbuf[i]);
}
flushDebugChar();
send_count = 0;
} else {
- send_buf[send_count] = ch;
+ kh->sendbuf[send_count] = ch;
checksum += ch;
count ++;
send_count++;
}
}
for(i = 0; i < send_count; i++)
- putDebugChar(send_buf[i]);
+ putDebugChar(kh->sendbuf[i]);
putDebugChar('#');
putDebugChar(hexchars[checksum >> 4]);
putDebugChar(hexchars[checksum % 16]);
@@ -1272,12 +1250,9 @@ kgdb_handle_exception(int exceptionVecto
print_regs(®s);
return (0);
}
- /*
- * If we're using eth mode, set the 'mode' in the netdevice.
- */
- if (kgdboe)
- netpoll_set_trap(1);
+ if (kh)
+ kh->trap(1);
kgdb_local_irq_save(flags);
@@ -1727,8 +1702,8 @@ kgdb_handle_exception(int exceptionVecto
}
}
- if (kgdboe)
- netpoll_set_trap(0);
+ if(kh)
+ kh->trap(0);
correct_hw_break();
asm volatile ("movl %0, %%db6\n"::"r" (0));
diff -puN arch/i386/lib/kgdb_serial.c~kgdb-plug arch/i386/lib/kgdb_serial.c
diff -puN drivers/net/kgdb_eth.c~kgdb-plug drivers/net/kgdb_eth.c
--- tiny/drivers/net/kgdb_eth.c~kgdb-plug 2003-12-27 12:18:47.000000000 -0600
+++ tiny-mpm/drivers/net/kgdb_eth.c 2003-12-27 13:19:18.000000000 -0600
@@ -34,8 +34,6 @@ static int in_head, in_tail, out_count;
static atomic_t in_count;
int kgdboe = 0; /* Default to tty mode */
-extern void set_debug_traps(void);
-extern void breakpoint(void);
static void rx_hook(struct netpoll *np, int port, char *msg, int len);
static struct netpoll np = {
@@ -47,7 +45,7 @@ static struct netpoll np = {
.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
};
-int eth_getDebugChar(void)
+static int getchar(void)
{
int chr;
@@ -60,7 +58,7 @@ int eth_getDebugChar(void)
return chr;
}
-void eth_flushDebugChar(void)
+static void flush(void)
{
if(out_count && np.dev) {
netpoll_send_udp(&np, out_buf, out_count);
@@ -68,13 +66,24 @@ void eth_flushDebugChar(void)
}
}
-void eth_putDebugChar(int chr)
+static void putchar(int chr)
{
out_buf[out_count++] = chr;
if(out_count == OUT_BUF_SIZE)
eth_flushDebugChar();
}
+#define MAX_SEND 30
+char sendbuf[MAX_SEND];
+static struct kgdb_hook kh = {
+ .sendbuf = sendbuf,
+ .maxsend = MAX_SEND
+ .getchar = getchar,
+ .putchar = putchar,
+ .flush = flush,
+ .trap = netpoll_set_trap
+};
+
static void rx_hook(struct netpoll *np, int port, char *msg, int len)
{
int i;
@@ -82,8 +91,10 @@ static void rx_hook(struct netpoll *np,
np->remote_port = port;
/* Is this gdb trying to attach? */
- if (!netpoll_trap() && len == 8 && !strncmp(msg, "$Hc-1#09", 8))
+ if (!netpoll_trap() && len == 8 && !strncmp(msg, "$Hc-1#09", 8)) {
+ kgdb_attach(kh);
kgdb_schedule_breakpoint();
+ }
for (i = 0; i < len; i++) {
if (msg[i] == 3)
@@ -117,12 +128,9 @@ static int init_kgdboe(void)
}
#endif
- set_debug_traps();
-
if(!np.remote_ip || netpoll_setup(&np))
return 1;
- kgdboe = 1;
printk(KERN_INFO "kgdb: debugging over ethernet enabled\n");
return 0;
_
--
Matt Mackall : http://www.selenic.com : Linux development and consulting
Hi!
> > >>>Hi!
> > >>>
> > >>>No real code changes, but cleanups all over the place. What about
> > >>>applying?
> > >>>
> > >>>Ouch and arch-dependend code is moved to kernel/kgdb.c. I'll probably
> > >>>do x86-64 version so that is rather important.
> > >>>
> > >>> Pavel
> > >>
> > >>A few comments:
> > >>
> > >>I like the code seperation. Does it follow what Amit is doing? It would
> > >>be nice if Amit's version and this one could come together around this.
> > >>
> > >>I don't think we want to merge the eth and regular kgdb just yet. I
> > >>would, however, like to keep eth completly out of the stub. Possibly a
> > >>new module which just takes care of steering the I/O to the correct place.
> > >
> > >
> > >I've sent Amit the start of an plug interface for abstracting the
> > >communication layer. Should be relatively painless and allow for
> > >starting sessions on the interface of your choice.
> > >
> > May I see?
>
> Here's the interface plus the eth side of it:
Does it work with those patches? (Amid's version does not seem to work
over ethernet).
Pavel
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
On Sat, Jan 10, 2004 at 08:34:06PM +0100, Pavel Machek wrote:
> Hi!
>
> > > >>>Hi!
> > > >>>
> > > >>>No real code changes, but cleanups all over the place. What about
> > > >>>applying?
> > > >>>
> > > >>>Ouch and arch-dependend code is moved to kernel/kgdb.c. I'll probably
> > > >>>do x86-64 version so that is rather important.
> > > >>>
> > > >>> Pavel
> > > >>
> > > >>A few comments:
> > > >>
> > > >>I like the code seperation. Does it follow what Amit is doing? It would
> > > >>be nice if Amit's version and this one could come together around this.
> > > >>
> > > >>I don't think we want to merge the eth and regular kgdb just yet. I
> > > >>would, however, like to keep eth completly out of the stub. Possibly a
> > > >>new module which just takes care of steering the I/O to the correct place.
> > > >
> > > >
> > > >I've sent Amit the start of an plug interface for abstracting the
> > > >communication layer. Should be relatively painless and allow for
> > > >starting sessions on the interface of your choice.
> > > >
> > > May I see?
> >
> > Here's the interface plus the eth side of it:
>
> Does it work with those patches? (Amid's version does not seem to work
> over ethernet).
The stuff currently in -mm and -tiny works. The "pluggable" bits are
proof of concept at this stage and I've been busy working on other
things - was hoping someone else would run with them.
--
Matt Mackall : http://www.selenic.com : Linux development and consulting
Matt Mackall wrote:
> On Sat, Jan 10, 2004 at 12:12:06AM -0800, George Anzinger wrote:
>
>>Matt Mackall wrote:
>>
>>>On Fri, Jan 09, 2004 at 01:54:12PM -0800, George Anzinger wrote:
>>>
>>>
>>>>Pavel Machek wrote:
>>>>
>>>>
>>>>>Hi!
>>>>>
>>>>>No real code changes, but cleanups all over the place. What about
>>>>>applying?
>>>>>
>>>>>Ouch and arch-dependend code is moved to kernel/kgdb.c. I'll probably
>>>>>do x86-64 version so that is rather important.
>>>>>
>>>>> Pavel
>>>>
>>>>A few comments:
>>>>
>>>>I like the code seperation. Does it follow what Amit is doing? It would
>>>>be nice if Amit's version and this one could come together around this.
>>>>
>>>>I don't think we want to merge the eth and regular kgdb just yet. I
>>>>would, however, like to keep eth completly out of the stub. Possibly a
>>>>new module which just takes care of steering the I/O to the correct place.
>>>
>>>
>>>I've sent Amit the start of an plug interface for abstracting the
>>>communication layer. Should be relatively painless and allow for
>>>starting sessions on the interface of your choice.
>>>
>>
>>May I see?
A few comments:
First, I would like to keep kgdb.h for the user of kgdb so that it may be
included without concern most anywhere. In this light I think it should only
contain the breakpoint macro and the timestamp macro stuff, i.e. those things
that a user might want to put in his code.
For the internal kgdb stuff I have created kdgb_local.h which I intended to be
local to the workings of kgdb and not to contain anything a user would need.
Other comments below.
>
>
> Here's the interface plus the eth side of it:
>
> tiny-mpm/arch/i386/kernel/kgdb_stub.c | 59 +++++++++-------------------------
> tiny-mpm/drivers/net/kgdb_eth.c | 26 +++++++++-----
> tiny-mpm/include/asm-i386/kgdb.h | 14 +++++---
> 3 files changed, 44 insertions(+), 55 deletions(-)
>
> diff -puN include/asm-i386/kgdb.h~kgdb-plug include/asm-i386/kgdb.h
> --- tiny/include/asm-i386/kgdb.h~kgdb-plug 2003-12-27 12:18:47.000000000 -0600
> +++ tiny-mpm/include/asm-i386/kgdb.h 2003-12-27 13:19:16.000000000 -0600
> @@ -19,13 +19,19 @@ extern void breakpoint(void);
> #define BREAKPOINT asm(" int $3")
> #endif
>
> +struct kgdb_hook {
> + char *sendbuf;
> + int maxsend;
I don't see the need of maxsend, or sendbuff, for that matter, as kgdb uses it
now (for the eth code) it is redundant, in that the eth putchar also does the
same thing as is being done in the kgdb_stub.c code. I think this should be
removed from the stub and the limit in the ethcode relied upon.
> + int (*getchar)(void);
> + void (*putchar)(int chr);
> + void (*flush)(void);
> + void (*trap)(int enable);
> +};
> +
> +extern void kgdb_attach(struct kgdb_hook *hook);
> extern void kgdb_schedule_breakpoint(void);
> extern void kgdb_process_breakpoint(void);
>
> -extern int kgdb_tty_hook(void);
> -extern int kgdb_eth_hook(void);
> -extern int kgdboe;
> -
> /*
> * GDB debug stub (or any debug stub) can point the 'linux_debug_hook'
> * pointer to its routine and it will be entered as the first thing
> diff -puN arch/i386/kernel/kgdb_stub.c~kgdb-plug arch/i386/kernel/kgdb_stub.c
> --- tiny/arch/i386/kernel/kgdb_stub.c~kgdb-plug 2003-12-27 12:18:47.000000000 -0600
> +++ tiny-mpm/arch/i386/kernel/kgdb_stub.c 2003-12-27 13:19:19.000000000 -0600
> @@ -130,12 +130,7 @@ typedef void (*Function) (void); /* poin
> /* Thread reference */
> typedef unsigned char threadref[8];
>
> -extern int tty_putDebugChar(int); /* write a single character */
> -extern int tty_getDebugChar(void); /* read and return a single char */
> -extern void tty_flushDebugChar(void); /* flush pending characters */
> -extern int eth_putDebugChar(int); /* write a single character */
> -extern int eth_getDebugChar(void); /* read and return a single char */
> -extern void eth_flushDebugChar(void); /* flush pending characters */
> +struct kgdb_hook *kh = 0;
>
> /************************************************************************/
> /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
> @@ -275,39 +270,25 @@ malloc(int size)
> }
> }
>
> -/*
> - * I/O dispatch functions...
> - * Based upon kgdboe, either call the ethernet
> - * handler or the serial one..
> - */
> void
> putDebugChar(int c)
> {
> - if (!kgdboe) {
> - tty_putDebugChar(c);
> - } else {
> - eth_putDebugChar(c);
> - }
> + if (kh)
> + kh->putchar(c);
> }
I was thinking that this might read something like:
if (xxx[kh].putchar(c))
xxx[kh].putchar(c);
One might further want to do something like:
if (!xxx[kh].putchar(c))
kh = 0;
In otherwords, an array (xxx must, of course, be renamed) of stuct kgdb_hook
(which name should also be changed to relate to I/O, kgdb_IO_hook, for example).
Then reserve entry 0 for the rs232 I/O code. An alternate possibility is an
array of pointer to struct kgdb_hook which allows one to define the struct
contents as below and to build the array, all at compile/link time. A legal
entry MUST define get and put, but why not define them all, using dummy
functions for the ones that make no sense in a particular interface.
I also think the functions that kgdb_stub calls should be putDebugChar and
friends, not the underlying functions. I.e. move these out of kgdb_stub.c to a
new common module. This would make it easy for other archs to use, as they
would be using something that looks very much like what they do today. So, in
short, kdgd_stub.c needs to know nothing of kh or the structure it references.
I would also like to see the index (kh in my code) in the kgdb_info structure so
that the user can examine it. I am not sure if I want to allow him to change
it, but I have considered it.
>
> int
> getDebugChar(void)
> {
> - if (!kgdboe) {
> - return tty_getDebugChar();
> - } else {
> - return eth_getDebugChar();
> - }
> + if (kh)
> + return kh->getchar();
> }
>
> void
> flushDebugChar(void)
> {
> - if (!kgdboe) {
> - tty_flushDebugChar();
> - } else {
> - eth_flushDebugChar();
> - }
> + if (kh)
> + kh->flush();
> }
>
> /*
> @@ -490,7 +471,7 @@ putpacket(char *buffer)
>
> /* $<packet info>#<checksum>. */
>
> - if (!kgdboe) {
> + if (kh && !kh->sendbuf) {
> do {
> if (remote_debug)
> printk("T:%s\n", buffer);
> @@ -516,10 +497,7 @@ putpacket(char *buffer)
> * We only transfer MAX_SEND_COUNT size bytes each time
> */
>
> -#define MAX_SEND_COUNT 30
> -
> int send_count = 0, i = 0;
> - char send_buf[MAX_SEND_COUNT];
>
> do {
> if (remote_debug)
> @@ -529,21 +507,21 @@ putpacket(char *buffer)
> count = 0;
> send_count = 0;
> while ((ch = buffer[count])) {
> - if (send_count >= MAX_SEND_COUNT) {
> - for(i = 0; i < MAX_SEND_COUNT; i++) {
> - putDebugChar(send_buf[i]);
> + if (send_count >= kh->maxsend) {
> + for(i = 0; i < kh->maxsend; i++) {
> + putDebugChar(kh->sendbuf[i]);
> }
As I observed above, the eth code already does all this. This code is redundant
and should be removed.
> flushDebugChar();
> send_count = 0;
> } else {
> - send_buf[send_count] = ch;
> + kh->sendbuf[send_count] = ch;
> checksum += ch;
> count ++;
> send_count++;
> }
> }
> for(i = 0; i < send_count; i++)
> - putDebugChar(send_buf[i]);
> + putDebugChar(kh->sendbuf[i]);
> putDebugChar('#');
> putDebugChar(hexchars[checksum >> 4]);
> putDebugChar(hexchars[checksum % 16]);
> @@ -1272,12 +1250,9 @@ kgdb_handle_exception(int exceptionVecto
> print_regs(®s);
> return (0);
> }
> - /*
> - * If we're using eth mode, set the 'mode' in the netdevice.
> - */
>
> - if (kgdboe)
> - netpoll_set_trap(1);
> + if (kh)
> + kh->trap(1);
>
> kgdb_local_irq_save(flags);
>
> @@ -1727,8 +1702,8 @@ kgdb_handle_exception(int exceptionVecto
> }
> }
>
> - if (kgdboe)
> - netpoll_set_trap(0);
> + if(kh)
> + kh->trap(0);
>
> correct_hw_break();
> asm volatile ("movl %0, %%db6\n"::"r" (0));
> diff -puN arch/i386/lib/kgdb_serial.c~kgdb-plug arch/i386/lib/kgdb_serial.c
> diff -puN drivers/net/kgdb_eth.c~kgdb-plug drivers/net/kgdb_eth.c
> --- tiny/drivers/net/kgdb_eth.c~kgdb-plug 2003-12-27 12:18:47.000000000 -0600
> +++ tiny-mpm/drivers/net/kgdb_eth.c 2003-12-27 13:19:18.000000000 -0600
> @@ -34,8 +34,6 @@ static int in_head, in_tail, out_count;
> static atomic_t in_count;
> int kgdboe = 0; /* Default to tty mode */
>
> -extern void set_debug_traps(void);
> -extern void breakpoint(void);
> static void rx_hook(struct netpoll *np, int port, char *msg, int len);
>
> static struct netpoll np = {
> @@ -47,7 +45,7 @@ static struct netpoll np = {
> .remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> };
>
> -int eth_getDebugChar(void)
> +static int getchar(void)
> {
> int chr;
>
> @@ -60,7 +58,7 @@ int eth_getDebugChar(void)
> return chr;
> }
>
> -void eth_flushDebugChar(void)
> +static void flush(void)
> {
> if(out_count && np.dev) {
> netpoll_send_udp(&np, out_buf, out_count);
> @@ -68,13 +66,24 @@ void eth_flushDebugChar(void)
> }
> }
>
> -void eth_putDebugChar(int chr)
> +static void putchar(int chr)
> {
> out_buf[out_count++] = chr;
> if(out_count == OUT_BUF_SIZE)
> eth_flushDebugChar();
> }
>
> +#define MAX_SEND 30
> +char sendbuf[MAX_SEND];
> +static struct kgdb_hook kh = {
> + .sendbuf = sendbuf,
> + .maxsend = MAX_SEND
> + .getchar = getchar,
> + .putchar = putchar,
> + .flush = flush,
> + .trap = netpoll_set_trap
> +};
> +
> static void rx_hook(struct netpoll *np, int port, char *msg, int len)
> {
> int i;
> @@ -82,8 +91,10 @@ static void rx_hook(struct netpoll *np,
> np->remote_port = port;
>
> /* Is this gdb trying to attach? */
> - if (!netpoll_trap() && len == 8 && !strncmp(msg, "$Hc-1#09", 8))
> + if (!netpoll_trap() && len == 8 && !strncmp(msg, "$Hc-1#09", 8)) {
> + kgdb_attach(kh);
> kgdb_schedule_breakpoint();
> + }
>
> for (i = 0; i < len; i++) {
> if (msg[i] == 3)
> @@ -117,12 +128,9 @@ static int init_kgdboe(void)
> }
> #endif
>
> - set_debug_traps();
> -
> if(!np.remote_ip || netpoll_setup(&np))
> return 1;
>
> - kgdboe = 1;
> printk(KERN_INFO "kgdb: debugging over ethernet enabled\n");
>
> return 0;
>
> _
>
>
--
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
On Sun, Jan 11, 2004 at 09:41:57PM -0800, George Anzinger wrote:
> For the internal kgdb stuff I have created kdgb_local.h which I intended to
> be local to the workings of kgdb and not to contain anything a user would
> need.
Agreed, I just haven't touched it since you last mentioned it.
> >+struct kgdb_hook {
> >+ char *sendbuf;
> >+ int maxsend;
>
> I don't see the need of maxsend, or sendbuff, for that matter, as kgdb uses
> it now (for the eth code) it is redundant, in that the eth putchar also
> does the same thing as is being done in the kgdb_stub.c code. I think this
> should be removed from the stub and the limit in the ethcode relied upon.
Fair enough.
> > void
> > putDebugChar(int c)
> > {
> >- if (!kgdboe) {
> >- tty_putDebugChar(c);
> >- } else {
> >- eth_putDebugChar(c);
> >- }
> >+ if (kh)
> >+ kh->putchar(c);
> > }
>
> I was thinking that this might read something like:
> if (xxx[kh].putchar(c))
> xxx[kh].putchar(c);
>
> One might further want to do something like:
> if (!xxx[kh].putchar(c))
> kh = 0;
>
> In otherwords, an array (xxx must, of course, be renamed) of stuct
> kgdb_hook (which name should also be changed to relate to I/O,
> kgdb_IO_hook, for example). Then reserve entry 0 for the rs232 I/O code.
Dunno about that. Probably should work more like the console code,
whoever registers first wins. Early boot will probably be the
exclusive province of serial for a while yet, but designing it in is
probably short-sighted.
> An alternate possibility is an array of pointer to struct kgdb_hook which
> allows one to define the struct contents as below and to build the array,
> all at compile/link time. A legal entry MUST define get and put, but why
> not define them all, using dummy functions for the ones that make no sense
> in a particular interface.
Throwing all the stubs in a special section could work well too. Then
we could add an avail() function so that early boot debugging could
discover if each one was available. The serial code could use this to
kickstart itself while the eth code could test a local initialized
flag and say "not a chance". Which gives us all the architecture to
throw in other trivial interfaces (parallel, bus-snoopers, etc.).
--
Matt Mackall : http://www.selenic.com : Linux development and consulting
Hi!
> > For the internal kgdb stuff I have created kdgb_local.h which I intended to
> > be local to the workings of kgdb and not to contain anything a user would
> > need.
>
> Agreed, I just haven't touched it since you last mentioned it.
I believe we need better name than kgdb_local.h.... Hmm, but I'm not
sure what the name should be.
Pavel
--
When do you have heart between your knees?
Regarding pluggable iterfaces -
The version I have lets a user to choose the interface by supplying
appropriate command line. (e.g. kgdbwait kgdb8250=... or kgdbwait
kgdbeth=...) It supports an arbitrary number of interfaces. The kgdb core
itself is independent of an interface. All interfaces are defined by a
structure described below. An interface registers itself with kgdb core by
assigning this structure to pointer kgdb_serial.
struct kgdb_serial {
int chunksize;
int (*read_char)(void);
void (*write_char)(int);
void (*flush)(void);
int (*hook)(void);
void (*begin_session)(void);
void (*end_session)(void);
};
Where chunksize is maximum chunksize an interface can handle.
read_char and write_char are derived from getDebugChar and putDebugChar
flush flushes written characters. Flush control is given to kgdb core so that
it can ensure that #checksum doesn't split.
begin_session and end_session inform an interface about a gdb communication
session. (Haven't decided about console packets to gdb yet)
hook is interface initialization. It can return errors. This allows kgdb core
to probe the interface for availability at multiple points. Because of this,
there can be multiple debugger entry points
1. At very begining of start_kernel -> Only an 8250 interface with early boot
enabled can respond to hook call.
2. After smp initialization -> An 8250 interface without an early boot can
respond to this.
3. An ethernet interface can itself call debugger_entry to enter debugger
after it's brought up from userland.
Other interfaces can come up at (1) or (2)
On Monday 12 Jan 2004 12:19 pm, Matt Mackall wrote:
> On Sun, Jan 11, 2004 at 09:41:57PM -0800, George Anzinger wrote:
> > For the internal kgdb stuff I have created kdgb_local.h which I intended
> > to be local to the workings of kgdb and not to contain anything a user
> > would need.
>
> Agreed, I just haven't touched it since you last mentioned it.
>
> > >+struct kgdb_hook {
> > >+ char *sendbuf;
> > >+ int maxsend;
> >
> > I don't see the need of maxsend, or sendbuff, for that matter, as kgdb
> > uses it now (for the eth code) it is redundant, in that the eth putchar
> > also does the same thing as is being done in the kgdb_stub.c code. I
> > think this should be removed from the stub and the limit in the ethcode
> > relied upon.
>
> Fair enough.
>
> > > void
> > > putDebugChar(int c)
> > > {
> > >- if (!kgdboe) {
> > >- tty_putDebugChar(c);
> > >- } else {
> > >- eth_putDebugChar(c);
> > >- }
> > >+ if (kh)
> > >+ kh->putchar(c);
> > > }
> >
> > I was thinking that this might read something like:
> > if (xxx[kh].putchar(c))
> > xxx[kh].putchar(c);
> >
> > One might further want to do something like:
> > if (!xxx[kh].putchar(c))
> > kh = 0;
> >
> > In otherwords, an array (xxx must, of course, be renamed) of stuct
> > kgdb_hook (which name should also be changed to relate to I/O,
> > kgdb_IO_hook, for example). Then reserve entry 0 for the rs232 I/O code.
>
> Dunno about that. Probably should work more like the console code,
> whoever registers first wins. Early boot will probably be the
> exclusive province of serial for a while yet, but designing it in is
> probably short-sighted.
>
> > An alternate possibility is an array of pointer to struct kgdb_hook
> > which allows one to define the struct contents as below and to build the
> > array, all at compile/link time. A legal entry MUST define get and put,
> > but why not define them all, using dummy functions for the ones that make
> > no sense in a particular interface.
>
> Throwing all the stubs in a special section could work well too. Then
> we could add an avail() function so that early boot debugging could
> discover if each one was available. The serial code could use this to
> kickstart itself while the eth code could test a local initialized
> flag and say "not a chance". Which gives us all the architecture to
> throw in other trivial interfaces (parallel, bus-snoopers, etc.).
--
Amit Kale
EmSysSoft (http://www.emsyssoft.com)
KGDB: Linux Kernel Source Level Debugger (http://kgdb.sourceforge.net)
Pavel Machek wrote:
> Hi!
>
>
>>>For the internal kgdb stuff I have created kdgb_local.h which I intended to
>>>be local to the workings of kgdb and not to contain anything a user would
>>>need.
>>
>>Agreed, I just haven't touched it since you last mentioned it.
>
>
> I believe we need better name than kgdb_local.h.... Hmm, but I'm not
> sure what the name should be.
Sure. How about kgdb_internal.h ??
--
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
Hi!
> >>>For the internal kgdb stuff I have created kdgb_local.h which I intended
> >>>to be local to the workings of kgdb and not to contain anything a user
> >>>would need.
> >>
> >>Agreed, I just haven't touched it since you last mentioned it.
> >
> >
> >I believe we need better name than kgdb_local.h.... Hmm, but I'm not
> >sure what the name should be.
>
> Sure. How about kgdb_internal.h ??
Yes, that looks better. [Somehow I thought even better name has to
exists.]
Pavel
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]
Matt Mackall wrote:
> On Sun, Jan 11, 2004 at 09:41:57PM -0800, George Anzinger wrote:
>
>>For the internal kgdb stuff I have created kdgb_local.h which I intended to
>>be local to the workings of kgdb and not to contain anything a user would
>>need.
>
>
> Agreed, I just haven't touched it since you last mentioned it.
>
>
>>>+struct kgdb_hook {
>>>+ char *sendbuf;
>>>+ int maxsend;
>>
>>I don't see the need of maxsend, or sendbuff, for that matter, as kgdb uses
>>it now (for the eth code) it is redundant, in that the eth putchar also
>>does the same thing as is being done in the kgdb_stub.c code. I think this
>>should be removed from the stub and the limit in the ethcode relied upon.
>
>
> Fair enough.
>
>
>>>void
>>>putDebugChar(int c)
>>>{
>>>- if (!kgdboe) {
>>>- tty_putDebugChar(c);
>>>- } else {
>>>- eth_putDebugChar(c);
>>>- }
>>>+ if (kh)
>>>+ kh->putchar(c);
>>>}
>>
>>I was thinking that this might read something like:
>> if (xxx[kh].putchar(c))
>> xxx[kh].putchar(c);
>>
>>One might further want to do something like:
>> if (!xxx[kh].putchar(c))
>> kh = 0;
>>
>>In otherwords, an array (xxx must, of course, be renamed) of stuct
>>kgdb_hook (which name should also be changed to relate to I/O,
>>kgdb_IO_hook, for example). Then reserve entry 0 for the rs232 I/O code.
>
>
> Dunno about that. Probably should work more like the console code,
> whoever registers first wins. Early boot will probably be the
> exclusive province of serial for a while yet, but designing it in is
> probably short-sighted.
>
>
>> An alternate possibility is an array of pointer to struct kgdb_hook which
>>allows one to define the struct contents as below and to build the array,
>>all at compile/link time. A legal entry MUST define get and put, but why
>>not define them all, using dummy functions for the ones that make no sense
>>in a particular interface.
>
>
> Throwing all the stubs in a special section could work well too. Then
> we could add an avail() function so that early boot debugging could
> discover if each one was available. The serial code could use this to
> kickstart itself while the eth code could test a local initialized
> flag and say "not a chance". Which gives us all the architecture to
> throw in other trivial interfaces (parallel, bus-snoopers, etc.).
>
I am thinking of something more like what was done with the x86 timer code.
Each timer option sets up a structure with an array of pointers to each option.
There it is done at compile time, and the runtime code tries each. There it is
done in order, but here we want to do it a bit differently.
Maybe we could have an "available" flag or just assume that the address being
!=0 for getdebugchar means it is "available". I think there should be a
prefered intface set at config time. Possibly over ride this with the command
line. Then have a back up order in case kgdb wants to communicate prior to the
prefered one being available.
We would also have a rule that the command line over ride only works if
communication has not yet been established. Here, we would also like control
from gdb/kgdb so we could switch to a different interface, but under gdb control
at this point. Either a maintaince command or setting the "channel" with a
memory modify command. We would want this to take effect only after the current
command is acknowledged.
--
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
Amit S. Kale wrote:
> Regarding pluggable iterfaces -
> The version I have lets a user to choose the interface by supplying
> appropriate command line. (e.g. kgdbwait kgdb8250=... or kgdbwait
> kgdbeth=...) It supports an arbitrary number of interfaces. The kgdb core
> itself is independent of an interface. All interfaces are defined by a
> structure described below. An interface registers itself with kgdb core by
> assigning this structure to pointer kgdb_serial.
>
> struct kgdb_serial {
> int chunksize;
Do we really need this? The only place I saw it used it did not seem to matter
where the split occured and there was now endchunck/beginchunck stuff. I would
MUCH rather see the interface code take care of this with out mucking up the
core code (as the eth code already does). Did I miss something here?
> int (*read_char)(void);
> void (*write_char)(int);
> void (*flush)(void);
> int (*hook)(void);
> void (*begin_session)(void);
> void (*end_session)(void);
> };
>
> Where chunksize is maximum chunksize an interface can handle.
>
> read_char and write_char are derived from getDebugChar and putDebugChar
> flush flushes written characters. Flush control is given to kgdb core so that
> it can ensure that #checksum doesn't split.
Actually, I think it is needed so that gdb knows that the kgdb stub has exited.
This could, of course, be done with out the flush, but then the write code
would have to recognize an end of record (not hard with the given protocol). I
don't think there is any requirement that a checksum not be split. My
assumption here is that the logical record is reassembled on the gdb end without
concern about how many physical records are involved. Is this not true?
>
> begin_session and end_session inform an interface about a gdb communication
> session. (Haven't decided about console packets to gdb yet)
I assume you mean entry to the stub/ exit the stub as a "session". This
eliminates the old hook, right?
>
> hook is interface initialization. It can return errors. This allows kgdb core
> to probe the interface for availability at multiple points. Because of this,
> there can be multiple debugger entry points
> 1. At very begining of start_kernel -> Only an 8250 interface with early boot
> enabled can respond to hook call.
> 2. After smp initialization -> An 8250 interface without an early boot can
> respond to this.
> 3. An ethernet interface can itself call debugger_entry to enter debugger
> after it's brought up from userland.
Hm.. Eth is up way before user land, else we could not nfs mount root and all
that that implies. I think eth should be "available" when it is initialized. I
am not sure I see a reason to support a way to get to kgdb from user land. We
have ^C and also the Sys Rq entry. That should be enough.
Also, as mention in a prior email, I don't think it is a good idea to switch
interfaces once communication is started, unless commanded to do so, even if the
default request is to use an inteface that just came up.
I would suggest the the readyness of an interface be something one can easily
determine from gdb (assuming we have established a connection). I suggest
putting this in the kgdb_info structure. Possibly a pointer to an array of ???
where each entry is one of the interfaces. Should have an "up" value here
(filled in by the hook calls), as well as, say a pointer to more details on the
interface. The details might be baud, irq, address, for serial, and the ip
address, etc for eth.
-g
>
> Other interfaces can come up at (1) or (2)
>
> On Monday 12 Jan 2004 12:19 pm, Matt Mackall wrote:
>
>>On Sun, Jan 11, 2004 at 09:41:57PM -0800, George Anzinger wrote:
>>
>>>For the internal kgdb stuff I have created kdgb_local.h which I intended
>>>to be local to the workings of kgdb and not to contain anything a user
>>>would need.
>>
>>Agreed, I just haven't touched it since you last mentioned it.
>>
>>
>>>>+struct kgdb_hook {
>>>>+ char *sendbuf;
>>>>+ int maxsend;
>>>
>>>I don't see the need of maxsend, or sendbuff, for that matter, as kgdb
>>>uses it now (for the eth code) it is redundant, in that the eth putchar
>>>also does the same thing as is being done in the kgdb_stub.c code. I
>>>think this should be removed from the stub and the limit in the ethcode
>>>relied upon.
>>
>>Fair enough.
>>
>>
>>>>void
>>>>putDebugChar(int c)
>>>>{
>>>>- if (!kgdboe) {
>>>>- tty_putDebugChar(c);
>>>>- } else {
>>>>- eth_putDebugChar(c);
>>>>- }
>>>>+ if (kh)
>>>>+ kh->putchar(c);
>>>>}
>>>
>>>I was thinking that this might read something like:
>>> if (xxx[kh].putchar(c))
>>> xxx[kh].putchar(c);
>>>
>>>One might further want to do something like:
>>> if (!xxx[kh].putchar(c))
>>> kh = 0;
>>>
>>>In otherwords, an array (xxx must, of course, be renamed) of stuct
>>>kgdb_hook (which name should also be changed to relate to I/O,
>>>kgdb_IO_hook, for example). Then reserve entry 0 for the rs232 I/O code.
>>
>>Dunno about that. Probably should work more like the console code,
>>whoever registers first wins. Early boot will probably be the
>>exclusive province of serial for a while yet, but designing it in is
>>probably short-sighted.
>>
>>
>>> An alternate possibility is an array of pointer to struct kgdb_hook
>>>which allows one to define the struct contents as below and to build the
>>>array, all at compile/link time. A legal entry MUST define get and put,
>>>but why not define them all, using dummy functions for the ones that make
>>>no sense in a particular interface.
>>
>>Throwing all the stubs in a special section could work well too. Then
>>we could add an avail() function so that early boot debugging could
>>discover if each one was available. The serial code could use this to
>>kickstart itself while the eth code could test a local initialized
>>flag and say "not a chance". Which gives us all the architecture to
>>throw in other trivial interfaces (parallel, bus-snoopers, etc.).
>
>
--
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
On Wednesday 14 Jan 2004 2:23 am, George Anzinger wrote:
> Matt Mackall wrote:
> > On Sun, Jan 11, 2004 at 09:41:57PM -0800, George Anzinger wrote:
> >>For the internal kgdb stuff I have created kdgb_local.h which I intended
> >> to be local to the workings of kgdb and not to contain anything a user
> >> would need.
> >
> > Agreed, I just haven't touched it since you last mentioned it.
> >
> >>>+struct kgdb_hook {
> >>>+ char *sendbuf;
> >>>+ int maxsend;
> >>
> >>I don't see the need of maxsend, or sendbuff, for that matter, as kgdb
> >> uses it now (for the eth code) it is redundant, in that the eth putchar
> >> also does the same thing as is being done in the kgdb_stub.c code. I
> >> think this should be removed from the stub and the limit in the ethcode
> >> relied upon.
> >
> > Fair enough.
> >
> >>>void
> >>>putDebugChar(int c)
> >>>{
> >>>- if (!kgdboe) {
> >>>- tty_putDebugChar(c);
> >>>- } else {
> >>>- eth_putDebugChar(c);
> >>>- }
> >>>+ if (kh)
> >>>+ kh->putchar(c);
> >>>}
> >>
> >>I was thinking that this might read something like:
> >> if (xxx[kh].putchar(c))
> >> xxx[kh].putchar(c);
> >>
> >>One might further want to do something like:
> >> if (!xxx[kh].putchar(c))
> >> kh = 0;
> >>
> >>In otherwords, an array (xxx must, of course, be renamed) of stuct
> >>kgdb_hook (which name should also be changed to relate to I/O,
> >>kgdb_IO_hook, for example). Then reserve entry 0 for the rs232 I/O code.
> >
> > Dunno about that. Probably should work more like the console code,
> > whoever registers first wins. Early boot will probably be the
> > exclusive province of serial for a while yet, but designing it in is
> > probably short-sighted.
> >
> >> An alternate possibility is an array of pointer to struct kgdb_hook
> >> which allows one to define the struct contents as below and to build the
> >> array, all at compile/link time. A legal entry MUST define get and put,
> >> but why not define them all, using dummy functions for the ones that
> >> make no sense in a particular interface.
> >
> > Throwing all the stubs in a special section could work well too. Then
> > we could add an avail() function so that early boot debugging could
> > discover if each one was available. The serial code could use this to
> > kickstart itself while the eth code could test a local initialized
> > flag and say "not a chance". Which gives us all the architecture to
> > throw in other trivial interfaces (parallel, bus-snoopers, etc.).
>
> I am thinking of something more like what was done with the x86 timer code.
> Each timer option sets up a structure with an array of pointers to each
> option. There it is done at compile time, and the runtime code tries each.
> There it is done in order, but here we want to do it a bit differently.
>
> Maybe we could have an "available" flag or just assume that the address
> being !=0 for getdebugchar means it is "available". I think there should
> be a prefered intface set at config time. Possibly over ride this with the
> command line. Then have a back up order in case kgdb wants to communicate
> prior to the prefered one being available.
>
> We would also have a rule that the command line over ride only works if
> communication has not yet been established. Here, we would also like
> control from gdb/kgdb so we could switch to a different interface, but
> under gdb control at this point. Either a maintaince command or setting
> the "channel" with a memory modify command. We would want this to take
> effect only after the current command is acknowledged.
I have something similar in my patches.
Each interface has kgdb_hook function, which returns failure if an interface
isn't ready.
--
Amit Kale
EmSysSoft (http://www.emsyssoft.com)
KGDB: Linux Kernel Source Level Debugger (http://kgdb.sourceforge.net)
On Wednesday 14 Jan 2004 2:50 am, George Anzinger wrote:
> Amit S. Kale wrote:
> > Regarding pluggable iterfaces -
> > The version I have lets a user to choose the interface by supplying
> > appropriate command line. (e.g. kgdbwait kgdb8250=... or kgdbwait
> > kgdbeth=...) It supports an arbitrary number of interfaces. The kgdb core
> > itself is independent of an interface. All interfaces are defined by a
> > structure described below. An interface registers itself with kgdb core
> > by assigning this structure to pointer kgdb_serial.
> >
> > struct kgdb_serial {
> > int chunksize;
>
> Do we really need this? The only place I saw it used it did not seem to
> matter where the split occured and there was now endchunck/beginchunck
> stuff. I would MUCH rather see the interface code take care of this with
> out mucking up the core code (as the eth code already does). Did I miss
> something here?
Having an interface recognize a kgdb core record isn't a good design.
Having kgdb core record know interface limitations isn't good either.
If kgdb calls flush at end of a packet and an interface splits a packet
whenever its length goes above its limit, that'll be the right way of doing
it.
>
> > int (*read_char)(void);
> > void (*write_char)(int);
> > void (*flush)(void);
> > int (*hook)(void);
> > void (*begin_session)(void);
> > void (*end_session)(void);
> > };
> >
> > Where chunksize is maximum chunksize an interface can handle.
> >
> > read_char and write_char are derived from getDebugChar and putDebugChar
> > flush flushes written characters. Flush control is given to kgdb core so
> > that it can ensure that #checksum doesn't split.
>
> Actually, I think it is needed so that gdb knows that the kgdb stub has
> exited. This could, of course, be done with out the flush, but then the
> write code would have to recognize an end of record (not hard with the
> given protocol). I don't think there is any requirement that a checksum
> not be split. My assumption here is that the logical record is reassembled
> on the gdb end without concern about how many physical records are
> involved. Is this not true?
I guess yes. Splitting of #checksum may not matter.
>
> > begin_session and end_session inform an interface about a gdb
> > communication session. (Haven't decided about console packets to gdb yet)
>
> I assume you mean entry to the stub/ exit the stub as a "session". This
> eliminates the old hook, right?
Yes. begin_session and end_session mark entry and exit points into
handle_exception. They are required to mark ethernet interface in trap mode.
What's old hook?
>
> > hook is interface initialization. It can return errors. This allows kgdb
> > core to probe the interface for availability at multiple points. Because
> > of this, there can be multiple debugger entry points
> > 1. At very begining of start_kernel -> Only an 8250 interface with early
> > boot enabled can respond to hook call.
> > 2. After smp initialization -> An 8250 interface without an early boot
> > can respond to this.
> > 3. An ethernet interface can itself call debugger_entry to enter debugger
> > after it's brought up from userland.
>
> Hm.. Eth is up way before user land, else we could not nfs mount root and
> all that that implies. I think eth should be "available" when it is
> initialized. I am not sure I see a reason to support a way to get to kgdb
> from user land. We have ^C and also the Sys Rq entry. That should be
> enough.
Pardon my poor knowledge of network stack. I still have to work out the
details of how and when to start kgdb-ethernet connection.
Now that you mention it, I'll think about it. I can actually bring up an
ethernet interface from kgdb eth code itself and associate an ip address with
it.
>
> Also, as mention in a prior email, I don't think it is a good idea to
> switch interfaces once communication is started, unless commanded to do so,
> even if the default request is to use an inteface that just came up.
Agreed.
-amit
>
> I would suggest the the readyness of an interface be something one can
> easily determine from gdb (assuming we have established a connection). I
> suggest putting this in the kgdb_info structure. Possibly a pointer to an
> array of ??? where each entry is one of the interfaces. Should have an
> "up" value here (filled in by the hook calls), as well as, say a pointer to
> more details on the interface. The details might be baud, irq, address,
> for serial, and the ip address, etc for eth.
>
> -g
>
> > Other interfaces can come up at (1) or (2)
> >
> > On Monday 12 Jan 2004 12:19 pm, Matt Mackall wrote:
> >>On Sun, Jan 11, 2004 at 09:41:57PM -0800, George Anzinger wrote:
> >>>For the internal kgdb stuff I have created kdgb_local.h which I intended
> >>>to be local to the workings of kgdb and not to contain anything a user
> >>>would need.
> >>
> >>Agreed, I just haven't touched it since you last mentioned it.
> >>
> >>>>+struct kgdb_hook {
> >>>>+ char *sendbuf;
> >>>>+ int maxsend;
> >>>
> >>>I don't see the need of maxsend, or sendbuff, for that matter, as kgdb
> >>>uses it now (for the eth code) it is redundant, in that the eth putchar
> >>>also does the same thing as is being done in the kgdb_stub.c code. I
> >>>think this should be removed from the stub and the limit in the ethcode
> >>>relied upon.
> >>
> >>Fair enough.
> >>
> >>>>void
> >>>>putDebugChar(int c)
> >>>>{
> >>>>- if (!kgdboe) {
> >>>>- tty_putDebugChar(c);
> >>>>- } else {
> >>>>- eth_putDebugChar(c);
> >>>>- }
> >>>>+ if (kh)
> >>>>+ kh->putchar(c);
> >>>>}
> >>>
> >>>I was thinking that this might read something like:
> >>> if (xxx[kh].putchar(c))
> >>> xxx[kh].putchar(c);
> >>>
> >>>One might further want to do something like:
> >>> if (!xxx[kh].putchar(c))
> >>> kh = 0;
> >>>
> >>>In otherwords, an array (xxx must, of course, be renamed) of stuct
> >>>kgdb_hook (which name should also be changed to relate to I/O,
> >>>kgdb_IO_hook, for example). Then reserve entry 0 for the rs232 I/O code.
> >>
> >>Dunno about that. Probably should work more like the console code,
> >>whoever registers first wins. Early boot will probably be the
> >>exclusive province of serial for a while yet, but designing it in is
> >>probably short-sighted.
> >>
> >>> An alternate possibility is an array of pointer to struct kgdb_hook
> >>>which allows one to define the struct contents as below and to build the
> >>>array, all at compile/link time. A legal entry MUST define get and put,
> >>>but why not define them all, using dummy functions for the ones that
> >>> make no sense in a particular interface.
> >>
> >>Throwing all the stubs in a special section could work well too. Then
> >>we could add an avail() function so that early boot debugging could
> >>discover if each one was available. The serial code could use this to
> >>kickstart itself while the eth code could test a local initialized
> >>flag and say "not a chance". Which gives us all the architecture to
> >>throw in other trivial interfaces (parallel, bus-snoopers, etc.).
--
Amit Kale
EmSysSoft (http://www.emsyssoft.com)
KGDB: Linux Kernel Source Level Debugger (http://kgdb.sourceforge.net)
Amit S. Kale wrote:
> On Wednesday 14 Jan 2004 2:23 am, George Anzinger wrote:
>
>>
>>>>An alternate possibility is an array of pointer to struct kgdb_hook
>>>>which allows one to define the struct contents as below and to build the
>>>>array, all at compile/link time. A legal entry MUST define get and put,
>>>>but why not define them all, using dummy functions for the ones that
>>>>make no sense in a particular interface.
>>>
>>>Throwing all the stubs in a special section could work well too. Then
>>>we could add an avail() function so that early boot debugging could
>>>discover if each one was available. The serial code could use this to
>>>kickstart itself while the eth code could test a local initialized
>>>flag and say "not a chance". Which gives us all the architecture to
>>>throw in other trivial interfaces (parallel, bus-snoopers, etc.).
>>
>>I am thinking of something more like what was done with the x86 timer code.
>>Each timer option sets up a structure with an array of pointers to each
>>option. There it is done at compile time, and the runtime code tries each.
>>There it is done in order, but here we want to do it a bit differently.
>>
>>Maybe we could have an "available" flag or just assume that the address
>>being !=0 for getdebugchar means it is "available". I think there should
>>be a prefered intface set at config time. Possibly over ride this with the
>>command line. Then have a back up order in case kgdb wants to communicate
>>prior to the prefered one being available.
>>
>>We would also have a rule that the command line over ride only works if
>>communication has not yet been established. Here, we would also like
>>control from gdb/kgdb so we could switch to a different interface, but
>>under gdb control at this point. Either a maintaince command or setting
>>the "channel" with a memory modify command. We would want this to take
>>effect only after the current command is acknowledged.
>
>
> I have something similar in my patches.
> Each interface has kgdb_hook function, which returns failure if an interface
> isn't ready.
Keep in mind that an interface may be ready to communicate and still not able to
handle the ^C break. The reason is that the ^C requires interrupt support which
is not available until rather late in the bring up. In particular, trying to
register an interrupt routine prior to the memory subsystem being able to do an
alloc causes failure to register the interrupt function, which does cause and
error return from request_irq(). The version in the common.patch seems to keep
this information but does nothing with it. I think it would be better to try
again later and to keep trying until the request is successful. See for
example, the kgdb patch in Andrew's mm breakout.
--
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
Amit S. Kale wrote:
> On Wednesday 14 Jan 2004 2:50 am, George Anzinger wrote:
>
>>Amit S. Kale wrote:
>>
>>>Regarding pluggable iterfaces -
>>>The version I have lets a user to choose the interface by supplying
>>>appropriate command line. (e.g. kgdbwait kgdb8250=... or kgdbwait
>>>kgdbeth=...) It supports an arbitrary number of interfaces. The kgdb core
>>>itself is independent of an interface. All interfaces are defined by a
>>>structure described below. An interface registers itself with kgdb core
>>>by assigning this structure to pointer kgdb_serial.
>>>
>>>struct kgdb_serial {
>>> int chunksize;
>>
>>Do we really need this? The only place I saw it used it did not seem to
>>matter where the split occured and there was now endchunck/beginchunck
>>stuff. I would MUCH rather see the interface code take care of this with
>>out mucking up the core code (as the eth code already does). Did I miss
>>something here?
>
>
> Having an interface recognize a kgdb core record isn't a good design.
> Having kgdb core record know interface limitations isn't good either.
>
> If kgdb calls flush at end of a packet and an interface splits a packet
> whenever its length goes above its limit, that'll be the right way of doing
> it.
I think this is what happens in the current eth code.
>
>>> int (*read_char)(void);
>>> void (*write_char)(int);
>>> void (*flush)(void);
>>> int (*hook)(void);
>>> void (*begin_session)(void);
>>> void (*end_session)(void);
>>>};
>>>
>>>Where chunksize is maximum chunksize an interface can handle.
>>>
>>>read_char and write_char are derived from getDebugChar and putDebugChar
>>>flush flushes written characters. Flush control is given to kgdb core so
>>>that it can ensure that #checksum doesn't split.
>>
>>Actually, I think it is needed so that gdb knows that the kgdb stub has
>>exited. This could, of course, be done with out the flush, but then the
>>write code would have to recognize an end of record (not hard with the
>>given protocol). I don't think there is any requirement that a checksum
>>not be split. My assumption here is that the logical record is reassembled
>>on the gdb end without concern about how many physical records are
>>involved. Is this not true?
>
>
> I guess yes. Splitting of #checksum may not matter.
>
>
>>>begin_session and end_session inform an interface about a gdb
>>>communication session. (Haven't decided about console packets to gdb yet)
>>
>>I assume you mean entry to the stub/ exit the stub as a "session". This
>>eliminates the old hook, right?
>
>
> Yes. begin_session and end_session mark entry and exit points into
> handle_exception. They are required to mark ethernet interface in trap mode.
>
> What's old hook?
I think it was a function in eth that was called to mark the begin and end just
as begin_session and end_session do. Might want to consider one function for
this, with a parameter.
-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