diff -c -r -N console-os/arch/i386/config.in console-os-kdb/arch/i386/config.in
*** console-os/arch/i386/config.in	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/config.in	2007-01-10 14:02:18.000000000 -0800
***************
*** 546,551 ****
--- 546,564 ----
  	bool '  Morse code panics' CONFIG_PANIC_MORSE
     bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
     bool '  Smaller kernel binary' CONFIG_SMALL
+    bool '  Built-in Kernel Debugger support' CONFIG_KDB
+    dep_tristate '    KDB modules' CONFIG_KDB_MODULES $CONFIG_KDB
+    if [ "$CONFIG_KDB" = "y" ]; then
+       bool '    KDB off by default' CONFIG_KDB_OFF
+       int  '    KDB continues after catastrophic errors' CONFIG_KDB_CONTINUE_CATASTROPHIC 0
+       if [ "$CONFIG_USB" != "n" ] ; then
+               bool '    Support for USB Keyboard in KDB' CONFIG_KDB_USB
+       fi
+       comment '  Load all symbols for debugging is required for KDB'
+       define_bool CONFIG_KALLSYMS y
+    else
+       bool '  Load all symbols for debugging' CONFIG_KALLSYMS
+    fi
  fi
  
  endmenu
diff -c -r -N console-os/arch/i386/kdb/ansidecl.h console-os-kdb/arch/i386/kdb/ansidecl.h
*** console-os/arch/i386/kdb/ansidecl.h	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/arch/i386/kdb/ansidecl.h	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,198 ----
+ /* ANSI and traditional C compatability macros
+    Copyright 1991, 1992, 1996, 1999 Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+ 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 of the License, 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.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ /* ANSI and traditional C compatibility macros
+ 
+    ANSI C is assumed if __STDC__ is #defined.
+ 
+    Macro	ANSI C definition	Traditional C definition
+    -----	---- - ----------	----------- - ----------
+    PTR		`void *'		`char *'
+    LONG_DOUBLE	`long double'		`double'
+    VOLATILE	`volatile'		`'
+    SIGNED	`signed'		`'
+    PTRCONST	`void *const'		`char *'
+    ANSI_PROTOTYPES  1			not defined
+ 
+    CONST is also defined, but is obsolete.  Just use const.
+ 
+    obsolete --     DEFUN (name, arglist, args)
+ 
+ 	Defines function NAME.
+ 
+ 	ARGLIST lists the arguments, separated by commas and enclosed in
+ 	parentheses.  ARGLIST becomes the argument list in traditional C.
+ 
+ 	ARGS list the arguments with their types.  It becomes a prototype in
+ 	ANSI C, and the type declarations in traditional C.  Arguments should
+ 	be separated with `AND'.  For functions with a variable number of
+ 	arguments, the last thing listed should be `DOTS'.
+ 
+    obsolete --     DEFUN_VOID (name)
+ 
+ 	Defines a function NAME, which takes no arguments.
+ 
+    obsolete --     EXFUN (name, (prototype))	-- obsolete.
+ 
+ 	Replaced by PARAMS.  Do not use; will disappear someday soon.
+ 	Was used in external function declarations.
+ 	In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+ 	parentheses).  In traditional C it is `NAME()'.
+ 	For a function that takes no arguments, PROTOTYPE should be `(void)'.
+ 
+    obsolete --     PROTO (type, name, (prototype)    -- obsolete.
+ 
+ 	This one has also been replaced by PARAMS.  Do not use.
+ 
+    PARAMS ((args))
+ 
+ 	We could use the EXFUN macro to handle prototype declarations, but
+ 	the name is misleading and the result is ugly.  So we just define a
+ 	simple macro to handle the parameter lists, as in:
+ 
+ 	      static int foo PARAMS ((int, char));
+ 
+ 	This produces:  `static int foo();' or `static int foo (int, char);'
+ 
+ 	EXFUN would have done it like this:
+ 
+ 	      static int EXFUN (foo, (int, char));
+ 
+ 	but the function is not external...and it's hard to visually parse
+ 	the function name out of the mess.   EXFUN should be considered
+ 	obsolete; new code should be written to use PARAMS.
+ 
+    DOTS is also obsolete.
+ 
+    Examples:
+ 
+ 	extern int printf PARAMS ((const char *format, ...));
+ */
+ 
+ #ifndef	_ANSIDECL_H
+ 
+ #define	_ANSIDECL_H	1
+ 
+ 
+ /* Every source file includes this file,
+    so they will all get the switch for lint.  */
+ /* LINTLIBRARY */
+ 
+ 
+ #if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32)
+ /* All known AIX compilers implement these things (but don't always
+    define __STDC__).  The RISC/OS MIPS compiler defines these things
+    in SVR4 mode, but does not define __STDC__.  */
+ 
+ #define	PTR		void *
+ #define	PTRCONST	void *CONST
+ #define	LONG_DOUBLE	long double
+ 
+ #ifndef IN_GCC
+ #define	AND		,
+ #define	NOARGS		void
+ #define	VOLATILE	volatile
+ #define	SIGNED		signed
+ #endif /* ! IN_GCC */
+ 
+ #ifndef PARAMS
+ #define PARAMS(paramlist)		paramlist
+ #endif
+ #define ANSI_PROTOTYPES			1
+ 
+ #define VPARAMS(ARGS)			ARGS
+ #define VA_START(va_list,var)		va_start(va_list,var)
+ 
+ /* These are obsolete.  Do not use.  */
+ #ifndef IN_GCC
+ #define CONST				const
+ #define DOTS				, ...
+ #define PROTO(type, name, arglist)	type name arglist
+ #define EXFUN(name, proto)		name proto
+ #define DEFUN(name, arglist, args)	name(args)
+ #define DEFUN_VOID(name)		name(void)
+ #endif /* ! IN_GCC */
+ 
+ #else	/* Not ANSI C.  */
+ 
+ #define	PTR		char *
+ #define	PTRCONST	PTR
+ #define	LONG_DOUBLE	double
+ 
+ #ifndef IN_GCC
+ #define	AND		;
+ #define	NOARGS
+ #define	VOLATILE
+ #define	SIGNED
+ #endif /* !IN_GCC */
+ 
+ #ifndef const /* some systems define it in header files for non-ansi mode */
+ #define	const
+ #endif
+ 
+ #define PARAMS(paramlist)		()
+ 
+ #define VPARAMS(ARGS)			(va_alist) va_dcl
+ #define VA_START(va_list,var)		va_start(va_list)
+ 
+ /* These are obsolete.  Do not use.  */
+ #ifndef IN_GCC
+ #define CONST
+ #define DOTS
+ #define PROTO(type, name, arglist)	type name ()
+ #define EXFUN(name, proto)		name()
+ #define DEFUN(name, arglist, args)	name arglist args;
+ #define DEFUN_VOID(name)		name()
+ #endif /* ! IN_GCC */
+ 
+ #endif	/* ANSI C.  */
+ 
+ /* Define macros for some gcc attributes.  This permits us to use the
+    macros freely, and know that they will come into play for the
+    version of gcc in which they are supported.  */
+ 
+ #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+ # define __attribute__(x)
+ #endif
+ 
+ #ifndef ATTRIBUTE_UNUSED_LABEL
+ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 93)
+ #  define ATTRIBUTE_UNUSED_LABEL
+ # else
+ #  define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
+ # endif /* GNUC < 2.93 */
+ #endif /* ATTRIBUTE_UNUSED_LABEL */
+ 
+ #ifndef ATTRIBUTE_UNUSED
+ #define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+ #endif /* ATTRIBUTE_UNUSED */
+ 
+ #ifndef ATTRIBUTE_NORETURN
+ #define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+ #endif /* ATTRIBUTE_NORETURN */
+ 
+ #ifndef ATTRIBUTE_PRINTF
+ #define ATTRIBUTE_PRINTF(m, n) __attribute__ ((format (__printf__, m, n)))
+ #define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
+ #define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
+ #define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4)
+ #define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5)
+ #define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
+ #endif /* ATTRIBUTE_PRINTF */
+ 
+ #endif	/* ansidecl.h	*/
diff -c -r -N console-os/arch/i386/kdb/bfd.h console-os-kdb/arch/i386/kdb/bfd.h
*** console-os/arch/i386/kdb/bfd.h	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/arch/i386/kdb/bfd.h	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,3102 ----
+ /* Main header file for the bfd library -- portable access to object files.
+    Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+    Free Software Foundation, Inc.
+    Contributed by Cygnus Support.
+ 
+ ** NOTE: bfd.h and bfd-in2.h are GENERATED files.  Don't change them;
+ ** instead, change bfd-in.h or the other BFD source files processed to
+ ** generate these files.
+ 
+ This file is part of BFD, the Binary File Descriptor library.
+ 
+ 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 of the License, 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.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ /* bfd.h -- The only header file required by users of the bfd library 
+ 
+ The bfd.h file is generated from bfd-in.h and various .c files; if you
+ change it, your changes will probably be lost.
+ 
+ All the prototypes and definitions following the comment "THE FOLLOWING
+ IS EXTRACTED FROM THE SOURCE" are extracted from the source files for
+ BFD.  If you change it, someone oneday will extract it from the source
+ again, and your changes will be lost.  To save yourself from this bind,
+ change the definitions in the source in the bfd directory.  Type "make
+ docs" and then "make headers" in that directory, and magically this file
+ will change to reflect your changes.
+ 
+ If you don't have the tools to perform the extraction, then you are
+ safe from someone on your system trampling over your header files.
+ You should still maintain the equivalence between the source and this
+ file though; every change you make to the .c file should be reflected
+ here.  */
+ 
+ #ifndef __BFD_H_SEEN__
+ #define __BFD_H_SEEN__
+ 
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ 
+ #include "ansidecl.h"
+ 
+ /* These two lines get substitutions done by commands in Makefile.in.  */
+ #define BFD_VERSION  "2.9.5.0.22"
+ #define BFD_ARCH_SIZE 32
+ #define BFD_HOST_64BIT_LONG 0
+ #if 0
+ #define BFD_HOST_64_BIT 
+ #define BFD_HOST_U_64_BIT 
+ #endif
+ 
+ #if BFD_ARCH_SIZE >= 64
+ #define BFD64
+ #endif
+ 
+ #ifndef INLINE
+ #if __GNUC__ >= 2
+ #define INLINE __inline__
+ #else
+ #define INLINE
+ #endif
+ #endif
+ 
+ /* forward declaration */
+ typedef struct _bfd bfd;
+ 
+ /* To squelch erroneous compiler warnings ("illegal pointer
+    combination") from the SVR3 compiler, we would like to typedef
+    boolean to int (it doesn't like functions which return boolean.
+    Making sure they are never implicitly declared to return int
+    doesn't seem to help).  But this file is not configured based on
+    the host.  */
+ /* General rules: functions which are boolean return true on success
+    and false on failure (unless they're a predicate).   -- bfd.doc */
+ /* I'm sure this is going to break something and someone is going to
+    force me to change it. */
+ /* typedef enum boolean {false, true} boolean; */
+ /* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h>  -fnf */
+ /* It gets worse if the host also defines a true/false enum... -sts */
+ /* And even worse if your compiler has built-in boolean types... -law */
+ #if defined (__GNUG__) && (__GNUC_MINOR__ > 5)
+ #define TRUE_FALSE_ALREADY_DEFINED
+ #endif
+ #ifdef MPW
+ /* Pre-emptive strike - get the file with the enum. */
+ #include <Types.h>
+ #define TRUE_FALSE_ALREADY_DEFINED
+ #endif /* MPW */
+ #ifndef TRUE_FALSE_ALREADY_DEFINED
+ typedef enum bfd_boolean {false, true} boolean;
+ #define BFD_TRUE_FALSE
+ #else
+ /* Use enum names that will appear nowhere else.  */
+ typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+ #endif
+ 
+ /* A pointer to a position in a file.  */
+ /* FIXME:  This should be using off_t from <sys/types.h>.
+    For now, try to avoid breaking stuff by not including <sys/types.h> here.
+    This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+    Probably the best long-term answer is to avoid using file_ptr AND off_t 
+    in this header file, and to handle this in the BFD implementation
+    rather than in its interface.  */
+ /* typedef off_t	file_ptr; */
+ typedef long int file_ptr;
+ 
+ /* Support for different sizes of target format ints and addresses.
+    If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+    set to 1 above.  Otherwise, if gcc is being used, this code will
+    use gcc's "long long" type.  Otherwise, BFD_HOST_64_BIT must be
+    defined above.  */
+ 
+ #ifndef BFD_HOST_64_BIT
+ # if BFD_HOST_64BIT_LONG
+ #  define BFD_HOST_64_BIT long
+ #  define BFD_HOST_U_64_BIT unsigned long
+ # else
+ #  ifdef __GNUC__
+ #   if __GNUC__ >= 2
+ #    define BFD_HOST_64_BIT long long
+ #    define BFD_HOST_U_64_BIT unsigned long long
+ #   endif /* __GNUC__ >= 2 */
+ #  endif /* ! defined (__GNUC__) */
+ # endif /* ! BFD_HOST_64BIT_LONG */
+ #endif /* ! defined (BFD_HOST_64_BIT) */
+ 
+ #ifdef BFD64
+ 
+ #ifndef BFD_HOST_64_BIT
+  #error No 64 bit integer type available
+ #endif /* ! defined (BFD_HOST_64_BIT) */
+ 
+ typedef BFD_HOST_U_64_BIT bfd_vma;
+ typedef BFD_HOST_64_BIT bfd_signed_vma;
+ typedef BFD_HOST_U_64_BIT bfd_size_type;
+ typedef BFD_HOST_U_64_BIT symvalue;
+ 
+ #ifndef fprintf_vma
+ #if BFD_HOST_64BIT_LONG
+ #define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+ #define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+ #else
+ #define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+ #define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+ #define fprintf_vma(s,x) \
+   fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+ #define sprintf_vma(s,x) \
+   sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+ #endif
+ #endif
+ 
+ #else /* not BFD64  */
+ 
+ /* Represent a target address.  Also used as a generic unsigned type
+    which is guaranteed to be big enough to hold any arithmetic types
+    we need to deal with.  */
+ typedef unsigned long bfd_vma;
+ 
+ /* A generic signed type which is guaranteed to be big enough to hold any
+    arithmetic types we need to deal with.  Can be assumed to be compatible
+    with bfd_vma in the same way that signed and unsigned ints are compatible
+    (as parameters, in assignment, etc).  */
+ typedef long bfd_signed_vma;
+ 
+ typedef unsigned long symvalue;
+ typedef unsigned long bfd_size_type;
+ 
+ /* Print a bfd_vma x on stream s.  */
+ #define fprintf_vma(s,x) fprintf(s, "%08lx", x)
+ #define sprintf_vma(s,x) sprintf(s, "%08lx", x)
+ 
+ #endif /* not BFD64  */
+ 
+ #define printf_vma(x) fprintf_vma(stdout,x)
+ 
+ typedef unsigned int flagword;	/* 32 bits of flags */
+ typedef unsigned char bfd_byte;
+ 
+ /** File formats */
+ 
+ typedef enum bfd_format {
+ 	      bfd_unknown = 0,	/* file format is unknown */
+ 	      bfd_object,	/* linker/assember/compiler output */
+ 	      bfd_archive,	/* object archive file */
+ 	      bfd_core,		/* core dump */
+ 	      bfd_type_end}	/* marks the end; don't use it! */
+          bfd_format;
+ 
+ /* Values that may appear in the flags field of a BFD.  These also
+    appear in the object_flags field of the bfd_target structure, where
+    they indicate the set of flags used by that backend (not all flags
+    are meaningful for all object file formats) (FIXME: at the moment,
+    the object_flags values have mostly just been copied from backend
+    to another, and are not necessarily correct).  */
+ 
+ /* No flags.  */
+ #define BFD_NO_FLAGS   	0x00
+ 
+ /* BFD contains relocation entries.  */
+ #define HAS_RELOC   	0x01
+ 
+ /* BFD is directly executable.  */
+ #define EXEC_P      	0x02
+ 
+ /* BFD has line number information (basically used for F_LNNO in a
+    COFF header).  */
+ #define HAS_LINENO  	0x04
+ 
+ /* BFD has debugging information.  */
+ #define HAS_DEBUG   	0x08
+ 
+ /* BFD has symbols.  */
+ #define HAS_SYMS    	0x10
+ 
+ /* BFD has local symbols (basically used for F_LSYMS in a COFF
+    header).  */
+ #define HAS_LOCALS  	0x20
+ 
+ /* BFD is a dynamic object.  */
+ #define DYNAMIC     	0x40
+ 
+ /* Text section is write protected (if D_PAGED is not set, this is
+    like an a.out NMAGIC file) (the linker sets this by default, but
+    clears it for -r or -N).  */
+ #define WP_TEXT     	0x80
+ 
+ /* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the
+    linker sets this by default, but clears it for -r or -n or -N).  */
+ #define D_PAGED     	0x100
+ 
+ /* BFD is relaxable (this means that bfd_relax_section may be able to
+    do something) (sometimes bfd_relax_section can do something even if
+    this is not set).  */
+ #define BFD_IS_RELAXABLE 0x200
+ 
+ /* This may be set before writing out a BFD to request using a
+    traditional format.  For example, this is used to request that when
+    writing out an a.out object the symbols not be hashed to eliminate
+    duplicates.  */
+ #define BFD_TRADITIONAL_FORMAT 0x400
+ 
+ /* This flag indicates that the BFD contents are actually cached in
+    memory.  If this is set, iostream points to a bfd_in_memory struct.  */
+ #define BFD_IN_MEMORY 0x800
+ 
+ /* symbols and relocation */
+ 
+ /* A count of carsyms (canonical archive symbols).  */
+ typedef unsigned long symindex;
+ 
+ /* How to perform a relocation.  */
+ typedef const struct reloc_howto_struct reloc_howto_type;
+ 
+ #define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+ 
+ /* General purpose part of a symbol X;
+    target specific parts are in libcoff.h, libaout.h, etc.  */
+ 
+ #define bfd_get_section(x) ((x)->section)
+ #define bfd_get_output_section(x) ((x)->section->output_section)
+ #define bfd_set_section(x,y) ((x)->section) = (y)
+ #define bfd_asymbol_base(x) ((x)->section->vma)
+ #define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+ #define bfd_asymbol_name(x) ((x)->name)
+ /*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+ #define bfd_asymbol_bfd(x) ((x)->the_bfd)
+ #define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour)
+ 
+ /* A canonical archive symbol.  */
+ /* This is a type pun with struct ranlib on purpose! */
+ typedef struct carsym {
+   char *name;
+   file_ptr file_offset;		/* look here to find the file */
+ } carsym;			/* to make these you call a carsymogen */
+ 
+   
+ /* Used in generating armaps (archive tables of contents).
+    Perhaps just a forward definition would do? */
+ struct orl {			/* output ranlib */
+   char **name;			/* symbol name */ 
+   file_ptr pos;			/* bfd* or file position */
+   int namidx;			/* index into string table */
+ };
+ 
+ 
+ /* Linenumber stuff */
+ typedef struct lineno_cache_entry {
+   unsigned int line_number;	/* Linenumber from start of function*/  
+   union {
+     struct symbol_cache_entry *sym; /* Function name */
+     unsigned long offset;	/* Offset into section */
+   } u;
+ } alent;
+ 
+ /* object and core file sections */
+ 
+ #define	align_power(addr, align)	\
+ 	( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+ 
+ typedef struct sec *sec_ptr;
+ 
+ #define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+ #define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+ #define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+ #define bfd_section_name(bfd, ptr) ((ptr)->name)
+ #define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+ #define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+ #define bfd_section_lma(bfd, ptr) ((ptr)->lma)
+ #define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+ #define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+ #define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+ 
+ #define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+ 
+ #define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+ #define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+ #define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+ 
+ typedef struct stat stat_type; 
+ 
+ typedef enum bfd_print_symbol
+ { 
+   bfd_print_symbol_name,
+   bfd_print_symbol_more,
+   bfd_print_symbol_all
+ } bfd_print_symbol_type;
+     
+ /* Information about a symbol that nm needs.  */
+ 
+ typedef struct _symbol_info
+ {
+   symvalue value;
+   char type;
+   CONST char *name;            /* Symbol name.  */
+   unsigned char stab_type;     /* Stab type.  */
+   char stab_other;             /* Stab other. */
+   short stab_desc;             /* Stab desc.  */
+   CONST char *stab_name;       /* String for stab type.  */
+ } symbol_info;
+ 
+ /* Get the name of a stabs type code.  */
+ 
+ extern const char *bfd_get_stab_name PARAMS ((int));
+ 
+ /* Hash table routines.  There is no way to free up a hash table.  */
+ 
+ /* An element in the hash table.  Most uses will actually use a larger
+    structure, and an instance of this will be the first field.  */
+ 
+ struct bfd_hash_entry
+ {
+   /* Next entry for this hash code.  */
+   struct bfd_hash_entry *next;
+   /* String being hashed.  */
+   const char *string;
+   /* Hash code.  This is the full hash code, not the index into the
+      table.  */
+   unsigned long hash;
+ };
+ 
+ /* A hash table.  */
+ 
+ struct bfd_hash_table
+ {
+   /* The hash array.  */
+   struct bfd_hash_entry **table;
+   /* The number of slots in the hash table.  */
+   unsigned int size;
+   /* A function used to create new elements in the hash table.  The
+      first entry is itself a pointer to an element.  When this
+      function is first invoked, this pointer will be NULL.  However,
+      having the pointer permits a hierarchy of method functions to be
+      built each of which calls the function in the superclass.  Thus
+      each function should be written to allocate a new block of memory
+      only if the argument is NULL.  */
+   struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ 					     struct bfd_hash_table *,
+ 					     const char *));
+    /* An objalloc for this hash table.  This is a struct objalloc *,
+      but we use PTR to avoid requiring the inclusion of objalloc.h.  */
+   PTR memory;
+ };
+ 
+ /* Initialize a hash table.  */
+ extern boolean bfd_hash_table_init
+   PARAMS ((struct bfd_hash_table *,
+ 	   struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ 				       struct bfd_hash_table *,
+ 				       const char *)));
+ 
+ /* Initialize a hash table specifying a size.  */
+ extern boolean bfd_hash_table_init_n
+   PARAMS ((struct bfd_hash_table *,
+ 	   struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ 				       struct bfd_hash_table *,
+ 				       const char *),
+ 	   unsigned int size));
+ 
+ /* Free up a hash table.  */
+ extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *));
+ 
+ /* Look up a string in a hash table.  If CREATE is true, a new entry
+    will be created for this string if one does not already exist.  The
+    COPY argument must be true if this routine should copy the string
+    into newly allocated memory when adding an entry.  */
+ extern struct bfd_hash_entry *bfd_hash_lookup
+   PARAMS ((struct bfd_hash_table *, const char *, boolean create,
+ 	   boolean copy));
+ 
+ /* Replace an entry in a hash table.  */
+ extern void bfd_hash_replace
+   PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+ 	   struct bfd_hash_entry *nw));
+ 
+ /* Base method for creating a hash table entry.  */
+ extern struct bfd_hash_entry *bfd_hash_newfunc
+   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ 	   const char *));
+ 
+ /* Grab some space for a hash table entry.  */
+ extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *,
+ 				      unsigned int));
+ 
+ /* Traverse a hash table in a random order, calling a function on each
+    element.  If the function returns false, the traversal stops.  The
+    INFO argument is passed to the function.  */
+ extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *,
+ 				       boolean (*) (struct bfd_hash_entry *,
+ 						    PTR),
+ 				       PTR info));
+ 
+ /* Semi-portable string concatenation in cpp.
+    The CAT4 hack is to avoid a problem with some strict ANSI C preprocessors.
+    The problem is, "32_" is not a valid preprocessing token, and we don't
+    want extra underscores (e.g., "nlm_32_").  The XCAT2 macro will cause the
+    inner CAT macros to be evaluated first, producing still-valid pp-tokens.
+    Then the final concatenation can be done.  (Sigh.)  */
+ #ifndef CAT
+ #ifdef SABER
+ #define CAT(a,b)	a##b
+ #define CAT3(a,b,c)	a##b##c
+ #define CAT4(a,b,c,d)	a##b##c##d
+ #else
+ #if defined(__STDC__) || defined(ALMOST_STDC)
+ #define CAT(a,b) a##b
+ #define CAT3(a,b,c) a##b##c
+ #define XCAT2(a,b)	CAT(a,b)
+ #define CAT4(a,b,c,d)	XCAT2(CAT(a,b),CAT(c,d))
+ #else
+ #define CAT(a,b) a/**/b
+ #define CAT3(a,b,c) a/**/b/**/c
+ #define CAT4(a,b,c,d)	a/**/b/**/c/**/d
+ #endif
+ #endif
+ #endif
+ 
+ #define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+ 
+ /* User program access to BFD facilities */
+ 
+ /* Direct I/O routines, for programs which know more about the object
+    file than BFD does.  Use higher level routines if possible.  */
+ 
+ extern bfd_size_type bfd_read
+   PARAMS ((PTR, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
+ extern bfd_size_type bfd_write
+   PARAMS ((const PTR, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
+ extern int bfd_seek PARAMS ((bfd *abfd, file_ptr fp, int direction));
+ extern long bfd_tell PARAMS ((bfd *abfd));
+ extern int bfd_flush PARAMS ((bfd *abfd));
+ extern int bfd_stat PARAMS ((bfd *abfd, struct stat *));
+ 
+ 
+ /* Cast from const char * to char * so that caller can assign to
+    a char * without a warning.  */
+ #define bfd_get_filename(abfd) ((char *) (abfd)->filename)
+ #define bfd_get_cacheable(abfd) ((abfd)->cacheable)
+ #define bfd_get_format(abfd) ((abfd)->format)
+ #define bfd_get_target(abfd) ((abfd)->xvec->name)
+ #define bfd_get_flavour(abfd) ((abfd)->xvec->flavour)
+ #define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+ #define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+ #define bfd_header_big_endian(abfd) \
+   ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+ #define bfd_header_little_endian(abfd) \
+   ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+ #define bfd_get_file_flags(abfd) ((abfd)->flags)
+ #define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags)
+ #define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
+ #define bfd_my_archive(abfd) ((abfd)->my_archive)
+ #define bfd_has_map(abfd) ((abfd)->has_armap)
+ 
+ #define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+ #define bfd_usrdata(abfd) ((abfd)->usrdata)
+ 
+ #define bfd_get_start_address(abfd) ((abfd)->start_address)
+ #define bfd_get_symcount(abfd) ((abfd)->symcount)
+ #define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+ #define bfd_count_sections(abfd) ((abfd)->section_count)
+ 
+ #define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+ 
+ #define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean)(bool)), true)
+ 
+ extern boolean bfd_record_phdr
+   PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+ 	   boolean, boolean, unsigned int, struct sec **));
+ 
+ /* Byte swapping routines.  */
+ 
+ bfd_vma		bfd_getb64	   PARAMS ((const unsigned char *));
+ bfd_vma 	bfd_getl64	   PARAMS ((const unsigned char *));
+ bfd_signed_vma	bfd_getb_signed_64 PARAMS ((const unsigned char *));
+ bfd_signed_vma	bfd_getl_signed_64 PARAMS ((const unsigned char *));
+ bfd_vma		bfd_getb32	   PARAMS ((const unsigned char *));
+ bfd_vma		bfd_getl32	   PARAMS ((const unsigned char *));
+ bfd_signed_vma	bfd_getb_signed_32 PARAMS ((const unsigned char *));
+ bfd_signed_vma	bfd_getl_signed_32 PARAMS ((const unsigned char *));
+ bfd_vma		bfd_getb16	   PARAMS ((const unsigned char *));
+ bfd_vma		bfd_getl16	   PARAMS ((const unsigned char *));
+ bfd_signed_vma	bfd_getb_signed_16 PARAMS ((const unsigned char *));
+ bfd_signed_vma	bfd_getl_signed_16 PARAMS ((const unsigned char *));
+ void		bfd_putb64	   PARAMS ((bfd_vma, unsigned char *));
+ void		bfd_putl64	   PARAMS ((bfd_vma, unsigned char *));
+ void		bfd_putb32	   PARAMS ((bfd_vma, unsigned char *));
+ void		bfd_putl32	   PARAMS ((bfd_vma, unsigned char *));
+ void		bfd_putb16	   PARAMS ((bfd_vma, unsigned char *));
+ void		bfd_putl16	   PARAMS ((bfd_vma, unsigned char *));
+ 
+ /* Externally visible ECOFF routines.  */
+ 
+ #if defined(__STDC__) || defined(ALMOST_STDC)
+ struct ecoff_debug_info;
+ struct ecoff_debug_swap;
+ struct ecoff_extr;
+ struct symbol_cache_entry;
+ struct bfd_link_info;
+ struct bfd_link_hash_entry;
+ struct bfd_elf_version_tree;
+ #endif
+ extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd));
+ extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value));
+ extern boolean bfd_ecoff_set_regmasks
+   PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+ 	   unsigned long *cprmask));
+ extern PTR bfd_ecoff_debug_init
+   PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ 	   const struct ecoff_debug_swap *output_swap,
+ 	   struct bfd_link_info *));
+ extern void bfd_ecoff_debug_free
+   PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ 	   const struct ecoff_debug_swap *output_swap,
+ 	   struct bfd_link_info *));
+ extern boolean bfd_ecoff_debug_accumulate
+   PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ 	   const struct ecoff_debug_swap *output_swap,
+ 	   bfd *input_bfd, struct ecoff_debug_info *input_debug,
+ 	   const struct ecoff_debug_swap *input_swap,
+ 	   struct bfd_link_info *));
+ extern boolean bfd_ecoff_debug_accumulate_other
+   PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ 	   const struct ecoff_debug_swap *output_swap, bfd *input_bfd,
+ 	   struct bfd_link_info *));
+ extern boolean bfd_ecoff_debug_externals
+   PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ 	   const struct ecoff_debug_swap *swap,
+ 	   boolean relocateable,
+ 	   boolean (*get_extr) (struct symbol_cache_entry *,
+ 				struct ecoff_extr *),
+ 	   void (*set_index) (struct symbol_cache_entry *,
+ 			      bfd_size_type)));
+ extern boolean bfd_ecoff_debug_one_external
+   PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ 	   const struct ecoff_debug_swap *swap,
+ 	   const char *name, struct ecoff_extr *esym));
+ extern bfd_size_type bfd_ecoff_debug_size
+   PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ 	   const struct ecoff_debug_swap *swap));
+ extern boolean bfd_ecoff_write_debug
+   PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ 	   const struct ecoff_debug_swap *swap, file_ptr where));
+ extern boolean bfd_ecoff_write_accumulated_debug
+   PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug,
+ 	   const struct ecoff_debug_swap *swap,
+ 	   struct bfd_link_info *info, file_ptr where));
+ extern boolean bfd_mips_ecoff_create_embedded_relocs
+   PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ 	   char **));
+ 
+ /* Externally visible ELF routines.  */
+ 
+ struct bfd_link_needed_list
+ {
+   struct bfd_link_needed_list *next;
+   bfd *by;
+   const char *name;
+ };
+ 
+ extern boolean bfd_elf32_record_link_assignment
+   PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+ extern boolean bfd_elf64_record_link_assignment
+   PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+ extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+   PARAMS ((bfd *, struct bfd_link_info *));
+ extern boolean bfd_elf_get_bfd_needed_list
+   PARAMS ((bfd *, struct bfd_link_needed_list **));
+ extern boolean bfd_elf32_size_dynamic_sections
+   PARAMS ((bfd *, const char *, const char *, boolean, const char *,
+ 	   const char * const *, struct bfd_link_info *, struct sec **,
+ 	   struct bfd_elf_version_tree *));
+ extern boolean bfd_elf64_size_dynamic_sections
+   PARAMS ((bfd *, const char *, const char *, boolean, const char *,
+ 	   const char * const *, struct bfd_link_info *, struct sec **,
+ 	   struct bfd_elf_version_tree *));
+ extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+ extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+ 
+ /* SunOS shared library support routines for the linker.  */
+ 
+ extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+   PARAMS ((bfd *, struct bfd_link_info *));
+ extern boolean bfd_sunos_record_link_assignment
+   PARAMS ((bfd *, struct bfd_link_info *, const char *));
+ extern boolean bfd_sunos_size_dynamic_sections
+   PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **,
+ 	   struct sec **));
+ 
+ /* Linux shared library support routines for the linker.  */
+ 
+ extern boolean bfd_i386linux_size_dynamic_sections
+   PARAMS ((bfd *, struct bfd_link_info *));
+ extern boolean bfd_m68klinux_size_dynamic_sections
+   PARAMS ((bfd *, struct bfd_link_info *));
+ extern boolean bfd_sparclinux_size_dynamic_sections
+   PARAMS ((bfd *, struct bfd_link_info *));
+ 
+ /* mmap hacks */
+ 
+ struct _bfd_window_internal;
+ typedef struct _bfd_window_internal bfd_window_internal;
+ 
+ typedef struct _bfd_window {
+   /* What the user asked for.  */
+   PTR data;
+   bfd_size_type size;
+   /* The actual window used by BFD.  Small user-requested read-only
+      regions sharing a page may share a single window into the object
+      file.  Read-write versions shouldn't until I've fixed things to
+      keep track of which portions have been claimed by the
+      application; don't want to give the same region back when the
+      application wants two writable copies!  */
+   struct _bfd_window_internal *i;
+ } bfd_window;
+ 
+ extern void bfd_init_window PARAMS ((bfd_window *));
+ extern void bfd_free_window PARAMS ((bfd_window *));
+ extern boolean bfd_get_file_window
+   PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+ 
+ /* XCOFF support routines for the linker.  */
+ 
+ extern boolean bfd_xcoff_link_record_set
+   PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ 	   bfd_size_type));
+ extern boolean bfd_xcoff_import_symbol
+   PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ 	   bfd_vma, const char *, const char *, const char *));
+ extern boolean bfd_xcoff_export_symbol
+   PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ 	   boolean));
+ extern boolean bfd_xcoff_link_count_reloc
+   PARAMS ((bfd *, struct bfd_link_info *, const char *));
+ extern boolean bfd_xcoff_record_link_assignment
+   PARAMS ((bfd *, struct bfd_link_info *, const char *));
+ extern boolean bfd_xcoff_size_dynamic_sections
+   PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+ 	   unsigned long, unsigned long, unsigned long, boolean,
+ 	   int, boolean, boolean, struct sec **));
+ 
+ /* Externally visible COFF routines.  */
+ 
+ #if defined(__STDC__) || defined(ALMOST_STDC)
+ struct internal_syment;
+ union internal_auxent;
+ #endif
+ 
+ extern boolean bfd_coff_get_syment
+   PARAMS ((bfd *, struct symbol_cache_entry *, struct internal_syment *));
+ 
+ extern boolean bfd_coff_get_auxent
+   PARAMS ((bfd *, struct symbol_cache_entry *, int, union internal_auxent *));
+ 
+ extern boolean bfd_coff_set_symbol_class
+   PARAMS ((bfd *, struct symbol_cache_entry *, unsigned int));
+ 
+ /* ARM Interworking support.  Called from linker.  */
+ extern boolean bfd_arm_allocate_interworking_sections
+   PARAMS ((struct bfd_link_info *));
+ 
+ extern boolean bfd_arm_process_before_allocation
+   PARAMS ((bfd *, struct bfd_link_info *, int));
+ 
+ extern boolean bfd_arm_get_bfd_for_interworking
+   PARAMS ((bfd *, struct bfd_link_info *));
+ 
+ /* ELF ARM Interworking support.  Called from linker.  */
+ extern boolean bfd_elf32_arm_allocate_interworking_sections
+   PARAMS ((struct bfd_link_info *));
+ 
+ extern boolean bfd_elf32_arm_process_before_allocation
+   PARAMS ((bfd *, struct bfd_link_info *, int));
+ 
+ extern boolean bfd_elf32_arm_get_bfd_for_interworking
+   PARAMS ((bfd *, struct bfd_link_info *));
+ 
+ /* And more from the source.  */
+ void 
+ bfd_init PARAMS ((void));
+ 
+ bfd *
+ bfd_openr PARAMS ((CONST char *filename, CONST char *target));
+ 
+ bfd *
+ bfd_fdopenr PARAMS ((CONST char *filename, CONST char *target, int fd));
+ 
+ bfd *
+ bfd_openstreamr PARAMS ((const char *, const char *, PTR));
+ 
+ bfd *
+ bfd_openw PARAMS ((CONST char *filename, CONST char *target));
+ 
+ boolean 
+ bfd_close PARAMS ((bfd *abfd));
+ 
+ boolean 
+ bfd_close_all_done PARAMS ((bfd *));
+ 
+ bfd *
+ bfd_create PARAMS ((CONST char *filename, bfd *templ));
+ 
+ boolean 
+ bfd_make_writable PARAMS ((bfd *abfd));
+ 
+ boolean 
+ bfd_make_readable PARAMS ((bfd *abfd));
+ 
+ 
+  /* Byte swapping macros for user section data.  */
+ 
+ #define bfd_put_8(abfd, val, ptr) \
+                 ((void) (*((unsigned char *)(ptr)) = (unsigned char)(val)))
+ #define bfd_put_signed_8 \
+                bfd_put_8
+ #define bfd_get_8(abfd, ptr) \
+                 (*(unsigned char *)(ptr))
+ #define bfd_get_signed_8(abfd, ptr) \
+                ((*(unsigned char *)(ptr) ^ 0x80) - 0x80)
+ 
+ #define bfd_put_16(abfd, val, ptr) \
+                 BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+ #define bfd_put_signed_16 \
+                 bfd_put_16
+ #define bfd_get_16(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_getx16, (ptr))
+ #define bfd_get_signed_16(abfd, ptr) \
+                 BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+ 
+ #define bfd_put_32(abfd, val, ptr) \
+                 BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+ #define bfd_put_signed_32 \
+                 bfd_put_32
+ #define bfd_get_32(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_getx32, (ptr))
+ #define bfd_get_signed_32(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+ 
+ #define bfd_put_64(abfd, val, ptr) \
+                 BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+ #define bfd_put_signed_64 \
+                 bfd_put_64
+ #define bfd_get_64(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_getx64, (ptr))
+ #define bfd_get_signed_64(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+ 
+ #define bfd_get(bits, abfd, ptr)                               \
+                 ((bits) == 8 ? bfd_get_8 (abfd, ptr)           \
+                 : (bits) == 16 ? bfd_get_16 (abfd, ptr)        \
+                 : (bits) == 32 ? bfd_get_32 (abfd, ptr)        \
+                 : (bits) == 64 ? bfd_get_64 (abfd, ptr)        \
+                 : (abort (), (bfd_vma) - 1))
+ 
+ #define bfd_put(bits, abfd, val, ptr)                          \
+                 ((bits) == 8 ? bfd_put_8 (abfd, val, ptr)      \
+                 : (bits) == 16 ? bfd_put_16 (abfd, val, ptr)   \
+                 : (bits) == 32 ? bfd_put_32 (abfd, val, ptr)   \
+                 : (bits) == 64 ? bfd_put_64 (abfd, val, ptr)   \
+                 : (abort (), (void) 0))
+ 
+ 
+  /* Byte swapping macros for file header data.  */
+ 
+ #define bfd_h_put_8(abfd, val, ptr) \
+                bfd_put_8 (abfd, val, ptr)
+ #define bfd_h_put_signed_8(abfd, val, ptr) \
+                bfd_put_8 (abfd, val, ptr)
+ #define bfd_h_get_8(abfd, ptr) \
+                bfd_get_8 (abfd, ptr)
+ #define bfd_h_get_signed_8(abfd, ptr) \
+                bfd_get_signed_8 (abfd, ptr)
+ 
+ #define bfd_h_put_16(abfd, val, ptr) \
+                 BFD_SEND(abfd, bfd_h_putx16,(val,ptr))
+ #define bfd_h_put_signed_16 \
+                 bfd_h_put_16
+ #define bfd_h_get_16(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_h_getx16,(ptr))
+ #define bfd_h_get_signed_16(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_h_getx_signed_16, (ptr))
+ 
+ #define bfd_h_put_32(abfd, val, ptr) \
+                 BFD_SEND(abfd, bfd_h_putx32,(val,ptr))
+ #define bfd_h_put_signed_32 \
+                 bfd_h_put_32
+ #define bfd_h_get_32(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_h_getx32,(ptr))
+ #define bfd_h_get_signed_32(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_h_getx_signed_32, (ptr))
+ 
+ #define bfd_h_put_64(abfd, val, ptr) \
+                 BFD_SEND(abfd, bfd_h_putx64,(val, ptr))
+ #define bfd_h_put_signed_64 \
+                 bfd_h_put_64
+ #define bfd_h_get_64(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_h_getx64,(ptr))
+ #define bfd_h_get_signed_64(abfd, ptr) \
+                 BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr))
+ 
+   /* This structure is used for a comdat section, as in PE.  A comdat
+     section is associated with a particular symbol.  When the linker
+     sees a comdat section, it keeps only one of the sections with a
+     given name and associated with a given symbol. */
+ 
+ struct bfd_comdat_info
+ {
+    /* The name of the symbol associated with a comdat section.  */
+   const char *name;
+ 
+    /* The local symbol table index of the symbol associated with a
+      comdat section.  This is only meaningful to the object file format
+      specific code; it is not an index into the list returned by
+      bfd_canonicalize_symtab.  */
+   long symbol;
+ 
+    /* If this section is being discarded, the linker uses this field
+      to point to the input section which is being kept.  */
+   struct sec *sec;
+ };
+ 
+ typedef struct sec
+ {
+          /* The name of the section; the name isn't a copy, the pointer is
+         the same as that passed to bfd_make_section. */
+ 
+     CONST char *name;
+ 
+          /* Which section is it; 0..nth.      */
+ 
+    int index;
+ 
+          /* The next section in the list belonging to the BFD, or NULL. */
+ 
+     struct sec *next;
+ 
+          /* The field flags contains attributes of the section. Some
+            flags are read in from the object file, and some are
+            synthesized from other information.  */
+ 
+     flagword flags;
+ 
+ #define SEC_NO_FLAGS   0x000
+ 
+          /* Tells the OS to allocate space for this section when loading.
+            This is clear for a section containing debug information
+            only. */
+ #define SEC_ALLOC      0x001
+ 
+          /* Tells the OS to load the section from the file when loading.
+            This is clear for a .bss section. */
+ #define SEC_LOAD       0x002
+ 
+          /* The section contains data still to be relocated, so there is
+            some relocation information too. */
+ #define SEC_RELOC      0x004
+ 
+ #if 0    /* Obsolete ? */
+ #define SEC_BALIGN     0x008
+ #endif
+ 
+          /* A signal to the OS that the section contains read only
+           data. */
+ #define SEC_READONLY   0x010
+ 
+          /* The section contains code only. */
+ #define SEC_CODE       0x020
+ 
+          /* The section contains data only. */
+ #define SEC_DATA       0x040
+ 
+          /* The section will reside in ROM. */
+ #define SEC_ROM        0x080
+ 
+          /* The section contains constructor information. This section
+            type is used by the linker to create lists of constructors and
+            destructors used by <<g++>>. When a back end sees a symbol
+            which should be used in a constructor list, it creates a new
+            section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
+            the symbol to it, and builds a relocation. To build the lists
+            of constructors, all the linker has to do is catenate all the
+            sections called <<__CTOR_LIST__>> and relocate the data
+            contained within - exactly the operations it would peform on
+            standard data. */
+ #define SEC_CONSTRUCTOR 0x100
+ 
+          /* The section is a constructor, and should be placed at the
+           end of the text, data, or bss section(?). */
+ #define SEC_CONSTRUCTOR_TEXT 0x1100
+ #define SEC_CONSTRUCTOR_DATA 0x2100
+ #define SEC_CONSTRUCTOR_BSS  0x3100
+ 
+          /* The section has contents - a data section could be
+            <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+            <<SEC_HAS_CONTENTS>> */
+ #define SEC_HAS_CONTENTS 0x200
+ 
+          /* An instruction to the linker to not output the section
+            even if it has information which would normally be written. */
+ #define SEC_NEVER_LOAD 0x400
+ 
+          /* The section is a COFF shared library section.  This flag is
+            only for the linker.  If this type of section appears in
+            the input file, the linker must copy it to the output file
+            without changing the vma or size.  FIXME: Although this
+            was originally intended to be general, it really is COFF
+            specific (and the flag was renamed to indicate this).  It
+            might be cleaner to have some more general mechanism to
+            allow the back end to control what the linker does with
+            sections. */
+ #define SEC_COFF_SHARED_LIBRARY 0x800
+ 
+          /* The section contains common symbols (symbols may be defined
+            multiple times, the value of a symbol is the amount of
+            space it requires, and the largest symbol value is the one
+            used).  Most targets have exactly one of these (which we
+            translate to bfd_com_section_ptr), but ECOFF has two. */
+ #define SEC_IS_COMMON 0x8000
+ 
+          /* The section contains only debugging information.  For
+            example, this is set for ELF .debug and .stab sections.
+            strip tests this flag to see if a section can be
+            discarded. */
+ #define SEC_DEBUGGING 0x10000
+ 
+          /* The contents of this section are held in memory pointed to
+            by the contents field.  This is checked by
+            bfd_get_section_contents, and the data is retrieved from
+            memory if appropriate.  */
+ #define SEC_IN_MEMORY 0x20000
+ 
+          /* The contents of this section are to be excluded by the
+            linker for executable and shared objects unless those
+            objects are to be further relocated.  */
+ #define SEC_EXCLUDE 0x40000
+ 
+         /* The contents of this section are to be sorted by the
+           based on the address specified in the associated symbol
+           table.  */
+ #define SEC_SORT_ENTRIES 0x80000
+ 
+         /* When linking, duplicate sections of the same name should be
+           discarded, rather than being combined into a single section as
+           is usually done.  This is similar to how common symbols are
+           handled.  See SEC_LINK_DUPLICATES below.  */
+ #define SEC_LINK_ONCE 0x100000
+ 
+         /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+           should handle duplicate sections.  */
+ #define SEC_LINK_DUPLICATES 0x600000
+ 
+         /* This value for SEC_LINK_DUPLICATES means that duplicate
+           sections with the same name should simply be discarded. */
+ #define SEC_LINK_DUPLICATES_DISCARD 0x0
+ 
+         /* This value for SEC_LINK_DUPLICATES means that the linker
+           should warn if there are any duplicate sections, although
+           it should still only link one copy.  */
+ #define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000
+ 
+         /* This value for SEC_LINK_DUPLICATES means that the linker
+           should warn if any duplicate sections are a different size.  */
+ #define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000
+ 
+         /* This value for SEC_LINK_DUPLICATES means that the linker
+           should warn if any duplicate sections contain different
+           contents.  */
+ #define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000
+ 
+         /* This section was created by the linker as part of dynamic
+           relocation or other arcane processing.  It is skipped when
+           going through the first-pass output, trusting that someone
+           else up the line will take care of it later.  */
+ #define SEC_LINKER_CREATED 0x800000
+ 
+         /* This section should not be subject to garbage collection.  */
+ #define SEC_KEEP 0x1000000
+ 
+         /* This section contains "short" data, and should be placed
+           "near" the GP.  */
+ #define SEC_SMALL_DATA 0x2000000
+ 
+         /* This section contains data which may be shared with other
+           executables or shared objects.  */
+ #define SEC_SHARED 0x4000000
+ 
+         /*  End of section flags.  */
+ 
+         /* Some internal packed boolean fields.  */
+ 
+         /* See the vma field.  */
+        unsigned int user_set_vma : 1;
+ 
+         /* Whether relocations have been processed.  */
+        unsigned int reloc_done : 1;
+ 
+         /* A mark flag used by some of the linker backends.  */
+        unsigned int linker_mark : 1;
+ 
+         /* A mark flag used by some linker backends for garbage collection.  */
+        unsigned int gc_mark : 1;
+ 
+         /* End of internal packed boolean fields.  */
+ 
+         /*  The virtual memory address of the section - where it will be
+            at run time.  The symbols are relocated against this.  The
+            user_set_vma flag is maintained by bfd; if it's not set, the
+            backend can assign addresses (for example, in <<a.out>>, where
+            the default address for <<.data>> is dependent on the specific
+            target and various flags).  */
+ 
+    bfd_vma vma;
+ 
+         /*  The load address of the section - where it would be in a
+            rom image; really only used for writing section header
+            information. */
+ 
+    bfd_vma lma;
+ 
+          /* The size of the section in bytes, as it will be output.
+            contains a value even if the section has no contents (e.g., the
+            size of <<.bss>>). This will be filled in after relocation */
+ 
+    bfd_size_type _cooked_size;
+ 
+          /* The original size on disk of the section, in bytes.  Normally this
+            value is the same as the size, but if some relaxing has
+            been done, then this value will be bigger.  */
+ 
+    bfd_size_type _raw_size;
+ 
+          /* If this section is going to be output, then this value is the
+            offset into the output section of the first byte in the input
+            section. E.g., if this was going to start at the 100th byte in
+            the output section, this value would be 100. */
+ 
+    bfd_vma output_offset;
+ 
+          /* The output section through which to map on output. */
+ 
+    struct sec *output_section;
+ 
+          /* The alignment requirement of the section, as an exponent of 2 -
+            e.g., 3 aligns to 2^3 (or 8). */
+ 
+    unsigned int alignment_power;
+ 
+          /* If an input section, a pointer to a vector of relocation
+            records for the data in this section. */
+ 
+    struct reloc_cache_entry *relocation;
+ 
+          /* If an output section, a pointer to a vector of pointers to
+            relocation records for the data in this section. */
+ 
+    struct reloc_cache_entry **orelocation;
+ 
+          /* The number of relocation records in one of the above  */
+ 
+    unsigned reloc_count;
+ 
+          /* Information below is back end specific - and not always used
+            or updated.  */
+ 
+          /* File position of section data    */
+ 
+    file_ptr filepos;
+ 
+          /* File position of relocation info */
+ 
+    file_ptr rel_filepos;
+ 
+          /* File position of line data       */
+ 
+    file_ptr line_filepos;
+ 
+          /* Pointer to data for applications */
+ 
+    PTR userdata;
+ 
+          /* If the SEC_IN_MEMORY flag is set, this points to the actual
+            contents.  */
+    unsigned char *contents;
+ 
+          /* Attached line number information */
+ 
+    alent *lineno;
+ 
+          /* Number of line number records   */
+ 
+    unsigned int lineno_count;
+ 
+          /* Optional information about a COMDAT entry; NULL if not COMDAT */
+ 
+    struct bfd_comdat_info *comdat;
+ 
+          /* When a section is being output, this value changes as more
+            linenumbers are written out */
+ 
+    file_ptr moving_line_filepos;
+ 
+          /* What the section number is in the target world  */
+ 
+    int target_index;
+ 
+    PTR used_by_bfd;
+ 
+          /* If this is a constructor section then here is a list of the
+            relocations created to relocate items within it. */
+ 
+    struct relent_chain *constructor_chain;
+ 
+          /* The BFD which owns the section. */
+ 
+    bfd *owner;
+ 
+          /* A symbol which points at this section only */
+    struct symbol_cache_entry *symbol;
+    struct symbol_cache_entry **symbol_ptr_ptr;
+ 
+    struct bfd_link_order *link_order_head;
+    struct bfd_link_order *link_order_tail;
+ } asection ;
+ 
+      /* These sections are global, and are managed by BFD.  The application
+        and target back end are not permitted to change the values in
+        these sections.  New code should use the section_ptr macros rather
+        than referring directly to the const sections.  The const sections
+        may eventually vanish.  */
+ #define BFD_ABS_SECTION_NAME "*ABS*"
+ #define BFD_UND_SECTION_NAME "*UND*"
+ #define BFD_COM_SECTION_NAME "*COM*"
+ #define BFD_IND_SECTION_NAME "*IND*"
+ 
+      /* the absolute section */
+ extern const asection bfd_abs_section;
+ #define bfd_abs_section_ptr ((asection *) &bfd_abs_section)
+ #define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
+      /* Pointer to the undefined section */
+ extern const asection bfd_und_section;
+ #define bfd_und_section_ptr ((asection *) &bfd_und_section)
+ #define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
+      /* Pointer to the common section */
+ extern const asection bfd_com_section;
+ #define bfd_com_section_ptr ((asection *) &bfd_com_section)
+      /* Pointer to the indirect section */
+ extern const asection bfd_ind_section;
+ #define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+ #define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+ 
+ extern const struct symbol_cache_entry * const bfd_abs_symbol;
+ extern const struct symbol_cache_entry * const bfd_com_symbol;
+ extern const struct symbol_cache_entry * const bfd_und_symbol;
+ extern const struct symbol_cache_entry * const bfd_ind_symbol;
+ #define bfd_get_section_size_before_reloc(section) \
+      (section->reloc_done ? (abort(),1): (section)->_raw_size)
+ #define bfd_get_section_size_after_reloc(section) \
+      ((section->reloc_done) ? (section)->_cooked_size: (abort(),1))
+ asection *
+ bfd_get_section_by_name PARAMS ((bfd *abfd, CONST char *name));
+ 
+ asection *
+ bfd_make_section_old_way PARAMS ((bfd *abfd, CONST char *name));
+ 
+ asection *
+ bfd_make_section_anyway PARAMS ((bfd *abfd, CONST char *name));
+ 
+ asection *
+ bfd_make_section PARAMS ((bfd *, CONST char *name));
+ 
+ boolean 
+ bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags));
+ 
+ void 
+ bfd_map_over_sections PARAMS ((bfd *abfd,
+     void (*func)(bfd *abfd,
+     asection *sect,
+     PTR obj),
+     PTR obj));
+ 
+ boolean 
+ bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val));
+ 
+ boolean 
+ bfd_set_section_contents
+  PARAMS ((bfd *abfd,
+     asection *section,
+     PTR data,
+     file_ptr offset,
+     bfd_size_type count));
+ 
+ boolean 
+ bfd_get_section_contents
+  PARAMS ((bfd *abfd, asection *section, PTR location,
+     file_ptr offset, bfd_size_type count));
+ 
+ boolean 
+ bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec, bfd *obfd, asection *osec));
+ 
+ #define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \
+      BFD_SEND (obfd, _bfd_copy_private_section_data, \
+                (ibfd, isection, obfd, osection))
+ void 
+ _bfd_strip_section_from_output
+  PARAMS ((asection *section));
+ 
+ enum bfd_architecture 
+ {
+   bfd_arch_unknown,    /* File arch not known */
+   bfd_arch_obscure,    /* Arch known, not one of these */
+   bfd_arch_m68k,       /* Motorola 68xxx */
+ #define bfd_mach_m68000 1
+ #define bfd_mach_m68008 2
+ #define bfd_mach_m68010 3
+ #define bfd_mach_m68020 4
+ #define bfd_mach_m68030 5
+ #define bfd_mach_m68040 6
+ #define bfd_mach_m68060 7
+ #define bfd_mach_cpu32  8
+   bfd_arch_vax,        /* DEC Vax */   
+   bfd_arch_i960,       /* Intel 960 */
+      /* The order of the following is important.
+        lower number indicates a machine type that 
+        only accepts a subset of the instructions
+        available to machines with higher numbers.
+        The exception is the "ca", which is
+        incompatible with all other machines except 
+        "core". */
+ 
+ #define bfd_mach_i960_core      1
+ #define bfd_mach_i960_ka_sa     2
+ #define bfd_mach_i960_kb_sb     3
+ #define bfd_mach_i960_mc        4
+ #define bfd_mach_i960_xa        5
+ #define bfd_mach_i960_ca        6
+ #define bfd_mach_i960_jx        7
+ #define bfd_mach_i960_hx        8
+ 
+   bfd_arch_a29k,       /* AMD 29000 */
+   bfd_arch_sparc,      /* SPARC */
+ #define bfd_mach_sparc                 1
+  /* The difference between v8plus and v9 is that v9 is a true 64 bit env.  */
+ #define bfd_mach_sparc_sparclet        2
+ #define bfd_mach_sparc_sparclite       3
+ #define bfd_mach_sparc_v8plus          4
+ #define bfd_mach_sparc_v8plusa         5  /* with ultrasparc add'ns */
+ #define bfd_mach_sparc_sparclite_le    6
+ #define bfd_mach_sparc_v9              7
+ #define bfd_mach_sparc_v9a             8  /* with ultrasparc add'ns */
+  /* Nonzero if MACH has the v9 instruction set.  */
+ #define bfd_mach_sparc_v9_p(mach) \
+   ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9a)
+   bfd_arch_mips,       /* MIPS Rxxxx */
+ #define bfd_mach_mips3000              3000
+ #define bfd_mach_mips3900              3900
+ #define bfd_mach_mips4000              4000
+ #define bfd_mach_mips4010              4010
+ #define bfd_mach_mips4100              4100
+ #define bfd_mach_mips4111              4111
+ #define bfd_mach_mips4300              4300
+ #define bfd_mach_mips4400              4400
+ #define bfd_mach_mips4600              4600
+ #define bfd_mach_mips4650              4650
+ #define bfd_mach_mips5000              5000
+ #define bfd_mach_mips6000              6000
+ #define bfd_mach_mips8000              8000
+ #define bfd_mach_mips10000             10000
+ #define bfd_mach_mips16                16
+   bfd_arch_i386,       /* Intel 386 */
+ #define bfd_mach_i386_i386 0
+ #define bfd_mach_i386_i8086 1
+ #define bfd_mach_i386_i386_intel_syntax 2
+   bfd_arch_we32k,      /* AT&T WE32xxx */
+   bfd_arch_tahoe,      /* CCI/Harris Tahoe */
+   bfd_arch_i860,       /* Intel 860 */
+   bfd_arch_i370,       /* IBM 360/370 Mainframes */
+   bfd_arch_romp,       /* IBM ROMP PC/RT */
+   bfd_arch_alliant,    /* Alliant */
+   bfd_arch_convex,     /* Convex */
+   bfd_arch_m88k,       /* Motorola 88xxx */
+   bfd_arch_pyramid,    /* Pyramid Technology */
+   bfd_arch_h8300,      /* Hitachi H8/300 */
+ #define bfd_mach_h8300   1
+ #define bfd_mach_h8300h  2
+ #define bfd_mach_h8300s  3
+   bfd_arch_powerpc,    /* PowerPC */
+   bfd_arch_rs6000,     /* IBM RS/6000 */
+   bfd_arch_hppa,       /* HP PA RISC */
+   bfd_arch_d10v,       /* Mitsubishi D10V */
+ #define bfd_mach_d10v          0
+ #define bfd_mach_d10v_ts2      2
+ #define bfd_mach_d10v_ts3      3
+   bfd_arch_d30v,       /* Mitsubishi D30V */
+   bfd_arch_z8k,        /* Zilog Z8000 */
+ #define bfd_mach_z8001         1
+ #define bfd_mach_z8002         2
+   bfd_arch_h8500,      /* Hitachi H8/500 */
+   bfd_arch_sh,         /* Hitachi SH */
+ #define bfd_mach_sh            0
+ #define bfd_mach_sh3        0x30
+ #define bfd_mach_sh3e       0x3e
+   bfd_arch_alpha,      /* Dec Alpha */
+ #define bfd_mach_alpha_ev4  0x10
+ #define bfd_mach_alpha_ev5  0x20
+ #define bfd_mach_alpha_ev6  0x30
+   bfd_arch_arm,        /* Advanced Risc Machines ARM */
+ #define bfd_mach_arm_2         1
+ #define bfd_mach_arm_2a        2
+ #define bfd_mach_arm_3         3
+ #define bfd_mach_arm_3M        4
+ #define bfd_mach_arm_4         5
+ #define bfd_mach_arm_4T        6
+ #define bfd_mach_arm_5         7
+ #define bfd_mach_arm_5T        8
+   bfd_arch_ns32k,      /* National Semiconductors ns32000 */
+   bfd_arch_w65,        /* WDC 65816 */
+   bfd_arch_tic30,      /* Texas Instruments TMS320C30 */
+   bfd_arch_tic80,      /* TI TMS320c80 (MVP) */
+   bfd_arch_v850,       /* NEC V850 */
+ #define bfd_mach_v850          0
+ #define bfd_mach_v850e         'E'
+ #define bfd_mach_v850ea        'A'
+   bfd_arch_arc,        /* Argonaut RISC Core */
+ #define bfd_mach_arc_base 0
+   bfd_arch_m32r,       /* Mitsubishi M32R/D */
+ #define bfd_mach_m32r          0  /* backwards compatibility */
+ #define bfd_mach_m32rx         'x'
+   bfd_arch_mn10200,    /* Matsushita MN10200 */
+   bfd_arch_mn10300,    /* Matsushita MN10300 */
+ #define bfd_mach_mn10300               300
+ #define bfd_mach_am33          330
+   bfd_arch_fr30,
+ #define bfd_mach_fr30          0x46523330
+   bfd_arch_mcore,
+   bfd_arch_pj,
+   bfd_arch_last
+   };
+ 
+ typedef struct bfd_arch_info 
+ {
+   int bits_per_word;
+   int bits_per_address;
+   int bits_per_byte;
+   enum bfd_architecture arch;
+   unsigned long mach;
+   const char *arch_name;
+   const char *printable_name;
+   unsigned int section_align_power;
+   /* true if this is the default machine for the architecture */
+   boolean the_default; 
+   const struct bfd_arch_info * (*compatible)
+        PARAMS ((const struct bfd_arch_info *a,
+                 const struct bfd_arch_info *b));
+ 
+   boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+ 
+   const struct bfd_arch_info *next;
+ } bfd_arch_info_type;
+ const char *
+ bfd_printable_name PARAMS ((bfd *abfd));
+ 
+ const bfd_arch_info_type *
+ bfd_scan_arch PARAMS ((const char *string));
+ 
+ const char **
+ bfd_arch_list PARAMS ((void));
+ 
+ const bfd_arch_info_type *
+ bfd_arch_get_compatible PARAMS ((
+     const bfd *abfd,
+     const bfd *bbfd));
+ 
+ void 
+ bfd_set_arch_info PARAMS ((bfd *abfd, const bfd_arch_info_type *arg));
+ 
+ enum bfd_architecture 
+ bfd_get_arch PARAMS ((bfd *abfd));
+ 
+ unsigned long 
+ bfd_get_mach PARAMS ((bfd *abfd));
+ 
+ unsigned int 
+ bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+ 
+ unsigned int 
+ bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+ 
+ const bfd_arch_info_type * 
+ bfd_get_arch_info PARAMS ((bfd *abfd));
+ 
+ const bfd_arch_info_type *
+ bfd_lookup_arch
+  PARAMS ((enum bfd_architecture
+     arch,
+     unsigned long machine));
+ 
+ const char *
+ bfd_printable_arch_mach
+  PARAMS ((enum bfd_architecture arch, unsigned long machine));
+ 
+ typedef enum bfd_reloc_status
+ {
+         /* No errors detected */
+   bfd_reloc_ok,
+ 
+         /* The relocation was performed, but there was an overflow. */
+   bfd_reloc_overflow,
+ 
+         /* The address to relocate was not within the section supplied. */
+   bfd_reloc_outofrange,
+ 
+         /* Used by special functions */
+   bfd_reloc_continue,
+ 
+         /* Unsupported relocation size requested. */
+   bfd_reloc_notsupported,
+ 
+         /* Unused */
+   bfd_reloc_other,
+ 
+         /* The symbol to relocate against was undefined. */
+   bfd_reloc_undefined,
+ 
+         /* The relocation was performed, but may not be ok - presently
+           generated only when linking i960 coff files with i960 b.out
+           symbols.  If this type is returned, the error_message argument
+           to bfd_perform_relocation will be set.  */
+   bfd_reloc_dangerous
+  }
+  bfd_reloc_status_type;
+ 
+ 
+ typedef struct reloc_cache_entry
+ {
+         /* A pointer into the canonical table of pointers  */
+   struct symbol_cache_entry **sym_ptr_ptr;
+ 
+         /* offset in section */
+   bfd_size_type address;
+ 
+         /* addend for relocation value */
+   bfd_vma addend;
+ 
+         /* Pointer to how to perform the required relocation */
+   reloc_howto_type *howto;
+ 
+ } arelent;
+ enum complain_overflow
+ {
+         /* Do not complain on overflow. */
+   complain_overflow_dont,
+ 
+         /* Complain if the bitfield overflows, whether it is considered
+           as signed or unsigned. */
+   complain_overflow_bitfield,
+ 
+         /* Complain if the value overflows when considered as signed
+           number. */
+   complain_overflow_signed,
+ 
+         /* Complain if the value overflows when considered as an
+           unsigned number. */
+   complain_overflow_unsigned
+ };
+ 
+ struct reloc_howto_struct
+ {
+         /*  The type field has mainly a documentary use - the back end can
+            do what it wants with it, though normally the back end's
+            external idea of what a reloc number is stored
+            in this field. For example, a PC relative word relocation
+            in a coff environment has the type 023 - because that's
+            what the outside world calls a R_PCRWORD reloc. */
+   unsigned int type;
+ 
+         /*  The value the final relocation is shifted right by. This drops
+            unwanted data from the relocation.  */
+   unsigned int rightshift;
+ 
+         /*  The size of the item to be relocated.  This is *not* a
+            power-of-two measure.  To get the number of bytes operated
+            on by a type of relocation, use bfd_get_reloc_size.  */
+   int size;
+ 
+         /*  The number of bits in the item to be relocated.  This is used
+            when doing overflow checking.  */
+   unsigned int bitsize;
+ 
+         /*  Notes that the relocation is relative to the location in the
+            data section of the addend. The relocation function will
+            subtract from the relocation value the address of the location
+            being relocated. */
+   boolean pc_relative;
+ 
+         /*  The bit position of the reloc value in the destination.
+            The relocated value is left shifted by this amount. */
+   unsigned int bitpos;
+ 
+         /* What type of overflow error should be checked for when
+           relocating. */
+   enum complain_overflow complain_on_overflow;
+ 
+         /* If this field is non null, then the supplied function is
+           called rather than the normal function. This allows really
+           strange relocation methods to be accomodated (e.g., i960 callj
+           instructions). */
+   bfd_reloc_status_type (*special_function)
+                                    PARAMS ((bfd *abfd,
+                                             arelent *reloc_entry,
+                                             struct symbol_cache_entry *symbol,
+                                             PTR data,
+                                             asection *input_section,
+                                             bfd *output_bfd,
+                                             char **error_message));
+ 
+         /* The textual name of the relocation type. */
+   char *name;
+ 
+         /* When performing a partial link, some formats must modify the
+           relocations rather than the data - this flag signals this.*/
+   boolean partial_inplace;
+ 
+         /* The src_mask selects which parts of the read in data
+           are to be used in the relocation sum.  E.g., if this was an 8 bit
+           bit of data which we read and relocated, this would be
+           0x000000ff. When we have relocs which have an addend, such as
+           sun4 extended relocs, the value in the offset part of a
+           relocating field is garbage so we never use it. In this case
+           the mask would be 0x00000000. */
+   bfd_vma src_mask;
+ 
+         /* The dst_mask selects which parts of the instruction are replaced
+           into the instruction. In most cases src_mask == dst_mask,
+           except in the above special case, where dst_mask would be
+           0x000000ff, and src_mask would be 0x00000000.   */
+   bfd_vma dst_mask;
+ 
+         /* When some formats create PC relative instructions, they leave
+           the value of the pc of the place being relocated in the offset
+           slot of the instruction, so that a PC relative relocation can
+           be made just by adding in an ordinary offset (e.g., sun3 a.out).
+           Some formats leave the displacement part of an instruction
+           empty (e.g., m88k bcs); this flag signals the fact.*/
+   boolean pcrel_offset;
+ 
+ };
+ #define HOWTO(C, R,S,B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+   {(unsigned)C,R,S,B, P, BI, O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC}
+ #define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN)
+ 
+ #define EMPTY_HOWTO(C) \
+   HOWTO((C),0,0,0,false,0,complain_overflow_dont,NULL,NULL,false,0,0,false)
+ 
+ #define HOWTO_PREPARE(relocation, symbol)      \
+   {                                            \
+   if (symbol != (asymbol *)NULL) {             \
+     if (bfd_is_com_section (symbol->section)) { \
+       relocation = 0;                          \
+     }                                          \
+     else {                                     \
+       relocation = symbol->value;              \
+     }                                          \
+   }                                            \
+ }
+ unsigned int 
+ bfd_get_reloc_size  PARAMS ((reloc_howto_type *));
+ 
+ typedef struct relent_chain {
+   arelent relent;
+   struct   relent_chain *next;
+ } arelent_chain;
+ bfd_reloc_status_type
+ 
+ bfd_check_overflow
+  PARAMS ((enum complain_overflow how,
+     unsigned int bitsize,
+     unsigned int rightshift,
+     unsigned int addrsize,
+     bfd_vma relocation));
+ 
+ bfd_reloc_status_type
+ 
+ bfd_perform_relocation
+  PARAMS ((bfd *abfd,
+     arelent *reloc_entry,
+     PTR data,
+     asection *input_section,
+     bfd *output_bfd,
+     char **error_message));
+ 
+ bfd_reloc_status_type
+ 
+ bfd_install_relocation
+  PARAMS ((bfd *abfd,
+     arelent *reloc_entry,
+     PTR data, bfd_vma data_start,
+     asection *input_section,
+     char **error_message));
+ 
+ enum bfd_reloc_code_real {
+   _dummy_first_bfd_reloc_code_real,
+ 
+ 
+ /* Basic absolute relocations of N bits. */
+   BFD_RELOC_64,
+   BFD_RELOC_32,
+   BFD_RELOC_26,
+   BFD_RELOC_24,
+   BFD_RELOC_16,
+   BFD_RELOC_14,
+   BFD_RELOC_8,
+ 
+ /* PC-relative relocations.  Sometimes these are relative to the address
+ of the relocation itself; sometimes they are relative to the start of
+ the section containing the relocation.  It depends on the specific target.
+ 
+ The 24-bit relocation is used in some Intel 960 configurations. */
+   BFD_RELOC_64_PCREL,
+   BFD_RELOC_32_PCREL,
+   BFD_RELOC_24_PCREL,
+   BFD_RELOC_16_PCREL,
+   BFD_RELOC_12_PCREL,
+   BFD_RELOC_8_PCREL,
+ 
+ /* For ELF. */
+   BFD_RELOC_32_GOT_PCREL,
+   BFD_RELOC_16_GOT_PCREL,
+   BFD_RELOC_8_GOT_PCREL,
+   BFD_RELOC_32_GOTOFF,
+   BFD_RELOC_16_GOTOFF,
+   BFD_RELOC_LO16_GOTOFF,
+   BFD_RELOC_HI16_GOTOFF,
+   BFD_RELOC_HI16_S_GOTOFF,
+   BFD_RELOC_8_GOTOFF,
+   BFD_RELOC_32_PLT_PCREL,
+   BFD_RELOC_24_PLT_PCREL,
+   BFD_RELOC_16_PLT_PCREL,
+   BFD_RELOC_8_PLT_PCREL,
+   BFD_RELOC_32_PLTOFF,
+   BFD_RELOC_16_PLTOFF,
+   BFD_RELOC_LO16_PLTOFF,
+   BFD_RELOC_HI16_PLTOFF,
+   BFD_RELOC_HI16_S_PLTOFF,
+   BFD_RELOC_8_PLTOFF,
+ 
+ /* Relocations used by 68K ELF. */
+   BFD_RELOC_68K_GLOB_DAT,
+   BFD_RELOC_68K_JMP_SLOT,
+   BFD_RELOC_68K_RELATIVE,
+ 
+ /* Linkage-table relative. */
+   BFD_RELOC_32_BASEREL,
+   BFD_RELOC_16_BASEREL,
+   BFD_RELOC_LO16_BASEREL,
+   BFD_RELOC_HI16_BASEREL,
+   BFD_RELOC_HI16_S_BASEREL,
+   BFD_RELOC_8_BASEREL,
+   BFD_RELOC_RVA,
+ 
+ /* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */
+   BFD_RELOC_8_FFnn,
+ 
+ /* These PC-relative relocations are stored as word displacements --
+ i.e., byte displacements shifted right two bits.  The 30-bit word
+ displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+ SPARC.  (SPARC tools generally refer to this as <<WDISP30>>.)  The
+ signed 16-bit displacement is used on the MIPS, and the 23-bit
+ displacement is used on the Alpha. */
+   BFD_RELOC_32_PCREL_S2,
+   BFD_RELOC_16_PCREL_S2,
+   BFD_RELOC_23_PCREL_S2,
+ 
+ /* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+ the target word.  These are used on the SPARC. */
+   BFD_RELOC_HI22,
+   BFD_RELOC_LO10,
+ 
+ /* For systems that allocate a Global Pointer register, these are
+ displacements off that register.  These relocation types are
+ handled specially, because the value the register will have is
+ decided relatively late. */
+   BFD_RELOC_GPREL16,
+   BFD_RELOC_GPREL32,
+ 
+ /* Reloc types used for i960/b.out. */
+   BFD_RELOC_I960_CALLJ,
+ 
+ /* SPARC ELF relocations.  There is probably some overlap with other
+ relocation types already defined. */
+   BFD_RELOC_NONE,
+   BFD_RELOC_SPARC_WDISP22,
+   BFD_RELOC_SPARC22,
+   BFD_RELOC_SPARC13,
+   BFD_RELOC_SPARC_GOT10,
+   BFD_RELOC_SPARC_GOT13,
+   BFD_RELOC_SPARC_GOT22,
+   BFD_RELOC_SPARC_PC10,
+   BFD_RELOC_SPARC_PC22,
+   BFD_RELOC_SPARC_WPLT30,
+   BFD_RELOC_SPARC_COPY,
+   BFD_RELOC_SPARC_GLOB_DAT,
+   BFD_RELOC_SPARC_JMP_SLOT,
+   BFD_RELOC_SPARC_RELATIVE,
+   BFD_RELOC_SPARC_UA32,
+ 
+ /* I think these are specific to SPARC a.out (e.g., Sun 4). */
+   BFD_RELOC_SPARC_BASE13,
+   BFD_RELOC_SPARC_BASE22,
+ 
+ /* SPARC64 relocations */
+ #define BFD_RELOC_SPARC_64 BFD_RELOC_64
+   BFD_RELOC_SPARC_10,
+   BFD_RELOC_SPARC_11,
+   BFD_RELOC_SPARC_OLO10,
+   BFD_RELOC_SPARC_HH22,
+   BFD_RELOC_SPARC_HM10,
+   BFD_RELOC_SPARC_LM22,
+   BFD_RELOC_SPARC_PC_HH22,
+   BFD_RELOC_SPARC_PC_HM10,
+   BFD_RELOC_SPARC_PC_LM22,
+   BFD_RELOC_SPARC_WDISP16,
+   BFD_RELOC_SPARC_WDISP19,
+   BFD_RELOC_SPARC_7,
+   BFD_RELOC_SPARC_6,
+   BFD_RELOC_SPARC_5,
+ #define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+   BFD_RELOC_SPARC_PLT64,
+   BFD_RELOC_SPARC_HIX22,
+   BFD_RELOC_SPARC_LOX10,
+   BFD_RELOC_SPARC_H44,
+   BFD_RELOC_SPARC_M44,
+   BFD_RELOC_SPARC_L44,
+   BFD_RELOC_SPARC_REGISTER,
+ 
+ /* SPARC little endian relocation */
+   BFD_RELOC_SPARC_REV32,
+ 
+ /* Alpha ECOFF and ELF relocations.  Some of these treat the symbol or
+ "addend" in some special way.
+ For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
+ writing; when reading, it will be the absolute section symbol.  The
+ addend is the displacement in bytes of the "lda" instruction from
+ the "ldah" instruction (which is at the address of this reloc). */
+   BFD_RELOC_ALPHA_GPDISP_HI16,
+ 
+ /* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
+ with GPDISP_HI16 relocs.  The addend is ignored when writing the
+ relocations out, and is filled in with the file's GP value on
+ reading, for convenience. */
+   BFD_RELOC_ALPHA_GPDISP_LO16,
+ 
+ /* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16
+ relocation except that there is no accompanying GPDISP_LO16
+ relocation. */
+   BFD_RELOC_ALPHA_GPDISP,
+ 
+ /* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
+ the assembler turns it into a LDQ instruction to load the address of
+ the symbol, and then fills in a register in the real instruction.
+ 
+ The LITERAL reloc, at the LDQ instruction, refers to the .lita
+ section symbol.  The addend is ignored when writing, but is filled
+ in with the file's GP value on reading, for convenience, as with the
+ GPDISP_LO16 reloc.
+ 
+ The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16.
+ It should refer to the symbol to be referenced, as with 16_GOTOFF,
+ but it generates output not based on the position within the .got
+ section, but relative to the GP value chosen for the file during the
+ final link stage.
+ 
+ The LITUSE reloc, on the instruction using the loaded address, gives
+ information to the linker that it might be able to use to optimize
+ away some literal section references.  The symbol is ignored (read
+ as the absolute section symbol), and the "addend" indicates the type
+ of instruction using the register:
+ 1 - "memory" fmt insn
+ 2 - byte-manipulation (byte offset reg)
+ 3 - jsr (target of branch)
+ 
+ The GNU linker currently doesn't do any of this optimizing. */
+   BFD_RELOC_ALPHA_LITERAL,
+   BFD_RELOC_ALPHA_ELF_LITERAL,
+   BFD_RELOC_ALPHA_LITUSE,
+ 
+ /* The BFD_RELOC_ALPHA_USER_* relocations are used by the assembler to
+ process the explicit !<reloc>!sequence relocations, and are mapped
+ into the normal relocations at the end of processing. */
+   BFD_RELOC_ALPHA_USER_LITERAL,
+   BFD_RELOC_ALPHA_USER_LITUSE_BASE,
+   BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF,
+   BFD_RELOC_ALPHA_USER_LITUSE_JSR,
+   BFD_RELOC_ALPHA_USER_GPDISP,
+   BFD_RELOC_ALPHA_USER_GPRELHIGH,
+   BFD_RELOC_ALPHA_USER_GPRELLOW,
+ 
+ /* The HINT relocation indicates a value that should be filled into the
+ "hint" field of a jmp/jsr/ret instruction, for possible branch-
+ prediction logic which may be provided on some processors. */
+   BFD_RELOC_ALPHA_HINT,
+ 
+ /* The LINKAGE relocation outputs a linkage pair in the object file,
+ which is filled by the linker. */
+   BFD_RELOC_ALPHA_LINKAGE,
+ 
+ /* The CODEADDR relocation outputs a STO_CA in the object file,
+ which is filled by the linker. */
+   BFD_RELOC_ALPHA_CODEADDR,
+ 
+ /* Bits 27..2 of the relocation address shifted right 2 bits;
+ simple reloc otherwise. */
+   BFD_RELOC_MIPS_JMP,
+ 
+ /* The MIPS16 jump instruction. */
+   BFD_RELOC_MIPS16_JMP,
+ 
+ /* MIPS16 GP relative reloc. */
+   BFD_RELOC_MIPS16_GPREL,
+ 
+ /* High 16 bits of 32-bit value; simple reloc. */
+   BFD_RELOC_HI16,
+ 
+ /* High 16 bits of 32-bit value but the low 16 bits will be sign
+ extended and added to form the final result.  If the low 16
+ bits form a negative number, we need to add one to the high value
+ to compensate for the borrow when the low bits are added. */
+   BFD_RELOC_HI16_S,
+ 
+ /* Low 16 bits. */
+   BFD_RELOC_LO16,
+ 
+ /* Like BFD_RELOC_HI16_S, but PC relative. */
+   BFD_RELOC_PCREL_HI16_S,
+ 
+ /* Like BFD_RELOC_LO16, but PC relative. */
+   BFD_RELOC_PCREL_LO16,
+ 
+ /* Relocation relative to the global pointer. */
+ #define BFD_RELOC_MIPS_GPREL BFD_RELOC_GPREL16
+ 
+ /* Relocation against a MIPS literal section. */
+   BFD_RELOC_MIPS_LITERAL,
+ 
+ /* MIPS ELF relocations. */
+   BFD_RELOC_MIPS_GOT16,
+   BFD_RELOC_MIPS_CALL16,
+ #define BFD_RELOC_MIPS_GPREL32 BFD_RELOC_GPREL32
+   BFD_RELOC_MIPS_GOT_HI16,
+   BFD_RELOC_MIPS_GOT_LO16,
+   BFD_RELOC_MIPS_CALL_HI16,
+   BFD_RELOC_MIPS_CALL_LO16,
+   BFD_RELOC_MIPS_SUB,
+   BFD_RELOC_MIPS_GOT_PAGE,
+   BFD_RELOC_MIPS_GOT_OFST,
+   BFD_RELOC_MIPS_GOT_DISP,
+ 
+ 
+ /* i386/elf relocations */
+   BFD_RELOC_386_GOT32,
+   BFD_RELOC_386_PLT32,
+   BFD_RELOC_386_COPY,
+   BFD_RELOC_386_GLOB_DAT,
+   BFD_RELOC_386_JUMP_SLOT,
+   BFD_RELOC_386_RELATIVE,
+   BFD_RELOC_386_GOTOFF,
+   BFD_RELOC_386_GOTPC,
+ 
+ /* ns32k relocations */
+   BFD_RELOC_NS32K_IMM_8,
+   BFD_RELOC_NS32K_IMM_16,
+   BFD_RELOC_NS32K_IMM_32,
+   BFD_RELOC_NS32K_IMM_8_PCREL,
+   BFD_RELOC_NS32K_IMM_16_PCREL,
+   BFD_RELOC_NS32K_IMM_32_PCREL,
+   BFD_RELOC_NS32K_DISP_8,
+   BFD_RELOC_NS32K_DISP_16,
+   BFD_RELOC_NS32K_DISP_32,
+   BFD_RELOC_NS32K_DISP_8_PCREL,
+   BFD_RELOC_NS32K_DISP_16_PCREL,
+   BFD_RELOC_NS32K_DISP_32_PCREL,
+ 
+ /* Picojava relocs.  Not all of these appear in object files. */
+   BFD_RELOC_PJ_CODE_HI16,
+   BFD_RELOC_PJ_CODE_LO16,
+   BFD_RELOC_PJ_CODE_DIR16,
+   BFD_RELOC_PJ_CODE_DIR32,
+   BFD_RELOC_PJ_CODE_REL16,
+   BFD_RELOC_PJ_CODE_REL32,
+ 
+ /* Power(rs6000) and PowerPC relocations. */
+   BFD_RELOC_PPC_B26,
+   BFD_RELOC_PPC_BA26,
+   BFD_RELOC_PPC_TOC16,
+   BFD_RELOC_PPC_B16,
+   BFD_RELOC_PPC_B16_BRTAKEN,
+   BFD_RELOC_PPC_B16_BRNTAKEN,
+   BFD_RELOC_PPC_BA16,
+   BFD_RELOC_PPC_BA16_BRTAKEN,
+   BFD_RELOC_PPC_BA16_BRNTAKEN,
+   BFD_RELOC_PPC_COPY,
+   BFD_RELOC_PPC_GLOB_DAT,
+   BFD_RELOC_PPC_JMP_SLOT,
+   BFD_RELOC_PPC_RELATIVE,
+   BFD_RELOC_PPC_LOCAL24PC,
+   BFD_RELOC_PPC_EMB_NADDR32,
+   BFD_RELOC_PPC_EMB_NADDR16,
+   BFD_RELOC_PPC_EMB_NADDR16_LO,
+   BFD_RELOC_PPC_EMB_NADDR16_HI,
+   BFD_RELOC_PPC_EMB_NADDR16_HA,
+   BFD_RELOC_PPC_EMB_SDAI16,
+   BFD_RELOC_PPC_EMB_SDA2I16,
+   BFD_RELOC_PPC_EMB_SDA2REL,
+   BFD_RELOC_PPC_EMB_SDA21,
+   BFD_RELOC_PPC_EMB_MRKREF,
+   BFD_RELOC_PPC_EMB_RELSEC16,
+   BFD_RELOC_PPC_EMB_RELST_LO,
+   BFD_RELOC_PPC_EMB_RELST_HI,
+   BFD_RELOC_PPC_EMB_RELST_HA,
+   BFD_RELOC_PPC_EMB_BIT_FLD,
+   BFD_RELOC_PPC_EMB_RELSDA,
+ 
+ /* Instruction 370/390 relocations */
+   BFD_RELOC_I370_D12,
+ 
+ /* The type of reloc used to build a contructor table - at the moment
+ probably a 32 bit wide absolute relocation, but the target can choose.
+ It generally does map to one of the other relocation types. */
+   BFD_RELOC_CTOR,
+ 
+ /* ARM 26 bit pc-relative branch.  The lowest two bits must be zero and are
+ not stored in the instruction. */
+   BFD_RELOC_ARM_PCREL_BRANCH,
+ 
+ /* These relocs are only used within the ARM assembler.  They are not
+ (at present) written to any object files. */
+   BFD_RELOC_ARM_IMMEDIATE,
+   BFD_RELOC_ARM_ADRL_IMMEDIATE,
+   BFD_RELOC_ARM_OFFSET_IMM,
+   BFD_RELOC_ARM_SHIFT_IMM,
+   BFD_RELOC_ARM_SWI,
+   BFD_RELOC_ARM_MULTI,
+   BFD_RELOC_ARM_CP_OFF_IMM,
+   BFD_RELOC_ARM_ADR_IMM,
+   BFD_RELOC_ARM_LDR_IMM,
+   BFD_RELOC_ARM_LITERAL,
+   BFD_RELOC_ARM_IN_POOL,
+   BFD_RELOC_ARM_OFFSET_IMM8,
+   BFD_RELOC_ARM_HWLITERAL,
+   BFD_RELOC_ARM_THUMB_ADD,
+   BFD_RELOC_ARM_THUMB_IMM,
+   BFD_RELOC_ARM_THUMB_SHIFT,
+   BFD_RELOC_ARM_THUMB_OFFSET,
+   BFD_RELOC_ARM_GOT12,
+   BFD_RELOC_ARM_GOT32,
+   BFD_RELOC_ARM_JUMP_SLOT,
+   BFD_RELOC_ARM_COPY,
+   BFD_RELOC_ARM_GLOB_DAT,
+   BFD_RELOC_ARM_PLT32,
+   BFD_RELOC_ARM_RELATIVE,
+   BFD_RELOC_ARM_GOTOFF,
+   BFD_RELOC_ARM_GOTPC,
+ 
+ /* Hitachi SH relocs.  Not all of these appear in object files. */
+   BFD_RELOC_SH_PCDISP8BY2,
+   BFD_RELOC_SH_PCDISP12BY2,
+   BFD_RELOC_SH_IMM4,
+   BFD_RELOC_SH_IMM4BY2,
+   BFD_RELOC_SH_IMM4BY4,
+   BFD_RELOC_SH_IMM8,
+   BFD_RELOC_SH_IMM8BY2,
+   BFD_RELOC_SH_IMM8BY4,
+   BFD_RELOC_SH_PCRELIMM8BY2,
+   BFD_RELOC_SH_PCRELIMM8BY4,
+   BFD_RELOC_SH_SWITCH16,
+   BFD_RELOC_SH_SWITCH32,
+   BFD_RELOC_SH_USES,
+   BFD_RELOC_SH_COUNT,
+   BFD_RELOC_SH_ALIGN,
+   BFD_RELOC_SH_CODE,
+   BFD_RELOC_SH_DATA,
+   BFD_RELOC_SH_LABEL,
+ 
+ /* Thumb 23-, 12- and 9-bit pc-relative branches.  The lowest bit must
+ be zero and is not stored in the instruction. */
+   BFD_RELOC_THUMB_PCREL_BRANCH9,
+   BFD_RELOC_THUMB_PCREL_BRANCH12,
+   BFD_RELOC_THUMB_PCREL_BRANCH23,
+ 
+ /* Argonaut RISC Core (ARC) relocs.
+ ARC 22 bit pc-relative branch.  The lowest two bits must be zero and are
+ not stored in the instruction.  The high 20 bits are installed in bits 26
+ through 7 of the instruction. */
+   BFD_RELOC_ARC_B22_PCREL,
+ 
+ /* ARC 26 bit absolute branch.  The lowest two bits must be zero and are not
+ stored in the instruction.  The high 24 bits are installed in bits 23
+ through 0. */
+   BFD_RELOC_ARC_B26,
+ 
+ /* Mitsubishi D10V relocs.
+ This is a 10-bit reloc with the right 2 bits
+ assumed to be 0. */
+   BFD_RELOC_D10V_10_PCREL_R,
+ 
+ /* Mitsubishi D10V relocs.
+ This is a 10-bit reloc with the right 2 bits
+ assumed to be 0.  This is the same as the previous reloc
+ except it is in the left container, i.e.,
+ shifted left 15 bits. */
+   BFD_RELOC_D10V_10_PCREL_L,
+ 
+ /* This is an 18-bit reloc with the right 2 bits
+ assumed to be 0. */
+   BFD_RELOC_D10V_18,
+ 
+ /* This is an 18-bit reloc with the right 2 bits
+ assumed to be 0. */
+   BFD_RELOC_D10V_18_PCREL,
+ 
+ /* Mitsubishi D30V relocs.
+ This is a 6-bit absolute reloc. */
+   BFD_RELOC_D30V_6,
+ 
+ /* This is a 6-bit pc-relative reloc with 
+ the right 3 bits assumed to be 0. */
+   BFD_RELOC_D30V_9_PCREL,
+ 
+ /* This is a 6-bit pc-relative reloc with 
+ the right 3 bits assumed to be 0. Same
+ as the previous reloc but on the right side
+ of the container. */
+   BFD_RELOC_D30V_9_PCREL_R,
+ 
+ /* This is a 12-bit absolute reloc with the 
+ right 3 bitsassumed to be 0. */
+   BFD_RELOC_D30V_15,
+ 
+ /* This is a 12-bit pc-relative reloc with 
+ the right 3 bits assumed to be 0. */
+   BFD_RELOC_D30V_15_PCREL,
+ 
+ /* This is a 12-bit pc-relative reloc with 
+ the right 3 bits assumed to be 0. Same
+ as the previous reloc but on the right side
+ of the container. */
+   BFD_RELOC_D30V_15_PCREL_R,
+ 
+ /* This is an 18-bit absolute reloc with 
+ the right 3 bits assumed to be 0. */
+   BFD_RELOC_D30V_21,
+ 
+ /* This is an 18-bit pc-relative reloc with 
+ the right 3 bits assumed to be 0. */
+   BFD_RELOC_D30V_21_PCREL,
+ 
+ /* This is an 18-bit pc-relative reloc with 
+ the right 3 bits assumed to be 0. Same
+ as the previous reloc but on the right side
+ of the container. */
+   BFD_RELOC_D30V_21_PCREL_R,
+ 
+ /* This is a 32-bit absolute reloc. */
+   BFD_RELOC_D30V_32,
+ 
+ /* This is a 32-bit pc-relative reloc. */
+   BFD_RELOC_D30V_32_PCREL,
+ 
+ /* Mitsubishi M32R relocs.
+ This is a 24 bit absolute address. */
+   BFD_RELOC_M32R_24,
+ 
+ /* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */
+   BFD_RELOC_M32R_10_PCREL,
+ 
+ /* This is an 18-bit reloc with the right 2 bits assumed to be 0. */
+   BFD_RELOC_M32R_18_PCREL,
+ 
+ /* This is a 26-bit reloc with the right 2 bits assumed to be 0. */
+   BFD_RELOC_M32R_26_PCREL,
+ 
+ /* This is a 16-bit reloc containing the high 16 bits of an address
+ used when the lower 16 bits are treated as unsigned. */
+   BFD_RELOC_M32R_HI16_ULO,
+ 
+ /* This is a 16-bit reloc containing the high 16 bits of an address
+ used when the lower 16 bits are treated as signed. */
+   BFD_RELOC_M32R_HI16_SLO,
+ 
+ /* This is a 16-bit reloc containing the lower 16 bits of an address. */
+   BFD_RELOC_M32R_LO16,
+ 
+ /* This is a 16-bit reloc containing the small data area offset for use in
+ add3, load, and store instructions. */
+   BFD_RELOC_M32R_SDA16,
+ 
+ /* This is a 9-bit reloc */
+   BFD_RELOC_V850_9_PCREL,
+ 
+ /* This is a 22-bit reloc */
+   BFD_RELOC_V850_22_PCREL,
+ 
+ /* This is a 16 bit offset from the short data area pointer. */
+   BFD_RELOC_V850_SDA_16_16_OFFSET,
+ 
+ /* This is a 16 bit offset (of which only 15 bits are used) from the
+ short data area pointer. */
+   BFD_RELOC_V850_SDA_15_16_OFFSET,
+ 
+ /* This is a 16 bit offset from the zero data area pointer. */
+   BFD_RELOC_V850_ZDA_16_16_OFFSET,
+ 
+ /* This is a 16 bit offset (of which only 15 bits are used) from the
+ zero data area pointer. */
+   BFD_RELOC_V850_ZDA_15_16_OFFSET,
+ 
+ /* This is an 8 bit offset (of which only 6 bits are used) from the
+ tiny data area pointer. */
+   BFD_RELOC_V850_TDA_6_8_OFFSET,
+ 
+ /* This is an 8bit offset (of which only 7 bits are used) from the tiny
+ data area pointer. */
+   BFD_RELOC_V850_TDA_7_8_OFFSET,
+ 
+ /* This is a 7 bit offset from the tiny data area pointer. */
+   BFD_RELOC_V850_TDA_7_7_OFFSET,
+ 
+ /* This is a 16 bit offset from the tiny data area pointer. */
+   BFD_RELOC_V850_TDA_16_16_OFFSET,
+ 
+ /* This is a 5 bit offset (of which only 4 bits are used) from the tiny
+ data area pointer. */
+   BFD_RELOC_V850_TDA_4_5_OFFSET,
+ 
+ /* This is a 4 bit offset from the tiny data area pointer. */
+   BFD_RELOC_V850_TDA_4_4_OFFSET,
+ 
+ /* This is a 16 bit offset from the short data area pointer, with the
+ bits placed non-contigously in the instruction. */
+   BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET,
+ 
+ /* This is a 16 bit offset from the zero data area pointer, with the
+ bits placed non-contigously in the instruction. */
+   BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET,
+ 
+ /* This is a 6 bit offset from the call table base pointer. */
+   BFD_RELOC_V850_CALLT_6_7_OFFSET,
+ 
+ /* This is a 16 bit offset from the call table base pointer. */
+   BFD_RELOC_V850_CALLT_16_16_OFFSET,
+ 
+ 
+ /* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
+ instruction. */
+   BFD_RELOC_MN10300_32_PCREL,
+ 
+ /* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the
+ instruction. */
+   BFD_RELOC_MN10300_16_PCREL,
+ 
+ /* This is a 8bit DP reloc for the tms320c30, where the most
+ significant 8 bits of a 24 bit word are placed into the least
+ significant 8 bits of the opcode. */
+   BFD_RELOC_TIC30_LDP,
+ 
+ /* This is a 48 bit reloc for the FR30 that stores 32 bits. */
+   BFD_RELOC_FR30_48,
+ 
+ /* This is a 32 bit reloc for the FR30 that stores 20 bits split up into
+ two sections. */
+   BFD_RELOC_FR30_20,
+ 
+ /* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in
+ 4 bits. */
+   BFD_RELOC_FR30_6_IN_4,
+ 
+ /* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset
+ into 8 bits. */
+   BFD_RELOC_FR30_8_IN_8,
+ 
+ /* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset
+ into 8 bits. */
+   BFD_RELOC_FR30_9_IN_8,
+ 
+ /* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset
+ into 8 bits. */
+   BFD_RELOC_FR30_10_IN_8,
+ 
+ /* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative
+ short offset into 8 bits. */
+   BFD_RELOC_FR30_9_PCREL,
+ 
+ /* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative
+ short offset into 11 bits. */
+   BFD_RELOC_FR30_12_PCREL,
+ 
+ /* Motorola Mcore relocations. */
+   BFD_RELOC_MCORE_PCREL_IMM8BY4,
+   BFD_RELOC_MCORE_PCREL_IMM11BY2,
+   BFD_RELOC_MCORE_PCREL_IMM4BY2,
+   BFD_RELOC_MCORE_PCREL_32,
+   BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2,
+   BFD_RELOC_MCORE_RVA,
+ 
+ /* These two relocations are used by the linker to determine which of 
+ the entries in a C++ virtual function table are actually used.  When
+ the --gc-sections option is given, the linker will zero out the entries
+ that are not used, so that the code for those functions need not be
+ included in the output.
+ 
+ VTABLE_INHERIT is a zero-space relocation used to describe to the
+ linker the inheritence tree of a C++ virtual function table.  The
+ relocation's symbol should be the parent class' vtable, and the
+ relocation should be located at the child vtable.
+ 
+ VTABLE_ENTRY is a zero-space relocation that describes the use of a
+ virtual function table entry.  The reloc's symbol should refer to the
+ table of the class mentioned in the code.  Off of that base, an offset
+ describes the entry that is being used.  For Rela hosts, this offset 
+ is stored in the reloc's addend.  For Rel hosts, we are forced to put
+ this offset in the reloc's section offset. */
+   BFD_RELOC_VTABLE_INHERIT,
+   BFD_RELOC_VTABLE_ENTRY,
+   BFD_RELOC_UNUSED };
+ typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+ reloc_howto_type *
+ 
+ bfd_reloc_type_lookup  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+ 
+ const char *
+ bfd_get_reloc_code_name  PARAMS ((bfd_reloc_code_real_type code));
+ 
+ 
+ typedef struct symbol_cache_entry
+ {
+         /* A pointer to the BFD which owns the symbol. This information
+           is necessary so that a back end can work out what additional
+           information (invisible to the application writer) is carried
+           with the symbol.
+ 
+           This field is *almost* redundant, since you can use section->owner
+           instead, except that some symbols point to the global sections
+           bfd_{abs,com,und}_section.  This could be fixed by making
+           these globals be per-bfd (or per-target-flavor).  FIXME. */
+ 
+   struct _bfd *the_bfd;  /* Use bfd_asymbol_bfd(sym) to access this field. */
+ 
+         /* The text of the symbol. The name is left alone, and not copied; the
+           application may not alter it. */
+   CONST char *name;
+ 
+         /* The value of the symbol.  This really should be a union of a
+           numeric value with a pointer, since some flags indicate that
+           a pointer to another symbol is stored here.  */
+   symvalue value;
+ 
+         /* Attributes of a symbol: */
+ 
+ #define BSF_NO_FLAGS    0x00
+ 
+         /* The symbol has local scope; <<static>> in <<C>>. The value
+           is the offset into the section of the data. */
+ #define BSF_LOCAL      0x01
+ 
+         /* The symbol has global scope; initialized data in <<C>>. The
+           value is the offset into the section of the data. */
+ #define BSF_GLOBAL     0x02
+ 
+         /* The symbol has global scope and is exported. The value is
+           the offset into the section of the data. */
+ #define BSF_EXPORT     BSF_GLOBAL  /* no real difference */
+ 
+         /* A normal C symbol would be one of:
+           <<BSF_LOCAL>>, <<BSF_FORT_COMM>>,  <<BSF_UNDEFINED>> or
+           <<BSF_GLOBAL>> */
+ 
+         /* The symbol is a debugging record. The value has an arbitary
+           meaning, unless BSF_DEBUGGING_RELOC is also set.  */
+ #define BSF_DEBUGGING  0x08
+ 
+         /* The symbol denotes a function entry point.  Used in ELF,
+           perhaps others someday.  */
+ #define BSF_FUNCTION    0x10
+ 
+         /* Used by the linker. */
+ #define BSF_KEEP        0x20
+ #define BSF_KEEP_G      0x40
+ 
+         /* A weak global symbol, overridable without warnings by
+           a regular global symbol of the same name.  */
+ #define BSF_WEAK        0x80
+ 
+         /* This symbol was created to point to a section, e.g. ELF's
+           STT_SECTION symbols.  */
+ #define BSF_SECTION_SYM 0x100
+ 
+         /* The symbol used to be a common symbol, but now it is
+           allocated. */
+ #define BSF_OLD_COMMON  0x200
+ 
+         /* The default value for common data. */
+ #define BFD_FORT_COMM_DEFAULT_VALUE 0
+ 
+         /* In some files the type of a symbol sometimes alters its
+           location in an output file - ie in coff a <<ISFCN>> symbol
+           which is also <<C_EXT>> symbol appears where it was
+           declared and not at the end of a section.  This bit is set
+           by the target BFD part to convey this information. */
+ 
+ #define BSF_NOT_AT_END    0x400
+ 
+         /* Signal that the symbol is the label of constructor section. */
+ #define BSF_CONSTRUCTOR   0x800
+ 
+         /* Signal that the symbol is a warning symbol.  The name is a
+           warning.  The name of the next symbol is the one to warn about;
+           if a reference is made to a symbol with the same name as the next
+           symbol, a warning is issued by the linker. */
+ #define BSF_WARNING       0x1000
+ 
+         /* Signal that the symbol is indirect.  This symbol is an indirect
+           pointer to the symbol with the same name as the next symbol. */
+ #define BSF_INDIRECT      0x2000
+ 
+         /* BSF_FILE marks symbols that contain a file name.  This is used
+           for ELF STT_FILE symbols.  */
+ #define BSF_FILE          0x4000
+ 
+         /* Symbol is from dynamic linking information.  */
+ #define BSF_DYNAMIC       0x8000
+ 
+         /* The symbol denotes a data object.  Used in ELF, and perhaps
+           others someday.  */
+ #define BSF_OBJECT        0x10000
+ 
+         /* This symbol is a debugging symbol.  The value is the offset
+           into the section of the data.  BSF_DEBUGGING should be set
+           as well.  */
+ #define BSF_DEBUGGING_RELOC 0x20000
+ 
+   flagword flags;
+ 
+         /* A pointer to the section to which this symbol is
+           relative.  This will always be non NULL, there are special
+           sections for undefined and absolute symbols.  */
+   struct sec *section;
+ 
+         /* Back end special data.  */
+   union
+     {
+       PTR p;
+       bfd_vma i;
+     } udata;
+ 
+ } asymbol;
+ #define bfd_get_symtab_upper_bound(abfd) \
+      BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+ boolean 
+ bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym));
+ 
+ boolean 
+ bfd_is_local_label_name PARAMS ((bfd *abfd, const char *name));
+ 
+ #define bfd_is_local_label_name(abfd, name) \
+      BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+ #define bfd_canonicalize_symtab(abfd, location) \
+      BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+                   (abfd, location))
+ boolean 
+ bfd_set_symtab  PARAMS ((bfd *abfd, asymbol **location, unsigned int count));
+ 
+ void 
+ bfd_print_symbol_vandf PARAMS ((PTR file, asymbol *symbol));
+ 
+ #define bfd_make_empty_symbol(abfd) \
+      BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+ #define bfd_make_debug_symbol(abfd,ptr,size) \
+         BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+ int 
+ bfd_decode_symclass PARAMS ((asymbol *symbol));
+ 
+ void 
+ bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+ 
+ boolean 
+ bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym));
+ 
+ #define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+      BFD_SEND (obfd, _bfd_copy_private_symbol_data, \
+                (ibfd, isymbol, obfd, osymbol))
+ struct _bfd 
+ {
+      /* The filename the application opened the BFD with.  */
+     CONST char *filename;                
+ 
+      /* A pointer to the target jump table.             */
+     const struct bfd_target *xvec;
+ 
+      /* To avoid dragging too many header files into every file that
+        includes `<<bfd.h>>', IOSTREAM has been declared as a "char
+        *", and MTIME as a "long".  Their correct types, to which they
+        are cast when used, are "FILE *" and "time_t".    The iostream
+        is the result of an fopen on the filename.  However, if the
+        BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+        to a bfd_in_memory struct.  */
+     PTR iostream;
+ 
+      /* Is the file descriptor being cached?  That is, can it be closed as
+        needed, and re-opened when accessed later?  */
+ 
+     boolean cacheable;
+ 
+      /* Marks whether there was a default target specified when the
+        BFD was opened. This is used to select which matching algorithm
+        to use to choose the back end. */
+ 
+     boolean target_defaulted;
+ 
+      /* The caching routines use these to maintain a
+        least-recently-used list of BFDs */
+ 
+     struct _bfd *lru_prev, *lru_next;
+ 
+      /* When a file is closed by the caching routines, BFD retains
+        state information on the file here: */
+ 
+     file_ptr where;              
+ 
+      /* and here: (``once'' means at least once) */
+ 
+     boolean opened_once;
+ 
+      /* Set if we have a locally maintained mtime value, rather than
+        getting it from the file each time: */
+ 
+     boolean mtime_set;
+ 
+      /* File modified time, if mtime_set is true: */
+ 
+     long mtime;          
+ 
+      /* Reserved for an unimplemented file locking extension.*/
+ 
+     int ifd;
+ 
+      /* The format which belongs to the BFD. (object, core, etc.) */
+ 
+     bfd_format format;
+ 
+      /* The direction the BFD was opened with*/
+ 
+     enum bfd_direction {no_direction = 0,
+                         read_direction = 1,
+                         write_direction = 2,
+                         both_direction = 3} direction;
+ 
+      /* Format_specific flags*/
+ 
+     flagword flags;              
+ 
+      /* Currently my_archive is tested before adding origin to
+        anything. I believe that this can become always an add of
+        origin, with origin set to 0 for non archive files.   */
+ 
+     file_ptr origin;             
+ 
+      /* Remember when output has begun, to stop strange things
+        from happening. */
+     boolean output_has_begun;
+ 
+      /* Pointer to linked list of sections*/
+     struct sec  *sections;
+ 
+      /* The number of sections */
+     unsigned int section_count;
+ 
+      /* Stuff only useful for object files: 
+        The start address. */
+     bfd_vma start_address;
+ 
+      /* Used for input and output*/
+     unsigned int symcount;
+ 
+      /* Symbol table for output BFD (with symcount entries) */
+     struct symbol_cache_entry  **outsymbols;             
+ 
+      /* Pointer to structure which contains architecture information*/
+     const struct bfd_arch_info *arch_info;
+ 
+      /* Stuff only useful for archives:*/
+     PTR arelt_data;              
+     struct _bfd *my_archive;      /* The containing archive BFD.  */
+     struct _bfd *next;            /* The next BFD in the archive.  */
+     struct _bfd *archive_head;    /* The first BFD in the archive.  */
+     boolean has_armap;           
+ 
+      /* A chain of BFD structures involved in a link.  */
+     struct _bfd *link_next;
+ 
+      /* A field used by _bfd_generic_link_add_archive_symbols.  This will
+        be used only for archive elements.  */
+     int archive_pass;
+ 
+      /* Used by the back end to hold private data. */
+ 
+     union 
+       {
+       struct aout_data_struct *aout_data;
+       struct artdata *aout_ar_data;
+       struct _oasys_data *oasys_obj_data;
+       struct _oasys_ar_data *oasys_ar_data;
+       struct coff_tdata *coff_obj_data;
+       struct pe_tdata *pe_obj_data;
+       struct xcoff_tdata *xcoff_obj_data;
+       struct ecoff_tdata *ecoff_obj_data;
+       struct ieee_data_struct *ieee_data;
+       struct ieee_ar_data_struct *ieee_ar_data;
+       struct srec_data_struct *srec_data;
+       struct ihex_data_struct *ihex_data;
+       struct tekhex_data_struct *tekhex_data;
+       struct elf_obj_tdata *elf_obj_data;
+       struct nlm_obj_tdata *nlm_obj_data;
+       struct bout_data_struct *bout_data;
+       struct sun_core_struct *sun_core_data;
+       struct sco5_core_struct *sco5_core_data;
+       struct trad_core_struct *trad_core_data;
+       struct som_data_struct *som_data;
+       struct hpux_core_struct *hpux_core_data;
+       struct hppabsd_core_struct *hppabsd_core_data;
+       struct sgi_core_struct *sgi_core_data;
+       struct lynx_core_struct *lynx_core_data;
+       struct osf_core_struct *osf_core_data;
+       struct cisco_core_struct *cisco_core_data;
+       struct versados_data_struct *versados_data;
+       struct netbsd_core_struct *netbsd_core_data;
+       PTR any;
+       } tdata;
+   
+      /* Used by the application to hold private data*/
+     PTR usrdata;
+ 
+    /* Where all the allocated stuff under this BFD goes.  This is a
+      struct objalloc *, but we use PTR to avoid requiring the inclusion of
+      objalloc.h.  */
+     PTR memory;
+ };
+ 
+ typedef enum bfd_error
+ {
+   bfd_error_no_error = 0,
+   bfd_error_system_call,
+   bfd_error_invalid_target,
+   bfd_error_wrong_format,
+   bfd_error_invalid_operation,
+   bfd_error_no_memory,
+   bfd_error_no_symbols,
+   bfd_error_no_armap,
+   bfd_error_no_more_archived_files,
+   bfd_error_malformed_archive,
+   bfd_error_file_not_recognized,
+   bfd_error_file_ambiguously_recognized,
+   bfd_error_no_contents,
+   bfd_error_nonrepresentable_section,
+   bfd_error_no_debug_section,
+   bfd_error_bad_value,
+   bfd_error_file_truncated,
+   bfd_error_file_too_big,
+   bfd_error_invalid_error_code
+ } bfd_error_type;
+ 
+ bfd_error_type 
+ bfd_get_error  PARAMS ((void));
+ 
+ void 
+ bfd_set_error  PARAMS ((bfd_error_type error_tag));
+ 
+ CONST char *
+ bfd_errmsg  PARAMS ((bfd_error_type error_tag));
+ 
+ void 
+ bfd_perror  PARAMS ((CONST char *message));
+ 
+ typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+ 
+ bfd_error_handler_type 
+ bfd_set_error_handler  PARAMS ((bfd_error_handler_type));
+ 
+ void 
+ bfd_set_error_program_name  PARAMS ((const char *));
+ 
+ bfd_error_handler_type 
+ bfd_get_error_handler  PARAMS ((void));
+ 
+ long 
+ bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+ 
+ long 
+ bfd_canonicalize_reloc
+  PARAMS ((bfd *abfd,
+     asection *sec,
+     arelent **loc,
+     asymbol **syms));
+ 
+ void 
+ bfd_set_reloc
+  PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count)
+     
+     );
+ 
+ boolean 
+ bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags));
+ 
+ boolean 
+ bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma));
+ 
+ long 
+ bfd_get_mtime PARAMS ((bfd *abfd));
+ 
+ long 
+ bfd_get_size PARAMS ((bfd *abfd));
+ 
+ int 
+ bfd_get_gp_size PARAMS ((bfd *abfd));
+ 
+ void 
+ bfd_set_gp_size PARAMS ((bfd *abfd, int i));
+ 
+ bfd_vma 
+ bfd_scan_vma PARAMS ((CONST char *string, CONST char **end, int base));
+ 
+ boolean 
+ bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+ 
+ #define bfd_copy_private_bfd_data(ibfd, obfd) \
+      BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+                (ibfd, obfd))
+ boolean 
+ bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+ 
+ #define bfd_merge_private_bfd_data(ibfd, obfd) \
+      BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+                (ibfd, obfd))
+ boolean 
+ bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
+ 
+ #define bfd_set_private_flags(abfd, flags) \
+      BFD_SEND (abfd, _bfd_set_private_flags, \
+                (abfd, flags))
+ #define bfd_sizeof_headers(abfd, reloc) \
+      BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+ 
+ #define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+      BFD_SEND (abfd, _bfd_find_nearest_line,  (abfd, sec, syms, off, file, func, line))
+ 
+         /* Do these three do anything useful at all, for any back end?  */
+ #define bfd_debug_info_start(abfd) \
+         BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+ 
+ #define bfd_debug_info_end(abfd) \
+         BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+ 
+ #define bfd_debug_info_accumulate(abfd, section) \
+         BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+ 
+ 
+ #define bfd_stat_arch_elt(abfd, stat) \
+         BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+ 
+ #define bfd_update_armap_timestamp(abfd) \
+         BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+ 
+ #define bfd_set_arch_mach(abfd, arch, mach)\
+         BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+ 
+ #define bfd_relax_section(abfd, section, link_info, again) \
+        BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
+ 
+ #define bfd_gc_sections(abfd, link_info) \
+        BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
+ 
+ #define bfd_link_hash_table_create(abfd) \
+        BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+ 
+ #define bfd_link_add_symbols(abfd, info) \
+        BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+ 
+ #define bfd_final_link(abfd, info) \
+        BFD_SEND (abfd, _bfd_final_link, (abfd, info))
+ 
+ #define bfd_free_cached_info(abfd) \
+        BFD_SEND (abfd, _bfd_free_cached_info, (abfd))
+ 
+ #define bfd_get_dynamic_symtab_upper_bound(abfd) \
+        BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd))
+ 
+ #define bfd_print_private_bfd_data(abfd, file)\
+        BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+ 
+ #define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
+        BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
+ 
+ #define bfd_get_dynamic_reloc_upper_bound(abfd) \
+        BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
+ 
+ #define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
+        BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
+ 
+ extern bfd_byte *bfd_get_relocated_section_contents
+        PARAMS ((bfd *, struct bfd_link_info *,
+                  struct bfd_link_order *, bfd_byte *,
+                  boolean, asymbol **));
+ 
+ symindex 
+ bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym));
+ 
+ boolean 
+ bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+ 
+ bfd *
+ bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+ 
+ CONST char *
+ bfd_core_file_failing_command PARAMS ((bfd *abfd));
+ 
+ int 
+ bfd_core_file_failing_signal PARAMS ((bfd *abfd));
+ 
+ boolean 
+ core_file_matches_executable_p
+  PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+ 
+ #define BFD_SEND(bfd, message, arglist) \
+                ((*((bfd)->xvec->message)) arglist)
+ 
+ #ifdef DEBUG_BFD_SEND
+ #undef BFD_SEND
+ #define BFD_SEND(bfd, message, arglist) \
+   (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+     ((*((bfd)->xvec->message)) arglist) : \
+     (bfd_assert (__FILE__,__LINE__), NULL))
+ #endif
+ #define BFD_SEND_FMT(bfd, message, arglist) \
+             (((bfd)->xvec->message[(int)((bfd)->format)]) arglist)
+ 
+ #ifdef DEBUG_BFD_SEND
+ #undef BFD_SEND_FMT
+ #define BFD_SEND_FMT(bfd, message, arglist) \
+   (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+    (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) : \
+    (bfd_assert (__FILE__,__LINE__), NULL))
+ #endif
+ enum bfd_flavour {
+   bfd_target_unknown_flavour,
+   bfd_target_aout_flavour,
+   bfd_target_coff_flavour,
+   bfd_target_ecoff_flavour,
+   bfd_target_elf_flavour,
+   bfd_target_ieee_flavour,
+   bfd_target_nlm_flavour,
+   bfd_target_oasys_flavour,
+   bfd_target_tekhex_flavour,
+   bfd_target_srec_flavour,
+   bfd_target_ihex_flavour,
+   bfd_target_som_flavour,
+   bfd_target_os9k_flavour,
+   bfd_target_versados_flavour,
+   bfd_target_msdos_flavour,
+   bfd_target_ovax_flavour,
+   bfd_target_evax_flavour
+ };
+ 
+ enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+ 
+  /* Forward declaration.  */
+ typedef struct bfd_link_info _bfd_link_info;
+ 
+ typedef struct bfd_target
+ {
+   char *name;
+   enum bfd_flavour flavour;
+   enum bfd_endian byteorder;
+   enum bfd_endian header_byteorder;
+   flagword object_flags;       
+   flagword section_flags;
+   char symbol_leading_char;
+   char ar_pad_char;            
+   unsigned short ar_max_namelen;
+   bfd_vma      (*bfd_getx64) PARAMS ((const bfd_byte *));
+   bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *));
+   void         (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+   bfd_vma      (*bfd_getx32) PARAMS ((const bfd_byte *));
+   bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *));
+   void         (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+   bfd_vma      (*bfd_getx16) PARAMS ((const bfd_byte *));
+   bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *));
+   void         (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+   bfd_vma      (*bfd_h_getx64) PARAMS ((const bfd_byte *));
+   bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *));
+   void         (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+   bfd_vma      (*bfd_h_getx32) PARAMS ((const bfd_byte *));
+   bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *));
+   void         (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+   bfd_vma      (*bfd_h_getx16) PARAMS ((const bfd_byte *));
+   bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *));
+   void         (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+   const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+   boolean             (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+   boolean             (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+ 
+    /* Generic entry points.  */
+ #define BFD_JUMP_TABLE_GENERIC(NAME)\
+ CAT(NAME,_close_and_cleanup),\
+ CAT(NAME,_bfd_free_cached_info),\
+ CAT(NAME,_new_section_hook),\
+ CAT(NAME,_get_section_contents),\
+ CAT(NAME,_get_section_contents_in_window)
+ 
+    /* Called when the BFD is being closed to do any necessary cleanup.  */
+   boolean       (*_close_and_cleanup) PARAMS ((bfd *));
+    /* Ask the BFD to free all cached information.  */
+   boolean (*_bfd_free_cached_info) PARAMS ((bfd *));
+    /* Called when a new section is created.  */
+   boolean       (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+    /* Read the contents of a section.  */
+   boolean       (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, 
+                                             file_ptr, bfd_size_type));
+   boolean       (*_bfd_get_section_contents_in_window)
+                           PARAMS ((bfd *, sec_ptr, bfd_window *,
+                                    file_ptr, bfd_size_type));
+ 
+    /* Entry points to copy private data.  */
+ #define BFD_JUMP_TABLE_COPY(NAME)\
+ CAT(NAME,_bfd_copy_private_bfd_data),\
+ CAT(NAME,_bfd_merge_private_bfd_data),\
+ CAT(NAME,_bfd_copy_private_section_data),\
+ CAT(NAME,_bfd_copy_private_symbol_data),\
+ CAT(NAME,_bfd_set_private_flags),\
+ CAT(NAME,_bfd_print_private_bfd_data)\
+    /* Called to copy BFD general private data from one object file
+      to another.  */
+   boolean       (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *));
+    /* Called to merge BFD general private data from one object file
+      to a common output file when linking.  */
+   boolean       (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *));
+    /* Called to copy BFD private section data from one object file
+      to another.  */
+   boolean       (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr,
+                                                        bfd *, sec_ptr));
+    /* Called to copy BFD private symbol data from one symbol 
+      to another.  */
+   boolean       (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+                                                           bfd *, asymbol *));
+    /* Called to set private backend flags */
+   boolean       (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+ 
+    /* Called to print private BFD data */
+   boolean       (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR));
+ 
+    /* Core file entry points.  */
+ #define BFD_JUMP_TABLE_CORE(NAME)\
+ CAT(NAME,_core_file_failing_command),\
+ CAT(NAME,_core_file_failing_signal),\
+ CAT(NAME,_core_file_matches_executable_p)
+   char *   (*_core_file_failing_command) PARAMS ((bfd *));
+   int      (*_core_file_failing_signal) PARAMS ((bfd *));
+   boolean  (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+ 
+    /* Archive entry points.  */
+ #define BFD_JUMP_TABLE_ARCHIVE(NAME)\
+ CAT(NAME,_slurp_armap),\
+ CAT(NAME,_slurp_extended_name_table),\
+ CAT(NAME,_construct_extended_name_table),\
+ CAT(NAME,_truncate_arname),\
+ CAT(NAME,_write_armap),\
+ CAT(NAME,_read_ar_hdr),\
+ CAT(NAME,_openr_next_archived_file),\
+ CAT(NAME,_get_elt_at_index),\
+ CAT(NAME,_generic_stat_arch_elt),\
+ CAT(NAME,_update_armap_timestamp)
+   boolean  (*_bfd_slurp_armap) PARAMS ((bfd *));
+   boolean  (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+   boolean  (*_bfd_construct_extended_name_table)
+              PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+   void     (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *));
+   boolean  (*write_armap) PARAMS ((bfd *arch, 
+                               unsigned int elength,
+                               struct orl *map,
+                               unsigned int orl_count, 
+                               int stridx));
+   PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+   bfd *    (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
+ #define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+   bfd *    (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+   int      (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+   boolean  (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+ 
+    /* Entry points used for symbols.  */
+ #define BFD_JUMP_TABLE_SYMBOLS(NAME)\
+ CAT(NAME,_get_symtab_upper_bound),\
+ CAT(NAME,_get_symtab),\
+ CAT(NAME,_make_empty_symbol),\
+ CAT(NAME,_print_symbol),\
+ CAT(NAME,_get_symbol_info),\
+ CAT(NAME,_bfd_is_local_label_name),\
+ CAT(NAME,_get_lineno),\
+ CAT(NAME,_find_nearest_line),\
+ CAT(NAME,_bfd_make_debug_symbol),\
+ CAT(NAME,_read_minisymbols),\
+ CAT(NAME,_minisymbol_to_symbol)
+   long  (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *));
+   long  (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+                                              struct symbol_cache_entry **));
+   struct symbol_cache_entry  *
+                 (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+   void          (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+                                       struct symbol_cache_entry *,
+                                       bfd_print_symbol_type));
+ #define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+   void          (*_bfd_get_symbol_info) PARAMS ((bfd *,
+                                       struct symbol_cache_entry *,
+                                       symbol_info *));
+ #define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+   boolean       (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *));
+ 
+   alent *    (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+   boolean    (*_bfd_find_nearest_line) PARAMS ((bfd *abfd,
+                     struct sec *section, struct symbol_cache_entry **symbols,
+                     bfd_vma offset, CONST char **file, CONST char **func,
+                     unsigned int *line));
+   /* Back-door to allow format-aware applications to create debug symbols
+     while using BFD for everything else.  Currently used by the assembler
+     when creating COFF files.  */
+   asymbol *  (*_bfd_make_debug_symbol) PARAMS ((
+        bfd *abfd,
+        void *ptr,
+        unsigned long size));
+ #define bfd_read_minisymbols(b, d, m, s) \
+   BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+   long  (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+                                       unsigned int *));
+ #define bfd_minisymbol_to_symbol(b, d, m, f) \
+   BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+   asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+                                              asymbol *));
+ 
+    /* Routines for relocs.  */
+ #define BFD_JUMP_TABLE_RELOCS(NAME)\
+ CAT(NAME,_get_reloc_upper_bound),\
+ CAT(NAME,_canonicalize_reloc),\
+ CAT(NAME,_bfd_reloc_type_lookup)
+   long  (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+   long  (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+                                             struct symbol_cache_entry **));
+    /* See documentation on reloc types.  */
+   reloc_howto_type *
+        (*reloc_type_lookup) PARAMS ((bfd *abfd,
+                                      bfd_reloc_code_real_type code));
+ 
+    /* Routines used when writing an object file.  */
+ #define BFD_JUMP_TABLE_WRITE(NAME)\
+ CAT(NAME,_set_arch_mach),\
+ CAT(NAME,_set_section_contents)
+   boolean    (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+                     unsigned long));
+   boolean       (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+                                             file_ptr, bfd_size_type));
+ 
+    /* Routines used by the linker.  */
+ #define BFD_JUMP_TABLE_LINK(NAME)\
+ CAT(NAME,_sizeof_headers),\
+ CAT(NAME,_bfd_get_relocated_section_contents),\
+ CAT(NAME,_bfd_relax_section),\
+ CAT(NAME,_bfd_link_hash_table_create),\
+ CAT(NAME,_bfd_link_add_symbols),\
+ CAT(NAME,_bfd_final_link),\
+ CAT(NAME,_bfd_link_split_section),\
+ CAT(NAME,_bfd_gc_sections)
+   int        (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+   bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
+                     struct bfd_link_info *, struct bfd_link_order *,
+                     bfd_byte *data, boolean relocateable,
+                     struct symbol_cache_entry **));
+ 
+   boolean    (*_bfd_relax_section) PARAMS ((bfd *, struct sec *,
+                     struct bfd_link_info *, boolean *again));
+ 
+    /* Create a hash table for the linker.  Different backends store
+      different information in this table.  */
+   struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *));
+ 
+    /* Add symbols from this object file into the hash table.  */
+   boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *));
+ 
+    /* Do a link based on the link_order structures attached to each
+      section of the BFD.  */
+   boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *));
+ 
+    /* Should this section be split up into smaller pieces during linking.  */
+   boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+ 
+    /* Remove sections that are not referenced from the output.  */
+   boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
+ 
+    /* Routines to handle dynamic symbols and relocs.  */
+ #define BFD_JUMP_TABLE_DYNAMIC(NAME)\
+ CAT(NAME,_get_dynamic_symtab_upper_bound),\
+ CAT(NAME,_canonicalize_dynamic_symtab),\
+ CAT(NAME,_get_dynamic_reloc_upper_bound),\
+ CAT(NAME,_canonicalize_dynamic_reloc)
+    /* Get the amount of memory required to hold the dynamic symbols. */
+   long  (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *));
+    /* Read in the dynamic symbols.  */
+   long  (*_bfd_canonicalize_dynamic_symtab)
+     PARAMS ((bfd *, struct symbol_cache_entry **));
+    /* Get the amount of memory required to hold the dynamic relocs.  */
+   long  (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *));
+    /* Read in the dynamic relocs.  */
+   long  (*_bfd_canonicalize_dynamic_reloc)
+     PARAMS ((bfd *, arelent **, struct symbol_cache_entry **));
+ 
+   /* Opposite endian version of this target.  */  
+  const struct bfd_target * alternative_target;
+  
+  PTR backend_data;
+  
+ } bfd_target;
+ boolean 
+ bfd_set_default_target  PARAMS ((const char *name));
+ 
+ const bfd_target *
+ bfd_find_target PARAMS ((CONST char *target_name, bfd *abfd));
+ 
+ const char **
+ bfd_target_list PARAMS ((void));
+ 
+ const bfd_target * 
+ bfd_search_for_target  PARAMS ((int (* search_func)(const bfd_target *, void *), void *));
+ 
+ boolean 
+ bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+ 
+ boolean 
+ bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching));
+ 
+ boolean 
+ bfd_set_format PARAMS ((bfd *abfd, bfd_format format));
+ 
+ CONST char *
+ bfd_format_string PARAMS ((bfd_format format));
+ 
+ #ifdef __cplusplus
+ }
+ #endif
+ #endif
diff -c -r -N console-os/arch/i386/kdb/ChangeLog console-os-kdb/arch/i386/kdb/ChangeLog
*** console-os/arch/i386/kdb/ChangeLog	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/arch/i386/kdb/ChangeLog	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,178 ----
+ 2003-07-20 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Remove compile warning on x86 commands.
+ 	* kdb v4.3-2.4.21-i386-5.
+ 
+ 2003-07-08 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Add new x86 commands - rdv, gdt, idt, ldt, ldtp, ptex.
+ 	  Vamsi Krishna S., IBM.
+ 	* kdb v4.3-2.4.21-i386-4.
+ 
+ 2003-07-01 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Convert kdba_find_return() to two passes to reduce false positives.
+ 	* Correct jmp disp8 offset calculation for out of line lock code.
+ 	* Use NMI for kdb IPI in clustered APIC mode.  Sachin Sant, IBM.
+ 	* kdb v4.3-2.4.21-i386-3.
+ 
+ 2003-06-23 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Sync with XFS 2.4.21 tree.
+ 	* kdb v4.3-2.4.21-i386-2.
+ 
+ 2003-06-20 Keith Owens  <kaos@sgi.com>
+ 
+ 	* kdb v4.3-2.4.21-i386-1.
+ 
+ 2003-06-20 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Add CONFIG_KDB_CONTINUE_CATASTROPHIC.
+ 	* Correct KDB_ENTER() definition.
+ 	* kdb v4.3-2.4.20-i386-1.
+ 
+ 2003-05-02 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Add kdba_fp_value().
+ 	* Limit backtrace size to catch loops.
+ 	* Add read/write access to user pages.  Vamsi Krishna S., IBM
+ 	* Clean up USB keyboard support.  Steven Dake.
+ 	* kdb v4.2-2.4.20-i386-1.
+ 
+ 2003-04-04 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Workarounds for scheduler bugs.
+ 	* kdb v4.1-2.4.20-i386-1.
+ 
+ 2003-03-16 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Each cpu saves its state as it enters kdb or before it enters code
+ 	  which cannot call kdb, converting kdb from a pull to a push model.
+ 	* Clean up kdb interaction with CONFIG_SERIAL_CONSOLE.
+ 	* Removal of special cases for i386 backtrace from common code
+ 	  simplifies the architecture code.
+ 	* Add command to dump i386 struct pt_regs.
+ 	* kdb v4.0-2.4.20-i386-1.
+ 
+ 2003-02-03 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Register kdb commands early.
+ 	* Handle KDB_ENTER() when kdb=off.
+ 	* Optimize __kdba_getarea_size when width is a constant.
+ 	* Decode oops via kallsyms if it is available.
+ 	* Update copyright notices to 2003.
+ 	* Handle call *disp32(%reg) in backtrace.
+ 	* Correct keyboard freeze.  Ashish Kalra.
+ 	* Add command history and editing.  Sonic Zhang.
+ 	* kdb_toggleled is conditional on KDB_BLINK_LED.  Bernhard Fischer.
+ 	* Allow tab on serial line for symbol completion.
+ 	* Ignore KDB_ENTER() when kdb is already running.
+ 	* kdb v3.0-2.4.20-i386-1.
+ 
+ 2002-11-29 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.20.
+ 	* kdb v2.5-2.4.20-i386-1.
+ 
+ 2002-11-14 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.20-rc1.
+ 	* kdb v2.5-2.4.20-rc1-i386-1.
+ 
+ 2002-11-14 Keith Owens  <kaos@sgi.com>
+ 
+ 	* General clean up of handling for breakpoints and single stepping over
+ 	  software breakpoints.
+ 	* Accept ff 1x as well as ff dx for call *(%reg) in backtrace.
+ 	* kdb v2.5-2.4.19-i386-1.
+ 
+ 2002-11-01 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Prevent SMP IRQ overwriting KDB_ENTER().
+ 	* kdb v2.4-2.4.19-i386-2.
+ 
+ 2002-10-31 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Avoid KDB_VECTOR conflict with DUMP_VECTOR.
+ 	* Remove kdb_eframe_t.
+ 	* Sanity check if we have pt_regs.
+ 	* Remove kdba_getcurrentframe().
+ 	* Reinstate missing nmi_watchdog/kdb hook.
+ 	* kdb v2.4-2.4.19-i386-1.
+ 
+ 2002-10-17 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Correct compile with CONFIG_VT_CONSOLE=n.
+ 	* kdb v2.3-2.4.19-i386-5.
+ 
+ 2002-10-04 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Add USB keyboard option.
+ 	* Minimize differences between patches for 2.4 and 2.5 kernels.
+ 	* kdb v2.3-2.4.19-i386-4.
+ 
+ 2002-08-10 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Replace kdb_port with kdb_serial to support memory mapped I/O.
+ 	  Note: This needs kdb v2.3-2.4.19-common-2 or later.
+ 	* kdb v2.3-2.4.19-i386-3.
+ 
+ 2002-08-09 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Use -fno-optimize-sibling-calls for kdb if gcc supports it.
+ 	* .text.lock does not consume an activation frame.
+ 	* kdb v2.3-2.4.19-i386-2.
+ 
+ 2002-08-07 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.19.
+ 	* Remove individual SGI copyrights, the general SGI copyright applies.
+ 	* New .text.lock name.  Hugh Dickins.
+ 	* Set KERNEL_CS in kdba_getcurrentframe.  Hugh Dickins.
+ 	* Clean up disassembly layout.  Hugh Dickins, Keith Owens.
+ 	* Replace hard coded stack size with THREAD_SIZE.  Hugh Dickins.
+ 	* Better stack layout on bt with no frame pointers.  Hugh Dickins.
+ 	* Make i386 IO breakpoints (bpha <address> IO) work again.
+ 	  Martin Wilck, Keith Owens.
+ 	* Remove fixed KDB_MAX_COMMANDS size.
+ 	* Add set_fs() around __copy_to_user on kernel addresses.
+ 	  Randolph Chung.
+ 	* Position i386 for CONFIG_NUMA_REPLICATE.
+ 	* kdb v2.3-2.4.19-i386-1.
+ 
+ 2002-07-09 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.19-rc1.
+ 
+ 2002-06-14 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.19-pre10.
+ 	* kdb v2.1-2.4.19-pre10-i386-1.
+ 
+ 2002-04-09 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.19-pre6.
+ 	* kdb v2.1-2.4.19-pre6-i386-1.
+ 
+ 2002-02-26 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.18.
+ 	* kdb v2.1-2.4.18-i386-1.
+ 
+ 2002-01-18 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Use new kdb_get/put functions.
+ 	* Define kdba_{get,put}area_size functions for i386.
+ 	* Remove over-engineered dblist callback functions.
+ 	* Correctly handle failing call disp32 in backtrace.
+ 	* Remove bp_instvalid flag, redundant code.
+ 	* Remove dead code.
+ 	* kdb v2.1-2.4.17-i386-1.
+ 
+ 2002-01-04 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Sync xfs <-> kdb i386 code.
+ 
+ 2001-12-22 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Split kdb for i386 as kdb v2.0-2.4.17-i386-1.
diff -c -r -N console-os/arch/i386/kdb/i386-dis.c console-os-kdb/arch/i386/kdb/i386-dis.c
*** console-os/arch/i386/kdb/i386-dis.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/arch/i386/kdb/i386-dis.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,3781 ----
+ /* Print i386 instructions for GDB, the GNU debugger.
+    Copyright (C) 1988, 89, 91, 93, 94, 95, 96, 97, 98, 1999
+    Free Software Foundation, Inc.
+ 
+ This file is part of GDB.
+ 
+ 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 of the License, 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.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+ /*
+  * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+  * July 1988
+  *  modified by John Hassey (hassey@dg-rtp.dg.com)
+  */
+ 
+ /* Extracted from cygnus CVS and modified for kdb use.
+  * Keith Owens <kaos@sgi.com> 30 Oct 2000
+  */
+ 
+ /*
+  * The main tables describing the instructions is essentially a copy
+  * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+  * Programmers Manual.  Usually, there is a capital letter, followed
+  * by a small letter.  The capital letter tell the addressing mode,
+  * and the small letter tells about the operand size.  Refer to
+  * the Intel manual for details.
+  */
+ 
+ #ifdef __KERNEL__
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+ #include <linux/dis-asm.h>
+ #include <linux/kdb.h>
+ #else
+ #include "dis-asm.h"
+ #include "sysdep.h"
+ #include "opintl.h"
+ #endif
+ 
+ #define MAXLEN 20
+ 
+ #ifndef __KERNEL__
+ #include <setjmp.h>
+ #endif
+ 
+ #ifndef UNIXWARE_COMPAT
+ /* Set non-zero for broken, compatible instructions.  Set to zero for
+    non-broken opcodes.  */
+ #define UNIXWARE_COMPAT 1
+ #endif
+ 
+ static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
+ 
+ struct dis_private
+ {
+   /* Points to first byte not fetched.  */
+   bfd_byte *max_fetched;
+   bfd_byte the_buffer[MAXLEN];
+   bfd_vma insn_start;
+ #ifndef __KERNEL__
+   jmp_buf bailout;
+ #endif
+ };
+ 
+ /* The opcode for the fwait instruction, which we treat as a prefix
+    when we can.  */
+ #define FWAIT_OPCODE (0x9b)
+ 
+ /* Flags for the prefixes for the current instruction.  See below.  */
+ static int prefixes;
+ 
+ /* Flags for prefixes which we somehow handled when printing the
+    current instruction.  */
+ static int used_prefixes;
+ 
+ /* Flags stored in PREFIXES.  */
+ #define PREFIX_REPZ 1
+ #define PREFIX_REPNZ 2
+ #define PREFIX_LOCK 4
+ #define PREFIX_CS 8
+ #define PREFIX_SS 0x10
+ #define PREFIX_DS 0x20
+ #define PREFIX_ES 0x40
+ #define PREFIX_FS 0x80
+ #define PREFIX_GS 0x100
+ #define PREFIX_DATA 0x200
+ #define PREFIX_ADDR 0x400
+ #define PREFIX_FWAIT 0x800
+ 
+ /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
+    on error.  */
+ #define FETCH_DATA(info, addr) \
+   ((addr) <= ((struct dis_private *)(info->private_data))->max_fetched \
+    ? 1 : fetch_data ((info), (addr)))
+ 
+ static int
+ fetch_data (info, addr)
+      struct disassemble_info *info;
+      bfd_byte *addr;
+ {
+   int status;
+   struct dis_private *priv = (struct dis_private *)info->private_data;
+   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
+ 
+   status = (*info->read_memory_func) (start,
+ 				      priv->max_fetched,
+ 				      addr - priv->max_fetched,
+ 				      info);
+   if (status != 0)
+     {
+       /* If we did manage to read at least one byte, then
+          print_insn_i386 will do something sensible.  Otherwise, print
+          an error.  We do that here because this is where we know
+          STATUS.  */
+       if (priv->max_fetched == priv->the_buffer)
+ 	(*info->memory_error_func) (status, start, info);
+ #ifndef __KERNEL__
+       longjmp (priv->bailout, 1);
+ #else
+ 	/* XXX - what to do? */
+ 	kdb_printf("Hmm. longjmp.\n");
+ #endif
+     }
+   else
+     priv->max_fetched = addr;
+   return 1;
+ }
+ 
+ #define XX NULL, 0
+ 
+ #define Eb OP_E, b_mode
+ #define indirEb OP_indirE, b_mode
+ #define Gb OP_G, b_mode
+ #define Ev OP_E, v_mode
+ #define Ed OP_E, d_mode
+ #define indirEv OP_indirE, v_mode
+ #define Ew OP_E, w_mode
+ #define Ma OP_E, v_mode
+ #define M OP_E, 0		/* lea */
+ #define Mp OP_E, 0		/* 32 or 48 bit memory operand for LDS, LES etc */
+ #define Gv OP_G, v_mode
+ #define Gw OP_G, w_mode
+ #define Rd OP_Rd, d_mode
+ #define Ib OP_I, b_mode
+ #define sIb OP_sI, b_mode	/* sign extened byte */
+ #define Iv OP_I, v_mode
+ #define Iw OP_I, w_mode
+ #define Jb OP_J, b_mode
+ #define Jv OP_J, v_mode
+ #define Cd OP_C, d_mode
+ #define Dd OP_D, d_mode
+ #define Td OP_T, d_mode
+ 
+ #define eAX OP_REG, eAX_reg
+ #define eBX OP_REG, eBX_reg
+ #define eCX OP_REG, eCX_reg
+ #define eDX OP_REG, eDX_reg
+ #define eSP OP_REG, eSP_reg
+ #define eBP OP_REG, eBP_reg
+ #define eSI OP_REG, eSI_reg
+ #define eDI OP_REG, eDI_reg
+ #define AL OP_REG, al_reg
+ #define CL OP_REG, cl_reg
+ #define DL OP_REG, dl_reg
+ #define BL OP_REG, bl_reg
+ #define AH OP_REG, ah_reg
+ #define CH OP_REG, ch_reg
+ #define DH OP_REG, dh_reg
+ #define BH OP_REG, bh_reg
+ #define AX OP_REG, ax_reg
+ #define DX OP_REG, dx_reg
+ #define indirDX OP_REG, indir_dx_reg
+ 
+ #define Sw OP_SEG, w_mode
+ #define Ap OP_DIR, 0
+ #define Ob OP_OFF, b_mode
+ #define Ov OP_OFF, v_mode
+ #define Xb OP_DSreg, eSI_reg
+ #define Xv OP_DSreg, eSI_reg
+ #define Yb OP_ESreg, eDI_reg
+ #define Yv OP_ESreg, eDI_reg
+ #define DSBX OP_DSreg, eBX_reg
+ 
+ #define es OP_REG, es_reg
+ #define ss OP_REG, ss_reg
+ #define cs OP_REG, cs_reg
+ #define ds OP_REG, ds_reg
+ #define fs OP_REG, fs_reg
+ #define gs OP_REG, gs_reg
+ 
+ #define MX OP_MMX, 0
+ #define XM OP_XMM, 0
+ #define EM OP_EM, v_mode
+ #define EX OP_EX, v_mode
+ #define MS OP_MS, v_mode
+ #define None OP_E, 0
+ #define OPSUF OP_3DNowSuffix, 0
+ #define OPSIMD OP_SIMD_Suffix, 0
+ 
+ /* bits in sizeflag */
+ #if 0 /* leave undefined until someone adds the extra flag to objdump */
+ #define SUFFIX_ALWAYS 4
+ #endif
+ #define AFLAG 2
+ #define DFLAG 1
+ 
+ typedef void (*op_rtn) PARAMS ((int bytemode, int sizeflag));
+ 
+ static void OP_E PARAMS ((int, int));
+ static void OP_G PARAMS ((int, int));
+ static void OP_I PARAMS ((int, int));
+ static void OP_indirE PARAMS ((int, int));
+ static void OP_sI PARAMS ((int, int));
+ static void OP_REG PARAMS ((int, int));
+ static void OP_J PARAMS ((int, int));
+ static void OP_DIR PARAMS ((int, int));
+ static void OP_OFF PARAMS ((int, int));
+ static void OP_ESreg PARAMS ((int, int));
+ static void OP_DSreg PARAMS ((int, int));
+ static void OP_SEG PARAMS ((int, int));
+ static void OP_C PARAMS ((int, int));
+ static void OP_D PARAMS ((int, int));
+ static void OP_T PARAMS ((int, int));
+ static void OP_Rd PARAMS ((int, int));
+ static void OP_ST PARAMS ((int, int));
+ static void OP_STi  PARAMS ((int, int));
+ static void OP_MMX PARAMS ((int, int));
+ static void OP_XMM PARAMS ((int, int));
+ static void OP_EM PARAMS ((int, int));
+ static void OP_EX PARAMS ((int, int));
+ static void OP_MS PARAMS ((int, int));
+ static void OP_3DNowSuffix PARAMS ((int, int));
+ static void OP_SIMD_Suffix PARAMS ((int, int));
+ static void SIMD_Fixup PARAMS ((int, int));
+ 
+ static void append_seg PARAMS ((void));
+ static void set_op PARAMS ((unsigned int op));
+ static void putop PARAMS ((const char *template, int sizeflag));
+ static void dofloat PARAMS ((int sizeflag));
+ static int get16 PARAMS ((void));
+ static int get32 PARAMS ((void));
+ static void ckprefix PARAMS ((void));
+ static const char *prefix_name PARAMS ((int, int));
+ static void ptr_reg PARAMS ((int, int));
+ static void BadOp PARAMS ((void));
+ 
+ #define b_mode 1
+ #define v_mode 2
+ #define w_mode 3
+ #define d_mode 4
+ #define x_mode 5
+ 
+ #define es_reg 100
+ #define cs_reg 101
+ #define ss_reg 102
+ #define ds_reg 103
+ #define fs_reg 104
+ #define gs_reg 105
+ 
+ #define eAX_reg 108
+ #define eCX_reg 109
+ #define eDX_reg 110
+ #define eBX_reg 111
+ #define eSP_reg 112
+ #define eBP_reg 113
+ #define eSI_reg 114
+ #define eDI_reg 115
+ 
+ #define al_reg 116
+ #define cl_reg 117
+ #define dl_reg 118
+ #define bl_reg 119
+ #define ah_reg 120
+ #define ch_reg 121
+ #define dh_reg 122
+ #define bh_reg 123
+ 
+ #define ax_reg 124
+ #define cx_reg 125
+ #define dx_reg 126
+ #define bx_reg 127
+ #define sp_reg 128
+ #define bp_reg 129
+ #define si_reg 130
+ #define di_reg 131
+ 
+ #define indir_dx_reg 150
+ 
+ #define USE_GROUPS 1
+ #define USE_PREFIX_USER_TABLE 2
+ 
+ #define GRP1b NULL, NULL, 0, NULL, USE_GROUPS, NULL, 0
+ #define GRP1S NULL, NULL, 1, NULL, USE_GROUPS, NULL, 0
+ #define GRP1Ss NULL, NULL, 2, NULL, USE_GROUPS, NULL, 0
+ #define GRP2b NULL, NULL, 3, NULL, USE_GROUPS, NULL, 0
+ #define GRP2S NULL, NULL, 4, NULL, USE_GROUPS, NULL, 0
+ #define GRP2b_one NULL, NULL, 5, NULL, USE_GROUPS, NULL, 0
+ #define GRP2S_one NULL, NULL, 6, NULL, USE_GROUPS, NULL, 0
+ #define GRP2b_cl NULL, NULL, 7, NULL, USE_GROUPS, NULL, 0
+ #define GRP2S_cl NULL, NULL, 8, NULL, USE_GROUPS, NULL, 0
+ #define GRP3b NULL, NULL, 9, NULL, USE_GROUPS, NULL, 0
+ #define GRP3S NULL, NULL, 10, NULL, USE_GROUPS, NULL, 0
+ #define GRP4  NULL, NULL, 11, NULL, USE_GROUPS, NULL, 0
+ #define GRP5  NULL, NULL, 12, NULL, USE_GROUPS, NULL, 0
+ #define GRP6  NULL, NULL, 13, NULL, USE_GROUPS, NULL, 0
+ #define GRP7 NULL, NULL, 14, NULL, USE_GROUPS, NULL, 0
+ #define GRP8 NULL, NULL, 15, NULL, USE_GROUPS, NULL, 0
+ #define GRP9 NULL, NULL, 16, NULL, USE_GROUPS, NULL, 0
+ #define GRP10 NULL, NULL, 17, NULL, USE_GROUPS, NULL, 0
+ #define GRP11 NULL, NULL, 18, NULL, USE_GROUPS, NULL, 0
+ #define GRP12 NULL, NULL, 19, NULL, USE_GROUPS, NULL, 0
+ #define GRP13 NULL, NULL, 20, NULL, USE_GROUPS, NULL, 0
+ #define GRP14 NULL, NULL, 21, NULL, USE_GROUPS, NULL, 0
+ #define GRPAMD NULL, NULL, 22, NULL, USE_GROUPS, NULL, 0
+ 
+ #define PREGRP0 NULL, NULL, 0, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP1 NULL, NULL, 1, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP2 NULL, NULL, 2, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP3 NULL, NULL, 3, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP4 NULL, NULL, 4, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP5 NULL, NULL, 5, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP6 NULL, NULL, 6, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP7 NULL, NULL, 7, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP8 NULL, NULL, 8, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP9 NULL, NULL, 9, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP10 NULL, NULL, 10, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP11 NULL, NULL, 11, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP12 NULL, NULL, 12, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP13 NULL, NULL, 13, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ #define PREGRP14 NULL, NULL, 14, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+ 
+ #define FLOATCODE 50
+ #define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
+ 
+ struct dis386 {
+   const char *name;
+   op_rtn op1;
+   int bytemode1;
+   op_rtn op2;
+   int bytemode2;
+   op_rtn op3;
+   int bytemode3;
+ };
+ 
+ /* Upper case letters in the instruction names here are macros.
+    'A' => print 'b' if no register operands or suffix_always is true
+    'B' => print 'b' if suffix_always is true
+    'E' => print 'e' if 32-bit form of jcxz
+    'L' => print 'l' if suffix_always is true
+    'N' => print 'n' if instruction has no wait "prefix"
+    'P' => print 'w' or 'l' if instruction has an operand size prefix,
+                               or suffix_always is true
+    'Q' => print 'w' or 'l' if no register operands or suffix_always is true
+    'R' => print 'w' or 'l' ("wd" or "dq" in intel mode)
+    'S' => print 'w' or 'l' if suffix_always is true
+    'W' => print 'b' or 'w' ("w" or "de" in intel mode)
+ */
+ 
+ static const struct dis386 dis386_att[] = {
+   /* 00 */
+   { "addB",	Eb, Gb, XX },
+   { "addS",	Ev, Gv, XX },
+   { "addB",	Gb, Eb, XX },
+   { "addS",	Gv, Ev, XX },
+   { "addB",	AL, Ib, XX },
+   { "addS",	eAX, Iv, XX },
+   { "pushP",	es, XX, XX },
+   { "popP",	es, XX, XX },
+   /* 08 */
+   { "orB",	Eb, Gb, XX },
+   { "orS",	Ev, Gv, XX },
+   { "orB",	Gb, Eb, XX },
+   { "orS",	Gv, Ev, XX },
+   { "orB",	AL, Ib, XX },
+   { "orS",	eAX, Iv, XX },
+   { "pushP",	cs, XX, XX },
+   { "(bad)",	XX, XX, XX },	/* 0x0f extended opcode escape */
+   /* 10 */
+   { "adcB",	Eb, Gb, XX },
+   { "adcS",	Ev, Gv, XX },
+   { "adcB",	Gb, Eb, XX },
+   { "adcS",	Gv, Ev, XX },
+   { "adcB",	AL, Ib, XX },
+   { "adcS",	eAX, Iv, XX },
+   { "pushP",	ss, XX, XX },
+   { "popP",	ss, XX, XX },
+   /* 18 */
+   { "sbbB",	Eb, Gb, XX },
+   { "sbbS",	Ev, Gv, XX },
+   { "sbbB",	Gb, Eb, XX },
+   { "sbbS",	Gv, Ev, XX },
+   { "sbbB",	AL, Ib, XX },
+   { "sbbS",	eAX, Iv, XX },
+   { "pushP",	ds, XX, XX },
+   { "popP",	ds, XX, XX },
+   /* 20 */
+   { "andB",	Eb, Gb, XX },
+   { "andS",	Ev, Gv, XX },
+   { "andB",	Gb, Eb, XX },
+   { "andS",	Gv, Ev, XX },
+   { "andB",	AL, Ib, XX },
+   { "andS",	eAX, Iv, XX },
+   { "(bad)",	XX, XX, XX },			/* SEG ES prefix */
+   { "daa",	XX, XX, XX },
+   /* 28 */
+   { "subB",	Eb, Gb, XX },
+   { "subS",	Ev, Gv, XX },
+   { "subB",	Gb, Eb, XX },
+   { "subS",	Gv, Ev, XX },
+   { "subB",	AL, Ib, XX },
+   { "subS",	eAX, Iv, XX },
+   { "(bad)",	XX, XX, XX },			/* SEG CS prefix */
+   { "das",	XX, XX, XX },
+   /* 30 */
+   { "xorB",	Eb, Gb, XX },
+   { "xorS",	Ev, Gv, XX },
+   { "xorB",	Gb, Eb, XX },
+   { "xorS",	Gv, Ev, XX },
+   { "xorB",	AL, Ib, XX },
+   { "xorS",	eAX, Iv, XX },
+   { "(bad)",	XX, XX, XX },			/* SEG SS prefix */
+   { "aaa",	XX, XX, XX },
+   /* 38 */
+   { "cmpB",	Eb, Gb, XX },
+   { "cmpS",	Ev, Gv, XX },
+   { "cmpB",	Gb, Eb, XX },
+   { "cmpS",	Gv, Ev, XX },
+   { "cmpB",	AL, Ib, XX },
+   { "cmpS",	eAX, Iv, XX },
+   { "(bad)",	XX, XX, XX },			/* SEG DS prefix */
+   { "aas",	XX, XX, XX },
+   /* 40 */
+   { "incS",	eAX, XX, XX },
+   { "incS",	eCX, XX, XX },
+   { "incS",	eDX, XX, XX },
+   { "incS",	eBX, XX, XX },
+   { "incS",	eSP, XX, XX },
+   { "incS",	eBP, XX, XX },
+   { "incS",	eSI, XX, XX },
+   { "incS",	eDI, XX, XX },
+   /* 48 */
+   { "decS",	eAX, XX, XX },
+   { "decS",	eCX, XX, XX },
+   { "decS",	eDX, XX, XX },
+   { "decS",	eBX, XX, XX },
+   { "decS",	eSP, XX, XX },
+   { "decS",	eBP, XX, XX },
+   { "decS",	eSI, XX, XX },
+   { "decS",	eDI, XX, XX },
+   /* 50 */
+   { "pushS",	eAX, XX, XX },
+   { "pushS",	eCX, XX, XX },
+   { "pushS",	eDX, XX, XX },
+   { "pushS",	eBX, XX, XX },
+   { "pushS",	eSP, XX, XX },
+   { "pushS",	eBP, XX, XX },
+   { "pushS",	eSI, XX, XX },
+   { "pushS",	eDI, XX, XX },
+   /* 58 */
+   { "popS",	eAX, XX, XX },
+   { "popS",	eCX, XX, XX },
+   { "popS",	eDX, XX, XX },
+   { "popS",	eBX, XX, XX },
+   { "popS",	eSP, XX, XX },
+   { "popS",	eBP, XX, XX },
+   { "popS",	eSI, XX, XX },
+   { "popS",	eDI, XX, XX },
+   /* 60 */
+   { "pushaP",	XX, XX, XX },
+   { "popaP",	XX, XX, XX },
+   { "boundS",	Gv, Ma, XX },
+   { "arpl",	Ew, Gw, XX },
+   { "(bad)",	XX, XX, XX },			/* seg fs */
+   { "(bad)",	XX, XX, XX },			/* seg gs */
+   { "(bad)",	XX, XX, XX },			/* op size prefix */
+   { "(bad)",	XX, XX, XX },			/* adr size prefix */
+   /* 68 */
+   { "pushP",	Iv, XX, XX },		/* 386 book wrong */
+   { "imulS",	Gv, Ev, Iv },
+   { "pushP",	sIb, XX, XX },	/* push of byte really pushes 2 or 4 bytes */
+   { "imulS",	Gv, Ev, sIb },
+   { "insb",	Yb, indirDX, XX },
+   { "insR",	Yv, indirDX, XX },
+   { "outsb",	indirDX, Xb, XX },
+   { "outsR",	indirDX, Xv, XX },
+   /* 70 */
+   { "jo",	Jb, XX, XX },
+   { "jno",	Jb, XX, XX },
+   { "jb",	Jb, XX, XX },
+   { "jae",	Jb, XX, XX },
+   { "je",	Jb, XX, XX },
+   { "jne",	Jb, XX, XX },
+   { "jbe",	Jb, XX, XX },
+   { "ja",	Jb, XX, XX },
+   /* 78 */
+   { "js",	Jb, XX, XX },
+   { "jns",	Jb, XX, XX },
+   { "jp",	Jb, XX, XX },
+   { "jnp",	Jb, XX, XX },
+   { "jl",	Jb, XX, XX },
+   { "jge",	Jb, XX, XX },
+   { "jle",	Jb, XX, XX },
+   { "jg",	Jb, XX, XX },
+   /* 80 */
+   { GRP1b },
+   { GRP1S },
+   { "(bad)",	XX, XX, XX },
+   { GRP1Ss },
+   { "testB",	Eb, Gb, XX },
+   { "testS",	Ev, Gv, XX },
+   { "xchgB",	Eb, Gb, XX },
+   { "xchgS",	Ev, Gv, XX },
+   /* 88 */
+   { "movB",	Eb, Gb, XX },
+   { "movS",	Ev, Gv, XX },
+   { "movB",	Gb, Eb, XX },
+   { "movS",	Gv, Ev, XX },
+   { "movQ",	Ev, Sw, XX },
+   { "leaS",	Gv, M, XX },
+   { "movQ",	Sw, Ev, XX },
+   { "popQ",	Ev, XX, XX },
+   /* 90 */
+   { "nop",	XX, XX, XX },
+   { "xchgS",	eCX, eAX, XX },
+   { "xchgS",	eDX, eAX, XX },
+   { "xchgS",	eBX, eAX, XX },
+   { "xchgS",	eSP, eAX, XX },
+   { "xchgS",	eBP, eAX, XX },
+   { "xchgS",	eSI, eAX, XX },
+   { "xchgS",	eDI, eAX, XX },
+   /* 98 */
+   { "cWtR",	XX, XX, XX },
+   { "cRtd",	XX, XX, XX },
+   { "lcallP",	Ap, XX, XX },
+   { "(bad)",	XX, XX, XX },		/* fwait */
+   { "pushfP",	XX, XX, XX },
+   { "popfP",	XX, XX, XX },
+   { "sahf",	XX, XX, XX },
+   { "lahf",	XX, XX, XX },
+   /* a0 */
+   { "movB",	AL, Ob, XX },
+   { "movS",	eAX, Ov, XX },
+   { "movB",	Ob, AL, XX },
+   { "movS",	Ov, eAX, XX },
+   { "movsb",	Yb, Xb, XX },
+   { "movsR",	Yv, Xv, XX },
+   { "cmpsb",	Xb, Yb, XX },
+   { "cmpsR",	Xv, Yv, XX },
+   /* a8 */
+   { "testB",	AL, Ib, XX },
+   { "testS",	eAX, Iv, XX },
+   { "stosB",	Yb, AL, XX },
+   { "stosS",	Yv, eAX, XX },
+   { "lodsB",	AL, Xb, XX },
+   { "lodsS",	eAX, Xv, XX },
+   { "scasB",	AL, Yb, XX },
+   { "scasS",	eAX, Yv, XX },
+   /* b0 */
+   { "movB",	AL, Ib, XX },
+   { "movB",	CL, Ib, XX },
+   { "movB",	DL, Ib, XX },
+   { "movB",	BL, Ib, XX },
+   { "movB",	AH, Ib, XX },
+   { "movB",	CH, Ib, XX },
+   { "movB",	DH, Ib, XX },
+   { "movB",	BH, Ib, XX },
+   /* b8 */
+   { "movS",	eAX, Iv, XX },
+   { "movS",	eCX, Iv, XX },
+   { "movS",	eDX, Iv, XX },
+   { "movS",	eBX, Iv, XX },
+   { "movS",	eSP, Iv, XX },
+   { "movS",	eBP, Iv, XX },
+   { "movS",	eSI, Iv, XX },
+   { "movS",	eDI, Iv, XX },
+   /* c0 */
+   { GRP2b },
+   { GRP2S },
+   { "retP",	Iw, XX, XX },
+   { "retP",	XX, XX, XX },
+   { "lesS",	Gv, Mp, XX },
+   { "ldsS",	Gv, Mp, XX },
+   { "movA",	Eb, Ib, XX },
+   { "movQ",	Ev, Iv, XX },
+   /* c8 */
+   { "enterP",	Iw, Ib, XX },
+   { "leaveP",	XX, XX, XX },
+   { "lretP",	Iw, XX, XX },
+   { "lretP",	XX, XX, XX },
+   { "int3",	XX, XX, XX },
+   { "int",	Ib, XX, XX },
+   { "into",	XX, XX, XX},
+   { "iretP",	XX, XX, XX },
+   /* d0 */
+   { GRP2b_one },
+   { GRP2S_one },
+   { GRP2b_cl },
+   { GRP2S_cl },
+   { "aam",	sIb, XX, XX },
+   { "aad",	sIb, XX, XX },
+   { "(bad)",	XX, XX, XX },
+   { "xlat",	DSBX, XX, XX },
+   /* d8 */
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   /* e0 */
+   { "loopne",	Jb, XX, XX },
+   { "loope",	Jb, XX, XX },
+   { "loop",	Jb, XX, XX },
+   { "jEcxz",	Jb, XX, XX },
+   { "inB",	AL, Ib, XX },
+   { "inS",	eAX, Ib, XX },
+   { "outB",	Ib, AL, XX },
+   { "outS",	Ib, eAX, XX },
+   /* e8 */
+   { "callP",	Jv, XX, XX },
+   { "jmpP",	Jv, XX, XX },
+   { "ljmpP",	Ap, XX, XX },
+   { "jmp",	Jb, XX, XX },
+   { "inB",	AL, indirDX, XX },
+   { "inS",	eAX, indirDX, XX },
+   { "outB",	indirDX, AL, XX },
+   { "outS",	indirDX, eAX, XX },
+   /* f0 */
+   { "(bad)",	XX, XX, XX },			/* lock prefix */
+   { "(bad)",	XX, XX, XX },
+   { "(bad)",	XX, XX, XX },			/* repne */
+   { "(bad)",	XX, XX, XX },			/* repz */
+   { "hlt",	XX, XX, XX },
+   { "cmc",	XX, XX, XX },
+   { GRP3b },
+   { GRP3S },
+   /* f8 */
+   { "clc",	XX, XX, XX },
+   { "stc",	XX, XX, XX },
+   { "cli",	XX, XX, XX },
+   { "sti",	XX, XX, XX },
+   { "cld",	XX, XX, XX },
+   { "std",	XX, XX, XX },
+   { GRP4 },
+   { GRP5 },
+ };
+ 
+ static const struct dis386 dis386_intel[] = {
+   /* 00 */
+   { "add",	Eb, Gb, XX },
+   { "add",	Ev, Gv, XX },
+   { "add",	Gb, Eb, XX },
+   { "add",	Gv, Ev, XX },
+   { "add",	AL, Ib, XX },
+   { "add",	eAX, Iv, XX },
+   { "push",	es, XX, XX },
+   { "pop",	es, XX, XX },
+   /* 08 */
+   { "or",	Eb, Gb, XX },
+   { "or",	Ev, Gv, XX },
+   { "or",	Gb, Eb, XX },
+   { "or",	Gv, Ev, XX },
+   { "or",	AL, Ib, XX },
+   { "or",	eAX, Iv, XX },
+   { "push",	cs, XX, XX },
+   { "(bad)",	XX, XX, XX },	/* 0x0f extended opcode escape */
+   /* 10 */
+   { "adc",	Eb, Gb, XX },
+   { "adc",	Ev, Gv, XX },
+   { "adc",	Gb, Eb, XX },
+   { "adc",	Gv, Ev, XX },
+   { "adc",	AL, Ib, XX },
+   { "adc",	eAX, Iv, XX },
+   { "push",	ss, XX, XX },
+   { "pop",	ss, XX, XX },
+   /* 18 */
+   { "sbb",	Eb, Gb, XX },
+   { "sbb",	Ev, Gv, XX },
+   { "sbb",	Gb, Eb, XX },
+   { "sbb",	Gv, Ev, XX },
+   { "sbb",	AL, Ib, XX },
+   { "sbb",	eAX, Iv, XX },
+   { "push",	ds, XX, XX },
+   { "pop",	ds, XX, XX },
+   /* 20 */
+   { "and",	Eb, Gb, XX },
+   { "and",	Ev, Gv, XX },
+   { "and",	Gb, Eb, XX },
+   { "and",	Gv, Ev, XX },
+   { "and",	AL, Ib, XX },
+   { "and",	eAX, Iv, XX },
+   { "(bad)",	XX, XX, XX },			/* SEG ES prefix */
+   { "daa",	XX, XX, XX },
+   /* 28 */
+   { "sub",	Eb, Gb, XX },
+   { "sub",	Ev, Gv, XX },
+   { "sub",	Gb, Eb, XX },
+   { "sub",	Gv, Ev, XX },
+   { "sub",	AL, Ib, XX },
+   { "sub",	eAX, Iv, XX },
+   { "(bad)",	XX, XX, XX },			/* SEG CS prefix */
+   { "das",	XX, XX, XX },
+   /* 30 */
+   { "xor",	Eb, Gb, XX },
+   { "xor",	Ev, Gv, XX },
+   { "xor",	Gb, Eb, XX },
+   { "xor",	Gv, Ev, XX },
+   { "xor",	AL, Ib, XX },
+   { "xor",	eAX, Iv, XX },
+   { "(bad)",	XX, XX, XX },			/* SEG SS prefix */
+   { "aaa",	XX, XX, XX },
+   /* 38 */
+   { "cmp",	Eb, Gb, XX },
+   { "cmp",	Ev, Gv, XX },
+   { "cmp",	Gb, Eb, XX },
+   { "cmp",	Gv, Ev, XX },
+   { "cmp",	AL, Ib, XX },
+   { "cmp",	eAX, Iv, XX },
+   { "(bad)",	XX, XX, XX },			/* SEG DS prefix */
+   { "aas",	XX, XX, XX },
+   /* 40 */
+   { "inc",	eAX, XX, XX },
+   { "inc",	eCX, XX, XX },
+   { "inc",	eDX, XX, XX },
+   { "inc",	eBX, XX, XX },
+   { "inc",	eSP, XX, XX },
+   { "inc",	eBP, XX, XX },
+   { "inc",	eSI, XX, XX },
+   { "inc",	eDI, XX, XX },
+   /* 48 */
+   { "dec",	eAX, XX, XX },
+   { "dec",	eCX, XX, XX },
+   { "dec",	eDX, XX, XX },
+   { "dec",	eBX, XX, XX },
+   { "dec",	eSP, XX, XX },
+   { "dec",	eBP, XX, XX },
+   { "dec",	eSI, XX, XX },
+   { "dec",	eDI, XX, XX },
+   /* 50 */
+   { "push",	eAX, XX, XX },
+   { "push",	eCX, XX, XX },
+   { "push",	eDX, XX, XX },
+   { "push",	eBX, XX, XX },
+   { "push",	eSP, XX, XX },
+   { "push",	eBP, XX, XX },
+   { "push",	eSI, XX, XX },
+   { "push",	eDI, XX, XX },
+   /* 58 */
+   { "pop",	eAX, XX, XX },
+   { "pop",	eCX, XX, XX },
+   { "pop",	eDX, XX, XX },
+   { "pop",	eBX, XX, XX },
+   { "pop",	eSP, XX, XX },
+   { "pop",	eBP, XX, XX },
+   { "pop",	eSI, XX, XX },
+   { "pop",	eDI, XX, XX },
+   /* 60 */
+   { "pusha",	XX, XX, XX },
+   { "popa",	XX, XX, XX },
+   { "bound",	Gv, Ma, XX },
+   { "arpl",	Ew, Gw, XX },
+   { "(bad)",	XX, XX, XX },			/* seg fs */
+   { "(bad)",	XX, XX, XX },			/* seg gs */
+   { "(bad)",	XX, XX, XX },			/* op size prefix */
+   { "(bad)",	XX, XX, XX },			/* adr size prefix */
+   /* 68 */
+   { "push",	Iv, XX, XX },		/* 386 book wrong */
+   { "imul",	Gv, Ev, Iv },
+   { "push",	sIb, XX, XX },	/* push of byte really pushes 2 or 4 bytes */
+   { "imul",	Gv, Ev, sIb },
+   { "ins",	Yb, indirDX, XX },
+   { "ins",	Yv, indirDX, XX },
+   { "outs",	indirDX, Xb, XX },
+   { "outs",	indirDX, Xv, XX },
+   /* 70 */
+   { "jo",	Jb, XX, XX },
+   { "jno",	Jb, XX, XX },
+   { "jb",	Jb, XX, XX },
+   { "jae",	Jb, XX, XX },
+   { "je",	Jb, XX, XX },
+   { "jne",	Jb, XX, XX },
+   { "jbe",	Jb, XX, XX },
+   { "ja",	Jb, XX, XX },
+   /* 78 */
+   { "js",	Jb, XX, XX },
+   { "jns",	Jb, XX, XX },
+   { "jp",	Jb, XX, XX },
+   { "jnp",	Jb, XX, XX },
+   { "jl",	Jb, XX, XX },
+   { "jge",	Jb, XX, XX },
+   { "jle",	Jb, XX, XX },
+   { "jg",	Jb, XX, XX },
+   /* 80 */
+   { GRP1b },
+   { GRP1S },
+   { "(bad)",	XX, XX, XX },
+   { GRP1Ss },
+   { "test",	Eb, Gb, XX },
+   { "test",	Ev, Gv, XX },
+   { "xchg",	Eb, Gb, XX },
+   { "xchg",	Ev, Gv, XX },
+   /* 88 */
+   { "mov",	Eb, Gb, XX },
+   { "mov",	Ev, Gv, XX },
+   { "mov",	Gb, Eb, XX },
+   { "mov",	Gv, Ev, XX },
+   { "mov",	Ev, Sw, XX },
+   { "lea",	Gv, M, XX },
+   { "mov",	Sw, Ev, XX },
+   { "pop",	Ev, XX, XX },
+   /* 90 */
+   { "nop",	XX, XX, XX },
+   { "xchg",	eCX, eAX, XX },
+   { "xchg",	eDX, eAX, XX },
+   { "xchg",	eBX, eAX, XX },
+   { "xchg",	eSP, eAX, XX },
+   { "xchg",	eBP, eAX, XX },
+   { "xchg",	eSI, eAX, XX },
+   { "xchg",	eDI, eAX, XX },
+   /* 98 */
+   { "cW",	XX, XX, XX },		/* cwde and cbw */
+   { "cR",	XX, XX, XX },		/* cdq and cwd */
+   { "lcall",	Ap, XX, XX },
+   { "(bad)",	XX, XX, XX },		/* fwait */
+   { "pushf",	XX, XX, XX },
+   { "popf",	XX, XX, XX },
+   { "sahf",	XX, XX, XX },
+   { "lahf",	XX, XX, XX },
+   /* a0 */
+   { "mov",	AL, Ob, XX },
+   { "mov",	eAX, Ov, XX },
+   { "mov",	Ob, AL, XX },
+   { "mov",	Ov, eAX, XX },
+   { "movs",	Yb, Xb, XX },
+   { "movs",	Yv, Xv, XX },
+   { "cmps",	Xb, Yb, XX },
+   { "cmps",	Xv, Yv, XX },
+   /* a8 */
+   { "test",	AL, Ib, XX },
+   { "test",	eAX, Iv, XX },
+   { "stos",	Yb, AL, XX },
+   { "stos",	Yv, eAX, XX },
+   { "lods",	AL, Xb, XX },
+   { "lods",	eAX, Xv, XX },
+   { "scas",	AL, Yb, XX },
+   { "scas",	eAX, Yv, XX },
+   /* b0 */
+   { "mov",	AL, Ib, XX },
+   { "mov",	CL, Ib, XX },
+   { "mov",	DL, Ib, XX },
+   { "mov",	BL, Ib, XX },
+   { "mov",	AH, Ib, XX },
+   { "mov",	CH, Ib, XX },
+   { "mov",	DH, Ib, XX },
+   { "mov",	BH, Ib, XX },
+   /* b8 */
+   { "mov",	eAX, Iv, XX },
+   { "mov",	eCX, Iv, XX },
+   { "mov",	eDX, Iv, XX },
+   { "mov",	eBX, Iv, XX },
+   { "mov",	eSP, Iv, XX },
+   { "mov",	eBP, Iv, XX },
+   { "mov",	eSI, Iv, XX },
+   { "mov",	eDI, Iv, XX },
+   /* c0 */
+   { GRP2b },
+   { GRP2S },
+   { "ret",	Iw, XX, XX },
+   { "ret",	XX, XX, XX },
+   { "les",	Gv, Mp, XX },
+   { "lds",	Gv, Mp, XX },
+   { "mov",	Eb, Ib, XX },
+   { "mov",	Ev, Iv, XX },
+   /* c8 */
+   { "enter",	Iw, Ib, XX },
+   { "leave",	XX, XX, XX },
+   { "lret",	Iw, XX, XX },
+   { "lret",	XX, XX, XX },
+   { "int3",	XX, XX, XX },
+   { "int",	Ib, XX, XX },
+   { "into",	XX, XX, XX },
+   { "iret",	XX, XX, XX },
+   /* d0 */
+   { GRP2b_one },
+   { GRP2S_one },
+   { GRP2b_cl },
+   { GRP2S_cl },
+   { "aam",	sIb, XX, XX },
+   { "aad",	sIb, XX, XX },
+   { "(bad)",	XX, XX, XX },
+   { "xlat",	DSBX, XX, XX },
+   /* d8 */
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   { FLOAT },
+   /* e0 */
+   { "loopne",	Jb, XX, XX },
+   { "loope",	Jb, XX, XX },
+   { "loop",	Jb, XX, XX },
+   { "jEcxz",	Jb, XX, XX },
+   { "in",	AL, Ib, XX },
+   { "in",	eAX, Ib, XX },
+   { "out",	Ib, AL, XX },
+   { "out",	Ib, eAX, XX },
+   /* e8 */
+   { "call",	Jv, XX, XX },
+   { "jmp",	Jv, XX, XX },
+   { "ljmp",	Ap, XX, XX },
+   { "jmp",	Jb, XX, XX },
+   { "in",	AL, indirDX, XX },
+   { "in",	eAX, indirDX, XX },
+   { "out",	indirDX, AL, XX },
+   { "out",	indirDX, eAX, XX },
+   /* f0 */
+   { "(bad)",	XX, XX, XX },			/* lock prefix */
+   { "(bad)",	XX, XX, XX },
+   { "(bad)",	XX, XX, XX },			/* repne */
+   { "(bad)",	XX, XX, XX },			/* repz */
+   { "hlt",	XX, XX, XX },
+   { "cmc",	XX, XX, XX },
+   { GRP3b },
+   { GRP3S },
+   /* f8 */
+   { "clc",	XX, XX, XX },
+   { "stc",	XX, XX, XX },
+   { "cli",	XX, XX, XX },
+   { "sti",	XX, XX, XX },
+   { "cld",	XX, XX, XX },
+   { "std",	XX, XX, XX },
+   { GRP4 },
+   { GRP5 },
+ };
+ 
+ static const struct dis386 dis386_twobyte_att[] = {
+   /* 00 */
+   { GRP6 },
+   { GRP7 },
+   { "larS", Gv, Ew, XX },
+   { "lslS", Gv, Ew, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "clts", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   /* 08 */
+   { "invd", XX, XX, XX },
+   { "wbinvd", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "ud2a", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { GRPAMD },
+   { "femms", XX, XX, XX },
+   { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix */
+   /* 10 */
+   { PREGRP8 },
+   { PREGRP9 },
+   { "movlps", XM, EX, SIMD_Fixup, 'h' },  /* really only 2 operands */
+   { "movlps", EX, XM, SIMD_Fixup, 'h' },
+   { "unpcklps", XM, EX, XX },
+   { "unpckhps", XM, EX, XX },
+   { "movhps", XM, EX, SIMD_Fixup, 'l' },
+   { "movhps", EX, XM, SIMD_Fixup, 'l' },
+   /* 18 */
+   { GRP14 },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   /* 20 */
+   /* these are all backward in appendix A of the intel book */
+   { "movL", Rd, Cd, XX },
+   { "movL", Rd, Dd, XX },
+   { "movL", Cd, Rd, XX },
+   { "movL", Dd, Rd, XX },
+   { "movL", Rd, Td, XX },
+   { "(bad)", XX, XX, XX },
+   { "movL", Td, Rd, XX },
+   { "(bad)", XX, XX, XX },
+   /* 28 */
+   { "movaps", XM, EX, XX },
+   { "movaps", EX, XM, XX },
+   { PREGRP2 },
+   { "movntps", Ev, XM, XX },
+   { PREGRP4 },
+   { PREGRP3 },
+   { "ucomiss", XM, EX, XX },
+   { "comiss", XM, EX, XX },
+   /* 30 */
+   { "wrmsr", XX, XX, XX },
+   { "rdtsc", XX, XX, XX },
+   { "rdmsr", XX, XX, XX },
+   { "rdpmc", XX, XX, XX },
+   { "sysenter", XX, XX, XX },
+   { "sysexit", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   /* 38 */
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   /* 40 */
+   { "cmovo", Gv, Ev, XX },
+   { "cmovno", Gv, Ev, XX },
+   { "cmovb", Gv, Ev, XX },
+   { "cmovae", Gv, Ev, XX },
+   { "cmove", Gv, Ev, XX },
+   { "cmovne", Gv, Ev, XX },
+   { "cmovbe", Gv, Ev, XX },
+   { "cmova", Gv, Ev, XX },
+   /* 48 */
+   { "cmovs", Gv, Ev, XX },
+   { "cmovns", Gv, Ev, XX },
+   { "cmovp", Gv, Ev, XX },
+   { "cmovnp", Gv, Ev, XX },
+   { "cmovl", Gv, Ev, XX },
+   { "cmovge", Gv, Ev, XX },
+   { "cmovle", Gv, Ev, XX },
+   { "cmovg", Gv, Ev, XX },
+   /* 50 */
+   { "movmskps", Gv, EX, XX },
+   { PREGRP13 },
+   { PREGRP12 },
+   { PREGRP11 },
+   { "andps", XM, EX, XX },
+   { "andnps", XM, EX, XX },
+   { "orps", XM, EX, XX },
+   { "xorps", XM, EX, XX },
+   /* 58 */
+   { PREGRP0 },
+   { PREGRP10 },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { PREGRP14 },
+   { PREGRP7 },
+   { PREGRP5 },
+   { PREGRP6 },
+   /* 60 */
+   { "punpcklbw", MX, EM, XX },
+   { "punpcklwd", MX, EM, XX },
+   { "punpckldq", MX, EM, XX },
+   { "packsswb", MX, EM, XX },
+   { "pcmpgtb", MX, EM, XX },
+   { "pcmpgtw", MX, EM, XX },
+   { "pcmpgtd", MX, EM, XX },
+   { "packuswb", MX, EM, XX },
+   /* 68 */
+   { "punpckhbw", MX, EM, XX },
+   { "punpckhwd", MX, EM, XX },
+   { "punpckhdq", MX, EM, XX },
+   { "packssdw", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "movd", MX, Ed, XX },
+   { "movq", MX, EM, XX },
+   /* 70 */
+   { "pshufw", MX, EM, Ib },
+   { GRP10 },
+   { GRP11 },
+   { GRP12 },
+   { "pcmpeqb", MX, EM, XX },
+   { "pcmpeqw", MX, EM, XX },
+   { "pcmpeqd", MX, EM, XX },
+   { "emms", XX, XX, XX },
+   /* 78 */
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "movd", Ed, MX, XX },
+   { "movq", EM, MX, XX },
+   /* 80 */
+   { "jo", Jv, XX, XX },
+   { "jno", Jv, XX, XX },
+   { "jb", Jv, XX, XX },
+   { "jae", Jv, XX, XX },
+   { "je", Jv, XX, XX },
+   { "jne", Jv, XX, XX },
+   { "jbe", Jv, XX, XX },
+   { "ja", Jv, XX, XX },
+   /* 88 */
+   { "js", Jv, XX, XX },
+   { "jns", Jv, XX, XX },
+   { "jp", Jv, XX, XX },
+   { "jnp", Jv, XX, XX },
+   { "jl", Jv, XX, XX },
+   { "jge", Jv, XX, XX },
+   { "jle", Jv, XX, XX },
+   { "jg", Jv, XX, XX },
+   /* 90 */
+   { "seto", Eb, XX, XX },
+   { "setno", Eb, XX, XX },
+   { "setb", Eb, XX, XX },
+   { "setae", Eb, XX, XX },
+   { "sete", Eb, XX, XX },
+   { "setne", Eb, XX, XX },
+   { "setbe", Eb, XX, XX },
+   { "seta", Eb, XX, XX },
+   /* 98 */
+   { "sets", Eb, XX, XX },
+   { "setns", Eb, XX, XX },
+   { "setp", Eb, XX, XX },
+   { "setnp", Eb, XX, XX },
+   { "setl", Eb, XX, XX },
+   { "setge", Eb, XX, XX },
+   { "setle", Eb, XX, XX },
+   { "setg", Eb, XX, XX },
+   /* a0 */
+   { "pushP", fs, XX, XX },
+   { "popP", fs, XX, XX },
+   { "cpuid", XX, XX, XX },
+   { "btS", Ev, Gv, XX },
+   { "shldS", Ev, Gv, Ib },
+   { "shldS", Ev, Gv, CL },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   /* a8 */
+   { "pushP", gs, XX, XX },
+   { "popP", gs, XX, XX },
+   { "rsm", XX, XX, XX },
+   { "btsS", Ev, Gv, XX },
+   { "shrdS", Ev, Gv, Ib },
+   { "shrdS", Ev, Gv, CL },
+   { GRP13 },
+   { "imulS", Gv, Ev, XX },
+   /* b0 */
+   { "cmpxchgB", Eb, Gb, XX },
+   { "cmpxchgS", Ev, Gv, XX },
+   { "lssS", Gv, Mp, XX },
+   { "btrS", Ev, Gv, XX },
+   { "lfsS", Gv, Mp, XX },
+   { "lgsS", Gv, Mp, XX },
+   { "movzbR", Gv, Eb, XX },
+   { "movzwR", Gv, Ew, XX }, /* yes, there really is movzww ! */
+   /* b8 */
+   { "(bad)", XX, XX, XX },
+   { "ud2b", XX, XX, XX },
+   { GRP8 },
+   { "btcS", Ev, Gv, XX },
+   { "bsfS", Gv, Ev, XX },
+   { "bsrS", Gv, Ev, XX },
+   { "movsbR", Gv, Eb, XX },
+   { "movswR", Gv, Ew, XX }, /* yes, there really is movsww ! */
+   /* c0 */
+   { "xaddB", Eb, Gb, XX },
+   { "xaddS", Ev, Gv, XX },
+   { PREGRP1 },
+   { "(bad)", XX, XX, XX },
+   { "pinsrw", MX, Ev, Ib },
+   { "pextrw", Ev, MX, Ib },
+   { "shufps", XM, EX, Ib },
+   { GRP9 },
+   /* c8 */
+   { "bswap", eAX, XX, XX },	/* bswap doesn't support 16 bit regs */
+   { "bswap", eCX, XX, XX },
+   { "bswap", eDX, XX, XX },
+   { "bswap", eBX, XX, XX },
+   { "bswap", eSP, XX, XX },
+   { "bswap", eBP, XX, XX },
+   { "bswap", eSI, XX, XX },
+   { "bswap", eDI, XX, XX },
+   /* d0 */
+   { "(bad)", XX, XX, XX },
+   { "psrlw", MX, EM, XX },
+   { "psrld", MX, EM, XX },
+   { "psrlq", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "pmullw", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "pmovmskb", Ev, MX, XX },
+   /* d8 */
+   { "psubusb", MX, EM, XX },
+   { "psubusw", MX, EM, XX },
+   { "pminub", MX, EM, XX },
+   { "pand", MX, EM, XX },
+   { "paddusb", MX, EM, XX },
+   { "paddusw", MX, EM, XX },
+   { "pmaxub", MX, EM, XX },
+   { "pandn", MX, EM, XX },
+   /* e0 */
+   { "pavgb", MX, EM, XX },
+   { "psraw", MX, EM, XX },
+   { "psrad", MX, EM, XX },
+   { "pavgw", MX, EM, XX },
+   { "pmulhuw", MX, EM, XX },
+   { "pmulhw", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "movntq", Ev, MX, XX },
+   /* e8 */
+   { "psubsb", MX, EM, XX },
+   { "psubsw", MX, EM, XX },
+   { "pminsw", MX, EM, XX },
+   { "por", MX, EM, XX },
+   { "paddsb", MX, EM, XX },
+   { "paddsw", MX, EM, XX },
+   { "pmaxsw", MX, EM, XX },
+   { "pxor", MX, EM, XX },
+   /* f0 */
+   { "(bad)", XX, XX, XX },
+   { "psllw", MX, EM, XX },
+   { "pslld", MX, EM, XX },
+   { "psllq", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "pmaddwd", MX, EM, XX },
+   { "psadbw", MX, EM, XX },
+   { "maskmovq", MX, EM, XX },
+   /* f8 */
+   { "psubb", MX, EM, XX },
+   { "psubw", MX, EM, XX },
+   { "psubd", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "paddb", MX, EM, XX },
+   { "paddw", MX, EM, XX },
+   { "paddd", MX, EM, XX },
+   { "(bad)", XX, XX, XX }
+ };
+ 
+ static const struct dis386 dis386_twobyte_intel[] = {
+   /* 00 */
+   { GRP6 },
+   { GRP7 },
+   { "lar", Gv, Ew, XX },
+   { "lsl", Gv, Ew, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "clts", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   /* 08 */
+   { "invd", XX, XX, XX },
+   { "wbinvd", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "ud2a", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { GRPAMD },
+   { "femms" , XX, XX, XX},
+   { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix */
+   /* 10 */
+   { PREGRP8 },
+   { PREGRP9 },
+   { "movlps", XM, EX, SIMD_Fixup, 'h' },  /* really only 2 operands */
+   { "movlps", EX, XM, SIMD_Fixup, 'h' },
+   { "unpcklps", XM, EX, XX },
+   { "unpckhps", XM, EX, XX },
+   { "movhps", XM, EX, SIMD_Fixup, 'l' },
+   { "movhps", EX, XM, SIMD_Fixup, 'l' },
+   /* 18 */
+   { GRP14 },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   /* 20 */
+   /* these are all backward in appendix A of the intel book */
+   { "mov", Rd, Cd, XX },
+   { "mov", Rd, Dd, XX },
+   { "mov", Cd, Rd, XX },
+   { "mov", Dd, Rd, XX },
+   { "mov", Rd, Td, XX },
+   { "(bad)", XX, XX, XX },
+   { "mov", Td, Rd, XX },
+   { "(bad)", XX, XX, XX },
+   /* 28 */
+   { "movaps", XM, EX, XX },
+   { "movaps", EX, XM, XX },
+   { PREGRP2 },
+   { "movntps", Ev, XM, XX },
+   { PREGRP4 },
+   { PREGRP3 },
+   { "ucomiss", XM, EX, XX },
+   { "comiss", XM, EX, XX },
+   /* 30 */
+   { "wrmsr", XX, XX, XX },
+   { "rdtsc", XX, XX, XX },
+   { "rdmsr", XX, XX, XX },
+   { "rdpmc", XX, XX, XX },
+   { "sysenter", XX, XX, XX },
+   { "sysexit", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   /* 38 */
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   /* 40 */
+   { "cmovo", Gv, Ev, XX },
+   { "cmovno", Gv, Ev, XX },
+   { "cmovb", Gv, Ev, XX },
+   { "cmovae", Gv, Ev, XX },
+   { "cmove", Gv, Ev, XX },
+   { "cmovne", Gv, Ev, XX },
+   { "cmovbe", Gv, Ev, XX },
+   { "cmova", Gv, Ev, XX },
+   /* 48 */
+   { "cmovs", Gv, Ev, XX },
+   { "cmovns", Gv, Ev, XX },
+   { "cmovp", Gv, Ev, XX },
+   { "cmovnp", Gv, Ev, XX },
+   { "cmovl", Gv, Ev, XX },
+   { "cmovge", Gv, Ev, XX },
+   { "cmovle", Gv, Ev, XX },
+   { "cmovg", Gv, Ev, XX },
+   /* 50 */
+   { "movmskps", Gv, EX, XX },
+   { PREGRP13 },
+   { PREGRP12 },
+   { PREGRP11 },
+   { "andps", XM, EX, XX },
+   { "andnps", XM, EX, XX },
+   { "orps", XM, EX, XX },
+   { "xorps", XM, EX, XX },
+   /* 58 */
+   { PREGRP0 },
+   { PREGRP10 },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { PREGRP14 },
+   { PREGRP7 },
+   { PREGRP5 },
+   { PREGRP6 },
+   /* 60 */
+   { "punpcklbw", MX, EM, XX },
+   { "punpcklwd", MX, EM, XX },
+   { "punpckldq", MX, EM, XX },
+   { "packsswb", MX, EM, XX },
+   { "pcmpgtb", MX, EM, XX },
+   { "pcmpgtw", MX, EM, XX },
+   { "pcmpgtd", MX, EM, XX },
+   { "packuswb", MX, EM, XX },
+   /* 68 */
+   { "punpckhbw", MX, EM, XX },
+   { "punpckhwd", MX, EM, XX },
+   { "punpckhdq", MX, EM, XX },
+   { "packssdw", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "movd", MX, Ed, XX },
+   { "movq", MX, EM, XX },
+   /* 70 */
+   { "pshufw", MX, EM, Ib },
+   { GRP10 },
+   { GRP11 },
+   { GRP12 },
+   { "pcmpeqb", MX, EM, XX },
+   { "pcmpeqw", MX, EM, XX },
+   { "pcmpeqd", MX, EM, XX },
+   { "emms", XX, XX, XX },
+   /* 78 */
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   { "movd", Ed, MX, XX },
+   { "movq", EM, MX, XX },
+   /* 80 */
+   { "jo", Jv, XX, XX },
+   { "jno", Jv, XX, XX },
+   { "jb", Jv, XX, XX },
+   { "jae", Jv, XX, XX },
+   { "je", Jv, XX, XX },
+   { "jne", Jv, XX, XX },
+   { "jbe", Jv, XX, XX },
+   { "ja", Jv, XX, XX },
+   /* 88 */
+   { "js", Jv, XX, XX },
+   { "jns", Jv, XX, XX },
+   { "jp", Jv, XX, XX },
+   { "jnp", Jv, XX, XX },
+   { "jl", Jv, XX, XX },
+   { "jge", Jv, XX, XX },
+   { "jle", Jv, XX, XX },
+   { "jg", Jv, XX, XX },
+   /* 90 */
+   { "seto", Eb, XX, XX },
+   { "setno", Eb, XX, XX },
+   { "setb", Eb, XX, XX },
+   { "setae", Eb, XX, XX },
+   { "sete", Eb, XX, XX },
+   { "setne", Eb, XX, XX },
+   { "setbe", Eb, XX, XX },
+   { "seta", Eb, XX, XX },
+   /* 98 */
+   { "sets", Eb, XX, XX },
+   { "setns", Eb, XX, XX },
+   { "setp", Eb, XX, XX },
+   { "setnp", Eb, XX, XX },
+   { "setl", Eb, XX, XX },
+   { "setge", Eb, XX, XX },
+   { "setle", Eb, XX, XX },
+   { "setg", Eb, XX, XX },
+   /* a0 */
+   { "push", fs, XX, XX },
+   { "pop", fs, XX, XX },
+   { "cpuid", XX, XX, XX },
+   { "bt", Ev, Gv, XX },
+   { "shld", Ev, Gv, Ib },
+   { "shld", Ev, Gv, CL },
+   { "(bad)", XX, XX, XX },
+   { "(bad)", XX, XX, XX },
+   /* a8 */
+   { "push", gs, XX, XX },
+   { "pop", gs, XX, XX },
+   { "rsm" , XX, XX, XX},
+   { "bts", Ev, Gv, XX },
+   { "shrd", Ev, Gv, Ib },
+   { "shrd", Ev, Gv, CL },
+   { GRP13 },
+   { "imul", Gv, Ev, XX },
+   /* b0 */
+   { "cmpxchg", Eb, Gb, XX },
+   { "cmpxchg", Ev, Gv, XX },
+   { "lss", Gv, Mp, XX },
+   { "btr", Ev, Gv, XX },
+   { "lfs", Gv, Mp, XX },
+   { "lgs", Gv, Mp, XX },
+   { "movzx", Gv, Eb, XX },
+   { "movzx", Gv, Ew, XX },
+   /* b8 */
+   { "(bad)", XX, XX, XX },
+   { "ud2b", XX, XX, XX },
+   { GRP8 },
+   { "btc", Ev, Gv, XX },
+   { "bsf", Gv, Ev, XX },
+   { "bsr", Gv, Ev, XX },
+   { "movsx", Gv, Eb, XX },
+   { "movsx", Gv, Ew, XX },
+   /* c0 */
+   { "xadd", Eb, Gb, XX },
+   { "xadd", Ev, Gv, XX },
+   { PREGRP1 },
+   { "(bad)", XX, XX, XX },
+   { "pinsrw", MX, Ev, Ib },
+   { "pextrw", Ev, MX, Ib },
+   { "shufps", XM, EX, Ib },
+   { GRP9 },
+   /* c8 */
+   { "bswap", eAX, XX, XX },	/* bswap doesn't support 16 bit regs */
+   { "bswap", eCX, XX, XX },
+   { "bswap", eDX, XX, XX },
+   { "bswap", eBX, XX, XX },
+   { "bswap", eSP, XX, XX },
+   { "bswap", eBP, XX, XX },
+   { "bswap", eSI, XX, XX },
+   { "bswap", eDI, XX, XX },
+   /* d0 */
+   { "(bad)", XX, XX, XX },
+   { "psrlw", MX, EM, XX },
+   { "psrld", MX, EM, XX },
+   { "psrlq", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "pmullw", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "pmovmskb", Ev, MX, XX },
+   /* d8 */
+   { "psubusb", MX, EM, XX },
+   { "psubusw", MX, EM, XX },
+   { "pminub", MX, EM, XX },
+   { "pand", MX, EM, XX },
+   { "paddusb", MX, EM, XX },
+   { "paddusw", MX, EM, XX },
+   { "pmaxub", MX, EM, XX },
+   { "pandn", MX, EM, XX },
+   /* e0 */
+   { "pavgb", MX, EM, XX },
+   { "psraw", MX, EM, XX },
+   { "psrad", MX, EM, XX },
+   { "pavgw", MX, EM, XX },
+   { "pmulhuw", MX, EM, XX },
+   { "pmulhw", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "movntq", Ev, MX, XX },
+   /* e8 */
+   { "psubsb", MX, EM, XX },
+   { "psubsw", MX, EM, XX },
+   { "pminsw", MX, EM, XX },
+   { "por", MX, EM, XX },
+   { "paddsb", MX, EM, XX },
+   { "paddsw", MX, EM, XX },
+   { "pmaxsw", MX, EM, XX },
+   { "pxor", MX, EM, XX },
+   /* f0 */
+   { "(bad)", XX, XX, XX },
+   { "psllw", MX, EM, XX },
+   { "pslld", MX, EM, XX },
+   { "psllq", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "pmaddwd", MX, EM, XX },
+   { "psadbw", MX, EM, XX },
+   { "maskmovq", MX, EM, XX },
+   /* f8 */
+   { "psubb", MX, EM, XX },
+   { "psubw", MX, EM, XX },
+   { "psubd", MX, EM, XX },
+   { "(bad)", XX, XX, XX },
+   { "paddb", MX, EM, XX },
+   { "paddw", MX, EM, XX },
+   { "paddd", MX, EM, XX },
+   { "(bad)", XX, XX, XX }
+ };
+ 
+ static const unsigned char onebyte_has_modrm[256] = {
+   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+   /*       -------------------------------        */
+   /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */
+   /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */
+   /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */
+   /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */
+   /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */
+   /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
+   /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */
+   /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */
+   /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */
+   /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */
+   /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */
+   /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */
+   /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */
+   /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */
+   /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */
+   /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1  /* f0 */
+   /*       -------------------------------        */
+   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+ };
+ 
+ static const unsigned char twobyte_has_modrm[256] = {
+   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+   /*       -------------------------------        */
+   /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */
+   /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */
+   /* 20 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 2f */
+   /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+   /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
+   /* 50 */ 1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1, /* 5f */
+   /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1, /* 6f */
+   /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */
+   /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+   /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
+   /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
+   /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
+   /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
+   /* d0 */ 0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1, /* df */
+   /* e0 */ 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, /* ef */
+   /* f0 */ 0,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0  /* ff */
+   /*       -------------------------------        */
+   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+ };
+ 
+ static const unsigned char twobyte_uses_f3_prefix[256] = {
+   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+   /*       -------------------------------        */
+   /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+   /* 10 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+   /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */
+   /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+   /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+   /* 50 */ 0,1,1,1,0,0,0,0,1,1,0,0,1,1,1,1, /* 5f */
+   /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+   /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+   /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+   /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+   /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+   /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+   /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+   /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+   /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+   /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0  /* ff */
+   /*       -------------------------------        */
+   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+ };
+ 
+ static char obuf[100];
+ static char *obufp;
+ static char scratchbuf[100];
+ static unsigned char *start_codep;
+ static unsigned char *insn_codep;
+ static unsigned char *codep;
+ static disassemble_info *the_info;
+ static int mod;
+ static int rm;
+ static int reg;
+ static void oappend PARAMS ((const char *s));
+ 
+ static const char *names32[]={
+   "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
+ };
+ static const char *names16[] = {
+   "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
+ };
+ static const char *names8[] = {
+   "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
+ };
+ static const char *names_seg[] = {
+   "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+ };
+ static const char *index16[] = {
+   "%bx,%si","%bx,%di","%bp,%si","%bp,%di","%si","%di","%bp","%bx"
+ };
+ 
+ static const struct dis386 grps[][8] = {
+   /* GRP1b */
+   {
+     { "addA",	Eb, Ib, XX },
+     { "orA",	Eb, Ib, XX },
+     { "adcA",	Eb, Ib, XX },
+     { "sbbA",	Eb, Ib, XX },
+     { "andA",	Eb, Ib, XX },
+     { "subA",	Eb, Ib, XX },
+     { "xorA",	Eb, Ib, XX },
+     { "cmpA",	Eb, Ib, XX }
+   },
+   /* GRP1S */
+   {
+     { "addQ",	Ev, Iv, XX },
+     { "orQ",	Ev, Iv, XX },
+     { "adcQ",	Ev, Iv, XX },
+     { "sbbQ",	Ev, Iv, XX },
+     { "andQ",	Ev, Iv, XX },
+     { "subQ",	Ev, Iv, XX },
+     { "xorQ",	Ev, Iv, XX },
+     { "cmpQ",	Ev, Iv, XX }
+   },
+   /* GRP1Ss */
+   {
+     { "addQ",	Ev, sIb, XX },
+     { "orQ",	Ev, sIb, XX },
+     { "adcQ",	Ev, sIb, XX },
+     { "sbbQ",	Ev, sIb, XX },
+     { "andQ",	Ev, sIb, XX },
+     { "subQ",	Ev, sIb, XX },
+     { "xorQ",	Ev, sIb, XX },
+     { "cmpQ",	Ev, sIb, XX }
+   },
+   /* GRP2b */
+   {
+     { "rolA",	Eb, Ib, XX },
+     { "rorA",	Eb, Ib, XX },
+     { "rclA",	Eb, Ib, XX },
+     { "rcrA",	Eb, Ib, XX },
+     { "shlA",	Eb, Ib, XX },
+     { "shrA",	Eb, Ib, XX },
+     { "(bad)",	XX, XX, XX },
+     { "sarA",	Eb, Ib, XX },
+   },
+   /* GRP2S */
+   {
+     { "rolQ",	Ev, Ib, XX },
+     { "rorQ",	Ev, Ib, XX },
+     { "rclQ",	Ev, Ib, XX },
+     { "rcrQ",	Ev, Ib, XX },
+     { "shlQ",	Ev, Ib, XX },
+     { "shrQ",	Ev, Ib, XX },
+     { "(bad)",	XX, XX, XX },
+     { "sarQ",	Ev, Ib, XX },
+   },
+   /* GRP2b_one */
+   {
+     { "rolA",	Eb, XX, XX },
+     { "rorA",	Eb, XX, XX },
+     { "rclA",	Eb, XX, XX },
+     { "rcrA",	Eb, XX, XX },
+     { "shlA",	Eb, XX, XX },
+     { "shrA",	Eb, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "sarA",	Eb, XX, XX },
+   },
+   /* GRP2S_one */
+   {
+     { "rolQ",	Ev, XX, XX },
+     { "rorQ",	Ev, XX, XX },
+     { "rclQ",	Ev, XX, XX },
+     { "rcrQ",	Ev, XX, XX },
+     { "shlQ",	Ev, XX, XX },
+     { "shrQ",	Ev, XX, XX },
+     { "(bad)",	XX, XX, XX},
+     { "sarQ",	Ev, XX, XX },
+   },
+   /* GRP2b_cl */
+   {
+     { "rolA",	Eb, CL, XX },
+     { "rorA",	Eb, CL, XX },
+     { "rclA",	Eb, CL, XX },
+     { "rcrA",	Eb, CL, XX },
+     { "shlA",	Eb, CL, XX },
+     { "shrA",	Eb, CL, XX },
+     { "(bad)",	XX, XX, XX },
+     { "sarA",	Eb, CL, XX },
+   },
+   /* GRP2S_cl */
+   {
+     { "rolQ",	Ev, CL, XX },
+     { "rorQ",	Ev, CL, XX },
+     { "rclQ",	Ev, CL, XX },
+     { "rcrQ",	Ev, CL, XX },
+     { "shlQ",	Ev, CL, XX },
+     { "shrQ",	Ev, CL, XX },
+     { "(bad)",	XX, XX, XX },
+     { "sarQ",	Ev, CL, XX }
+   },
+   /* GRP3b */
+   {
+     { "testA",	Eb, Ib, XX },
+     { "(bad)",	Eb, XX, XX },
+     { "notA",	Eb, XX, XX },
+     { "negA",	Eb, XX, XX },
+     { "mulB",	AL, Eb, XX },
+     { "imulB",	AL, Eb, XX },
+     { "divB",	AL, Eb, XX },
+     { "idivB",	AL, Eb, XX }
+   },
+   /* GRP3S */
+   {
+     { "testQ",	Ev, Iv, XX },
+     { "(bad)",	XX, XX, XX },
+     { "notQ",	Ev, XX, XX },
+     { "negQ",	Ev, XX, XX },
+     { "mulS",	eAX, Ev, XX },
+     { "imulS",	eAX, Ev, XX },
+     { "divS",	eAX, Ev, XX },
+     { "idivS",	eAX, Ev, XX },
+   },
+   /* GRP4 */
+   {
+     { "incA",	Eb, XX, XX },
+     { "decA",	Eb, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+   /* GRP5 */
+   {
+     { "incQ",	Ev, XX, XX },
+     { "decQ",	Ev, XX, XX },
+     { "callP",	indirEv, XX, XX },
+     { "lcallP",	indirEv, XX, XX },
+     { "jmpP",	indirEv, XX, XX },
+     { "ljmpP",	indirEv, XX, XX },
+     { "pushQ",	Ev, XX, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+   /* GRP6 */
+   {
+     { "sldt",	Ew, XX, XX },
+     { "str",	Ew, XX, XX },
+     { "lldt",	Ew, XX, XX },
+     { "ltr",	Ew, XX, XX },
+     { "verr",	Ew, XX, XX },
+     { "verw",	Ew, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX }
+   },
+   /* GRP7 */
+   {
+     { "sgdt", Ew, XX, XX },
+     { "sidt", Ew, XX, XX },
+     { "lgdt", Ew, XX, XX },
+     { "lidt", Ew, XX, XX },
+     { "smsw", Ew, XX, XX },
+     { "(bad)", XX, XX, XX },
+     { "lmsw", Ew, XX, XX },
+     { "invlpg", Ew, XX, XX },
+   },
+   /* GRP8 */
+   {
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "btQ",	Ev, Ib, XX },
+     { "btsQ",	Ev, Ib, XX },
+     { "btrQ",	Ev, Ib, XX },
+     { "btcQ",	Ev, Ib, XX },
+   },
+   /* GRP9 */
+   {
+     { "(bad)",	XX, XX, XX },
+     { "cmpxchg8b", Ev, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+   /* GRP10 */
+   {
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "psrlw",	MS, Ib, XX },
+     { "(bad)",	XX, XX, XX },
+     { "psraw",	MS, Ib, XX },
+     { "(bad)",	XX, XX, XX },
+     { "psllw",	MS, Ib, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+   /* GRP11 */
+   {
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "psrld",	MS, Ib, XX },
+     { "(bad)",	XX, XX, XX },
+     { "psrad",	MS, Ib, XX },
+     { "(bad)",	XX, XX, XX },
+     { "pslld",	MS, Ib, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+   /* GRP12 */
+   {
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "psrlq",	MS, Ib, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "psllq",	MS, Ib, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+   /* GRP13 */
+   {
+     { "fxsave", Ev, XX, XX },
+     { "fxrstor", Ev, XX, XX },
+     { "ldmxcsr", Ev, XX, XX },
+     { "stmxcsr", Ev, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "sfence", None, XX, XX },
+   },
+   /* GRP14 */
+   {
+     { "prefetchnta", Ev, XX, XX },
+     { "prefetcht0", Ev, XX, XX },
+     { "prefetcht1", Ev, XX, XX },
+     { "prefetcht2", Ev, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+   /* GRPAMD */
+   {
+     { "prefetch", Eb, XX, XX },
+     { "prefetchw", Eb, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+   }
+ 
+ };
+ 
+ static const struct dis386 prefix_user_table[][2] = {
+   /* PREGRP0 */
+   {
+     { "addps", XM, EX, XX },
+     { "addss", XM, EX, XX },
+   },
+   /* PREGRP1 */
+   {
+     { "", XM, EX, OPSIMD },	/* See OP_SIMD_SUFFIX */
+     { "", XM, EX, OPSIMD },
+   },
+   /* PREGRP2 */
+   {
+     { "cvtpi2ps", XM, EM, XX },
+     { "cvtsi2ss", XM, Ev, XX },
+   },
+   /* PREGRP3 */
+   {
+     { "cvtps2pi", MX, EX, XX },
+     { "cvtss2si", Gv, EX, XX },
+   },
+   /* PREGRP4 */
+   {
+     { "cvttps2pi", MX, EX, XX },
+     { "cvttss2si", Gv, EX, XX },
+   },
+   /* PREGRP5 */
+   {
+     { "divps", XM, EX, XX },
+     { "divss", XM, EX, XX },
+   },
+   /* PREGRP6 */
+   {
+     { "maxps", XM, EX, XX },
+     { "maxss", XM, EX, XX },
+   },
+   /* PREGRP7 */
+   {
+     { "minps", XM, EX, XX },
+     { "minss", XM, EX, XX },
+   },
+   /* PREGRP8 */
+   {
+     { "movups", XM, EX, XX },
+     { "movss", XM, EX, XX },
+   },
+   /* PREGRP9 */
+   {
+     { "movups", EX, XM, XX },
+     { "movss", EX, XM, XX },
+   },
+   /* PREGRP10 */
+   {
+     { "mulps", XM, EX, XX },
+     { "mulss", XM, EX, XX },
+   },
+   /* PREGRP11 */
+   {
+     { "rcpps", XM, EX, XX },
+     { "rcpss", XM, EX, XX },
+   },
+   /* PREGRP12 */
+   {
+     { "rsqrtps", XM, EX, XX },
+     { "rsqrtss", XM, EX, XX },
+   },
+   /* PREGRP13 */
+   {
+     { "sqrtps", XM, EX, XX },
+     { "sqrtss", XM, EX, XX },
+   },
+   /* PREGRP14 */
+   {
+     { "subps", XM, EX, XX },
+     { "subss", XM, EX, XX },
+   }
+ };
+ 
+ #define INTERNAL_DISASSEMBLER_ERROR "<internal disassembler error>"
+ 
+ static void
+ ckprefix ()
+ {
+   prefixes = 0;
+   used_prefixes = 0;
+   while (1)
+     {
+       FETCH_DATA (the_info, codep + 1);
+       switch (*codep)
+ 	{
+ 	case 0xf3:
+ 	  prefixes |= PREFIX_REPZ;
+ 	  break;
+ 	case 0xf2:
+ 	  prefixes |= PREFIX_REPNZ;
+ 	  break;
+ 	case 0xf0:
+ 	  prefixes |= PREFIX_LOCK;
+ 	  break;
+ 	case 0x2e:
+ 	  prefixes |= PREFIX_CS;
+ 	  break;
+ 	case 0x36:
+ 	  prefixes |= PREFIX_SS;
+ 	  break;
+ 	case 0x3e:
+ 	  prefixes |= PREFIX_DS;
+ 	  break;
+ 	case 0x26:
+ 	  prefixes |= PREFIX_ES;
+ 	  break;
+ 	case 0x64:
+ 	  prefixes |= PREFIX_FS;
+ 	  break;
+ 	case 0x65:
+ 	  prefixes |= PREFIX_GS;
+ 	  break;
+ 	case 0x66:
+ 	  prefixes |= PREFIX_DATA;
+ 	  break;
+ 	case 0x67:
+ 	  prefixes |= PREFIX_ADDR;
+ 	  break;
+ 	case FWAIT_OPCODE:
+ 	  /* fwait is really an instruction.  If there are prefixes
+ 	     before the fwait, they belong to the fwait, *not* to the
+ 	     following instruction.  */
+ 	  if (prefixes)
+ 	    {
+ 	      prefixes |= PREFIX_FWAIT;
+ 	      codep++;
+ 	      return;
+ 	    }
+ 	  prefixes = PREFIX_FWAIT;
+ 	  break;
+ 	default:
+ 	  return;
+ 	}
+       codep++;
+     }
+ }
+ 
+ /* Return the name of the prefix byte PREF, or NULL if PREF is not a
+    prefix byte.  */
+ 
+ static const char *
+ prefix_name (pref, sizeflag)
+      int pref;
+      int sizeflag;
+ {
+   switch (pref)
+     {
+     case 0xf3:
+       return "repz";
+     case 0xf2:
+       return "repnz";
+     case 0xf0:
+       return "lock";
+     case 0x2e:
+       return "cs";
+     case 0x36:
+       return "ss";
+     case 0x3e:
+       return "ds";
+     case 0x26:
+       return "es";
+     case 0x64:
+       return "fs";
+     case 0x65:
+       return "gs";
+     case 0x66:
+       return (sizeflag & DFLAG) ? "data16" : "data32";
+     case 0x67:
+       return (sizeflag & AFLAG) ? "addr16" : "addr32";
+     case FWAIT_OPCODE:
+       return "fwait";
+     default:
+       return NULL;
+     }
+ }
+ 
+ static char op1out[100], op2out[100], op3out[100];
+ static int op_ad, op_index[3];
+ static unsigned int op_address[3];
+ static unsigned int start_pc;
+ 
+ 
+ /*
+  *   On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+  *   (see topic "Redundant prefixes" in the "Differences from 8086"
+  *   section of the "Virtual 8086 Mode" chapter.)
+  * 'pc' should be the address of this instruction, it will
+  *   be used to print the target address if this is a relative jump or call
+  * The function returns the length of this instruction in bytes.
+  */
+ 
+ static int print_insn_i386
+   PARAMS ((bfd_vma pc, disassemble_info *info));
+ 
+ static char intel_syntax;
+ static char open_char;
+ static char close_char;
+ static char separator_char;
+ static char scale_char;
+ 
+ int
+ print_insn_i386_att (pc, info)
+      bfd_vma pc;
+      disassemble_info *info;
+ {
+   intel_syntax = 0;
+   open_char = '(';
+   close_char =  ')';
+   separator_char = ',';
+   scale_char = ',';
+ 
+   return print_insn_i386 (pc, info);
+ }
+ 
+ int
+ print_insn_i386_intel (pc, info)
+      bfd_vma pc;
+      disassemble_info *info;
+ {
+   intel_syntax = 1;
+   open_char = '[';
+   close_char = ']';
+   separator_char = '+';
+   scale_char = '*';
+ 
+   return print_insn_i386 (pc, info);
+ }
+ 
+ static int
+ print_insn_i386 (pc, info)
+      bfd_vma pc;
+      disassemble_info *info;
+ {
+   const struct dis386 *dp;
+   int i;
+   int two_source_ops;
+   char *first, *second, *third;
+   int needcomma;
+   unsigned char need_modrm;
+   unsigned char uses_f3_prefix;
+   VOLATILE int sizeflag;
+   VOLATILE int orig_sizeflag;
+ 
+   struct dis_private priv;
+   bfd_byte *inbuf = priv.the_buffer;
+ 
+   if (info->mach == bfd_mach_i386_i386
+       || info->mach == bfd_mach_i386_i386_intel_syntax)
+     sizeflag = AFLAG|DFLAG;
+   else if (info->mach == bfd_mach_i386_i8086)
+     sizeflag = 0;
+   else
+     abort ();
+   orig_sizeflag = sizeflag;
+ 
+   /* The output looks better if we put 7 bytes on a line, since that
+      puts most long word instructions on a single line.  */
+   info->bytes_per_line = 7;
+ 
+   info->private_data = (PTR) &priv;
+   priv.max_fetched = priv.the_buffer;
+   priv.insn_start = pc;
+ 
+   obuf[0] = 0;
+   op1out[0] = 0;
+   op2out[0] = 0;
+   op3out[0] = 0;
+ 
+   op_index[0] = op_index[1] = op_index[2] = -1;
+ 
+   the_info = info;
+   start_pc = pc;
+   start_codep = inbuf;
+   codep = inbuf;
+ 
+ #ifndef __KERNEL__
+   if (setjmp (priv.bailout) != 0)
+     {
+       const char *name;
+ 
+       /* Getting here means we tried for data but didn't get it.  That
+          means we have an incomplete instruction of some sort.  Just
+          print the first byte as a prefix or a .byte pseudo-op.  */
+       if (codep > inbuf)
+ 	{
+ 	  name = prefix_name (inbuf[0], orig_sizeflag);
+ 	  if (name != NULL)
+ 	    (*info->fprintf_func) (info->stream, "%s", name);
+ 	  else
+ 	    {
+ 	      /* Just print the first byte as a .byte instruction.  */
+ 	      (*info->fprintf_func) (info->stream, ".byte 0x%x",
+ 				     (unsigned int) inbuf[0]);
+ 	    }
+ 
+ 	  return 1;
+ 	}
+ 
+       return -1;
+     }
+ #endif
+ 
+   ckprefix ();
+ 
+   insn_codep = codep;
+ 
+   FETCH_DATA (info, codep + 1);
+   two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
+ 
+   obufp = obuf;
+ 
+   if ((prefixes & PREFIX_FWAIT)
+       && ((*codep < 0xd8) || (*codep > 0xdf)))
+     {
+       const char *name;
+ 
+       /* fwait not followed by floating point instruction.  Print the
+          first prefix, which is probably fwait itself.  */
+       name = prefix_name (inbuf[0], orig_sizeflag);
+       if (name == NULL)
+ 	name = INTERNAL_DISASSEMBLER_ERROR;
+       (*info->fprintf_func) (info->stream, "%s", name);
+       return 1;
+     }
+ 
+   if (*codep == 0x0f)
+     {
+       FETCH_DATA (info, codep + 2);
+       if (intel_syntax)
+         dp = &dis386_twobyte_intel[*++codep];
+       else
+         dp = &dis386_twobyte_att[*++codep];
+       need_modrm = twobyte_has_modrm[*codep];
+       uses_f3_prefix = twobyte_uses_f3_prefix[*codep];
+     }
+   else
+     {
+       if (intel_syntax)
+         dp = &dis386_intel[*codep];
+       else
+         dp = &dis386_att[*codep];
+       need_modrm = onebyte_has_modrm[*codep];
+       uses_f3_prefix = 0;
+     }
+   codep++;
+ 
+   if (!uses_f3_prefix && (prefixes & PREFIX_REPZ))
+     {
+       oappend ("repz ");
+       used_prefixes |= PREFIX_REPZ;
+     }
+   if (prefixes & PREFIX_REPNZ)
+     {
+       oappend ("repnz ");
+       used_prefixes |= PREFIX_REPNZ;
+     }
+   if (prefixes & PREFIX_LOCK)
+     {
+       oappend ("lock ");
+       used_prefixes |= PREFIX_LOCK;
+     }
+ 
+   if (prefixes & PREFIX_DATA)
+     sizeflag ^= DFLAG;
+ 
+   if (prefixes & PREFIX_ADDR)
+     {
+       sizeflag ^= AFLAG;
+       if (sizeflag & AFLAG)
+         oappend ("addr32 ");
+       else
+ 	oappend ("addr16 ");
+       used_prefixes |= PREFIX_ADDR;
+     }
+ 
+   if (need_modrm)
+     {
+       FETCH_DATA (info, codep + 1);
+       mod = (*codep >> 6) & 3;
+       reg = (*codep >> 3) & 7;
+       rm = *codep & 7;
+     }
+ 
+   if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
+     {
+       dofloat (sizeflag);
+     }
+   else
+     {
+       if (dp->name == NULL)
+ 	{
+ 	  switch(dp->bytemode2)
+ 	    {
+ 	      case USE_GROUPS:
+ 	        dp = &grps[dp->bytemode1][reg];
+ 		break;
+ 	      case USE_PREFIX_USER_TABLE:
+ 		dp = &prefix_user_table[dp->bytemode1][prefixes & PREFIX_REPZ ? 1 : 0];
+ 		used_prefixes |= (prefixes & PREFIX_REPZ);
+ 		break;
+ 	      default:
+ 		oappend (INTERNAL_DISASSEMBLER_ERROR);
+ 		break;
+ 	    }
+ 	}
+ 
+       putop (dp->name, sizeflag);
+ 
+       obufp = op1out;
+       op_ad = 2;
+       if (dp->op1)
+ 	(*dp->op1)(dp->bytemode1, sizeflag);
+ 
+       obufp = op2out;
+       op_ad = 1;
+       if (dp->op2)
+ 	(*dp->op2)(dp->bytemode2, sizeflag);
+ 
+       obufp = op3out;
+       op_ad = 0;
+       if (dp->op3)
+ 	(*dp->op3)(dp->bytemode3, sizeflag);
+     }
+ 
+   /* See if any prefixes were not used.  If so, print the first one
+      separately.  If we don't do this, we'll wind up printing an
+      instruction stream which does not precisely correspond to the
+      bytes we are disassembling.  */
+   if ((prefixes & ~used_prefixes) != 0)
+     {
+       const char *name;
+ 
+       name = prefix_name (inbuf[0], orig_sizeflag);
+       if (name == NULL)
+ 	name = INTERNAL_DISASSEMBLER_ERROR;
+       (*info->fprintf_func) (info->stream, "%s", name);
+       return 1;
+     }
+ 
+   obufp = obuf + strlen (obuf);
+   for (i = strlen (obuf); i < 6; i++)
+     oappend (" ");
+   oappend (" ");
+   (*info->fprintf_func) (info->stream, "%s", obuf);
+ 
+   /* The enter and bound instructions are printed with operands in the same
+      order as the intel book; everything else is printed in reverse order.  */
+   if (intel_syntax || two_source_ops)
+     {
+       first = op1out;
+       second = op2out;
+       third = op3out;
+       op_ad = op_index[0];
+       op_index[0] = op_index[2];
+       op_index[2] = op_ad;
+     }
+   else
+     {
+       first = op3out;
+       second = op2out;
+       third = op1out;
+     }
+   needcomma = 0;
+   if (*first)
+     {
+       if (op_index[0] != -1)
+ 	(*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info);
+       else
+ 	(*info->fprintf_func) (info->stream, "%s", first);
+       needcomma = 1;
+     }
+   if (*second)
+     {
+       if (needcomma)
+ 	(*info->fprintf_func) (info->stream, ",");
+       if (op_index[1] != -1)
+ 	(*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info);
+       else
+ 	(*info->fprintf_func) (info->stream, "%s", second);
+       needcomma = 1;
+     }
+   if (*third)
+     {
+       if (needcomma)
+ 	(*info->fprintf_func) (info->stream, ",");
+       if (op_index[2] != -1)
+ 	(*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
+       else
+ 	(*info->fprintf_func) (info->stream, "%s", third);
+     }
+   return codep - inbuf;
+ }
+ 
+ static const char *float_mem_att[] = {
+   /* d8 */
+   "fadds",
+   "fmuls",
+   "fcoms",
+   "fcomps",
+   "fsubs",
+   "fsubrs",
+   "fdivs",
+   "fdivrs",
+   /*  d9 */
+   "flds",
+   "(bad)",
+   "fsts",
+   "fstps",
+   "fldenv",
+   "fldcw",
+   "fNstenv",
+   "fNstcw",
+   /* da */
+   "fiaddl",
+   "fimull",
+   "ficoml",
+   "ficompl",
+   "fisubl",
+   "fisubrl",
+   "fidivl",
+   "fidivrl",
+   /* db */
+   "fildl",
+   "(bad)",
+   "fistl",
+   "fistpl",
+   "(bad)",
+   "fldt",
+   "(bad)",
+   "fstpt",
+   /* dc */
+   "faddl",
+   "fmull",
+   "fcoml",
+   "fcompl",
+   "fsubl",
+   "fsubrl",
+   "fdivl",
+   "fdivrl",
+   /* dd */
+   "fldl",
+   "(bad)",
+   "fstl",
+   "fstpl",
+   "frstor",
+   "(bad)",
+   "fNsave",
+   "fNstsw",
+   /* de */
+   "fiadd",
+   "fimul",
+   "ficom",
+   "ficomp",
+   "fisub",
+   "fisubr",
+   "fidiv",
+   "fidivr",
+   /* df */
+   "fild",
+   "(bad)",
+   "fist",
+   "fistp",
+   "fbld",
+   "fildll",
+   "fbstp",
+   "fistpll",
+ };
+ 
+ static const char *float_mem_intel[] = {
+   /* d8 */
+   "fadd",
+   "fmul",
+   "fcom",
+   "fcomp",
+   "fsub",
+   "fsubr",
+   "fdiv",
+   "fdivr",
+   /*  d9 */
+   "fld",
+   "(bad)",
+   "fst",
+   "fstp",
+   "fldenv",
+   "fldcw",
+   "fNstenv",
+   "fNstcw",
+   /* da */
+   "fiadd",
+   "fimul",
+   "ficom",
+   "ficomp",
+   "fisub",
+   "fisubr",
+   "fidiv",
+   "fidivr",
+   /* db */
+   "fild",
+   "(bad)",
+   "fist",
+   "fistp",
+   "(bad)",
+   "fld",
+   "(bad)",
+   "fstp",
+   /* dc */
+   "fadd",
+   "fmul",
+   "fcom",
+   "fcomp",
+   "fsub",
+   "fsubr",
+   "fdiv",
+   "fdivr",
+   /* dd */
+   "fld",
+   "(bad)",
+   "fst",
+   "fstp",
+   "frstor",
+   "(bad)",
+   "fNsave",
+   "fNstsw",
+   /* de */
+   "fiadd",
+   "fimul",
+   "ficom",
+   "ficomp",
+   "fisub",
+   "fisubr",
+   "fidiv",
+   "fidivr",
+   /* df */
+   "fild",
+   "(bad)",
+   "fist",
+   "fistp",
+   "fbld",
+   "fild",
+   "fbstp",
+   "fistpll",
+ };
+ 
+ #define ST OP_ST, 0
+ #define STi OP_STi, 0
+ 
+ #define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0
+ #define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0
+ #define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0
+ #define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0
+ #define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0
+ #define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0
+ #define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0
+ #define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0
+ #define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0
+ 
+ static const struct dis386 float_reg[][8] = {
+   /* d8 */
+   {
+     { "fadd",	ST, STi, XX },
+     { "fmul",	ST, STi, XX },
+     { "fcom",	STi, XX, XX },
+     { "fcomp",	STi, XX, XX },
+     { "fsub",	ST, STi, XX },
+     { "fsubr",	ST, STi, XX },
+     { "fdiv",	ST, STi, XX },
+     { "fdivr",	ST, STi, XX },
+   },
+   /* d9 */
+   {
+     { "fld",	STi, XX, XX },
+     { "fxch",	STi, XX, XX },
+     { FGRPd9_2 },
+     { "(bad)",	XX, XX, XX },
+     { FGRPd9_4 },
+     { FGRPd9_5 },
+     { FGRPd9_6 },
+     { FGRPd9_7 },
+   },
+   /* da */
+   {
+     { "fcmovb",	ST, STi, XX },
+     { "fcmove",	ST, STi, XX },
+     { "fcmovbe",ST, STi, XX },
+     { "fcmovu",	ST, STi, XX },
+     { "(bad)",	XX, XX, XX },
+     { FGRPda_5 },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+   /* db */
+   {
+     { "fcmovnb",ST, STi, XX },
+     { "fcmovne",ST, STi, XX },
+     { "fcmovnbe",ST, STi, XX },
+     { "fcmovnu",ST, STi, XX },
+     { FGRPdb_4 },
+     { "fucomi",	ST, STi, XX },
+     { "fcomi",	ST, STi, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+   /* dc */
+   {
+     { "fadd",	STi, ST, XX },
+     { "fmul",	STi, ST, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+ #if UNIXWARE_COMPAT
+     { "fsub",	STi, ST, XX },
+     { "fsubr",	STi, ST, XX },
+     { "fdiv",	STi, ST, XX },
+     { "fdivr",	STi, ST, XX },
+ #else
+     { "fsubr",	STi, ST, XX },
+     { "fsub",	STi, ST, XX },
+     { "fdivr",	STi, ST, XX },
+     { "fdiv",	STi, ST, XX },
+ #endif
+   },
+   /* dd */
+   {
+     { "ffree",	STi, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "fst",	STi, XX, XX },
+     { "fstp",	STi, XX, XX },
+     { "fucom",	STi, XX, XX },
+     { "fucomp",	STi, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+   /* de */
+   {
+     { "faddp",	STi, ST, XX },
+     { "fmulp",	STi, ST, XX },
+     { "(bad)",	XX, XX, XX },
+     { FGRPde_3 },
+ #if UNIXWARE_COMPAT
+     { "fsubp",	STi, ST, XX },
+     { "fsubrp",	STi, ST, XX },
+     { "fdivp",	STi, ST, XX },
+     { "fdivrp",	STi, ST, XX },
+ #else
+     { "fsubrp",	STi, ST, XX },
+     { "fsubp",	STi, ST, XX },
+     { "fdivrp",	STi, ST, XX },
+     { "fdivp",	STi, ST, XX },
+ #endif
+   },
+   /* df */
+   {
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { "(bad)",	XX, XX, XX },
+     { FGRPdf_4 },
+     { "fucomip",ST, STi, XX },
+     { "fcomip", ST, STi, XX },
+     { "(bad)",	XX, XX, XX },
+   },
+ };
+ 
+ 
+ static char *fgrps[][8] = {
+   /* d9_2  0 */
+   {
+     "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+   },
+ 
+   /* d9_4  1 */
+   {
+     "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+   },
+ 
+   /* d9_5  2 */
+   {
+     "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+   },
+ 
+   /* d9_6  3 */
+   {
+     "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+   },
+ 
+   /* d9_7  4 */
+   {
+     "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+   },
+ 
+   /* da_5  5 */
+   {
+     "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+   },
+ 
+   /* db_4  6 */
+   {
+     "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+     "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+   },
+ 
+   /* de_3  7 */
+   {
+     "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+   },
+ 
+   /* df_4  8 */
+   {
+     "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+   },
+ };
+ 
+ static void
+ dofloat (sizeflag)
+      int sizeflag;
+ {
+   const struct dis386 *dp;
+   unsigned char floatop;
+ 
+   floatop = codep[-1];
+ 
+   if (mod != 3)
+     {
+       if (intel_syntax)
+         putop (float_mem_intel[(floatop - 0xd8 ) * 8 + reg], sizeflag);
+       else
+         putop (float_mem_att[(floatop - 0xd8 ) * 8 + reg], sizeflag);
+       obufp = op1out;
+       if (floatop == 0xdb)
+         OP_E (x_mode, sizeflag);
+       else if (floatop == 0xdd)
+         OP_E (d_mode, sizeflag);
+       else
+         OP_E (v_mode, sizeflag);
+       return;
+     }
+   codep++;
+ 
+   dp = &float_reg[floatop - 0xd8][reg];
+   if (dp->name == NULL)
+     {
+       putop (fgrps[dp->bytemode1][rm], sizeflag);
+ 
+       /* instruction fnstsw is only one with strange arg */
+       if (floatop == 0xdf && codep[-1] == 0xe0)
+ 	strcpy (op1out, names16[0]);
+     }
+   else
+     {
+       putop (dp->name, sizeflag);
+ 
+       obufp = op1out;
+       if (dp->op1)
+ 	(*dp->op1)(dp->bytemode1, sizeflag);
+       obufp = op2out;
+       if (dp->op2)
+ 	(*dp->op2)(dp->bytemode2, sizeflag);
+     }
+ }
+ 
+ /* ARGSUSED */
+ static void
+ OP_ST (ignore, sizeflag)
+      int ignore ATTRIBUTE_UNUSED;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   oappend ("%st");
+ }
+ 
+ /* ARGSUSED */
+ static void
+ OP_STi (ignore, sizeflag)
+      int ignore ATTRIBUTE_UNUSED;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   sprintf (scratchbuf, "%%st(%d)", rm);
+   oappend (scratchbuf);
+ }
+ 
+ 
+ /* capital letters in template are macros */
+ static void
+ putop (template, sizeflag)
+      const char *template;
+      int sizeflag;
+ {
+   const char *p;
+ 
+   for (p = template; *p; p++)
+     {
+       switch (*p)
+ 	{
+ 	default:
+ 	  *obufp++ = *p;
+ 	  break;
+ 	case 'A':
+           if (intel_syntax)
+             break;
+ 	  if (mod != 3
+ #ifdef SUFFIX_ALWAYS
+ 	      || (sizeflag & SUFFIX_ALWAYS)
+ #endif
+ 	      )
+ 	    *obufp++ = 'b';
+ 	  break;
+ 	case 'B':
+           if (intel_syntax)
+             break;
+ #ifdef SUFFIX_ALWAYS
+ 	  if (sizeflag & SUFFIX_ALWAYS)
+ 	    *obufp++ = 'b';
+ #endif
+ 	  break;
+ 	case 'E':		/* For jcxz/jecxz */
+ 	  if (sizeflag & AFLAG)
+ 	    *obufp++ = 'e';
+ 	  break;
+ 	case 'L':
+           if (intel_syntax)
+             break;
+ #ifdef SUFFIX_ALWAYS
+ 	  if (sizeflag & SUFFIX_ALWAYS)
+ 	    *obufp++ = 'l';
+ #endif
+ 	  break;
+ 	case 'N':
+ 	  if ((prefixes & PREFIX_FWAIT) == 0)
+ 	    *obufp++ = 'n';
+ 	  else
+ 	    used_prefixes |= PREFIX_FWAIT;
+ 	  break;
+ 	case 'P':
+           if (intel_syntax)
+             break;
+ 	  if ((prefixes & PREFIX_DATA)
+ #ifdef SUFFIX_ALWAYS
+ 	      || (sizeflag & SUFFIX_ALWAYS)
+ #endif
+ 	      )
+ 	    {
+ 	      if (sizeflag & DFLAG)
+ 		*obufp++ = 'l';
+ 	      else
+ 		*obufp++ = 'w';
+ 	      used_prefixes |= (prefixes & PREFIX_DATA);
+ 	    }
+ 	  break;
+ 	case 'Q':
+           if (intel_syntax)
+             break;
+ 	  if (mod != 3
+ #ifdef SUFFIX_ALWAYS
+ 	      || (sizeflag & SUFFIX_ALWAYS)
+ #endif
+ 	      )
+ 	    {
+ 	      if (sizeflag & DFLAG)
+ 		*obufp++ = 'l';
+ 	      else
+ 		*obufp++ = 'w';
+ 	      used_prefixes |= (prefixes & PREFIX_DATA);
+ 	    }
+ 	  break;
+ 	case 'R':
+           if (intel_syntax)
+ 	    {
+ 	      if (sizeflag & DFLAG)
+ 		{
+ 		  *obufp++ = 'd';
+ 		  *obufp++ = 'q';
+ 		}
+ 	      else
+ 		{
+ 		  *obufp++ = 'w';
+ 		  *obufp++ = 'd';
+ 		}
+ 	    }
+ 	  else
+ 	    {
+ 	      if (sizeflag & DFLAG)
+ 		*obufp++ = 'l';
+ 	      else
+ 		*obufp++ = 'w';
+ 	    }
+ 	  used_prefixes |= (prefixes & PREFIX_DATA);
+ 	  break;
+ 	case 'S':
+           if (intel_syntax)
+             break;
+ #ifdef SUFFIX_ALWAYS
+ 	  if (sizeflag & SUFFIX_ALWAYS)
+ 	    {
+ 	      if (sizeflag & DFLAG)
+ 		*obufp++ = 'l';
+ 	      else
+ 		*obufp++ = 'w';
+ 	      used_prefixes |= (prefixes & PREFIX_DATA);
+ 	    }
+ #endif
+ 	  break;
+ 	case 'W':
+ 	  /* operand size flag for cwtl, cbtw */
+ 	  if (sizeflag & DFLAG)
+ 	    *obufp++ = 'w';
+ 	  else
+ 	    *obufp++ = 'b';
+           if (intel_syntax)
+ 	    {
+ 	      if (sizeflag & DFLAG)
+ 		{
+ 		  *obufp++ = 'd';
+ 		  *obufp++ = 'e';
+ 		}
+ 	      else
+ 		{
+ 		  *obufp++ = 'w';
+ 		}
+ 	    }
+ 	  used_prefixes |= (prefixes & PREFIX_DATA);
+ 	  break;
+ 	}
+     }
+   *obufp = 0;
+ }
+ 
+ static void
+ oappend (s)
+      const char *s;
+ {
+   strcpy (obufp, s);
+   obufp += strlen (s);
+ }
+ 
+ static void
+ append_seg ()
+ {
+   if (prefixes & PREFIX_CS)
+     {
+       oappend ("%cs:");
+       used_prefixes |= PREFIX_CS;
+     }
+   if (prefixes & PREFIX_DS)
+     {
+       oappend ("%ds:");
+       used_prefixes |= PREFIX_DS;
+     }
+   if (prefixes & PREFIX_SS)
+     {
+       oappend ("%ss:");
+       used_prefixes |= PREFIX_SS;
+     }
+   if (prefixes & PREFIX_ES)
+     {
+       oappend ("%es:");
+       used_prefixes |= PREFIX_ES;
+     }
+   if (prefixes & PREFIX_FS)
+     {
+       oappend ("%fs:");
+       used_prefixes |= PREFIX_FS;
+     }
+   if (prefixes & PREFIX_GS)
+     {
+       oappend ("%gs:");
+       used_prefixes |= PREFIX_GS;
+     }
+ }
+ 
+ static void
+ OP_indirE (bytemode, sizeflag)
+      int bytemode;
+      int sizeflag;
+ {
+   if (!intel_syntax)
+     oappend ("*");
+   OP_E (bytemode, sizeflag);
+ }
+ 
+ static void
+ OP_E (bytemode, sizeflag)
+      int bytemode;
+      int sizeflag;
+ {
+   int disp;
+ 
+   /* skip mod/rm byte */
+   codep++;
+ 
+   if (mod == 3)
+     {
+       switch (bytemode)
+ 	{
+ 	case b_mode:
+ 	  oappend (names8[rm]);
+ 	  break;
+ 	case w_mode:
+ 	  oappend (names16[rm]);
+ 	  break;
+ 	case d_mode:
+ 	  oappend (names32[rm]);
+ 	  break;
+ 	case v_mode:
+ 	  if (sizeflag & DFLAG)
+ 	    oappend (names32[rm]);
+ 	  else
+ 	    oappend (names16[rm]);
+ 	  used_prefixes |= (prefixes & PREFIX_DATA);
+ 	  break;
+ 	case 0:
+ 	  if ( !(codep[-2] == 0xAE && codep[-1] == 0xF8 /* sfence */))
+ 	    BadOp();	/* bad sfence,lea,lds,les,lfs,lgs,lss modrm */
+ 	  break;
+ 	default:
+ 	  oappend (INTERNAL_DISASSEMBLER_ERROR);
+ 	  break;
+ 	}
+       return;
+     }
+ 
+   disp = 0;
+   append_seg ();
+ 
+   if (sizeflag & AFLAG) /* 32 bit address mode */
+     {
+       int havesib;
+       int havebase;
+       int base;
+       int index = 0;
+       int scale = 0;
+ 
+       havesib = 0;
+       havebase = 1;
+       base = rm;
+ 
+       if (base == 4)
+ 	{
+ 	  havesib = 1;
+ 	  FETCH_DATA (the_info, codep + 1);
+ 	  scale = (*codep >> 6) & 3;
+ 	  index = (*codep >> 3) & 7;
+ 	  base = *codep & 7;
+ 	  codep++;
+ 	}
+ 
+       switch (mod)
+ 	{
+ 	case 0:
+ 	  if (base == 5)
+ 	    {
+ 	      havebase = 0;
+ 	      disp = get32 ();
+ 	    }
+ 	  break;
+ 	case 1:
+ 	  FETCH_DATA (the_info, codep + 1);
+ 	  disp = *codep++;
+ 	  if ((disp & 0x80) != 0)
+ 	    disp -= 0x100;
+ 	  break;
+ 	case 2:
+ 	  disp = get32 ();
+ 	  break;
+ 	}
+ 
+       if (!intel_syntax)
+         if (mod != 0 || base == 5)
+           {
+             sprintf (scratchbuf, "0x%x", disp);
+             oappend (scratchbuf);
+           }
+ 
+       if (havebase || (havesib && (index != 4 || scale != 0)))
+ 	{
+           if (intel_syntax)
+             {
+               switch (bytemode)
+                 {
+                 case b_mode:
+                   oappend("BYTE PTR ");
+                   break;
+                 case w_mode:
+                   oappend("WORD PTR ");
+                   break;
+                 case v_mode:
+                   oappend("DWORD PTR ");
+                   break;
+                 case d_mode:
+                   oappend("QWORD PTR ");
+                   break;
+                 case x_mode:
+                   oappend("XWORD PTR ");
+                   break;
+                 default:
+                   break;
+                 }
+              }
+ 	  *obufp++ = open_char;
+           *obufp = '\0';
+ 	  if (havebase)
+ 	    oappend (names32[base]);
+ 	  if (havesib)
+ 	    {
+ 	      if (index != 4)
+ 		{
+                   if (intel_syntax)
+                     {
+                       if (havebase)
+                         {
+                           *obufp++ = separator_char;
+                           *obufp = '\0';
+                         }
+                       sprintf (scratchbuf, "%s", names32[index]);
+                     }
+                   else
+ 		    sprintf (scratchbuf, ",%s", names32[index]);
+ 		  oappend (scratchbuf);
+ 		}
+               if (!intel_syntax
+                   || (intel_syntax
+                       && bytemode != b_mode
+                       && bytemode != w_mode
+                       && bytemode != v_mode))
+                 {
+                   *obufp++ = scale_char;
+                   *obufp = '\0';
+ 	          sprintf (scratchbuf, "%d", 1 << scale);
+ 	          oappend (scratchbuf);
+                 }
+ 	    }
+           if (intel_syntax)
+             if (mod != 0 || base == 5)
+               {
+                 /* Don't print zero displacements */
+                 if (disp > 0)
+                   {
+                     sprintf (scratchbuf, "+%d", disp);
+                     oappend (scratchbuf);
+                   }
+                 else if (disp < 0)
+                   {
+                     sprintf (scratchbuf, "%d", disp);
+                     oappend (scratchbuf);
+                   }
+               }
+ 
+ 	  *obufp++ = close_char;
+           *obufp = '\0';
+ 	}
+       else if (intel_syntax)
+         {
+           if (mod != 0 || base == 5)
+             {
+ 	      if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+ 			      | PREFIX_ES | PREFIX_FS | PREFIX_GS))
+ 		;
+ 	      else
+ 		{
+ 		  oappend (names_seg[3]);
+ 		  oappend (":");
+ 		}
+               sprintf (scratchbuf, "0x%x", disp);
+               oappend (scratchbuf);
+             }
+         }
+     }
+   else
+     { /* 16 bit address mode */
+       switch (mod)
+ 	{
+ 	case 0:
+ 	  if (rm == 6)
+ 	    {
+ 	      disp = get16 ();
+ 	      if ((disp & 0x8000) != 0)
+ 		disp -= 0x10000;
+ 	    }
+ 	  break;
+ 	case 1:
+ 	  FETCH_DATA (the_info, codep + 1);
+ 	  disp = *codep++;
+ 	  if ((disp & 0x80) != 0)
+ 	    disp -= 0x100;
+ 	  break;
+ 	case 2:
+ 	  disp = get16 ();
+ 	  if ((disp & 0x8000) != 0)
+ 	    disp -= 0x10000;
+ 	  break;
+ 	}
+ 
+       if (!intel_syntax)
+         if (mod != 0 || rm == 6)
+           {
+             sprintf (scratchbuf, "%d", disp);
+             oappend (scratchbuf);
+           }
+ 
+       if (mod != 0 || rm != 6)
+ 	{
+ 	  *obufp++ = open_char;
+           *obufp = '\0';
+ 	  oappend (index16[rm]);
+           *obufp++ = close_char;
+           *obufp = '\0';
+ 	}
+     }
+ }
+ 
+ static void
+ OP_G (bytemode, sizeflag)
+      int bytemode;
+      int sizeflag;
+ {
+   switch (bytemode)
+     {
+     case b_mode:
+       oappend (names8[reg]);
+       break;
+     case w_mode:
+       oappend (names16[reg]);
+       break;
+     case d_mode:
+       oappend (names32[reg]);
+       break;
+     case v_mode:
+       if (sizeflag & DFLAG)
+ 	oappend (names32[reg]);
+       else
+ 	oappend (names16[reg]);
+       used_prefixes |= (prefixes & PREFIX_DATA);
+       break;
+     default:
+       oappend (INTERNAL_DISASSEMBLER_ERROR);
+       break;
+     }
+ }
+ 
+ static int
+ get32 ()
+ {
+   int x = 0;
+ 
+   FETCH_DATA (the_info, codep + 4);
+   x = *codep++ & 0xff;
+   x |= (*codep++ & 0xff) << 8;
+   x |= (*codep++ & 0xff) << 16;
+   x |= (*codep++ & 0xff) << 24;
+   return x;
+ }
+ 
+ static int
+ get16 ()
+ {
+   int x = 0;
+ 
+   FETCH_DATA (the_info, codep + 2);
+   x = *codep++ & 0xff;
+   x |= (*codep++ & 0xff) << 8;
+   return x;
+ }
+ 
+ static void
+ set_op (op)
+      unsigned int op;
+ {
+   op_index[op_ad] = op_ad;
+   op_address[op_ad] = op;
+ }
+ 
+ static void
+ OP_REG (code, sizeflag)
+      int code;
+      int sizeflag;
+ {
+   const char *s;
+ 
+   switch (code)
+     {
+     case indir_dx_reg:
+       s = "(%dx)";
+       break;
+     case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+     case sp_reg: case bp_reg: case si_reg: case di_reg:
+       s = names16[code - ax_reg];
+       break;
+     case es_reg: case ss_reg: case cs_reg:
+     case ds_reg: case fs_reg: case gs_reg:
+       s = names_seg[code - es_reg];
+       break;
+     case al_reg: case ah_reg: case cl_reg: case ch_reg:
+     case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+       s = names8[code - al_reg];
+       break;
+     case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+     case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+       if (sizeflag & DFLAG)
+ 	s = names32[code - eAX_reg];
+       else
+ 	s = names16[code - eAX_reg];
+       used_prefixes |= (prefixes & PREFIX_DATA);
+       break;
+     default:
+       s = INTERNAL_DISASSEMBLER_ERROR;
+       break;
+     }
+   oappend (s);
+ }
+ 
+ static void
+ OP_I (bytemode, sizeflag)
+      int bytemode;
+      int sizeflag;
+ {
+   int op;
+ 
+   switch (bytemode)
+     {
+     case b_mode:
+       FETCH_DATA (the_info, codep + 1);
+       op = *codep++ & 0xff;
+       break;
+     case v_mode:
+       if (sizeflag & DFLAG)
+ 	op = get32 ();
+       else
+ 	op = get16 ();
+       used_prefixes |= (prefixes & PREFIX_DATA);
+       break;
+     case w_mode:
+       op = get16 ();
+       break;
+     default:
+       oappend (INTERNAL_DISASSEMBLER_ERROR);
+       return;
+     }
+ 
+   if (intel_syntax)
+     sprintf (scratchbuf, "0x%x", op);
+   else
+     sprintf (scratchbuf, "$0x%x", op);
+   oappend (scratchbuf);
+   scratchbuf[0] = '\0';
+ }
+ 
+ static void
+ OP_sI (bytemode, sizeflag)
+      int bytemode;
+      int sizeflag;
+ {
+   int op;
+ 
+   switch (bytemode)
+     {
+     case b_mode:
+       FETCH_DATA (the_info, codep + 1);
+       op = *codep++;
+       if ((op & 0x80) != 0)
+ 	op -= 0x100;
+       break;
+     case v_mode:
+       if (sizeflag & DFLAG)
+ 	op = get32 ();
+       else
+ 	{
+ 	  op = get16();
+ 	  if ((op & 0x8000) != 0)
+ 	    op -= 0x10000;
+ 	}
+       used_prefixes |= (prefixes & PREFIX_DATA);
+       break;
+     case w_mode:
+       op = get16 ();
+       if ((op & 0x8000) != 0)
+ 	op -= 0x10000;
+       break;
+     default:
+       oappend (INTERNAL_DISASSEMBLER_ERROR);
+       return;
+     }
+   if (intel_syntax)
+     sprintf (scratchbuf, "%d", op);
+   else
+     sprintf (scratchbuf, "$0x%x", op);
+   oappend (scratchbuf);
+ }
+ 
+ static void
+ OP_J (bytemode, sizeflag)
+      int bytemode;
+      int sizeflag;
+ {
+   int disp;
+   int mask = -1;
+ 
+   switch (bytemode)
+     {
+     case b_mode:
+       FETCH_DATA (the_info, codep + 1);
+       disp = *codep++;
+       if ((disp & 0x80) != 0)
+ 	disp -= 0x100;
+       break;
+     case v_mode:
+       if (sizeflag & DFLAG)
+ 	disp = get32 ();
+       else
+ 	{
+ 	  disp = get16 ();
+ 	  /* for some reason, a data16 prefix on a jump instruction
+ 	     means that the pc is masked to 16 bits after the
+ 	     displacement is added!  */
+ 	  mask = 0xffff;
+ 	}
+       used_prefixes |= (prefixes & PREFIX_DATA);
+       break;
+     default:
+       oappend (INTERNAL_DISASSEMBLER_ERROR);
+       return;
+     }
+   disp = (start_pc + codep - start_codep + disp) & mask;
+   set_op (disp);
+   sprintf (scratchbuf, "0x%x", disp);
+   oappend (scratchbuf);
+ }
+ 
+ /* ARGSUSED */
+ static void
+ OP_SEG (dummy, sizeflag)
+      int dummy ATTRIBUTE_UNUSED;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   static char *sreg[] = {
+     "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+   };
+ 
+   oappend (sreg[reg]);
+ }
+ 
+ /* ARGSUSED */
+ static void
+ OP_DIR (dummy, sizeflag)
+      int dummy ATTRIBUTE_UNUSED;
+      int sizeflag;
+ {
+   int seg, offset;
+ 
+   if (sizeflag & DFLAG)
+     {
+       offset = get32 ();
+       seg = get16 ();
+     }
+   else
+     {
+       offset = get16 ();
+       seg = get16 ();
+     }
+   used_prefixes |= (prefixes & PREFIX_DATA);
+   sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
+   oappend (scratchbuf);
+ }
+ 
+ /* ARGSUSED */
+ static void
+ OP_OFF (ignore, sizeflag)
+      int ignore ATTRIBUTE_UNUSED;
+      int sizeflag;
+ {
+   int off;
+ 
+   append_seg ();
+ 
+   if (sizeflag & AFLAG)
+     off = get32 ();
+   else
+     off = get16 ();
+ 
+   if (intel_syntax)
+     {
+       if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+ 		        | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+ 	{
+ 	  oappend (names_seg[3]);
+ 	  oappend (":");
+ 	}
+     }
+   sprintf (scratchbuf, "0x%x", off);
+   oappend (scratchbuf);
+ }
+ 
+ static void
+ ptr_reg (code, sizeflag)
+      int code;
+      int sizeflag;
+ {
+   const char *s;
+   oappend ("(");
+   if (sizeflag & AFLAG)
+     s = names32[code - eAX_reg];
+   else
+     s = names16[code - eAX_reg];
+   oappend (s);
+   oappend (")");
+ }
+ 
+ static void
+ OP_ESreg (code, sizeflag)
+      int code;
+      int sizeflag;
+ {
+   oappend ("%es:");
+   ptr_reg (code, sizeflag);
+ }
+ 
+ static void
+ OP_DSreg (code, sizeflag)
+      int code;
+      int sizeflag;
+ {
+   if ((prefixes
+        & (PREFIX_CS
+ 	  | PREFIX_DS
+ 	  | PREFIX_SS
+ 	  | PREFIX_ES
+ 	  | PREFIX_FS
+ 	  | PREFIX_GS)) == 0)
+     prefixes |= PREFIX_DS;
+   append_seg();
+   ptr_reg (code, sizeflag);
+ }
+ 
+ /* ARGSUSED */
+ static void
+ OP_C (dummy, sizeflag)
+      int dummy ATTRIBUTE_UNUSED;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   sprintf (scratchbuf, "%%cr%d", reg);
+   oappend (scratchbuf);
+ }
+ 
+ /* ARGSUSED */
+ static void
+ OP_D (dummy, sizeflag)
+      int dummy ATTRIBUTE_UNUSED;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   sprintf (scratchbuf, "%%db%d", reg);
+   oappend (scratchbuf);
+ }
+ 
+ /* ARGSUSED */
+ static void
+ OP_T (dummy, sizeflag)
+      int dummy ATTRIBUTE_UNUSED;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   sprintf (scratchbuf, "%%tr%d", reg);
+   oappend (scratchbuf);
+ }
+ 
+ static void
+ OP_Rd (bytemode, sizeflag)
+      int bytemode;
+      int sizeflag;
+ {
+   if (mod == 3)
+     OP_E (bytemode, sizeflag);
+   else
+     BadOp();
+ }
+ 
+ static void
+ OP_MMX (ignore, sizeflag)
+      int ignore ATTRIBUTE_UNUSED;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   sprintf (scratchbuf, "%%mm%d", reg);
+   oappend (scratchbuf);
+ }
+ 
+ static void
+ OP_XMM (bytemode, sizeflag)
+      int bytemode ATTRIBUTE_UNUSED;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   sprintf (scratchbuf, "%%xmm%d", reg);
+   oappend (scratchbuf);
+ }
+ 
+ static void
+ OP_EM (bytemode, sizeflag)
+      int bytemode;
+      int sizeflag;
+ {
+   if (mod != 3)
+     {
+       OP_E (bytemode, sizeflag);
+       return;
+     }
+ 
+   codep++;
+   sprintf (scratchbuf, "%%mm%d", rm);
+   oappend (scratchbuf);
+ }
+ 
+ static void
+ OP_EX (bytemode, sizeflag)
+      int bytemode;
+      int sizeflag;
+ {
+   if (mod != 3)
+     {
+       OP_E (bytemode, sizeflag);
+       return;
+     }
+ 
+   codep++;
+   sprintf (scratchbuf, "%%xmm%d", rm);
+   oappend (scratchbuf);
+ }
+ 
+ static void
+ OP_MS (bytemode, sizeflag)
+      int bytemode;
+      int sizeflag;
+ {
+   if (mod == 3)
+     OP_EM (bytemode, sizeflag);
+   else
+     BadOp();
+ }
+ 
+ static const char *Suffix3DNow[] = {
+ /* 00 */	NULL,		NULL,		NULL,		NULL,
+ /* 04 */	NULL,		NULL,		NULL,		NULL,
+ /* 08 */	NULL,		NULL,		NULL,		NULL,
+ /* 0C */	"pi2fw",	"pi2fd",	NULL,		NULL,
+ /* 10 */	NULL,		NULL,		NULL,		NULL,
+ /* 14 */	NULL,		NULL,		NULL,		NULL,
+ /* 18 */	NULL,		NULL,		NULL,		NULL,
+ /* 1C */	"pf2iw",	"pf2id",	NULL,		NULL,
+ /* 20 */	NULL,		NULL,		NULL,		NULL,
+ /* 24 */	NULL,		NULL,		NULL,		NULL,
+ /* 28 */	NULL,		NULL,		NULL,		NULL,
+ /* 2C */	NULL,		NULL,		NULL,		NULL,
+ /* 30 */	NULL,		NULL,		NULL,		NULL,
+ /* 34 */	NULL,		NULL,		NULL,		NULL,
+ /* 38 */	NULL,		NULL,		NULL,		NULL,
+ /* 3C */	NULL,		NULL,		NULL,		NULL,
+ /* 40 */	NULL,		NULL,		NULL,		NULL,
+ /* 44 */	NULL,		NULL,		NULL,		NULL,
+ /* 48 */	NULL,		NULL,		NULL,		NULL,
+ /* 4C */	NULL,		NULL,		NULL,		NULL,
+ /* 50 */	NULL,		NULL,		NULL,		NULL,
+ /* 54 */	NULL,		NULL,		NULL,		NULL,
+ /* 58 */	NULL,		NULL,		NULL,		NULL,
+ /* 5C */	NULL,		NULL,		NULL,		NULL,
+ /* 60 */	NULL,		NULL,		NULL,		NULL,
+ /* 64 */	NULL,		NULL,		NULL,		NULL,
+ /* 68 */	NULL,		NULL,		NULL,		NULL,
+ /* 6C */	NULL,		NULL,		NULL,		NULL,
+ /* 70 */	NULL,		NULL,		NULL,		NULL,
+ /* 74 */	NULL,		NULL,		NULL,		NULL,
+ /* 78 */	NULL,		NULL,		NULL,		NULL,
+ /* 7C */	NULL,		NULL,		NULL,		NULL,
+ /* 80 */	NULL,		NULL,		NULL,		NULL,
+ /* 84 */	NULL,		NULL,		NULL,		NULL,
+ /* 88 */	NULL,		NULL,		"pfnacc",	NULL,
+ /* 8C */	NULL,		NULL,		"pfpnacc",	NULL,
+ /* 90 */	"pfcmpge",	NULL,		NULL,		NULL,
+ /* 94 */	"pfmin",	NULL,		"pfrcp",	"pfrsqrt",
+ /* 98 */	NULL,		NULL,		"pfsub",	NULL,
+ /* 9C */	NULL,		NULL,		"pfadd",	NULL,
+ /* A0 */	"pfcmpgt",	NULL,		NULL,		NULL,
+ /* A4 */	"pfmax",	NULL,		"pfrcpit1",	"pfrsqit1",
+ /* A8 */	NULL,		NULL,		"pfsubr",	NULL,
+ /* AC */	NULL,		NULL,		"pfacc",	NULL,
+ /* B0 */	"pfcmpeq",	NULL,		NULL,		NULL,
+ /* B4 */	"pfmul",	NULL,		"pfrcpit2",	"pfmulhrw",
+ /* B8 */	NULL,		NULL,		NULL,		"pswapd",
+ /* BC */	NULL,		NULL,		NULL,		"pavgusb",
+ /* C0 */	NULL,		NULL,		NULL,		NULL,
+ /* C4 */	NULL,		NULL,		NULL,		NULL,
+ /* C8 */	NULL,		NULL,		NULL,		NULL,
+ /* CC */	NULL,		NULL,		NULL,		NULL,
+ /* D0 */	NULL,		NULL,		NULL,		NULL,
+ /* D4 */	NULL,		NULL,		NULL,		NULL,
+ /* D8 */	NULL,		NULL,		NULL,		NULL,
+ /* DC */	NULL,		NULL,		NULL,		NULL,
+ /* E0 */	NULL,		NULL,		NULL,		NULL,
+ /* E4 */	NULL,		NULL,		NULL,		NULL,
+ /* E8 */	NULL,		NULL,		NULL,		NULL,
+ /* EC */	NULL,		NULL,		NULL,		NULL,
+ /* F0 */	NULL,		NULL,		NULL,		NULL,
+ /* F4 */	NULL,		NULL,		NULL,		NULL,
+ /* F8 */	NULL,		NULL,		NULL,		NULL,
+ /* FC */	NULL,		NULL,		NULL,		NULL,
+ };
+ 
+ static void
+ OP_3DNowSuffix (bytemode, sizeflag)
+      int bytemode ATTRIBUTE_UNUSED;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   const char *mnemonic;
+ 
+   FETCH_DATA (the_info, codep + 1);
+   /* AMD 3DNow! instructions are specified by an opcode suffix in the
+      place where an 8-bit immediate would normally go.  ie. the last
+      byte of the instruction.  */
+   obufp = obuf + strlen(obuf);
+   mnemonic = Suffix3DNow[*codep++ & 0xff];
+   if (mnemonic)
+     oappend (mnemonic);
+   else
+     {
+       /* Since a variable sized modrm/sib chunk is between the start
+ 	 of the opcode (0x0f0f) and the opcode suffix, we need to do
+ 	 all the modrm processing first, and don't know until now that
+ 	 we have a bad opcode.  This necessitates some cleaning up.  */
+       op1out[0] = '\0';
+       op2out[0] = '\0';
+       BadOp();
+     }
+ }
+ 
+ 
+ static const char *simd_cmp_op [] = {
+   "eq",
+   "lt",
+   "le",
+   "unord",
+   "neq",
+   "nlt",
+   "nle",
+   "ord"
+ };
+ 
+ static void
+ OP_SIMD_Suffix (bytemode, sizeflag)
+      int bytemode ATTRIBUTE_UNUSED;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   unsigned int cmp_type;
+ 
+   FETCH_DATA (the_info, codep + 1);
+   obufp = obuf + strlen(obuf);
+   cmp_type = *codep++ & 0xff;
+   if (cmp_type < 8)
+     {
+       sprintf (scratchbuf, "cmp%s%cs",
+ 	       simd_cmp_op[cmp_type],
+ 	       prefixes & PREFIX_REPZ ? 's' : 'p');
+       used_prefixes |= (prefixes & PREFIX_REPZ);
+       oappend (scratchbuf);
+     }
+   else
+     {
+       /* We have a bad extension byte.  Clean up.  */
+       op1out[0] = '\0';
+       op2out[0] = '\0';
+       BadOp();
+     }
+ }
+ 
+ static void
+ SIMD_Fixup (extrachar, sizeflag)
+      int extrachar;
+      int sizeflag ATTRIBUTE_UNUSED;
+ {
+   /* Change movlps/movhps to movhlps/movlhps for 2 register operand
+      forms of these instructions.  */
+   if (mod == 3)
+     {
+       char *p = obuf + strlen(obuf);
+       *(p+1) = '\0';
+       *p     = *(p-1);
+       *(p-1) = *(p-2);
+       *(p-2) = *(p-3);
+       *(p-3) = extrachar;
+     }
+ }
+ 
+ static void BadOp (void)
+ {
+   codep = insn_codep + 1;	/* throw away prefixes and 1st. opcode byte */
+   oappend ("(bad)");
+ }
diff -c -r -N console-os/arch/i386/kdb/kdba_bp.c console-os-kdb/arch/i386/kdb/kdba_bp.c
*** console-os/arch/i386/kdb/kdba_bp.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/arch/i386/kdb/kdba_bp.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,804 ----
+ /*
+  * Kernel Debugger Architecture Dependent Breakpoint Handling
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/string.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/smp.h>
+ #include <linux/ptrace.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ 
+ 
+ static char *kdba_rwtypes[] = { "Instruction(Register)", "Data Write",
+ 			"I/O", "Data Access"};
+ 
+ /*
+  * Table describing processor architecture hardware
+  * breakpoint registers.
+  */
+ 
+ kdbhard_bp_t	kdb_hardbreaks[KDB_MAXHARDBPT];
+ 
+ /*
+  * kdba_db_trap
+  *
+  * 	Perform breakpoint processing upon entry to the
+  *	processor debugger fault.   Determine and print
+  *	the active breakpoint.
+  *
+  * Parameters:
+  *	regs	Exception frame containing machine register state
+  *	error	Error number passed to kdb.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	KDB_DB_BPT	Standard instruction or data breakpoint encountered
+  *	KDB_DB_SS	Single Step fault ('ss' command or end of 'ssb' command)
+  *	KDB_DB_SSB	Single Step fault, caller should continue ('ssb' command)
+  *	KDB_DB_SSBPT	Single step over breakpoint
+  *	KDB_DB_NOBPT	No existing kdb breakpoint matches this debug exception
+  * Locking:
+  *	None.
+  * Remarks:
+  *	Yup, there be goto's here.
+  *
+  *	If multiple processors receive debug exceptions simultaneously,
+  *	one may be waiting at the kdb fence in kdb() while the user
+  *	issues a 'bc' command to clear the breakpoint the processor
+  *	which is waiting has already encountered.  If this is the case,
+  *	the debug registers will no longer match any entry in the
+  *	breakpoint table, and we'll return the value KDB_DB_NOBPT.
+  *	This can cause a panic in die_if_kernel().  It is safer to
+  *	disable the breakpoint (bd), go until all processors are past
+  *	the breakpoint then clear the breakpoint (bc).  This code
+  *	recognises a breakpoint even when disabled but not when it has
+  *	been cleared.
+  *
+  *	WARNING: This routine clears the debug state.  It should be called
+  *		 once per debug and the result cached.
+  */
+ 
+ kdb_dbtrap_t
+ kdba_db_trap(struct pt_regs *regs, int error_unused)
+ {
+ 	kdb_machreg_t  dr6;
+ 	kdb_machreg_t  dr7;
+ 	int rw, reg;
+ 	int i;
+ 	kdb_dbtrap_t rv = KDB_DB_BPT;
+ 	kdb_bp_t *bp;
+ 
+ 	if (KDB_NULL_REGS(regs))
+ 		return KDB_DB_NOBPT;
+ 
+ 	dr6 = kdba_getdr6();
+ 	dr7 = kdba_getdr7();
+ 
+ 	if (KDB_DEBUG(BP))
+ 		kdb_printf("kdb: dr6 0x%lx dr7 0x%lx\n", dr6, dr7);
+ 	if (dr6 & DR6_BS) {
+ 		if (KDB_STATE(SSBPT)) {
+ 			if (KDB_DEBUG(BP))
+ 				kdb_printf("ssbpt\n");
+ 			KDB_STATE_CLEAR(SSBPT);
+ 			for(i=0,bp=kdb_breakpoints;
+ 			    i < KDB_MAXBPT;
+ 			    i++, bp++) {
+ 				if (KDB_DEBUG(BP))
+ 					kdb_printf("bp 0x%p enabled %d delayed %d global %d cpu %d\n",
+ 						   bp, bp->bp_enabled, bp->bp_delayed, bp->bp_global, bp->bp_cpu);
+ 				if (!bp->bp_enabled)
+ 					continue;
+ 				if (!bp->bp_global && bp->bp_cpu != smp_processor_id())
+ 					continue;
+ 				if (KDB_DEBUG(BP))
+ 					kdb_printf("bp for this cpu\n");
+ 				if (bp->bp_delayed) {
+ 					bp->bp_delayed = 0;
+ 					if (KDB_DEBUG(BP))
+ 						kdb_printf("kdba_installbp\n");
+ 					kdba_installbp(regs, bp);
+ 					if (!KDB_STATE(DOING_SS)) {
+ 						regs->eflags &= ~EF_TF;
+ 						return(KDB_DB_SSBPT);
+ 					}
+ 					break;
+ 				}
+ 			}
+ 			if (i == KDB_MAXBPT) {
+ 				kdb_printf("kdb: Unable to find delayed breakpoint\n");
+ 			}
+ 			if (!KDB_STATE(DOING_SS)) {
+ 				regs->eflags &= ~EF_TF;
+ 				return(KDB_DB_NOBPT);
+ 			}
+ 			/* FALLTHROUGH */
+ 		}
+ 
+ 		/*
+ 		 * KDB_STATE_DOING_SS is set when the kernel debugger is using
+ 		 * the processor trap flag to single-step a processor.  If a
+ 		 * single step trap occurs and this flag is clear, the SS trap
+ 		 * will be ignored by KDB and the kernel will be allowed to deal
+ 		 * with it as necessary (e.g. for ptrace).
+ 		 */
+ 		if (!KDB_STATE(DOING_SS))
+ 			goto unknown;
+ 
+ 		/* single step */
+ 		rv = KDB_DB_SS;		/* Indicate single step */
+ 		if (KDB_STATE(DOING_SSB)) {
+ 			unsigned char instruction[2];
+ 
+ 			kdb_id1(regs->eip);
+ 			if (kdb_getarea(instruction, regs->eip) ||
+ 			    (instruction[0]&0xf0) == 0xe0 ||	/* short disp jumps */
+ 			    (instruction[0]&0xf0) == 0x70 ||	/* Misc. jumps */
+ 			    instruction[0]        == 0xc2 ||	/* ret */
+ 			    instruction[0]        == 0x9a ||	/* call */
+ 			    (instruction[0]&0xf8) == 0xc8 ||	/* enter, leave, iret, int, */
+ 			    ((instruction[0]      == 0x0f) &&
+ 			     ((instruction[1]&0xf0)== 0x80))
+ 			   ) {
+ 				/*
+ 				 * End the ssb command here.
+ 				 */
+ 				KDB_STATE_CLEAR(DOING_SSB);
+ 				KDB_STATE_CLEAR(DOING_SS);
+ 			} else {
+ 				rv = KDB_DB_SSB; /* Indicate ssb - dismiss immediately */
+ 			}
+ 		} else {
+ 			/*
+ 			 * Print current insn
+ 			 */
+ 			kdb_printf("SS trap at ");
+ 			kdb_symbol_print(regs->eip, NULL, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+ 			kdb_id1(regs->eip);
+ 			KDB_STATE_CLEAR(DOING_SS);
+ 		}
+ 
+ 		if (rv != KDB_DB_SSB)
+ 			regs->eflags &= ~EF_TF;
+ 	}
+ 
+ 	if (dr6 & DR6_B0) {
+ 		rw = DR7_RW0(dr7);
+ 		reg = 0;
+ 		goto handle;
+ 	}
+ 
+ 	if (dr6 & DR6_B1) {
+ 		rw = DR7_RW1(dr7);
+ 		reg = 1;
+ 		goto handle;
+ 	}
+ 
+ 	if (dr6 & DR6_B2) {
+ 		rw = DR7_RW2(dr7);
+ 		reg = 2;
+ 		goto handle;
+ 	}
+ 
+ 	if (dr6 & DR6_B3) {
+ 		rw = DR7_RW3(dr7);
+ 		reg = 3;
+ 		goto handle;
+ 	}
+ 
+ 	if (rv > 0)
+ 		goto handled;
+ 
+ 	goto unknown;	/* dismiss */
+ 
+ handle:
+ 	/*
+ 	 * Set Resume Flag
+ 	 */
+ 	regs->eflags |= EF_RF;
+ 
+ 	/*
+ 	 * Determine which breakpoint was encountered.
+ 	 */
+ 	for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+ 		if (!(bp->bp_free)
+ 		 && (bp->bp_global || bp->bp_cpu == smp_processor_id())
+ 		 && (bp->bp_hard)
+ 		 && (bp->bp_hard->bph_reg == reg)) {
+ 			/*
+ 			 * Hit this breakpoint.
+ 			 */
+ 			kdb_printf("%s breakpoint #%d at " kdb_bfd_vma_fmt "\n",
+ 				  kdba_rwtypes[rw],
+ 				  i, bp->bp_addr);
+ 
+ 			/*
+ 			 * For an instruction breakpoint, disassemble
+ 			 * the current instruction.
+ 			 */
+ 			if (rw == 0) {
+ 				kdb_id1(regs->eip);
+ 			}
+ 
+ 			goto handled;
+ 		}
+ 	}
+ 
+ unknown:
+ 	regs->eflags |= EF_RF;	/* Supress further faults */
+ 	rv = KDB_DB_NOBPT;	/* Cause kdb() to return */
+ 
+ handled:
+ 
+ 	/*
+ 	 * Clear the pending exceptions.
+ 	 */
+ 	kdba_putdr6(0);
+ 
+ 	return rv;
+ }
+ 
+ /*
+  * kdba_bp_trap
+  *
+  * 	Perform breakpoint processing upon entry to the
+  *	processor breakpoint instruction fault.   Determine and print
+  *	the active breakpoint.
+  *
+  * Parameters:
+  *	regs	Exception frame containing machine register state
+  *	error	Error number passed to kdb.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	0	Standard instruction or data breakpoint encountered
+  *	1	Single Step fault ('ss' command)
+  *	2	Single Step fault, caller should continue ('ssb' command)
+  *	3	No existing kdb breakpoint matches this debug exception
+  * Locking:
+  *	None.
+  * Remarks:
+  *
+  * 	If multiple processors receive debug exceptions simultaneously,
+  *	one may be waiting at the kdb fence in kdb() while the user
+  *	issues a 'bc' command to clear the breakpoint the processor which
+  * 	is waiting has already encountered.   If this is the case, the
+  *	debug registers will no longer match any entry in the breakpoint
+  *	table, and we'll return the value '3'.  This can cause a panic
+  *	in die_if_kernel().  It is safer to disable the breakpoint (bd),
+  *	'go' until all processors are past the breakpoint then clear the
+  *	breakpoint (bc).  This code recognises a breakpoint even when
+  *	disabled but not when it has been cleared.
+  *
+  *	WARNING: This routine resets the eip.  It should be called
+  *		 once per breakpoint and the result cached.
+  */
+ 
+ kdb_dbtrap_t
+ kdba_bp_trap(struct pt_regs *regs, int error_unused)
+ {
+ 	int i;
+ 	kdb_dbtrap_t rv;
+ 	kdb_bp_t *bp;
+ 
+ 	if (KDB_NULL_REGS(regs))
+ 		return KDB_DB_NOBPT;
+ 
+ 	/*
+ 	 * Determine which breakpoint was encountered.
+ 	 */
+ 	if (KDB_DEBUG(BP))
+ 		kdb_printf("kdba_bp_trap: eip=0x%lx (not adjusted) "
+ 			   "eflags=0x%lx regs=0x%p esp=0x%lx\n",
+ 			   regs->eip, regs->eflags, regs, regs->esp);
+ 
+ 	rv = KDB_DB_NOBPT;	/* Cause kdb() to return */
+ 
+ 	for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+ 		if (bp->bp_free)
+ 			continue;
+ 		if (!bp->bp_global && bp->bp_cpu != smp_processor_id())
+ 			continue;
+ 		 if ((void *)bp->bp_addr == (void *)(regs->eip - bp->bp_adjust)) {
+ 			/* Hit this breakpoint.  */
+ 			regs->eip -= bp->bp_adjust;
+ 			kdb_printf("Instruction(i) breakpoint #%d at 0x%lx (adjusted)\n",
+ 				  i, regs->eip);
+ 			kdb_id1(regs->eip);
+ 			rv = KDB_DB_BPT;
+ 			bp->bp_delay = 1;
+ 			/* SSBPT is set when the kernel debugger must single
+ 			 * step a task in order to re-establish an instruction
+ 			 * breakpoint which uses the instruction replacement
+ 			 * mechanism.  It is cleared by any action that removes
+ 			 * the need to single-step the breakpoint.
+ 			 */
+ 			KDB_STATE_SET(SSBPT);
+ 			break;
+ 		}
+ 	}
+ 
+ 	return rv;
+ }
+ 
+ /*
+  * kdba_handle_bp
+  *
+  *	Handle an instruction-breakpoint trap.  Called when re-installing
+  *	an enabled breakpoint which has has the bp_delay bit set.
+  *
+  * Parameters:
+  * Returns:
+  * Locking:
+  * Remarks:
+  *
+  * Ok, we really need to:
+  *	1) Restore the original instruction byte
+  *	2) Single Step
+  *	3) Restore breakpoint instruction
+  *	4) Continue.
+  *
+  *
+  */
+ 
+ static void
+ kdba_handle_bp(struct pt_regs *regs, kdb_bp_t *bp)
+ {
+ 	if (KDB_NULL_REGS(regs))
+ 		return;
+ 
+ 	if (KDB_DEBUG(BP))
+ 		kdb_printf("regs->eip = 0x%lx\n", regs->eip);
+ 
+ 	/*
+ 	 * Setup single step
+ 	 */
+ 	kdba_setsinglestep(regs);
+ 
+ 	/*
+ 	 * Reset delay attribute
+ 	 */
+ 	bp->bp_delay = 0;
+ 	bp->bp_delayed = 1;
+ }
+ 
+ 
+ /*
+  * kdba_bptype
+  *
+  *	Return a string describing type of breakpoint.
+  *
+  * Parameters:
+  *	bph	Pointer to hardware breakpoint description
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Character string.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ char *
+ kdba_bptype(kdbhard_bp_t *bph)
+ {
+ 	char *mode;
+ 
+ 	mode = kdba_rwtypes[bph->bph_mode];
+ 
+ 	return mode;
+ }
+ 
+ /*
+  * kdba_printbpreg
+  *
+  *	Print register name assigned to breakpoint
+  *
+  * Parameters:
+  *	bph	Pointer hardware breakpoint structure
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ void
+ kdba_printbpreg(kdbhard_bp_t *bph)
+ {
+ 	kdb_printf(" in dr%ld", bph->bph_reg);
+ }
+ 
+ /*
+  * kdba_printbp
+  *
+  *	Print string describing hardware breakpoint.
+  *
+  * Parameters:
+  *	bph	Pointer to hardware breakpoint description
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ void
+ kdba_printbp(kdb_bp_t *bp)
+ {
+ 	kdb_printf("\n    is enabled");
+ 	if (bp->bp_hardtype) {
+ 		kdba_printbpreg(bp->bp_hard);
+ 		if (bp->bp_hard->bph_mode != 0) {
+ 			kdb_printf(" for %d bytes",
+ 				   bp->bp_hard->bph_length+1);
+ 		}
+ 	}
+ }
+ 
+ /*
+  * kdba_parsebp
+  *
+  *	Parse architecture dependent portion of the
+  *	breakpoint command.
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Zero for success, a kdb diagnostic for failure
+  * Locking:
+  *	None.
+  * Remarks:
+  *	for Ia32 architure, data access, data write and
+  *	I/O breakpoints are supported in addition to instruction
+  * 	breakpoints.
+  *
+  *	{datar|dataw|io|inst} [length]
+  */
+ 
+ int
+ kdba_parsebp(int argc, const char **argv, int *nextargp, kdb_bp_t *bp)
+ {
+ 	int		nextarg = *nextargp;
+ 	int		diag;
+ 	kdbhard_bp_t 	*bph = &bp->bp_template;
+ 
+ 	bph->bph_mode = 0;		/* Default to instruction breakpoint */
+ 	bph->bph_length = 0;		/* Length must be zero for insn bp */
+ 	if ((argc + 1) != nextarg) {
+ 		if (strnicmp(argv[nextarg], "datar", sizeof("datar")) == 0) {
+ 			bph->bph_mode = 3;
+ 		} else if (strnicmp(argv[nextarg], "dataw", sizeof("dataw")) == 0) {
+ 			bph->bph_mode = 1;
+ 		} else if (strnicmp(argv[nextarg], "io", sizeof("io")) == 0) {
+ 			bph->bph_mode = 2;
+ 		} else if (strnicmp(argv[nextarg], "inst", sizeof("inst")) == 0) {
+ 			bph->bph_mode = 0;
+ 		} else {
+ 			return KDB_ARGCOUNT;
+ 		}
+ 
+ 		bph->bph_length = 3;	/* Default to 4 byte */
+ 
+ 		nextarg++;
+ 
+ 		if ((argc + 1) != nextarg) {
+ 			unsigned long len;
+ 
+ 			diag = kdbgetularg((char *)argv[nextarg],
+ 					   &len);
+ 			if (diag)
+ 				return diag;
+ 
+ 
+ 			if ((len > 4) || (len == 3))
+ 				return KDB_BADLENGTH;
+ 
+ 			bph->bph_length = len;
+ 			bph->bph_length--; /* Normalize for debug register */
+ 			nextarg++;
+ 		}
+ 
+ 		if ((argc + 1) != nextarg)
+ 			return KDB_ARGCOUNT;
+ 
+ 		/*
+ 		 * Indicate to architecture independent level that
+ 		 * a hardware register assignment is required to enable
+ 		 * this breakpoint.
+ 		 */
+ 
+ 		bph->bph_free = 0;
+ 	} else {
+ 		if (KDB_DEBUG(BP))
+ 			kdb_printf("kdba_bp: no args, forcehw is %d\n", bp->bp_forcehw);
+ 		if (bp->bp_forcehw) {
+ 			/*
+ 			 * We are forced to use a hardware register for this
+ 			 * breakpoint because either the bph or bpha
+ 			 * commands were used to establish this breakpoint.
+ 			 */
+ 			bph->bph_free = 0;
+ 		} else {
+ 			/*
+ 			 * Indicate to architecture dependent level that
+ 			 * the instruction replacement breakpoint technique
+ 			 * should be used for this breakpoint.
+ 			 */
+ 			bph->bph_free = 1;
+ 			bp->bp_adjust = 1;	/* software, int 3 is one byte */
+ 		}
+ 	}
+ 
+ 	if (bph->bph_mode != 2 && kdba_verify_rw(bp->bp_addr, bph->bph_length+1)) {
+ 		kdb_printf("Invalid address for breakpoint, ignoring bp command\n");
+ 		return KDB_BADADDR;
+ 	}
+ 
+ 	*nextargp = nextarg;
+ 	return 0;
+ }
+ 
+ /*
+  * kdba_allocbp
+  *
+  *	Associate a hardware register with a breakpoint.
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	A pointer to the allocated register kdbhard_bp_t structure for
+  *	success, Null and a non-zero diagnostic for failure.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ kdbhard_bp_t *
+ kdba_allocbp(kdbhard_bp_t *bph, int *diagp)
+ {
+ 	int i;
+ 	kdbhard_bp_t *newbph;
+ 
+ 	for(i=0,newbph=kdb_hardbreaks; i < KDB_MAXHARDBPT; i++, newbph++) {
+ 		if (newbph->bph_free) {
+ 			break;
+ 		}
+ 	}
+ 
+ 	if (i == KDB_MAXHARDBPT) {
+ 		*diagp = KDB_TOOMANYDBREGS;
+ 		return NULL;
+ 	}
+ 
+ 	*diagp = 0;
+ 
+ 	/*
+ 	 * Copy data from template.  Can't just copy the entire template
+ 	 * here because the register number in kdb_hardbreaks must be
+ 	 * preserved.
+ 	 */
+ 	newbph->bph_data = bph->bph_data;
+ 	newbph->bph_write = bph->bph_write;
+ 	newbph->bph_mode = bph->bph_mode;
+ 	newbph->bph_length = bph->bph_length;
+ 
+ 	/*
+ 	 * Mark entry allocated.
+ 	 */
+ 	newbph->bph_free = 0;
+ 
+ 	return newbph;
+ }
+ 
+ /*
+  * kdba_freebp
+  *
+  *	Deallocate a hardware breakpoint
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Zero for success, a kdb diagnostic for failure
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ void
+ kdba_freebp(kdbhard_bp_t *bph)
+ {
+ 	bph->bph_free = 1;
+ }
+ 
+ /*
+  * kdba_initbp
+  *
+  *	Initialize the breakpoint table for the hardware breakpoint
+  *	register.
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Zero for success, a kdb diagnostic for failure
+  * Locking:
+  *	None.
+  * Remarks:
+  *
+  *	There is one entry per register.  On the ia32 architecture
+  *	all the registers are interchangeable, so no special allocation
+  *	criteria are required.
+  */
+ 
+ void
+ kdba_initbp(void)
+ {
+ 	int i;
+ 	kdbhard_bp_t *bph;
+ 
+ 	/*
+ 	 * Clear the hardware breakpoint table
+ 	 */
+ 
+ 	memset(kdb_hardbreaks, '\0', sizeof(kdb_hardbreaks));
+ 
+ 	for(i=0,bph=kdb_hardbreaks; i<KDB_MAXHARDBPT; i++, bph++) {
+ 		bph->bph_reg = i;
+ 		bph->bph_free = 1;
+ 	}
+ }
+ 
+ /*
+  * kdba_installbp
+  *
+  *	Install a breakpoint
+  *
+  * Parameters:
+  *	regs	Exception frame
+  *	bp	Breakpoint structure for the breakpoint to be installed
+  * Outputs:
+  *	None.
+  * Returns:
+  *	0 if breakpoint installed.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	For hardware breakpoints, a debug register is allocated
+  *	and assigned to the breakpoint.  If no debug register is
+  *	available, a warning message is printed and the breakpoint
+  *	is disabled.
+  *
+  *	For instruction replacement breakpoints, we must single-step
+  *	over the replaced instruction at this point so we can re-install
+  *	the breakpoint instruction after the single-step.  SSBPT is set
+  *	when the breakpoint is initially hit and is cleared by any action
+  *	that removes the need for single-step over the breakpoint.
+  */
+ 
+ int
+ kdba_installbp(struct pt_regs *regs, kdb_bp_t *bp)
+ {
+ 	/*
+ 	 * Install the breakpoint, if it is not already installed.
+ 	 */
+ 
+ 	if (KDB_DEBUG(BP)) {
+ 		kdb_printf("kdba_installbp bp_installed %d\n", bp->bp_installed);
+ 	}
+ 	if (!KDB_STATE(SSBPT))
+ 		bp->bp_delay = 0;
+ 	if (!bp->bp_installed) {
+ 		if (bp->bp_hardtype) {
+ 			kdba_installdbreg(bp);
+ 			bp->bp_installed = 1;
+ 			if (KDB_DEBUG(BP)) {
+ 				kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+ 					   bp->bp_hard->bph_reg, bp->bp_addr);
+ 			}
+ 		} else if (bp->bp_delay) {
+ 			if (KDB_DEBUG(BP))
+ 				kdb_printf("kdba_installbp delayed bp\n");
+ 			kdba_handle_bp(regs, bp);
+ 		} else {
+ 			if (kdb_getarea_size(&(bp->bp_inst), bp->bp_addr, 1) ||
+ 			    kdb_putword(bp->bp_addr, IA32_BREAKPOINT_INSTRUCTION, 1)) {
+ 				kdb_printf("kdba_installbp failed to set software breakpoint at 0x%lx\n", bp->bp_addr);
+ 				return(1);
+ 			}
+ 			bp->bp_installed = 1;
+ 			if (KDB_DEBUG(BP))
+ 				kdb_printf("kdba_installbp instruction 0x%x at " kdb_bfd_vma_fmt "\n",
+ 					   IA32_BREAKPOINT_INSTRUCTION, bp->bp_addr);
+ 		}
+ 	}
+ 	return(0);
+ }
+ 
+ /*
+  * kdba_removebp
+  *
+  *	Make a breakpoint ineffective.
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ int
+ kdba_removebp(kdb_bp_t *bp)
+ {
+ 	/*
+ 	 * For hardware breakpoints, remove it from the active register,
+ 	 * for software breakpoints, restore the instruction stream.
+ 	 */
+ 	if (KDB_DEBUG(BP)) {
+ 		kdb_printf("kdba_removebp bp_installed %d\n", bp->bp_installed);
+ 	}
+ 	if (bp->bp_installed) {
+ 		if (bp->bp_hardtype) {
+ 			if (KDB_DEBUG(BP)) {
+ 				kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+ 					   bp->bp_hard->bph_reg, bp->bp_addr);
+ 			}
+ 			kdba_removedbreg(bp);
+ 		} else {
+ 			if (KDB_DEBUG(BP))
+ 				kdb_printf("kdb: restoring instruction 0x%x at " kdb_bfd_vma_fmt "\n",
+ 					   bp->bp_inst, bp->bp_addr);
+ 			if (kdb_putword(bp->bp_addr, bp->bp_inst, 1))
+ 				return(1);
+ 		}
+ 		bp->bp_installed = 0;
+ 	}
+ 	return(0);
+ }
diff -c -r -N console-os/arch/i386/kdb/kdba_bt.c console-os-kdb/arch/i386/kdb/kdba_bt.c
*** console-os/arch/i386/kdb/kdba_bt.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/arch/i386/kdb/kdba_bt.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,379 ----
+ /*
+  * Kernel Debugger Architecture Dependent Stack Traceback
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/config.h>
+ #include <linux/ctype.h>
+ #include <linux/string.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/kallsyms.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ #include <asm/system.h>
+ 
+ #ifdef CONFIG_FRAME_POINTER
+ #define EFPSTR	"EBP"
+ #define EFP	ebp
+ #define NOBP	0
+ #else
+ #define EFPSTR	"ESP"
+ #define EFP	esp
+ #define NOBP	esp
+ #endif
+ 
+ /*
+  * bt_print_one
+  *
+  *	Print one back trace entry.
+  *
+  * Inputs:
+  *	eip	Current program counter, or return address.
+  *	efp	#ifdef CONFIG_FRAME_POINTER: Previous frame pointer ebp,
+  *		0 if not valid; #else: Stack pointer esp when at eip.
+  *	ar	Activation record for this frame.
+  *	symtab	Information about symbol that eip falls within.
+  *	argcount Maximum number of arguments to print.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	None.
+  */
+ 
+ static void
+ bt_print_one(kdb_machreg_t eip, kdb_machreg_t efp, const kdb_ar_t *ar,
+ 	     const kdb_symtab_t *symtab, int argcount)
+ {
+ 	int	btsymarg = 0;
+ 	int	nosect = 0;
+ 	kdb_machreg_t word;
+ 
+ 	kdbgetintenv("BTSYMARG", &btsymarg);
+ 	kdbgetintenv("NOSECT", &nosect);
+ 
+ 	if (efp)
+ 		kdb_printf("0x%08lx", efp);
+ 	else
+ 		kdb_printf("          ");
+ 	kdb_symbol_print(eip, symtab, KDB_SP_SPACEB|KDB_SP_VALUE);
+ 	if (argcount && ar->args) {
+ 		int i, argc = ar->args / 4;
+ 
+ 		kdb_printf(" (");
+ 		if (argc > argcount)
+ 			argc = argcount;
+ 
+ 		for(i=1; i<=argc; i++){
+ 			kdb_machreg_t argp = ar->arg0 - ar->args + 4*i;
+ 
+ 			if (i != 1)
+ 				kdb_printf(", ");
+ 			kdb_getword(&word, argp, sizeof(word));
+ 			kdb_printf("0x%lx", word);
+ 		}
+ 		kdb_printf(")");
+ 	}
+ 	if (symtab->sym_name) {
+ 		if (!nosect) {
+ 			kdb_printf("\n");
+ 			kdb_printf("                               %s %s 0x%lx 0x%lx 0x%lx",
+ 				symtab->mod_name,
+ 				symtab->sec_name,
+ 				symtab->sec_start,
+ 				symtab->sym_start,
+ 				symtab->sym_end);
+ 		}
+ 	}
+ 	kdb_printf("\n");
+ 	if (argcount && ar->args && btsymarg) {
+ 		int i, argc = ar->args / 4;
+ 		kdb_symtab_t	arg_symtab;
+ 		kdb_machreg_t	arg;
+ 		for(i=1; i<=argc; i++){
+ 			kdb_machreg_t argp = ar->arg0 - ar->args + 4*i;
+ 			kdb_getword(&arg, argp, sizeof(arg));
+ 			if (kdbnearsym(arg, &arg_symtab)) {
+ 				kdb_printf("                               ");
+ 				kdb_symbol_print(arg, &arg_symtab, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+ 			}
+ 		}
+ 	}
+ }
+ 
+ /*
+  * kdba_bt_stack
+  *
+  * Inputs:
+  *	addr	Pointer to Address provided to 'bt' command, if any.
+  *	argcount
+  *	p	Pointer to task for 'btp' command.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	mds comes in handy when examining the stack to do a manual
+  *	traceback.
+  */
+ 
+ static int
+ kdba_bt_stack(kdb_machreg_t addr, int argcount, struct task_struct *p)
+ {
+ 	kdb_ar_t	ar;
+ 	kdb_machreg_t	eip, esp, ebp, ss, cs;
+ 	kdb_symtab_t	symtab;
+ 	int count;
+ 
+ 	/*
+ 	 * The caller may have supplied an address at which the
+ 	 * stack traceback operation should begin.  This address
+ 	 * is assumed by this code to point to a return-address
+ 	 * on the stack to be traced back.
+ 	 *
+ 	 * The end result of this will make it appear as if a function
+ 	 * entitled '<unknown>' was called from the function which
+ 	 * contains return-address.
+ 	 */
+ 	if (addr) {
+ 		eip = 0;
+ 		ebp = 0;
+ 		esp = addr;
+ 		cs  = __KERNEL_CS;	/* have to assume kernel space */
+ 	} else {
+ 		if (kdb_task_has_cpu(p)) {
+ 			struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+ 			struct pt_regs *regs;
+ 			if (!krp->seqno) {
+ 				kdb_printf("Process did not save state, cannot backtrace\n");
+ 				kdb_ps1(p);
+ 				return 0;
+ 			}
+ 			regs = krp->regs;
+ 			if (KDB_NULL_REGS(regs))
+ 				return KDB_BADREG;
+ 			kdba_getregcontents("eip", regs, &eip);
+ 			kdba_getregcontents("ebp", regs, &ebp);
+ 			kdba_getregcontents("esp", regs, &esp);
+ 			kdba_getregcontents("xcs", regs, &cs);
+ 		}
+ 		else {
+ 			/* Not on cpu, assume blocked.  Blocked i386 tasks do
+ 			 * not have pt_regs.  p->thread.{esp,eip} are set, esp
+ 			 * points to the ebp value, assume kernel space.
+ 			 */
+ 			eip = p->thread.eip;
+ 			esp = p->thread.esp;
+ 			ebp = *(unsigned long *)esp;
+ 			cs  = __KERNEL_CS;
+ 		}
+ 		if (esp < (unsigned long)p || esp >= (unsigned long)p + THREAD_SIZE) {
+ 			kdb_printf("Stack is not in task_struct, backtrace not available\n");
+ 			return(0);
+ 		}
+ 	}
+ 	ss = esp & -THREAD_SIZE;
+ 
+ 	if ((cs & 0xffff) != __KERNEL_CS) {
+ 		kdb_printf("Stack is not in kernel space, backtrace not available\n");
+ 		return 0;
+ 	}
+ 
+ 	kdb_printf(EFPSTR "        EIP        Function (args)\n");
+ 
+ 	/*
+ 	 * Run through the activation records and print them.
+ 	 */
+ 
+ 	for (count = 0; count < 200; ++count) {
+ 		kdb_ar_t save_ar = ar;
+ 		kdbnearsym(eip, &symtab);
+ 		if (!kdb_get_next_ar(esp, symtab.sym_start, eip, ebp, ss,
+ 			&ar, &symtab)) {
+ 			break;
+ 		}
+ 
+ 		if (strncmp(".text.lock.", symtab.sym_name, 11) == 0) {
+ 			/*
+ 			 * Instructions in the .text.lock area are generated by
+ 			 * the out of line code in lock handling, see
+ 			 * include/asm-i386 semaphore.h and rwlock.h.  There can
+ 			 * be multiple instructions which eventually end with a
+ 			 * jump back to the mainline code.  Use the disassmebler
+ 			 * to silently step through the code until we find the
+ 			 * jump, resolve its destination and translate it to a
+ 			 * symbol.  Replace '.text.lock' with the symbol.
+ 			 */
+ 			unsigned char inst;
+ 			kdb_machreg_t offset = 0, realeip = eip;
+ 			int length, offsize = 0;
+ 			kdb_symtab_t lock_symtab;
+ 			/* Dummy out the disassembler print function */
+ 			fprintf_ftype save_fprintf_func = kdb_di.fprintf_func;
+ 
+ 			kdb_di.fprintf_func = &kdb_dis_fprintf_dummy;
+ 			while((length = kdba_id_printinsn(realeip, &kdb_di)) > 0) {
+ 				kdb_getarea(inst, realeip);
+ 				offsize = 0;
+ 				switch (inst) {
+ 				case 0xeb:	/* jmp with 1 byte offset */
+ 					offsize = 1-4;
+ 					/* drop through */
+ 				case 0xe9:	/* jmp with 4 byte offset */
+ 					offsize += 4;
+ 					kdb_getword(&offset, realeip+1, offsize);
+ 					break;
+ 				default:
+ 					realeip += length;	/* next instruction */
+ 					break;
+ 				}
+ 				if (offsize)
+ 					break;
+ 			}
+ 			kdb_di.fprintf_func = save_fprintf_func;
+ 
+ 			if (offsize) {
+ 				realeip += 1 + offsize + (offsize == 1 ? (s8)offset : (s32)offset);
+ 				if (kdbnearsym(realeip, &lock_symtab)) {
+ 					/* Print the stext entry without args */
+ 					bt_print_one(eip, NOBP, &ar, &symtab, 0);
+ 					/* Point to mainline code */
+ 					eip = realeip;
+ 					ar = save_ar;	/* lock text does not consume an activation frame */
+ 					continue;
+ 				}
+ 			}
+ 		}
+ 
+ 		if (strcmp("ret_from_intr", symtab.sym_name) == 0 ||
+ 		    strcmp("error_code", symtab.sym_name) == 0) {
+ 			if (strcmp("ret_from_intr", symtab.sym_name) == 0) {
+ 				/*
+ 				 * Non-standard frame.  ret_from_intr is
+ 				 * preceded by 9 registers (ebx, ecx, edx, esi,
+ 				 * edi, ebp, eax, ds, cs), original eax and the
+ 				 * return address for a total of 11 words.
+ 				 */
+ 				ar.start = ar.end + 11*4;
+ 			}
+ 			if (strcmp("error_code", symtab.sym_name) == 0) {
+ 				/*
+ 				 * Non-standard frame.  error_code is preceded
+ 				 * by two parameters (-> registers, error code),
+ 				 * 9 registers (ebx, ecx, edx, esi, edi, ebp,
+ 				 * eax, ds, cs), original eax and the return
+ 				 * address for a total of 13 words.
+ 				 */
+ 				ar.start = ar.end + 13*4;
+ 			}
+ 			/* Print the non-standard entry without args */
+ 			bt_print_one(eip, NOBP, &ar, &symtab, 0);
+ 			kdb_printf("Interrupt registers:\n");
+ 			kdba_dumpregs((struct pt_regs *)(ar.end), NULL, NULL);
+ 			/* Step the frame to the interrupted code */
+ 			kdb_getword(&eip, ar.start-4, 4);
+ 			ebp = 0;
+ 			esp = ar.start;
+ 			if ((((struct pt_regs *)(ar.end))->xcs & 0xffff) != __KERNEL_CS) {
+ 				kdb_printf("Interrupt from user space, end of kernel trace\n");
+ 				break;
+ 			}
+ 			continue;
+ 		}
+ 
+ 		bt_print_one(eip, EFP, &ar, &symtab, argcount);
+ 
+ 		if (ar.ret == 0)
+ 			break;	/* End of frames */
+ 		eip = ar.ret;
+ 		ebp = ar.oldfp;
+ 		esp = ar.start;
+ 	}
+ 	if (count >= 200)
+ 		kdb_printf("bt truncated, count limit reached\n");
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdba_bt_address
+  *
+  *	Do a backtrace starting at a specified stack address.  Use this if the
+  *	heuristics get the i386 stack decode wrong.
+  *
+  * Inputs:
+  *	addr	Address provided to 'bt' command.
+  *	argcount
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	mds %esp comes in handy when examining the stack to do a manual
+  *	traceback.
+  */
+ 
+ int
+ kdba_bt_address(kdb_machreg_t addr, int argcount)
+ {
+ 	return kdba_bt_stack(addr, argcount, NULL);
+ }
+ 
+ /*
+  * kdba_bt_process
+  *
+  *	Do a backtrace for a specified process.
+  *
+  * Inputs:
+  *	p	Struct task pointer extracted by 'bt' command.
+  *	argcount
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  */
+ 
+ int
+ kdba_bt_process(struct task_struct *p, int argcount)
+ {
+ 	return kdba_bt_stack(0, argcount, p);
+ }
diff -c -r -N console-os/arch/i386/kdb/kdba_id.c console-os-kdb/arch/i386/kdb/kdba_id.c
*** console-os/arch/i386/kdb/kdba_id.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/arch/i386/kdb/kdba_id.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,279 ----
+ /*
+  * Kernel Debugger Architecture Dependent Instruction Disassembly
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <stdarg.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/ctype.h>
+ #include <linux/string.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ 
+ /*
+  * kdba_dis_getsym
+  *
+  *	Get a symbol for the disassembler.
+  *
+  * Parameters:
+  *	addr	Address for which to get symbol
+  *	dip	Pointer to disassemble_info
+  * Returns:
+  *	0
+  * Locking:
+  * Remarks:
+  *	Not used for kdb.
+  */
+ 
+ /* ARGSUSED */
+ static int
+ kdba_dis_getsym(bfd_vma addr, disassemble_info *dip)
+ {
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdba_printaddress
+  *
+  *	Print (symbolically) an address.
+  *
+  * Parameters:
+  *	addr	Address for which to get symbol
+  *	dip	Pointer to disassemble_info
+  *	flag	True if a ":<tab>" sequence should follow the address
+  * Returns:
+  *	0
+  * Locking:
+  * Remarks:
+  *
+  */
+ 
+ /* ARGSUSED */
+ void
+ kdba_printaddress(kdb_machreg_t addr, disassemble_info *dip, int flag)
+ {
+ 	kdb_symtab_t symtab;
+ 	int spaces = 5;
+ 	unsigned int offset;
+ 
+ 	/*
+ 	 * Print a symbol name or address as necessary.
+ 	 */
+ 	kdbnearsym(addr, &symtab);
+ 	if (symtab.sym_name) {
+ 		/* Do not use kdb_symbol_print here, it always does
+ 		 * kdb_printf but we want dip->fprintf_func.
+ 		 */
+ 		dip->fprintf_func(dip->stream,
+ 			"0x%0*lx %s",
+ 			2*sizeof(addr), addr, symtab.sym_name);
+ 		if ((offset = addr - symtab.sym_start) == 0) {
+ 			spaces += 4;
+ 		}
+ 		else {
+ 			unsigned int o = offset;
+ 			while (o >>= 4)
+ 				--spaces;
+ 			dip->fprintf_func(dip->stream, "+0x%x", offset);
+ 		}
+ 
+ 	} else {
+ 		dip->fprintf_func(dip->stream, "0x%x", addr);
+ 	}
+ 
+ 	if (flag) {
+ 		if (spaces < 1) {
+ 			spaces = 1;
+ 		}
+ 		dip->fprintf_func(dip->stream, ":%*s", spaces, " ");
+ 	}
+ }
+ 
+ /*
+  * kdba_dis_printaddr
+  *
+  *	Print (symbolically) an address.  Called by GNU disassembly
+  *	code via disassemble_info structure.
+  *
+  * Parameters:
+  *	addr	Address for which to get symbol
+  *	dip	Pointer to disassemble_info
+  * Returns:
+  *	0
+  * Locking:
+  * Remarks:
+  *	This function will never append ":<tab>" to the printed
+  *	symbolic address.
+  */
+ 
+ static void
+ kdba_dis_printaddr(bfd_vma addr, disassemble_info *dip)
+ {
+ 	kdba_printaddress(addr, dip, 0);
+ }
+ 
+ /*
+  * kdba_dis_getmem
+  *
+  *	Fetch 'length' bytes from 'addr' into 'buf'.
+  *
+  * Parameters:
+  *	addr	Address for which to get symbol
+  *	buf	Address of buffer to fill with bytes from 'addr'
+  *	length	Number of bytes to fetch
+  *	dip	Pointer to disassemble_info
+  * Returns:
+  *	0 if data is available, otherwise error.
+  * Locking:
+  * Remarks:
+  *
+  */
+ 
+ /* ARGSUSED */
+ static int
+ kdba_dis_getmem(bfd_vma addr, bfd_byte *buf, unsigned int length, disassemble_info *dip)
+ {
+ 	return kdb_getarea_size(buf, addr, length);
+ }
+ 
+ /*
+  * kdba_id_parsemode
+  *
+  * 	Parse IDMODE environment variable string and
+  *	set appropriate value into "disassemble_info" structure.
+  *
+  * Parameters:
+  *	mode	Mode string
+  *	dip	Disassemble_info structure pointer
+  * Returns:
+  * Locking:
+  * Remarks:
+  *	We handle the values 'x86' and '8086' to enable either
+  *	32-bit instruction set or 16-bit legacy instruction set.
+  */
+ 
+ int
+ kdba_id_parsemode(const char *mode, disassemble_info *dip)
+ {
+ 
+ 	if (mode) {
+ 		if (strcmp(mode, "x86") == 0) {
+ 			dip->mach = bfd_mach_i386_i386;
+ 		} else if (strcmp(mode, "8086") == 0) {
+ 			dip->mach = bfd_mach_i386_i8086;
+ 		} else {
+ 			return KDB_BADMODE;
+ 		}
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdba_check_pc
+  *
+  * 	Check that the pc is satisfactory.
+  *
+  * Parameters:
+  *	pc	Program Counter Value.
+  * Returns:
+  *	None
+  * Locking:
+  *	None.
+  * Remarks:
+  *	Can change pc.
+  */
+ 
+ void
+ kdba_check_pc(kdb_machreg_t *pc)
+ {
+ 	/* No action */
+ }
+ 
+ /*
+  * kdba_id_printinsn
+  *
+  * 	Format and print a single instruction at 'pc'. Return the
+  *	length of the instruction.
+  *
+  * Parameters:
+  *	pc	Program Counter Value.
+  *	dip	Disassemble_info structure pointer
+  * Returns:
+  *	Length of instruction, -1 for error.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	Depends on 'IDMODE' environment variable.
+  */
+ 
+ int
+ kdba_id_printinsn(kdb_machreg_t pc, disassemble_info *dip)
+ {
+ 	kdba_printaddress(pc, dip, 1);
+ 	return print_insn_i386_att(pc, dip);
+ }
+ 
+ /*
+  * kdba_id_init
+  *
+  * 	Initialize the architecture dependent elements of
+  *	the disassembly information structure
+  *	for the GNU disassembler.
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ void __init
+ kdba_id_init(disassemble_info *dip)
+ {
+ 	dip->read_memory_func       = kdba_dis_getmem;
+ 	dip->print_address_func     = kdba_dis_printaddr;
+ 	dip->symbol_at_address_func = kdba_dis_getsym;
+ 
+ 	dip->flavour                = bfd_target_elf_flavour;
+ 	dip->arch		    = bfd_arch_i386;
+ 	dip->mach		    = bfd_mach_i386_i386;
+ 	dip->endian	    	    = BFD_ENDIAN_LITTLE;
+ 
+ 	dip->display_endian         = BFD_ENDIAN_LITTLE;
+ }
diff -c -r -N console-os/arch/i386/kdb/kdba_io.c console-os-kdb/arch/i386/kdb/kdba_io.c
*** console-os/arch/i386/kdb/kdba_io.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/arch/i386/kdb/kdba_io.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,518 ----
+ /*
+  * Kernel Debugger Architecture Dependent Console I/O handler
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <asm/io.h>
+ #include <linux/delay.h>
+ #include <linux/pc_keyb.h>
+ #include <linux/console.h>
+ #include <linux/ctype.h>
+ #include <linux/keyboard.h>
+ #include <linux/serial.h>
+ #include <linux/serial_reg.h>
+ 
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ #include <asm/keyboard.h>	/* ashishk@sco.com */
+ 
+ #ifdef	CONFIG_VT_CONSOLE
+ #define KDB_BLINK_LED 1
+ #else
+ #undef	KDB_BLINK_LED
+ #endif
+ 
+ #ifdef CONFIG_KDB_USB
+ struct kdb_usb_exchange kdb_usb_infos = { NULL, NULL, NULL, NULL, NULL, 0};
+ 
+ static unsigned char kdb_usb_keycode[256] = {
+ 	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
+ 	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
+ 	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
+ 	 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+ 	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
+ 	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
+ 	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
+ 	120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
+ 	115,114,  0,  0,  0,124,  0,181,182,183,184,185,186,187,188,189,
+ 	190,191,192,193,194,195,196,197,198,  0,  0,  0,  0,  0,  0,  0,
+ 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+ 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+ 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+ 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+ 	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
+ 	150,158,159,128,136,177,178,176,142,152,173,140
+ };
+ 
+ /* get_usb_char
+  * This function drives the UHCI controller,
+  * fetch the USB scancode and decode it
+  */
+ static int get_usb_char(void)
+ {
+ 	static int usb_lock;
+ 	unsigned char keycode, spec;
+ 	extern u_short  plain_map[], shift_map[], ctrl_map[];
+ 
+ 	/* Is USB initialized ? */
+ 	if(!kdb_usb_infos.poll_func)
+     		return -1;
+ 
+ 	/* Transfer char if they are present */
+ 	(*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb);
+ 
+ 	spec = kdb_usb_infos.buffer[0];
+ 	keycode = kdb_usb_infos.buffer[2];
+ 	kdb_usb_infos.buffer[0] = (char)0;
+ 	kdb_usb_infos.buffer[2] = (char)0;
+ 
+ 	if(kdb_usb_infos.buffer[3])
+   		return -1;
+ 
+ 	/* A normal key is pressed, decode it */
+ 	if(keycode)
+ 		keycode = kdb_usb_keycode[keycode];
+ 
+ 	/* 2 Keys pressed at one time ? */
+ 	if (spec && keycode) {
+ 		switch(spec)
+   		{
+   			case 0x2:
+   			case 0x20: /* Shift */
+     				return shift_map[keycode];
+ 	  		case 0x1:
+   			case 0x10: /* Ctrl */
+     				return ctrl_map[keycode];
+ 			case 0x4:
+ 			case 0x40: /* Alt */
+     				break;
+   		}
+ 	}
+ 	else {
+     		if(keycode) { /* If only one key pressed */
+       			switch(keycode)
+ 			{
+ 				case 0x1C: /* Enter */
+ 	  				return 13;
+ 
+ 				case 0x3A: /* Capslock */
+ 	  				usb_lock ? (usb_lock = 0) : (usb_lock = 1);
+ 	  				break;
+ 				case 0x0E: /* Backspace */
+ 	  				return 8;
+ 				case 0x0F: /* TAB */
+ 					return 9;
+ 				case 0x77: /* Pause */
+ 	  				break ;
+ 				default:
+ 	  				if(!usb_lock) {
+ 	    					return plain_map[keycode];
+ 					}
+ 					else {
+ 	    					return shift_map[keycode];
+ 	  				}
+ 			}
+     		}
+    	}
+ 	return -1;
+ }
+ #endif
+ 
+ /*
+  * This module contains code to read characters from the keyboard or a serial
+  * port.
+  *
+  * It is used by the kernel debugger, and is polled, not interrupt driven.
+  *
+  */
+ 
+ #ifdef	KDB_BLINK_LED
+ /*
+  * send:  Send a byte to the keyboard controller.  Used primarily to
+  * 	  alter LED settings.
+  */
+ 
+ static void
+ kdb_kbdsend(unsigned char byte)
+ {
+ 	while (inb(KBD_STATUS_REG) & KBD_STAT_IBF)
+ 		;
+ 	outb(byte, KBD_DATA_REG);
+ }
+ 
+ static void
+ kdb_toggleled(int led)
+ {
+ 	static int leds;
+ 
+ 	leds ^= led;
+ 
+ 	kdb_kbdsend(KBD_CMD_SET_LEDS);
+ 	kdb_kbdsend((unsigned char)leds);
+ }
+ #endif	/* KDB_BLINK_LED */
+ 
+ #if defined(CONFIG_SERIAL_CONSOLE)
+ 
+ struct kdb_serial kdb_serial;
+ 
+ static inline unsigned int
+ serial_inp(struct kdb_serial *kdb_serial, unsigned long offset)
+ {
+ 	offset <<= kdb_serial->ioreg_shift;
+ 
+ 	switch (kdb_serial->io_type) {
+ 	case SERIAL_IO_MEM:
+ 		return readb(kdb_serial->iobase + offset);
+ 		break;
+ 	default:
+ 		return inb(kdb_serial->iobase + offset);
+ 		break;
+ 	}
+ }
+ 
+ /* Check if there is a byte ready at the serial port */
+ static int get_serial_char(void)
+ {
+ 	unsigned char ch;
+ 
+ 	if (kdb_serial.iobase == 0)
+ 		return -1;
+ 
+ 	if (serial_inp(&kdb_serial, UART_LSR) & UART_LSR_DR) {
+ 		ch = serial_inp(&kdb_serial, UART_RX);
+ 		if (ch == 0x7f)
+ 			ch = 8;
+ 		return ch;
+ 	}
+ 	return -1;
+ }
+ #endif /* CONFIG_SERIAL_CONSOLE */
+ 
+ #ifdef	CONFIG_VT_CONSOLE
+ 
+ static int kbd_exists = -1;
+ 
+ /*
+  * Check if the keyboard controller has a keypress for us.
+  * Some parts (Enter Release, LED change) are still blocking polled here,
+  * but hopefully they are all short.
+  */
+ static int get_kbd_char(void)
+ {
+ 	int	scancode, scanstatus;
+ 	static int shift_lock;	/* CAPS LOCK state (0-off, 1-on) */
+ 	static int shift_key;	/* Shift next keypress */
+ 	static int ctrl_key;
+ 	u_short keychar;
+ 	extern u_short plain_map[], shift_map[], ctrl_map[];
+ 
+ 	if (kbd_exists <= 0) {
+ 		if (kbd_exists == 0)
+ 			return -1;
+ 
+ 		if (inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff) {
+ 			kbd_exists = 0;
+ 			return -1;
+ 		}
+ 		kbd_exists = 1;
+ 	}
+ 
+ 	if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
+ 		return -1;
+ 
+ 	/*
+ 	 * Fetch the scancode
+ 	 */
+ 	scancode = inb(KBD_DATA_REG);
+ 	scanstatus = inb(KBD_STATUS_REG);
+ 
+ 	/*
+ 	 * Ignore mouse events.
+ 	 */
+ 	if (scanstatus & KBD_STAT_MOUSE_OBF)
+ 		return -1;
+ 
+ 	/*
+ 	 * Ignore release, trigger on make
+ 	 * (except for shift keys, where we want to
+ 	 *  keep the shift state so long as the key is
+ 	 *  held down).
+ 	 */
+ 
+ 	if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) {
+ 		/*
+ 		 * Next key may use shift table
+ 		 */
+ 		if ((scancode & 0x80) == 0) {
+ 			shift_key=1;
+ 		} else {
+ 			shift_key=0;
+ 		}
+ 		return -1;
+ 	}
+ 
+ 	if ((scancode&0x7f) == 0x1d) {
+ 		/*
+ 		 * Left ctrl key
+ 		 */
+ 		if ((scancode & 0x80) == 0) {
+ 			ctrl_key = 1;
+ 		} else {
+ 			ctrl_key = 0;
+ 		}
+ 		return -1;
+ 	}
+ 
+ 	if ((scancode & 0x80) != 0)
+ 		return -1;
+ 
+ 	scancode &= 0x7f;
+ 
+ 	/*
+ 	 * Translate scancode
+ 	 */
+ 
+ 	if (scancode == 0x3a) {
+ 		/*
+ 		 * Toggle caps lock
+ 		 */
+ 		shift_lock ^= 1;
+ 
+ #ifdef	KDB_BLINK_LED
+ 		kdb_toggleled(0x4);
+ #endif
+ 		return -1;
+ 	}
+ 
+ 	if (scancode == 0x0e) {
+ 		/*
+ 		 * Backspace
+ 		 */
+ 		return 8;
+ 	}
+ 
+ 	/* Special Key */
+ 	switch (scancode) {
+ 	case 0xF: /* Tab */
+ 		return 9;
+ 	case 0x53: /* Del */
+ 		return 4;
+ 	case 0x47: /* Home */
+ 		return 1;
+ 	case 0x4F: /* End */
+ 		return 5;
+ 	case 0x4B: /* Left */
+ 		return 2;
+ 	case 0x48: /* Up */
+ 		return 16;
+ 	case 0x50: /* Down */
+ 		return 14;
+ 	case 0x4D: /* Right */
+ 		return 6;
+ 	}
+ 
+ 	if (scancode == 0xe0) {
+ 		return -1;
+ 	}
+ 
+ 	/*
+ 	 * For Japanese 86/106 keyboards
+ 	 * 	See comment in drivers/char/pc_keyb.c.
+ 	 * 	- Masahiro Adegawa
+ 	 */
+ 	if (scancode == 0x73) {
+ 		scancode = 0x59;
+ 	} else if (scancode == 0x7d) {
+ 		scancode = 0x7c;
+ 	}
+ 
+ 	if (!shift_lock && !shift_key && !ctrl_key) {
+ 		keychar = plain_map[scancode];
+ 	} else if (shift_lock || shift_key) {
+ 		keychar = shift_map[scancode];
+ 	} else if (ctrl_key) {
+ 		keychar = ctrl_map[scancode];
+ 	} else {
+ 		keychar = 0x0020;
+ 		kdb_printf("Unknown state/scancode (%d)\n", scancode);
+ 	}
+ 	keychar &= 0x0fff;
+ 	if (keychar == '\t')
+ 		keychar = ' ';
+ 	switch (KTYP(keychar)) {
+ 	case KT_LETTER:
+ 	case KT_LATIN:
+ 		if (isprint(keychar))
+ 			break;		/* printable characters */
+ 		/* drop through */
+ 	case KT_SPEC:
+ 		if (keychar == K_ENTER)
+ 			break;
+ 		/* drop through */
+ 	default:
+ 		return(-1);	/* ignore unprintables */
+ 	}
+ 
+ 	if ((scancode & 0x7f) == 0x1c) {
+ 		/*
+ 		 * enter key.  All done.  Absorb the release scancode.
+ 		 */
+ 		while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
+ 			;
+ 
+ 		/*
+ 		 * Fetch the scancode
+ 		 */
+ 		scancode = inb(KBD_DATA_REG);
+ 		scanstatus = inb(KBD_STATUS_REG);
+ 
+ 		while (scanstatus & KBD_STAT_MOUSE_OBF) {
+ 			scancode = inb(KBD_DATA_REG);
+ 			scanstatus = inb(KBD_STATUS_REG);
+ 		}
+ 
+ 		if (scancode != 0x9c) {
+ 			/*
+ 			 * Wasn't an enter-release,  why not?
+ 			 */
+ 			kdb_printf("kdb: expected enter got 0x%x status 0x%x\n",
+ 			       scancode, scanstatus);
+ 		}
+ 
+ 		kdb_printf("\n");
+ 		return 13;
+ 	}
+ 
+ 	return keychar & 0xff;
+ }
+ #endif	/* CONFIG_VT_CONSOLE */
+ 
+ #ifdef KDB_BLINK_LED
+ 
+ /* Leave numlock alone, setting it messes up laptop keyboards with the keypad
+  * mapped over normal keys.
+  */
+ int kdba_blink_mask = 0x1 | 0x4;
+ 
+ #define BOGOMIPS (boot_cpu_data.loops_per_jiffy/(500000/HZ))
+ static int blink_led(void)
+ {
+ 	static long delay;
+ 
+ 	if (kbd_exists == 0)
+ 		return -1;
+ 
+ 	if (--delay < 0) {
+ 		if (BOGOMIPS == 0)	/* early kdb */
+ 			delay = 150000000/1000;     /* arbitrary bogomips */
+ 		else
+ 			delay = 150000000/BOGOMIPS; /* Roughly 1 second when polling */
+ 		kdb_toggleled(kdba_blink_mask);
+ 	}
+ 	return -1;
+ }
+ #endif
+ 
+ get_char_func poll_funcs[] = {
+ #if defined(CONFIG_VT_CONSOLE)
+ 	get_kbd_char,
+ #endif
+ #if defined(CONFIG_SERIAL_CONSOLE)
+ 	get_serial_char,
+ #endif
+ #ifdef KDB_BLINK_LED
+ 	blink_led,
+ #endif
+ #ifdef CONFIG_KDB_USB
+ 	get_usb_char,
+ #endif
+ 	NULL
+ };
+ 
+ /* 
+  * On some Compaq Deskpro's, there is a keyboard freeze many times after
+  * exiting from the kdb. As kdb's keyboard handler is not interrupt-driven and 
+  * uses a polled interface, it makes more sense to disable motherboard keyboard
+  * controller's OBF interrupts during kdb's polling.In case, of interrupts 
+  * remaining enabled during kdb's polling, it may cause un-necessary 
+  * interrupts being signalled during keypresses, which are also sometimes seen
+  * as spurious interrupts after exiting from kdb. This hack to disable OBF
+  * interrupts before entry to kdb and re-enabling them at kdb exit point also 
+  * solves the keyboard freeze issue. These functions are called from
+  * kdb_local(), hence these are arch. specific setup and cleanup functions
+  * executing only on the local processor - ashishk@sco.com 
+  */
+ 
+ void kdba_local_arch_setup(void)
+ {
+ 	unsigned char c;
+ 
+ 	while (kbd_read_status() & KBD_STAT_IBF);
+ 	kbd_write_command(KBD_CCMD_READ_MODE);
+ 	mdelay(1);
+ 	while (kbd_read_status() & KBD_STAT_IBF);
+ 	while ( !(kbd_read_status() & KBD_STAT_OBF) );
+ 	c = kbd_read_input();
+ 	c &= ~KBD_MODE_KBD_INT;
+ 	while (kbd_read_status() & KBD_STAT_IBF);
+ 	kbd_write_command(KBD_CCMD_WRITE_MODE);
+ 	mdelay(1);
+ 	while (kbd_read_status() & KBD_STAT_IBF);
+ 	kbd_write_output(c);
+ 	mdelay(1);
+ 	while (kbd_read_status() & KBD_STAT_IBF);
+ 	mdelay(1);
+ }
+ 
+ void kdba_local_arch_cleanup(void)
+ {
+ 	unsigned char c;
+ 
+ 	while (kbd_read_status() & KBD_STAT_IBF);
+ 	kbd_write_command(KBD_CCMD_READ_MODE);
+ 	mdelay(1);
+ 	while (kbd_read_status() & KBD_STAT_IBF);
+ 	while ( !(kbd_read_status() & KBD_STAT_OBF) );
+ 	c = kbd_read_input();
+ 	c |= KBD_MODE_KBD_INT;
+ 	while (kbd_read_status() & KBD_STAT_IBF);
+ 	kbd_write_command(KBD_CCMD_WRITE_MODE);
+ 	mdelay(1);
+ 	while (kbd_read_status() & KBD_STAT_IBF);
+ 	kbd_write_output(c);
+ 	mdelay(1);
+ 	while (kbd_read_status() & KBD_STAT_IBF);
+ 	mdelay(1);
+ }
diff -c -r -N console-os/arch/i386/kdb/kdbasupport.c console-os-kdb/arch/i386/kdb/kdbasupport.c
*** console-os/arch/i386/kdb/kdbasupport.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/arch/i386/kdb/kdbasupport.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,1407 ----
+ /*
+  * Kernel Debugger Architecture Independent Support Functions
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/config.h>
+ #include <linux/string.h>
+ #include <linux/stddef.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/ptrace.h>
+ #include <linux/mm.h>
+ #include <linux/sched.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/msr.h>
+ #include <asm/uaccess.h>
+ 
+ /*
+  * kdba_find_return_1
+  *
+  *	Given a starting point on the stack and symtab data for the
+  *	current function, scan up the stack looking for a return
+  *	address for this function.
+  * Inputs:
+  *	sp	Starting stack pointer for scan
+  *	ss	Start of stack for current process
+  *	symtab	kallsyms symbol data for the function
+  *	assume	When false, do not apply tests that have to assume a branch is valid
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Position on stack of return address, 0 if not found.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	This is sensitive to the calling sequence generated by gcc.
+  */
+ 
+ static kdb_machreg_t
+ kdba_find_return_1(kdb_machreg_t sp, kdb_machreg_t ss, const kdb_symtab_t *symtab, int assume)
+ {
+ 	kdb_machreg_t	ret;
+ 	kdb_symtab_t	caller_symtab;
+ 	unsigned long	disp8;
+ 	unsigned long	disp32;
+ 	unsigned char	code[7];
+ #define retaddr(off) code[sizeof(code)+(off)]
+ 
+ 	for (;ret = 0, sp & (THREAD_SIZE-1);sp += 4) {
+ 		if (KDB_DEBUG(ARA)) {
+ 			kdb_printf("    sp=0x%lx", sp);
+ 		}
+ 		if (kdb_getword(&ret, sp, 4))
+ 			break;
+ 		kdbnearsym(ret, &caller_symtab);
+ 		if (KDB_DEBUG(ARA)) {
+ 			kdb_printf(" ret=");
+ 			kdb_symbol_print(ret, &caller_symtab, KDB_SP_DEFAULT|KDB_SP_SYMSIZE);
+ 		}
+ 		if (!caller_symtab.sym_name) {
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf("\n");
+ 			}
+ 			continue;	/* not a valid kernel address */
+ 		}
+ 		KDB_STATE_SET(SUPPRESS);
+ 		if (kdb_getarea(code, ret-sizeof(code)) ||
+ 		    kdb_getword(&disp32, ret-4, 4) ||
+ 		    kdb_getword(&disp8, ret-1, 1))
+ 			continue;	/* not a valid return address */
+ 		if (retaddr(-5) == 0xe8) {
+ 			/* call disp32 */
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" call disp32");
+ 			}
+ 			if (ret + (s32) disp32 == symtab->sym_start) {
+ 				if (KDB_DEBUG(ARA)) {
+ 					kdb_printf(" matched\n");
+ 				}
+ 				break;		/* call to this function */
+ 			}
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" failed");
+ 			}
+ 		} else if (retaddr(-5) == 0xe9) {
+ 			/* jmp disp32.  I have been told that gcc may
+ 			 * do function tail optimization and replace
+ 			 * call with jmp.
+ 			 */
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" jmp disp32\n");
+ 			}
+ 			if (ret + (s32) disp32 == symtab->sym_start) {
+ 				if (KDB_DEBUG(ARA)) {
+ 					kdb_printf(" matched\n");
+ 				}
+ 				break;		/* jmp to this function */
+ 			}
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" failed");
+ 			}
+ 		} else if (retaddr(-2) == 0xeb) {
+ 			/* jmp disp8 */
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" jmp disp8\n");
+ 			}
+ 			if (ret + (s8) disp8 == symtab->sym_start) {
+ 				if (KDB_DEBUG(ARA)) {
+ 					kdb_printf(" matched\n");
+ 				}
+ 				break;		/* jmp to this function */
+ 			}
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" failed");
+ 			}
+ 		} else if (strcmp(caller_symtab.sym_name, "ret_from_intr") == 0
+ 		           && ret == caller_symtab.sym_start) {
+ 			/* ret_from_intr is pushed on stack for interrupts */
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" ret_from_intr matched\n");
+ 			}
+ 			break;		/* special case, hand crafted frame */
+ 		} else if (!assume) {
+ 			/* All following tests cannot validate the target address so they
+ 			 * must assume that the return address is valid.
+ 			 */
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf("\n");
+ 			}
+ 			continue;
+ 		} else if (retaddr(-7) == 0xff && retaddr(-6) == 0x14 && retaddr(-5) == 0x85) {
+ 			/* call *disp32(,%eax,4), used by syscall.
+ 			 * Cannot calculate address, assume it is valid
+ 			 * if the current function name starts with
+ 			 * 'sys_' or 'old_'.
+ 			 */
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" call *0xnnnn(,%%eax,4)");
+ 			}
+ 			if (strncmp(symtab->sym_name, "sys_", 4) == 0 ||
+ 			    strncmp(symtab->sym_name, "old_", 4) == 0) {
+ 				if (KDB_DEBUG(ARA)) {
+ 					kdb_printf(" assume valid\n");
+ 				}
+ 				break;		/* probably call to this function */
+ 			}
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" failed");
+ 			}
+ 		} else if (retaddr(-2) == 0xff &&
+ 			   ((retaddr(-1) & 0xf8) == 0xd0 || (retaddr(-1) & 0xf8) == 0x10)) {
+ 			/* call *%reg.  Cannot validate, have to assume
+ 			 * it is valid.
+ 			 */
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" call *%%reg, assume valid\n");
+ 			}
+ 			break;		/* hope it is a call to this function */
+ 		} else if (retaddr(-3) == 0xff && (retaddr(-2) & 0xf8) == 0x50) {
+ 			/* call *disp8(%reg).  Cannot validate, have to assume
+ 			 * it is valid.
+ 			 */
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" call *disp8(%%reg), assume valid\n");
+ 			}
+ 			break;		/* hope it is a call to this function */
+ 		} else if (retaddr(-6) == 0xff && (retaddr(-5) & 0xf8) == 0x90) {
+ 			/* call *disp32(%reg).  Cannot validate, have to assume
+ 			 * it is valid.
+ 			 */
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" call *disp32(%%reg), assume valid\n");
+ 			}
+ 			break;		/* hope it is a call to this function */
+ 		}
+ 		if (KDB_DEBUG(ARA)) {
+ 			kdb_printf("\n");
+ 		}
+ 	}
+ 	if (KDB_DEBUG(ARA)) {
+ 		kdb_printf("  end ret=0x%lx sp=0x%lx\n", ret, sp);
+ 	}
+ 	if (ret)
+ 		return sp;
+ 	return 0;
+ }
+ 
+ /*
+  * kdba_find_return
+  *
+  *	Given a starting point on the stack and symtab data for the
+  *	current function, scan up the stack looking for a return
+  *	address for this function.
+  * Inputs:
+  *	sp	Starting stack pointer for scan
+  *	ss	Start of stack for current process
+  *	symtab	kallsyms symbol data for the function
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Position on stack of return address, 0 if not found.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	This is sensitive to the calling sequence generated by gcc.
+  */
+ 
+ static kdb_machreg_t
+ kdba_find_return(kdb_machreg_t sp, kdb_machreg_t ss, const kdb_symtab_t *symtab)
+ {
+ 	kdb_machreg_t	ret;
+ 
+ 	if (KDB_DEBUG(ARA)) {
+ 		kdb_printf("  kdba_find_return: start\n");
+ 	}
+ 
+ 	if ((sp & -THREAD_SIZE) != ss) {
+ 		kdb_printf("    sp is in wrong stack 0x%lx 0x%lx 0x%lx\n", sp, ss, sp & -THREAD_SIZE);
+ 		return 0;
+ 	}
+ 
+ 	if ((sp & (THREAD_SIZE - 1)) < sizeof(struct task_struct)) {
+ 		kdb_printf("    sp is inside task_struct\n");
+ 		return 0;
+ 	}
+ 
+ 	if (KDB_DEBUG(ARA)) {
+ 		kdb_printf(" kdba_find_return_1(assume==0)\n");
+ 	}
+ 	if ((ret = kdba_find_return_1(sp, ss, symtab, 0)))
+ 		return ret;
+ 	if (KDB_DEBUG(ARA)) {
+ 		kdb_printf(" kdba_find_return_1(assume==1)\n");
+ 	}
+ 	ret = kdba_find_return_1(sp, ss, symtab, 1);
+ 	return ret;
+ }
+ 
+ /*
+  * kdba_prologue
+  *
+  *	This function analyzes a gcc-generated function prototype
+  *	with or without frame pointers to determine the amount of
+  *	automatic storage and register save storage is used on the
+  *	stack of the target function.  It only counts instructions
+  *	that have been executed up to but excluding the current eip.
+  * Inputs:
+  *	code	Start address of function code to analyze
+  *	pc	Current program counter within function
+  *	sp	Current stack pointer for function
+  *	fp	Current frame pointer for function, may not be valid
+  *	ss	Start of stack for current process.
+  *	caller	1 if looking for data on the caller frame, 0 for callee.
+  * Outputs:
+  *	ar	Activation record, all fields may be set.  fp and oldfp
+  *		are 0 if they cannot be extracted.  return is 0 if the
+  *		code cannot find a valid return address.  args and arg0
+  *		are 0 if the number of arguments cannot be safely
+  *		calculated.
+  * Returns:
+  *	1 if prologue is valid, 0 otherwise.  If pc is 0 treat it as a
+  *	valid prologue to allow bt on wild branches.
+  * Locking:
+  *	None.
+  * Remarks:
+  *
+  *	A prologue for ia32 generally looks like:
+  *
+  *		pushl  %ebp		[All functions, but only if
+  *		movl   %esp, %ebp	 compiled with frame pointers]
+  *		subl   $auto, %esp	[some functions]
+  *		pushl  %reg		[some functions]
+  *		pushl  %reg		[some functions]
+  *
+  *	FIXME: Mike Galbraith says that gcc 2.95 can generate a slightly
+  *	       different prologue.  No support for gcc 2.95 yet.
+  */
+ 
+ int
+ kdba_prologue(const kdb_symtab_t *symtab, kdb_machreg_t pc, kdb_machreg_t sp,
+ 	      kdb_machreg_t fp, kdb_machreg_t ss, int caller, kdb_ar_t *ar)
+ {
+ 	kdb_machreg_t	ret_p, code = symtab->sym_start;
+ 	int		oldfp_present = 0, unwound = 0;
+ 	unsigned char	instruction[6];
+ 
+ 	if (KDB_DEBUG(ARA)) {
+ 		kdb_printf("kdba_prologue: code=0x%lx %s pc=0x%lx sp=0x%lx fp=0x%lx\n",
+ 		code, symtab->sym_name, pc, sp, fp);
+ 	}
+ 
+ 	/* Special case for wild branches.  Assumes top of stack is return address */
+ 	if (pc == 0) {
+ 		memset(ar, 0, sizeof(*ar));
+ 		ar->setup = 4;
+ 		ar->end = sp;
+ 		ar->start = ar->end + 4;
+ 		kdb_getword(&(ar->ret), sp, 4);
+ 		if (KDB_DEBUG(ARA)) {
+ 			kdb_printf("  pc==0: ret=0x%lx\n", ar->ret);
+ 		}
+ 		return(1);
+ 	}
+ 
+ 	if (code == 0 || sp & 3 || ss != (sp & -THREAD_SIZE))
+ 		return(0);
+ 
+ 	ar->end = sp;				/* End of activation record +1 */
+ 
+ 	/* Special cases galore when the caller pc is within entry.S.
+ 	 * The return address for these routines is outside the kernel,
+ 	 * so the normal algorithm to find the frame does not work.
+ 	 * Hand craft the frame to no setup, regs, locals etc, assume 6
+ 	 * parameters.
+ 	 * This list was extracted from entry.S by looking for all call
+ 	 * instructions that were eventually followed by RESTORE_ALL,
+ 	 * take the label before each such instruction.
+ 	 */
+ 	if (caller &&
+ 	    (strcmp(symtab->sym_name, "lcall7") == 0 ||
+ 	     strcmp(symtab->sym_name, "lcall27") == 0 ||
+ 	     strcmp(symtab->sym_name, "kdb_call") == 0 ||
+ 	     strcmp(symtab->sym_name, "system_call") == 0 ||
+ 	     strcmp(symtab->sym_name, "tracesys") == 0 ||
+ 	     strcmp(symtab->sym_name, "signal_return") == 0 ||
+ 	     strcmp(symtab->sym_name, "v86_signal_return") == 0 ||
+ 	     strcmp(symtab->sym_name, "tracesys") == 0 ||
+ 	     strcmp(symtab->sym_name, "tracesys_exit") == 0 ||
+ 	     strcmp(symtab->sym_name, "handle_softirq") == 0 ||
+ 	     strcmp(symtab->sym_name, "reschedule") == 0 ||
+ 	     strcmp(symtab->sym_name, "error_code") == 0 ||
+ 	     strcmp(symtab->sym_name, "device_not_available") == 0 ||
+ 	     strcmp(symtab->sym_name, "nmi") == 0)) {
+ 		ar->start = ar->end + 6*4;	/* 6 parameters */
+ 		if ((ar->start & -THREAD_SIZE) != ss)
+ 			ar->start = 0;
+ 		return(1);
+ 	}
+ 
+ 	ar->setup = 4;	/* Return address is always on stack */
+ 
+ 	/* Kludge.  If we are sitting on 'ret' then the stack has been unwound,
+ 	 * ignore all the startup code.
+ 	 */
+ 	if (kdb_getarea(instruction[0], pc))
+ 		return(0);
+ 	if (instruction[0] == 0xc3) {
+ 		/* ret */
+ 		unwound = 1;
+ 	}
+ 
+ 	if (kdb_getarea(instruction, code))
+ 		return(0);
+ 	if (!unwound && code < pc && instruction[0] == 0x55) {
+ 		/* pushl %ebp */
+ 		ar->setup += 4;	/* Frame pointer is on stack */
+ 		oldfp_present = 1;
+ 		++code;
+ 		if (KDB_DEBUG(ARA)) {
+ 			kdb_printf("  pushl %%ebp\n");
+ 		}
+ 		if (code < pc && instruction[0] == 0x89 && instruction[1] == 0xe5) {
+ 			/* movl %esp,%ebp */
+ 			if (fp >= sp && (fp & -THREAD_SIZE) == ss)
+ 				ar->fp = fp;	/* %ebp has been set */
+ 			code += 2;
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf("  movl %%esp,%%ebp, fp=0x%lx\n", ar->fp);
+ 			}
+ 		}
+ 	}
+ 
+ 	if (!unwound && code < pc) {
+ 		if (instruction[0] == 0x83 && instruction[1] == 0xec) {
+ 			/* subl $xx,%esp */
+ 			kdb_getword(&(ar->locals), (unsigned long)(instruction+2), 1);
+ 			code += 3;
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf("  subl $xx,%%esp, locals=%ld\n", ar->locals);
+ 			}
+ 		} else if (instruction[0] == 0x81 && instruction[1] == 0xec) {
+ 			/* subl $xxxxxxxx,%esp */
+ 			kdb_getword(&(ar->locals), (unsigned long)(instruction+2), 4);
+ 			code += 6;
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf("  subl $xxxxxxxx,%%esp, locals=%ld\n", ar->locals);
+ 			}
+ 		}
+ 	}
+ 
+ 	while (!unwound && code < pc &&
+ 	       kdb_getarea(instruction, code) == 0 &&
+ 	       (instruction[0] & 0xf8) == 0x50) {
+ 		/* pushl %reg */
+ 		ar->regs += 4;
+ 		++code;
+ 		if (KDB_DEBUG(ARA)) {
+ 			kdb_printf("  pushl %%reg, regs=%ld\n", ar->regs);
+ 		}
+ 	}
+ 
+ 	/* Check the return address.  It must point within the kernel
+ 	 * and the code at that location must be a valid entry sequence.
+ 	 */
+ 	if (ar->fp) {
+ 		ret_p = ar->fp + ar->setup;
+ 	}
+ 	else {
+ 		ret_p = ar->end + ar->regs + ar->locals + ar->setup;
+ 	}
+ 	ret_p -= 4;
+ 	if (KDB_DEBUG(ARA)) {
+ 		kdb_printf("  ret_p(0)=0x%lx\n", ret_p);
+ 	}
+ 	ar->ret = 0;
+ 	if ((ret_p & -THREAD_SIZE) == ss &&
+ 	    (ret_p = kdba_find_return(ret_p, ss, symtab))) {
+ 		kdb_getword(&(ar->ret), ret_p, 4);
+ 	}
+ 	if (KDB_DEBUG(ARA)) {
+ 		kdb_printf("  ret_p(1)=0x%lx ret=0x%lx\n", ret_p, ar->ret);
+ 	}
+ 	if (ar->ret) {
+ 		ar->fp = ret_p - ar->setup + 4;	/* "accurate" fp */
+ 		ar->start = ret_p + 4;
+ 		if (KDB_DEBUG(ARA)) {
+ 			kdb_printf("  fp=0x%lx start=0x%lx\n", ar->fp, ar->start);
+ 		}
+ 	}
+ 	if (oldfp_present) {
+ 		if (ar->fp)
+ 			kdb_getword(&(ar->oldfp), ar->fp, 4);
+ 		if (KDB_DEBUG(ARA)) {
+ 			kdb_printf("  oldfp=0x%lx", ar->oldfp);
+ 		}
+ 		if (ar->oldfp <= ar->fp || (ar->oldfp & -THREAD_SIZE) != ss) {
+ 			ar->oldfp = 0;
+ 			if (KDB_DEBUG(ARA)) {
+ 				kdb_printf(" (out of range)");
+ 			}
+ 		}
+ 		if (KDB_DEBUG(ARA)) {
+ 			kdb_printf("\n");
+ 		}
+ 	}
+ 	return(1);
+ }
+ 
+ kdb_machreg_t
+ kdba_getdr6(void)
+ {
+ 	return kdba_getdr(6);
+ }
+ 
+ kdb_machreg_t
+ kdba_getdr7(void)
+ {
+ 	return kdba_getdr(7);
+ }
+ 
+ void
+ kdba_putdr6(kdb_machreg_t contents)
+ {
+ 	kdba_putdr(6, contents);
+ }
+ 
+ static void
+ kdba_putdr7(kdb_machreg_t contents)
+ {
+ 	kdba_putdr(7, contents);
+ }
+ 
+ void
+ kdba_installdbreg(kdb_bp_t *bp)
+ {
+ 	kdb_machreg_t	dr7;
+ 
+ 	dr7 = kdba_getdr7();
+ 
+ 	kdba_putdr(bp->bp_hard->bph_reg, bp->bp_addr);
+ 
+ 	dr7 |= DR7_GE;
+ 	if (cpu_has_de)
+ 		set_in_cr4(X86_CR4_DE);
+ 
+ 	switch (bp->bp_hard->bph_reg){
+ 	case 0:
+ 		DR7_RW0SET(dr7,bp->bp_hard->bph_mode);
+ 		DR7_LEN0SET(dr7,bp->bp_hard->bph_length);
+ 		DR7_G0SET(dr7);
+ 		break;
+ 	case 1:
+ 		DR7_RW1SET(dr7,bp->bp_hard->bph_mode);
+ 		DR7_LEN1SET(dr7,bp->bp_hard->bph_length);
+ 		DR7_G1SET(dr7);
+ 		break;
+ 	case 2:
+ 		DR7_RW2SET(dr7,bp->bp_hard->bph_mode);
+ 		DR7_LEN2SET(dr7,bp->bp_hard->bph_length);
+ 		DR7_G2SET(dr7);
+ 		break;
+ 	case 3:
+ 		DR7_RW3SET(dr7,bp->bp_hard->bph_mode);
+ 		DR7_LEN3SET(dr7,bp->bp_hard->bph_length);
+ 		DR7_G3SET(dr7);
+ 		break;
+ 	default:
+ 		kdb_printf("kdb: Bad debug register!! %ld\n",
+ 			   bp->bp_hard->bph_reg);
+ 		break;
+ 	}
+ 
+ 	kdba_putdr7(dr7);
+ 	return;
+ }
+ 
+ void
+ kdba_removedbreg(kdb_bp_t *bp)
+ {
+ 	int 		regnum;
+ 	kdb_machreg_t	dr7;
+ 
+ 	if (!bp->bp_hard)
+ 		return;
+ 
+ 	regnum = bp->bp_hard->bph_reg;
+ 
+ 	dr7 = kdba_getdr7();
+ 
+ 	kdba_putdr(regnum, 0);
+ 
+ 	switch (regnum) {
+ 	case 0:
+ 		DR7_G0CLR(dr7);
+ 		DR7_L0CLR(dr7);
+ 		break;
+ 	case 1:
+ 		DR7_G1CLR(dr7);
+ 		DR7_L1CLR(dr7);
+ 		break;
+ 	case 2:
+ 		DR7_G2CLR(dr7);
+ 		DR7_L2CLR(dr7);
+ 		break;
+ 	case 3:
+ 		DR7_G3CLR(dr7);
+ 		DR7_L3CLR(dr7);
+ 		break;
+ 	default:
+ 		kdb_printf("kdb: Bad debug register!! %d\n", regnum);
+ 		break;
+ 	}
+ 
+ 	kdba_putdr7(dr7);
+ }
+ 
+ kdb_machreg_t
+ kdba_getdr(int regnum)
+ {
+ 	kdb_machreg_t contents = 0;
+ 	switch(regnum) {
+ 	case 0:
+ 		__asm__ ("movl %%db0,%0\n\t":"=r"(contents));
+ 		break;
+ 	case 1:
+ 		__asm__ ("movl %%db1,%0\n\t":"=r"(contents));
+ 		break;
+ 	case 2:
+ 		__asm__ ("movl %%db2,%0\n\t":"=r"(contents));
+ 		break;
+ 	case 3:
+ 		__asm__ ("movl %%db3,%0\n\t":"=r"(contents));
+ 		break;
+ 	case 4:
+ 	case 5:
+ 		break;
+ 	case 6:
+ 		__asm__ ("movl %%db6,%0\n\t":"=r"(contents));
+ 		break;
+ 	case 7:
+ 		__asm__ ("movl %%db7,%0\n\t":"=r"(contents));
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ 
+ 	return contents;
+ }
+ 
+ 
+ kdb_machreg_t
+ kdb_getcr(int regnum)
+ {
+ 	kdb_machreg_t contents = 0;
+ 	switch(regnum) {
+ 	case 0:
+ 		__asm__ ("movl %%cr0,%0\n\t":"=r"(contents));
+ 		break;
+ 	case 1:
+ 		break;
+ 	case 2:
+ 		__asm__ ("movl %%cr2,%0\n\t":"=r"(contents));
+ 		break;
+ 	case 3:
+ 		__asm__ ("movl %%cr3,%0\n\t":"=r"(contents));
+ 		break;
+ 	case 4:
+ 		__asm__ ("movl %%cr4,%0\n\t":"=r"(contents));
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ 
+ 	return contents;
+ }
+ 
+ void
+ kdba_putdr(int regnum, kdb_machreg_t contents)
+ {
+ 	switch(regnum) {
+ 	case 0:
+ 		__asm__ ("movl %0,%%db0\n\t"::"r"(contents));
+ 		break;
+ 	case 1:
+ 		__asm__ ("movl %0,%%db1\n\t"::"r"(contents));
+ 		break;
+ 	case 2:
+ 		__asm__ ("movl %0,%%db2\n\t"::"r"(contents));
+ 		break;
+ 	case 3:
+ 		__asm__ ("movl %0,%%db3\n\t"::"r"(contents));
+ 		break;
+ 	case 4:
+ 	case 5:
+ 		break;
+ 	case 6:
+ 		__asm__ ("movl %0,%%db6\n\t"::"r"(contents));
+ 		break;
+ 	case 7:
+ 		__asm__ ("movl %0,%%db7\n\t"::"r"(contents));
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ }
+ 
+ /*
+  * kdba_getregcontents
+  *
+  *	Return the contents of the register specified by the
+  *	input string argument.   Return an error if the string
+  *	does not match a machine register.
+  *
+  *	The following pseudo register names are supported:
+  *	   &regs	 - Prints address of exception frame
+  *	   kesp		 - Prints kernel stack pointer at time of fault
+  *	   cesp		 - Prints current kernel stack pointer, inside kdb
+  *	   ceflags	 - Prints current flags, inside kdb
+  *	   %<regname>	 - Uses the value of the registers at the
+  *			   last time the user process entered kernel
+  *			   mode, instead of the registers at the time
+  *			   kdb was entered.
+  *
+  * Parameters:
+  *	regname		Pointer to string naming register
+  *	regs		Pointer to structure containing registers.
+  * Outputs:
+  *	*contents	Pointer to unsigned long to recieve register contents
+  * Returns:
+  *	0		Success
+  *	KDB_BADREG	Invalid register name
+  * Locking:
+  * 	None.
+  * Remarks:
+  * 	If kdb was entered via an interrupt from the kernel itself then
+  *	ss and esp are *not* on the stack.
+  */
+ 
+ static struct kdbregs {
+ 	char   *reg_name;
+ 	size_t	reg_offset;
+ } kdbreglist[] = {
+ 	{ "eax",	offsetof(struct pt_regs, eax) },
+ 	{ "ebx",	offsetof(struct pt_regs, ebx) },
+ 	{ "ecx",	offsetof(struct pt_regs, ecx) },
+ 	{ "edx",	offsetof(struct pt_regs, edx) },
+ 
+ 	{ "esi",	offsetof(struct pt_regs, esi) },
+ 	{ "edi",	offsetof(struct pt_regs, edi) },
+ 	{ "esp",	offsetof(struct pt_regs, esp) },
+ 	{ "eip",	offsetof(struct pt_regs, eip) },
+ 
+ 	{ "ebp",	offsetof(struct pt_regs, ebp) },
+ 	{ "xss", 	offsetof(struct pt_regs, xss) },
+ 	{ "xcs",	offsetof(struct pt_regs, xcs) },
+ 	{ "eflags", 	offsetof(struct pt_regs, eflags) },
+ 
+ 	{ "xds", 	offsetof(struct pt_regs, xds) },
+ 	{ "xes", 	offsetof(struct pt_regs, xes) },
+ 	{ "origeax",	offsetof(struct pt_regs, orig_eax) },
+ 
+ };
+ 
+ static const int nkdbreglist = sizeof(kdbreglist) / sizeof(struct kdbregs);
+ 
+ static struct kdbregs dbreglist[] = {
+ 	{ "dr0", 	0 },
+ 	{ "dr1", 	1 },
+ 	{ "dr2",	2 },
+ 	{ "dr3", 	3 },
+ 	{ "dr6", 	6 },
+ 	{ "dr7",	7 },
+ };
+ 
+ static const int ndbreglist = sizeof(dbreglist) / sizeof(struct kdbregs);
+ 
+ int
+ kdba_getregcontents(const char *regname,
+ 		    struct pt_regs *regs,
+ 		    kdb_machreg_t *contents)
+ {
+ 	int i;
+ 
+ 	if (strcmp(regname, "cesp") == 0) {
+ 		asm volatile("movl %%esp,%0":"=m" (*contents));
+ 		return 0;
+ 	}
+ 
+ 	if (strcmp(regname, "ceflags") == 0) {
+ 		int flags;
+ 		__save_flags(flags);
+ 		*contents = flags;
+ 		return 0;
+ 	}
+ 
+ 	if (regname[0] == '%') {
+ 		/* User registers:  %%e[a-c]x, etc */
+ 		regname++;
+ 		regs = (struct pt_regs *)
+ 			(kdb_current_task->thread.esp0 - sizeof(struct pt_regs));
+ 	}
+ 
+ 	for (i=0; i<ndbreglist; i++) {
+ 		if (strnicmp(dbreglist[i].reg_name,
+ 			     regname,
+ 			     strlen(regname)) == 0)
+ 			break;
+ 	}
+ 
+ 	if ((i < ndbreglist)
+ 	 && (strlen(dbreglist[i].reg_name) == strlen(regname))) {
+ 		*contents = kdba_getdr(dbreglist[i].reg_offset);
+ 		return 0;
+ 	}
+ 
+ 	if (!regs) {
+ 		kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+ 		return KDB_BADREG;
+ 	}
+ 
+ 	if (strcmp(regname, "&regs") == 0) {
+ 		*contents = (unsigned long)regs;
+ 		return 0;
+ 	}
+ 
+ 	if (strcmp(regname, "kesp") == 0) {
+ 		*contents = (unsigned long)regs + sizeof(struct pt_regs);
+ 		if ((regs->xcs & 0xffff) == __KERNEL_CS) {
+ 			/* esp and ss are not on stack */
+ 			*contents -= 2*4;
+ 		}
+ 		return 0;
+ 	}
+ 
+ 	for (i=0; i<nkdbreglist; i++) {
+ 		if (strnicmp(kdbreglist[i].reg_name,
+ 			     regname,
+ 			     strlen(regname)) == 0)
+ 			break;
+ 	}
+ 
+ 	if ((i < nkdbreglist)
+ 	 && (strlen(kdbreglist[i].reg_name) == strlen(regname))) {
+ 		if ((regs->xcs & 0xffff) == __KERNEL_CS) {
+ 			/* No cpl switch, esp and ss are not on stack */
+ 			if (strcmp(kdbreglist[i].reg_name, "esp") == 0) {
+ 				*contents = (kdb_machreg_t)regs +
+ 					sizeof(struct pt_regs) - 2*4;
+ 				return(0);
+ 			}
+ 			if (strcmp(kdbreglist[i].reg_name, "xss") == 0) {
+ 				asm volatile(
+ 					"pushl %%ss\n"
+ 					"popl %0\n"
+ 					:"=m" (*contents));
+ 				return(0);
+ 			}
+ 		}
+ 		*contents = *(unsigned long *)((unsigned long)regs +
+ 				kdbreglist[i].reg_offset);
+ 		return(0);
+ 	}
+ 
+ 	return KDB_BADREG;
+ }
+ 
+ /*
+  * kdba_setregcontents
+  *
+  *	Set the contents of the register specified by the
+  *	input string argument.   Return an error if the string
+  *	does not match a machine register.
+  *
+  *	Supports modification of user-mode registers via
+  *	%<register-name>
+  *
+  * Parameters:
+  *	regname		Pointer to string naming register
+  *	regs		Pointer to structure containing registers.
+  *	contents	Unsigned long containing new register contents
+  * Outputs:
+  * Returns:
+  *	0		Success
+  *	KDB_BADREG	Invalid register name
+  * Locking:
+  * 	None.
+  * Remarks:
+  */
+ 
+ int
+ kdba_setregcontents(const char *regname,
+ 		  struct pt_regs *regs,
+ 		  unsigned long contents)
+ {
+ 	int i;
+ 
+ 	if (regname[0] == '%') {
+ 		regname++;
+ 		regs = (struct pt_regs *)
+ 			(kdb_current_task->thread.esp0 - sizeof(struct pt_regs));
+ 	}
+ 
+ 	for (i=0; i<ndbreglist; i++) {
+ 		if (strnicmp(dbreglist[i].reg_name,
+ 			     regname,
+ 			     strlen(regname)) == 0)
+ 			break;
+ 	}
+ 
+ 	if ((i < ndbreglist)
+ 	 && (strlen(dbreglist[i].reg_name) == strlen(regname))) {
+ 		kdba_putdr(dbreglist[i].reg_offset, contents);
+ 		return 0;
+ 	}
+ 
+ 	if (!regs) {
+ 		kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+ 		return KDB_BADREG;
+ 	}
+ 
+ 	for (i=0; i<nkdbreglist; i++) {
+ 		if (strnicmp(kdbreglist[i].reg_name,
+ 			     regname,
+ 			     strlen(regname)) == 0)
+ 			break;
+ 	}
+ 
+ 	if ((i < nkdbreglist)
+ 	 && (strlen(kdbreglist[i].reg_name) == strlen(regname))) {
+ 		*(unsigned long *)((unsigned long)regs
+ 				   + kdbreglist[i].reg_offset) = contents;
+ 		return 0;
+ 	}
+ 
+ 	return KDB_BADREG;
+ }
+ 
+ /*
+  * kdba_dumpregs
+  *
+  *	Dump the specified register set to the display.
+  *
+  * Parameters:
+  *	regs		Pointer to structure containing registers.
+  *	type		Character string identifying register set to dump
+  *	extra		string further identifying register (optional)
+  * Outputs:
+  * Returns:
+  *	0		Success
+  * Locking:
+  * 	None.
+  * Remarks:
+  *	This function will dump the general register set if the type
+  *	argument is NULL (struct pt_regs).   The alternate register
+  *	set types supported by this function:
+  *
+  *	d 		Debug registers
+  *	c		Control registers
+  *	u		User registers at most recent entry to kernel
+  *			for the process currently selected with "pid" command.
+  * Following not yet implemented:
+  *	m		Model Specific Registers (extra defines register #)
+  *	r		Memory Type Range Registers (extra defines register)
+  */
+ 
+ int
+ kdba_dumpregs(struct pt_regs *regs,
+ 	    const char *type,
+ 	    const char *extra)
+ {
+ 	int i;
+ 	int count = 0;
+ 
+ 	if (type
+ 	 && (type[0] == 'u')) {
+ 		type = NULL;
+ 		regs = (struct pt_regs *)
+ 			(kdb_current_task->thread.esp0 - sizeof(struct pt_regs));
+ 	}
+ 
+ 	if (type == NULL) {
+ 		struct kdbregs *rlp;
+ 		kdb_machreg_t contents;
+ 
+ 		if (!regs) {
+ 			kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+ 			return KDB_BADREG;
+ 		}
+ 
+ 		for (i=0, rlp=kdbreglist; i<nkdbreglist; i++,rlp++) {
+ 			kdb_printf("%s = ", rlp->reg_name);
+ 			kdba_getregcontents(rlp->reg_name, regs, &contents);
+ 			kdb_printf("0x%08lx ", contents);
+ 			if ((++count % 4) == 0)
+ 				kdb_printf("\n");
+ 		}
+ 
+ 		kdb_printf("&regs = 0x%p\n", regs);
+ 
+ 		return 0;
+ 	}
+ 
+ 	switch (type[0]) {
+ 	case 'd':
+ 	{
+ 		unsigned long dr[8];
+ 
+ 		for(i=0; i<8; i++) {
+ 			if ((i == 4) || (i == 5)) continue;
+ 			dr[i] = kdba_getdr(i);
+ 		}
+ 		kdb_printf("dr0 = 0x%08lx  dr1 = 0x%08lx  dr2 = 0x%08lx  dr3 = 0x%08lx\n",
+ 			   dr[0], dr[1], dr[2], dr[3]);
+ 		kdb_printf("dr6 = 0x%08lx  dr7 = 0x%08lx\n",
+ 			   dr[6], dr[7]);
+ 		return 0;
+ 	}
+ 	case 'c':
+ 	{
+ 		unsigned long cr[5];
+ 
+ 		for (i=0; i<5; i++) {
+ 			cr[i] = kdb_getcr(i);
+ 		}
+ 		kdb_printf("cr0 = 0x%08lx  cr1 = 0x%08lx  cr2 = 0x%08lx  cr3 = 0x%08lx\ncr4 = 0x%08lx\n",
+ 			   cr[0], cr[1], cr[2], cr[3], cr[4]);
+ 		return 0;
+ 	}
+ 	case 'm':
+ 		break;
+ 	case 'r':
+ 		break;
+ 	default:
+ 		return KDB_BADREG;
+ 	}
+ 
+ 	/* NOTREACHED */
+ 	return 0;
+ }
+ 
+ kdb_machreg_t
+ kdba_getpc(struct pt_regs *regs)
+ {
+ 	return regs ? regs->eip : 0;
+ }
+ 
+ int
+ kdba_setpc(struct pt_regs *regs, kdb_machreg_t newpc)
+ {
+ 	if (KDB_NULL_REGS(regs))
+ 		return KDB_BADREG;
+ 	regs->eip = newpc;
+ 	KDB_STATE_SET(IP_ADJUSTED);
+ 	return 0;
+ }
+ 
+ /*
+  * kdba_main_loop
+  *
+  *	Do any architecture specific set up before entering the main kdb loop.
+  *	The primary function of this routine is to make all processes look the
+  *	same to kdb, kdb must be able to list a process without worrying if the
+  *	process is running or blocked, so make all process look as though they
+  *	are blocked.
+  *
+  * Inputs:
+  *	reason		The reason KDB was invoked
+  *	error		The hardware-defined error code
+  *	error2		kdb's current reason code.  Initially error but can change
+  *			acording to kdb state.
+  *	db_result	Result from break or debug point.
+  *	regs		The exception frame at time of fault/breakpoint.  If reason
+  *			is KDB_REASON_SILENT then regs is NULL, otherwise it should
+  *			always be valid.
+  * Returns:
+  *	0	KDB was invoked for an event which it wasn't responsible
+  *	1	KDB handled the event for which it was invoked.
+  * Outputs:
+  *	Sets eip and esp in current->thread.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	none.
+  */
+ 
+ int
+ kdba_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
+ 	       kdb_dbtrap_t db_result, struct pt_regs *regs)
+ {
+ 	int ret;
+ 	kdb_save_running(regs);
+ 	ret = kdb_main_loop(reason, reason2, error, db_result, regs);
+ 	kdb_unsave_running(regs);
+ 	return ret;
+ }
+ 
+ void
+ kdba_disableint(kdb_intstate_t *state)
+ {
+ 	int *fp = (int *)state;
+ 	int   flags;
+ 
+ 	__save_flags(flags);
+ 	__cli();
+ 
+ 	*fp = flags;
+ }
+ 
+ void
+ kdba_restoreint(kdb_intstate_t *state)
+ {
+ 	int flags = *(int *)state;
+ 	__restore_flags(flags);
+ }
+ 
+ void
+ kdba_setsinglestep(struct pt_regs *regs)
+ {
+ 	if (KDB_NULL_REGS(regs))
+ 		return;
+ 	if (regs->eflags & EF_IE)
+ 		KDB_STATE_SET(A_IF);
+ 	else
+ 		KDB_STATE_CLEAR(A_IF);
+ 	regs->eflags = (regs->eflags | EF_TF) & ~EF_IE;
+ }
+ 
+ void
+ kdba_clearsinglestep(struct pt_regs *regs)
+ {
+ 	if (KDB_NULL_REGS(regs))
+ 		return;
+ 	if (KDB_STATE(A_IF))
+ 		regs->eflags |= EF_IE;
+ 	else
+ 		regs->eflags &= ~EF_IE;
+ }
+ 
+ #ifdef KDB_HAVE_LONGJMP
+ int
+ kdba_setjmp(kdb_jmp_buf *jb)
+ {
+ #if defined(CONFIG_FRAME_POINTER)
+ 	__asm__ ("movl 8(%esp), %eax\n\t"
+ 		 "movl %ebx, 0(%eax)\n\t"
+ 		 "movl %esi, 4(%eax)\n\t"
+ 		 "movl %edi, 8(%eax)\n\t"
+ 		 "movl (%esp), %ecx\n\t"
+ 		 "movl %ecx, 12(%eax)\n\t"
+ 		 "leal 8(%esp), %ecx\n\t"
+ 		 "movl %ecx, 16(%eax)\n\t"
+ 		 "movl 4(%esp), %ecx\n\t"
+ 		 "movl %ecx, 20(%eax)\n\t");
+ #else	 /* CONFIG_FRAME_POINTER */
+ 	__asm__ ("movl 4(%esp), %eax\n\t"
+ 		 "movl %ebx, 0(%eax)\n\t"
+ 		 "movl %esi, 4(%eax)\n\t"
+ 		 "movl %edi, 8(%eax)\n\t"
+ 		 "movl %ebp, 12(%eax)\n\t"
+ 		 "leal 4(%esp), %ecx\n\t"
+ 		 "movl %ecx, 16(%eax)\n\t"
+ 		 "movl 0(%esp), %ecx\n\t"
+ 		 "movl %ecx, 20(%eax)\n\t");
+ #endif   /* CONFIG_FRAME_POINTER */
+ 	KDB_STATE_SET(LONGJMP);
+ 	return 0;
+ }
+ 
+ void
+ kdba_longjmp(kdb_jmp_buf *jb, int reason)
+ {
+ #if defined(CONFIG_FRAME_POINTER)
+ 	__asm__("movl 8(%esp), %ecx\n\t"
+ 		"movl 12(%esp), %eax\n\t"
+ 		"movl 20(%ecx), %edx\n\t"
+ 		"movl 0(%ecx), %ebx\n\t"
+ 		"movl 4(%ecx), %esi\n\t"
+ 		"movl 8(%ecx), %edi\n\t"
+ 		"movl 12(%ecx), %ebp\n\t"
+ 		"movl 16(%ecx), %esp\n\t"
+ 		"jmp *%edx\n");
+ #else    /* CONFIG_FRAME_POINTER */
+ 	__asm__("movl 4(%esp), %ecx\n\t"
+ 		"movl 8(%esp), %eax\n\t"
+ 		"movl 20(%ecx), %edx\n\t"
+ 		"movl 0(%ecx), %ebx\n\t"
+ 		"movl 4(%ecx), %esi\n\t"
+ 		"movl 8(%ecx), %edi\n\t"
+ 		"movl 12(%ecx), %ebp\n\t"
+ 		"movl 16(%ecx), %esp\n\t"
+ 		"jmp *%edx\n");
+ #endif	 /* CONFIG_FRAME_POINTER */
+ }
+ #endif	/* KDB_HAVE_LONGJMP */
+ 
+ 
+ /*
+  * kdba_enable_mce
+  *
+  *	This function is called once on each CPU to enable machine
+  *	check exception handling.
+  *
+  * Inputs:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  *
+  */
+ 
+ void
+ kdba_enable_mce(void)
+ {
+ 	/* No longer required, arch/i386/kernel/bluesmoke.c does the job now */
+ }
+ 
+ /*
+  * kdba_enable_lbr
+  *
+  *	Enable last branch recording.
+  *
+  * Parameters:
+  *	None.
+  * Returns:
+  *	None
+  * Locking:
+  *	None
+  * Remarks:
+  *	None.
+  */
+ 
+ static unsigned char lbr_warned;
+ 
+ void
+ kdba_enable_lbr(void)
+ {
+ 	u32  lv, hv;
+ 
+ 	if (!test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability)) {
+ 		if (lbr_warned) {
+ 			kdb_printf("kdb: machine does not support last branch recording\n");
+ 			lbr_warned = 1;
+ 		}
+ 		return;
+ 	}
+ 	rdmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+ 	lv |= 0x1;	/* Set LBR enable */
+ 	wrmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+ }
+ 
+ /*
+  * kdba_disable_lbr
+  *
+  *	disable last branch recording.
+  *
+  * Parameters:
+  *	None.
+  * Returns:
+  *	None
+  * Locking:
+  *	None
+  * Remarks:
+  *	None.
+  */
+ 
+ void
+ kdba_disable_lbr(void)
+ {
+ 	u32  lv, hv;
+ 
+ 	if (!test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability)) {
+ 		if (lbr_warned) {
+ 			kdb_printf("kdb: machine does not support last branch recording\n");
+ 			lbr_warned = 1;
+ 		}
+ 		return;
+ 	}
+ 	rdmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+ 	lv &= ~0x1;	/* Set LBR disable */
+ 	wrmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+ }
+ 
+ /*
+  * kdba_print_lbr
+  *
+  *	Print last branch and last exception addresses
+  *
+  * Parameters:
+  *	None.
+  * Returns:
+  *	None
+  * Locking:
+  *	None
+  * Remarks:
+  *	None.
+  */
+ 
+ void
+ kdba_print_lbr(void)
+ {
+ 	u32  from, to, dummy;
+ 
+ 	if (!test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability))
+ 		return;
+ 
+ 	rdmsr(MSR_IA32_LASTBRANCHFROMIP, from, dummy);
+ 	rdmsr(MSR_IA32_LASTBRANCHTOIP, to, dummy);
+ 	kdb_printf("Last Branch IP, from: ");
+ 	kdb_symbol_print(from, NULL, KDB_SP_DEFAULT);
+ 	kdb_printf(" to: ");
+ 	kdb_symbol_print(to, NULL, KDB_SP_DEFAULT);
+ 	kdb_printf("\n");
+ 	rdmsr(MSR_IA32_LASTINTFROMIP, from, dummy);
+ 	rdmsr(MSR_IA32_LASTINTTOIP, to, dummy);
+ 	kdb_printf("Last Int IP, from: ");
+ 	kdb_symbol_print(from, NULL, KDB_SP_DEFAULT);
+ 	kdb_printf(" to: ");
+ 	kdb_symbol_print(to, NULL, KDB_SP_DEFAULT);
+ 	kdb_printf("\n");
+ }
+ 
+ /*
+  * kdba_pt_regs
+  *
+  *	Format a struct pt_regs
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	If no address is supplied, it uses regs.
+  */
+ 
+ static int
+ kdba_pt_regs(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int diag;
+ 	kdb_machreg_t addr;
+ 	long offset = 0;
+ 	int nextarg;
+ 	struct pt_regs *p;
+ 	static const char *fmt = "  %-11.11s 0x%lx\n";
+ 
+ 	if (argc == 0) {
+ 		addr = (kdb_machreg_t) regs;
+ 	} else if (argc == 1) {
+ 		nextarg = 1;
+ 		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+ 		if (diag)
+ 			return diag;
+ 	} else {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 
+ 	p = (struct pt_regs *) addr;
+ 	kdb_printf("struct pt_regs %p-%p\n", p, (unsigned char *)p + sizeof(*p) - 1);
+ 	kdb_print_nameval("ebx", p->ebx);
+ 	kdb_print_nameval("ecx", p->ecx);
+ 	kdb_print_nameval("edx", p->edx);
+ 	kdb_print_nameval("esi", p->esi);
+ 	kdb_print_nameval("edi", p->edi);
+ 	kdb_print_nameval("ebp", p->ebp);
+ 	kdb_print_nameval("eax", p->eax);
+ 	kdb_printf(fmt, "xds", p->xds);
+ 	kdb_printf(fmt, "xes", p->xes);
+ 	kdb_print_nameval("orig_eax", p->orig_eax);
+ 	kdb_print_nameval("eip", p->eip);
+ 	kdb_printf(fmt, "xcs", p->xcs);
+ 	kdb_printf(fmt, "eflags", p->eflags);
+ 	kdb_printf(fmt, "esp", p->esp);
+ 	kdb_printf(fmt, "xss", p->xss);
+ 	return 0;
+ }
+ 
+ /*
+  * kdba_init
+  *
+  * 	Architecture specific initialization.
+  *
+  * Parameters:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	None.
+  */
+ 
+ void __init
+ kdba_init(void)
+ {
+ 	kdba_enable_lbr();
+ 	kdb_register("pt_regs", kdba_pt_regs, "address", "Format struct pt_regs", 0);
+ 
+ 	return;
+ }
+ 
+ /*
+  * kdba_adjust_ip
+  *
+  * 	Architecture specific adjustment of instruction pointer before leaving
+  *	kdb.
+  *
+  * Parameters:
+  *	reason		The reason KDB was invoked
+  *	error		The hardware-defined error code
+  *	regs		The exception frame at time of fault/breakpoint.  If reason
+  *			is KDB_REASON_SILENT then regs is NULL, otherwise it should
+  *			always be valid.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	noop on ix86.
+  */
+ 
+ void
+ kdba_adjust_ip(kdb_reason_t reason, int error, struct pt_regs *regs)
+ {
+ 	return;
+ }
diff -c -r -N console-os/arch/i386/kdb/Makefile console-os-kdb/arch/i386/kdb/Makefile
*** console-os/arch/i386/kdb/Makefile	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/arch/i386/kdb/Makefile	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,40 ----
+ #
+ # Copyright (c) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ #
+ # This program is free software; you can redistribute it and/or modify it
+ # under the terms of version 2 of the GNU General Public License as
+ # published by the Free Software Foundation.
+ #
+ # This program is distributed in the hope that it would be useful, but
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ #
+ # Further, this software is distributed without any warranty that it is
+ # free of the rightful claim of any third person regarding infringement
+ # or the like.  Any license provided herein, whether implied or
+ # otherwise, applies only to this software file.  Patent licenses, if
+ # any, provided herein do not apply to combinations of this program with
+ # other software, or any other product whatsoever.
+ #
+ # You should have received a copy of the GNU General Public License along
+ # with this program; if not, write the Free Software Foundation, Inc., 59
+ # Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ #
+ # Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ # Mountain View, CA  94043, or:
+ #
+ # http://www.sgi.com
+ #
+ # For further information regarding this notice, see:
+ #
+ # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ #
+ 
+ O_TARGET	:= kdba.o
+ obj-y		:= kdba_bt.o kdba_bp.o kdba_id.o kdba_io.o kdbasupport.o i386-dis.o
+ 
+ override CFLAGS := $(CFLAGS:%-pg=% )
+ 
+ EXTRA_CFLAGS += -I $(TOPDIR)/arch/$(ARCH)/kdb
+ 
+ include $(TOPDIR)/Rules.make
diff -c -r -N console-os/arch/i386/kernel/bluesmoke.c console-os-kdb/arch/i386/kernel/bluesmoke.c
*** console-os/arch/i386/kernel/bluesmoke.c	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/kernel/bluesmoke.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 4,9 ****
--- 4,12 ----
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/config.h>
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif	/* CONFIG_KDB */
  #include <asm/processor.h> 
  #include <asm/msr.h>
  
***************
*** 109,114 ****
--- 112,120 ----
  asmlinkage void do_machine_check(struct pt_regs * regs, long error_code)
  {
  	machine_check_vector(regs, error_code);
+ #ifdef	CONFIG_KDB
+ 	(void)kdb(KDB_REASON_NMI, error_code, regs);
+ #endif	/* CONFIG_KDB */
  }
  
  /*
diff -c -r -N console-os/arch/i386/kernel/entry.S console-os-kdb/arch/i386/kernel/entry.S
*** console-os/arch/i386/kernel/entry.S	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/kernel/entry.S	2007-01-10 14:02:18.000000000 -0800
***************
*** 296,301 ****
--- 296,313 ----
  
  #endif
  
+ #if defined(CONFIG_KDB)
+ ENTRY(kdb_call)
+ 	pushl %eax              # save orig EAX
+ 	SAVE_ALL
+ 	pushl %esp              # struct pt_regs
+ 	pushl $0                # error_code
+ 	pushl $7                # KDB_REASON_ENTRY
+ 	call  SYMBOL_NAME(kdb)
+ 	addl  $12,%esp          # remove args
+ 	RESTORE_ALL
+ #endif
+ 
  /*
   * Return to user mode is not as complex as all this looks,
   * but we want the default path for a system call return to
***************
*** 536,541 ****
--- 548,569 ----
  	pushl $ SYMBOL_NAME(do_alignment_check)
  	jmp error_code
  
+ #if defined(CONFIG_KDB)
+ ENTRY(page_fault_mca)
+ 	pushl %ecx
+ 	pushl %edx
+ 	pushl %eax
+ 	movl  $473,%ecx
+ 	rdmsr
+ 	andl  $0xfffffffe,%eax		/* Disable last branch recording */
+ 	wrmsr
+ 	popl  %eax
+ 	popl  %edx
+ 	popl  %ecx
+ 	pushl $ SYMBOL_NAME(do_page_fault)
+ 	jmp error_code
+ #endif
+ 
  ENTRY(page_fault)
  	pushl $ SYMBOL_NAME(do_page_fault)
  	jmp error_code
diff -c -r -N console-os/arch/i386/kernel/i8259.c console-os-kdb/arch/i386/kernel/i8259.c
*** console-os/arch/i386/kernel/i8259.c	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/kernel/i8259.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 456,462 ****
  	 */
  	for (i = 0; i < NR_IRQS; i++) {
  		int vector = FIRST_EXTERNAL_VECTOR + i;
! 		if (vector != SYSCALL_VECTOR) 
  			set_intr_gate(vector, interrupt[i]);
  	}
  
--- 456,466 ----
  	 */
  	for (i = 0; i < NR_IRQS; i++) {
  		int vector = FIRST_EXTERNAL_VECTOR + i;
! 		if ((vector != SYSCALL_VECTOR) 
! #if defined(CONFIG_KDB)
! 		 && (vector != KDBENTER_VECTOR)
! #endif
! 						)
  			set_intr_gate(vector, interrupt[i]);
  	}
  
diff -c -r -N console-os/arch/i386/kernel/io_apic.c console-os-kdb/arch/i386/kernel/io_apic.c
*** console-os/arch/i386/kernel/io_apic.c	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/kernel/io_apic.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 26,31 ****
--- 26,34 ----
  #include <linux/delay.h>
  #include <linux/sched.h>
  #include <linux/config.h>
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif	/* CONFIG_KDB */
  #include <linux/smp_lock.h>
  #include <linux/mc146818rtc.h>
  
***************
*** 673,678 ****
--- 676,685 ----
  	current_vector += 8;
  	if (current_vector == SYSCALL_VECTOR)
  		goto next;
+ #ifdef	CONFIG_KDB
+ 	if (current_vector == KDBENTER_VECTOR)
+ 		goto next;
+ #endif	/* CONFIG_KDB */
  
  	if (current_vector > FIRST_SYSTEM_VECTOR) {
  		offset++;
diff -c -r -N console-os/arch/i386/kernel/irq.c console-os-kdb/arch/i386/kernel/irq.c
*** console-os/arch/i386/kernel/irq.c	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/kernel/irq.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 32,37 ****
--- 32,40 ----
  #include <linux/kernel_stat.h>
  #include <linux/irq.h>
  #include <linux/proc_fs.h>
+ #ifdef CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif /* CONFIG_KDB */
  #include <linux/seq_file.h>
  #include <linux/process_timing.h>
  
***************
*** 317,322 ****
--- 320,330 ----
  
  static inline void get_irqlock(int cpu)
  {
+ #ifdef	CONFIG_KDB
+ 	static int kdb_rate;
+ 	if (KDB_IS_RUNNING() && kdb_rate++ < 10)
+ 		kdb_printf("Warning: get_irqlock on cpu %d while kdb is running, may hang\n", smp_processor_id());
+ #endif	/* CONFIG_KDB */
  	if (test_and_set_bit(0,&global_irq_lock)) {
  		/* do we already hold the lock? */
  		if ((unsigned char) cpu == global_irq_holder)
diff -c -r -N console-os/arch/i386/kernel/nmi.c console-os-kdb/arch/i386/kernel/nmi.c
*** console-os/arch/i386/kernel/nmi.c	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/kernel/nmi.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 20,25 ****
--- 20,28 ----
  #include <linux/interrupt.h>
  #include <linux/mc146818rtc.h>
  #include <linux/kernel_stat.h>
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif	/* CONFIG_KDB */
  
  #include <asm/smp.h>
  #include <asm/mtrr.h>
diff -c -r -N console-os/arch/i386/kernel/process.c console-os-kdb/arch/i386/kernel/process.c
*** console-os/arch/i386/kernel/process.c	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/kernel/process.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 34,39 ****
--- 34,42 ----
  #include <linux/reboot.h>
  #include <linux/init.h>
  #include <linux/mc146818rtc.h>
+ #ifdef CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif /* CONFIG_KDB */
  #include <linux/mman.h>
  #include <linux/random.h>
  #include <linux/elfcore.h>
***************
*** 413,418 ****
--- 416,430 ----
  		for (;;)
  		__asm__ __volatile__ ("hlt");
  	}
+ #ifdef CONFIG_KDB
+ 	/*
+ 	 * If this restart is occuring while kdb is running (e.g. reboot
+ 	 * command), the other CPU's are already stopped.  Don't try to
+ 	 * stop them yet again.
+ 	 */
+       if (!KDB_IS_RUNNING())
+ #endif /* CONFIG_KDB */
+ 
  	/*
  	 * Stop all CPUs and turn off local APICs and the IO-APIC, so
  	 * other OSs see a clean IRQ state.
diff -c -r -N console-os/arch/i386/kernel/smpboot.c console-os-kdb/arch/i386/kernel/smpboot.c
*** console-os/arch/i386/kernel/smpboot.c	2007-01-09 11:50:02.000000000 -0800
--- console-os-kdb/arch/i386/kernel/smpboot.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 41,46 ****
--- 41,49 ----
  #include <linux/smp_lock.h>
  #include <linux/irq.h>
  #include <linux/bootmem.h>
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif	/* CONFIG_KDB */
  
  #include <linux/delay.h>
  #include <linux/mc146818rtc.h>
***************
*** 433,438 ****
--- 436,446 ----
  	calibrate_delay();
  	Dprintk("Stack at about %p\n",&cpuid);
  
+ #ifdef	CONFIG_KDB
+ 	/* Activate any preset global breakpoints on this cpu */
+ 	kdb(KDB_REASON_SILENT, 0, 0);
+ #endif	/* CONFIG_KDB */
+ 
  	/*
  	 * Save our processor parameters
  	 */
diff -c -r -N console-os/arch/i386/kernel/smp.c console-os-kdb/arch/i386/kernel/smp.c
*** console-os/arch/i386/kernel/smp.c	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/kernel/smp.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 24,29 ****
--- 24,34 ----
  #include <asm/smpboot.h>
  #include <asm/apic.h>
  
+ #include <linux/config.h>
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif	/* CONFIG_KDB */
+ 
  /*
   *	Some notes on x86 processor bugs affecting SMP operation:
   *
***************
*** 149,154 ****
--- 154,168 ----
  	 */
  	cfg = __prepare_ICR(shortcut, vector);
  
+ #ifdef	CONFIG_KDB
+ 	if (vector == KDB_VECTOR) {
+ 		/*
+ 		 * Setup KDB IPI to be delivered as an NMI
+ 		 */
+ 		cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+ 	}
+ #endif	/* CONFIG_KDB */
+ 
  	/*
  	 * Send the IPI. The write to APIC_ICR fires this off.
  	 */
***************
*** 230,235 ****
--- 244,258 ----
  			 * program the ICR 
  			 */
  			cfg = __prepare_ICR(0, vector);
+ 
+ #ifdef	CONFIG_KDB
+ 			if (vector == KDB_VECTOR) {
+ 				/*
+ 				 * Setup KDB IPI to be delivered as an NMI
+ 				 */
+ 				cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+ 			}
+ #endif	/* CONFIG_KDB */
  			
  			/*
  			 * Send the IPI. The write to APIC_ICR fires this off.
***************
*** 492,497 ****
--- 515,529 ----
  	do_flush_tlb_all_local();
  }
  
+ #ifdef	CONFIG_KDB
+ void
+ smp_kdb_stop(void)
+ {
+ 	if (!KDB_FLAG(NOIPI))
+ 		send_IPI_allbutself(KDB_VECTOR);
+ }
+ #endif	/* CONFIG_KDB */
+ 
  /*
   * this function sends a 'reschedule' IPI to another CPU.
   * it goes straight through and wastes no time serializing
diff -c -r -N console-os/arch/i386/kernel/traps.c console-os-kdb/arch/i386/kernel/traps.c
*** console-os/arch/i386/kernel/traps.c	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/kernel/traps.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 31,36 ****
--- 31,40 ----
  #include <asm/processor.h>
  #endif
  
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif	/* CONFIG_KDB */
+ 
  #include <asm/system.h>
  #include <asm/uaccess.h>
  #include <asm/io.h>
***************
*** 53,58 ****
--- 57,65 ----
  #include <linux/module.h>
  
  asmlinkage int system_call(void);
+ #ifdef	CONFIG_KDB
+ asmlinkage int kdb_call(void);
+ #endif	/* CONFIG_KDB */
  asmlinkage void lcall7(void);
  asmlinkage void lcall27(void);
  
***************
*** 81,86 ****
--- 88,96 ----
  asmlinkage void stack_segment(void);
  asmlinkage void general_protection(void);
  asmlinkage void page_fault(void);
+ #ifdef	CONFIG_KDB
+ asmlinkage void page_fault_mca(void);
+ #endif	/* CONFIG_KDB */
  asmlinkage void coprocessor_error(void);
  asmlinkage void simd_coprocessor_error(void);
  asmlinkage void alignment_check(void);
***************
*** 180,186 ****
--- 190,202 ----
  #if CONFIG_FRAME_POINTER
          show_trace_ebp(ebp, buffer, 512);
          printk("\nCall Trace(2):  ");
+ #if CONFIG_KALLSYMS
+ 	printk("\n");
+ #endif
  #else
+ #if CONFIG_KALLSYMS
+ 	printk("\n");
+ #endif
  	i = 1;
  #endif
  
***************
*** 190,196 ****
  		if (kernel_text_address(addr)) {
  			lookup_symbol(addr, buffer, 512);
  			printk("[<%08lx>] %s (0x%p)\n", addr,buffer,stack-1);
- 			i++;
  		}
  	}
  	printk("\n");
--- 206,211 ----
***************
*** 460,465 ****
--- 475,484 ----
  	bust_spinlocks(0);
  	die_owner = -1;
  	spin_unlock_irq(&die_lock);
+ #ifdef	CONFIG_KDB
+ 	kdb_diemsg = str;
+ 	kdb(KDB_REASON_OOPS, err, regs);
+ #endif	/* CONFIG_KDB */
  	do_exit(SIGSEGV);
  }
  
***************
*** 553,559 ****
--- 572,580 ----
  }
  
  DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->eip)
+ #ifndef	CONFIG_KDB
  DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
+ #endif	/* !CONFIG_KDB */
  DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
  DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
  DO_ERROR_INFO( 6, SIGILL,  "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
***************
*** 675,680 ****
--- 696,704 ----
  		return;
  	}
  #endif
+ #ifdef CONFIG_KDB
+ 	(void)kdb(KDB_REASON_NMI, reason, regs);
+ #endif /* CONFIG_KDB */
  	printk("NMI received for unknown reason %02x on CPU %d.\n",
  		reason, smp_processor_id());
  	printk("Do you have a strange power saving mode enabled?\n");
***************
*** 753,758 ****
--- 777,790 ----
  	return 0;
  }
   
+ #if defined(CONFIG_SMP) && defined(CONFIG_KDB)
+ static void
+ do_ack_apic_irq(void)
+ {
+ 	ack_APIC_irq();
+ }
+ #endif /* defined(CONFIG_SMP) && defined(CONFIG_KDB) */
+ 
  static nmi_callback_t nmi_callback = dummy_nmi_callback;
   
  asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
***************
*** 760,765 ****
--- 792,806 ----
  	int cpu = smp_processor_id();
  
  	++nmi_count(cpu);
+ #if defined(CONFIG_SMP) && defined(CONFIG_KDB)
+ 	/*
+ 	 * Call the kernel debugger to see if this NMI is due
+ 	 * to an KDB requested IPI.  If so, kdb will handle it.
+ 	 */
+ 	if (kdb_ipi(regs, do_ack_apic_irq)) {
+ 		return;
+ 	}
+ #endif        /* defined(CONFIG_SMP) && defined(CONFIG_KDB) */
  
  	if (!nmi_callback(regs, cpu))
  		default_do_nmi(regs);
***************
*** 806,811 ****
--- 847,857 ----
  
  	__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
  
+ #ifdef	CONFIG_KDB
+ 	if (kdb(KDB_REASON_DEBUG, error_code, regs))
+ 		return;
+ #endif	/* CONFIG_KDB */
+ 
  	/* If the user set TF, it's simplest to clear it right away. */
  	if ((eip >= PAGE_OFFSET_USER) && (regs->eflags & TF_MASK))
  		goto clear_TF;
***************
*** 874,879 ****
--- 920,935 ----
  	return;
  }
  
+ #ifdef	CONFIG_KDB
+ asmlinkage void do_int3(struct pt_regs * regs, long error_code)
+ {
+ 	if (kdb(KDB_REASON_BREAK, error_code, regs))
+ 		return;
+ 	do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
+ }
+ #endif	/* CONFIG_KDB */
+ 
+ 
  /*
   * Note that we play around with the 'TS' bit in an attempt to get
   * the correct behaviour even in the presence of the asynchronous
***************
*** 1264,1270 ****
--- 1320,1336 ----
  	set_trap_gate(11,&segment_not_present);
  	set_trap_gate(12,&stack_segment);
  	set_trap_gate(13,&general_protection);
+ #ifdef	CONFIG_KDB
+ 	if (test_bit(X86_FEATURE_MCE, boot_cpu_data.x86_capability) &&
+ 	    test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability)) {
+ 		set_intr_gate(14,&page_fault_mca);
+ 	}
+ 	else {
+ 		set_intr_gate(14,&page_fault);
+ 	}
+ #else	/* !CONFIG_KDB */
  	set_intr_gate(14,&page_fault);
+ #endif	/* CONFIG_KDB */
  	set_trap_gate(15,&spurious_interrupt_bug);
  	set_trap_gate(16,&coprocessor_error);
  	set_trap_gate(17,&alignment_check);
***************
*** 1273,1278 ****
--- 1339,1355 ----
  
  	set_system_gate(SYSCALL_VECTOR,&system_call);
  	set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
+ #ifdef CONFIG_KDB
+ 	{
+ 		set_trap_gate(18, &machine_check);
+ 	}
+ 	kdb_enablehwfault();
+ 	/*
+ 	 * A trap gate, used by the kernel to enter the 
+ 	 * debugger, preserving all registers.
+ 	 */
+ 	set_trap_gate(KDBENTER_VECTOR, &kdb_call);
+ #endif /* CONFIG_KDB */
  
  	/*
  	 * Should be a barrier for any external CPU state.
diff -c -r -N console-os/arch/i386/Makefile console-os-kdb/arch/i386/Makefile
*** console-os/arch/i386/Makefile	2006-11-20 12:22:44.000000000 -0800
--- console-os-kdb/arch/i386/Makefile	2007-01-10 14:02:18.000000000 -0800
***************
*** 102,107 ****
--- 102,113 ----
  CORE_FILES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o $(CORE_FILES)
  LIBS := $(TOPDIR)/arch/i386/lib/lib.a $(LIBS) $(TOPDIR)/arch/i386/lib/lib.a
  
+ ifdef CONFIG_KDB
+ LIBS := $(LIBS) $(TOPDIR)/arch/i386/kdb/kdba.o
+ SUBDIRS := $(SUBDIRS) arch/i386/kdb
+ CFLAGS += $(call check_gcc,-fno-optimize-sibling-calls,)
+ endif
+ 
  ifdef CONFIG_MATH_EMULATION
  SUBDIRS += arch/i386/math-emu
  DRIVERS += arch/i386/math-emu/math.o
***************
*** 121,126 ****
--- 127,137 ----
  arch/i386/mm: dummy
  	$(MAKE) linuxsubdirs SUBDIRS=arch/i386/mm
  
+ ifdef CONFIG_KDB
+ arch/i386/kdb: dummy
+ 	$(MAKE) linuxsubdirs SUBDIRS=arch/i386/kdb
+ endif
+ 
  MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
  
  vmlinux: arch/i386/vmlinux.lds
diff -c -r -N console-os/arch/i386/vmlinux.lds.in console-os-kdb/arch/i386/vmlinux.lds.in
*** console-os/arch/i386/vmlinux.lds.in	2006-11-20 12:22:46.000000000 -0800
--- console-os-kdb/arch/i386/vmlinux.lds.in	2007-01-10 14:02:18.000000000 -0800
***************
*** 67,72 ****
--- 67,75 ----
    __setup_start = .;
    .setup.init : { *(.setup.init) }
    __setup_end = .;
+   __kdb_initcall_start = .;
+   .kdb_initcall.init : { *(.kdb_initcall.init) }
+   __kdb_initcall_end = .;
    __initcall_start = .;
    .initcall.init : { *(.initcall.init) }
    __initcall_end = .;
diff -c -r -N console-os/configs/kernel-2.4.21-i386-BOOT.config console-os-kdb/configs/kernel-2.4.21-i386-BOOT.config
*** console-os/configs/kernel-2.4.21-i386-BOOT.config	2006-12-22 15:12:20.000000000 -0800
--- console-os-kdb/configs/kernel-2.4.21-i386-BOOT.config	2007-01-10 14:02:18.000000000 -0800
***************
*** 1118,1123 ****
--- 1118,1124 ----
  # CONFIG_PANIC_MORSE is not set
  # CONFIG_DEBUG_SPINLOCK is not set
  CONFIG_SMALL=y
+ # CONFIG_KDB is not set
  
  #
  # Cryptographic options
diff -c -r -N console-os/configs/kernel-2.4.21-i386.config console-os-kdb/configs/kernel-2.4.21-i386.config
*** console-os/configs/kernel-2.4.21-i386.config	2006-12-22 15:12:20.000000000 -0800
--- console-os-kdb/configs/kernel-2.4.21-i386.config	2007-01-10 14:02:18.000000000 -0800
***************
*** 2157,2162 ****
--- 2157,2163 ----
  CONFIG_DISKDUMP=n
  CONFIG_SCSI_DUMP=n
  CONFIG_BLOCKDUMP=n
+ # CONFIG_KDB is not set
  
  #
  # Library routines
diff -c -r -N console-os/configs/kernel-2.4.21-i686.config console-os-kdb/configs/kernel-2.4.21-i686.config
*** console-os/configs/kernel-2.4.21-i686.config	2006-12-22 15:12:20.000000000 -0800
--- console-os-kdb/configs/kernel-2.4.21-i686.config	2007-01-10 14:02:18.000000000 -0800
***************
*** 1792,1797 ****
--- 1792,1798 ----
  CONFIG_DISKDUMP=n
  CONFIG_SCSI_DUMP=n
  CONFIG_BLOCKDUMP=n
+ # CONFIG_KDB is not set
  # Library routines
  CONFIG_CRC32=m
  CONFIG_QSORT=y
diff -c -r -N console-os/configs/kernel-2.4.21-i686-smp.config console-os-kdb/configs/kernel-2.4.21-i686-smp.config
*** console-os/configs/kernel-2.4.21-i686-smp.config	2006-12-22 15:12:20.000000000 -0800
--- console-os-kdb/configs/kernel-2.4.21-i686-smp.config	2007-01-10 14:02:18.000000000 -0800
***************
*** 1797,1802 ****
--- 1797,1803 ----
  CONFIG_DISKDUMP=n
  CONFIG_SCSI_DUMP=n
  CONFIG_BLOCKDUMP=n
+ # CONFIG_KDB is not set
  # Library routines
  CONFIG_CRC32=m
  CONFIG_QSORT=y
diff -c -r -N console-os/configs/vmnix.config console-os-kdb/configs/vmnix.config
*** console-os/configs/vmnix.config	2006-12-22 15:12:20.000000000 -0800
--- console-os-kdb/configs/vmnix.config	2007-01-10 14:02:18.000000000 -0800
***************
*** 1171,1176 ****
--- 1171,1181 ----
  # Kernel hacking
  #
  # CONFIG_DEBUG_KERNEL is not set
+ CONFIG_KDB=y
+ CONFIG_KDB_MODULES=n
+ CONFIG_KDB_OFF=y
+ CONFIG_KDB_CONTINUE_CATASTROPHIC=0
+ CONFIG_KDB_USB=n
  
  #
  # Cryptographic options
diff -c -r -N console-os/Documentation/Configure.help console-os-kdb/Documentation/Configure.help
*** console-os/Documentation/Configure.help	2006-11-20 12:22:39.000000000 -0800
--- console-os-kdb/Documentation/Configure.help	2007-01-10 14:02:18.000000000 -0800
***************
*** 21712,21717 ****
--- 21712,21801 ----
    keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
    unless you really know what this hack does.
  
+ Kernel Debugging support
+ CONFIG_KDB
+   This option provides a built-in kernel debugger.  The built-in
+   kernel debugger contains commands which allow memory to be examined,
+   instructions to be disassembled and breakpoints to be set.  For details,
+   see Documentation/kdb/kdb.mm and the manual pages kdb_bt, kdb_ss, etc.
+   Kdb can also be used via the serial port.  Set up the system to
+   have a serial console (see Documentation/serial-console.txt).
+   The Control-A key sequence on the serial port will cause the
+   kernel debugger to be entered with input from the serial port and
+   output to the serial console.  Selecting this option will
+   automatically set CONFIG_KALLSYMS. If unsure, say N.
+ 
+ KDB modules
+ CONFIG_KDB_MODULES
+   KDB can be extended by adding your own modules, in directory
+   kdb/modules.  This option selects the way that these modules should
+   be compiled, as free standing modules (select M) or built into the
+   kernel (select Y).  If unsure say M.
+ 
+ KDB off by default
+ CONFIG_KDB_OFF
+   Normally kdb is activated by default, as long as CONFIG_KDB is set.
+   If you want to ship a kernel with kdb support but only have kdb
+   turned on when the user requests it then select this option.  When
+   compiled with CONFIG_KDB_OFF, kdb ignores all events unless you boot
+   with kdb=on or you echo "1" > /proc/sys/kernel/kdb.  This option also
+   works in reverse, if kdb is normally activated, you can boot with
+   kdb=off or echo "0" > /proc/sys/kernel/kdb to deactivate kdb. If
+   unsure, say N.
+ 
+ KDB continues after catastrophic errors
+ CONFIG_KDB_CONTINUE_CATASTROPHIC
+   This integer controls the behaviour of kdb when the kernel gets a
+   catastrophic error, i.e. for a panic, oops, NMI or other watchdog
+   tripping.  CONFIG_KDB_CONTINUE_CATASTROPHIC interacts with
+   /proc/sys/kernel/kdb and CONFIG_DUMP (if your kernel has the LKCD
+   patch).
+ 
+   When KDB is active (/proc/sys/kernel/kdb == 1) and a catastrophic
+   error occurs, nothing extra happens until you type 'go'.
+ 
+     CONFIG_KDB_CONTINUE_CATASTROPHIC == 0 (default).  The first time
+     you type 'go', kdb warns you.  The second time you type 'go', KDB
+     tries to continue - no guarantees that the kernel is still usable.
+ 
+     CONFIG_KDB_CONTINUE_CATASTROPHIC == 1.  KDB tries to continue - no
+     guarantees that the kernel is still usable.
+ 
+     CONFIG_KDB_CONTINUE_CATASTROPHIC == 2.  If your kernel has the LKCD
+     patch and LKCD is configured to take a dump then KDB forces a dump.
+     Whether or not a dump is taken, KDB forces a reboot.
+ 
+   When KDB is not active (/proc/sys/kernel/kdb == 0) and a catastrophic
+   error occurs, the following steps are automatic, no human
+   intervention is required.
+ 
+     CONFIG_KDB_CONTINUE_CATASTROPHIC == 0 (default) or 1.  KDB attempts
+     to continue - no guarantees that the kernel is still usable.
+ 
+     CONFIG_KDB_CONTINUE_CATASTROPHIC == 2.  If your kernel has the LKCD
+     patch and LKCD is configured to take a dump then KDB automatically
+     forces a dump.  Whether or not a dump is taken, KDB forces a
+     reboot.
+ 
+   If you are not sure, say 0.  Read Documentation/kdb/dump.txt before
+   setting to 2.
+ 
+ Support for USB Keyboard in KDB
+ CONFIG_KDB_USB
+   If you want to use kdb from a USB keyboard then say Y here.  If you
+   say N then kdb can only be used from a PC (AT) keyboard or a serial
+   console.
+ 
+ Load all symbols for debugging
+ CONFIG_KALLSYMS
+   Normally only exported symbols are available to modules. For
+   debugging you may want all symbols, not just the exported ones. If
+   you say Y here then extra data is added to the kernel and modules,
+   this data lists all the non-stack symbols in the kernel or module
+   and can be used by any debugger.  You need modutils >= 2.3.11 to use
+   this option. See "man kallsyms" for the data format, it adds 10-20%
+   to the size of the kernel and the loaded modules. If unsure, say N.
+ 
  ISDN support
  CONFIG_ISDN
    ISDN ("Integrated Services Digital Networks", called RNIS in France)
diff -c -r -N console-os/Documentation/kdb/dump.txt console-os-kdb/Documentation/kdb/dump.txt
*** console-os/Documentation/kdb/dump.txt	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/dump.txt	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,364 ----
+ Interaction between KDB and LKCD.
+ 
+ Executive summary: Do not select CONFIG_KDB_CONTINUE_CATASTROPHIC=2 or
+ use KDB command 'sr c' without first patching LKCD to use KDB data.
+ 
+ Both KDB and LKCD try to stop all the other cpus, so the system is not
+ changing while it is being debugged or dumped.  KDB will cope with cpus
+ that cannot be stopped, some versions of LKCD will just hang.  In
+ particular, when LKCD is invoked from KDB, LKCD will attempt to stop
+ the other cpus again and may hang.
+ 
+ Some versions of LKCD detect that other cpus are not responding and
+ ignore them.  This is almost as bad, the data is changing while it is
+ being dumped.  Also the method used to avoid hung cpus has been known
+ to cause oops when LKCD has finished dumping.
+ 
+ LKCD does not know about several special cases on IA64, including INIT
+ and MCA backtraces, interrupt handlers, out of line code etc.  LKCD
+ cannot capture cpu state on any cpu that is not responding to OS
+ interrupts, which means that any cpu that is spinning in a disabled
+ loop cannot be debugged.  Any cpu that calls into SAL for MCA
+ rendezvous cannot be debugged.  Even when LKCD captures IA64 state, the
+ user space lcrash code cannot unwind through any assembler code, which
+ rules out all the interesting cases.
+ 
+ KDB knows far more than LKCD about architecture peculiarities, stack
+ formats, interrupt handling etc.  The methods used by KDB to stop the
+ other processors and capture their state are far more reliable than
+ those used by LKCD.  KDB can capture INIT and MCA data on IA64, as well
+ as save the state of cpus before they enter SAL.
+ 
+ Rather than duplicating the complex KDB code in LKCD, LKCD can be
+ patched to use the information that has already been captured by KDB.
+ Obviously this only works when LKCD is invoked from KDB.  If you invoke
+ LKCD directly from the console with SysRq-c or the dump() function is
+ called from code outside KDB then you get the old and broken LKCD
+ processing.  Because lcrash uses the old unwind algorithm which cannot
+ unwind through IA64 assembler code, KDB kludges the saved state into
+ something that the old unwind algorithm can cope with.  Calling LKCD
+ from KDB gives you a clean dump, but you have to patch LKCD first.
+ 
+ There are two ways to invoke LKCD from KDB.  One way is manual, using
+ the KDB 'sr c' command.  This is identical to doing SysRq-C from the
+ console except that it goes through KDB first, so LKCD can use the data
+ that KDB has captured.  Obviously 'sr c' requires human intervention
+ and KDB must be on, it is up to the person doing the debugging if they
+ want to take a dump.
+ 
+ The second way is to set CONFIG_KDB_CONTINUE_CATASTROPHIC=2.  With this
+ setting, you automatically get a dump for catastrophic errors.  A
+ catastrophic error is a panic, oops, NMI or other watchdog tripping,
+ INIT and MCA events on IA64.  CONFIG_KDB_CONTINUE_CATASTROPHIC=2 has no
+ effect on debugging events such as break points, single step etc. so it
+ does not interfere with manual debugging.
+ 
+ When CONFIG_KDB_CONTINUE_CATASTROPHIC=2 and KDB is on, a catastrophic
+ error will drop into KDB to allow manual debugging, typing 'go' will
+ take a dump and force a reboot.  With this setting and KDB is off, KDB
+ detects a catastrophic error, does enough processing to capture the
+ state, takes a dump and forces a reboot - all automatic with no human
+ intervention.
+ 
+ For unattended and clean LKCD dumps, patch LKCD to use KDB data.  Use
+   CONFIG_DUMP=y
+   CONFIG_KDB=y
+   CONFIG_KDB_OFF=y
+   CONFIG_KDB_CONTINUE_CATASTROPHIC=2
+ 
+ If you want human intervention before taking a dump, use
+   CONFIG_DUMP=y
+   CONFIG_KDB=y
+   CONFIG_KDB_OFF=n
+   CONFIG_KDB_CONTINUE_CATASTROPHIC=2
+ 
+ 
+ The following are indicative patches against lkcd 4.1, kernel 2.4.20.
+ You may have to to modify the patches for other kernels or other
+ versions of lkcd.
+ 
+ diff -urp lkcd/drivers/dump/dump_base.c lkcd/drivers/dump/dump_base.c
+ --- lkcd/drivers/dump/dump_base.c	Thu May  1 13:10:12 2003
+ +++ lkcd/drivers/dump/dump_base.c	Fri Jun 20 12:28:16 2003
+ @@ -207,6 +207,9 @@
+  #include <asm/hardirq.h>
+  #include <linux/version.h>
+  #include <asm/system.h>
+ +#ifdef	CONFIG_KDB
+ +#include <linux/kdb.h>
+ +#endif
+  
+  /*
+   * -----------------------------------------------------------------------
+ @@ -852,6 +855,13 @@ dump_silence_system(void)
+  	unsigned int stage = 0;
+  	int cpu = smp_processor_id();
+  
+ +#ifdef	CONFIG_KDB
+ +	if (KDB_IS_RUNNING()) {
+ +		/* kdb is in control, the system is already silenced */
+ +		printk(KERN_ALERT "LKCD entered from KDB\n");
+ +	}
+ +#endif	/* CONFIG_KDB */
+ +
+  	if (in_interrupt()) {
+  		printk(KERN_ALERT "Dumping from interrupt handler !\n");
+  		printk(KERN_ALERT "Uncertain scenario - but will try my best\n");
+ @@ -861,6 +871,9 @@ dump_silence_system(void)
+  		 * another approach 
+  		 */
+  	}
+  	/* see if there's something to do before we re-enable interrupts */
+ +#ifdef	CONFIG_KDB
+ +	if (!KDB_IS_RUNNING())
+ +#endif	/* CONFIG_KDB */
+  	(void)__dump_silence_system(stage);
+  
+ @@ -905,6 +918,9 @@ dump_silence_system(void)
+  
+  	/* now increment the stage and do stuff after interrupts are enabled */
+  	stage++;
+ +#ifdef	CONFIG_KDB
+ +	if (!KDB_IS_RUNNING())
+ +#endif	/* CONFIG_KDB */
+  	(void)__dump_silence_system(stage);
+  
+  	/* time to leave */
+ diff -urp lkcd/drivers/dump/dump_i386.c lkcd/drivers/dump/dump_i386.c
+ --- lkcd/drivers/dump/dump_i386.c	Tue Jul  9 07:14:11 2002
+ +++ lkcd/drivers/dump/dump_i386.c	Fri Jun 20 12:29:12 2003
+ @@ -27,6 +27,10 @@
+  #include <asm/processor.h>
+  #include <asm/hardirq.h>
+  #include <linux/irq.h>
+ +#ifdef	CONFIG_KDB
+ +#include <linux/kdb.h>
+ +#include <linux/kdbprivate.h>
+ +#endif	/* CONFIG_KDB */
+  
+  static int alloc_dha_stack(void)
+  {
+ @@ -119,6 +123,31 @@ save_other_cpu_states(void)
+  {
+  	int i;
+  
+ +#ifdef	CONFIG_KDB
+ +	if (KDB_IS_RUNNING()) {
+ +		/* invoked from kdb, which has already saved all the state */
+ +		int cpu;
+ +		struct kdb_running_process *krp;
+ +		for (cpu = 0, krp = kdb_running_process; cpu < smp_num_cpus; ++cpu, ++krp) {
+ +			if (krp->seqno < kdb_seqno - 1 ||
+ +			    !krp->regs ||
+ +			    !krp->p ||
+ +			    kdb_process_cpu(krp->p) != cpu) {
+ +				printk(KERN_WARNING "No KDB data for cpu %d, it will not be in the LKCD dump\n", cpu);
+ +				continue;
+ +			}
+ +			if (cpu == smp_processor_id())
+ +				continue;	/* dumped by save_this_cpu_state */
+ +			// kdb_printf("%s: cpu %d task %p regs %p\n", __FUNCTION__, cpu, krp->p, krp->regs);
+ +			save_this_cpu_state(cpu, krp->regs, krp->p);
+ +		}
+ +		return;
+ +	}
+ +	printk(KERN_WARNING "This kernel supports KDB but LKCD was invoked directly, not via KDB.\n");
+ +	printk(KERN_WARNING "Falling back to the old and broken LKCD method of getting data from all cpus,\n");
+ +	printk(KERN_WARNING "do not be surprised if LKCD hangs.\n");
+ +#endif	/* CONFIG_KDB */
+ +
+  	if (smp_num_cpus > 1) {
+  		atomic_set(&waiting_for_dump_ipi, smp_num_cpus-1);
+  		for (i = 0; i < NR_CPUS; i++)
+ diff -urp lkcd/drivers/dump/dump_ia64.c lkcd/drivers/dump/dump_ia64.c
+ --- lkcd/drivers/dump/dump_ia64.c	Tue Jul  9 07:14:11 2002
+ +++ lkcd/drivers/dump/dump_ia64.c	Fri Jun 20 12:31:41 2003
+ @@ -30,6 +30,10 @@
+  #include <asm/processor.h>
+  #include <asm/hardirq.h>
+  #include <linux/irq.h>
+ +#ifdef	CONFIG_KDB
+ +#include <linux/kdb.h>
+ +#include <linux/kdbprivate.h>
+ +#endif	/* CONFIG_KDB */
+  
+  extern unsigned long irq_affinity[];
+  
+ @@ -75,6 +79,12 @@ save_this_cpu_state(int cpu, struct pt_r
+  
+  	if (tsk && dump_header_asm.dha_stack[cpu]) {
+  		memcpy((void*)dump_header_asm.dha_stack[cpu], tsk, THREAD_SIZE);
+ +#ifdef	CONFIG_KDB
+ +		if (KDB_IS_RUNNING()) {
+ +			static void kludge_for_broken_lcrash(int);
+ +			kludge_for_broken_lcrash(cpu);
+ +		}
+ +#endif	/* CONFIG_KDB */
+  	}
+  	return;
+  }
+ @@ -107,6 +117,32 @@ save_other_cpu_states(void)
+  {
+  	int i;
+  
+ +#ifdef	CONFIG_KDB
+ +	if (KDB_IS_RUNNING()) {
+ +		/* invoked from kdb, which has already saved all the state */
+ +		int cpu;
+ +		struct kdb_running_process *krp;
+ +		for (cpu = 0, krp = kdb_running_process; cpu < smp_num_cpus; ++cpu, ++krp) {
+ +			if (krp->seqno < kdb_seqno - 1 ||
+ +			    !krp->regs ||
+ +			    !krp->arch.sw ||
+ +			    !krp->p ||
+ +			    kdb_process_cpu(krp->p) != cpu) {
+ +				printk(KERN_WARNING "No KDB data for cpu %d, it will not be in the LKCD dump\n", cpu);
+ +				continue;
+ +			}
+ +			if (cpu == smp_processor_id())
+ +				continue;	/* dumped by save_this_cpu_state */
+ +			// kdb_printf("%s: cpu %d task %p regs %p\n", __FUNCTION__, cpu, krp->p, krp->regs);
+ +			save_this_cpu_state(cpu, krp->regs, krp->p);
+ +		}
+ +		return;
+ +	}
+ +	printk(KERN_WARNING "This kernel supports KDB but LKCD was invoked directly, not via KDB.\n");
+ +	printk(KERN_WARNING "Falling back to the old and broken LKCD method of getting data from all cpus,\n");
+ +	printk(KERN_WARNING "do not be surprised if LKCD hangs.\n");
+ +#endif	/* CONFIG_KDB */
+ +
+  	if (smp_num_cpus > 1) {
+  		atomic_set(&waiting_for_dump_ipi, smp_num_cpus-1);
+  		for (i = 0; i < NR_CPUS; i++)
+ @@ -380,3 +416,131 @@ void * __dump_memcpy(void * dest, const 
+  	}
+  	return(vp);
+  }
+ +
+ +#ifdef	CONFIG_KDB
+ +/*
+ + * lcrash is broken.  It incorrectly assumes that all tasks are blocked, it
+ + * assumes that all code is built by gcc (and therefore it cannot unwind through
+ + * assembler code), it assumes that there is only one pt_regs at the base of the
+ + * stack (where user space entered the kernel).  Dumping from kdb (or any
+ + * interrupt context) breaks all those assumptions, resulting in a good dump
+ + * that lcrash cannot get any useful backtraces from.
+ + *
+ + * The real fix is to correct lcrash, using libunwind.  That is not going to
+ + * happen any time soon, so this kludge takes the kdb data and reformats it to
+ + * suit the broken lcrash code.  The task state is unwound past the interrupt
+ + * frame (pt_regs) before kdb, then a switch_stack is synthesized in place of
+ + * the pt_regs, using the unwound data.  ksp is changed to point to this
+ + * switch_stack, making it look like the task is blocked with no interrupt.
+ + *
+ + * This will not work when the interrupt occurred in a leaf function, with no
+ + * save of b0.  But the old unwind code in lcrash cannot cope with that either,
+ + * so no change.
+ + */
+ +
+ +static inline void *
+ +kludge_copy_addr(int cpu, void *addr, struct task_struct *p)
+ +{
+ +	return (char *)addr - (char *)p + (char *)(dump_header_asm.dha_stack[cpu]);
+ +}
+ +
+ +static void
+ +kludge_for_broken_lcrash(int cpu)
+ +{
+ +	struct kdb_running_process *krp = kdb_running_process + cpu;
+ +	struct task_struct *p, *p_copy;
+ +	struct switch_stack *sw, *sw_copy, *sw_new;
+ +	struct pt_regs *regs;
+ +	struct unw_frame_info info;
+ +	kdb_symtab_t symtab;
+ +	kdb_machreg_t sp;
+ +	int count, i;
+ +	char nat;
+ +
+ +	if (krp->seqno < kdb_seqno - 1 ||
+ +	    !krp->regs ||
+ +	    user_mode(krp->regs) ||
+ +	    !krp->arch.sw ||
+ +	    !krp->p ||
+ +	    kdb_process_cpu(krp->p) != cpu)
+ +		return;
+ +	p = krp->p;
+ +	regs = krp->regs;
+ +	sw = krp->arch.sw;
+ +#if 0
+ +	{
+ +		char buf[80];
+ +		sprintf(buf, "btc %d\n", cpu);
+ +		kdb_parse(buf, regs);
+ +	}
+ +#endif
+ +
+ +	unw_init_frame_info(&info, p, sw);
+ +	count = 0;
+ +	do {
+ +		unw_get_sp(&info, &sp);
+ +		// kdb_printf("sp 0x%lx regs 0x%lx\n", sp, regs);
+ +	} while (sp < (kdb_machreg_t)regs && unw_unwind(&info) >= 0 && count++ < 200);
+ +	if (count >= 200) {
+ +		printk(KERN_WARNING "Unwind for process %d on cpu %d looped\n", p->pid, cpu);
+ +		return;
+ +	}
+ +
+ +	/* Must not touch the real stack data, kludge the data using the copies
+ +	 * in dump_header_asm.
+ +	 */
+ +	p_copy = kludge_copy_addr(cpu, p, p);
+ +	sw_new = (struct switch_stack *)((u64)(regs + 1) + 16) - 1;
+ +	sw_copy = kludge_copy_addr(cpu, sw_new, p);
+ +	// kdb_printf("p_copy 0x%p sw_new 0x%p sw_copy 0x%p\n", p_copy, sw_new, sw_copy);
+ +	memset(sw_copy, 0, sizeof(*sw_copy));
+ +
+ +	sw_copy->caller_unat = sw->caller_unat;
+ +	unw_access_ar(&info, UNW_AR_FPSR, &sw_copy->ar_fpsr, 0);
+ +	for (i = 2; i <= 5; ++i)
+ +		unw_access_fr(&info, i, &sw_copy->f2 + i - 2, 0);
+ +	for (i = 10; i <= 31; ++i)
+ +		unw_access_fr(&info, i, &sw_copy->f10 + i - 10, 0);
+ +	for (i = 4; i <= 7; ++i)
+ +		unw_access_gr(&info, i, &sw_copy->r4 + i - 4, &nat, 0);
+ +	for (i = 0; i <= 5; ++i)
+ +		unw_access_br(&info, i, &sw_copy->b0 + i, 0);
+ +	sw_copy->ar_pfs = *info.cfm_loc;
+ +	unw_access_ar(&info, UNW_AR_LC, &sw_copy->ar_lc, 0);
+ +	unw_access_ar(&info, UNW_AR_UNAT, &sw_copy->ar_unat, 0);
+ +	unw_access_ar(&info, UNW_AR_RNAT, &sw_copy->ar_rnat, 0);
+ +	/* FIXME: unwind.c returns the original bspstore, not the value that
+ +	 * matches the current unwind state.  Calculate our own value for the
+ +	 * modified bspstore.  This should work but does not
+ +	 *   unw_access_ar(&info, UNW_AR_BSPSTORE, &sw_copy->ar_bspstore, 0);
+ +	*/
+ +	sw_copy->ar_bspstore = (unsigned long)ia64_rse_skip_regs((unsigned long *)info.bsp, (*info.cfm_loc >> 7) & 0x7f);
+ +	unw_access_pr(&info, &sw_copy->pr, 0);
+ +
+ +	/* lcrash cannot unwind through the new spinlock contention code and it
+ +	 * is too important a case to ignore.  So the kludge extracts the
+ +	 * calling IP before saving the data.
+ +	 */
+ +	if (kdbnearsym(regs->cr_iip, &symtab) &&
+ +		strncmp(symtab.sym_name, "ia64_spinlock_contention", 24) == 0)
+ +		unw_get_rp(&info, &sw_copy->b0);
+ +
+ +	p_copy->thread.ksp = (__u64)sw_new - 16;
+ +	dump_header_asm.dha_smp_regs[cpu] = *((struct pt_regs *)((unsigned long)p + THREAD_SIZE) - 1);
+ +#if 0
+ +	{
+ +		/* debug.  Destructive overwrite of task, then bt the result in kdb to
+ +		 * validate the modified task.
+ +		 */
+ +		char buf[80];
+ +		memcpy(p, p_copy, THREAD_SIZE);
+ +		krp->regs = NULL;
+ +		krp->arch.sw = sw_new;
+ +		sprintf(buf, "btc %d\n", cpu);
+ +		kdb_parse(buf, NULL);
+ +		while(1){};
+ +	}
+ +#endif
+ +}
+ +
+ +#endif	/* CONFIG_KDB */
diff -c -r -N console-os/Documentation/kdb/kdb_bp.man console-os-kdb/Documentation/kdb/kdb_bp.man
*** console-os/Documentation/kdb/kdb_bp.man	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/kdb_bp.man	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,194 ----
+ .TH BD 1 "1 June 2003"
+ .SH NAME
+ bp, bpa, bph, bpha, bd, bc, be, bl \- breakpoint commands
+ .SH SYNOPSIS
+ bp \fIaddress-expression\fP
+ .LP
+ bpa \fIaddress-expression\fP
+ .LP
+ bph \fIaddress-expression\fP [\f(CWDATAR|DATAW|DATAA|IO\fP [\fIlength\fP]]
+ .LP
+ bpha \fIaddress-expression\fP [\f(CWDATAR|DATAW|DATAA|IO\fP [\fIlength\fP]]
+ .LP
+ bd \fIbreakpoint-number\fP
+ .LP
+ bc \fIbreakpoint-number\fP
+ .LP
+ be \fIbreakpoint-number\fP
+ .LP
+ bl
+ .SH DESCRIPTION
+ .hy 0
+ The
+ .B bp 
+ family of commands are used to establish a breakpoint.   
+ The \fIaddress-expression\fP may be a numeric value (decimal or
+ hexidecimal), a symbol name, a register name preceeded by a 
+ percent symbol '%', or a simple expression consisting of a 
+ symbol name, an addition or subtraction character and a numeric
+ value (decimal or hexidecimal).
+ .P
+ \fBbph\fP and \fBbpha\fP will force the use of a hardware register, provided 
+ the processor architecture supports them. 
+ .P
+ The \fIaddress-expression\fP may also consist of a single
+ asterisk '*' symbol which indicates that the command should
+ operate on all existing breakpoints (valid only for \fBbc\fP, 
+ \fBbd\fP and \fBbe\fP).
+ .P
+ Four different types of
+ breakpoints may be set:
+ 
+ .TP 8
+ Instruction
+ Causes the kernel debugger to be invoked from the debug exception
+ path when an instruction is fetched from the specified address.  This
+ is the default if no other type of breakpoint is requested or when
+ the \fBbp\fP command is used.
+ 
+ .TP 8
+ DATAR
+ Causes the kernel debugger to be entered when data of length
+ \fIlength\fP is read from or written to the specified address.
+ This type of breakpoint must use a processor debug register which
+ places an architecture dependent limit on the number of data and I/O
+ breakpoints that may be established. On arm mode XScale platform
+ (thumb mode is not supported yet),
+ debugger is triggered by reading from the specified address.
+ The \fBbph\fP or \fBbpha\fP commands must be used.
+ 
+ .TP 8
+ DATAW
+ Enters the kernel debugger when data of length \fIlength\fP
+ is written to the specified address.  \fIlength\fP defaults 
+ to four bytes if it is not explicitly specified.
+ Note that the processor may have already overwritten the prior data at
+ the breakpoint location before the kernel debugger is invoked.
+ The prior data should be saved before establishing the breakpoint, if
+ required. On arm mode XScale platform, the debugger is triggered 
+ after having overwritten the specified address.
+ The \fBbph\fP or \fBbpha\fP commands must be used.
+ 
+ .TP 8
+ IO
+ Enters the kernel debugger when an \fBin\fP or \fBout\fP instruction
+ targets the specified I/O address.  The \fBbph\fP or \fBbpha\fP
+ commands must be used. This type of breakpoint is not valid in
+ arm mode XScale platform. This option is not valid in arm 
+ mode XScale platform.
+ 
+ .TP 8
+ DATAA
+ Enters the kernel debugger after the data in specified address has
+ been accessed (read or write), this option is only used in arm 
+ mode XScale platform.
+ 
+ .P
+ The
+ .B bpha
+ command will establish a breakpoint on all processors in an
+ SMP system.   This command is not available in an uniprocessor
+ kernel.
+ .P
+ The
+ .B bd
+ command will disable a breakpoint without removing it from the kernel
+ debugger's breakpoint table.
+ This can be used to keep breakpoints in the table without exceeding the
+ architecture limit on breakpoint registers.
+ .P
+ The
+ .B be
+ command will re-enable a disabled breakpoint.
+ .P
+ The
+ .B bc
+ command will clear a breakpoint from the breakpoint table.
+ .P
+ The 
+ .B bl
+ command will list the existing set of breakpoints.
+ .SH LIMITATIONS
+ There is a compile time limit of sixteen entries in the 
+ breakpoint table at any one time.
+ .P
+ There are architecture dependent limits on the number of hardware
+ breakpoints that can be set.
+ .IP ix86 8
+ Four.
+ .PD 0
+ .IP xscale 8
+ Two for insruction breakpoints and another two for data breakpoint.
+ .PD 0
+ .IP ia64 8
+ ?
+ .PD 0
+ .IP sparc64 8
+ None.
+ .PD 1
+ When issuing the "go" command after entering the debugger due to
+ a breakpoint, kdb will silently perform a single step in order to
+ reapply the breakpoint. The sparc64 port has some limitations on
+ single stepping, which may limit where a breakpoint may be safely
+ set. Please read the man page for \fBss\fP for more information.
+ .SH ENVIRONMENT
+ The breakpoint subsystem does not currently use any environment
+ variables.
+ .SH SMP CONSIDERATIONS
+ Using
+ .B bc
+ is risky on SMP systems.
+ If you clear a breakpoint when another cpu has hit that breakpoint but
+ has not been processed then it may not be recognised as a kdb
+ breakpoint, usually resulting in incorrect program counters and kernel
+ panics.
+ It is safer to disable the breakpoint with
+ .BR bd ,
+ then
+ .B go
+ to let any other processors that are waiting on the breakpoint to
+ clear.
+ After all processors are clear of the disabled breakpoint then it is
+ safe to clear it using
+ .BR bc .
+ .P
+ Breakpoints which use the processor breakpoint registers
+ are only established on the processor which is
+ currently active.  If you wish breakpoints to be universal
+ use the
+ .B bpa
+ or
+ .B bpha
+ commands.
+ .SH EXAMPLES
+ .TP 8
+ bp schedule
+ Sets an instruction breakpoint at the begining of the 
+ function \fBschedule\fP.
+ 
+ .TP 8
+ bp schedule+0x12e
+ Sets an instruction breakpoint at the instruction located
+ at \fBschedule\fP+\fI0x12e\fP.
+ 
+ .TP 8
+ bph ttybuffer+0x24 dataw
+ Sets a data write breakpoint at the location referenced by
+ \fBttybuffer\fP+\fI0x24\fP for a length of four bytes.
+ 
+ .TP 8
+ bph 0xc0254010 datar 1
+ Establishes a data reference breakpoint at address \fB0xc0254010\fP
+ for a length of one byte.
+ 
+ .TP 8
+ bp
+ List current breakpoint table.
+ 
+ .TP 8
+ bd 0
+ Disable breakpoint #0.
+ 
+ .TP 8
+ bc *
+ Clear all breakpoints
diff -c -r -N console-os/Documentation/kdb/kdb_bt.man console-os-kdb/Documentation/kdb/kdb_bt.man
*** console-os/Documentation/kdb/kdb_bt.man	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/kdb_bt.man	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,219 ----
+ .TH BT 1 "20 July 2003"
+ .SH NAME
+ bt \- Stack Traceback command
+ .SH SYNOPSIS
+ bt [ <stack-frame-address> ]
+ .LP
+ btp <pid>
+ .LP
+ btt <struct-task-address>
+ .LP
+ bta [ DRSTZU ]
+ .LP
+ btc [<cpu>]
+ .SH DESCRIPTION
+ .hy 0
+ The
+ .B bt 
+ command is used to print a stack traceback.  It uses the 
+ current registers (see \fBrd\fP command) to determine
+ the starting context and attempts to provide a complete
+ stack traceback for the active thread.   If \fIstack-frame-address\fP
+ is supplied, it is assumed to point to the start of a valid
+ stack frame and the stack will be traced back from that 
+ point (e.g. on i386 architecture, \fIstack-frame-address\fP 
+ should be the stack address of a saved \fB%eip\fP value from a \fBcall\fP
+ instruction. on sparc64 architecture, it should be a pointer to a
+ saved register window, as is found in the \fB%fp\fP register).
+ .P
+ If present, a kernel configuration option \fBCONFIG_FRAME_POINTER\fP
+ should be enabled so that the compiler will utilize the frame pointer
+ register properly to maintain a stack which can be correctly 
+ analyzed. Some architectures (e.g. sparc64) always use
+ \fBCONFIG_FRAME_POINTER\fP, and so the option is not present.
+ .P
+ The \fBbt\fP command will attempt to analyze the stack without
+ frame pointers if the \fBCONFIG_FRAME_POINTER\fP option is not
+ enabled, but the analysis is difficult and may not produce
+ accurate nor complete results. 
+ .P
+ The \fBbtp\fP command will analyze the stack for the given
+ process identification (see the \fBps\fP command).
+ .P
+ The \fBbtt\fP command will analyze the stack for the given task
+ structure.
+ It is exactly equivalent to \fBbtp\fR on the pid extracted from the
+ task structure.
+ .P
+ The \fBbta\fP command lists the stack for all processes in the desired
+ state.
+ Without any parameters, \fBbta\fP gives a backtrace for all processes.
+ If a parameter is specified, it is a single string consisting of the
+ letters D, R, S, T, Z and U, in any order.
+ Each letter selects processes in a specific state, when multiple
+ letters are specified, a process will be traced if it is in any of the
+ specified states.
+ \fBbta\ RD\fR displays only tasks that are running or are in an
+ uninterruptible sleep.
+ The states are\ :-
+ .IP D 3
+ Uninterruptible sleep.
+ .PD 0
+ .IP R 3
+ Running.
+ The process may not be on a cpu at the moment, but it is ready to run.
+ The header line above the backtrace contains '1' in the fourth field if
+ the process is actually on a cpu.
+ .IP S 3
+ Interruptible sleep.
+ .IP T 3
+ Traced or stopped.
+ .IP Z 3
+ Zombie.
+ .IP U 3
+ Unrunnable.
+ .PD 1
+ .P
+ The \fBbtc\fP command will analyze the stack for the current process on
+ a specified cpu or, if no cpu number is supplied, for the current
+ process on all cpus.
+ It does not switch to the other cpus, instead it uses the task
+ structures to identify and issue \fBbtt\fR against the current task on
+ the desired cpus.
+ .P
+ For each function, the stack trace prints at least two lines.
+ The first line contains four or five fields\ :-
+ .IP * 3
+ The pointer to the previous stack frame, blank if there is no valid
+ frame pointer.
+ .PD 0
+ .IP * 3
+ The current address within this frame.
+ .IP * 3
+ The address converted to a function name (actually the first non-local
+ label which is <= the address).
+ .IP * 3
+ The offset of the address within the function.
+ .IP * 3
+ Any parameters to the function.
+ .PD 1
+ .PP
+ On the next line there are five fields which are designed to make it
+ easier to match the trace against the kernel code\ :-
+ .IP * 3
+ The module name that contains the address, "kernel" if it is in the
+ base kernel.
+ .PD 0
+ .IP * 3
+ The section name that contains the address.
+ .IP * 3
+ The start address of the section.
+ .IP * 3
+ The start address of the function.
+ .IP * 3
+ The end address of the function (the first non-local label which is >
+ the address).
+ .PD 1
+ .PP
+ If arguments are being converted to symbols, any argument which
+ converts to a kernel or module address is printed as\ :-
+ .IP * 3
+ Argument address.
+ .PD 0
+ .IP * 3
+ The module name that contains the address, "kernel" if it is in the
+ base kernel.
+ .IP * 3
+ The symbol name the argument maps to.
+ .IP * 3
+ The offset of the argument from the symbol, suppressed if 0.
+ .PD 1
+ .SH MATCHING TRACE TO KERNEL CODE
+ The command "objdump\ -S" will disassemble an object and, if the code
+ was compiled with debugging (gcc flag -g), objdump will interleave the
+ C source lines with the generated object.
+ .PP
+ A complete objdump of the kernel or a module is too big, normally you
+ only want specific functions.
+ By default objdump will only print the .text section but Linux uses
+ other section names for executable code.
+ When objdump prints relocatable objects (modules) it uses an offset of
+ 0 which is awkward to relate to the stack trace.
+ The five fields which are printed for each function are designed to
+ make it easier to match the stack trace against the kernel code using
+ "objdump\ -S".
+ .PP
+ If the function is in the kernel then you need the section name, the
+ start and end address of the function.  The command is
+ .PP
+ .nf
+   objdump -S -j <section_name> \\
+           --start-address=<start-address> \\
+           --stop-address=<end-address> \\
+           /usr/src/linux/vmlinux
+ .fi
+ .PP
+ If the function is in a module then you need the section name, the
+ start address of the section, the start and end address of the
+ function, the module name.  The command is
+ .PP
+ .nf
+   objdump -S -j <section_name> \\
+           --adjust-vma=<section-start> \\
+           --start-address=<start-address> \\
+           --stop-address=<end-address> \\
+           /path/to/module/<module-name>.o
+ .fi
+ .PP
+ All addresses to objdump must be preceded by '0x' if they are in hex,
+ objdump does not assume hex.
+ The stack trace values are printed with leading '0x' to make it easy to
+ run objdump.
+ .SH LIMITATIONS
+ If the kernel is compiled without frame pointers, stack tracebacks
+ may be incomplete.  The \fBmds %esp\fP (i386) or \fBmds %fp\fP (sparc64)
+ command may be useful in attemping to determine the actual stack
+ traceback manually.
+ .P
+ A stack trace can be misleading if any code in a function exit has been
+ executed, the stack is partially unwound at that stage.
+ .P
+ The \fBbt\fP command may print more arguments for a function
+ than that function accepts;  For sparc64, this will always happen
+ as the debugger cannot determine the correct number. For i386, this happens
+ when the C compiler doesn't immediately pop the arguments off the stack upon
+ return from a called function.  When this is this case, these extra 
+ stack words will be considered additional arguments by the \fBbt\fP
+ command.
+ .SH ENVIRONMENT
+ The \fBBTARGS\fP environment variable governs the maximum number
+ of arguments that are printed for any single function.
+ .PP
+ If the \fBBTSYMARG\fP environment variable is non-zero then any
+ arguments that fall within the kernel are converted to symbols.
+ .PP
+ If the \fBNOSECT\fP environment variable is non-zero then the
+ section information is suppressed.
+ .PP
+ The \fBBTAPROMPT\fP environment variable controls the prompt after each
+ process is listed by the \fBbta\fP command.  If \fBBTAPROMPT\fP is not
+ set or is non-zero then \fBbta\fP issues a prompt after each process is
+ listed.  If \fBBTAPROMPT\fP is set to zero then no prompt is issued and
+ all processes are listed without human intervention.
+ .SH SMP CONSIDERATIONS
+ None.
+ .SH EXAMPLES
+ .nf
+ .na
+ .ft CW
+ Entering kdb (0xc3cb4000) due to Breakpoint @ 0xc011725d
+ Instruction(i) breakpoint #0 at 0xc011725c
+ qm_modules+0xd1:   movl   %ebp,%esp
+ kdb> bt
+     EBP       EIP         Function(args)
+ 0xc3cb5f98 0xc011725d  qm_modules+0xd1 (0x80721c0, 0x100, 0xbfff5000)
+                        kernel .text 0xc0100000 0xc011718c 0xc0117264
+ 0xc3cb5fbc 0xc0117875  sys_query_module+0x1b1 (0x0, 0x1, 0x80721c0, 0x100, 0xbfff5000)
+                        kernel .text 0xc0100000 0xc01176c4 0xc01178e8
+            0xc01095f8  system_call+0x34
+                        kernel .text 0xc0100000 0xc01095c4 0xc01095fc
diff -c -r -N console-os/Documentation/kdb/kdb_env.man console-os-kdb/Documentation/kdb/kdb_env.man
*** console-os/Documentation/kdb/kdb_env.man	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/kdb_env.man	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,46 ----
+ .TH ENV 1 "24 September 2000"
+ .SH NAME
+ env, set \- Environment manipulation commands
+ .SH SYNOPSIS
+ env
+ .LP
+ set \fIenvironment-variable\fP=\fIvalue\fP
+ .SH DESCRIPTION
+ The kernel debugger contains an environment which contains a series
+ of name-value pairs.  Some environment variables are known to the
+ various kernel debugger commands and have specific meaning to the
+ command; such are enumerated on the respective reference material. 
+ .P
+ Arbitrary environment variables may be created and used with 
+ many commands (those which require an \fIaddress-expression\fP).
+ .P
+ The
+ .B env
+ command is used to display the current environment.
+ .P
+ The
+ .B set
+ command is used to alter an existing environment variable or
+ establish a new environment variable.   
+ .SH LIMITATIONS
+ There is a compile-time limit of 33 environment variables.
+ .P
+ There is a compile-time limit of 512 bytes (\fBKDB_ENVBUFSIZE\fP)
+ of heap space available for new environment variables and for
+ environment variables changed from their compile-time values.
+ .SH ENVIRONMENT
+ These commands explicitly manipulate the environment.
+ .SH SMP CONSIDERATIONS
+ None.
+ .SH USER SETTINGS
+ You can include "set" commands in kdb/kdb_cmds (see kdb.mm) to define
+ your environment variables at kernel startup.
+ .SH EXAMPLES
+ .TP 8
+ env
+ Display current environment settings.
+ 
+ .TP 8
+ set IDCOUNT=100
+ Set the number of lines to display for the \fBid\fP command
+ to the value \fI100\fP.
diff -c -r -N console-os/Documentation/kdb/kdb_ll.man console-os-kdb/Documentation/kdb/kdb_ll.man
*** console-os/Documentation/kdb/kdb_ll.man	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/kdb_ll.man	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,134 ----
+ .TH LL 1 "19 April 1999"
+ .SH NAME
+ ll \- Linked List examination
+ .SH SYNOPSIS
+ ll <addr> <link-offset> <cmd>
+ .SH DESCRIPTION
+ The
+ .B ll
+ command is used to execute a single command repetitively for
+ each element of a linked list.
+ .P
+ The command specified by <cmd> will be executed with a single
+ argument, the address of the current element.
+ .SH LIMITATIONS
+ Be careful if using this command recursively.
+ .SH ENVIRONMENT
+ None.
+ .SH SMP CONSIDERATIONS
+ None.
+ .SH EXAMPLES
+ .nf
+ .na
+ .ft CW
+ # cd modules
+ # insmod kdbm_vm.o
+ # Entering kdb on processor 0 due to PAUSE
+ kdb> ps
+ Task Addr     Pid       Parent   cpu  lcpu    Tss     Command
+ 0xc03de000 0000000001 0000000000 0000 0000 0xc03de2d4 init
+ 0xc0090000 0000000002 0000000001 0000 0000 0xc00902d4 kflushd
+ 0xc000e000 0000000003 0000000001 0000 0000 0xc000e2d4 kpiod
+ 0xc000c000 0000000004 0000000001 0000 0000 0xc000c2d4 kswapd
+ 0xc7de2000 0000000056 0000000001 0000 0000 0xc7de22d4 kerneld
+ 0xc7d3a000 0000000179 0000000001 0000 0000 0xc7d3a2d4 syslogd
+ 0xc7a7e000 0000000188 0000000001 0000 0000 0xc7a7e2d4 klogd
+ 0xc7a04000 0000000199 0000000001 0000 0000 0xc7a042d4 atd
+ 0xc7b84000 0000000210 0000000001 0000 0000 0xc7b842d4 crond
+ 0xc79d6000 0000000221 0000000001 0000 0000 0xc79d62d4 portmap
+ 0xc798e000 0000000232 0000000001 0000 0000 0xc798e2d4 snmpd
+ 0xc7904000 0000000244 0000000001 0000 0000 0xc79042d4 inetd
+ 0xc78fc000 0000000255 0000000001 0000 0000 0xc78fc2d4 lpd
+ 0xc77ec000 0000000270 0000000001 0000 0000 0xc77ec2d4 sendmail
+ 0xc77b8000 0000000282 0000000001 0000 0000 0xc77b82d4 gpm
+ 0xc7716000 0000000300 0000000001 0000 0000 0xc77162d4 smbd
+ 0xc7ee2000 0000000322 0000000001 0000 0000 0xc7ee22d4 mingetty
+ 0xc7d6e000 0000000323 0000000001 0000 0000 0xc7d6e2d4 login
+ 0xc778c000 0000000324 0000000001 0000 0000 0xc778c2d4 mingetty
+ 0xc78b6000 0000000325 0000000001 0000 0000 0xc78b62d4 mingetty
+ 0xc77e8000 0000000326 0000000001 0000 0000 0xc77e82d4 mingetty
+ 0xc7708000 0000000327 0000000001 0000 0000 0xc77082d4 mingetty
+ 0xc770e000 0000000328 0000000001 0000 0000 0xc770e2d4 mingetty
+ 0xc76b0000 0000000330 0000000001 0000 0000 0xc76b02d4 update
+ 0xc7592000 0000000331 0000000323 0000 0000 0xc75922d4 ksh
+ 0xc7546000 0000000338 0000000331 0000 0000 0xc75462d4 su
+ 0xc74dc000 0000000339 0000000338 0000 0000 0xc74dc2d4 ksh
+ kdb> md 0xc74dc2d4
+ c74dc2d4: 00000000 c74de000 00000018 00000000  .....`MG........
+ c74dc2e4: 00000000 00000000 00000000 074de000  .............`M.
+ c74dc2f4: c01123ff 00000000 00000000 00000000  #.@............
+ c74dc304: 00000000 00000000 c74dded0 00000000  ........P^MG....
+ [omitted]
+ c74dc474: 00000000 00000000 00000000 00000000  ................
+ c74dc484: 00000000 c7c15d00 c77b0900 c026fbe0  .....]AG..{G`{&@
+ c74dc494: 00000000 c76c2000 00000000 00000000  ..... lG........
+ c74dc4a4: 00000000 00000000 00000000 c74dc4ac  ............,DMG
+ kdb> md 0xc026fbe0
+ c026fbe0: c0262b60 00000000 c7594940 c74de000  @HYG....@IYG.`MG
+ [omitted]
+ kdb> md 0xc0262b60
+ c0262b60: c0266660 08048000 0804c000 c7bec360  `f&@.....@..`C>G
+ kdb> ll c0262b60 12 md
+ c0262b60: c0266660 08048000 0804c000 c7bec360  `f&@.....@..`C>G
+ c7bec360: c0266660 0804c000 0804d000 c7becb20  `f&@.@...P.. K>G
+ c7becb20: c0266660 0804d000 08050000 c7bec3a0  `f&@.P...... C>G
+ c7bec3a0: c0266660 40000000 40009000 c7bec420  `f&@...@...@ D>G
+ c7bec420: c0266660 40009000 4000b000 c7bec4a0  `f&@...@.0.@ D>G
+ c7bec4a0: c0266660 4000b000 40010000 c7bec8e0  `f&@.0.@...@`H>G
+ c7bec8e0: c0266660 40010000 400a1000 c7becbe0  `f&@...@...@`K>G
+ c7becbe0: c0266660 400a1000 400a8000 c7becc60  `f&@...@...@`L>G
+ c7becc60: c0266660 400a8000 400b4000 c7952300  `f&@...@.@.@.#.G
+ c7952300: c0266660 400b5000 400bc000 c79521c0  `f&@.P.@.@.@@!.G
+ c79521c0: c0266660 400bc000 400bd000 c7bec6e0  `f&@.@.@.P.@`F>G
+ c7bec6e0: c0266660 bffff000 c0000000 00000000  `f&@.p?...@....
+ kdb>
+ kdb> ll c0262b60 12 vm
+ struct vm_area_struct at 0xc0262b60 for 56 bytes
+ vm_start = 0x8048000   vm_end = 0x804c000
+ page_prot = 0x25   avl_height = 2244    vm_offset = 0x0
+ flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE
+ struct vm_area_struct at 0xc7bec360 for 56 bytes
+ vm_start = 0x804c000   vm_end = 0x804d000
+ page_prot = 0x25   avl_height = -31808    vm_offset = 0x3000
+ flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE
+ struct vm_area_struct at 0xc7becb20 for 56 bytes
+ vm_start = 0x804d000   vm_end = 0x8050000
+ page_prot = 0x25   avl_height = -28664    vm_offset = 0x0
+ flags:  READ WRITE EXEC MAYREAD MAYWRITE MAYEXEC
+ struct vm_area_struct at 0xc7bec3a0 for 56 bytes
+ vm_start = 0x40000000   vm_end = 0x40009000
+ page_prot = 0x25   avl_height = 30126    vm_offset = 0x0
+ flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC DENYWRITE
+ struct vm_area_struct at 0xc7bec420 for 56 bytes
+ vm_start = 0x40009000   vm_end = 0x4000b000
+ page_prot = 0x25   avl_height = 30126    vm_offset = 0x8000
+ flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC DENYWRITE
+ struct vm_area_struct at 0xc7bec4a0 for 56 bytes
+ vm_start = 0x4000b000   vm_end = 0x40010000
+ page_prot = 0x25   avl_height = 26853    vm_offset = 0x0
+ flags:  READ MAYREAD MAYWRITE MAYEXEC
+ struct vm_area_struct at 0xc7bec8e0 for 56 bytes
+ vm_start = 0x40010000   vm_end = 0x400a1000
+ page_prot = 0x25   avl_height = 2244    vm_offset = 0x0
+ flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC
+ struct vm_area_struct at 0xc7becbe0 for 56 bytes
+ vm_start = 0x400a1000   vm_end = 0x400a8000
+ page_prot = 0x25   avl_height = 30126    vm_offset = 0x90000
+ flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC
+ struct vm_area_struct at 0xc7becc60 for 56 bytes
+ vm_start = 0x400a8000   vm_end = 0x400b4000
+ page_prot = 0x25   avl_height = 2244    vm_offset = 0x0
+ flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC
+ struct vm_area_struct at 0xc7952300 for 56 bytes
+ vm_start = 0x400b5000   vm_end = 0x400bc000
+ page_prot = 0x25   avl_height = 30126    vm_offset = 0x0
+ flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC
+ struct vm_area_struct at 0xc79521c0 for 56 bytes
+ vm_start = 0x400bc000   vm_end = 0x400bd000
+ page_prot = 0x25   avl_height = -16344    vm_offset = 0x6000
+ flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC
+ struct vm_area_struct at 0xc7bec6e0 for 56 bytes
+ vm_start = 0xbffff000   vm_end = 0xc0000000
+ page_prot = 0x25   avl_height = 2244    vm_offset = 0x0
+ flags:  READ WRITE EXEC MAYREAD MAYWRITE MAYEXEC GROWSDOWN
+ kdb>
diff -c -r -N console-os/Documentation/kdb/kdb_md.man console-os-kdb/Documentation/kdb/kdb_md.man
*** console-os/Documentation/kdb/kdb_md.man	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/kdb_md.man	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,125 ----
+ .TH MD 1 "25 September, 2001"
+ .SH NAME
+ md, mdWcN, mdr, mds, mm, mmW\- Memory manipulation commands
+ .SH SYNOPSIS
+ md [ \fIaddress-expression\fP [ \fIline-count\fP [\fIoutput-radix\fP ] ] ]
+ .LP
+ md\fIW\fRc\fIn\fR [ \fIaddress-expression\fP [ \fIline-count\fP [\fIoutput-radix\fP ] ] ]
+ .LP
+ mdr \fIaddress-expression\fP,\fIbytes\fP
+ .LP
+ mds [ \fIaddress-expression\fP [ \fIline-count\fP [\fIoutput-radix\fP ] ] ]
+ .LP
+ mm \fIaddress-expression\fP \fInew-contents\fP
+ .LP
+ mm\fIW\fR \fIaddress-expression\fP \fInew-contents\fP
+ .SH DESCRIPTION
+ The
+ .B md 
+ command is used to display the contents of memory.
+ The \fIaddress-expression\fP may be a numeric value (decimal or
+ hexidecimal), a symbol name, a register name preceeded by one or more
+ percent symbols '%', an environment variable name preceeded by
+ a currency symbol '$',  or a simple expression consisting of a 
+ symbol name, an addition or subtraction character and a numeric
+ value (decimal or hexidecimal).
+ .P
+ If an address is specified and the \fIline-count\fP or \fIradix\fP arguments
+ are omitted, they default to the values of the \fBMDCOUNT\fP and \fBRADIX\fP
+ environment variables respectively.  If the \fBMDCOUNT\fP or \fBRADIX\fP
+ environment variables are unset, the appropriate defaults will be used [see
+ \fBENVIRONMENT\fP below].  If no address is specified then md resumes
+ after the last address printed, using the previous values of count and
+ radix.  The start address is rounded down to a multiple of the
+ BYTESPERWORD (md) or width (md\fIW\fR).
+ .P
+ md uses the current value of environment variable \fBBYTESPERWORD\fP to
+ read the data.  When reading hardware registers that require special
+ widths, it is more convenient to use md\fIW\fRc\fIn\fR where \fIW\fR is
+ the width for this command and \fRc\fIn\fR is the number of entries to
+ read.  For example, md1c20 reads 20 bytes, 1 at a time.  To continue
+ printing just type md, the width and count apply to following md
+ commands with no parameters.  \fBNote:\fR The count is the number of
+ repeats of the width, unlike MDCOUNT which gives the number of md lines
+ to print.
+ .P
+ The
+ .B mdr
+ command displays the raw contents of memory, starting at the specified
+ address for the specified number of bytes.
+ The data is printed in one line without a leading address and no
+ trailing character conversion.
+ .B mdr
+ is intended for interfacing with external debuggers, it is of little
+ use to humans.
+ .P
+ The
+ .B mds
+ command displays the contents of memory one word per line and
+ attempts to correlate the contents of each word with a symbol
+ in the symbol table.   If no symbol is found, the ascii representation
+ of the word is printed, otherwise the symbol name and offset from
+ symbol value are printed.
+ By default the section data is printed for kernel symbols.
+ .P
+ The
+ .B mm
+ and
+ \fBmm\fIW\fR
+ commands allow modification of memory.   The bytes at the address
+ represented by \fIaddress-expression\fP are changed to 
+ \fInew-contents\fP.  \fInew-contents\fP is allowed to be an
+ \fIaddress-expression\fP.
+ .B mm
+ changes a machine word, \fBmm\fIW\fR changes \fIW\fR bytes at that
+ address.
+ .SH LIMITATIONS
+ None.
+ .SH ENVIRONMENT
+ .TP 8
+ MDCOUNT
+ This environment variable (default=8) defines the number of lines
+ that will be displayed by each invocation of the \fBmd\fP command.
+ 
+ .TP 8
+ RADIX
+ This environment variable (default=16) defines the radix used to
+ print the memory contents.  
+ 
+ .TP 8
+ BYTESPERWORD
+ This environment variable (default=4) selects the width of output
+ data when printing memory contents.  Select the value two to get
+ 16-bit word output, select the value one to get byte output.
+ 
+ .TP 8
+ LINES
+ This environment variable governs the number of lines of output 
+ that will be presented before the kernel debugger built-in pager
+ pauses the output.   This variable only affects the functioning
+ of the \fBmd\fP and \fBmds\fP if the \fBMDCOUNT\fP variable 
+ is set to a value greater than the \fBLINES\fP variable.
+ 
+ .TP 8
+ If the \fBNOSECT\fP environment variable is non-zero then the
+ section information is suppressed.
+ .SH SMP CONSIDERATIONS
+ None.
+ .SH EXAMPLES
+ .TP 8
+ md %edx
+ Display memory starting at the address contained in register \fB%edx\fP.
+ 
+ .TP 8
+ mds %esp
+ Display stack contents symbolically.   This command is quite useful
+ in manual stack traceback.
+ 
+ .TP 8
+ mm 0xc0252110 0x25
+ Change the memory location at 0xc0252110 to the value 0x25.
+ 
+ .TP 8
+ md chrdev_table 15
+ Display 15 lines (at 16 bytes per line) starting at address 
+ represented by the symbol \fIchrdev_table\fP.
diff -c -r -N console-os/Documentation/kdb/kdb.mm console-os-kdb/Documentation/kdb/kdb.mm
*** console-os/Documentation/kdb/kdb.mm	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/kdb.mm	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,406 ----
+ .TH KDB 8 "April 4, 2003"
+ .hy 0
+ .SH NAME
+ Built-in Kernel Debugger for Linux - v4.1
+ .SH "Overview"
+ This document describes the built-in kernel debugger available
+ for linux.   This debugger allows the programmer to interactively
+ examine kernel memory, disassemble kernel functions, set breakpoints
+ in the kernel code and display and modify register contents.
+ .P
+ A symbol table is included in the kernel image and in modules which
+ enables all non-stack symbols (including static symbols) to be used as
+ arguments to the kernel debugger commands.
+ .SH "Getting Started"
+ To include the kernel debugger in a linux kernel, use a
+ configuration mechanism (e.g. xconfig, menuconfig, et. al.)
+ to enable the \fBCONFIG_KDB\fP option.   Additionally, for accurate
+ stack tracebacks, it is recommended that the \fBCONFIG_FRAME_POINTER\fP
+ option be enabled (if present).   \fBCONFIG_FRAME_POINTER\fP changes the compiler
+ flags so that the frame pointer register will be used as a frame
+ pointer rather than a general purpose register.
+ .P
+ After linux has been configured to include the kernel debugger,
+ make a new kernel with the new configuration file (a make clean
+ is recommended before making the kernel), and install the kernel
+ as normal.
+ .P
+ You can compile a kernel with kdb support but have kdb off by default,
+ select \fBCONFIG_KDB_OFF\fR.  Then the user has to explicitly activate
+ kdb by booting with the 'kdb=on' flag or, after /proc is mounted, by
+ .nf
+   echo "1" > /proc/sys/kernel/kdb
+ .fi
+ You can also do the reverse, compile a kernel with kdb on and
+ deactivate kdb with the boot flag 'kdb=off' or, after /proc is mounted,
+ by
+ .nf
+   echo "0" > /proc/sys/kernel/kdb
+ .fi
+ .P
+ When booting the new kernel, the 'kdb=early' flag
+ may be added after the image name on the boot line to
+ force the kernel to stop in the kernel debugger early in the
+ kernel initialization process.  'kdb=early' implies 'kdb=on'.
+ If the 'kdb=early' flag isn't provided, then kdb will automatically be
+ invoked upon system panic or when the \fBPAUSE\fP key is used from the
+ keyboard, assuming that kdb is on.  Older versions of kdb used just a
+ boot flag of 'kdb' to activate kdb early, this is still supported but
+ is deprecated.
+ .P
+ Kdb can also be used via the serial port.  Set up the system to
+ have a serial console (see \fIDocumentation/serial-console.txt\fP), you
+ must also have a user space program such as agetty set up to read from
+ the serial console..
+ The \fBControl-A\fP key sequence on the serial port will cause the
+ kernel debugger to be entered, assuming that kdb is on, that some
+ program is reading from the serial console, at least one cpu is
+ accepting interrupts and the serial consoel driver is still usable.
+ .P
+ \fBNote:\fR\ Your distributor may have chosen a different kdb
+ activation sequence for the serial console.
+ Consult your distribution documentation.
+ .P
+ If you have both a keyboard+video and a serial console, you can use
+ either for kdb.
+ Define both video and serial consoles with boot parameters
+ .P
+ .nf
+   console=tty0 console=ttyS0,38400
+ .fi
+ .P
+ Any kdb data entered on the keyboard or the serial console will be echoed
+ to both.
+ .P
+ While kdb is active, the keyboard (not serial console) indicators may strobe.
+ The caps lock and scroll lock lights will turn on and off, num lock is not used
+ because it can confuse laptop keyboards where the numeric keypad is mapped over
+ the normal keys.
+ On exit from kdb the keyboard indicators will probably be wrong, they will not match the kernel state.
+ Pressing caps lock twice should get the indicators back in sync with
+ the kernel.
+ .SH "Basic Commands"
+ There are several categories of commands available to the
+ kernel debugger user including commands providing memory
+ display and modification, register display and modification,
+ instruction disassemble, breakpoints and stack tracebacks.
+ Any command can be prefixed with '-' which will cause kdb to ignore any
+ errors on that command, this is useful when packaging commands using
+ defcmd.
+ .P
+ The following table shows the currently implemented standard commands,
+ these are always available.  Other commands can be added by extra
+ debugging modules, type '?' at the kdb prompt to get a list of all
+ available commands.
+ .DS
+ .TS
+ box, center;
+ l | l
+ l | l.
+ Command	Description
+ _
+ bc	Clear Breakpoint
+ bd	Disable Breakpoint
+ be	Enable Breakpoint
+ bl	Display breakpoints
+ bp	Set or Display breakpoint
+ bph	Set or Display hardware breakpoint
+ bpa	Set or Display breakpoint globally
+ bpha	Set or Display hardware breakpoint globally
+ bt	Stack backtrace for current process
+ btp	Stack backtrace for specific process
+ bta	Stack backtrace for all processes
+ btc	Cycle over all live cpus and backtrace each one
+ cpu	Display or switch cpus
+ dmesg	Display system messages
+ defcmd	Define a command as a set of other commands
+ ef	Print exception frame
+ env	Show environment
+ go	Restart execution
+ help	Display help message
+ id	Disassemble Instructions
+ kill	Send a signal to a process
+ ll	Follow Linked Lists
+ lsmod	List loaded modules
+ md	Display memory contents
+ mdWcN	Display memory contents with width W and count N.
+ mdr	Display raw memory contents
+ mds	Display memory contents symbolically
+ mm	Modify memory contents, words
+ mmW	Modify memory contents, bytes
+ ps	Display process status
+ reboot	Reboot the machine
+ rd	Display register contents
+ rm	Modify register contents
+ rmmod	Remove a module
+ sections	List information on all known sections
+ set	Add/change environment variable
+ sr	Invoke SysReq commands
+ ss	Single step a cpu
+ ssb	Single step a cpu until a branch instruction
+ .TE
+ .DE
+ .P
+ Some commands can be abbreviated, such commands are indicated by a
+ non-zero \fIminlen\fP parameter to \fBkdb_register\fP; the value of
+ \fIminlen\fP being the minimum length to which the command can be
+ abbreviated (for example, the \fBgo\fP command can be abbreviated
+ legally to \fBg\fP).
+ .P
+ If an input string does not match a command in the command table,
+ it is treated as an address expression and the corresponding address
+ value and nearest symbol are shown.
+ .P
+ Some of the commands are described here.
+ Information on the more complicated commands can be found in the
+ appropriate manual pages.
+ .TP 8
+ cpu
+ With no parameters, it lists the available cpus, '*' after a cpu number
+ indicates a cpu that did not respond to the kdb stop signal.
+ .I cpu
+ followed by a number will switch to that cpu, you cannot switch to
+ a cpu marked '*'.
+ This command is only available if the kernel was configured for SMP.
+ .TP 8
+ dmesg [lines]
+ Displays the last set of system messages from the kernel buffer.  If
+ kdb logging is on, it is disabled by dmesg and is left as disabled.
+ If lines is specified, only dump the last 'lines' from the buffer, 0
+ dumps all lines.
+ .TP 8
+ defcmd
+ Defines a new command as a set of other commands, all input until
+ .I endefcmd
+ is saved and executed as a package.
+ .I defcmd
+ takes three parameters, the command name to be defined and used to
+ invoke the package, a quoted string containing the usage text and a
+ quoted string containing the help text for the command.
+ When using defcmd, it is a good idea to prefix commands that might fail
+ with '-', this ignores errors so the following commands are still
+ executed.
+ For example,
+ .P
+ .nf
+         defcmd diag "" "Standard diagnostics"
+           set LINES 2000
+           set BTAPROMPT 0
+           -id %eip-0x40
+           -cpu
+           -ps
+           -dmesg 80
+           -bt
+           -bta
+         endefcmd          
+ .fi
+ .TP 8
+ go
+ Continue normal execution.
+ Active breakpoints are reestablished and the processor(s) allowed to
+ run normally.
+ To continue at a specific address, use
+ .I rm
+ to change the instruction pointer then go.
+ .TP 8
+ id
+ Disassemble instructions starting at an address.
+ Environment variable IDCOUNT controls how many lines of disassembly
+ output the command produces.
+ .TP 8
+ kill
+ Internal command to send a signal (like kill(1)) to a process.
+ kill -signal pid.
+ .TP 8
+ lsmod
+ Internal command to list modules.
+ This does not use any kernel nor user space services so can be used at any time.
+ .TP 8
+ ps
+ Display status of all processes in the desired state.
+ This command does not take any locks (all cpus should be frozen while
+ kdb is running) so it can safely be used to debug lock problems with
+ the process table.
+ Without any parameters, \fBps\fP displays all processes.
+ If a parameter is specified, it is a single string consisting of the
+ letters D, R, S, T, Z and U, in any order.
+ Each letter selects processes in a specific state, when multiple
+ letters are specified, a process will be displayed if it is in any of
+ the specified states.
+ \fBps\ RD\fR displays only tasks that are running or are in an
+ uninterruptible sleep.
+ The states are\ :-
+ .P
+ .DS
+ .TS
+ box, center;
+ l | l
+ l | l.
+ D	Uninterruptible sleep
+ R	Running
+ S	Interruptible sleep
+ T	Traced or stopped
+ Z	Zombie
+ U	Unrunnable
+ .TE
+ .DE
+ .P
+ .TP 8
+ reboot
+ Reboot the system, with no attempt to do a clean close down.
+ .TP 8
+ rmmod
+ Internal command to remove a module.
+ This does not use any user space services, however it calls the module
+ cleanup routine and that routine may try to use kernel services.
+ Because kdb runs disabled there is no guarantee that the module cleanup
+ routine will succeed, there is a real risk of the routine hanging and
+ taking kdb with it.
+ Use the
+ .I rmmod
+ command with extreme care.
+ .TP 8
+ sections
+ List information for all known sections.  The output is one line per
+ module plus the kernel, starting with the module name.  This is
+ followed by one or more repeats of section name, section start,
+ section end and section flags.  This data is not designed for human
+ readability, it is intended to tell external debuggers where each
+ section has been loaded.
+ .SH INITIAL KDB COMMANDS
+ kdb/kdb_cmds is a plain text file where you can define kdb commands
+ which are to be issued during kdb_init().  One command per line, blank
+ lines are ignored, lines starting with '#' are ignored.  kdb_cmds is
+ intended for per user customization of kdb, you can use it to set
+ environment variables to suit your hardware or to set standard
+ breakpoints for the problem you are debugging.  This file is converted
+ to a small C object, compiled and linked into the kernel.  You must
+ rebuild and reinstall the kernel after changing kdb_cmds.  This file
+ will never be shipped with any useful data so you can always override
+ it with your local copy.  Sample kdb_cmds:
+ .P
+ .nf
+ # Initial commands for kdb, alter to suit your needs.
+ # These commands are executed in kdb_init() context, no SMP, no
+ # processes.  Commands that require process data (including stack or
+ # registers) are not reliable this early.  set and bp commands should
+ # be safe.  Global breakpoint commands affect each cpu as it is booted.
+ 
+ set LINES=50
+ set MDCOUNT=25
+ set RECURSE=1
+ bp sys_init_module
+ .fi
+ .SH INTERRUPTS AND KDB
+ When a kdb event occurs, one cpu (the initial cpu) enters kdb state.
+ It uses a cross system interrupt to interrupt the
+ other cpus and bring them all into kdb state.  All cpus run with
+ interrupts disabled while they are inside kdb, this prevents most
+ external events from disturbing the kernel while kdb is running.
+ .B Note:
+ Disabled interrupts means that any I/O that relies on interrupts cannot
+ proceed while kdb is in control, devices can time out.  The clock tick
+ is also disabled, machines will lose track of time while they are
+ inside kdb.
+ .P
+ Even with interrupts disabled, some non-maskable interrupt events will
+ still occur, these can disturb the kernel while you are debugging it.
+ The initial cpu will still accept NMI events, assuming that kdb was not
+ entered for an NMI event.  Any cpu where you use the SS or SSB commands
+ will accept NMI events, even after the instruction has finished and the
+ cpu is back in kdb.  This is an unavoidable side effect of the fact that
+ doing SS[B] requires the cpu to drop all the way out of kdb, including
+ exiting from the event that brought the cpu into kdb.  Under normal
+ circumstances the only NMI event is for the NMI oopser and that is kdb
+ aware so it does not disturb the kernel while kdb is running.
+ .P
+ Sometimes doing SS or SSB on ix86 will allow one interrupt to proceed,
+ even though the cpu is disabled for interrupts.  I have not been able
+ to track this one down but I suspect that the interrupt was pending
+ when kdb was entered and it runs when kdb exits through IRET even
+ though the popped flags are marked as cli().  If any ix86 hardware
+ expert can shed some light on this problem, please notify the kdb
+ maintainer.
+ .SH RECOVERING FROM KDB ERRORS
+ If a kdb command breaks and kdb has enough of a recovery environment
+ then kdb will abort the command and drop back into mainline kdb code.
+ This means that user written kdb commands can follow bad pointers
+ without killing kdb.  Ideally all code should verify that data areas
+ are valid (using kdb_getarea) before accessing it but lots of calls to
+ kdb_getarea can be clumsy.
+ .P
+ The sparc64 port does not currently provide this error recovery.
+ If someone would volunteer to write the necessary longjmp/setjmp
+ code, their efforts would be greatly appreciated. In the
+ meantime, it is possible for kdb to trigger a panic by accessing
+ a bad address.
+ .SH DEBUGGING THE DEBUGGER
+ kdb has limited support for debugging problems within kdb.  If you
+ suspect that kdb is failing, you can set environment variable KDBDEBUG
+ to a bit pattern which will activate kdb_printf statements within kdb.
+ See include/linux/kdb.h, KDB_DEBUG_FLAG_xxx defines.  For example
+ .nf
+   set KDBDEBUG=0x60
+ .fi
+ activates the event callbacks into kdb plus state tracing in sections
+ of kdb.
+ .nf
+   set KDBDEBUG=0x18
+ .fi
+ gives lots of tracing as kdb tries to decode the process stack.
+ .P
+ You can also perform one level of recursion in kdb.  If environment
+ variable RECURSE is not set or is 0 then kdb will either recover from
+ an error (if the recovery environment is satisfactory) or kdb will
+ allow the error to percolate, usually resulting in a dead system.  When
+ RECURSE is 1 then kdb will recover from an error or, if there is no
+ satisfactory recovery environment, it will drop into kdb state to let
+ you diagnose the problem.  When RECURSE is 2 then all errors drop into
+ kdb state, kdb does not attempt recovery first.  Errors while in
+ recursive state all drop through, kdb does not even attempt to recover
+ from recursive errors.
+ .SH KEYBOARD EDITING
+ kdb supports a command history, which can be accessed via keyboard
+ sequences.
+ It supports the special keys on PC keyboards, control characters and
+ vt100 sequences on a serial console or a PC keyboard.
+ .P
+ .DS
+ .TS
+ box, center;
+ l | l | l l | l
+ l | l | l l | l.
+ PC Special keys	Control	VT100 key	Codes	Action
+ _
+ Backspace	ctrl-H	Backspace	0x7f	Delete character to the left of the cursor
+ Delete	ctrl-D	Delete	\\e[3~	Delete character to the right of the cursor
+ Home	ctrl-A	Home	\\e[1~	Go to start of line
+ End	ctrl-E	End	\\e[4~	Go to end of line
+ Up arrow	ctrl-P	Up arrow	\\e[A	Up one command in history
+ Down arrow	ctrl-N	Down arrow	\\e[B	Down one command in history
+ Left arrow	ctrl-B	Left arrow	\\e[D	Left one character in current command
+ Right arrow	ctrl-F	Right arrow	\\e[C	Right one character in current command
+ .TE
+ .DE
+ .P
+ There is no toggle for insert/replace mode, kdb editing is always in
+ insert mode.
+ Use delete and backspace to delete characters.
+ .P
+ kdb also supports tab completion for kernel symbols
+ Type the start of a kernel symbol and press tab (ctrl-I) to complete
+ the name
+ If there is more than one possible match, kdb will append any common
+ characters and wait for more input, pressing tab a second time will
+ display the possible matches
+ The number of matches is limited by environment variable DTABCOUNT,
+ with a default of 30 if that variable is not set.
+ .SH AUTHORS
+ Scott Lurndal, Richard Bass, Scott Foehner, Srinivasa Thirumalachar,
+ Masahiro Adegawa, Marc Esipovich, Ted Kline, Steve Lord, Andi Kleen,
+ Sonic Zhang.
+ .br
+ Keith Owens <kaos@sgi.com> - kdb maintainer.
+ .SH SEE ALSO
+ .P
+ linux/Documentation/kdb/kdb_{bp,bt,env,ll,md,rd,sr,ss}.man
diff -c -r -N console-os/Documentation/kdb/kdb_rd.man console-os-kdb/Documentation/kdb/kdb_rd.man
*** console-os/Documentation/kdb/kdb_rd.man	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/kdb_rd.man	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,114 ----
+ .TH RD 1 "1 June 2003"
+ .SH NAME
+ rd, rm\- Register manipulation commands
+ .SH SYNOPSIS
+ rd [[c [n]]|d|u]
+ .LP
+ rm \fIregister-name\fP \fInew-contents\fP
+ .LP
+ ef <address>
+ .SH DESCRIPTION
+ The
+ .B rd 
+ command is used to display the contents of processor and coprocessor registers.
+ Without any arguments, the rd command displays the contents of
+ the general register set at the point at which the kernel debugger
+ was entered. 'n' argumnet is only used for XScale platform to identify
+ the want coprocessor number, while 'd' option is not valid for XScale platform.
+ .P
+ On IA32 and IA64, with the 'c' argument, the processor control registers
+ %cr0, %cr1, %cr2 and %cr4 are displayed, while with the 'd' argument
+ the processor debug registers are displayed.  If the 'u' argument
+ is supplied, the registers for the current task as of the last
+ time the current task entered the kernel are displayed.
+ .P
+ On XScale, 'c' argument is used to display the 
+ all coprocessor control registers or specified coprocessor registers by 
+ argumnet 'n'. Argument 'u' is used to display the 
+ registers for the current task as of the last time the current task
+ entered the kernel. Argument 'd' is not supported.
+ .P
+ On ix86, the
+ .B rm
+ command allows modification of a register.  The following 
+ register names are valid:  \fB%eax\fP, \fB%ebx\fP, \fB%ecx\fP,
+ \fB%edx\fP, \fB%esi\fP, \fB%edi\fP, \fB%esp\fP, \fB%eip\fP, 
+ and \fB%ebp\fP.   Note that if two '%' symbols are used 
+ consecutively, the register set displayed by the 'u' argument
+ to the \fBrd\fP command is modified.
+ .P
+ The debug registers, \fBdr0\fP through \fBdr3\fP and both
+ \fBdr6\fP and \fBdr7\fP can also be modified with the \fBrm\fP
+ command.
+ .P
+ On sparc64, the valid registers are named \fB%g0\fP through
+ \fB%g7\fP, \fB%l0\fP through \fB%l7\fP, \fB%o0\fP through
+ \fB%o7\fP, and \fB%i0\fP through \fB%i7\fP, with the exceptions
+ that \fB%o6\fP is called \fB%sp\fP and that \fB%i6\fP is called
+ \fB%fp\fP. The registers \fB%tstate\fP, \fB%tpc\fP, \fB%tnpc\fP,
+ \fB%y\fP, and \fB%fprs\fP provide state information at the time
+ the system entered kdb. Additionally, when viewing registers, two
+ convenience names are provided: \fB%&regs\fP shows the
+ address on the stack of the current registers, and \fB%csp\fP
+ shows the current stack pointer within kdb itself.
+ .P
+ While on XScale, both the cpu registers and most coprocessor
+ registers can be be modified. \fIregister-name\fP can be followings like
+ r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14,
+ r15, cpsr to address  cpu registers. For the coprocessor registers in XSacle,
+ either alias name or \fICpcc[CRndd[CRmbb[Opaa]]]\fP can be used to address
+ the register in coprocessor cc with CRn=dd, CRm=bb and opcode2=aa. All aa, bb, cc, dd can be 
+ 1 or 2 decimal digitals, the default value is 0 when any of them is omitted. Name 
+ acc0_h and acc0_l are used to identify the high byte and
+ low word of accumulator in coprocessor 0.
+ .P
+ The
+ .B ef
+ command displays an exception frame at the specified address.
+ .SH LIMITATIONS
+ Currently the \fBrm\fP command will not allow modification of the
+ control registers.
+ .P
+ Currently neither the \fBrd\fP command nor the \fBrm\fP command will
+ display or modify the model specific registers on the Pentium
+ and Pentium Pro families.
+ .SH ENVIRONMENT
+ None.
+ .SH SMP CONSIDERATIONS
+ None.
+ .SH EXAMPLES
+ .TP 8
+ rd
+ Display general register set.
+ 
+ .TP 8
+ rd c 0
+ Display coprocessor 0 registers.
+ 
+ .TP 8
+ rm %eax 0
+ Set the contents of \fB%eax\fP to zero.  This will be the
+ value of %eax when kdb returns from the condition which 
+ invoked it.
+ 
+ .TP 8
+ rm %%eax 0
+ Set the value of the \fB%eax\fP register to zero.  This will
+ be the value the user-mode application will see upon returning
+ from the kernel.
+ 
+ .TP 8
+ rm %acc0_h 0
+ Set the contents of high byte of accumulator to zero.
+ 
+ .TP 8
+ rm dr0 0xc1287220
+ Set the value of the \fBdr0\fB register to \f(CW0xc1287220\fP.
+ 
+ .TP 8
+ rm %InVLD_BTB 0
+ Write 0 to coprocessor 15 register with CRn=7, CRm=5, opcode2=6.
+ 
+ .TP 8
+ rm %CP15CRn7CRm5Op6 0
+ Same with above.
diff -c -r -N console-os/Documentation/kdb/kdb_sr.man console-os-kdb/Documentation/kdb/kdb_sr.man
*** console-os/Documentation/kdb/kdb_sr.man	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/kdb_sr.man	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,68 ----
+ .TH SR 1 "7 October 2002"
+ .SH NAME
+ sr \- invoke sysrq commands from kdb
+ .SH SYNOPSIS
+ sr \fIx\fP
+ .SH DESCRIPTION
+ .hy 0
+ The
+ .B sr 
+ command invokes the existing sysrq handler code in the kernel.
+ This command takes a single character which is passed to sysrq
+ processing, as if you had entered the sysrq key sequence followed by
+ that character.
+ .P
+ .B Caveats:
+ .P
+ kdb will always call the sysrq code but sysrq may be disabled.
+ If you expect to use sysrq functions during debugging then
+ .IP ""
+ echo "1" > /proc/sys/kernel/sysrq
+ .P
+ before starting the debug session.
+ Alternatively issue
+ .IP ""
+ mm4 sysrq_enabled 1
+ .P
+ during debugging.
+ .P
+ The sysrq code prints a heading using console loglevel 7 then reverts
+ to the original loglevel for the rest of the sysrq processing.
+ If the rest of the sysrq output is printed at a level below your
+ current loglevel then you will not see the output on the kdb console,
+ the output will only appear in the printk buffer.
+ It is the user's responsibility to set the loglevel correctly if they
+ want to see the sysrq output on the console.
+ Issue
+ .IP ""
+ sr 7
+ .P
+ before any other
+ .B sr
+ commands if you want to see the output on the console.
+ You may even have to adjust the default message loglevel in order to
+ see any output from
+ .BR sr .
+ See Documentation/sysctl/kernel.txt for details on setting console
+ loglevels via /proc.
+ You can also adjust the loglevel variables via kdb
+ .BR mm ;
+ on older kernels there are variables such as default_message_level, on
+ newer kernels all the loglevel variables are in array console_printk,
+ see kernel/printk.c for your kernel.
+ .P
+ Operations that require interrupt driven I/O can be invoked from kdb
+ .BR sr ,
+ but they will not do anything until you type 'go' to exit from kdb
+ (interrupts are disabled while in kdb).
+ There is no guarantee that these operations will work, if the machine
+ entered kdb because of an error then interrupt driven I/O may already
+ be dead.
+ Do not assume that
+ .B sr\ s
+ does anything useful.
+ .P
+ The sysrq handler uses locks and calls printk which also uses locks.
+ If the sysrq handler or any of the sysrq functions have to wait for a
+ lock then they will never return and kdb will appear to hang.
+ Invoking sysrq code from kdb is inherently unsafe.
diff -c -r -N console-os/Documentation/kdb/kdb_ss.man console-os-kdb/Documentation/kdb/kdb_ss.man
*** console-os/Documentation/kdb/kdb_ss.man	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/kdb_ss.man	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,109 ----
+ .TH SS 1 "17 January 2002"
+ .SH NAME
+ ss, ssb \- Single Step 
+ .SH SYNOPSIS
+ ss
+ .LP
+ ssb 
+ .SH DESCRIPTION
+ The
+ .B ss
+ command is used to execute a single instruction and return
+ to the kernel debugger.
+ .P
+ Both the instruction that was single-stepped and the next
+ instruction to execute are printed. 
+ .P
+ The \fBssb\fP command will execute instructions from the
+ current value of the instruction pointer.  Each instruction
+ may be printed as it is executed, depending upon architecture;
+ execution will stop at any instruction which would cause the flow 
+ of control to change (e.g. branch, call, interrupt instruction, 
+ return, etc.)
+ .SH LIMITATIONS
+ On sparc64, there are some circumstances where single-stepping
+ can be dangerous. Do not single-step across an instruction which
+ changes the interrupt-enable bit in %tstate. Do not single step
+ through code which is invoked when entering or leaving the
+ kernel, particularly any kernel entry code before %tl is set to
+ 0, or any kernel exit code after %tl is set to 1.
+ .SH ENVIRONMENT
+ None.
+ .SH SMP CONSIDERATIONS
+ Other processors are held in the kernel debugger when the instruction
+ is traced.  Single stepping though code that requires a lock which is
+ in use by another processor is an exercise in futility, it will never
+ succeed.
+ .SH INTERRUPT CONSIDERATIONS
+ When a kdb event occurs, one cpu (the initial cpu) enters kdb state.
+ It uses a cross system interrupt to interrupt the
+ other cpus and bring them all into kdb state.  All cpus run with
+ interrupts disabled while they are inside kdb, this prevents most
+ external events from disturbing the kernel while kdb is running.
+ .B Note:
+ Disabled interrupts means that any I/O that relies on interrupts cannot
+ proceed while kdb is in control, devices can time out.  The clock tick
+ is also disabled, machines will lose track of time while they are
+ inside kdb.
+ .P
+ Even with interrupts disabled, some non-maskable interrupt events
+ will still occur, these can disturb the kernel while you are
+ debugging it.  The initial cpu will still accept NMI events,
+ assuming that kdb was not entered for an NMI event.  Any cpu
+ where you use the SS or SSB commands will accept NMI events, even
+ after the instruction has finished and the cpu is back in kdb.
+ This is an unavoidable side effect of the fact that doing SS[B]
+ requires the cpu to drop all the way out of kdb, including
+ exiting from the NMI event that brought the cpu into kdb.  Under
+ normal circumstances the only NMI event is for the NMI oopser and
+ that is kdb aware so it does not disturb the kernel while kdb is
+ running.
+ .P
+ Sometimes doing SS or SSB on ix86 will allow one interrupt to proceed,
+ even though the cpu is disabled for interrupts.  I have not been able
+ to track this one down but I suspect that the interrupt was pending
+ when kdb was entered and it runs when kdb exits through IRET even
+ though the popped flags are marked as cli().  If any ix86 hardware
+ expert can shed some light on this problem, please notify the kdb
+ maintainer.
+ .SH EXAMPLES
+ .nf
+ .na
+ .ft CW
+ kdb> bp gendisk_head datar 4
+ Data Access Breakpoint #0 at 0xc024ddf4 (gendisk_head) in dr0 is enabled on cpu 0
+ for 4 bytes
+ kdb> go
+ ...
+ [root@host /root]# cat /proc/partitions
+ Entering kdb on processor 0 due to Debug Exception @ 0xc01845e3
+ Read/Write breakpoint #0 at 0xc024ddf4
+ [0]kdb> ssb
+ sd_finish+0x7b:  movzbl 0xc02565d4,%edx
+ sd_finish+0x82:  leal   0xf(%edx),%eax
+ sd_finish+0x85:  sarl   $0x4,%eax
+ sd_finish+0x88:  movl   0xc0256654,%ecx
+ sd_finish+0x8e:  leal   (%eax,%eax,4),%edx
+ sd_finish+0x91:  leal   (%eax,%edx,2),%edx
+ sd_finish+0x94:  movl   0xc0251108,%eax
+ sd_finish+0x99:  movl   %eax,0xffffffc(%ecx,%edx,4)
+ sd_finish+0x9d:  movl   %ecx,0xc0251108
+ sd_finish+0xa3:  xorl   %ebx,%ebx
+ sd_finish+0xa5:  cmpb   $0x0,0xc02565d4
+ [0]kdb> go
+ [root@host /root]# 
+ 
+ [0]kdb> ss
+ sys_read:   pushl  %ebp
+ SS trap at 0xc01274c1
+ sys_read+0x1:   movl   %esp,%ebp
+ [0]kdb> ss
+ sys_read+0x1:   movl   %esp,%ebp
+ SS trap at 0xc01274c3
+ sys_read+0x3:   subl   $0xc,%esp
+ [0]kdb> ss
+ sys_read+0x3:   subl   $0xc,%esp
+ SS trap at 0xc01274c6
+ sys_read+0x6:   pushl  %edi
+ [0]kdb>
+ 
diff -c -r -N console-os/Documentation/kdb/slides console-os-kdb/Documentation/kdb/slides
*** console-os/Documentation/kdb/slides	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/Documentation/kdb/slides	2007-01-10 14:02:18.000000000 -0800
***************
*** 0 ****
--- 1,1383 ----
+ #! /opt/cpg/bin/do-mgp
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %%
+ %deffont "standard" tfont "comic.ttf"
+ %deffont "thick" tfont "arialb.ttf"
+ %deffont "typewriter" xfont "courier new-bold-r"
+ %deffont "type2writer" xfont "arial narrow-bold-r"
+ %%
+ %% Default settings per each line numbers.
+ %%
+ #%default 1 leftfill, size 2, fore "black", back "LemonChiffon2", font "thick"
+ %default 1 leftfill, size 2, fore "black", back "white", font "thick"
+ %default 2 size 10, vgap 10, prefix " ", center
+ %default 3 size 2, bar "gray70", vgap 10
+ %default 4 size 6, fore "black", vgap 30, prefix " ", font "standard", left
+ %%
+ %% Default settings that are applied to TAB-indented lines.
+ %%
+ %tab 1 size 4, vgap 35, prefix "  ", icon arc "red" 40
+ %tab 2 size 4, vgap 20, prefix "      ", icon delta3 "blue" 40
+ %tab 3 size 4, vgap 20, prefix "            ", icon delta3 "green" 40 
+ %%
+ %%
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ KDB - Kernel Debugger
+ 
+ 
+ 
+ %size 7,center, font "thick"
+ Introduction
+ 
+ And 
+ 
+ Demonstration
+ 
+ 
+ %size 3
+ 
+ February 5, 2002                                   IBM Linux Technology Center                                   Paul Dorwin
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ IBM Legal 
+ 
+ 
+ 	IBM Legal requires this information:
+ 
+ %size 3 
+ 
+         THE INFORMATION IN THE FOLLOWING PRESENTATION IS PREPARED 
+         SOLELY FOR THE INFORMATION OF THE READER, AND COMES "AS IS"
+         AND WITHOUT WARRANTY OR REPRESENATION OF ANY KIND.  
+ 
+         ANY PARTY USING THE MATERIALS IN THIS PRESENTATION DOES SO 
+         AT ITS OWN RISK LIABILITY AND THE PROVIDER OF THE MATERIALS 
+         ACCEPTS NO RISK OR LIABILITY FOR SUCH USE OR RESULTING FROM 
+         DISSEMINATION TO OR USE BY ANY OTHER PARTY
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Agenda
+ 
+ %size 5
+ 
+         Installing and Configuring KDB
+ 
+         KDB Commands
+ 
+         Scull Demo
+ 
+                 Setting Breakpoints 
+ 
+                 Displaying Data Structures
+ 
+         Kernel Data structures
+ 
+                 Take a walk through an IO operation
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Installing Configuring KDB
+ 
+ 
+ 	Install KDB patch.
+ 		Start with a clean source tree
+ 		Apply architecture specific patches
+ 		Obtain patch for your kernel version
+ 			see http://oss.sgi.com/projects/kdb/
+ 		Apply the kdb patch
+ 			patch -p 1 -N -u -i /path/to/patch
+ 		Apply any other patches
+ 		Build and reboot on your kdb enabled kernel
+ 		Man pages can be found at Documentation/kdb
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Configuring KDB
+ 
+ 
+ 	Config kernel with the following options:
+ 		These are documented in Documentation/Configure.help
+ 
+ 		CONFIG_KDB=y
+ 			Enable compilation of KDB in the kernel..
+ 			Setting this also sets CONFIG_KALLSYMS=y.
+ 		CONFIG_KDB_MODULES=n
+ 			KDB may be extended, compiling kdb/modules.
+ 		CONFIG_KDB_OFF=n
+ 			y = KDB is disabled  by default. 
+ 			boot with kdb=on to enable at boot.
+ 			/proc/sys/kernel/kdb to enable/disable when system is up.
+ 		CONFIG_KALLSYMS=y
+ 			This causes all symbols to be exported.
+ 		CONFIG_FRAME_POINTER=y
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Invoking KDB
+ 
+ 
+ 	KDB can be invoked in the following ways:
+ 
+ 		Early init with "kdb=early" lilo flag 
+ 			Hits breakpoint prior to fork_init() (init/main.c)
+ 
+ 		Serial console with CNTRL-A
+ 
+ 		Console with PAUSE key 
+ 
+ 		When a pre-set breakpoint is hit
+ 
+ 		On panic
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ KDB Commands
+ 
+ 
+ 	KDB environment
+ 		env				Show environment variables
+ 		set				Set environment variables
+ 		help			Display Help Message
+ 		?				Display Help Message
+ 
+ 	System related
+ 		sections			List kernel and module sections
+ 		lsmod			List loaded kernel modules
+ 		rmmod	<modname>	Remove a kernel module
+ 		reboot			Reboot the machine immediately
+ 		cpu		<cpunum>	Switch to new cpu
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ KDB Commands
+ 
+ 
+ 	Memory Manipulation
+ 		md		<vaddr>		Display Memory Contents
+ 		mdr	<vaddr> <bytes>	Display Raw Memory
+ 		mds	<vaddr>		Display Symbolically
+ 		mm	<vaddr> <value>	Modify Memory Contents
+ 		id		<vaddr>		Display Instructions
+ 
+ 	Register Manipulation
+ 		rd				Display Registers
+ 		rm		<reg> <value> 	Modify Registers
+ 		ef		 <vaddr>		Display exception frame
+ 
+ 	Stack
+ 		bt		[<vaddr>]	Stack traceback
+ 		btp		 <pid>		Display stack for <pid>
+ 		bta				Display all stacks
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ KDB Commands
+ 
+ 
+ 	Breakpoint
+ 		bc		 <bpnum>	Clear Breakpoint
+ 		bd		 <bpnum>	Disable Breakpoint
+ 		be		 <bpnum>	Enable Breakpoint
+ 		bl		[<vaddr>]	Display breakpoints
+ 		bp		[<vaddr>]	Set/Display breakpoints
+ 		bpa		[<vaddr>]	Set/Display global breakpoints
+ 		bph	[<vaddr>]	Set hardware breakpoint
+ 		bpha	[<vaddr>]	Set global hardware breakpoint
+ 		bp* modifiers:
+ 			instruction - break on instruction fetch (default)
+ 			datar - break on read  at vaddr
+ 			dataw - break on write at vaddr
+ 			IO - break on in or out op at vaddress
+ 
+ 	Execution control
+ 		go		  [<vaddr>]	Continue Execution
+ 		ss  		  [<#steps>]	Single Step
+ 		ssb				Single step to branch/call
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ KDB Commands
+ 
+ 
+ 	Kernel structures
+ 		ll <vaddr> <offset> <command>	Traverse list and execute command 
+ 		ps				Display active task list
+ 		vm		<vaddr>		Display vm_area_struct
+ 		dentry	<dentry>		Display interesting dentry stuff
+ 		filp		<filp>		Display interesting filp stuff
+ 		sh		<vaddr>		Show scsi_host
+ 		sd		<vaddr>		Show scsi_device
+ 		sc		<vaddr>		Show scsi_cmnd
+ 		kiobuf	<vaddr>		Display kiobuf
+ 		page	<vaddr>		Display page
+ 		inode	<vaddr>		Display inode
+ 		bh		<vaddr>		Display buffer head 
+ 		inode_pages	<inode *>	Display pages in an inode
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo
+ 
+ 
+ 	Objective
+ 		Find and display the data associated with a scull device
+ 
+ 	The sequence of events
+ 		Populate the scull device with data
+ 		Identify the breakpoints
+ 		Set breakpoint in the device read function
+ 		Identify the data structure elements
+ 		Identify device structures used to track data
+ 		Display data structures containing the data
+ 		Show the usage of the filp command
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo: Populate Device
+ 
+ 
+ 	Obtain the code
+ 		Surf to http://examples.oreilly.com/linuxdrive2/
+ 		Download the tarball
+ 		Untar it to /usr/src
+ 
+ 	Build and install the module
+ 		cd /usr/src/ldd2-samples-1.0.1/scull
+ 		make
+ 		./scull.init start
+ 
+ 	Populate the scull device
+ 		cat main.c > /dev/scull0
+ 		cat /dev/scull0
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo: Driver Details
+ 
+ 
+ 	cat /dev/scull0
+ 		fd = 
+ %fore "blue", cont
+ open
+ %fore "black", cont
+ ("/dev/scull0", O_RDONLY);
+ 			Kernel finds the file_operations structure
+ 			Kernel then invokes the open function
+ %fore "blue"
+ 		read
+ %fore "black", cont
+ (fd, buf, size);
+ 			Kernel finds the file_operations structure
+ 			Kernel then invokes the read function
+ 
+ 	Scull device file operations structure
+ 
+ %font "typewriter", size 3
+     struct file_operations scull_fops = {
+         llseek:     scull_llseek,
+ %fore "blue"
+         read:       scull_read,
+ %fore "black"
+         write:      scull_write,
+         ioctl:      scull_ioctl,
+ %fore "blue"
+         open:       scull_open,
+ %fore "black"
+         release:    scull_release,
+     };
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo: Driver Details
+ 
+ %font "typewriter", size 3
+ 	scull_open code
+ %font "typewriter", size 3
+     int 
+ %fore "blue", cont
+ scull_open
+ %fore "black", cont
+ (struct inode *inode, struct file *filp)
+     {
+         Scull_Dev *dev; /* device information */
+         int num = NUM(inode->i_rdev);
+ 
+         <snip>
+ 
+         dev = (Scull_Dev *)filp->private_data;
+         if (!dev) {
+             if (num >= scull_nr_devs) return -ENODEV;
+ %fore "blue"
+             dev = &scull_devices[num];
+             filp->private_data = dev;
+ %fore "black"
+         }
+ 
+         <snip>
+ 
+     }
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo: Driver Details
+ 
+ %font "typewriter", size 3
+ 	scull_read code
+ %font "typewriter", size 3
+     ssize_t 
+ %fore "blue", cont
+ scull_read
+ %fore "black", cont
+ (struct file *filp, char *buf, size_t count,
+             loff_t *f_pos)
+     {
+ 
+ %fore "blue", cont
+         Scull_Dev *dev = filp->private_data;
+ %fore "black", cont
+  /* the first listitem */
+ %fore "blue"
+         Scull_Dev *dptr;
+ %fore "black"
+         int quantum = dev->quantum;
+         int qset = dev->qset;
+         int itemsize = quantum * qset;
+         if (down_interruptible(&dev->sem))
+                 return -ERESTARTSYS;
+         if (*f_pos + count > dev->size)
+             count = dev->size - *f_pos;
+ 
+         /* find listitem, qset index, and offset in the quantum */
+         item = (long)*f_pos / itemsize;
+         rest = (long)*f_pos % itemsize;
+         s_pos = rest / quantum; q_pos = rest % quantum;
+ 
+         /* follow the list up to the right position */
+ %fore "blue"
+         dptr = scull_follow(dev, item);
+ %fore "black"
+ 
+         <snip>
+ 
+     }
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo: Breakpoints
+ 
+ 
+ %font "typewriter", size 3
+ 	Determine where to set breakpoint
+ %font "typewriter", size 3
+ %fore "blue"
+         dptr = scull_follow(dev, item);
+ %fore "black"
+ 
+ %font "typewriter", size 3
+ 	Disassemble scull_read
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue", cont
+ id scull_read
+ %fore "black"
+     0xf8c083b4 scull_read:  push   %ebp
+     0xf8c083b5 scull_read+0x1:mov    %esp,%ebp
+     0xf8c083b7 scull_read+0x3:push   %edi
+             <snip>
+     0xf8c08465 scull_read+0xb1:sub    $0x8,%esp
+ %fore "blue"
+     0xf8c08468 scull_read+0xb4:push   %ecx
+     0xf8c08469 scull_read+0xb5:push   %esi
+     0xf8c0846a scull_read+0xb6:call   0xf8c08364 scull_follow: 
+ %fore "black"
+     0xf8c0846f scull_read+0xbb:mov    %eax,
+ %fore "blue", cont
+  %edx 
+ %fore "black"
+     0xf8c08471 
+ %fore "blue", cont
+ scull_read+0xbd
+ %fore "black", cont
+ :add    $0x10,%esp
+             <snip>
+ 
+ 	Set breakpoint in driver read
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue",cont
+ bp scull_read+0xbd
+ %fore "black"
+     Instruction(i) BP #0 at 0xf8c08471 ([scull]scull_read+0xbd)
+         is enabled globally adjust 1
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo: Breakpoints
+ 
+ 
+ %font "typewriter", size 3
+ 	Restart the system
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue", cont
+ go
+ %fore "black"
+ 
+ 	Hit the Breakpoint
+ %font "typewriter", size 3
+     [root@elm3b77 root]# 
+ %fore "blue", cont
+ cat /dev/scull0
+ %fore "black"
+     Instruction(i) breakpoint #0 at 0xf8c08471 (adjusted)
+     0xf8c08471 scull_read+0xbd:int3   
+     Entering kdb (current=0xf73ec000, pid 1249) on processor 2 
+                   due to Breakpoint @ 0xf8c08471
+ 
+ 	Display the registers
+ %font "typewriter", size 3
+     [2]kdb> 
+ %fore "blue", cont
+ rd
+ %fore "black"
+     eax = 0xf77d7b60 ebx = 0x00000000 ecx = 0x00000000 edx = 
+ %fore "blue", cont
+ 0xf77d7b60
+ %fore "black"
+     esi = 
+ %fore "blue", cont
+ 0xf77d7b60
+ %fore "black", cont
+  edi = 0x00001000 esp = 0xf7415f40 eip = 0xf8c08471 
+     ebp = 0xf7415f78 xss = 0x00000018 xcs = 0x00000010 eflags = 0x00000246
+     xds = 0xf7590018 xes = 0x00000018 origeax = 0xffffffff &regs = 0xf7415f0c
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo: Data Structures
+ 
+ %font "typewriter", size 3
+ 	Display the Scull_Dev structure 
+ %font "typewriter", size 3
+     [2]kdb> 
+ %fore "blue", cont
+ md 0xf77d7b60 2
+ %fore "black"
+     0xf77d7b60 
+ %fore "blue", cont
+ f7400000
+ %fore "black", cont
+  00000000 00000fa0 000003e8   ..@w.... ...h...
+     0xf77d7b70 0000534e 00000000 00000000 00000000   NS..............
+ 
+ 	Scull Device Structure
+ %font "typewriter", size 3
+     typedef struct Scull_Dev {
+ %fore "blue"
+        void **data;
+ %fore "black"
+        struct Scull_Dev *next;   /* next listitem */
+        int quantum;              /* the current quantum size */
+        int qset;                 /* the current array size */
+        unsigned long size;
+        devfs_handle_t handle;    /* only used if devfs is there */
+        unsigned int access_key;  /* used by sculluid and scullpriv */
+        struct semaphore sem;     /* mutual exclusion semaphore     */
+     } Scull_Dev;
+ %size 6
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo: Data Structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Display the quantum set (dev->data)
+ %font "typewriter", size 3
+     [2]kdb> 
+ %fore "blue", cont
+ md f7400000 2
+ %fore "black"
+     0xf7400000 
+ %fore "blue", cont
+ f73ea000
+ %fore "black", cont
+  f73f1000 f740c000 f7ab4000   . >w..?w.@@w.@+w
+     0xf7400010 f73ef000 f755b000 00000000 00000000   .p>w.0Uw........
+ 
+ 	Display the first quantum (dev->data[0])
+ %font "typewriter", size 3
+     [2]kdb> 
+ %fore "blue", cont
+ md f73ea000
+ %fore "black"
+     0xf73ea000 200a2a2f 616d202a 632e6e69 202d2d20   /*. * main.c -- 
+     0xf73ea010 20656874 65726162 75637320 63206c6c   the bare scull c
+     0xf73ea020 20726168 75646f6d 200a656c 2a200a2a   har module. *. *
+     0xf73ea030 706f4320 67697279 28207468 32202943    Copyright (C) 2
+     0xf73ea040 20313030 73656c41 646e6173 52206f72   001 Alessandro R
+     0xf73ea050 6e696275 6e612069 6f4a2064 6874616e   ubini and Jonath
+     0xf73ea060 43206e61 6562726f 2a200a74 706f4320   an Corbet. * Cop
+     0xf73ea070 67697279 28207468 32202943 20313030   yright (C) 2001 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo: filp command
+ 
+ 
+ %font "typewriter", size 3
+ 	Show filp usage - here is the scull_read prototype
+ %font "typewriter", size 3
+     ssize_t scull_read(
+ %fore "blue", cont
+ struct file *filp
+ %fore "black", cont
+ , char *buf, 
+                        size_t count, loff_t *f_pos);
+ 	Show the stack trace:
+ %font "typewriter", size 3
+ [2]kdb> 
+ %fore "blue", cont
+ bt
+ %fore "black"
+     EBP       EIP         Function(args)
+     0xee9dbf78 0xf8c08471 [scull]scull_read+0xbd (
+ %fore "blue", cont
+ 0xeaf6c0c0
+ %fore "black", cont
+ , 0x804e128, 
+                                           0x1000, 0xeaf6c0e0, 0x804f000)
+                      scull .text 0xf8c08060 0xf8c083b4 0xf8c084dc
+     0xee9dbfbc 0xc0136278 sys_read+0x98 (0x3, 0x804e128, 0x1000, ...
+                      kernel .text 0xc0100000 0xc01361e0 0xc01362b0
+                0xc010702b system_call+0x33
+                      kernel .text 0xc0100000 0xc0106ff8 0xc0107030
+ 	And show the filp output
+ %font "typewriter", size 3
+     [2]kdb> 
+ %fore "blue", cont
+ filp 0xeaf6c0c0
+ %fore "black"
+     name.name 0xe93889fc  name.len  6
+     File Pointer at 0xeaf6c0c0
+      f_list.nxt = 0xe42deca0 f_list.prv = 0xf7e69070
+ %fore "blue"
+      f_dentry = 0xe93889a0
+ %fore "black", cont
+  f_op = 0xf8c0a200
+      f_count = 2 f_flags = 0x8000 f_mode = 0x1
+      f_pos = 0 f_reada = 0 f_ramax = 0
+      f_raend = 0 f_ralen = 0 f_rawin = 0
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Scull Demo: filp command
+ 
+ 
+ %font "typewriter", size 3
+ 	filp output - continued
+ %font "typewriter", size 3
+ %fore "blue"
+     Directory Entry at 0xe93889a0
+ %fore "black"
+      d_name.len = 6 
+ %fore "orange", cont
+ d_name.name = 0xe93889fc
+ %fore "black", cont
+ >
+      d_count = 1 d_flags = 0x0 
+ %fore "blue", cont
+ d_inode = 0xe827b680
+ %fore "black"
+      d_hash.nxt = 0xc215aec8 d_hash.prv = 0xc215aec8
+      d_lru.nxt = 0xe93889b8 d_lru.prv = 0xe93889b8
+      d_child.nxt = 0xe89e1e80 d_child.prv = 0xe9388940
+      d_subdirs.nxt = 0xe93889c8 d_subdirs.prv = 0xe93889c8
+      d_alias.nxt = 0xe827b690 d_alias.prv = 0xe827b690
+      d_op = 0x00000000 d_sb = 0xf7e69000
+ 
+ %fore "blue"
+     Inode Entry at 0xe827b680
+ %fore "black"
+      i_mode = 0x21a4  i_nlink = 1  i_rdev = 0xfe00
+      i_ino = 37182 i_count = 1 i_dev = 0x821
+      i_hash.nxt = 0xc20e6be8 i_hash.prv = 0xc20e6be8
+      i_list.nxt = 0xe827b2c8 i_list.prv = 0xe827b868
+      i_dentry.nxt = 0xe93889d0 i_dentry.prv = 0xe93889d0
+ 
+ 	Check the filename (display d_name.name)
+ %font "typewriter", size 3
+     [2]kdb> 
+ %fore "orange", cont
+ md 0xe93889fc 1
+ %fore "black"
+     0xe93889fc 6c756373 0000306c 00000000 00000000   scull0..........
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Kernel Structures
+ 
+ 
+ 	Objective
+ 		Show output from various kernel related kdb commands
+ 
+ 	Sequence of events
+ 		Simple Program
+ 			Write a simple program which allocates memory and hangs
+ 			Show usage of the ps, vm, and ll commands
+ 		Walk an IO operation
+ 			Hit a breakpoint in qlogic driver (isp1020_queuecommand)
+ 			Show usage of scsi related commands (sc, sh, and sd)
+ 			Show usage of vm related commands (bh, page, inode, inode_pages)
+ 
+ 
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Simple program
+ 
+ %font "typewriter", size 3
+ 	simple.c - simple program which allocates memory
+ %font "typewriter", size 3
+ %fore "blue"
+     int foo_global[8192];
+ %fore "black"
+     main()
+     {
+         int *
+ %fore "blue", cont
+ foo_malloc;
+ %fore "black"
+         int i;
+         foo_malloc = (int *)malloc(0x8192);
+         for(i = 0; i < 0x100; i++) {
+             foo_global[i] = 0xdead0000 | i;
+             foo_malloc[i] = 0xbeef0000 | i;
+         }
+         printf("foo_global at %x\n", (int)foo_global);
+         printf("foo_malloc at %x\n", (int)foo_malloc);
+         printf("sleep forever\n");
+         sleep(2000000);
+     }
+ 
+ 	simple output
+ %font "typewriter", size 3
+     [root@elm3b77 scull]# cc -o simple simple.c
+     [root@elm3b77 scull]# ./simple
+     foo_global at 
+ %fore "blue", cont
+ 8049780
+ %fore "black"
+     foo_malloc at 
+ %fore "blue", cont
+ 8051788
+ %fore "black"
+     sleep forever
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Simple Program
+ 
+ %font "typewriter", size 3
+ 	Show the output of the ps command
+ %font "typewriter", size 3
+     Entering kdb (current=0xc2010000, pid 0) on processor 3 due to
+                                              Keyboard Entry
+     [3]kdb> 
+ %fore "blue", cont
+ ps
+ %fore "black"
+     Task Addr  Pid      Parent   [*] cpu  State Thread     Command
+     0xf7efe000 00000001 00000000  0  003  stop  0xf7efe370 init
+     0xf7ef0000 00000002 00000001  0  001  stop  0xf7ef0370 keventd
+     0xf7eec000 00000003 00000000  0  000  stop  0xf7eec370 ksoftirqd_CPU0
+     0xf7eea000 00000004 00000000  0  001  stop  0xf7eea370 ksoftirqd_CPU1
+     0xf7ee8000 00000005 00000000  0  002  stop  0xf7ee8370 ksoftirqd_CPU2
+     0xf7ee6000 00000006 00000000  0  003  stop  0xf7ee6370 ksoftirqd_CPU3
+ 
+                          <snip>
+ 
+     0xf7b46000 00001006 00000737  0  003  stop  0xf7b46370 sshd
+     0xf7ace000 00001007 00001006  0  000  stop  0xf7ace370 bash
+     0xef06a000 00001066 00001007  0  003  stop  0xef06a370 su
+     0xeef88000 00001067 00001066  0  000  stop  0xeef88370 bash
+     0xeef64000 00001119 00000770  0  001  stop  0xeef64370 in.ftpd
+ %fore "blue"
+     0xeeeac000
+ %fore "black", cont
+  00001138 00001067  0  001  stop  0xeeeac370 
+ %fore "blue", cont
+ simple
+ %fore "black"
+     [3]kdb>
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Simple Program
+ 
+ %font "typewriter", size 3
+ 	Display the task struct
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ md 0xeeeac000
+ %fore "black"
+     0xeeeac000 00000001 00000000 00000000 c0000000   ................
+     0xeeeac010 c0339880 00000000 00000000 ffffffff   ................
+     0xeeeac020 0000000a 00000000 00000000 
+ %fore "blue", cont
+ f7e10f00
+ %fore "black", cont
+    ..............aw
+     0xeeeac030 00000001 ffffffff ffffffff 00000000   ................
+ 
+ %font "typewriter", size 3
+ 	Determine offset of mm_struct ptr in task_struct
+ %font "typewriter", size 3
+     struct task_struct {
+       [0]   volatile long state;      
+       [4]   unsigned long flags;      
+       [8]   int sigpending;
+       [c]   mm_segment_t addr_limit;  
+       [10]  struct exec_domain *exec_domain;
+       [14]  volatile long need_resched;
+       [18]  unsigned long ptrace;
+       [1c]  int lock_depth;           
+       [20]  long counter;
+       [24]  long nice;
+       [28]  unsigned long policy;
+ %fore "blue"
+       [2c]  struct mm_struct *mm;
+ %fore "black"
+       [30]  int processor;
+       [34]  unsigned long cpus_runnable, cpus_allowed;
+     	<snip>
+     };
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Simple Program
+ 
+ 
+ %font "typewriter", size 3
+ 	Display the mm_struct associated with simple process
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ md f7e10f00
+ %fore "black"
+     0xf7e10f00 
+ %fore "blue", cont
+ e8357a80
+ %fore "black", cont
+  e8357978 f7ac77e0 eb15eac0   .z5hxy5h`w,w@j.k
+     0xf7e10f10 00000001 00000002 0000000b 00000000   ................
+     0xf7e10f20 00000001 f7e10f24 f7e10f24 00000001   ................
+     0xf7e10f30 f7e35e70 eea7e8f0 08048000 0804862b   ................
+     0xf7e10f40 0804962c 08049744 08051780 0805a000   ................
+     0xf7e10f50 bffffd10 bffffe00 bffffe09 bffffe09   ................
+     0xf7e10f60 bffffff3 0000005a 00000168 00000000   ................
+     0xf7e10f70 00000000 00000002 00000000 00000001   ................
+ 
+ %font "typewriter", size 3
+ 	Determine offset of the first vma in the process
+ %font "typewriter", size 3
+     struct mm_struct {
+ %fore "blue"
+             struct vm_area_struct * mmap;	
+ %fore "black"
+             rb_root_t mm_rb;
+             struct vm_area_struct * mmap_cache;	
+             <snip>
+     };
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Simple Program
+ 
+ %font "typewriter", size 3
+ 	Display the first vma using md
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ md  e8357a80
+ %fore "black"
+     0xe8357a80 f7e10f00 08048000 08049000 
+ %fore "blue", cont
+ e8727e00
+ %fore "black",cont
+    ..aw.........~rh
+     0xe8357a90 00000025 00001875 e8727e18 00000001   %...u....~rh....
+ 
+ 	Display the first vma using vma
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ vma e8357a80
+ %fore "black"
+     struct vm_area_struct at 0xe8357a80 for 68 bytes
+     vm_start = 0x8048000   vm_end = 0x8049000
+     page_prot = 0x25
+     flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE 
+ %font "typewriter", size 3
+ 
+ 	Determine the offset to the vma list
+ %font "typewriter", size 3
+     struct vm_area_struct {
+       [0]   struct mm_struct * vm_mm;
+       [4]   unsigned long vm_start;
+       [8]   unsigned long vm_end;
+ %fore "blue"
+       [c]   struct vm_area_struct *vm_next;
+ %fore "black"
+             <snip>
+     };
+ 	Display the next vma
+ %font "typewriter", size 3
+     [3]kdb> vma e8727e00
+     struct vm_area_struct at 0xe8727e00 for 68 bytes
+     vm_start = 0x8049000   vm_end = 0x804a000
+     page_prot = 0x25
+     flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Simple Program
+ 
+ %font "typewriter", size 3
+ 	Use the ll command to display the list of vma's
+ %font "typewriter", size 3
+         [3]kdb> ll e8357a80 0xc vma
+ .
+         struct vm_area_struct at 0xe8357a80 for 68 bytes
+         vm_start = 0x8048000   vm_end = 0x8049000
+         page_prot = 0x25
+         flags:  READ EXEC MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE 
+ .
+         struct vm_area_struct at 0xe8727e00 for 68 bytes
+         vm_start = 
+ %fore "orange", cont
+ 0x8049000
+ %fore "black", cont
+    vm_end = 
+ %fore "orange", cont
+ 0x804a000
+ %fore "black"
+         page_prot = 0x25
+         flags:  READ WRITE MAYREAD MAYWRITE MAYEXEC DENYWRITE EXECUTABLE 
+ .
+         struct vm_area_struct at 0xe8727c80 for 68 bytes
+         vm_start = 
+ %fore "blue", cont
+ 0x804a000
+ %fore "black", cont
+    vm_end = 
+ %fore "blue", cont
+ 0x805a000
+ %fore "black"
+         page_prot = 0x25
+         flags:  READ WRITE EXEC MAYREAD MAYWRITE MAYEXEC 
+         <snip>
+         struct vm_area_struct at 0xe8357900 for 68 bytes
+         vm_start = 0xbfffe000   vm_end = 0xc0000000
+         page_prot = 0x25
+         flags:  READ WRITE EXEC MAYREAD MAYWRITE MAYEXEC GROWSDOWN 
+ 
+ 	Match the vma to the displayed addresses
+ %font "typewriter", size 3
+         foo_global  at 
+ %fore "orange", cont
+ 8049780
+ %fore "black"
+         foo_malloc at 
+ %fore "blue", cont
+ 8051788
+ %fore "black"
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ 	Objective
+ 		Show usage of various scsi and vm related kdb commands
+ 
+ 	Sequence:
+ 		Set a breakpoint in the scsi driver
+ 			Stops when queueing a command to the controller
+ 		Cause IO on an idle disk
+ 		Show various IO stack traces
+ 		Display the IO data structures
+ 		Display vm information about the data
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Set the breakpoint
+ 
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ bp isp1020_queuecommand
+ %fore "black"
+     Instruction(i) BP #0 at 0xc01ecfe0 (isp1020_queuecommand)
+         is enabled globally adjust 1
+ 
+ %font "typewriter", size 3
+ 	Create some activity on a previously unused disk
+ 
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ go
+ %fore "black"
+     [root@elm3b77 root]# 
+ %fore "blue", cont
+ ls /rh62
+ %fore "black"
+ 
+     Instruction(i) breakpoint #0 at 0xc01ecfe0 (adjusted)
+     0xc01ecfe0 isp1020_queuecommand:int3   
+ 
+     Entering kdb (current=0xf75ba000, pid 1181) on processor 3 due to 
+                                                 Breakpoint @ 0xc01ecfe0
+ 
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Show the stack.
+ 	This is a read of the /rh62 directory
+ 
+ %font "typewriter", size 3
+     [1]kdb> 
+ %fore "blue", cont
+ bt
+ %fore "black"
+         EBP       EIP         Function(args)
+     0xf75bbdf4 0xc01ecfe0 isp1020_queuecommand
+                0xc01e2c77 scsi_dispatch_cmd+0x1f7
+     0xf75bbe24 0xc01e99b1 scsi_request_fn+0x2f1
+     0xf75bbe34 0xc01c84fd generic_unplug_device+0x2d
+     0xf75bbe50 0xc011b3af __run_task_queue+0x5f
+     0xf75bbe6c 0xc013a63c block_sync_page+0x1c
+     0xf75bbe98 0xc0128127 __lock_page+0x77
+     0xf75bbea4 0xc0128178 lock_page+0x18
+     0xf75bbec8 0xc012a4b3 read_cache_page+0xc3
+     0xf75bbef4 0xc0168e23 ext2_get_page+0x23
+     0xf75bbf48 0xc0168fdd ext2_readdir+0xfd
+     0xf75bbf68 0xc0143d2e vfs_readdir+0x7e
+     0xf75bbfbc 0xc01442ed 
+ %fore "blue", cont
+ sys_getdents64+0x4d
+ %fore "black"
+                0xc010702b system_call+0x33
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Allow the operation to complete
+ 
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ go
+ %fore "black"
+     bench  build  etc   lib         mnt   oldsys  rh72  spv   usr
+     bin    data   h     linux       mnt1  opt     root  test  var
+     boot   dev    home  lost+found  mnt2  proc    sbin  tmp
+ 
+ %font "typewriter", size 3
+ 	Force some more activity
+ 
+ %font "typewriter", size 3
+     [root@elm3b77 root]# 
+ %fore "blue", cont
+ cd /rh62/tmp
+ %fore "black"
+     Instruction(i) breakpoint #0 at 0xc01ecfe0 (adjusted)
+     0xc01ecfe0 isp1020_queuecommand:int3 
+ 
+     Entering kdb (current=0xf768a000, pid 981) on processor 3 due to 
+                                                Breakpoint @ 0xc01ecfe0
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Show the stack. 
+ 	This is an inode read for /rh62/tmp
+ 
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ bt
+ %fore "black"
+         EBP       EIP         Function(args)
+     0xf768bd68 0xc01ecfe0 isp1020_queuecommand
+                0xc01e2c77 scsi_dispatch_cmd+0x1f7
+     0xf768bd98 0xc01e99b1 scsi_request_fn+0x2f1
+     0xf768bda8 0xc01c84fd generic_unplug_device+0x2d
+     0xf768bdc4 0xc011b3af __run_task_queue+0x5f
+     0xf768bdfc 0xc0137216 __wait_on_buffer+0x56
+     0xf768be1c 0xc0138600 bread+0x50
+     0xf768be5c 0xc016b684 ext2_read_inode+0x114
+     0xf768bf0c 0xc013fbec real_lookup+0x7c
+     0xf768bf78 0xc014035d link_path_walk+0x5ad
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Create a new file, causing yet more disk activity
+ 
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ go
+ %fore "black"
+ 
+     [root@elm3b77 tmp]# 
+ %fore "blue", cont
+ echo "Hello linux reading group" > j1;sync
+ %fore "black"
+ 
+     Instruction(i) breakpoint #0 at 0xc01ecfe0 (adjusted)
+     0xc01ecfe0 isp1020_queuecommand:int3
+ 
+     Entering kdb (current=0xf768a000, pid 981) on processor 3 due to 
+                                                Breakpoint @ 0xc01ecfe0
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Show the stack 
+ 	This is an inode read in response to the open
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ bt
+ %fore "black"
+         EBP       EIP         Function(args)
+     0xf768bd78 0xc01ecfe0 isp1020_queuecommand
+                0xc01e2c77 scsi_dispatch_cmd+0x1f7
+     0xf768bda8 0xc01e99b1 scsi_request_fn+0x2f1
+     0xf768bdb8 0xc01c84fd generic_unplug_device+0x2d
+     0xf768bdd4 0xc011b3af __run_task_queue+0x5f
+     0xf768bdf0 0xc013a63c block_sync_page+0x1c
+     0xf768be1c 0xc0128127 __lock_page+0x77
+     0xf768be28 0xc0128178 lock_page+0x18
+     0xf768be4c 0xc012a4b3 read_cache_page+0xc3
+     0xf768be78 0xc0168e23 ext2_get_page+0x23
+     0xf768beb8 0xc01691ed ext2_find_entry+0x8d
+     0xf768bed4 0xc016933a ext2_inode_by_name+0x1a
+     0xf768befc 0xc016c077 ext2_lookup+0x27
+     0xf768bf1c 0xc014094a lookup_hash+0x9a
+     0xf768bf64 0xc0140c4d open_namei+0xfd
+     0xf768bfa0 0xc0135907 filp_open+0x37
+     0xf768bfbc 0xc0135c64 sys_open+0x34
+                0xc010702b system_call+0x33
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Let the operation continue
+ %font "typewriter", size 3
+     [3]kdb> 
+ %fore "blue", cont
+ go
+ %fore "black"
+     Instruction(i) breakpoint #0 at 0xc01ecfe0 (adjusted)
+     0xc01ecfe0 isp1020_queuecommand: int3   
+     Entering kdb (current=0xc0352000, pid 0) on processor 0 due to 
+                                                Breakpoint @ 0xc01ecfe0
+ 	Show the stack
+ 	This is an io completion queuing the next request
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue", cont
+ bt
+ %fore "black"
+         EBP       EIP         Function(args)
+     0xc0353df4 0xc01ecfe0 isp1020_queuecommand(
+ %fore "blue", cont
+ 0xf7e63a00
+ %fore "black", cont
+ ,0xc01e7fc0...
+                0xc01e2c77 scsi_dispatch_cmd+0x1f7
+     0xc0353e24 0xc01e99b1 scsi_request_fn+0x2f1
+     0xc0353e40 0xc01e8f6a 
+ %fore "blue", cont
+ scsi_queue_next_request+0x4a
+ %fore "black"
+     0xc0353e5c 0xc01e9166 __scsi_end_request+0x116
+     0xc0353ea8 0xc01e93e0 
+ %fore "blue", cont
+ scsi_io_completion+0x170
+ %fore "black"
+     0xc0353ecc 0xc01f658e rw_intr+0x14e
+     0xc0353ef8 0xc01e8668 scsi_old_done+0x6a8
+     0xc0353fd4 0xc01052c2 cpu_idle+0x52
+ 	Function prototype
+ %font "typewriter", size 3
+         int isp1020_queuecommand(
+ %fore "blue", cont
+ Scsi_Cmnd *Cmnd, 
+ %fore "black"
+                                  void (*done)(Scsi_Cmnd *))
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Show the command being queued
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue", cont
+ sc 0xf7e63a00
+ %fore "black"
+     scsi_cmnd at 0xf7e63a00
+ %fore "blue"
+     host = 0xf7e91400
+ %fore "black", cont
+   state = 4099  owner = 258  
+ %fore "blue", cont
+ device = 0xf7ed5d80
+ %fore "black"
+     bnext = 0x00000000  reset_chain = 0x00000000  eh_state = 0 
+                                                   done = 0xc01f6440
+     serial_number = 3402  serial_num_at_to = 0 retries = 0 timeout = 0
+     id/lun/cmnd = [0/0/0]  cmd_len = 10  old_cmd_len = 10
+     cmnd = [2a/00/00/28/00/3f/00/00/10/00/ef/f7]
+     data_cmnd = [2a/00/00/28/00/3f/00/00/10/00/ef/f7]
+     request_buffer = 0xc03fd000  bh_next = 0x00000000  
+                                  request_bufflen = 8192
+     use_sg = 2  old_use_sg = 2 sglist_len = 512 abore_reason = 0
+     bufflen = 8192  buffer = 0xc03fd000  underflow = 8192 
+                                          transfersize = 512
+     tag = 0 pid = 3401
+     request struct
+     rq_status = RQ_ACTIVE  rq_dev = [8/1]  errors = 1  cmd = 0
+     sector = 2621440  nr_sectors = 16  current_nr_sectors = 8
+     buffer = 0xf7599000 
+ %fore "blue", cont
+ bh = 0xf75ca300
+ %fore "black", cont
+  bhtail = 0xf75ca3c0
+ 
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Display the host adapter
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue", cont
+ sh 0xf7e91400
+ %fore "black"
+     Scsi_Host at 0xf7e91400
+     next = 0x00000000   
+ %fore "blue", cont
+ host_queue = 0xf7ed5d80
+ %fore "black"
+     ehandler = 0x00000000 eh_wait = 0x00000000  en_notify = 0x00000000 
+                                                 eh_action = 0x00000000
+     h_active = 0x0 host_wait = 0xc0353ac4 hostt = 0xc034bce0 
+                                           host_busy = 1
+     host_failed = 0  extra_bytes = 524  host_no = 0 resetting = 0
+     max id/lun/channel = [16/8/0]  this_id = 7
+     can_queue = 64 cmd_per_lun = 1  sg_tablesize = 427 u_isa_dma = 0
+     host_blocked = 0  reverse_ordering = 0 
+ 
+ %font "typewriter", size 3
+ 	Display the scsi device
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue", cont
+ sd 0xf7ed5d80
+ %fore "black"
+     scsi_device at 0xf7ed5d80
+     next = 0xf7ed5c80   prev = 0x00000000  host = 0xf7e91400
+     device_busy = 1   
+ %fore "blue", cont
+ device_queue 0xf7e63a00
+ %fore "black"
+     id/lun/chan = [0/0/0]  single_lun = 0  device_blocked = 0
+     queue_depth = 1 current_tag = 0  scsi_level = 4
+     IBM      DGHS18X          0360
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Display the Buffer header associated with the command
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue", cont
+ bh 0xf75ca300
+ %fore "black"
+     buffer_head at 0xf75ca300
+       next 0x00000000 bno 327680 rsec 2621440 size 4096 
+                                       dev 0x801 rdev 0x801
+       count 2 state 0x1d [Uptodate Lock Req Mapped] ftime 0x7695e 
+                     b_list 1 b_reqnext 0xf75ca3c0 b_data 0xf7599000
+ %fore "blue"
+       b_page 0xc1dd6640
+ %fore "black", cont
+  b_this_page 0xf75ca300 b_private 0x00000000
+ 
+ 	Display the associated page structure 
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue", cont
+ page 0xc1dd6640
+ %fore "black"
+     struct page at 0xc1dd6640
+       next 0xc1dd7300 prev 0xc1dd6240 
+ %fore "blue", cont
+ addr space 0xf7af04d0 
+ %fore "black"
+                                       index 327680 (offset 0x50000000)
+       count 2 flags PG_referenced PG_lru virtual 0xf7599000
+       buffers 0xf75ca300
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Display the Address space associated with the page
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue", cont
+ md 0xf7af04d0
+ %fore "black"
+     0xf7af04d0 c1dd6240 c1dea740 f7af04d8 f7af04d8   @b]A@'^AX./wX./w
+     0xf7af04e0 f7af04e0 f7af04e0 00000007 c033b700   `./w`./w.....73@
+     0xf7af04f0 
+ %fore "blue", cont
+ f7af0420
+ %fore "black", cont
+  00000000 00000000 00000001    ./w............
+     0xf7af0500 000001d0 00000000 00000000 f7af050c   P............./w
+     0xf7af0510 f7af050c 00000000 f7a8afa0 00000000   ../w.... /(w....
+ 
+ 	The structure looks like:
+ %size 3
+     struct address_space {
+         struct list_head    clean_pages; /* list of clean pages */
+         struct list_head    dirty_pages; /* list of dirty pages */
+         struct list_head    locked_pages;/* list of locked pages */
+         unsigned long       nrpages;     /* number of total pages */
+         spinlock_t          page_lock;   /* spinlock protecting them*/
+         struct address_space_operations *a_ops;    /* methods */
+ %fore "blue"
+         struct inode        *host;       /* owner: inode, block_dev */
+ %fore "black"
+     <snip>
+     };
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Display the inode associated with the address space
+ 	I think htis is the inode for the block device.
+ 
+ %font "typewriter", size 3
+     [1]kdb> 
+ %fore "blue", cont
+ inode f7af0420
+ %fore "black"
+     struct inode at  0xf7af0420
+      i_ino = 289 i_count = 1 i_dev = 0x801 i_size 4301789184
+      i_mode = 0x8000  i_nlink = 1  i_rdev = 0x801
+      i_hash.nxt = 0xf7af0420 i_hash.prv = 0xf7af0420
+      i_list.nxt = 0xf7af0608 i_list.prv = 0xf7af0068
+      i_dentry.nxt = 0xf7af0430 i_dentry.prv = 0xf7af0430
+      i_dirty_buffers.nxt = 0xf7af0438 i_dirty_buffers.prv = 0xf7af0438
+      i_sb = 0xc201f200 i_op = 0xc03cfdc0 i_data = 0xf7af04d0 nrpages = 6
+      i_mapping = 0xf7af04d0
+      i_flags 0x0 i_state 0x0 []  fs specific info @ 0xf7af0540
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %page
+ 
+ Walking IO structures
+ 
+ 
+ %font "typewriter", size 3
+ 	Display the page list associated with the inode
+ %font "typewriter", size 3
+     [0]kdb> 
+ %fore "blue", cont
+ inode_pages f7af0420
+ %fore "black"
+ CLEAN  page_struct   index  cnt  flags
+    0xc1dd6240    327735        2    0x44 bh 0xf75caae0 bno   327735 
+                                             [Lock Req Mapped]
+ %fore "blue"
+    0xc1dd6640    327680        2    0x44 bh 0xf75ca300 bno   327680 
+                                             [Uptodate Lock Req Mapped]
+ %fore "black"
+    0xc1dd7300    327681        2    0x44 bh 0xf75ca3c0 bno   327681 
+                                             [Uptodate Lock Req Mapped]
+    0xc1dd6e00    327684        2    0x44 bh 0xf75ca420 bno   327684 
+                                             [Uptodate Req Mapped]
+    0xc1de8fc0         4        2    0xc0 bh 0xf7b5ade0 bno        4 
+                                             [Uptodate Req Mapped]
+    0xc1dea700         1        2    0x44 bh 0xf7e02740 bno        1 
+                                             [Uptodate Req Mapped]
+    0xc1dea740         0        2    0x44 bh 0xf7e028c0 bno        0 
+                                             [Uptodate Req Mapped]
+ DIRTY  page_struct   index  cnt  flags
+ LOCKED page_struct   index  cnt  flags
diff -c -r -N console-os/drivers/char/keyboard.c console-os-kdb/drivers/char/keyboard.c
*** console-os/drivers/char/keyboard.c	2006-11-20 12:23:05.000000000 -0800
--- console-os-kdb/drivers/char/keyboard.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 48,53 ****
--- 48,56 ----
  #include <linux/kbd_ll.h>
  #include <linux/sysrq.h>
  #include <linux/pm.h>
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif	/* CONFIG_KDB */
  
  #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
  
***************
*** 264,269 ****
--- 267,279 ----
  	} else
  		rep = test_and_set_bit(keycode, key_down);
  
+ #ifdef	CONFIG_KDB
+ 	if (!up_flag && (keycode == E1_PAUSE) && kdb_on) {
+ 		kdb(KDB_REASON_KEYBOARD, 0, kbd_pt_regs);
+ 		return;
+ 	}
+ #endif	/* CONFIG_KDB */
+ 
  #ifdef CONFIG_MAGIC_SYSRQ		/* Handle the SysRq Hack */
  	/*
  	  Pressing magic + command key acts as a chorded command.
diff -c -r -N console-os/drivers/char/serial.c console-os-kdb/drivers/char/serial.c
*** console-os/drivers/char/serial.c	2006-11-20 12:23:05.000000000 -0800
--- console-os-kdb/drivers/char/serial.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 233,238 ****
--- 233,253 ----
  #include <linux/acpi.h>
  #endif
  
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ #ifdef	CONFIG_SERIAL_CONSOLE
+ /*
+  * kdb_serial_line records the serial line number of the first serial console.
+  * NOTE: The kernel ignores characters on the serial line unless a user space
+  * program has opened the line first.  To enter kdb before user space has opened
+  * the serial line, you can use the 'kdb=early' flag to lilo and set the
+  * appropriate breakpoints.
+  */
+ 
+ static int  kdb_serial_line = -1;
+ static const char *kdb_serial_ptr = kdb_serial_str;
+ #endif	/* CONFIG_SERIAL_CONSOLE */
+ #endif	/* CONFIG_KDB */
  /*
   * All of the compatibilty code so we can compile serial.c against
   * older kernels is hidden in serial_compat.h
***************
*** 597,602 ****
--- 612,629 ----
  				return;		// if TTY_DONT_FLIP is set
  		}
  		ch = serial_inp(info, UART_RX);
+ #if	defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_KDB)
+ 		if ((info->line == kdb_serial_line) && kdb_on) {
+ 		    if (ch == *kdb_serial_ptr) {
+ 			if (!(*++kdb_serial_ptr)) {
+ 			    kdb(KDB_REASON_KEYBOARD, 0, regs);
+ 			    kdb_serial_ptr = kdb_serial_str;
+ 			    break;
+ 			}
+ 		    } else
+ 			kdb_serial_ptr = kdb_serial_str;
+ 		}
+ #endif	/* CONFIG_SERIAL_CONSOLE && CONFIG_KDB */
  		*tty->flip.char_buf_ptr = ch;
  		icount->rx++;
  		
***************
*** 6236,6241 ****
--- 6263,6292 ----
  	if (serial_in(info, UART_LSR) == 0xff)
  		return -1;
  
+ #if	defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_KDB)
+ 	/*
+ 	 * Remember the line number of the first serial
+ 	 * console.  We'll make this the kdb serial console too.
+ 	 */
+ 	if (kdb_serial_line == -1) {
+ 		kdb_serial_line = co->index;
+ 		kdb_serial.io_type = info->io_type;
+ 		switch (info->io_type) {
+ 		case SERIAL_IO_MEM:
+ #ifdef  SERIAL_IO_MEM32
+ 		case SERIAL_IO_MEM32:
+ #endif
+ 			kdb_serial.iobase = (unsigned long)(info->iomem_base);
+ 			kdb_serial.ioreg_shift = info->iomem_reg_shift;
+ 			break;
+ 		default:
+ 			kdb_serial.iobase = state->port;
+ 			kdb_serial.ioreg_shift = 0;
+ 			break;
+ 		}
+ 	}
+ #endif	/* CONFIG_SERIAL_CONSOLE && CONFIG_KDB */
+ 
  	return 0;
  }
  
diff -c -r -N console-os/drivers/sbus/char/sab82532.c console-os-kdb/drivers/sbus/char/sab82532.c
*** console-os/drivers/sbus/char/sab82532.c	2006-11-20 12:23:35.000000000 -0800
--- console-os-kdb/drivers/sbus/char/sab82532.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 42,47 ****
--- 42,59 ----
  
  #include "sunserial.h"
  
+ #if defined(CONFIG_KDB)
+ #include <linux/kdb.h>
+ /*
+  * NOTE: The kernel ignores characters on the serial line unless a user space
+  * program has opened the line first.  To enter kdb before user space has opened
+  * the serial line, you can use the 'kdb=early' flag to lilo and set the
+  * appropriate breakpoints.
+  */
+ 
+ static const char *kdb_serial_ptr = kdb_serial_str;
+ #endif	/* CONFIG_KDB */
+ 
  static DECLARE_TASK_QUEUE(tq_serial);
  
  /* This is (one of many) a special gross hack to allow SU and
***************
*** 318,325 ****
  }
  
  static void receive_chars(struct sab82532 *info,
! 			  union sab82532_irq_status *stat)
  {
  	struct tty_struct *tty = info->tty;
  	unsigned char buf[32];
  	unsigned char status;
--- 330,341 ----
  }
  
  static void receive_chars(struct sab82532 *info,
! 			  union sab82532_irq_status *stat,
! 			  struct pt_regs *regs)
  {
+ #if defined(CONFIG_KDB)
+ 	int need_kdb = 0;
+ #endif
  	struct tty_struct *tty = info->tty;
  	unsigned char buf[32];
  	unsigned char status;
***************
*** 373,378 ****
--- 389,406 ----
  			break;
  		}
  
+ #if defined(CONFIG_KDB)
+ 		if (info->is_console && kdb_on) {
+ 			if (buf[i] == *kdb_serial_ptr) {
+ 				if (!(*++kdb_serial_ptr)) {
+ 					need_kdb = 1;
+ 					kdb_serial_ptr = kdb_serial_str;
+ 					break;
+ 				}
+ 			} else
+ 				kdb_serial_ptr = kdb_serial_str;
+ 		}
+ #endif	/* CONFIG_KDB */
  		tty->flip.count++;
  		*tty->flip.char_buf_ptr++ = buf[i++];
  		status = buf[i++];
***************
*** 392,398 ****
  		else
  			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
  	}
! 
  	queue_task(&tty->flip.tqueue, &tq_timer);
  }
  
--- 420,429 ----
  		else
  			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
  	}
! #ifdef CONFIG_KDB
! 	if (need_kdb)
! 		kdb(KDB_REASON_KEYBOARD, 0, regs);
! #endif
  	queue_task(&tty->flip.tqueue, &tq_timer);
  }
  
***************
*** 600,606 ****
  
  	if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
  				SAB82532_ISR0_RFO | SAB82532_ISR0_RPF))
! 		receive_chars(info, &status);
  	if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
  	    (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC)))
  		check_status(info, &status);
--- 631,637 ----
  
  	if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
  				SAB82532_ISR0_RFO | SAB82532_ISR0_RPF))
! 		receive_chars(info, &status, regs);
  	if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
  	    (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC)))
  		check_status(info, &status);
***************
*** 625,631 ****
  
  	if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
  				SAB82532_ISR0_RFO | SAB82532_ISR0_RPF))
! 		receive_chars(info, &status);
  	if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
  	    (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC)))
  		check_status(info, &status);
--- 656,662 ----
  
  	if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
  				SAB82532_ISR0_RFO | SAB82532_ISR0_RPF))
! 		receive_chars(info, &status, regs);
  	if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
  	    (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC)))
  		check_status(info, &status);
diff -c -r -N console-os/drivers/sbus/char/su.c console-os-kdb/drivers/sbus/char/su.c
*** console-os/drivers/sbus/char/su.c	2006-11-20 12:23:35.000000000 -0800
--- console-os-kdb/drivers/sbus/char/su.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 74,79 ****
--- 74,93 ----
  #endif
  #include <linux/sysrq.h>
  
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ /*
+  * kdb_serial_line records the serial line number of the first serial console.
+  * NOTE: The kernel ignores characters on the serial line unless a user space
+  * program has opened the line first.  To enter kdb before user space has opened
+  * the serial line, you can use the 'kdb=early' flag to lilo and set the
+  * appropriate breakpoints.
+  */
+ 
+ static int  kdb_serial_line = -1;
+ static const char *kdb_serial_ptr = kdb_serial_str;
+ #endif	/* CONFIG_KDB */
+ 
  #include <asm/system.h>
  #include <asm/oplib.h>
  #include <asm/io.h>
***************
*** 400,405 ****
--- 414,431 ----
  			saw_console_brk = 1;
  		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  			break;
+ #ifdef	CONFIG_KDB
+ 		if ((info->line == kdb_serial_line) && kdb_on) {
+ 		    if (ch == *kdb_serial_ptr) {
+ 			if (!(*++kdb_serial_ptr)) {
+ 			    kdb(KDB_REASON_KEYBOARD, 0, regs);
+ 			    kdb_serial_ptr = kdb_serial_str;
+ 			    break;
+ 			}
+ 		    } else
+ 			kdb_serial_ptr = kdb_serial_str;
+ 		}
+ #endif	/* CONFIG_KDB */
  		*tty->flip.char_buf_ptr = ch;
  		icount->rx++;
  
***************
*** 2965,2970 ****
--- 2991,3006 ----
  
  	info->is_console = 1;
  
+ #ifdef	CONFIG_KDB
+ 	/*
+ 	 * Remember the line number of the first serial
+ 	 * console.  We'll make this the kdb serial console too.
+ 	 */
+ 	if (kdb_serial_line == -1)
+ 		kdb_serial_line = co->index;
+ 	
+ #endif	/* CONFIG_KDB */
+ 
  	return 0;
  }
  
diff -c -r -N console-os/drivers/sbus/char/sunkbd.c console-os-kdb/drivers/sbus/char/sunkbd.c
*** console-os/drivers/sbus/char/sunkbd.c	2006-11-20 12:23:35.000000000 -0800
--- console-os-kdb/drivers/sbus/char/sunkbd.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 44,49 ****
--- 44,53 ----
  #include <asm/ebus.h>
  #endif
  
+ #ifdef CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif
+ 
  #include "sunkbd.h"
  
  #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
***************
*** 138,143 ****
--- 142,150 ----
  
  static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
  	num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
+ #ifdef CONFIG_KDB
+ 	call_kdb,
+ #endif
  	SAK, decr_console, incr_console, spawn_console, bare_num;
  
  static void_fnp spec_fn_table[] = {
***************
*** 145,151 ****
  	show_state,	send_intr,	lastcons,	caps_toggle,
  	num,		hold,		scroll_forw,	scroll_back,
  	boot_it,	caps_on,	compose,	SAK,
! 	decr_console,	incr_console,	spawn_console,	bare_num
  };
  
  /* maximum values each key_handler can handle */
--- 152,161 ----
  	show_state,	send_intr,	lastcons,	caps_toggle,
  	num,		hold,		scroll_forw,	scroll_back,
  	boot_it,	caps_on,	compose,	SAK,
! 	decr_console,	incr_console,	spawn_console,	bare_num,
! #ifdef CONFIG_KDB
! 	call_kdb
! #endif
  };
  
  /* maximum values each key_handler can handle */
***************
*** 813,818 ****
--- 823,835 ----
  {
  }
  
+ #ifdef CONFIG_KDB
+ static void call_kdb()
+ {
+ 	kdb(KDB_REASON_KEYBOARD, 0, pt_regs);
+ }
+ #endif
+ 
  static void do_null()
  {
  	sun_compute_shiftstate();
diff -c -r -N console-os/drivers/sbus/char/sunkeymap.c console-os-kdb/drivers/sbus/char/sunkeymap.c
*** console-os/drivers/sbus/char/sunkeymap.c	2006-11-20 12:23:35.000000000 -0800
--- console-os-kdb/drivers/sbus/char/sunkeymap.c	2007-01-10 14:02:18.000000000 -0800
***************
*** 9,15 ****
  u_short plain_map[NR_KEYS] = {
  	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf100,	0xf101,	0xf109,
  	0xf102,	0xf10a,	0xf103,	0xf10b,	0xf104,	0xf701,	0xf105,	0xf200,
! 	0xf106,	0xf107,	0xf108,	0xf703,	0xf603,	0xf11d,	0xf200,	0xf209,
  	0xf601,	0xf200,	0xf200,	0xf600,	0xf602,	0xf01b,	0xf031,	0xf032,
  	0xf033,	0xf034,	0xf035,	0xf036,	0xf037,	0xf038,	0xf039,	0xf030,
  	0xf02d,	0xf03d,	0xf060,	0xf07f,	0xf115,	0xf03d,	0xf30d,	0xf30c,
--- 9,21 ----
  u_short plain_map[NR_KEYS] = {
  	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf100,	0xf101,	0xf109,
  	0xf102,	0xf10a,	0xf103,	0xf10b,	0xf104,	0xf701,	0xf105,	0xf200,
! 	0xf106,	0xf107,	0xf108,	0xf703,	0xf603,
! #ifdef CONFIG_KDB
! 	/* Pause (keycode 0x15) triggers kdb */ 0xf214,
! #else
! 						0xf11d,
! #endif
! 							0xf200,	0xf209,
  	0xf601,	0xf200,	0xf200,	0xf600,	0xf602,	0xf01b,	0xf031,	0xf032,
  	0xf033,	0xf034,	0xf035,	0xf036,	0xf037,	0xf038,	0xf039,	0xf030,
  	0xf02d,	0xf03d,	0xf060,	0xf07f,	0xf115,	0xf03d,	0xf30d,	0xf30c,
diff -c -r -N console-os/drivers/usb/hid-core.c console-os-kdb/drivers/usb/hid-core.c
*** console-os/drivers/usb/hid-core.c	2006-11-20 12:23:55.000000000 -0800
--- console-os-kdb/drivers/usb/hid-core.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 57,62 ****
--- 57,82 ----
  #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>"
  #define DRIVER_DESC "USB HID support drivers"
  
+ #if defined(CONFIG_KDB_USB)
+ #include <linux/kdb.h>
+ extern struct kdb_usb_exchange kdb_usb_infos;
+ struct hid_device *hid_kbd = NULL;
+ 
+ /* kdb_usb_hid_reset_timer
+  * This function reset the timer in the input_dev structure
+  * If you don't do that you'll be unable to exit KDB in the case 
+  * you've entered by pressing the Pause key
+  */
+ void hid_reset_timer(void)
+ {
+   if(hid_kbd->input.timer.list.next) {
+     (hid_kbd->input.timer.list.next)->prev = hid_kbd->input.timer.list.prev;
+     (hid_kbd->input.timer.list.prev)->next = hid_kbd->input.timer.list.next;
+     hid_kbd->input.timer.list.prev = hid_kbd->input.timer.list.next = NULL;
+   }
+ }
+ #endif /* CONFIG_KDB_USB */
+ 
  static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
  				"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
  
***************
*** 1341,1347 ****
  	printk(": USB HID v%x.%02x %s [%s] on usb%d:%d.%d\n",
  		hid->version >> 8, hid->version & 0xff, c, hid->name,
  		dev->bus->busnum, dev->devnum, ifnum);
! 
  	return hid;
  }
  
--- 1361,1376 ----
  	printk(": USB HID v%x.%02x %s [%s] on usb%d:%d.%d\n",
  		hid->version >> 8, hid->version & 0xff, c, hid->name,
  		dev->bus->busnum, dev->devnum, ifnum);
! #if defined(CONFIG_KDB_USB)
! 	/* Initialisation of the KDB structure */
! 	if (!strcmp(c, "Keyboard")) {
! 	        hid_kbd = hid;
! 	        kdb_usb_infos.urb = &hid->urb;
! 	        kdb_usb_infos.buffer = &hid->buffer[0];
! 	        kdb_usb_infos.reset_timer = hid_reset_timer;
! 	        kdb_usb_infos.driver = HID_ACTIVE;
! 	}
! #endif
  	return hid;
  }
  
diff -c -r -N console-os/drivers/usb/host/usb-uhci.c console-os-kdb/drivers/usb/host/usb-uhci.c
*** console-os/drivers/usb/host/usb-uhci.c	2006-11-20 12:23:55.000000000 -0800
--- console-os-kdb/drivers/usb/host/usb-uhci.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 40,46 ****
  #include <asm/io.h>
  #include <asm/irq.h>
  #include <asm/system.h>
! 
  /* This enables more detailed sanity checks in submit_iso */
  //#define ISO_SANITY_CHECK
  
--- 40,49 ----
  #include <asm/io.h>
  #include <asm/irq.h>
  #include <asm/system.h>
! #if defined(CONFIG_KDB_USB)
! #include <linux/kdb.h>
! extern struct kdb_usb_exchange kdb_usb_infos;
! #endif
  /* This enables more detailed sanity checks in submit_iso */
  //#define ISO_SANITY_CHECK
  
***************
*** 2912,2917 ****
--- 2915,3026 ----
  }
  #endif
  
+ /* ------------------------------------------------------------------ */
+ /* KDB part */
+ 
+ #if defined(CONFIG_KDB_USB)
+ /* 
+ * The part of the code of UHCI controller that
+ * process the interrupt transfer
+ */
+ 
+ void uhci_process_kdb_interrupt (uhci_t *s, struct urb *urb)
+ {	
+ 	int i;
+ 	urb_priv_t *urb_priv = urb->hcpriv;
+ 	struct list_head *p = urb_priv->desc_list.next;
+ 	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
+   
+ 	int actual_length;
+ 	int status = 0;
+   
+ 	for (i = 0; p != &urb_priv->desc_list; p = p->next, i++)	// Maybe we allow more than one TD later ;-)
+ 	{
+       		desc = list_entry (p, uhci_desc_t, desc_list);
+       
+       		if (is_td_active(desc)) {
+ 			// do not process active TDs
+ 			//dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status));
+ 			break;
+       		}
+       
+       		if (!(desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC))) {
+ 			// do not process one-shot TDs, no recycling
+ 			break;
+       		}
+       		// extract transfer parameters from TD
+       
+       		actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status));
+       		status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
+       
+      	 	// see if EP is stalled
+       		if (status == -EPIPE) {
+ 			// set up stalled condition
+ 			usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+       		}
+       
+       		// if any error occurred: ignore this td, and continue
+       		if (status != 0) {
+ 			//uhci_show_td (desc);
+ 			urb->error_count++;
+ 			goto recycle;
+       		}
+       		else
+ 			urb->actual_length = actual_length;
+       
+ recycle:
+       		uhci_urb_dma_sync(s, urb, urb->hcpriv);
+       
+       		if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) &&
+ 		    (urb->status != -ENOENT)) {
+ 	
+ 			urb->status = -EINPROGRESS;
+ 	
+ 			// Recycle INT-TD if interval!=0, else mark TD as one-shot
+ 			if (urb->interval) {
+ 	  
+ 	  			desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE));
+ 	  			if (status==0) {
+ 	    				desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+ 							    usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
+ 	    				usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+ 	  			} else {
+ 	    				desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+ 							     usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
+ 	  			}
+ 	  			desc->hw.td.status= cpu_to_le32((urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
+ 								(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27));
+ 	  			mb();
+ 			} else {
+ 	  			uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
+ 					// correct toggle after unlink
+ 	  			usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+ 	  			clr_td_ioc(desc); // inactivate TD
+ 			}
+     	}
+    	}
+ }
+ 
+ /* uhci_kdb_poll
+  * This function is a minimalist version of the 
+  * controller interrupt handler
+  */
+ void uhci_kdb_poll (void *__uhci, struct urb *urb)
+ {
+ 	uhci_t *s = __uhci;
+ 
+ 	/* Reset input timer to be able to quit KDB */
+ 	(*kdb_usb_infos.reset_timer)();
+ 
+ 	s->unlink_urb_done=0;
+ 	uhci_process_kdb_interrupt (s, urb);
+ 
+ 	clean_descs(s, CLEAN_NOT_FORCED);
+ 	uhci_cleanup_unlink(s, CLEAN_NOT_FORCED);
+ 	uhci_switch_timer_int(s);
+ }
+ #endif
+ /*-------------------------------------------------------------------*/
  _static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size)
  {
  	uhci_t *s;
***************
*** 2931,2936 ****
--- 3040,3049 ----
  		return -1;
  
  	memset (s, 0, sizeof (uhci_t));
+ #if defined(CONFIG_KDB_USB)
+ 	kdb_usb_infos.uhci = (void *)s;
+ 	kdb_usb_infos.poll_func = uhci_kdb_poll;
+ #endif
  	INIT_LIST_HEAD (&s->free_desc);
  	INIT_LIST_HEAD (&s->urb_list);
  	INIT_LIST_HEAD (&s->urb_unlinked);
diff -c -r -N console-os/drivers/usb/usbkbd.c console-os-kdb/drivers/usb/usbkbd.c
*** console-os/drivers/usb/usbkbd.c	2006-11-20 12:23:57.000000000 -0800
--- console-os-kdb/drivers/usb/usbkbd.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 77,82 ****
--- 77,104 ----
  	int open;
  };
  
+ 
+ #if defined(CONFIG_KDB_USB)
+ #include <linux/kdb.h>
+ static struct usb_kbd *usb_kbd_ptr = NULL;
+ extern struct kdb_usb_exchange kdb_usb_infos;
+ 
+ /* usb_kbd_reset_timer
+  * This function reset the timer in the input_dev structure
+  * If you don't do that you'll be unable to exit KDB in the case 
+  * you've entered by pressing the Pause key
+  */
+ 
+ void usb_kbd_reset_timer(void)
+ {
+ 	if(usb_kbd_ptr->dev.timer.list.next) {
+ 	       (usb_kbd_ptr->dev.timer.list.next)->prev = usb_kbd_ptr->dev.timer.list.prev;
+ 	       (usb_kbd_ptr->dev.timer.list.prev)->next = usb_kbd_ptr->dev.timer.list.next;
+ 	       usb_kbd_ptr->dev.timer.list.prev = usb_kbd_ptr->dev.timer.list.next = NULL;
+ 	}
+ }
+ #endif /* CONFIG_KDB_USB */
+ 
  static void usb_kbd_irq(struct urb *urb)
  {
  	struct usb_kbd *kbd = urb->context;
***************
*** 214,219 ****
--- 236,249 ----
  
  	FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
  		usb_kbd_irq, kbd, endpoint->bInterval);
+ #if defined(CONFIG_KDB_USB)
+ 	/* Init the KDB structure */
+ 	usb_kbd_ptr = kbd;
+ 	kdb_usb_infos.urb = &kbd->irq;
+ 	kdb_usb_infos.buffer = &kbd->new[0];
+ 	kdb_usb_infos.reset_timer = usb_kbd_reset_timer;
+ 	kdb_usb_infos.driver = USB_KBD_ACTIVE;
+ #endif /* CONFIG_KDB_USB */
  
  	kbd->dr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
  	kbd->dr.bRequest = USB_REQ_SET_REPORT;
diff -c -r -N console-os/include/asm-i386/hw_irq.h console-os-kdb/include/asm-i386/hw_irq.h
*** console-os/include/asm-i386/hw_irq.h	2007-01-09 18:01:54.000000000 -0800
--- console-os-kdb/include/asm-i386/hw_irq.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 26,31 ****
--- 26,32 ----
  #define FIRST_EXTERNAL_VECTOR	0x20
  
  #define SYSCALL_VECTOR		0x80
+ #define KDBENTER_VECTOR		0x81
  
  /*
   * Vectors 0x20-0x2f are used for ISA interrupts.
***************
*** 45,50 ****
--- 46,52 ----
  #define INVALIDATE_TLB_VECTOR	0xfd
  #define RESCHEDULE_VECTOR	0xfc
  #define CALL_FUNCTION_VECTOR	0xfb
+ #define KDB_VECTOR		0xf9
  
  /*
   * Local APIC timer IRQ vector is on a different priority level,
diff -c -r -N console-os/include/asm-i386/kdb.h console-os-kdb/include/asm-i386/kdb.h
*** console-os/include/asm-i386/kdb.h	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/include/asm-i386/kdb.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,162 ----
+ #ifndef	_ASM_KDB_H
+ #define _ASM_KDB_H
+ 
+ /*
+  * Kernel Debugger Architecture Dependent Global Headers
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ 	/*
+ 	 * KDB_ENTER() is a macro which causes entry into the kernel
+ 	 * debugger from any point in the kernel code stream.  If it
+ 	 * is intended to be used from interrupt level, it must  use
+ 	 * a non-maskable entry method.
+ 	 */
+ #define KDB_ENTER()	do {if (kdb_on && !KDB_IS_RUNNING()) { asm("\tint $129\n"); }} while(0)
+ 
+ 	/*
+ 	 * Needed for exported symbols.
+ 	 */
+ typedef unsigned long kdb_machreg_t;
+ 
+ #define kdb_machreg_fmt		"0x%lx"
+ #define kdb_machreg_fmt0	"0x%08lx"
+ #define kdb_bfd_vma_fmt		"0x%lx"
+ #define kdb_bfd_vma_fmt0	"0x%08lx"
+ #define kdb_elfw_addr_fmt	"0x%x"
+ #define kdb_elfw_addr_fmt0	"0x%08x"
+ 
+ 	/*
+ 	 * Per cpu arch specific kdb state.  Must be in range 0xff000000.
+ 	 */
+ #define KDB_STATE_A_IF		0x01000000	/* Saved IF flag */
+ 
+ 	/*
+ 	 * Functions to safely read and write kernel areas.  The {to,from}_xxx
+ 	 * addresses are not necessarily valid, these functions must check for
+ 	 * validity.  If the arch already supports get and put routines with
+ 	 * suitable validation and/or recovery on invalid addresses then use
+ 	 * those routines, otherwise check it yourself.
+ 	 */
+ 
+ 	/*
+ 	 * asm-i386 uaccess.h supplies __copy_to_user which relies on MMU to
+ 	 * trap invalid addresses in the _xxx fields.  Verify the other address
+ 	 * of the pair is valid by accessing the first and last byte ourselves,
+ 	 * then any access violations should only be caused by the _xxx
+ 	 * addresses,
+ 	 */
+ 
+ #include <asm/uaccess.h>
+ 
+ extern int kdb_getuserarea_size(void *, unsigned long, size_t);
+ extern int kdb_putuserarea_size(unsigned long, void *, size_t);
+ 
+ static inline int
+ __kdba_putarea_size(unsigned long to_xxx, void *from, size_t size)
+ {
+ 	mm_segment_t oldfs = get_fs();
+ 	int r;
+ 	char c;
+ 	c = *((volatile char *)from);
+ 	c = *((volatile char *)from + size - 1);
+ 	
+ 	if (to_xxx < PAGE_OFFSET) {
+ 		return kdb_putuserarea_size(to_xxx, from, size);
+ 	}
+ 
+ 	set_fs(KERNEL_DS);
+ 	r = __copy_to_user((void *)to_xxx, from, size);
+ 	set_fs(oldfs);
+ 	return r;
+ }
+ 
+ static inline int
+ __kdba_getarea_size(void *to, unsigned long from_xxx, size_t size)
+ {
+ 	mm_segment_t oldfs = get_fs();
+ 	int r;
+ 	*((volatile char *)to) = '\0';
+ 	*((volatile char *)to + size - 1) = '\0';
+ 
+ 	if (from_xxx < PAGE_OFFSET) {
+ 		return kdb_getuserarea_size(to, from_xxx, size);
+ 	}
+ 
+ 	set_fs(KERNEL_DS);
+ 	switch (size) {
+ 	case 1:
+ 		r = __copy_to_user(to, (void *)from_xxx, 1);
+ 		break;
+ 	case 2:
+ 		r = __copy_to_user(to, (void *)from_xxx, 2);
+ 		break;
+ 	case 4:
+ 		r = __copy_to_user(to, (void *)from_xxx, 4);
+ 		break;
+ 	case 8:
+ 		r = __copy_to_user(to, (void *)from_xxx, 8);
+ 		break;
+ 	default:
+ 		r = __copy_to_user(to, (void *)from_xxx, size);
+ 		break;
+ 	}
+ 	set_fs(oldfs);
+ 	return r;
+ }
+ 
+ /* For numa with replicated code/data, the platform must supply its own
+  * kdba_putarea_size and kdba_getarea_size routines.  Without replication kdb
+  * uses the standard architecture routines.
+  */
+ #ifdef CONFIG_NUMA_REPLICATE
+ extern int kdba_putarea_size(unsigned long to_xxx, void *from, size_t size);
+ extern int kdba_getarea_size(void *to, unsigned long from_xxx, size_t size);
+ #else
+ #define kdba_putarea_size __kdba_putarea_size
+ #define kdba_getarea_size __kdba_getarea_size
+ #endif
+ 
+ static inline int
+ kdba_verify_rw(unsigned long addr, size_t size)
+ {
+ 	unsigned char data[size];
+ 	return(kdba_getarea_size(data, addr, size) || kdba_putarea_size(addr, data, size));
+ }
+ 
+ static inline unsigned long
+ kdba_funcptr_value(void *fp)
+ {
+ 	return (unsigned long)fp;
+ }
+ 
+ #endif	/* !_ASM_KDB_H */
diff -c -r -N console-os/include/asm-i386/kdbprivate.h console-os-kdb/include/asm-i386/kdbprivate.h
*** console-os/include/asm-i386/kdbprivate.h	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/include/asm-i386/kdbprivate.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,209 ----
+ #ifndef	_ASM_KDBPRIVATE_H
+ #define _ASM_KDBPRIVATE_H
+ 
+ /*
+  * Kernel Debugger Architecture Dependent Private Headers
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ typedef unsigned char kdb_machinst_t;
+ 
+ 	/*
+ 	 * KDB_MAXBPT describes the total number of breakpoints
+ 	 * supported by this architecure.
+ 	 */
+ #define KDB_MAXBPT	16
+ 
+ 	/*
+ 	 * KDB_MAXHARDBPT describes the total number of hardware
+ 	 * breakpoint registers that exist.
+ 	 */
+ #define KDB_MAXHARDBPT	 4
+ 
+ 	/*
+ 	 * Platform specific environment entries
+ 	 */
+ #define KDB_PLATFORM_ENV	"IDMODE=x86", "BYTESPERWORD=4", "IDCOUNT=16"
+ 
+ 	/*
+ 	 * Define the direction that the stack grows
+ 	 */
+ #define KDB_STACK_DIRECTION	(-1)	/* Stack grows down */
+ 
+ 	/*
+ 	 * Support for ia32 debug registers
+ 	 */
+ typedef struct _kdbhard_bp {
+ 	kdb_machreg_t	bph_reg;	/* Register this breakpoint uses */
+ 
+ 	unsigned int	bph_free:1;	/* Register available for use */
+ 	unsigned int	bph_data:1;	/* Data Access breakpoint */
+ 
+ 	unsigned int	bph_write:1;	/* Write Data breakpoint */
+ 	unsigned int	bph_mode:2;	/* 0=inst, 1=write, 2=io, 3=read */
+ 	unsigned int	bph_length:2;	/* 0=1, 1=2, 2=BAD, 3=4 (bytes) */
+ } kdbhard_bp_t;
+ 
+ extern kdbhard_bp_t	kdb_hardbreaks[/* KDB_MAXHARDBPT */];
+ 
+ #define IA32_BREAKPOINT_INSTRUCTION	0xcc
+ 
+ #define DR6_BT  0x00008000
+ #define DR6_BS  0x00004000
+ #define DR6_BD  0x00002000
+ 
+ #define DR6_B3  0x00000008
+ #define DR6_B2  0x00000004
+ #define DR6_B1  0x00000002
+ #define DR6_B0  0x00000001
+ #define DR6_DR_MASK  0x0000000F
+ 
+ #define DR7_RW_VAL(dr, drnum) \
+        (((dr) >> (16 + (4 * (drnum)))) & 0x3)
+ 
+ #define DR7_RW_SET(dr, drnum, rw)                              \
+        do {                                                    \
+                (dr) &= ~(0x3 << (16 + (4 * (drnum))));         \
+                (dr) |= (((rw) & 0x3) << (16 + (4 * (drnum)))); \
+        } while (0)
+ 
+ #define DR7_RW0(dr)       DR7_RW_VAL(dr, 0)
+ #define DR7_RW0SET(dr,rw)  DR7_RW_SET(dr, 0, rw)
+ #define DR7_RW1(dr)       DR7_RW_VAL(dr, 1)
+ #define DR7_RW1SET(dr,rw)  DR7_RW_SET(dr, 1, rw)
+ #define DR7_RW2(dr)       DR7_RW_VAL(dr, 2)
+ #define DR7_RW2SET(dr,rw)  DR7_RW_SET(dr, 2, rw)
+ #define DR7_RW3(dr)       DR7_RW_VAL(dr, 3)
+ #define DR7_RW3SET(dr,rw)  DR7_RW_SET(dr, 3, rw)
+ 
+ 
+ #define DR7_LEN_VAL(dr, drnum) \
+        (((dr) >> (18 + (4 * (drnum)))) & 0x3)
+ 
+ #define DR7_LEN_SET(dr, drnum, rw)                             \
+        do {                                                    \
+                (dr) &= ~(0x3 << (18 + (4 * (drnum))));         \
+                (dr) |= (((rw) & 0x3) << (18 + (4 * (drnum)))); \
+        } while (0)
+ #define DR7_LEN0(dr)        DR7_LEN_VAL(dr, 0)
+ #define DR7_LEN0SET(dr,len)  DR7_LEN_SET(dr, 0, len)
+ #define DR7_LEN1(dr)        DR7_LEN_VAL(dr, 1)
+ #define DR7_LEN1SET(dr,len)  DR7_LEN_SET(dr, 1, len)
+ #define DR7_LEN2(dr)        DR7_LEN_VAL(dr, 2)
+ #define DR7_LEN2SET(dr,len)  DR7_LEN_SET(dr, 2, len)
+ #define DR7_LEN3(dr)        DR7_LEN_VAL(dr, 3)
+ #define DR7_LEN3SET(dr,len)  DR7_LEN_SET(dr, 3, len)
+ 
+ #define DR7_G0(dr)    (((dr)>>1)&0x1)
+ #define DR7_G0SET(dr) ((dr) |= 0x2)
+ #define DR7_G0CLR(dr) ((dr) &= ~0x2)
+ #define DR7_G1(dr)    (((dr)>>3)&0x1)
+ #define DR7_G1SET(dr) ((dr) |= 0x8)
+ #define DR7_G1CLR(dr) ((dr) &= ~0x8)
+ #define DR7_G2(dr)    (((dr)>>5)&0x1)
+ #define DR7_G2SET(dr) ((dr) |= 0x20)
+ #define DR7_G2CLR(dr) ((dr) &= ~0x20)
+ #define DR7_G3(dr)    (((dr)>>7)&0x1)
+ #define DR7_G3SET(dr) ((dr) |= 0x80)
+ #define DR7_G3CLR(dr) ((dr) &= ~0x80)
+ 
+ #define DR7_L0(dr)    (((dr))&0x1)
+ #define DR7_L0SET(dr) ((dr) |= 0x1)
+ #define DR7_L0CLR(dr) ((dr) &= ~0x1)
+ #define DR7_L1(dr)    (((dr)>>2)&0x1)
+ #define DR7_L1SET(dr) ((dr) |= 0x4)
+ #define DR7_L1CLR(dr) ((dr) &= ~0x4)
+ #define DR7_L2(dr)    (((dr)>>4)&0x1)
+ #define DR7_L2SET(dr) ((dr) |= 0x10)
+ #define DR7_L2CLR(dr) ((dr) &= ~0x10)
+ #define DR7_L3(dr)    (((dr)>>6)&0x1)
+ #define DR7_L3SET(dr) ((dr) |= 0x40)
+ #define DR7_L3CLR(dr) ((dr) &= ~0x40)
+ 
+ #define DR7_GD          0x00002000              /* General Detect Enable */
+ #define DR7_GE          0x00000200              /* Global exact */
+ #define DR7_LE          0x00000100              /* Local exact */
+ 
+ #define DR_TYPE_EXECUTE	0x0
+ #define DR_TYPE_WRITE	0x1
+ #define DR_TYPE_IO	0x2
+ #define DR_TYPE_RW	0x3
+ 
+ extern kdb_machreg_t kdba_getdr6(void);
+ extern void kdba_putdr6(kdb_machreg_t);
+ 
+ extern kdb_machreg_t kdba_getdr7(void);
+ 
+ extern kdb_machreg_t kdba_getdr(int);
+ extern void kdba_putdr(int, kdb_machreg_t);
+ 
+ extern kdb_machreg_t kdb_getcr(int);
+ 
+ #define KDB_HAVE_LONGJMP
+ #ifdef KDB_HAVE_LONGJMP
+ /*
+  * Support for setjmp/longjmp
+  */
+ #define JB_BX   0
+ #define JB_SI   1
+ #define JB_DI   2
+ #define JB_BP   3
+ #define JB_SP   4
+ #define JB_PC   5
+ 
+ typedef struct __kdb_jmp_buf {
+         unsigned long   regs[6];	/* kdba_setjmp assumes fixed offsets here */
+ } kdb_jmp_buf;
+ 
+ extern int kdba_setjmp(kdb_jmp_buf *);
+ extern void kdba_longjmp(kdb_jmp_buf *, int);
+ 
+ extern kdb_jmp_buf  kdbjmpbuf[];
+ #endif	/* KDB_HAVE_LONGJMP */
+ 
+ /* Arch specific data saved for running processes */
+ 
+ struct kdba_running_process {
+ 	int dummy[0];	/* Everything is in pt_regs for i386 */
+ };
+ 
+ static inline
+ void kdba_save_running(struct kdba_running_process *k, struct pt_regs *regs)
+ {
+ }
+ 
+ static inline
+ void kdba_unsave_running(struct kdba_running_process *k, struct pt_regs *regs)
+ {
+ }
+ 
+ #endif	/* !_ASM_KDBPRIVATE_H */
diff -c -r -N console-os/include/asm-i386/keyboard.h console-os-kdb/include/asm-i386/keyboard.h
*** console-os/include/asm-i386/keyboard.h	2007-01-09 18:01:54.000000000 -0800
--- console-os-kdb/include/asm-i386/keyboard.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 42,47 ****
--- 42,48 ----
  #define kbd_sysrq_xlate		pckbd_sysrq_xlate
  
  #define SYSRQ_KEY 0x54
+ #define E1_PAUSE   119		/* PAUSE key */
  
  /* resource allocation */
  #define kbd_request_region()
diff -c -r -N console-os/include/asm-i386/kmap_types.h console-os-kdb/include/asm-i386/kmap_types.h
*** console-os/include/asm-i386/kmap_types.h	2006-11-20 12:24:13.000000000 -0800
--- console-os-kdb/include/asm-i386/kmap_types.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 27,32 ****
--- 27,33 ----
  	KM_SOFTIRQ0,
  	KM_SOFTIRQ1,
  	KM_NETDUMP,
+ 	KM_KDB,
  	KM_TYPE_NR
  };
  
diff -c -r -N console-os/include/asm-i386/ptrace.h console-os-kdb/include/asm-i386/ptrace.h
*** console-os/include/asm-i386/ptrace.h	2006-11-20 12:24:14.000000000 -0800
--- console-os-kdb/include/asm-i386/ptrace.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 54,59 ****
--- 54,82 ----
  #define PTRACE_GET_THREAD_AREA    25
  #define PTRACE_SET_THREAD_AREA    26
  
+ enum EFLAGS {
+         EF_CF   = 0x00000001,
+         EF_PF   = 0x00000004,
+         EF_AF   = 0x00000010,
+         EF_ZF   = 0x00000040,
+         EF_SF   = 0x00000080,
+         EF_TF   = 0x00000100,
+         EF_IE   = 0x00000200,
+         EF_DF   = 0x00000400,
+         EF_OF   = 0x00000800,
+         EF_IOPL = 0x00003000,
+         EF_IOPL_RING0 = 0x00000000,
+         EF_IOPL_RING1 = 0x00001000,
+         EF_IOPL_RING2 = 0x00002000,
+         EF_NT   = 0x00004000,   /* nested task */
+         EF_RF   = 0x00010000,   /* resume */
+         EF_VM   = 0x00020000,   /* virtual mode */
+         EF_AC   = 0x00040000,   /* alignment */
+         EF_VIF  = 0x00080000,   /* virtual interrupt */
+         EF_VIP  = 0x00100000,   /* virtual interrupt pending */
+         EF_ID   = 0x00200000,   /* id */
+ };
+ 
  #ifdef __KERNEL__
  #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
  #define instruction_pointer(regs) ((regs)->eip)
diff -c -r -N console-os/include/linux/dis-asm.h console-os-kdb/include/linux/dis-asm.h
*** console-os/include/linux/dis-asm.h	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/include/linux/dis-asm.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,307 ----
+ /* Interface between the opcode library and its callers.
+    Written by Cygnus Support, 1993.
+ 
+    The opcode library (libopcodes.a) provides instruction decoders for
+    a large variety of instruction sets, callable with an identical
+    interface, for making instruction-processing programs more independent
+    of the instruction set being processed.  */
+ 
+ /* Hacked by Scott Lurndal at SGI (02/1999) for linux kernel debugger */
+ /* Upgraded to cygnus CVS Keith Owens <kaos@sgi.com> 30 Oct 2000 */
+ 
+ #ifndef DIS_ASM_H
+ #define DIS_ASM_H
+ 
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ 
+ 	/*
+ 	 * Misc definitions
+ 	 */
+ #ifndef PARAMS
+ #define PARAMS(x)	x
+ #endif
+ #define PTR void *
+ #define FILE int
+ #if !defined(NULL)
+ #define NULL 0
+ #endif
+ 
+ #define abort()		dis_abort(__LINE__)
+ 
+ static inline void
+ dis_abort(int line)
+ {
+ 	panic("Aborting disassembler @ line %d\n", line);
+ }
+ 
+ #include <linux/slab.h>
+ #include <asm/page.h>
+ #define xstrdup(string) ({ char *res = kdb_strdup(string, GFP_ATOMIC); if (!res) BUG(); res; })
+ #define xmalloc(size) ({ void *res = kmalloc(size, GFP_ATOMIC); if (!res) BUG(); res; })
+ #define free(address) kfree(address)
+ 
+ #include <bfd.h>
+ 
+ typedef int (*fprintf_ftype) PARAMS((PTR, const char*, ...));
+ 
+ enum dis_insn_type {
+   dis_noninsn,			/* Not a valid instruction */
+   dis_nonbranch,		/* Not a branch instruction */
+   dis_branch,			/* Unconditional branch */
+   dis_condbranch,		/* Conditional branch */
+   dis_jsr,			/* Jump to subroutine */
+   dis_condjsr,			/* Conditional jump to subroutine */
+   dis_dref,			/* Data reference instruction */
+   dis_dref2			/* Two data references in instruction */
+ };
+ 
+ /* This struct is passed into the instruction decoding routine, 
+    and is passed back out into each callback.  The various fields are used
+    for conveying information from your main routine into your callbacks,
+    for passing information into the instruction decoders (such as the
+    addresses of the callback functions), or for passing information
+    back from the instruction decoders to their callers.
+ 
+    It must be initialized before it is first passed; this can be done
+    by hand, or using one of the initialization macros below.  */
+ 
+ typedef struct disassemble_info {
+   fprintf_ftype fprintf_func;
+   fprintf_ftype fprintf_dummy;
+   PTR stream;
+   PTR application_data;
+ 
+   /* Target description.  We could replace this with a pointer to the bfd,
+      but that would require one.  There currently isn't any such requirement
+      so to avoid introducing one we record these explicitly.  */
+   /* The bfd_flavour.  This can be bfd_target_unknown_flavour.  */
+   enum bfd_flavour flavour;
+   /* The bfd_arch value.  */
+   enum bfd_architecture arch;
+   /* The bfd_mach value.  */
+   unsigned long mach;
+   /* Endianness (for bi-endian cpus).  Mono-endian cpus can ignore this.  */
+   enum bfd_endian endian;
+ 
+   /* An array of pointers to symbols either at the location being disassembled
+      or at the start of the function being disassembled.  The array is sorted
+      so that the first symbol is intended to be the one used.  The others are
+      present for any misc. purposes.  This is not set reliably, but if it is
+      not NULL, it is correct.  */
+   asymbol **symbols;
+   /* Number of symbols in array.  */
+   int num_symbols;
+ 
+   /* For use by the disassembler.
+      The top 16 bits are reserved for public use (and are documented here).
+      The bottom 16 bits are for the internal use of the disassembler.  */
+   unsigned long flags;
+ #define INSN_HAS_RELOC	0x80000000
+   PTR private_data;
+ 
+   /* Function used to get bytes to disassemble.  MEMADDR is the
+      address of the stuff to be disassembled, MYADDR is the address to
+      put the bytes in, and LENGTH is the number of bytes to read.
+      INFO is a pointer to this struct.
+      Returns an errno value or 0 for success.  */
+   int (*read_memory_func)
+     PARAMS ((bfd_vma memaddr, bfd_byte *myaddr, unsigned int length,
+ 	     struct disassemble_info *info));
+ 
+   /* Function which should be called if we get an error that we can't
+      recover from.  STATUS is the errno value from read_memory_func and
+      MEMADDR is the address that we were trying to read.  INFO is a
+      pointer to this struct.  */
+   void (*memory_error_func)
+     PARAMS ((int status, bfd_vma memaddr, struct disassemble_info *info));
+ 
+   /* Function called to print ADDR.  */
+   void (*print_address_func)
+     PARAMS ((bfd_vma addr, struct disassemble_info *info));
+ 
+   /* Function called to determine if there is a symbol at the given ADDR.
+      If there is, the function returns 1, otherwise it returns 0.
+      This is used by ports which support an overlay manager where
+      the overlay number is held in the top part of an address.  In
+      some circumstances we want to include the overlay number in the
+      address, (normally because there is a symbol associated with
+      that address), but sometimes we want to mask out the overlay bits.  */
+   int (* symbol_at_address_func)
+     PARAMS ((bfd_vma addr, struct disassemble_info * info));
+ 
+   /* These are for buffer_read_memory.  */
+   bfd_byte *buffer;
+   bfd_vma buffer_vma;
+   unsigned int buffer_length;
+ 
+   /* This variable may be set by the instruction decoder.  It suggests
+       the number of bytes objdump should display on a single line.  If
+       the instruction decoder sets this, it should always set it to
+       the same value in order to get reasonable looking output.  */
+   int bytes_per_line;
+ 
+   /* the next two variables control the way objdump displays the raw data */
+   /* For example, if bytes_per_line is 8 and bytes_per_chunk is 4, the */
+   /* output will look like this:
+      00:   00000000 00000000
+      with the chunks displayed according to "display_endian". */
+   int bytes_per_chunk;
+   enum bfd_endian display_endian;
+ 
+   /* Number of octets per incremented target address 
+      Normally one, but some DSPs have byte sizes of 16 or 32 bits
+    */
+   unsigned int octets_per_byte;
+ 
+   /* Results from instruction decoders.  Not all decoders yet support
+      this information.  This info is set each time an instruction is
+      decoded, and is only valid for the last such instruction.
+ 
+      To determine whether this decoder supports this information, set
+      insn_info_valid to 0, decode an instruction, then check it.  */
+ 
+   char insn_info_valid;		/* Branch info has been set. */
+   char branch_delay_insns;	/* How many sequential insn's will run before
+ 				   a branch takes effect.  (0 = normal) */
+   char data_size;		/* Size of data reference in insn, in bytes */
+   enum dis_insn_type insn_type;	/* Type of instruction */
+   bfd_vma target;		/* Target address of branch or dref, if known;
+ 				   zero if unknown.  */
+   bfd_vma target2;		/* Second target address for dref2 */
+ 
+   /* Command line options specific to the target disassembler.  */
+   char * disassembler_options;
+ 
+ } disassemble_info;
+ 
+ 
+ /* Standard disassemblers.  Disassemble one instruction at the given
+    target address.  Return number of bytes processed.  */
+ typedef int (*disassembler_ftype)
+      PARAMS((bfd_vma, disassemble_info *));
+ 
+ extern int print_insn_big_mips		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_little_mips	PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_i386_att		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_i386_intel	PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_ia64		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_i370		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_m68hc11		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_m68hc12		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_m68k		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_z8001		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_z8002		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_h8300		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_h8300h		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_h8300s		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_h8500		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_alpha		PARAMS ((bfd_vma, disassemble_info*));
+ extern disassembler_ftype arc_get_disassembler PARAMS ((int, int));
+ extern int print_insn_big_arm		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_little_arm	PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_sparc		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_big_a29k		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_little_a29k	PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_i860		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_i960		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_sh		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_shl		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_hppa		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_fr30		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_m32r		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_m88k		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_mcore		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_mn10200		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_mn10300		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_ns32k		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_big_powerpc	PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_little_powerpc	PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_rs6000		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_w65		PARAMS ((bfd_vma, disassemble_info*));
+ extern disassembler_ftype cris_get_disassembler PARAMS ((bfd *));
+ extern int print_insn_d10v		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_d30v		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_v850		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_tic30		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_vax		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_tic54x		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_tic80		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_pj		PARAMS ((bfd_vma, disassemble_info*));
+ extern int print_insn_avr		PARAMS ((bfd_vma, disassemble_info*));
+ 
+ extern void print_arm_disassembler_options PARAMS ((FILE *));
+ extern void parse_arm_disassembler_option  PARAMS ((char *));
+ extern int  get_arm_regname_num_options    PARAMS ((void));
+ extern int  set_arm_regname_option         PARAMS ((int));
+ extern int  get_arm_regnames               PARAMS ((int, const char **, const char **, const char ***));
+ 
+ /* Fetch the disassembler for a given BFD, if that support is available.  */
+ extern disassembler_ftype disassembler	PARAMS ((bfd *));
+ 
+ /* Document any target specific options available from the disassembler.  */
+ extern void disassembler_usage          PARAMS ((FILE *));
+ 
+ 
+ /* This block of definitions is for particular callers who read instructions
+    into a buffer before calling the instruction decoder.  */
+ 
+ /* Here is a function which callers may wish to use for read_memory_func.
+    It gets bytes from a buffer.  */
+ extern int buffer_read_memory
+   PARAMS ((bfd_vma, bfd_byte *, unsigned int, struct disassemble_info *));
+ 
+ /* This function goes with buffer_read_memory.
+    It prints a message using info->fprintf_func and info->stream.  */
+ extern void perror_memory PARAMS ((int, bfd_vma, struct disassemble_info *));
+ 
+ 
+ /* Just print the address in hex.  This is included for completeness even
+    though both GDB and objdump provide their own (to print symbolic
+    addresses).  */
+ extern void generic_print_address
+   PARAMS ((bfd_vma, struct disassemble_info *));
+ 
+ /* Always true.  */
+ extern int generic_symbol_at_address
+   PARAMS ((bfd_vma, struct disassemble_info *));
+ 
+ /* Macro to initialize a disassemble_info struct.  This should be called
+    by all applications creating such a struct.  */
+ #define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \
+   (INFO).flavour = bfd_target_unknown_flavour, \
+   (INFO).arch = bfd_arch_unknown, \
+   (INFO).mach = 0, \
+   (INFO).endian = BFD_ENDIAN_UNKNOWN, \
+   (INFO).octets_per_byte = 1, \
+   INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC)
+ 
+ /* Call this macro to initialize only the internal variables for the
+    disassembler.  Architecture dependent things such as byte order, or machine
+    variant are not touched by this macro.  This makes things much easier for
+    GDB which must initialize these things separately.  */
+ 
+ #define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \
+   (INFO).fprintf_func = (fprintf_ftype)(FPRINTF_FUNC), \
+   (INFO).stream = (PTR)(STREAM), \
+   (INFO).symbols = NULL, \
+   (INFO).num_symbols = 0, \
+   (INFO).buffer = NULL, \
+   (INFO).buffer_vma = 0, \
+   (INFO).buffer_length = 0, \
+   (INFO).read_memory_func = buffer_read_memory, \
+   (INFO).memory_error_func = perror_memory, \
+   (INFO).print_address_func = generic_print_address, \
+   (INFO).symbol_at_address_func = generic_symbol_at_address, \
+   (INFO).flags = 0, \
+   (INFO).bytes_per_line = 0, \
+   (INFO).bytes_per_chunk = 0, \
+   (INFO).display_endian = BFD_ENDIAN_UNKNOWN, \
+   (INFO).insn_info_valid = 0
+ 
+ #ifdef __cplusplus
+ };
+ #endif
+ 
+ #endif /* ! defined (DIS_ASM_H) */
diff -c -r -N console-os/include/linux/kallsyms.h console-os-kdb/include/linux/kallsyms.h
*** console-os/include/linux/kallsyms.h	2007-01-09 18:01:54.000000000 -0800
--- console-os-kdb/include/linux/kallsyms.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 24,29 ****
--- 24,198 ----
     Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   */
  
+ #ifndef MODUTILS_KALLSYMS_H
+ #define MODUTILS_KALLSYMS_H 1
+ 
+ /* Have to (re)define these ElfW entries here because external kallsyms
+  * code does not have access to modutils/include/obj.h.  This code is
+  * included from user spaces tools (modutils) and kernel, they need
+  * different includes.
+  */
+ 
+ #ifndef ELFCLASS32
+ #ifdef __KERNEL__
+ #include <linux/elf.h>
+ #else	/* __KERNEL__ */
+ #include <elf.h>
+ #endif	/* __KERNEL__ */
+ #endif	/* ELFCLASS32 */
+ 
+ #ifndef ELFCLASSM
+ #define ELFCLASSM ELF_CLASS
+ #endif
+ 
+ #ifndef ElfW
+ # if ELFCLASSM == ELFCLASS32
+ #  define ElfW(x)  Elf32_ ## x
+ #  define ELFW(x)  ELF32_ ## x
+ # else
+ #  define ElfW(x)  Elf64_ ## x
+ #  define ELFW(x)  ELF64_ ## x
+ # endif
+ #endif
+ 
+ /* Format of data in the kallsyms section.
+  * Most of the fields are small numbers but the total size and all
+  * offsets can be large so use the 32/64 bit types for these fields.
+  *
+  * Do not use sizeof() on these structures, modutils may be using extra
+  * fields.  Instead use the size fields in the header to access the
+  * other bits of data.
+  */  
+ 
+ struct kallsyms_header {
+ 	int		size;		/* Size of this header */
+ 	ElfW(Word)	total_size;	/* Total size of kallsyms data */
+ 	int		sections;	/* Number of section entries */
+ 	ElfW(Off)	section_off;	/* Offset to first section entry */
+ 	int		section_size;	/* Size of one section entry */
+ 	int		symbols;	/* Number of symbol entries */
+ 	ElfW(Off)	symbol_off;	/* Offset to first symbol entry */
+ 	int		symbol_size;	/* Size of one symbol entry */
+ 	ElfW(Off)	string_off;	/* Offset to first string */
+ 	ElfW(Addr)	start;		/* Start address of first section */
+ 	ElfW(Addr)	end;		/* End address of last section */
+ };
+ 
+ struct kallsyms_section {
+ 	ElfW(Addr)	start;		/* Start address of section */
+ 	ElfW(Word)	size;		/* Size of this section */
+ 	ElfW(Off)	name_off;	/* Offset to section name */
+ 	ElfW(Word)	flags;		/* Flags from section */
+ };
+ 
+ struct kallsyms_symbol {
+ 	ElfW(Off)	section_off;	/* Offset to section that owns this symbol */
+ 	ElfW(Addr)	symbol_addr;	/* Address of symbol */
+ 	ElfW(Off)	name_off;	/* Offset to symbol name */
+ };
+ 
+ #define KALLSYMS_SEC_NAME "__kallsyms"
+ #define KALLSYMS_IDX 2			/* obj_kallsyms creates kallsyms as section 2 */
+ 
+ #define kallsyms_next_sec(h,s) \
+ 	((s) = (struct kallsyms_section *)((char *)(s) + (h)->section_size))
+ #define kallsyms_next_sym(h,s) \
+ 	((s) = (struct kallsyms_symbol *)((char *)(s) + (h)->symbol_size))
+ 
+ #ifdef CONFIG_KALLSYMS
+ 
+ int kallsyms_symbol_to_address(
+ 	const char       *name,			/* Name to lookup */
+ 	unsigned long    *token,		/* Which module to start with */
+ 	const char      **mod_name,		/* Set to module name or "kernel" */
+ 	unsigned long    *mod_start,		/* Set to start address of module */
+ 	unsigned long    *mod_end,		/* Set to end address of module */
+ 	const char      **sec_name,		/* Set to section name */
+ 	unsigned long    *sec_start,		/* Set to start address of section */
+ 	unsigned long    *sec_end,		/* Set to end address of section */
+ 	const char      **sym_name,		/* Set to full symbol name */
+ 	unsigned long    *sym_start,		/* Set to start address of symbol */
+ 	unsigned long    *sym_end		/* Set to end address of symbol */
+ 	);
+ 
+ int kallsyms_address_to_symbol(
+ 	unsigned long     address,		/* Address to lookup */
+ 	const char      **mod_name,		/* Set to module name */
+ 	unsigned long    *mod_start,		/* Set to start address of module */
+ 	unsigned long    *mod_end,		/* Set to end address of module */
+ 	const char      **sec_name,		/* Set to section name */
+ 	unsigned long    *sec_start,		/* Set to start address of section */
+ 	unsigned long    *sec_end,		/* Set to end address of section */
+ 	const char      **sym_name,		/* Set to full symbol name */
+ 	unsigned long    *sym_start,		/* Set to start address of symbol */
+ 	unsigned long    *sym_end		/* Set to end address of symbol */
+ 	);
+ 
+ int kallsyms_sections(void *token,
+ 		      int (*callback)(void *,	/* token */
+ 		      	const char *,		/* module name */
+ 			const char *,		/* section name */
+ 			ElfW(Addr),		/* Section start */
+ 			ElfW(Addr),		/* Section end */
+ 			ElfW(Word)		/* Section flags */
+ 		      )
+ 		);
+ 
+ #else
+ 
+ static inline int kallsyms_address_to_symbol(
+ 	unsigned long     address,		/* Address to lookup */
+ 	const char      **mod_name,		/* Set to module name */
+ 	unsigned long    *mod_start,		/* Set to start address of module */
+ 	unsigned long    *mod_end,		/* Set to end address of module */
+ 	const char      **sec_name,		/* Set to section name */
+ 	unsigned long    *sec_start,		/* Set to start address of section */
+ 	unsigned long    *sec_end,		/* Set to end address of section */
+ 	const char      **sym_name,		/* Set to full symbol name */
+ 	unsigned long    *sym_start,		/* Set to start address of symbol */
+ 	unsigned long    *sym_end		/* Set to end address of symbol */
+ 	)
+ {
+ 	return -ESRCH;
+ }
+ 
+ #endif
+ 
+ int kallsyms_symbol_complete(
+ 	char	 *prefix_name	/* Prefix of a symbol name to lookup */
+ 	);
+ int kallsyms_symbol_next(
+ 	char	 *prefix_name,	/* Prefix of a symbol name to lookup */
+ 	int flag			/* Indicate if search from the head */
+ 	);
+ 
+ #endif /* kallsyms.h */
+ /* kallsyms headers
+    Copyright 2000 Keith Owens <kaos@ocs.com.au>
+ 
+    This file is part of the Linux modutils.  It is exported to kernel
+    space so debuggers can access the kallsyms data.
+ 
+    The kallsyms data contains all the non-stack symbols from a kernel
+    or a module.  The kernel symbols are held between __start___kallsyms
+    and __stop___kallsyms.  The symbols for a module are accessed via
+    the struct module chain which is based at module_list.
+ 
+    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 of the License, 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.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software Foundation,
+    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  */
+ 
  #ident "$Id: linux-2.4.9-kallsyms.patch,v 1.8 2002/02/11 18:34:53 arjanv Exp $"
  
  #ifndef MODUTILS_KALLSYMS_H
diff -c -r -N console-os/include/linux/kdb.h console-os-kdb/include/linux/kdb.h
*** console-os/include/linux/kdb.h	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/include/linux/kdb.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,339 ----
+ #ifndef _KDB_H
+ #define _KDB_H
+ 
+ /*
+  * Kernel Debugger Architecture Independent Global Headers
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+  * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/config.h>
+ #include <linux/init.h>
+ #include <linux/sched.h>
+ #include <asm/kdb.h>
+ 
+ #define KDB_MAJOR_VERSION	4
+ #define KDB_MINOR_VERSION	3
+ #define KDB_TEST_VERSION	""
+ 
+ 	/*
+ 	 * kdb_initial_cpu is initialized to -1, and is set to the cpu
+ 	 * number whenever the kernel debugger is entered.
+ 	 */
+ extern volatile int kdb_initial_cpu;	
+ #ifdef	CONFIG_KDB
+ #define KDB_IS_RUNNING() (kdb_initial_cpu != -1)
+ #else
+ #define KDB_IS_RUNNING() (0)
+ #endif	/* CONFIG_KDB */
+ 
+ 	/*
+ 	 * kdb_on
+ 	 *
+ 	 * 	Defines whether kdb is on or not.  Default value
+ 	 *	is set by CONFIG_KDB_OFF.  Boot with kdb=on/off
+ 	 *	or echo "[01]" > /proc/sys/kernel/kdb to change it.
+ 	 */
+ extern int kdb_on;
+ 
+ 	/* Global 'enter the debugger' variable tested by scheduler, spinlocks
+ 	 * etc., to handle problems when interrupts are not working or are not
+ 	 * safe.
+ 	 */
+ extern volatile int kdb_enter_debugger;
+ 
+ #if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SGI_L1_SERIAL_CONSOLE)
+ 	/*
+ 	 * kdb_serial.iobase is initialized to zero, and is set to the I/O
+ 	 * address of the serial port when the console is setup in
+ 	 * serial_console_setup.
+ 	 */
+ extern struct kdb_serial {
+ 	int io_type;
+ 	unsigned long iobase;
+ 	unsigned long ioreg_shift;
+ } kdb_serial;
+ #endif
+ 
+ 	/*
+ 	 * kdb_diemsg
+ 	 *
+ 	 *	Contains a pointer to the last string supplied to the
+ 	 *	kernel 'die' panic function.
+ 	 */
+ extern const char *kdb_diemsg;
+ 
+ #define KDB_FLAG_EARLYKDB	(1 << 0)	/* set from boot parameter kdb=early */
+ #define KDB_FLAG_CATASTROPHIC	(1 << 1)	/* A catastrophic event has occurred */
+ #define KDB_FLAG_CMD_INTERRUPT	(1 << 2)	/* Previous command was interrupted */
+ #define KDB_FLAG_NOIPI		(1 << 3)	/* Do not send IPIs */
+ #define KDB_FLAG_ONLY_DO_DUMP	(1 << 4)	/* Only do a dump, used when kdb is off */
+ 
+ 	/*
+ 	 * Internal debug flags
+ 	 */
+ #define KDB_DEBUG_FLAG_BT	0x0001		/* Stack traceback debug */
+ #define KDB_DEBUG_FLAG_BP	0x0002		/* Breakpoint subsystem debug */
+ #define KDB_DEBUG_FLAG_LBR	0x0004		/* Print last branch register */
+ #define KDB_DEBUG_FLAG_AR	0x0008		/* Activation record, generic */
+ #define KDB_DEBUG_FLAG_ARA	0x0010		/* Activation record, arch specific */
+ /*      KDB_DEBUG_FLAG_CALLBACK	0x0020		WAS Event callbacks to kdb */
+ #define KDB_DEBUG_FLAG_STATE	0x0040		/* State flags */
+ #define KDB_DEBUG_FLAG_MASK	0xffff		/* All debug flags */
+ #define KDB_DEBUG_FLAG_SHIFT	16		/* Shift factor for dbflags */
+ 
+ extern volatile int kdb_flags;			/* Global flags, see kdb_state for per cpu state */
+ 
+ #define KDB_FLAG(flag)		(kdb_flags & KDB_FLAG_##flag)
+ #define KDB_FLAG_SET(flag)	((void)(kdb_flags |= KDB_FLAG_##flag))
+ #define KDB_FLAG_CLEAR(flag)	((void)(kdb_flags &= ~KDB_FLAG_##flag))
+ #define KDB_DEBUG(flag)		(kdb_flags & (KDB_DEBUG_FLAG_##flag << KDB_DEBUG_FLAG_SHIFT))
+ #define KDB_DEBUG_STATE(text,value)	if (KDB_DEBUG(STATE)) kdb_print_state(text, value)
+ 
+ 	/*
+ 	 * Per cpu kdb state.  A cpu can be under kdb control but outside kdb,
+ 	 * for example when doing single step.
+ 	 */
+ volatile extern int kdb_state[ /*NR_CPUS*/ ];
+ #define KDB_STATE_KDB		0x00000001	/* Cpu is inside kdb */
+ #define KDB_STATE_LEAVING	0x00000002	/* Cpu is leaving kdb */
+ #define KDB_STATE_CMD		0x00000004	/* Running a kdb command */
+ #define KDB_STATE_KDB_CONTROL	0x00000008	/* This cpu is under kdb control */
+ #define KDB_STATE_HOLD_CPU	0x00000010	/* Hold this cpu inside kdb */
+ #define KDB_STATE_DOING_SS	0x00000020	/* Doing ss command */
+ #define KDB_STATE_DOING_SSB	0x00000040	/* Doing ssb command, DOING_SS is also set */
+ #define KDB_STATE_SSBPT		0x00000080	/* Install breakpoint after one ss, independent of DOING_SS */
+ #define KDB_STATE_REENTRY	0x00000100	/* Valid re-entry into kdb */
+ #define KDB_STATE_SUPPRESS	0x00000200	/* Suppress error messages */
+ #define KDB_STATE_LONGJMP	0x00000400	/* longjmp() data is available */
+ #define KDB_STATE_GO_SWITCH	0x00000800	/* go is switching back to initial cpu */
+ #define KDB_STATE_PRINTF_LOCK	0x00001000	/* Holds kdb_printf lock */
+ #define KDB_STATE_WAIT_IPI	0x00002000	/* Waiting for kdb_ipi() NMI */
+ #define KDB_STATE_RECURSE	0x00004000	/* Recursive entry to kdb */
+ #define KDB_STATE_IP_ADJUSTED	0x00008000	/* Restart IP has been adjusted */
+ #define KDB_STATE_GO1		0x00010000	/* go only releases one cpu */
+ #define KDB_STATE_ARCH		0xff000000	/* Reserved for arch specific use */
+ 
+ #define KDB_STATE_CPU(flag,cpu)		(kdb_state[cpu] & KDB_STATE_##flag)
+ #define KDB_STATE_SET_CPU(flag,cpu)	((void)(kdb_state[cpu] |= KDB_STATE_##flag))
+ #define KDB_STATE_CLEAR_CPU(flag,cpu)	((void)(kdb_state[cpu] &= ~KDB_STATE_##flag))
+ 
+ #define KDB_STATE(flag)		KDB_STATE_CPU(flag,smp_processor_id())
+ #define KDB_STATE_SET(flag)	KDB_STATE_SET_CPU(flag,smp_processor_id())
+ #define KDB_STATE_CLEAR(flag)	KDB_STATE_CLEAR_CPU(flag,smp_processor_id())
+ 
+ 	/*
+ 	 * External entry point for the kernel debugger.  The pt_regs
+ 	 * at the time of entry are supplied along with the reason for
+ 	 * entry to the kernel debugger.
+ 	 */
+ 
+ typedef enum {
+ 	KDB_REASON_CALL = 1,		/* Call kdb() directly - regs should be valid */
+ 	KDB_REASON_FAULT,		/* Kernel fault - regs valid */
+ 	KDB_REASON_BREAK,		/* Breakpoint inst. - regs valid */
+ 	KDB_REASON_DEBUG,		/* Debug Fault - regs valid */
+ 	KDB_REASON_OOPS,		/* Kernel Oops - regs valid */
+ 	KDB_REASON_SWITCH,		/* CPU switch - regs valid*/
+ 	KDB_REASON_ENTER,		/* KDB_ENTER() trap/fault - regs valid */
+ 	KDB_REASON_KEYBOARD,		/* Keyboard entry - regs valid */
+ 	KDB_REASON_NMI,			/* Non-maskable interrupt; regs valid */
+ 	KDB_REASON_WATCHDOG,		/* Watchdog interrupt; regs valid */
+ 	KDB_REASON_RECURSE,		/* Recursive entry to kdb; regs probably valid */
+ 	KDB_REASON_SILENT,		/* Silent entry/exit to kdb; regs invalid */
+ 	KDB_REASON_CALL_PRESET,		/* Same as KDB_REASON_CALL but kdb_process_running has been preset */
+ } kdb_reason_t;
+ 
+ typedef enum {
+ 	KDB_REPEAT_NONE = 0,		/* Do not repeat this command */
+ 	KDB_REPEAT_NO_ARGS,		/* Repeat the command without arguments */
+ 	KDB_REPEAT_WITH_ARGS,		/* Repeat the command including its arguments */
+ } kdb_repeat_t;
+ 
+ #ifdef	CONFIG_KDB
+ extern int   kdb(kdb_reason_t, int, struct pt_regs *);
+ #else
+ #define kdb(reason,error_code,frame) (0)
+ #endif
+ 
+ typedef int (*kdb_func_t)(int, const char **, const char **, struct pt_regs *);
+ 
+ 	/*
+ 	 * Symbol table format returned by kallsyms.
+ 	 */
+ 
+ typedef struct __ksymtab {
+ 		unsigned long value;		/* Address of symbol */
+ 		const char *mod_name;		/* Module containing symbol or "kernel" */
+ 		unsigned long mod_start;
+ 		unsigned long mod_end;
+ 		const char *sec_name;		/* Section containing symbol */
+ 		unsigned long sec_start;
+ 		unsigned long sec_end;
+ 		const char *sym_name;		/* Full symbol name, including any version */
+ 		unsigned long sym_start;
+ 		unsigned long sym_end;
+ 		} kdb_symtab_t;
+ 
+ 	/*
+ 	 * Exported Symbols for kernel loadable modules to use.
+ 	 */
+ extern int           kdb_register(char *, kdb_func_t, char *, char *, short);
+ extern int           kdb_register_repeat(char *, kdb_func_t, char *, char *, short, kdb_repeat_t);
+ extern int           kdb_unregister(char *);
+ 
+ extern int	     kdb_getarea_size(void *, unsigned long, size_t);
+ extern int	     kdb_putarea_size(unsigned long, void *, size_t);
+ 
+ /* Like get_user and put_user, kdb_getarea and kdb_putarea take variable
+  * names, not pointers.  The underlying *_size functions take pointers.
+  */
+ #define kdb_getarea(x,addr)	kdb_getarea_size(&(x), addr, sizeof((x)))
+ #define kdb_putarea(addr,x)	kdb_putarea_size(addr, &(x), sizeof((x)))
+ 
+ extern int	     kdb_getword(unsigned long *, unsigned long, size_t);
+ extern int	     kdb_putword(unsigned long, unsigned long, size_t);
+ 
+ extern int	     kdbgetularg(const char *, unsigned long *);
+ extern char         *kdbgetenv(const char *);
+ extern int	     kdbgetintenv(const char *, int *);
+ extern int	     kdbgetaddrarg(int, const char**, int*, unsigned long *,
+ 			           long *, char **, struct pt_regs *);
+ extern int	     kdbgetsymval(const char *, kdb_symtab_t *);
+ extern int	     kdbnearsym(unsigned long, kdb_symtab_t *);
+ extern void	     kdb_printf(const char *,...)
+ 		     __attribute__ ((format (printf, 1, 2)));
+ extern void	     kdb_init(void);
+ extern void	     kdb_symbol_print(kdb_machreg_t, const kdb_symtab_t *, unsigned int);
+ extern char	    *kdb_read(char *buffer, size_t bufsize);
+ extern char	    *kdb_strdup(const char *str, int type);
+ 
+ #if defined(CONFIG_SMP)
+ 	/*
+ 	 * Kernel debugger non-maskable IPI handler.
+ 	 */
+ extern int           kdb_ipi(struct pt_regs *, void (*ack_interrupt)(void));
+ extern void	     smp_kdb_stop(void);
+ #else	/* CONFIG_SMP */
+ #define	smp_kdb_stop()
+ #endif	/* CONFIG_SMP */
+ 
+ 	/*
+ 	 * Interface from general kernel to enable any hardware
+ 	 * error reporting mechanisms.  Such as the Intel Machine
+ 	 * Check Architecture, for example.
+ 	 */
+ extern void	     kdb_enablehwfault(void);
+ 
+ 	 /*
+ 	  * Let other code know that kdb is in control.  Routines registered
+ 	  * on this list are called from the initial cpu with 1 when kdb is
+ 	  * entered and 0 when kdb exits.
+ 	  *
+ 	  * WARNING: If a module registers itself on this list (or any notifier
+ 	  * list) then there is a race condition.  The module could be in the
+ 	  * middle of removal on one cpu when it is called via the notifier
+ 	  * chain on another cpu.  It is the responsibility of the module to
+ 	  * prevent this race.  The safest way is for the module to define a
+ 	  * 'can_unload' function which unregisters the module from all
+ 	  * notifier chains before allowing the module to be unloaded.
+ 	  */
+ 
+ extern struct notifier_block *kdb_notifier_list;
+ 
+ 	 /*
+ 	  * Do we have a set of registers?
+ 	  */
+ 
+ #define KDB_NULL_REGS(regs) \
+ 	(regs == (struct pt_regs *)NULL ? kdb_printf("%s: null regs - should never happen\n", __FUNCTION__), 1 : 0)
+ 
+ 	 /*
+ 	  * Routine for debugging the debugger state.
+ 	  */
+ 
+ extern void kdb_print_state(const char *, int);
+ 
+ #ifdef CONFIG_KDB_USB
+ #include <linux/usb.h>
+ #define KDB_USB_ACTIVE 	1 /* Keyboard driver is usbkbd */
+ #define HID_ACTIVE 	2 /* Keyboard driver is hid    */
+ 
+ struct kdb_usb_exchange {
+ 	void *uhci;			/* pointer to the UHCI structure */
+   	struct urb *urb;		/* pointer to the URB */
+ 	unsigned char *buffer;		/* pointer to buffer */
+ 	void (*poll_func)(void *, struct urb *); /* pointer to the polling function */
+ 	void (*reset_timer)(void);	/* pointer to the reset timer function */
+ 	int driver;			/* driver mode, see above KDB_USB_KBD */
+ };
+ extern struct kdb_usb_exchange kdb_usb_infos; /* KDB common structure */
+ #endif /* CONFIG_KDB_USB */
+ 
+ #ifdef	MODULE
+ #define kdb_module_init(fn) module_init(fn)
+ #define kdb_module_exit(fn) module_exit(fn)
+ #else	/* !MODULE */
+ extern initcall_t __kdb_initcall_start, __kdb_initcall_end;
+ #define kdb_module_init(fn) \
+ 	static initcall_t __kdb_initcall_##fn __attribute__ ((unused,__section__ (".kdb_initcall.init"))) = fn;
+ #define kdb_module_exit(fn) \
+ 	static exitcall_t __kdb_exitcall_##fn __attribute__ ((unused,__section__ (".kdb_exitcall.exit"))) = fn;
+ #endif	/* MODULE */
+ 
+ 
+ /*
+  * A backport of the 2.5 scheduler is used by many vendors of 2.4-based
+  * distributions.
+  * We can only guess its presence by the lack of the SCHED_YIELD flag.
+  * If the heuristic doesn't work, change this define by hand.
+  */
+ #ifndef SCHED_YIELD
+ #define __KDB_HAVE_NEW_SCHEDULER    1
+ #endif
+ 
+ static inline
+ int kdb_process_cpu(const struct task_struct *p)
+ {
+ #ifdef __KDB_HAVE_NEW_SCHEDULER
+ 	return p->cpu;		/* p->cpu for O(1) scheduler */
+ #else
+ 	return p->processor;	/* p->processor for not O(1) scheduler */
+ #endif
+ }
+ 
+ extern struct task_struct *kdb_current_task;
+ extern struct page * kdb_follow_page(struct mm_struct *, unsigned long, int); /* from mm/memory.c */
+ 
+ extern const char kdb_serial_str[];
+ 
+ #endif	/* !_KDB_H */
diff -c -r -N console-os/include/linux/kdbprivate.h console-os-kdb/include/linux/kdbprivate.h
*** console-os/include/linux/kdbprivate.h	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/include/linux/kdbprivate.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,370 ----
+ #ifndef _KDBPRIVATE_H
+ #define _KDBPRIVATE_H
+ 
+ /*
+  * Kernel Debugger Architecture Independent Private Headers
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/dis-asm.h>
+ #include <asm/kdbprivate.h>
+ 
+ #include "bfd.h"
+ 
+ /*
+  * Kernel Debugger Error codes.  Must not overlap with command codes.
+  */
+ 
+ #define KDB_NOTFOUND	(-1)
+ #define KDB_ARGCOUNT	(-2)
+ #define KDB_BADWIDTH	(-3)
+ #define KDB_BADRADIX	(-4)
+ #define KDB_NOTENV	(-5)
+ #define KDB_NOENVVALUE	(-6)
+ #define KDB_NOTIMP	(-7)
+ #define KDB_ENVFULL	(-8)
+ #define KDB_ENVBUFFULL	(-9 )
+ #define KDB_TOOMANYBPT	(-10)
+ #define KDB_TOOMANYDBREGS (-11)
+ #define KDB_DUPBPT	(-12)
+ #define KDB_BPTNOTFOUND	(-13)
+ #define KDB_BADMODE	(-14)
+ #define KDB_BADINT	(-15)
+ #define KDB_INVADDRFMT  (-16)
+ #define KDB_BADREG      (-17)
+ #define KDB_BADCPUNUM   (-18)
+ #define KDB_BADLENGTH	(-19)
+ #define KDB_NOBP	(-20)
+ #define KDB_BADADDR	(-21)
+ 
+ /*
+  * Kernel Debugger Command codes.  Must not overlap with error codes.
+  */
+ #define KDB_CMD_GO	(-1001)
+ #define KDB_CMD_CPU	(-1002)
+ #define KDB_CMD_SS	(-1003)
+ #define KDB_CMD_SSB	(-1004)
+ 
+ 	/*
+ 	 * kdb_nextline
+ 	 *
+ 	 * 	Contains the current line number on the screen.  Used
+ 	 *	to handle the built-in pager (LINES env variable)
+ 	 */
+ extern volatile int kdb_nextline;
+ 
+ 	/*
+ 	 * Breakpoint state
+ 	 *
+ 	 * 	Each active and inactive breakpoint is represented by
+ 	 * 	an instance of the following data structure.
+ 	 */
+ 
+ typedef struct _kdb_bp {
+ 	bfd_vma 	bp_addr;	/* Address breakpoint is present at */
+ 	kdb_machinst_t	bp_inst;	/* Replaced instruction */
+ 
+ 	unsigned int	bp_free:1;	/* This entry is available */
+ 
+ 	unsigned int	bp_enabled:1;	/* Breakpoint is active in register */
+ 	unsigned int	bp_global:1;	/* Global to all processors */
+ 
+ 	unsigned int	bp_hardtype:1;	/* Uses hardware register */
+ 	unsigned int	bp_forcehw:1;	/* Force hardware register */
+ 	unsigned int	bp_installed:1;	/* Breakpoint is installed */
+ 	unsigned int	bp_delay:1;	/* Do delayed bp handling */
+ 	unsigned int	bp_delayed:1;	/* Delayed breakpoint */
+ 
+ 	int		bp_cpu;		/* Cpu #  (if bp_global == 0) */
+ 	kdbhard_bp_t	bp_template;	/* Hardware breakpoint template */
+ 	kdbhard_bp_t	*bp_hard;	/* Hardware breakpoint structure */
+ 	int		bp_adjust;	/* Adjustment to PC for real instruction */
+ } kdb_bp_t;
+ 
+ 	/*
+ 	 * Breakpoint handling subsystem global variables
+ 	 */
+ extern kdb_bp_t		kdb_breakpoints[/* KDB_MAXBPT */];
+ 
+ 	/*
+ 	 * Breakpoint architecture dependent functions.  Must be provided
+ 	 * in some form for all architectures.
+ 	 */
+ extern void 		kdba_initbp(void);
+ extern void		kdba_printbp(kdb_bp_t *);
+ extern void		kdba_printbpreg(kdbhard_bp_t *);
+ extern kdbhard_bp_t	*kdba_allocbp(kdbhard_bp_t *, int *);
+ extern void		kdba_freebp(kdbhard_bp_t *);
+ extern int		kdba_parsebp(int, const char**, int *, kdb_bp_t*);
+ extern char 		*kdba_bptype(kdbhard_bp_t *);
+ extern void		kdba_setsinglestep(struct pt_regs *);
+ extern void		kdba_clearsinglestep(struct pt_regs *);
+ 
+ 	/*
+ 	 * Adjust instruction pointer architecture dependent function.  Must be
+ 	 * provided in some form for all architectures.
+ 	 */
+ extern void		kdba_adjust_ip(kdb_reason_t, int, struct pt_regs *);
+ 
+ 	/*
+ 	 * KDB-only global function prototypes.
+ 	 */
+ extern void	     kdb_id1(unsigned long);
+ extern void	     kdb_id_init(void);
+ 
+ 	/*
+ 	 * Architecture dependent function to enable any
+ 	 * processor machine check exception handling modes.
+ 	 */
+ extern void	     kdba_enable_mce(void);
+ 
+ extern void	     kdba_enable_lbr(void);
+ extern void	     kdba_disable_lbr(void);
+ extern void	     kdba_print_lbr(void);
+ 
+ 	/*
+ 	 * Initialization functions.
+ 	 */
+ extern void	     kdba_init(void);
+ extern void	     kdb_io_init(void);
+ 
+ 	/*
+ 	 * Architecture specific function to read a string.
+ 	 */
+ typedef int (*get_char_func)(void);
+ extern get_char_func poll_funcs[];
+ 
+ 	/*
+ 	 * Data for a single activation record on stack.
+ 	 */
+ 
+ typedef struct __kdb_activation_record {
+ 	kdb_machreg_t	start;		/* -> start of activation record */
+ 	kdb_machreg_t	end;		/* -> end+1 of activation record */
+ 	kdb_machreg_t	ret;		/* Return address to caller */
+ 	kdb_machreg_t	oldfp;		/* Frame pointer for caller's frame */
+ 	kdb_machreg_t	fp;		/* Frame pointer for callee's frame */
+ 	kdb_machreg_t	arg0;		/* -> First argument on stack (in previous ar) */
+ 	unsigned long	locals;		/* Bytes allocated for local variables */
+ 	unsigned long	regs;		/* Bytes allocated for saved registers */
+ 	unsigned long	args;		/* Bytes allocated for arguments (in previous ar) */
+ 	unsigned long	setup;		/* Bytes allocated for setup data */
+ } kdb_ar_t;
+ 
+ 	/*
+ 	 * General Stack Traceback functions.
+ 	 */
+ 
+ extern int	     kdb_get_next_ar(kdb_machreg_t, kdb_machreg_t,
+ 				     kdb_machreg_t, kdb_machreg_t,
+ 				     kdb_machreg_t,
+ 				     kdb_ar_t *, kdb_symtab_t *);
+ 
+ 	/*
+ 	 * Architecture specific Stack Traceback functions.
+ 	 */
+ 
+ struct task_struct;
+ 
+ extern int	     kdba_bt_address(kdb_machreg_t, int);
+ extern int	     kdba_bt_process(struct task_struct *, int);
+ extern int	     kdba_prologue(const kdb_symtab_t *, kdb_machreg_t,
+ 				   kdb_machreg_t, kdb_machreg_t, kdb_machreg_t,
+ 				   int, kdb_ar_t *);
+ 	/*
+ 	 * KDB Command Table
+ 	 */
+ 
+ typedef struct _kdbtab {
+         char    *cmd_name;		/* Command name */
+         kdb_func_t cmd_func;		/* Function to execute command */
+         char    *cmd_usage;		/* Usage String for this command */
+         char    *cmd_help;		/* Help message for this command */
+         short    cmd_flags;		/* Parsing flags */
+         short    cmd_minlen;		/* Minimum legal # command chars required */
+ 	kdb_repeat_t cmd_repeat;	/* Does command auto repeat on enter? */
+ } kdbtab_t;
+ 
+ 	/*
+ 	 * External command function declarations
+ 	 */
+ 
+ extern int kdb_id(int, const char **, const char **, struct pt_regs *);
+ extern int kdb_bp(int, const char **, const char **, struct pt_regs *);
+ extern int kdb_bc(int, const char **, const char **, struct pt_regs *);
+ extern int kdb_bt(int, const char **, const char **, struct pt_regs *);
+ extern int kdb_ss(int, const char **, const char **, struct pt_regs *);
+ 
+ 	/*
+ 	 * External utility function declarations
+ 	 */
+ extern char* kdb_getstr(char *, size_t, char *);
+ 
+ 	/*
+ 	 * Register contents manipulation
+ 	 */
+ extern int kdba_getregcontents(const char *, struct pt_regs *, kdb_machreg_t *);
+ extern int kdba_setregcontents(const char *, struct pt_regs *, kdb_machreg_t);
+ extern int kdba_dumpregs(struct pt_regs *, const char *, const char *);
+ extern int kdba_setpc(struct pt_regs *, kdb_machreg_t);
+ extern kdb_machreg_t   kdba_getpc(struct pt_regs *);
+ 
+ 	/*
+ 	 * Debug register handling.
+ 	 */
+ extern void kdba_installdbreg(kdb_bp_t*);
+ extern void kdba_removedbreg(kdb_bp_t*);
+ 
+ 	/*
+ 	 * Breakpoint handling - External interfaces
+ 	 */
+ extern void kdb_initbptab(void);
+ extern void kdb_bp_install_global(struct pt_regs *);
+ extern void kdb_bp_install_local(struct pt_regs *);
+ extern void kdb_bp_remove_global(void);
+ extern void kdb_bp_remove_local(void);
+ 
+ 	/*
+ 	 * Breakpoint handling - Internal to kdb_bp.c/kdba_bp.c
+ 	 */
+ extern int kdba_installbp(struct pt_regs *regs, kdb_bp_t *);
+ extern int kdba_removebp(kdb_bp_t *);
+ 
+ 
+ typedef enum {
+ 	KDB_DB_BPT,	/* Breakpoint */
+ 	KDB_DB_SS,	/* Single-step trap */
+ 	KDB_DB_SSB,	/* Single step to branch */
+ 	KDB_DB_SSBPT,	/* Single step over breakpoint */
+ 	KDB_DB_NOBPT	/* Spurious breakpoint */
+ } kdb_dbtrap_t;
+ 
+ extern kdb_dbtrap_t kdba_db_trap(struct pt_regs *, int);	/* DEBUG trap/fault handler */
+ extern kdb_dbtrap_t kdba_bp_trap(struct pt_regs *, int);	/* Breakpoint trap/fault hdlr */
+ 
+ 	/*
+ 	 * Interrupt Handling
+ 	 */
+ typedef int kdb_intstate_t;
+ 
+ extern void kdba_disableint(kdb_intstate_t *);
+ extern void kdba_restoreint(kdb_intstate_t *);
+ 
+ 	/*
+ 	 * SMP and process stack manipulation routines.
+ 	 */
+ extern int	     kdba_ipi(struct pt_regs *, void (*)(void));
+ extern int	     kdba_main_loop(kdb_reason_t, kdb_reason_t, int, kdb_dbtrap_t, struct pt_regs *);
+ extern int           kdb_main_loop(kdb_reason_t, kdb_reason_t, int, kdb_dbtrap_t, struct pt_regs *);
+ 
+ 	/*
+ 	 * General Disassembler interfaces
+ 	 */
+ extern int kdb_dis_fprintf(PTR, const char *, ...) __attribute__ ((format (printf, 2, 3)));
+ extern int kdb_dis_fprintf_dummy(PTR, const char *, ...) __attribute__ ((format (printf, 2, 3)));
+ extern disassemble_info	kdb_di;
+ 
+ 	/*
+ 	 * Architecture Dependent Disassembler interfaces
+ 	 */
+ extern void kdba_printaddress(kdb_machreg_t, disassemble_info *, int);
+ extern int  kdba_id_printinsn(kdb_machreg_t, disassemble_info *);
+ extern int  kdba_id_parsemode(const char *, disassemble_info*);
+ extern void kdba_id_init(disassemble_info *);
+ extern void kdba_check_pc(kdb_machreg_t *);
+ 
+ 	/*
+ 	 * Miscellaneous functions and data areas
+ 	 */
+ extern char *kdb_cmds[];
+ extern void kdb_syslog_data(char *syslog_data[]);
+ extern unsigned long kdb_task_state_string(int argc, const char **argv, const char **envp);
+ extern unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask);
+ extern void kdb_ps1(struct task_struct *p);
+ extern int kdb_parse(const char *cmdstr, struct pt_regs *regs);
+ extern void kdb_print_nameval(const char *name, unsigned long val);
+ 
+ 	/*
+ 	 * Architecture Dependant Local Processor setup & cleanup interfaces
+ 	 */
+ extern void kdba_local_arch_setup(void);
+ extern void kdba_local_arch_cleanup(void);
+ 
+ 	/*
+ 	 * Defines for kdb_symbol_print.
+ 	 */
+ #define KDB_SP_SPACEB	0x0001		/* Space before string */
+ #define KDB_SP_SPACEA	0x0002		/* Space after string */
+ #define KDB_SP_PAREN	0x0004		/* Parenthesis around string */
+ #define KDB_SP_VALUE	0x0008		/* Print the value of the address */
+ #define KDB_SP_SYMSIZE	0x0010		/* Print the size of the symbol */
+ #define KDB_SP_NEWLINE	0x0020		/* Newline after string */
+ #define KDB_SP_DEFAULT (KDB_SP_VALUE|KDB_SP_PAREN)
+ 
+ /* Save data about running processes */
+ 
+ struct kdb_running_process {
+ 	struct task_struct *p;
+ 	struct pt_regs *regs;
+ 	int seqno;				/* kdb sequence number */
+ 	struct kdba_running_process arch;	/* arch dependent save data */
+ };
+ 
+ extern struct kdb_running_process kdb_running_process[/* NR_CPUS */];
+ extern struct task_struct *kdb_active_task[/* NR_CPUS */];
+ 
+ extern void kdb_save_running(struct pt_regs *);
+ extern void kdb_unsave_running(struct pt_regs *);
+ 
+ /* 	Incremented each time the main kdb loop is entered on the initial cpu,
+  * 	it gives some indication of how old the saved data is.
+  */
+ extern int kdb_seqno;
+ 
+ /* Compatibility code until cpu_online() is in the standard kernel */
+ #ifndef cpu_online
+ #ifdef CONFIG_SMP
+ #define cpu_online(cpu) test_bit(cpu, &cpu_online_map)
+ #else  /* !SMP */
+ #define cpu_online(cpu) ({ BUG_ON((cpu) != 0); 1; })
+ #endif /* SMP */
+ #endif /* cpu_online */
+ 
+ /* kdb needs to know if a task owns the cpu.  Due to bugs in the scheduling code
+  * the initial tasks on each cpu do not decode correctly, uni-processor also has
+  * incorrect state for task_has_cpu.  Use my own function to workaround the
+  * scheduler bugs.
+  */
+ 
+ #define kdb_task_has_cpu(p) (kdb_active_task[kdb_process_cpu(p)] == p)
+ 
+ #endif	/* !_KDBPRIVATE_H */
diff -c -r -N console-os/include/linux/module.h console-os-kdb/include/linux/module.h
*** console-os/include/linux/module.h	2007-01-09 18:01:54.000000000 -0800
--- console-os-kdb/include/linux/module.h	2007-01-10 14:02:29.000000000 -0800
***************
*** 447,450 ****
--- 447,475 ----
  }
  #endif
  
+ extern void print_modules(void);
+ 
+ #if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
+ 
+ extern struct module *module_list;
+ 
+ /*
+  * print_symbols takes a format string containing one %s.
+  * If support for resolving symbols is compiled in, the %s will
+  * be replaced by the closest symbol to the address and the entire
+  * string is printk()ed. Otherwise, nothing is printed.
+  */
+ extern void print_symbol(const char *fmt, unsigned long address);
+ 
+ #else
+ 
+ #include <linux/errno.h>
+ static inline int
+ print_symbol(const char *fmt, unsigned long address)
+ {
+ 	return -ESRCH;
+ }
+ 
+ #endif
+ 
  #endif /* _LINUX_MODULE_H */
diff -c -r -N console-os/include/linux/sysctl.h console-os-kdb/include/linux/sysctl.h
*** console-os/include/linux/sysctl.h	2007-01-09 18:01:54.000000000 -0800
--- console-os-kdb/include/linux/sysctl.h	2007-01-10 14:04:15.000000000 -0800
***************
*** 136,141 ****
--- 136,142 ----
  	KERN_MEM_NMI_PANIC=64,  /* int: memory nmi panic flag */
  	KERN_PRINTK_RATELIMIT=65, /* int: tune printk ratelimiting */
  	KERN_PRINTK_RATELIMIT_BURST=66,	/* int: tune printk ratelimiting */
+ 	KERN_KDB=67,		/* int: kdb on/off */
  };
  
  
diff -c -r -N console-os/init/main.c console-os-kdb/init/main.c
*** console-os/init/main.c	2006-11-30 16:31:23.000000000 -0800
--- console-os-kdb/init/main.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 80,85 ****
--- 80,89 ----
  #include <asm/smp.h>
  #endif
  
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif	/* CONFIG_KDB */
+ 
  /*
   * Versions of gcc older than that listed below may actually compile
   * and link okay, but the end product can have subtle run time bugs.
***************
*** 277,282 ****
--- 281,305 ----
                  }
                  if (next != NULL)
                          *next++ = 0;
+ #ifdef	CONFIG_KDB
+ 		/* kdb=on, kdb=off, kdb=early */
+ 		if (strncmp(line, "kdb=", 4) == 0) {
+ 			if (strcmp(line+4, "on") == 0) {
+ 				kdb_on = 1;
+ 				continue;
+ 			}
+ 			if (strcmp(line+4, "off") == 0) {
+ 				kdb_on = 0;
+ 				continue;
+ 			}
+ 			if (strcmp(line+4, "early") == 0) {
+ 				kdb_on = 1;
+ 				kdb_flags |= KDB_FLAG_EARLYKDB;
+ 				continue;
+ 			}
+ 			printk("Boot flag %s not recognised, assumed to be environment variable\n", line);
+ 		}
+ #endif	/* CONFIG_KDB */
  		if (!strncmp(line,"init=",5)) {
  			line += 5;
  			execute_command = line;
***************
*** 412,417 ****
--- 435,447 ----
  	pgtable_cache_init();
  	pte_chain_init();
  
+ #ifdef	CONFIG_KDB
+ 	kdb_init();
+ 	if (KDB_FLAG(EARLYKDB)) {
+ 		KDB_ENTER();
+ 	}
+ #endif	/* CONFIG_KDB */
+ 
  	/*
  	 * For architectures that have highmem, num_mappedpages represents
  	 * the amount of memory the kernel can use.  For other architectures
diff -c -r -N console-os/kdb/ChangeLog console-os-kdb/kdb/ChangeLog
*** console-os/kdb/ChangeLog	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/ChangeLog	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,742 ----
+ 2003-07-20 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Make kdb_serial_str a common constant, the same for all consoles.
+ 	* Support SGI L1 console.
+ 	* kdb v4.3-2.4.21-common-8.
+ 
+ 2003-07-14 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Correct ll command.
+ 	* kdb v4.3-2.4.21-common-7.
+ 
+ 2003-07-08 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Export more kdb symbols.  Vamsi Krishna S., IBM.
+ 	* kdb v4.3-2.4.21-common-6.
+ 
+ 2003-07-07 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Tweak 'waiting for cpus' message.
+ 	* kdb v4.3-2.4.21-common-5.
+ 
+ 2003-07-07 Keith Owens  <kaos@sgi.com>
+ 
+ 	* 2.4.21-ia64-030702 patches common code that affects kdb.  Workaround
+ 	  this nuisance.
+ 	* kdb v4.3-2.4.21-common-4.
+ 
+ 2003-06-24 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Add task and sigset commands.  Mark Goodwin, SGI.
+ 	* kdb v4.3-2.4.21-common-3.
+ 
+ 2003-06-23 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Sync with XFS 2.4.21 tree.
+ 	* kdb v4.3-2.4.21-common-2.
+ 
+ 2003-06-20 Keith Owens  <kaos@sgi.com>
+ 
+ 	* kdb v4.3-2.4.21-common-1.
+ 
+ 2003-06-20 Keith Owens  <kaos@sgi.com>
+ 
+ 	* More details on vm command, add vmp and pte commands.
+ 	  Dean Nelson, Dean Roe, SGI.
+ 	* YAO1SCF (Yet Another O(1) Scheduler Coexistence Fix).
+ 	* Changes to common code to build on sparc.  Tom Duffy.
+ 	* Move Tom Duffy's changes to drivers/sbus from the sparc64
+ 	  patch to the common patch to keep all the serial changes
+ 	  together.
+ 	* Changes to common code to build on Xscale.  Eddie Dong, Intel.
+ 	* Remove CROSS_COMPILE_INC.
+ 	* Remove obsolete boot parameter 'kdb', long since replaced by
+ 	  'kdb=on'.
+ 	* Remove obsolete kdb_eframe_t casts.
+ 	* Add CONFIG_KDB_CONTINUE_CATASTROPHIC.
+ 	* Wait a short interval for cpus to join kdb before proceeding.
+ 	* Automatically enable sysrq for sr command.
+ 	* Correct double free of kdb_printf lock, spotted by Richard Sanders.
+ 	* Add optional cpu parameter to btc command.
+ 	* kdb v4.3-2.4.20-common-1.
+ 
+ 2003-05-02 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Some architectures have problems with the initial empty kallsyms
+ 	  section so revert to three kallsyms passes.
+ 	* Flush buffered input at startup and at 'more' prompt.
+ 	* Only print 'more' prompt when longjmp data is available.
+ 	* Print more data for buffers and inodes.
+ 	* Disable kill command when O(1) scheduler is installed, the code
+ 	  needs to be redone for O(1).
+ 	* The kernel has an undocumented assumption that enable_bh() is
+ 	  always called with interrupts enabled, make it so.
+ 	* Print trailing punctuation even for symbols that are not in kernel.
+ 	* Add read/write access to user pages.  Vamsi Krishna S., IBM
+ 	* Rename cpu_is_online to cpu_online, as in 2.5.
+ 	* O(1) scheduler removes init_task so kdb maintains its own list of
+ 	  active tasks.
+ 	* Delete btp 0 <cpuid> option, it needed init_tasks.
+ 	* Clean up USB keyboard support.  Steven Dake.
+ 	* Sync with XFS 2.4.20 tree.
+ 	* kdb v4.2-2.4.20-common-1.
+ 
+ 2003-04-04 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Remove one kallsyms pass.
+ 	* Automatic detection of O(1) scheduler.
+ 	* Rename cpu_online to cpu_is_online.
+ 	* Workarounds for scheduler bugs.
+ 	* Tweak algorithm for detecting if cpu process data is available.
+ 	* Add 'kill' command.  Sonic Zhang, Keith Owens.
+ 	* kdb v4.1-2.4.20-common-1.
+ 
+ 2003-03-16 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Each cpu saves its state as it enters kdb or before it enters code
+ 	  which cannot call kdb.
+ 	* Allow btp on process 0 for a specified cpu.
+ 	* Add btt command, backtrace given a struct task address.
+ 	* btc command no longer switches cpus, instead it uses the saved data.
+ 	* bta shows the idle task on each cpu as well as real tasks, the idle
+ 	  task could be handling an interrupt.
+ 	* ps command shows the idle task on each cpu.
+ 	* ps checks that the saved data for a cpu matches the process running on
+ 	  that cpu and warns about stale saved data or no saved data at all.
+ 	* Remove special cases for i386 backtrace from common code and simplify
+ 	  common bt code.
+ 	* Clean up kdb interaction with CONFIG_SERIAL_CONSOLE.
+ 	* Do not automatically repeat commands after the user typed 'q'.
+ 	* O(1) scheduler patch changes the process cpu field but does not set
+ 	  any indicator that O(1) is being used.  Adjust kdb_process_cpu() by
+ 	  hand after applying O(1).
+ 	* Add kdb_print_nameval() to common code.
+ 	* Convert tests of cpu_online_map to cpu_online() macro.
+ 	* module.h needs errno.h when compiling with CONFIG_MODULES=n.
+ 	* Correct duplicate breakpoint handling.
+ 	* Do not try to send IPI during a catastrophic error, send_ipi can hang
+ 	  and take kdb with it.
+ 	* kdb memmap command is i386 only, restrict it.
+ 	* Add large block device (LBD) support from XFS tree.  Eric Sandeen.
+ 	* kdb v4.0-2.4.20-common-1.
+ 
+ 2003-02-03 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Register kdb commands early.
+ 	* Decode oops via kallsyms if it is available.
+ 	* Update copyright notices to 2003.
+ 	* Add defcmd/endefcmd to allow users to package their own macros.
+ 	* kdb commands that fail are ignored when prefixed with '-'.
+ 	* Add selection options to bta command.
+ 	* Add btc command (switch to each cpu and backtrace).
+ 	* Do real time detection of dead cpus.
+ 	* Clear ip adjusted flag when leaving kdb.
+ 	* Clean up ps command.
+ 	* Print ps output for each task when backtracing.
+ 	* Bump to version v3.0 to reduce confusion between kdb and kernel
+ 	  version numbers.
+ 	* Add kdba_local_arch_setup/kdba_local_arch_cleanup to correct
+ 	  keyboard freeze.  Ashish Kalra.
+ 	* Refuse multiple breakpoints at the same address.
+ 	* Add fl (file_lock) command, from XFS development tree.
+ 	* Correct inode_pages, from XFS development tree.
+ 	* Add command history and editing.  Sonic Zhang.
+ 	* Extend command history and editing to handle vt100 escape sequences.
+ 	* Allow tab completion at start of line.
+ 	* Touch nmi watchdog on long running bta and btc commands.
+ 	* Clean up ps output and standardize with bta codes.
+ 	* Correctly handle escaped characters in commands.
+ 	* Update man pages for btc and command history/editing.
+ 	* kdb v3.0-2.4.20-common-1.
+ 
+ 2002-11-29 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.20.
+ 	* Correct Documentation/kdb/kdb_sr.man.
+ 	* Remove leading zeroes from pids, they are decimal, not octal.
+ 	* kdb v2.5-2.4.20-common-1.
+ 
+ 2002-11-14 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.20-rc1.
+ 	* kdb v2.5-2.4.20-rc1-common-1.
+ 
+ 2002-11-14 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Fix processing with O(1) scheduler.
+ 	* 'go' switches back to initial cpu first.
+ 	* 'go <address>' only allowed on initial cpu.
+ 	* 'go' installs the global breakpoints from the initial cpu before
+ 	   releasing the other cpus.
+ 	* If 'go' has to single step over a breakpoint then it single steps just
+ 	  the initial cpu, installs the global breakpoints then releases the
+ 	  other cpus.
+ 	* General clean up of handling for breakpoints and single stepping over
+ 	  software breakpoints.
+ 	* Add kdb_notifier_block so other code can tell when kdb is in control.
+ 	* kdb v2.5-2.4.19-common-1.
+ 
+ 2002-11-02 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Correct build without CONFIG_KDB.
+ 	* kdb v2.4-2.4.19-common-3.
+ 
+ 2002-11-01 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Minimize differences from 2.5.44.
+ 	* kdb v2.4-2.4.19-common-2.
+ 
+ 2002-10-31 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Add defcmd/endefcmd feature.
+ 	* Remove kdb_eframe_t.
+ 	* Clear bp data before using.
+ 	* Sanity check if we have pt_regs.
+ 	* Force LINES > 1.
+ 	* Remove special case for KDB_REASON_PANIC, use KDB_ENTER() instead.
+ 	* Remove kdba_getcurrentframe().
+ 	* Coexist with O(1) scheduler.
+ 	* Add lines option to dmesg, speed up dmesg.
+ 	* kdb v2.4-2.4.19-common-1.
+ 
+ 2002-10-17 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Add selection critera to ps and bta commands.
+ 	* kdb v2.3-2.4.19-common-4.
+ 
+ 2002-10-07 Keith Owens  <kaos@sgi.com>
+ 
+ 	* New man page, Documentation/kdb/kdb_sr.man.
+ 
+ 2002-10-04 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Minimize differences between patches for 2.4 and 2.5 kernels.
+ 	* Add Configure.help for CONFIG_KDB_USB.
+ 	* Reduce stack usage.
+ 	* kdb v2.3-2.4.19-common-3.
+ 
+ 2002-08-10 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Replace kdb_port with kdb_serial to support memory mapped I/O.
+ 	  David Mosberger.
+ 	* kdb v2.3-2.4.19-common-2.
+ 
+ 2002-08-07 Keith Owens <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.19.
+ 	* Remove individual SGI copyrights, the general SGI copyright applies.
+ 	* Handle md0.  Reported by Hugh Dickins, different fix by Keith Owens.
+ 	* Use page_address() in kdbm_pg.c.  Hugh Dickins.
+ 	* Remove debugging printk from kdbm_pg.c.  Hugh Dickins.
+ 	* Move breakpoint address verification into arch dependent code.
+ 	* Dynamically resize kdb command table as required.
+ 	* Common code to support USB keyboard.  Sebastien Lelarge.
+ 	* kdb v2.3-2.4.19-common-1.
+ 
+ 2002-07-09 Keith Owens <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.19-rc1.
+ 	* Add dmesg command.
+ 	* Clean up copyrights, Eric Sandeen.
+ 	* kdb v2.2-2.4.19-rc1-common-1.
+ 
+ 2002-06-14 Keith Owens <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.19-pre10.
+ 	* Sync with XFS.
+ 	* kdb v2.1-2.4.19-pre10-common-1.
+ 
+ 2002-04-09 Keith Owens <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.19-pre6.
+ 	* kdb v2.1-2.4.19-pre6-common-1.
+ 
+ 2002-03-18 Keith Owens <kaos@sgi.com>
+ 
+ 	* Syntax check mdWcN commands.
+ 
+ 2002-03-01 Keith Owens <kaos@sgi.com>
+ 
+ 	* Sync with XFS 2.4.18.
+ 	* kdb v2.1-2.4.18-common-2.
+ 
+ 2002-02-26 Keith Owens <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.18.
+ 	* Add Paul Dorwin (IBM) magicpoint slides on using kdb as
+ 	  Documentation/kdb/slides.
+ 	* kdb v2.1-2.4.18-common-1.
+ 
+ 2002-01-23 Keith Owens <kaos@sgi.com>
+ 
+ 	* Sync with XFS pagebuf changes.
+ 	* kdb v2.1-2.4.17-common-2.
+ 
+ 2002-01-18 Keith Owens <kaos@sgi.com>
+ 
+ 	* Ignore single stepping during panic.
+ 	* Remove kdba_getword, kdba_putword.  Replace with kdb_getword,
+ 	  kdb_putword that rely on copy_xx_user.  The new functions return
+ 	  an error code, like copy_xx_user.
+ 	* New functions kdb_getarea, kdb_putarea for copying areas of data
+ 	  such as structures.  These functions also return an error code.
+ 	* Change all common code to use the new functions.
+ 	* bp command checks that it can read and write the word at the
+ 	  breakpoint before accepting the address.
+ 	* Break points are now set FIFO and cleared LIFO so overlapping
+ 	  entries give sensible results.
+ 	* Verify address before disassembling code.
+ 	* Common changes for sparc64.  Ethan Solomita, Tom Duffy.
+ 	* Remove ss <count>, never supported.
+ 	* Remove kallsyms entries from arch vmlinux.lds files.
+ 	* Specify which commands auto repeat.
+ 	* kdb v2.1-2.4.17-common-1.
+ 
+ 2002-01-07 Keith Owens <kaos@sgi.com>
+ 
+ 	* Remove console semaphore code, not good in interrupt.
+ 	* Remove fragment of ia64 patch that had crept into kdb.
+ 	* Release as kdb v2.0-2.4.17-common-3.
+ 
+ 2002-01-04 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Sync xfs <-> kdb common code.
+ 
+ 2001-12-22 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.17.
+ 	* Clean up ifdef CONFIG_KDB.
+ 	* Add ifdef CONFIG_KDB around include kdb.h.
+ 	* Delete dummy kdb.h files for unsupported architectures.
+ 	* Delete arch i386 and ia64 specific files.  This changelog now
+ 	  applies to kdb common code only.
+ 	* Release as kdb v2.0-2.4.17-common-1.
+ 
+ 2001-12-03 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.16.
+ 	* Add include/asm-um/kdb.h stub to allow XFS to be tested under UML.
+ 	* Check if an interrupt frame on i386 came from user space.
+ 	* Out of scope bug fix in kdb_id.c.  Ethan Solomita.
+ 	* Changes to common code to support sparc64.  Ethan Solomita.
+ 	* Change GFP_KERNEL to GFP_ATOMIC in disasm.  Ethan Solomita.
+ 
+ 2001-11-16 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.15-pre5.
+ 	* Wrap () around #define expressions with unary operators.
+ 
+ 2001-11-13 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.15-pre4.
+ 	* kbdm_pg.c patch from Hugh Dickins.
+ 
+ 2001-11-07 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to 2.4.14-ia64-011105.
+ 	* Change name of l1 serial I/O routine, add ia64 init command.  SGI.
+ 	* Sync kdbm_pg with XFS.
+ 
+ 2001-11-06 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to kernel 2.4.14.
+ 
+ 2001-11-02 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Sync kdbm_pg.c with XFS.
+ 
+ 2001-10-24 Keith Owens  <kaos@sgi.com>
+ 
+ 	* Upgrade to kernel 2.4.13.
+ 
+ 2001-10-14 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* More use of TMPPREFIX in top level Makefile to speed up NFS compiles.
+ 
+ 	* Correct repeat calculations in md/mds commands.
+ 
+ 2001-10-10 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* Copy bfd.h and ansidecl.h to arch/$(ARCH)/kdb, remove dependecies on
+ 	  user space includes.
+ 
+ 	* Update kdb v1.9 to kernel 2.4.11.
+ 
+ 2001-10-01 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* Update kdb v1.9 to kernel 2.4.11-pre1 and 2.4.10-ac1.
+ 
+ 	* Correct loop in kdb_parse, reported by Tachino Nobuhiro.
+ 
+ 2001-09-25 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* Update kdb v1.8 to kernel 2.4.10.
+ 
+ 	* kdbm_pg patch from Hugh Dickens.
+ 
+ 	* DProbes patch from Bharata B Rao.
+ 
+ 	* mdWcn and mmW patch from Vamsi Krishna S.
+ 
+ 	* i386 disasm layout patch from Jean-Marc Saffroy.
+ 
+ 	* Work around for 64 bit binutils, Simon Munton.
+ 
+ 	* kdb.mm doc correction by Chris Pascoe.
+ 
+ 	* Enter repeats the last command, IA64 disasm only prints one
+ 	  instruction.  Don Dugger.
+ 
+ 	* Allow kdb/modules to be linked into vmlinux.
+ 
+ 	* Remove obsolete code from kdb/modules/kdbm_{pg,vm}.c.
+ 
+ 	* Warn when commands are entered at more prompt.
+ 
+ 	* Add MODULE_AUTHOR, DESCRIPTION, LICENSE.
+ 
+ 	* Release as kdb v1.9.
+ 
+ 2001-02-27 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* Update kdb v1.8 to kernel 2.4.2, sync kdb/modules with XFS.
+ 
+ 	* Hook into panic() call.
+ 
+ 2000-12-18 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* Update kdb v1.7 to kernel 2.4.0-test13-pre3, sync kdb/modules with
+ 	XFS.
+ 
+ 2000-11-18 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* Update to kernel 2.4.0-test11-pre7, including forward port of
+ 	bug fixes from WIP 2.4.0-test9 tree.
+ 
+ 	* Update to Cygnus CVS trees for disassembly code.
+ 
+ 	* Bump to kdb v1.6.
+ 
+ 2000-10-19 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* Update to kernel 2.4.0-test10-pre4.
+ 
+ 2000-10-15 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* kdb/kdbmain.c (kdb_parse): Correctly handle blank input.
+ 
+ 	* kdb/kdbmain.c (kdb_local, kdb): Reason SILENT can have NULL regs.
+ 
+ 2000-10-13 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* kdb/kdbmain.c: Reduce CMD_LEN to avoid overflowing kdb_printf buffer.
+ 
+ 2000-10-11 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* kdb/kdbmain.c (kdb): Test for userspace breakpoints before driving
+ 	  other cpus into kdb.  Speeds up gdb and avoids SMP race.
+ 
+ 	* arch/i386/kdb/kdba_io.c (get_serial_char, get_kbd_char): Ignore
+ 	  unprintable characters.
+ 
+ 	* arch/i386/kdb/kdba_io.c (kdba_read): Better handling of buffer size.
+ 
+ 2000-10-04 Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* arch/i386/kdb/kdba_bt.c (kdba_bt_process): Verify that esp is inside
+ 	task_struct.  Original patch by Mike Galbraith.
+ 
+ 	* kdb/kdb_io.c (kdb_getstr): Reset output line counter, remove
+ 	unnecessary prompts.
+ 
+ 	* arch/i386/kdb/kdbasupport.c (kdb_getregcontents): Change " cs" to
+ 	"xcs", ditto ss, ds, es.  gdb2kdb does not like leading spaces.
+ 
+ 	* include/asm-xxx/kdb.h: Add dummy kdb.h for all architectures except
+ 	ix86.  This allows #include <linux/kdb.h> to appear in arch independent
+ 	code without causing compile errors.
+ 
+ 	* kdb/modules/kdbm_pg: Sync with XFS.
+ 
+ 2000-10-03  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* kdb/kdb_io.c (kdb_read): Ignore NMI while waiting for input.
+ 
+ 	* kdb/kdb_io.c, kdb/Makefile: Export kdb_read.
+ 
+ 2000-10-02  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* arch/i386/kernel/smpboot.c (do_boot_cpu): Set nmi_watchdog_source to 2
+ 	to avoid premature NMI oops during cpu bring up.  We have to assume that
+ 	a box with more than 1 cpu has a working IO-APIC.
+ 
+ 	* Documentation/kdb/{kdb.mm,kdb_md.man}: Add mdr command.
+ 
+ 	* kdb/kdbmain.c (kdb_md): Add mdr command.
+ 
+ 	* Release as kdb v1.5 against 2.4.0-test9-pre8.
+ 
+ 	* arch/i386/kdb/kdba_io.c, arch/i386/kdb/kdbasupport.c, kdb/kdbmain.c,
+ 	kdb/kdb_io.c, kdb/kdb_id.c: Remove zero initializers for static
+ 	variables.
+ 
+ 2000-09-28  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* various: Add nmi_watchdog_source, 1 local APIC, 2 IO-APIC.
+ 	Test nmi_watchdog_source instead of nr_ioapics so UP works on SMP hardware.
+ 
+ 	* arch/i386/kernel/io_apic.c: Rename setup_nmi to setup_nmi_io for clarity.
+ 
+ 	* kdb/kdbmain.c (kdb_parse): Only set NO_WATCHDOG if it was already set.
+ 
+ 	* kdb/kdbmain.c (kdb): Clear NO_WATCHDOG on all exit paths.
+ 
+ 	* include/linux/kdb.h: Add KDB_REASON_SILENT.
+ 
+ 	* kdb/kdbmain.c (kdb_local): Treat reason SILENT as immediate 'go'.
+ 
+ 	* kdb/kdbmain.c (kdb_init): Invoke kdb with reason SILENT to instantiate
+ 	any breakpoints on boot cpu.
+ 
+ 	* arch/i386/kernel/smpboot.c (smp_callin): Invoke kdb with reason SILENT
+ 	to instantiate any global breakpoints on this cpu.
+ 
+ 	* kdb/kdb_cmds: Remove comment that said initial commands only worked on
+ 	boot cpu.
+ 
+ 2000-09-27  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* arch/i386/kernel/msr.c: Move {rd,wr}msr_eio to include/asm-i386/apic.h.
+ 
+ 	* include/asm-i386/apic.h: Define NMI interfaces.
+ 
+ 	* kernel/sysctl.c (kern_table):
+ 	* kernel/sysctl.c (do_proc_set_nmi_watchdog):
+ 	Add /proc/sys/kernel/nmi_watchdog.
+ 
+ 	* arch/i386/kernel/apic.c: New routines set_nmi_counter_local,
+ 	setup_apic_nmi_watchdog.
+ 
+ 	* arch/i386/kernel/traps.c: New routine set_nmi_watchdog().  Call apic
+ 	routines to set/clear local apic timer.
+ 
+ 2000-09-26  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* include/linux/sysctl.h (enum): Add NMI_WATCHDOG.
+ 
+ 	* arch/i386/kernel/traps.c (nmi_watchdog_tick): Check nmi_watchdog is
+ 	still on.
+ 
+ 	* arch/i386/config.in: Add CONFIG_UP_NMI_WATCHDOG.
+ 
+ 	* Documentation/Configure.help: Add CONFIG_UP_NMI_WATCHDOG.
+ 
+ 	* Documentation/nmi_watchdog.txt: Update for UP NMI watchdog.
+ 
+ 2000-09-25  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* arch/i386/kernel/apic.c (init_apic_mappings):
+ 	* arch/i386/kernel/io_apic.c (IO_APIC_init_uniprocessor):
+ 	Merge Keir Fraser's local APIC for uniprocessors patch.
+ 
+ 2000-09-24  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* Various: Declare initialization routines as __init.
+ 
+ 	* Makefile: Define and export AWK.
+ 
+ 	* kdb/Makefile: Generate gen-kdb_cmds.c from kdb/kdb_cmds.
+ 
+ 	* kdb/kdbmain.c (kdb_init): Call new routine kdb_cmds_init to execute
+ 	whatever the user put in kdb/kdb_cmds.
+ 
+ 	* arch/i386/kdb/kdba_bt.c (kdba_bt_stack): New parameter to
+ 	indicate if esp in regs is known to be valid or not.
+ 
+ 	* kdb/kdb_bp.c, arch/i386/kdb/kdba_bp.c: More trace prints for
+ 	breakpoint handling.
+ 
+ 	* arch/i386/kdb/kdba_bp.c (kdba_installbp): Finally found and fixed the
+ 	annoying breakpoint bug where breakpoints where not always installed
+ 	after 'go'.
+ 
+ 	* Documentation/kdb: Update man pages kdb.mm, kdb_env.man, kdb_ss.man.
+ 
+ 	* Released as kdb-v1.5-beta1-2.4.0-test8.
+ 
+ 	* Sync to 2.4.0-test9-pre6 and release as kdb-v1.5-beta1-2.4.0-test9-pre6.
+ 
+ 2000-09-23  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* arch/i386/kdb/kdbasupport.c (kdba_getregcontents): New pseudo
+ 	registers cesp and ceflags to help with debugging the debugger.
+ 
+ 	* kdb/kdbmain.c (kdb_local, kdb): Add KDB_REASON_RECURSE.  Add
+ 	environment variable RECURSE.  Add code to cope with some types of
+ 	recursion.
+ 
+ 	* kdb/kdbmain.c (kdb), arch/i386/kdba/kdba_bp.c: Add
+ 	kdba_clearsinglestep.
+ 
+ 2000-09-22  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* drivers/video/vgacon.c (write_vga): No cli() if kdb is running, avoid
+ 	console deadlock.
+ 
+ 	* arch/i386/kernel/irq.c (get_irqlock): Warn if kdb is running, may hang.
+ 
+ 	* include/linux/kdb.h: Define KDB_IS_RUNNING as (0) if no CONFIG_KDB.
+ 
+ 	* arch/i386/kdb/kdba_bt.c (kdba_bt_stack): Do not attempt a backtrace if
+ 	the code segment is not in the kernel.
+ 
+ 	* kdb/modules: Change modules from MX_OBJS to M_OBJS.  Remove EXPORT_NOSYMBOLS.
+ 
+ 2000-09-21  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* arch/i386/kernel/i386_ksyms.c: Move EXPORT_SYMBOLS for kdb to kdb/kdbmain.c.
+ 
+ 	* kdb/Makefile: Change kdb/kdbmain.o from O_OBJS to OX_OBJS.
+ 
+ 	* arch/i386/kernel/smp.c: Remove some #ifdef CONFIG_KDB.  Remove kdbprivate.h.
+ 
+ 	* include/linux/kdb.h: Add kdb_print_state.  Add KDB_STATE_WAIT_IPI.
+ 
+ 	* kdb/kdbmain.c (kdb): Only mark cpu as leaving if it is in KDB state.  Maintain
+ 	WAIT_IPI state so a cpu is only driven through NMI once.
+ 
+ 	* arch/i386/kernel/smp.c (smp_kdb_stop): All state fiddling moved to kdb().
+ 
+ 2000-09-20  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* include/linux/kdb.h: #define kdb() as (0) if kdb is not configured.
+ 
+ 	* arch/i386/kernel/traps.c: Remove some #ifdef CONFIG_KDB.
+ 
+ 	* include/linux/kdbprivate.h: Move per cpu state to kdb.h.
+ 
+ 	* include/linux/kdb.h: Add KDB_STATE_NO_WATCHDOG, KDB_STATE_PRINTF_LOCK.
+ 	Rename KDB_DEBUG_xxx to KDB_DEBUG_FLAG_xxx.  Clean up debug flag
+ 	definitions.
+ 
+ 	* arch/i386/kernel/traps.c (nmi_watchdog_tick): Check no watchdog.
+ 
+ 	* kdb/kdbmain.c (kdb): Set no watchdog in normal kdb code.
+ 
+ 	* kdb/kdbmain.c (kdb_parse): Allow watchdog in commands.
+ 
+ 	* kdb/kdb_io.c (kdb_printf): No watchdog during printing.  Clean up lock handling.
+ 
+ 	* kdb/kdbmain.c (kdb_set): Clean up debug flag handling.
+ 
+ 2000-09-19  Juan J. Quintela  <quintela@fi.udc.es>
+ 
+ 	* kdb/arch/i386/kdb/kdba_io.c: Allow kdb to compile without CONFIG_VT and/or
+ 	serial console.
+ 
+ 2000-09-19  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* include/linux/kdb.h: Define KDB_DEBUG_STATE().
+ 
+ 	* kdb/kdbmain.c (kdb): Add kdb_print_state(), calls to KDB_DEBUG_STATE().
+ 
+ 2000-09-16  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* Move to finer grained control over individual processors in kdb with
+ 	per cpu kdb state.  Needed to allow ss[b] to only release one processor,
+ 	previously ss[b] released all processors.  Also need to recover from
+ 	errors inside kdb commands, e.g. oops in kdbm_pg code.
+ 
+ 	* various:
+ 	  Move global flags KDB_FLAG_SSB, KDB_FLAG_SUPRESS, KDB_FLAG_FAULT,
+ 	  KDB_FLAG_SS, KDB_FLAG_SSBPT, kdb_active, to per cpu state and macros
+ 	  KDB_STATE(xxx).
+ 	  Replace kdb_flags & KDB_FLAG_xxx with KDB_FLAG(xxx).
+ 	  Replace kdb_flags & KDB_DEBUG_xxx with KDB_DEBUG(xxx).
+ 	  Replace specific tests with wrapper KDB_IS_RUNNING().
+ 
+ 	* various: Remove #ifdef CONFIG_SMP from kdb code wherever
+ 	possible.  Simplifies the code and makes it much more readable.
+ 
+ 	* arch/i386/kdb/kdbasupport.c (kdb_setjmp): Record if we have reliable
+ 	longjmp data instead of assuming it is always set.
+ 
+ 	* various: Replace smp_kdb_wait with per cpu state, HOLD_CPU.
+ 
+ 	* init/main.c : Replace #ifdef KDB_DEBUG with KDB_DEBUG(CALLBACK).
+ 
+ 	* include/linux/kdbprivate.h: Separate command return codes from error
+ 	codes.  Add more detailed command codes.
+ 
+ 	* arch/i386/kernel/traps.c (die): Change spin_lock_irq to
+ 	spin_lock_irqsave.  Why did I do this?
+ 
+ 	* kdb/kdbmain.c (kdb_parse): Set per cpu flag CMD before executing kdb
+ 	command.  More detailed return codes for commands that affect
+ 	processors.
+ 
+ 	* kdb/kdbmain.c (kdb_previous_event): New, check if any processors are
+ 	still executing the previous kdb event.  Removes a race window where a
+ 	second event could enter kdb before the first had completely ended.
+ 
+ 	* kdb/kdbmain.c (kdb): Document all the concurrency conditions and how
+ 	kdb handles them.  ss[b] now releases only the current cpu.  Do not set
+ 	breakpoints when releasing for ss[b].  Recover from errors in kdb
+ 	commands.  Check that we have reliable longjmp data before using it.
+ 
+ 	* various: Update return code documentation.
+ 
+ 	* kdb/kdb_bp.c (kdb_ss): Separate ss and ssb return codes.
+ 
+ 	* kdb/kdbsupport.c (kdb_ipi): Finer grained algorithm for deciding
+ 	whether to call send a stop signal to a cpu.
+ 
+ 	* arch/i386/kdb/kdba_bp.c (kdba_db_trap): Separate ss and ssb return
+ 	codes.  Reinstall delayed software breakpoints per cpu instead of
+ 	globally.  Changed algorithm for handling ss[b].
+ 
+ 	* arch/i386/kdb/kdba_bp.c (kdba_bp_trap): Match software breakpoints per
+ 	cpu instead of globally.
+ 
+ 	* include/linux/kdb.h: Bump version to kdb v1.5.
+ 
+ 2000-09-16  Keith Owens  <kaos@melbourne.sgi.com>
+ 
+ 	* kernel/sysctl.c (kern_table): add /proc/sys/kernel/kdb.
+ 
+ 	* init/main.c (parse_options): add boot flags kdb=on, kdb=off,
+ 	kdb=early.
+ 
+ 	* include/linux/sysctl.h (enum): add KERN_KDB.
+ 
+ 	* drivers/char/serial.c (receive_chars): check kdb_on.
+ 
+ 	* drivers/char/keyboard.c (handle_scancode): check kdb_on.
+ 
+ 	* arch/i386/kernel/traps.c (nmi_watchdog_tick): check kdb_on.
+ 
+ 	* arch/i386/config.in: add CONFIG_KDB_OFF.
+ 
+ 	* Documentation/Configure.help: add CONFIG_KDB_OFF.
+ 
+ 	* kdb/kdbmain.c: add kdb_initial_cpu, kdb_on.
+ 
+ 	* kdb/kdbmain.c (kdb): check kdb_on, set kdb_initial_cpu.
+ 
+ 	* kdb/kdbmain.c (kdb_init): add Keith Owens to kdb banner.
+ 
+ 	* kdb/kdb_io.c (kdb_printf): serialize kdb_printf output.
+ 
+ 	* kdb/kdb_bt.c (kdb_bt): check environment variable BTAPROMPT.
+ 
+ 	* kdb/kdbsupport.c (kdb_ipi): ignore NMI for kdb_initial_cpu.
+ 
+ 	* kdb/modules/kdbm_pg.c (kdbm_page): merge updates from 2.4.0-test5-xfs.
+ 
+ 	* kdb/kdb_bt.man: add btp, bta, BTAPROMPT.
+ 
+ 	* kdb/kdb.mm: add CONFIG_KDB_OFF, boot flags, btp, bta.
+ 
+ 	* include/linux/kdbprivate.h: add kdb_initial_cpu.
+ 
+ 	* include/linux/kdb.h: add kdb_on, bump version to kdb v1.4.
diff -c -r -N console-os/kdb/gen-kdb_cmds.c console-os-kdb/kdb/gen-kdb_cmds.c
*** console-os/kdb/gen-kdb_cmds.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/gen-kdb_cmds.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,4 ----
+ #include <linux/init.h>
+ char __initdata *kdb_cmds[] = {
+   0
+ };
diff -c -r -N console-os/kdb/kdb_bp.c console-os-kdb/kdb/kdb_bp.c
*** console-os/kdb/kdb_bp.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/kdb_bp.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,648 ----
+ /*
+  * Kernel Debugger Architecture Independent Breakpoint Handler
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/string.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ #include <linux/smp.h>
+ #include <linux/sched.h>
+ #include <asm/system.h>
+ 
+ /*
+  * Table of kdb_breakpoints
+  */
+ kdb_bp_t	kdb_breakpoints[KDB_MAXBPT];
+ 
+ /*
+  * kdb_bp_install_global
+  *
+  *	Install global kdb_breakpoints prior to returning from the
+  *	kernel debugger.  This allows the kdb_breakpoints to be set
+  *	upon functions that are used internally by kdb, such as
+  *	printk().
+  *
+  * Parameters:
+  *	regs	Execution frame.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  *
+  *	This function is only called once per kdb session.
+  */
+ 
+ void
+ kdb_bp_install_global(struct pt_regs *regs)
+ {
+ 	int i;
+ 
+ 	for(i=0; i<KDB_MAXBPT; i++) {
+ 		if (KDB_DEBUG(BP)) {
+ 			kdb_printf("kdb_bp_install_global bp %d bp_enabled %d bp_global %d\n",
+ 				i, kdb_breakpoints[i].bp_enabled, kdb_breakpoints[i].bp_global);
+ 		}
+ 		if (kdb_breakpoints[i].bp_enabled
+ 		 && kdb_breakpoints[i].bp_global) {
+ 			kdba_installbp(regs, &kdb_breakpoints[i]);
+ 		}
+ 	}
+ }
+ 
+ /*
+  * kdb_bp_install_local
+  *
+  *	Install local kdb_breakpoints prior to returning from the
+  *	kernel debugger.  This allows the kdb_breakpoints to be set
+  *	upon functions that are used internally by kdb, such as
+  *	printk().
+  *
+  * Parameters:
+  *	regs	Execution frame.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  *
+  *	This function is called once per processor.
+  */
+ 
+ void
+ kdb_bp_install_local(struct pt_regs *regs)
+ {
+ 	int i;
+ 
+ 	for(i=0; i<KDB_MAXBPT; i++) {
+ 		if (KDB_DEBUG(BP)) {
+ 			kdb_printf("kdb_bp_install_local bp %d bp_enabled %d bp_global %d cpu %d bp_cpu %d\n",
+ 				i, kdb_breakpoints[i].bp_enabled, kdb_breakpoints[i].bp_global,
+ 				smp_processor_id(), kdb_breakpoints[i].bp_cpu);
+ 		}
+ 		if (kdb_breakpoints[i].bp_enabled
+ 		 && kdb_breakpoints[i].bp_cpu == smp_processor_id()
+ 		 && !kdb_breakpoints[i].bp_global){
+ 			kdba_installbp(regs, &kdb_breakpoints[i]);
+ 		}
+ 	}
+ }
+ 
+ /*
+  * kdb_bp_remove_global
+  *
+  * 	Remove global kdb_breakpoints upon entry to the kernel debugger.
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ void
+ kdb_bp_remove_global(void)
+ {
+ 	int i;
+ 
+ 	for(i=KDB_MAXBPT-1; i>=0; i--) {
+ 		if (KDB_DEBUG(BP)) {
+ 			kdb_printf("kdb_bp_remove_global bp %d bp_enabled %d bp_global %d\n",
+ 				i, kdb_breakpoints[i].bp_enabled, kdb_breakpoints[i].bp_global);
+ 		}
+ 		if (kdb_breakpoints[i].bp_enabled
+ 		 && kdb_breakpoints[i].bp_global) {
+ 			kdba_removebp(&kdb_breakpoints[i]);
+ 		}
+ 	}
+ }
+ 
+ 
+ /*
+  * kdb_bp_remove_local
+  *
+  * 	Remove local kdb_breakpoints upon entry to the kernel debugger.
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ void
+ kdb_bp_remove_local(void)
+ {
+ 	int i;
+ 
+ 	for(i=KDB_MAXBPT-1; i>=0; i--) {
+ 		if (KDB_DEBUG(BP)) {
+ 			kdb_printf("kdb_bp_remove_local bp %d bp_enabled %d bp_global %d cpu %d bp_cpu %d\n",
+ 				i, kdb_breakpoints[i].bp_enabled, kdb_breakpoints[i].bp_global,
+ 				smp_processor_id(), kdb_breakpoints[i].bp_cpu);
+ 		}
+ 		if (kdb_breakpoints[i].bp_enabled
+ 		 && kdb_breakpoints[i].bp_cpu == smp_processor_id()
+ 		 && !kdb_breakpoints[i].bp_global){
+ 			kdba_removebp(&kdb_breakpoints[i]);
+ 		}
+ 	}
+ }
+ 
+ /*
+  * kdb_printbp
+  *
+  * 	Internal function to format and print a breakpoint entry.
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ static void
+ kdb_printbp(kdb_bp_t *bp, int i)
+ {
+ 	if (bp->bp_forcehw) {
+ 		kdb_printf("Forced ");
+ 	}
+ 
+ 	if (!bp->bp_template.bph_free) {
+ 		kdb_printf("%s ", kdba_bptype(&bp->bp_template));
+ 	} else {
+ 		kdb_printf("Instruction(i) ");
+ 	}
+ 
+ 	kdb_printf("BP #%d at ", i);
+ 	kdb_symbol_print(bp->bp_addr, NULL, KDB_SP_DEFAULT);
+ 
+ 	if (bp->bp_enabled) {
+ 		kdba_printbp(bp);
+ 		if (bp->bp_global)
+ 			kdb_printf(" globally");
+ 		else
+ 			kdb_printf(" on cpu %d", bp->bp_cpu);
+ 		if (bp->bp_adjust)
+ 			kdb_printf(" adjust %d", bp->bp_adjust);
+ 	} else {
+ 		kdb_printf("\n    is disabled");
+ 	}
+ 
+ 	kdb_printf("\n");
+ }
+ 
+ /*
+  * kdb_bp
+  *
+  * 	Handle the bp, and bpa commands.
+  *
+  *	[bp|bpa|bph] <addr-expression> [DATAR|DATAW|IO [length]]
+  *
+  * Parameters:
+  *	argc	Count of arguments in argv
+  *	argv	Space delimited command line arguments
+  *	envp	Environment value
+  *	regs	Exception frame at entry to kernel debugger
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Zero for success, a kdb diagnostic if failure.
+  * Locking:
+  *	None.
+  * Remarks:
+  *
+  * 	bp	Set breakpoint.  Only use hardware assist if necessary.
+  *	bpa	Set breakpoint on all cpus, only use hardware regs if necessary
+  *	bph	Set breakpoint - force hardware register
+  *	bpha	Set breakpoint on all cpus, force hardware register
+  */
+ 
+ int
+ kdb_bp(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int     i, bpno;
+ 	kdb_bp_t *bp, *bp_check;
+ 	int     diag;
+ 	int     free;
+ 	kdb_machreg_t addr;
+ 	char   *symname = NULL;
+ 	long    offset = 0ul;
+ 	int	nextarg;
+ 	int	hardware;
+ 	int	global;
+ 
+ 	if (argc == 0) {
+ 		/*
+ 		 * Display breakpoint table
+ 		 */
+ 		for(bpno=0,bp=kdb_breakpoints; bpno<KDB_MAXBPT; bpno++, bp++) {
+ 			if (bp->bp_free) continue;
+ 
+ 			kdb_printbp(bp, bpno);
+ 		}
+ 
+ 		return 0;
+ 	}
+ 
+ 	global = ((strcmp(argv[0], "bpa") == 0)
+ 	       || (strcmp(argv[0], "bpha") == 0));
+ 	hardware = ((strcmp(argv[0], "bph") == 0)
+ 		 || (strcmp(argv[0], "bpha") == 0));
+ 
+ 	nextarg = 1;
+ 	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, &symname, regs);
+ 	if (diag)
+ 		return diag;
+ 	if (!addr)
+ 		return KDB_BADINT;
+ 
+ 	/*
+ 	 * Allocate a new bp structure
+ 	 */
+ 	free = KDB_MAXBPT;
+ 	for(bpno=0,bp=kdb_breakpoints; bpno<KDB_MAXBPT; bpno++,bp++) {
+ 		if (bp->bp_free) {
+ 			break;
+ 		}
+ 	}
+ 
+ 	if (bpno == KDB_MAXBPT)
+ 		return KDB_TOOMANYBPT;
+ 
+ 	memset(bp, 0, sizeof(*bp));
+ 	bp->bp_free = 1;
+ 	kdba_check_pc(&addr);
+ 	for(i=0,bp_check=kdb_breakpoints; i<KDB_MAXBPT; i++,bp_check++) {
+ 		if (!bp_check->bp_free && bp_check->bp_addr == addr) {
+ 			kdb_printf("You already have a breakpoint at " kdb_bfd_vma_fmt0 "\n", addr);
+ 			return KDB_DUPBPT;
+ 		}
+ 	}
+ 	bp->bp_addr = addr;
+ 	bp->bp_free = 0;
+ 
+ 	bp->bp_forcehw = hardware;
+ 	if (KDB_DEBUG(BP))
+ 		kdb_printf("kdb_bp: forcehw is %d hardware is %d\n", bp->bp_forcehw, hardware);
+ 
+ 	/*
+ 	 * Handle architecture dependent parsing
+ 	 */
+ 	diag = kdba_parsebp(argc, argv, &nextarg, bp);
+ 	if (diag) {
+ 		return diag;
+ 	}
+ 
+ 	bp->bp_enabled = 1;
+ 	bp->bp_global = 1;	/* Most breakpoints are global */
+ 
+ 	if (hardware && !global) {
+ 		bp->bp_global = 0;
+ 		bp->bp_cpu = smp_processor_id();
+ 	}
+ 
+ 	/*
+ 	 * Allocate a hardware breakpoint.  If one is not available,
+  	 * disable the breakpoint, but leave it in the breakpoint
+ 	 * table.  When the breakpoint is re-enabled (via 'be'), we'll
+ 	 * attempt to allocate a hardware register for it.
+ 	 */
+ 	if (!bp->bp_template.bph_free) {
+ 		bp->bp_hard = kdba_allocbp(&bp->bp_template, &diag);
+ 		if (diag) {
+ 			bp->bp_enabled = 0;
+ 			return diag;
+ 		}
+ 		bp->bp_hardtype = 1;
+ 	}
+ 
+ 	kdb_printbp(bp, bpno);
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_bc
+  *
+  * 	Handles the 'bc', 'be', and 'bd' commands
+  *
+  *	[bd|bc|be] <breakpoint-number>
+  *
+  * Parameters:
+  *	argc	Count of arguments in argv
+  *	argv	Space delimited command line arguments
+  *	envp	Environment value
+  *	regs	Exception frame at entry to kernel debugger
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Zero for success, a kdb diagnostic for failure
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ #define KDBCMD_BC	0
+ #define KDBCMD_BE	1
+ #define KDBCMD_BD	2
+ 
+ int
+ kdb_bc(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	kdb_machreg_t 	addr;
+ 	kdb_bp_t	*bp = 0;
+ 	int lowbp = KDB_MAXBPT;
+ 	int highbp = 0;
+ 	int done = 0;
+ 	int i;
+ 	int diag;
+ 	int cmd;			/* KDBCMD_B? */
+ 
+ 	if (strcmp(argv[0], "be") == 0) {
+ 		cmd = KDBCMD_BE;
+ 	} else if (strcmp(argv[0], "bd") == 0) {
+ 		cmd = KDBCMD_BD;
+ 	} else
+ 		cmd = KDBCMD_BC;
+ 
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	if (strcmp(argv[1], "*") == 0) {
+ 		lowbp = 0;
+ 		highbp = KDB_MAXBPT;
+ 	} else {
+ 		diag = kdbgetularg(argv[1], &addr);
+ 		if (diag)
+ 			return diag;
+ 
+ 		/*
+ 		 * For addresses less than the maximum breakpoint number,
+ 		 * assume that the breakpoint number is desired.
+ 		 */
+ 		if (addr < KDB_MAXBPT) {
+ 			bp = &kdb_breakpoints[addr];
+ 			lowbp = highbp = addr;
+ 			highbp++;
+ 		} else {
+ 			for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+ 				if (bp->bp_addr == addr) {
+ 					lowbp = highbp = i;
+ 					highbp++;
+ 					break;
+ 				}
+ 			}
+ 		}
+ 	}
+ 
+ 	/*
+ 	 * Now operate on the set of breakpoints matching the input
+ 	 * criteria (either '*' for all, or an individual breakpoint).
+ 	 */
+ 	for(bp=&kdb_breakpoints[lowbp], i=lowbp;
+ 	    i < highbp;
+ 	    i++, bp++) {
+ 		if (bp->bp_free)
+ 			continue;
+ 
+ 		done++;
+ 
+ 		switch (cmd) {
+ 		case KDBCMD_BC:
+ 			if (bp->bp_hardtype) {
+ 				kdba_freebp(bp->bp_hard);
+ 				bp->bp_hard = 0;
+ 				bp->bp_hardtype = 0;
+ 			}
+ 
+ 			bp->bp_enabled = 0;
+ 			bp->bp_global = 0;
+ 
+ 			kdb_printf("Breakpoint %d at " kdb_bfd_vma_fmt " cleared\n",
+ 				i, bp->bp_addr);
+ 
+ 			bp->bp_addr = 0;
+ 			bp->bp_free = 1;
+ 
+ 			break;
+ 		case KDBCMD_BE:
+ 			/*
+ 			 * Allocate a hardware breakpoint.  If one is not
+ 			 * available, don't enable the breakpoint.
+ 			 */
+ 			if (!bp->bp_template.bph_free
+ 			 && !bp->bp_hardtype) {
+ 				bp->bp_hard = kdba_allocbp(&bp->bp_template, &diag);
+ 				if (diag) {
+ 					bp->bp_enabled = 0;
+ 					return diag;
+ 				}
+ 				bp->bp_hardtype = 1;
+ 			}
+ 
+ 			bp->bp_enabled = 1;
+ 
+ 			kdb_printf("Breakpoint %d at " kdb_bfd_vma_fmt " in enabled",
+ 				i, bp->bp_addr);
+ 
+ 			kdb_printf("\n");
+ 			break;
+ 		case KDBCMD_BD:
+ 			if (!bp->bp_enabled) {
+ 				return 0;
+ 			}
+ 
+ 			/*
+ 			 * Since this breakpoint is now disabled, we can
+ 			 * give up the hardware register which is allocated
+ 			 * to it.
+ 			 */
+ 			if (bp->bp_hardtype) {
+ 				kdba_freebp(bp->bp_hard);
+ 				bp->bp_hard = 0;
+ 				bp->bp_hardtype = 0;
+ 			}
+ 
+ 			bp->bp_enabled = 0;
+ 
+ 			kdb_printf("Breakpoint %d at " kdb_bfd_vma_fmt " disabled\n",
+ 				i, bp->bp_addr);
+ 
+ 			break;
+ 		}
+ 		if (bp->bp_delay && (cmd == KDBCMD_BC || cmd == KDBCMD_BD)) {
+ 			bp->bp_delay = 0;
+ 			KDB_STATE_CLEAR(SSBPT);
+ 		}
+ 	}
+ 
+ 	return (!done)?KDB_BPTNOTFOUND:0;
+ }
+ 
+ /*
+  * kdb_ss
+  *
+  *	Process the 'ss' (Single Step) and 'ssb' (Single Step to Branch)
+  *	commands.
+  *
+  *	ss
+  *	ssb
+  *
+  * Parameters:
+  *	argc	Argument count
+  *	argv	Argument vector
+  *	envp	Environment vector
+  *	regs	Registers at time of entry to kernel debugger
+  * Outputs:
+  *	None.
+  * Returns:
+  *	KDB_CMD_SS[B] for success, a kdb error if failure.
+  * Locking:
+  *	None.
+  * Remarks:
+  *
+  *	Set the arch specific option to trigger a debug trap after the next
+  *	instruction.
+  *
+  *	For 'ssb', set the trace flag in the debug trap handler
+  *	after printing the current insn and return directly without
+  *	invoking the kdb command processor, until a branch instruction
+  *	is encountered.
+  */
+ 
+ int
+ kdb_ss(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int ssb = 0;
+ 
+ 	ssb = (strcmp(argv[0], "ssb") == 0);
+ 	if (argc != 0)
+ 		return KDB_ARGCOUNT;
+ 
+ 	if (!regs) {
+ 		kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+ 		return KDB_BADREG;
+ 	}
+ 
+ 	/*
+ 	 * Set trace flag and go.
+ 	 */
+ 	KDB_STATE_SET(DOING_SS);
+ 	if (ssb)
+ 		KDB_STATE_SET(DOING_SSB);
+ 
+ 	kdba_setsinglestep(regs);		/* Enable single step */
+ 
+ 	if (ssb)
+ 		return KDB_CMD_SSB;
+ 	return KDB_CMD_SS;
+ }
+ 
+ /*
+  * kdb_initbptab
+  *
+  *	Initialize the breakpoint table.  Register breakpoint commands.
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ void __init
+ kdb_initbptab(void)
+ {
+ 	int i;
+ 	kdb_bp_t *bp;
+ 
+ 	/*
+ 	 * First time initialization.
+ 	 */
+ 	memset(&kdb_breakpoints, '\0', sizeof(kdb_breakpoints));
+ 
+ 	for (i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+ 		bp->bp_free = 1;
+ 		/*
+ 		 * The bph_free flag is architecturally required.  It
+ 		 * is set by architecture-dependent code to false (zero)
+ 		 * in the event a hardware breakpoint register is required
+ 		 * for this breakpoint.
+ 		 *
+ 		 * The rest of the template is reserved to the architecture
+ 		 * dependent code and _must_ not be touched by the architecture
+ 		 * independent code.
+ 		 */
+ 		bp->bp_template.bph_free = 1;
+ 	}
+ 
+ 	kdb_register_repeat("bp", kdb_bp, "[<vaddr>]", "Set/Display breakpoints", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("bl", kdb_bp, "[<vaddr>]", "Display breakpoints", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("bpa", kdb_bp, "[<vaddr>]", "Set/Display global breakpoints", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("bph", kdb_bp, "[<vaddr>]", "Set hardware breakpoint", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("bpha", kdb_bp, "[<vaddr>]", "Set global hardware breakpoint", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("bc", kdb_bc, "<bpnum>",   "Clear Breakpoint", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("be", kdb_bc, "<bpnum>",   "Enable Breakpoint", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("bd", kdb_bc, "<bpnum>",   "Disable Breakpoint", 0, KDB_REPEAT_NONE);
+ 
+ 	kdb_register_repeat("ss", kdb_ss, "", "Single Step", 1, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("ssb", kdb_ss, "", "Single step to branch/call", 0, KDB_REPEAT_NO_ARGS);
+ 	/*
+ 	 * Architecture dependent initialization.
+ 	 */
+ 	kdba_initbp();
+ }
+ 
diff -c -r -N console-os/kdb/kdb_bt.c console-os-kdb/kdb/kdb_bt.c
*** console-os/kdb/kdb_bt.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/kdb_bt.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,200 ----
+ /*
+  * Kernel Debugger Architecture Independent Stack Traceback
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/ctype.h>
+ #include <linux/string.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ #include <linux/nmi.h>
+ #include <asm/system.h>
+ 
+ 
+ /*
+  * kdb_bt
+  *
+  *	This function implements the 'bt' command.  Print a stack
+  *	traceback.
+  *
+  *	bt [<address-expression>]	(addr-exp is for alternate stacks)
+  *	btp <pid>			Kernel stack for <pid>
+  *	btt <address-expression>	Kernel stack for task structure at <address-expression>
+  *	bta [DRSTZU]			All processes, optionally filtered by state
+  *	btc [<cpu>]			The current process on one cpu, default is all cpus
+  *
+  * 	address expression refers to a return address on the stack.  It
+  *	is expected to be preceeded by a frame pointer.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	Backtrack works best when the code uses frame pointers.  But
+  *	even without frame pointers we should get a reasonable trace.
+  *
+  *	mds comes in handy when examining the stack to do a manual
+  *	traceback.
+  */
+ 
+ static int
+ kdb_bt1(struct task_struct *p, unsigned long mask, int argcount, int btaprompt)
+ {
+ 	int diag;
+ 	char buffer[2];
+ 	if (kdb_getarea(buffer[0], (unsigned long)p) ||
+ 	    kdb_getarea(buffer[0], (unsigned long)(p+1)-1))
+ 		return KDB_BADADDR;
+ 	if (!kdb_task_state(p, mask))
+ 		return 0;
+ 	kdb_printf("Stack traceback for pid %d\n", p->pid);
+ 	kdb_ps1(p);
+ 	diag = kdba_bt_process(p, argcount);
+ 	if (btaprompt) {
+ 		kdb_getstr(buffer, sizeof(buffer), "Enter <q> to end, <cr> to continue:");
+ 		if (buffer[0] == 'q') {
+ 			kdb_printf("\n");
+ 			return 1;
+ 		}
+ 	}
+ 	touch_nmi_watchdog();
+ 	return 0;
+ }
+ 
+ int
+ kdb_bt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int	diag;
+ 	int	argcount = 5;
+ 	int	btaprompt = 1;
+ 	int 	nextarg;
+ 	unsigned long addr;
+ 	long	offset;
+ 
+ 	kdbgetintenv("BTARGS", &argcount);	/* Arguments to print */
+ 	kdbgetintenv("BTAPROMPT", &btaprompt);	/* Prompt after each proc in bta */
+ 
+ 	if (strcmp(argv[0], "bta") == 0) {
+ 		struct task_struct *p;
+ 		unsigned long cpu;
+ 		unsigned long mask = kdb_task_state_string(argc, argv, envp);
+ 		/* Run the active tasks first */
+ 		for (cpu = 0; cpu < smp_num_cpus; ++cpu) {
+ 			p = kdb_active_task[cpu];
+ 			if (kdb_bt1(p, mask, argcount, btaprompt))
+ 				return 0;
+ 		}
+ 		/* Now the inactive tasks */
+ 		for_each_process(p) {
+ 			if (kdb_task_has_cpu(p) && kdb_active_task[kdb_process_cpu(p)] == p)
+ 				continue;
+ 			if (kdb_bt1(p, mask, argcount, btaprompt))
+ 				return 0;
+ 		}
+ 	} else if (strcmp(argv[0], "btp") == 0) {
+ 		struct task_struct *p = NULL;
+ 		unsigned long	   pid;
+ 		if (argc != 1)
+ 			return KDB_ARGCOUNT;
+ 		if ((diag = kdbgetularg((char *)argv[1], &pid)))
+ 			return diag;
+ 		for_each_process(p) {
+ 			if (p->pid == (pid_t)pid)
+ 				break;
+ 		}
+ 		if (p && p->pid == (pid_t)pid)
+ 			return kdb_bt1(p, ~0, argcount, 0);
+ 		kdb_printf("No process with pid == %ld found\n", pid);
+ 		return 0;
+ 	} else if (strcmp(argv[0], "btt") == 0) {
+ 		unsigned long addr;
+ 		if (argc != 1)
+ 			return KDB_ARGCOUNT;
+ 		if ((diag = kdbgetularg((char *)argv[1], &addr)))
+ 			return diag;
+ 		return kdb_bt1((struct task_struct *)addr, ~0, argcount, 0);
+ 	} else if (strcmp(argv[0], "btc") == 0) {
+ 		unsigned long cpu = ~0;
+ 		struct kdb_running_process *krp;
+ 		char buf[80];
+ 		if (argc > 1)
+ 			return KDB_ARGCOUNT;
+ 		if (argc == 1 && (diag = kdbgetularg((char *)argv[1], &cpu)))
+ 			return diag;
+ 		/* Recursive use of kdb_parse, do not use argv after this point */
+ 		argv = NULL;
+ 		if (cpu != ~0) {
+ 			krp = kdb_running_process + cpu;
+ 			if (cpu >= smp_num_cpus || !krp->seqno) {
+ 				kdb_printf("no process for cpu %ld\n", cpu);
+ 				return 0;
+ 			}
+ 			sprintf(buf, "btt 0x%p\n", krp->p);
+ 			kdb_parse(buf, regs);
+ 			return 0;
+ 		}
+ 		kdb_printf("btc: cpu status: ");
+ 		kdb_parse("cpu\n", regs);
+ 		for (cpu = 0, krp = kdb_running_process; cpu < smp_num_cpus; ++cpu, ++krp) {
+ 			if (!krp->seqno)
+ 				continue;
+ 			sprintf(buf, "btt 0x%p\n", krp->p);
+ 			kdb_parse(buf, regs);
+ 			touch_nmi_watchdog();
+ 		}
+ 		return 0;
+ 	} else {
+ 		if (argc) {
+ 			nextarg = 1;
+ 			diag = kdbgetaddrarg(argc, argv, &nextarg, &addr,
+ 					     &offset, NULL, regs);
+ 			if (diag)
+ 				return diag;
+ 			return kdba_bt_address(addr, argcount);
+ 		} else {
+ 			return kdb_bt1(current, ~0, argcount, 0);
+ 		}
+ 	}
+ 
+ 	/* NOTREACHED */
+ 	return 0;
+ }
diff -c -r -N console-os/kdb/kdb_cmds console-os-kdb/kdb/kdb_cmds
*** console-os/kdb/kdb_cmds	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/kdb_cmds	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,6 ----
+ # Initial commands for kdb, alter to suit your needs.
+ # These commands are executed in kdb_init() context, no SMP, no
+ # processes.  Commands that require process data (including stack or
+ # registers) are not reliable this early.  set and bp commands should
+ # be safe.  Global breakpoint commands affect each cpu as it is booted.
+ 
diff -c -r -N console-os/kdb/kdb_id.c console-os-kdb/kdb/kdb_id.c
*** console-os/kdb/kdb_id.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/kdb_id.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,263 ----
+ /*
+  * Kernel Debugger Architecture Independent Instruction Disassembly
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <stdarg.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/ctype.h>
+ #include <linux/string.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ 
+ disassemble_info	kdb_di;
+ 
+ /*
+  * kdb_id
+  *
+  * 	Handle the id (instruction display) command.
+  *
+  *	id  [<addr>]
+  *
+  * Parameters:
+  *	argc	Count of arguments in argv
+  *	argv	Space delimited command line arguments
+  *	envp	Environment value
+  *	regs	Exception frame at entry to kernel debugger
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Zero for success, a kdb diagnostic if failure.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ int
+ kdb_id(int argc, const char **argv, const char **envp, struct pt_regs* regs)
+ {
+ 	kdb_machreg_t		pc;
+ 	int			icount;
+ 	int			diag;
+ 	int			i;
+ 	char *			mode;
+ 	int			nextarg;
+ 	long			offset = 0;
+ 	static kdb_machreg_t 	lastpc;
+ 	struct disassemble_info *dip = &kdb_di;
+ 	char			lastbuf[50];
+ 	unsigned long		word;
+ 
+ 	if (argc != 1)  {
+ 		if (lastpc == 0) {
+ 			return KDB_ARGCOUNT;
+ 		} else {
+ 			sprintf(lastbuf, "0x%lx", lastpc);
+ 			argv[1] = lastbuf;
+ 			argc = 1;
+ 		}
+ 	}
+ 
+ 
+ 	/*
+ 	 * Fetch PC.  First, check to see if it is a symbol, if not,
+ 	 * try address.
+ 	 */
+ 	nextarg = 1;
+ 	diag = kdbgetaddrarg(argc, argv, &nextarg, &pc, &offset, NULL, regs);
+ 	if (diag)
+ 		return diag;
+ 	kdba_check_pc(&pc);
+ 	if (kdb_getarea(word, pc))
+ 		return(0);
+ 
+ 	/*
+ 	 * Number of lines to display
+ 	 */
+ 	diag = kdbgetintenv("IDCOUNT", &icount);
+ 	if (diag)
+ 		return diag;
+ 
+ 	dip->fprintf_dummy = kdb_dis_fprintf;
+ 
+ 	mode = kdbgetenv("IDMODE");
+ 	diag = kdba_id_parsemode(mode, dip);
+ 	if (diag) {
+ 		return diag;
+ 	}
+ 
+ 	for(i=0; i<icount; i++) {
+ 		pc += kdba_id_printinsn(pc, &kdb_di);
+ 		kdb_printf("\n");
+ 	}
+ 
+ 	lastpc = pc;
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_id1
+  *
+  * 	Disassemble a single instruction at 'pc'.
+  *
+  * Parameters:
+  *	pc	Address of instruction to disassemble
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Zero for success, a kdb diagnostic if failure.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ void
+ kdb_id1(unsigned long pc)
+ {
+ 	char   *mode;
+ 	int	diag;
+ 
+ 	/*
+ 	 * Allow the user to specify that this instruction
+ 	 * should be treated differently.
+ 	 */
+ 
+ 	kdb_di.fprintf_dummy = kdb_dis_fprintf_dummy;
+ 
+ 	mode = kdbgetenv("IDMODE");
+ 	diag = kdba_id_parsemode(mode, &kdb_di);
+ 	if (diag) {
+ 		kdb_printf("kdb_id: bad value in 'IDMODE' environment variable ignored\n");
+ 	}
+ 
+ 	(void) kdba_id_printinsn(pc, &kdb_di);
+ 	kdb_printf("\n");
+ }
+ 
+ /*
+  * kdb_dis_fprintf
+  *
+  *	Format and print a string.
+  *
+  * Parameters:
+  *	file	Unused paramter.
+  *	fmt	Format string
+  *	...	Optional additional parameters.
+  * Returns:
+  *	0
+  * Locking:
+  * Remarks:
+  * 	Result of format conversion cannot exceed 255 bytes.
+  */
+ 
+ int
+ kdb_dis_fprintf(PTR file, const char *fmt, ...)
+ {
+ 	char buffer[256];
+ 	va_list ap;
+ 
+ 	va_start(ap, fmt);
+ 	vsprintf(buffer, fmt, ap);
+ 	va_end(ap);
+ 
+ 	kdb_printf("%s", buffer);
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_dis_fprintf_dummy
+  *
+  *	A dummy printf function for the disassembler, it does nothing.
+  *	This lets code call the disassembler to step through
+  *	instructions without actually printing anything.
+  * Inputs:
+  *	Always ignored.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Always 0.
+  * Locking:
+  *	none.
+  * Remarks:
+  *	None.
+  */
+ 
+ int
+ kdb_dis_fprintf_dummy(PTR file, const char *fmt, ...)
+ {
+ 	return(0);
+ }
+ 
+ /*
+  * kdb_disinit
+  *
+  * 	Initialize the disassembly information structure
+  *	for the GNU disassembler.
+  *
+  * Parameters:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Zero for success, a kdb diagnostic if failure.
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ void __init
+ kdb_id_init(void)
+ {
+ 	kdb_di.stream	    = NULL;
+ 	kdb_di.application_data = NULL;
+ 	kdb_di.symbols	    = NULL;
+ 	kdb_di.num_symbols  = 0;
+ 	kdb_di.flags	    = 0;
+ 	kdb_di.private_data	    = NULL;
+ 	kdb_di.buffer	    = NULL;
+ 	kdb_di.buffer_vma       = 0;
+ 	kdb_di.buffer_length    = 0;
+ 	kdb_di.bytes_per_line   = 0;
+ 	kdb_di.bytes_per_chunk  = 0;
+ 	kdb_di.insn_info_valid  = 0;
+ 	kdb_di.branch_delay_insns = 0;
+ 	kdb_di.data_size	    = 0;
+ 	kdb_di.insn_type	    = 0;
+ 	kdb_di.target           = 0;
+ 	kdb_di.target2          = 0;
+ 	kdb_di.fprintf_func	= kdb_dis_fprintf;
+ 
+ 	kdba_id_init(&kdb_di);
+ }
diff -c -r -N console-os/kdb/kdb_io.c console-os-kdb/kdb/kdb_io.c
*** console-os/kdb/kdb_io.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/kdb_io.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,649 ----
+ /*
+  * Kernel Debugger Architecture Independent Console I/O handler
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/kdev_t.h>
+ #include <linux/console.h>
+ #include <linux/string.h>
+ #include <linux/sched.h>
+ #include <linux/smp.h>
+ #include <linux/nmi.h>
+ #include <linux/delay.h>
+ 
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ #include <linux/kallsyms.h>
+ 
+ #ifdef CONFIG_SPARC64
+ #include <asm/oplib.h>
+ #else
+ static struct console *kdbcons;
+ #endif
+ 
+ 
+ #define CMD_BUFLEN 256
+ char kdb_prompt_str[CMD_BUFLEN];
+ 
+ /*
+  * kdb_read
+  *
+  *	This function reads a string of characters, terminated by
+  *	a newline, or by reaching the end of the supplied buffer,
+  *	from the current kernel debugger console device.
+  * Parameters:
+  *	buffer	- Address of character buffer to receive input characters.
+  *	bufsize - size, in bytes, of the character buffer
+  * Returns:
+  *	Returns a pointer to the buffer containing the received
+  *	character string.  This string will be terminated by a
+  *	newline character.
+  * Locking:
+  *	No locks are required to be held upon entry to this
+  *	function.  It is not reentrant - it relies on the fact
+  *	that while kdb is running on any one processor all other
+  *	processors will be spinning at the kdb barrier.
+  * Remarks:
+  *
+  * Davidm asks, why doesn't kdb use the console abstraction;
+  * here are some reasons:
+  *      - you cannot debug the console abstraction with kdb if
+  *        kdb uses it.
+  *      - you rely on the correct functioning of the abstraction
+  *        in the presence of general system failures.
+  *      - You must acquire the console spinlock thus restricting
+  *        the usability - what if the kernel fails with the spinlock
+  *        held - one still wishes to debug such situations.
+  *      - How about debugging before the console(s) are registered?
+  *      - None of the current consoles (sercons, vt_console_driver)
+  *        have read functions defined.
+  *	- The standard pc keyboard and terminal drivers are interrupt
+  *	  driven.   We cannot enable interrupts while kdb is active,
+  *	  so the standard input functions cannot be used by kdb.
+  *
+  * An implementation could be improved by removing the need for
+  * lock acquisition - just keep a 'struct console *kdbconsole;' global
+  * variable which refers to the preferred kdb console.
+  *
+  * The bulk of this function is architecture dependent.
+  *
+  * The buffer size must be >= 2.  A buffer size of 2 means that the caller only
+  * wants a single key.
+  *
+  * An escape key could be the start of a vt100 control sequence such as \e[D
+  * (left arrow) or it could be a character in its own right.  The standard
+  * method for detecting the difference is to wait for 2 seconds to see if there
+  * are any other characters.  kdb is complicated by the lack of a timer service
+  * (interrupts are off), by multiple input sources and by the need to sometimes
+  * return after just one key.  Escape sequence processing has to be done as
+  * states in the polling loop.
+  */
+ 
+ char *
+ kdb_read(char *buffer, size_t bufsize)
+ {
+ 	char	*cp = buffer;
+ 	char	*bufend = buffer+bufsize-2;	/* Reserve space for newline and null byte */
+ 
+ 	char	*lastchar;
+ 	char	*p_tmp;
+ 	char	tmp;
+ 	static char	tmpbuffer[CMD_BUFLEN];
+ 	int len = strlen(buffer);
+ 	int len_tmp;
+ 	int tab=0;
+ 	int count;
+ 	int i;
+ 	int diag, dtab_count;
+ 
+ #define ESCAPE_UDELAY 1000
+ #define ESCAPE_DELAY 2*1000000/ESCAPE_UDELAY	/* 2 seconds worth of udelays */
+ 	char escape_data[5];	/* longest vt100 escape sequence is 4 bytes */
+ 	char *ped = escape_data;
+ 	int escape_delay = 0;
+ 	get_char_func *f, *f_escape = NULL;
+ 
+ 	diag = kdbgetintenv("DTABCOUNT",&dtab_count);
+ 	if (diag)
+ 		dtab_count = 30;
+ 
+ 	if (len > 0 ) {
+ 		cp += len;
+ 		if (*(buffer+len-1) == '\n')
+ 			cp--;
+ 	}
+ 
+ 	lastchar = cp;
+ 	*cp = '\0';
+ 	kdb_printf("%s", buffer);
+ 
+ 	for (;;) {
+ 		int key;
+ 		for (f = &poll_funcs[0]; ; ++f) {
+ 			if (*f == NULL) {
+ 				/* Reset NMI watchdog once per poll loop */
+ 				touch_nmi_watchdog();
+ 				f = &poll_funcs[0];
+ 			}
+ 			if (escape_delay == 2) {
+ 				*ped = '\0';
+ 				ped = escape_data;
+ 				--escape_delay;
+ 			}
+ 			if (escape_delay == 1) {
+ 				key = *ped++;
+ 				if (!*ped)
+ 					--escape_delay;
+ 				break;
+ 			}
+ 			key = (*f)();
+ 			if (key == -1) {
+ 				if (escape_delay) {
+ 					udelay(ESCAPE_UDELAY);
+ 					--escape_delay;
+ 				}
+ 				continue;
+ 			}
+ 			if (bufsize <= 2) {
+ 				if (key == '\r')
+ 					key = '\n';
+ 				kdb_printf("%c", key);
+ 				*buffer++ = key;
+ 				*buffer = '\0';
+ 				return buffer;
+ 			}
+ 			if (escape_delay == 0 && key == '\e') {
+ 				escape_delay = ESCAPE_DELAY;
+ 				ped = escape_data;
+ 				f_escape = f;
+ 			}
+ 			if (escape_delay) {
+ 				*ped++ = key;
+ 				if (f_escape != f) {
+ 					escape_delay = 2;
+ 					continue;
+ 				}
+ 				if (ped - escape_data == 1) {
+ 					/* \e */
+ 					continue;
+ 				}
+ 				else if (ped - escape_data == 2) {
+ 					/* \e<something> */
+ 					if (key != '[')
+ 						escape_delay = 2;
+ 					continue;
+ 				} else if (ped - escape_data == 3) {
+ 					/* \e[<something> */
+ 					int mapkey = 0;
+ 					switch (key) {
+ 					case 'A': mapkey = 16; break;	/* \e[A, up arrow */
+ 					case 'B': mapkey = 14; break;	/* \e[B, down arrow */
+ 					case 'C': mapkey = 6; break;	/* \e[C, right arrow */
+ 					case 'D': mapkey = 2; break;	/* \e[D, left arrow */
+ 					case '1': /* dropthrough */
+ 					case '3': /* dropthrough */
+ 					case '4': mapkey = -1; break;	/* \e[<1,3,4>], may be home, del, end */
+ 					}
+ 					if (mapkey != -1) {
+ 						if (mapkey > 0) {
+ 							escape_data[0] = mapkey;
+ 							escape_data[1] = '\0';
+ 						}
+ 						escape_delay = 2;
+ 					}
+ 					continue;
+ 				} else if (ped - escape_data == 4) {
+ 					/* \e[<1,3,4><something> */
+ 					int mapkey = 0;
+ 					if (key == '~') {
+ 						switch (escape_data[2]) {
+ 						case '1': mapkey = 1; break;	/* \e[1~, home */
+ 						case '3': mapkey = 4; break;	/* \e[3~, del */
+ 						case '4': mapkey = 5; break;	/* \e[4~, end */
+ 						}
+ 					}
+ 					if (mapkey > 0) {
+ 						escape_data[0] = mapkey;
+ 						escape_data[1] = '\0';
+ 					}
+ 					escape_delay = 2;
+ 					continue;
+ 				}
+ 			}
+ 			break;	/* A key to process */
+ 		}
+ 
+ 		if (key != 9)
+ 			tab = 0;
+ 		switch (key) {
+ 		case 8: /* backspace */
+ 			if (cp > buffer) {
+ 				if (cp < lastchar) {
+ 					memcpy(tmpbuffer, cp, lastchar - cp);
+ 					memcpy(cp-1, tmpbuffer, lastchar - cp);
+ 				}
+ 				*(--lastchar) = '\0';
+ 				--cp;
+ 				kdb_printf("\b%s \r", cp);
+ 				tmp = *cp;
+ 				*cp = '\0';
+ 				kdb_printf(kdb_prompt_str);
+ 				kdb_printf("%s", buffer);
+ 				*cp = tmp;
+ 			}
+ 			break;
+ 		case 13: /* enter */
+ 			*lastchar++ = '\n';
+ 			*lastchar++ = '\0';
+ 			kdb_printf("\n");
+ 			return buffer;
+ 		case 4: /* Del */
+ 			if(cp < lastchar) {
+ 				memcpy(tmpbuffer, cp+1, lastchar - cp -1);
+ 				memcpy(cp, tmpbuffer, lastchar - cp -1);
+ 				*(--lastchar) = '\0';
+ 				kdb_printf("%s \r", cp);
+ 				tmp = *cp;
+ 				*cp = '\0';
+ 				kdb_printf(kdb_prompt_str);
+ 				kdb_printf("%s", buffer);
+ 				*cp = tmp;
+ 			}
+ 			break;
+ 		case 1: /* Home */
+ 			if(cp > buffer) {
+ 				kdb_printf("\r");
+ 				kdb_printf(kdb_prompt_str);
+ 				cp = buffer;
+ 			}
+ 			break;
+ 		case 5: /* End */
+ 			if(cp < lastchar) {
+ 				kdb_printf("%s", cp);
+ 				cp = lastchar;
+ 			}
+ 			break;
+ 		case 2: /* Left */
+ 			if (cp > buffer) {
+ 				kdb_printf("\b");
+ 				--cp;
+ 			}
+ 			break;
+ 		case 14: /* Down */
+ 			memset(tmpbuffer, ' ', strlen(kdb_prompt_str)+(lastchar-buffer));
+ 			*(tmpbuffer+strlen(kdb_prompt_str)+(lastchar-buffer)) = '\0';
+ 			kdb_printf("\r%s\r", tmpbuffer);
+ 			*lastchar = (char)key;
+ 			*(lastchar+1) = '\0';
+ 			return lastchar;
+ 		case 6: /* Right */
+ 			if (cp < lastchar) {
+ 				kdb_printf("%c", *cp);
+ 				++cp;
+ 			}
+ 			break;
+ 		case 16: /* Up */
+ 			memset(tmpbuffer, ' ', strlen(kdb_prompt_str)+(lastchar-buffer));
+ 			*(tmpbuffer+strlen(kdb_prompt_str)+(lastchar-buffer)) = '\0';
+ 			kdb_printf("\r%s\r", tmpbuffer);
+ 			*lastchar = (char)key;
+ 			*(lastchar+1) = '\0';
+ 			return lastchar;
+ 		case 9: /* Tab */
+ 			if (tab < 2)
+ 				++tab;
+ 			p_tmp = buffer;
+ 			while(*p_tmp==' ') p_tmp++;
+ 			if (p_tmp<=cp) {
+ 				memcpy(tmpbuffer, p_tmp, cp-p_tmp);
+ 				*(tmpbuffer + (cp-p_tmp)) = '\0';
+ 				p_tmp = strrchr(tmpbuffer, ' ');
+ 				if (p_tmp)
+ 					++p_tmp;
+ 				else
+ 					p_tmp = tmpbuffer;
+ 				len = strlen(p_tmp);
+ 				if (tab == 2) {
+ 					if((count=kallsyms_symbol_complete(p_tmp))>0) {
+ 						kdb_printf("\n%d symbols are found.", count);
+ 						if(count>dtab_count) {
+ 							count=dtab_count;
+ 							kdb_printf(" But only first %d symbols will be printed.\nYou can change the environment variable DTABCOUNT.", count);
+ 						}
+ 						kdb_printf("\n");
+ 						for(i=0;i<count;i++) {
+ 							if(kallsyms_symbol_next(p_tmp, i)<0)
+ 								break;
+ 							kdb_printf("%s ",p_tmp);
+ 							*(p_tmp+len)='\0';
+ 						}
+ 						if(i>=dtab_count)kdb_printf("...");
+ 						kdb_printf("\n");
+ 						kdb_printf(kdb_prompt_str);
+ 						kdb_printf("%s", buffer);
+ 					}
+ 				}
+ 				else {
+ 					if(kallsyms_symbol_complete(p_tmp)>0) {
+ 						len_tmp = strlen(p_tmp);
+ 						strncpy(p_tmp+len_tmp,cp, lastchar-cp+1);
+ 						len_tmp = strlen(p_tmp);
+ 						strncpy(cp, p_tmp+len, len_tmp-len+1);
+ 						len = len_tmp - len;
+ 						kdb_printf("%s", cp);
+ 						cp+=len;
+ 						lastchar+=len;
+ 					}
+ 				}
+ 				kdb_nextline = 1;		/* reset output line number */
+ 			}
+ 			break;
+ 		default:
+ 			if (key >= 32 &&lastchar < bufend) {
+ 				if (cp < lastchar) {
+ 					memcpy(tmpbuffer, cp, lastchar - cp);
+ 					memcpy(cp+1, tmpbuffer, lastchar - cp);
+ 				}
+ 				*(++lastchar) = '\0';
+ 				*cp = key;
+ 				kdb_printf("%s\r", cp);
+ 				++cp;
+ 				tmp = *cp;
+ 				*cp = '\0';
+ 				kdb_printf(kdb_prompt_str);
+ 				kdb_printf("%s", buffer);
+ 				*cp = tmp;
+ 			}
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ /*
+  * kdb_getstr
+  *
+  *	Print the prompt string and read a command from the
+  *	input device.
+  *
+  * Parameters:
+  *	buffer	Address of buffer to receive command
+  *	bufsize Size of buffer in bytes
+  *	prompt	Pointer to string to use as prompt string
+  * Returns:
+  *	Pointer to command buffer.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	For SMP kernels, the processor number will be
+  *	substituted for %d, %x or %o in the prompt.
+  */
+ 
+ char *
+ kdb_getstr(char *buffer, size_t bufsize, char *prompt)
+ {
+ 	if(prompt && kdb_prompt_str!=prompt)
+ 		strncpy(kdb_prompt_str, prompt, CMD_BUFLEN);
+ 	kdb_printf(kdb_prompt_str);
+ 	kdb_nextline = 1;	/* Prompt and input resets line number */
+ 	return kdb_read(buffer, bufsize);
+ }
+ 
+ /*
+  * kdb_input_flush
+  *
+  *	Get rid of any buffered console input.
+  *
+  * Parameters:
+  *	none
+  * Returns:
+  *	nothing
+  * Locking:
+  *	none
+  * Remarks:
+  *	Call this function whenever you want to flush input.  If there is any
+  *	outstanding input, it ignores all characters until there has been no
+  *	data for approximately half a second.
+  */
+ 
+ #define FLUSH_UDELAY 100
+ #define FLUSH_DELAY 500000/FLUSH_UDELAY	/* 0.5 seconds worth of udelays */
+ 
+ static void
+ kdb_input_flush(void)
+ {
+ 	get_char_func *f;
+ 	int flush_delay = 1;
+ 	while (flush_delay--) {
+ 		touch_nmi_watchdog();
+ 		for (f = &poll_funcs[0]; *f; ++f) {
+ 			if ((*f)() != -1) {
+ 				flush_delay = FLUSH_DELAY;
+ 				break;
+ 			}
+ 		}
+ 		if (flush_delay)
+ 			udelay(FLUSH_UDELAY);
+ 	}
+ }
+ 
+ /*
+  * kdb_printf
+  *
+  *	Print a string to the output device(s).
+  *
+  * Parameters:
+  *	printf-like format and optional args.
+  * Returns:
+  *	0
+  * Locking:
+  *	None.
+  * Remarks:
+  *	use 'kdbcons->write()' to avoid polluting 'log_buf' with
+  *	kdb output.
+  */
+ 
+ static char kdb_buffer[256];	/* A bit too big to go on stack */
+ 
+ void
+ kdb_printf(const char *fmt, ...)
+ {
+ 	va_list	ap;
+ 	int diag;
+ 	int linecount;
+ 	int logging, saved_loglevel = 0;
+ 	int do_longjmp = 0;
+ 	int got_printf_lock = 0;
+ 	struct console *c = console_drivers;
+ 	static spinlock_t kdb_printf_lock = SPIN_LOCK_UNLOCKED;
+ 
+ 	/* Serialize kdb_printf if multiple cpus try to write at once.
+ 	 * But if any cpu goes recursive in kdb, just print the output,
+ 	 * even if it is interleaved with any other text.
+ 	 */
+ 	if (!KDB_STATE(PRINTF_LOCK)) {
+ 		KDB_STATE_SET(PRINTF_LOCK);
+ 		spin_lock(&kdb_printf_lock);
+ 		got_printf_lock = 1;
+ 	}
+ 
+ 	diag = kdbgetintenv("LINES", &linecount);
+ 	if (diag || linecount <= 1)
+ 		linecount = 22;
+ 
+ 	diag = kdbgetintenv("LOGGING", &logging);
+ 	if (diag)
+ 		logging = 0;
+ 
+ 	va_start(ap, fmt);
+ 	vsnprintf(kdb_buffer, sizeof(kdb_buffer), fmt, ap);
+ 	va_end(ap);
+ 
+ 	/*
+ 	 * Write to all consoles.
+ 	 */
+ #ifdef CONFIG_SPARC64
+ 	if (c == NULL)
+ 		prom_printf("%s", kdb_buffer);
+ 	else
+ #endif
+ 	while (c) {
+ 		c->write(c, kdb_buffer, strlen(kdb_buffer));
+ 		c = c->next;
+ 	}
+ 	if (logging) {
+ 		saved_loglevel = console_loglevel;
+ 		console_loglevel = 0;
+ 		printk("%s", kdb_buffer);
+ 	}
+ 
+ 	if (KDB_STATE(LONGJMP) && strchr(kdb_buffer, '\n'))
+ 		kdb_nextline++;
+ 
+ 	if (kdb_nextline == linecount) {
+ 		char buf1[16]="";
+ #if defined(CONFIG_SMP)
+ 		char buf2[32];
+ #endif
+ 		char *moreprompt;
+ 
+ 		/* Watch out for recursion here.  Any routine that calls
+ 		 * kdb_printf will come back through here.  And kdb_read
+ 		 * uses kdb_printf to echo on serial consoles ...
+ 		 */
+ 		kdb_nextline = 1;	/* In case of recursion */
+ 
+ 		/*
+ 		 * Pause until cr.
+ 		 */
+ 		moreprompt = kdbgetenv("MOREPROMPT");
+ 		if (moreprompt == NULL) {
+ 			moreprompt = "more> ";
+ 		}
+ 
+ #if defined(CONFIG_SMP)
+ 		if (strchr(moreprompt, '%')) {
+ 			sprintf(buf2, moreprompt, smp_processor_id());
+ 			moreprompt = buf2;
+ 		}
+ #endif
+ 
+ 		kdb_input_flush();
+ 		c = console_drivers;
+ #ifdef CONFIG_SPARC64
+ 		if (c == NULL)
+ 			prom_printf("%s", moreprompt);
+ 		else
+ #endif
+ 		while (c) {
+ 			c->write(c, moreprompt, strlen(moreprompt));
+ 			c = c->next;
+ 		}
+ 
+ 		if (logging)
+ 			printk("%s", moreprompt);
+ 
+ 		kdb_read(buf1, 2); /* '2' indicates to return immediately after getting one key. */
+ 		kdb_nextline = 1;	/* Really set output line 1 */
+ 
+ 		if ((buf1[0] == 'q') || (buf1[0] == 'Q')) {
+ 			do_longjmp = 1;
+ 			KDB_FLAG_SET(CMD_INTERRUPT);	/* command was interrupted */
+ 			kdb_printf("\n");
+ 		}
+ 		else if (buf1[0] && buf1[0] != '\n') {
+ 			kdb_printf("\nOnly 'q' or 'Q' are processed at more prompt, input ignored\n");
+ 		}
+ 		kdb_input_flush();
+ 	}
+ 
+ 	if (logging) {
+ 		console_loglevel = saved_loglevel;
+ 	}
+ 	if (KDB_STATE(PRINTF_LOCK) && got_printf_lock) {
+ 		got_printf_lock = 0;
+ 		spin_unlock(&kdb_printf_lock);
+ 		KDB_STATE_CLEAR(PRINTF_LOCK);
+ 	}
+ 	if (do_longjmp)
+ #ifdef KDB_HAVE_LONGJMP
+ 		kdba_longjmp(&kdbjmpbuf[smp_processor_id()], 1)
+ #endif	/* KDB_HAVE_LONGJMP */
+ 		;
+ }
+ 
+ /*
+  * kdb_io_init
+  *
+  *	Initialize kernel debugger output environment.
+  *
+  * Parameters:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	Select a console device.
+  */
+ 
+ void __init
+ kdb_io_init(void)
+ {
+ #ifndef CONFIG_SPARC64 /* we don't register serial consoles in time */
+ 	/*
+  	 * Select a console.
+  	 */
+ 	struct console *c = console_drivers;
+ 
+ 	while (c) {
+ 		if ((c->flags & CON_CONSDEV)) {
+ 			kdbcons = c;
+ 			break;
+ 		}
+ 		c = c->next;
+ 	}
+ 
+ 	if (kdbcons == NULL) {
+ 		printk("kdb: Initialization failed - no console\n");
+ 		while (1) {};
+ 	}
+ 	kdb_input_flush();
+ #endif
+ 	return;
+ }
+ 
+ EXPORT_SYMBOL(kdb_read);
diff -c -r -N console-os/kdb/kdbmain.c console-os-kdb/kdb/kdbmain.c
*** console-os/kdb/kdbmain.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/kdbmain.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,3678 ----
+ /*
+  * Kernel Debugger Architecture Independent Main Code
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+  * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+  * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ /*
+  * Updated for Xscale (R) architecture support 
+  * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+  */
+ 
+ #include <linux/config.h>
+ #include <linux/ctype.h>
+ #include <linux/string.h>
+ #include <linux/kernel.h>
+ #include <linux/reboot.h>
+ #include <linux/sched.h>
+ #include <linux/sysrq.h>
+ #include <linux/smp.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/kallsyms.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ #include <linux/notifier.h>
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+ #include <linux/nmi.h>
+ #if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ #include <linux/dump.h>
+ #endif
+ 
+ #include <asm/system.h>
+ 
+ #if defined(CONFIG_MODULES)
+ extern struct module *module_list;
+ #endif
+ 
+ 	/*
+ 	 * Kernel debugger state flags
+ 	 */
+ volatile int kdb_flags;
+ volatile int kdb_enter_debugger;
+ 
+ 	/*
+ 	 * kdb_lock protects updates to kdb_initial_cpu.  Used to
+ 	 * single thread processors through the kernel debugger.
+ 	 */
+ spinlock_t kdb_lock = SPIN_LOCK_UNLOCKED;
+ volatile int kdb_initial_cpu = -1;		/* cpu number that owns kdb */
+ int kdb_seqno = 2;				/* how many times kdb has been entered */
+ 
+ volatile int kdb_nextline = 1;
+ static volatile int kdb_new_cpu;		/* Which cpu to switch to */
+ struct task_struct *kdb_active_task[NR_CPUS];	/* Task that is active on each cpu */
+ 
+ volatile int kdb_state[NR_CPUS];		/* Per cpu state */
+ 
+ struct task_struct *kdb_current_task;
+ 
+ #ifdef	CONFIG_KDB_OFF
+ int kdb_on = 0;				/* Default is off */
+ #else
+ int kdb_on = 1;				/* Default is on */
+ #endif	/* CONFIG_KDB_OFF */
+ 
+ const char *kdb_diemsg;
+ struct notifier_block *kdb_notifier_list;	/* racy for modules, see comments in kdb.h */
+ static int kdb_go_count;
+ #ifdef CONFIG_KDB_CONTINUE_CATASTROPHIC
+ static unsigned int kdb_continue_catastrophic = CONFIG_KDB_CONTINUE_CATASTROPHIC;
+ #else
+ static unsigned int kdb_continue_catastrophic = 0;
+ #endif
+ 
+ #ifdef KDB_HAVE_LONGJMP
+ 	/*
+ 	 * Must have a setjmp buffer per CPU.  Switching cpus will
+ 	 * cause the jump buffer to be setup for the new cpu, and
+ 	 * subsequent switches (and pager aborts) will use the
+ 	 * appropriate per-processor values.
+ 	 */
+ kdb_jmp_buf	kdbjmpbuf[NR_CPUS];
+ #endif	/* KDB_HAVE_LONGJMP */
+ 
+ 	/*
+ 	 * kdb_commands describes the available commands.
+ 	 */
+ static kdbtab_t *kdb_commands;
+ static int kdb_max_commands;
+ 
+ typedef struct _kdbmsg {
+ 	int	km_diag;	/* kdb diagnostic */
+ 	char	*km_msg;	/* Corresponding message text */
+ } kdbmsg_t;
+ 
+ #define KDBMSG(msgnum, text) \
+ 	{ KDB_##msgnum, text }
+ 
+ static kdbmsg_t kdbmsgs[] = {
+ 	KDBMSG(NOTFOUND,"Command Not Found"),
+ 	KDBMSG(ARGCOUNT, "Improper argument count, see usage."),
+ 	KDBMSG(BADWIDTH, "Illegal value for BYTESPERWORD use 1, 2, 4 or 8, 8 is only allowed on 64 bit systems"),
+ 	KDBMSG(BADRADIX, "Illegal value for RADIX use 8, 10 or 16"),
+ 	KDBMSG(NOTENV, "Cannot find environment variable"),
+ 	KDBMSG(NOENVVALUE, "Environment variable should have value"),
+ 	KDBMSG(NOTIMP, "Command not implemented"),
+ 	KDBMSG(ENVFULL, "Environment full"),
+ 	KDBMSG(ENVBUFFULL, "Environment buffer full"),
+ 	KDBMSG(TOOMANYBPT, "Too many breakpoints defined"),
+ #ifdef  CONFIG_CPU_XSCALE
+ 	KDBMSG(TOOMANYDBREGS, "More breakpoints than ibcr registers defined"),
+ #else
+ 	KDBMSG(TOOMANYDBREGS, "More breakpoints than db registers defined"),
+ #endif
+ 	KDBMSG(DUPBPT, "Duplicate breakpoint address"),
+ 	KDBMSG(BPTNOTFOUND, "Breakpoint not found"),
+ 	KDBMSG(BADMODE, "Invalid IDMODE"),
+ 	KDBMSG(BADINT, "Illegal numeric value"),
+ 	KDBMSG(INVADDRFMT, "Invalid symbolic address format"),
+ 	KDBMSG(BADREG, "Invalid register name"),
+ 	KDBMSG(BADCPUNUM, "Invalid cpu number"),
+ 	KDBMSG(BADLENGTH, "Invalid length field"),
+ 	KDBMSG(NOBP, "No Breakpoint exists"),
+ 	KDBMSG(BADADDR, "Invalid address"),
+ };
+ #undef KDBMSG
+ 
+ static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t);
+ 
+ 
+ /*
+  * Initial environment.   This is all kept static and local to
+  * this file.   We don't want to rely on the memory allocation
+  * mechanisms in the kernel, so we use a very limited allocate-only
+  * heap for new and altered environment variables.  The entire
+  * environment is limited to a fixed number of entries (add more
+  * to __env[] if required) and a fixed amount of heap (add more to
+  * KDB_ENVBUFSIZE if required).
+  */
+ 
+ static char *__env[] = {
+ #if defined(CONFIG_SMP)
+  "PROMPT=[%d]kdb> ",
+  "MOREPROMPT=[%d]more> ",
+ #else
+  "PROMPT=kdb> ",
+  "MOREPROMPT=more> ",
+ #endif
+  "RADIX=16",
+  "LINES=24",
+  "COLUMNS=80",
+  "MDCOUNT=8",			/* lines of md output */
+  "BTARGS=5",			/* 5 possible args in bt */
+  KDB_PLATFORM_ENV,
+  "DTABCOUNT=30",
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+  (char *)0,
+ };
+ 
+ static const int __nenv = (sizeof(__env) / sizeof(char *));
+ 
+ /* 
+  * kdb_serial_str is the sequence that the user must enter on a serial
+  * console to invoke kdb.  It can be a single character such as "\001"
+  * (control-A) or multiple characters such as "\eKDB".  NOTE: All except the
+  * last character are passed through to the application reading from the serial
+  * console.
+  *
+  * I tried to make the sequence a CONFIG_ option but most of CML1 cannot cope
+  * with '\' in strings.  CML2 would have been able to do it but we lost CML2.
+  * KAO.
+  */
+ const char kdb_serial_str[] = "\001";
+ 
+ /*
+  * kdbgetenv
+  *
+  *	This function will return the character string value of
+  *	an environment variable.
+  *
+  * Parameters:
+  *	match	A character string representing an environment variable.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	NULL	No environment variable matches 'match'
+  *	char*	Pointer to string value of environment variable.
+  * Locking:
+  *	No locking considerations required.
+  * Remarks:
+  */
+ char *
+ kdbgetenv(const char *match)
+ {
+ 	char **ep = __env;
+ 	int    matchlen = strlen(match);
+ 	int i;
+ 
+ 	for(i=0; i<__nenv; i++) {
+ 		char *e = *ep++;
+ 
+ 		if (!e) continue;
+ 
+ 		if ((strncmp(match, e, matchlen) == 0)
+ 		 && ((e[matchlen] == '\0')
+ 		   ||(e[matchlen] == '='))) {
+ 			char *cp = strchr(e, '=');
+ 			return (cp)?++cp:"";
+ 		}
+ 	}
+ 	return (char *)0;
+ }
+ 
+ /*
+  * kdballocenv
+  *
+  *	This function is used to allocate bytes for environment entries.
+  *
+  * Parameters:
+  *	match	A character string representing a numeric value
+  * Outputs:
+  *	*value  the unsigned long represntation of the env variable 'match'
+  * Returns:
+  *	Zero on success, a kdb diagnostic on failure.
+  * Locking:
+  *	No locking considerations required.  Must be called with all
+  *	processors halted.
+  * Remarks:
+  *	We use a static environment buffer (envbuffer) to hold the values
+  *	of dynamically generated environment variables (see kdb_set).  Buffer
+  *	space once allocated is never free'd, so over time, the amount of space
+  *	(currently 512 bytes) will be exhausted if env variables are changed
+  *	frequently.
+  */
+ static char *
+ kdballocenv(size_t bytes)
+ {
+ #define	KDB_ENVBUFSIZE	512
+ 	static char envbuffer[KDB_ENVBUFSIZE];
+ 	static int  envbufsize;
+ 	char *ep = (char *)0;
+ 
+ 	if ((KDB_ENVBUFSIZE - envbufsize) >= bytes) {
+ 		ep = &envbuffer[envbufsize];
+ 		envbufsize += bytes;
+ 	}
+ 	return ep;
+ }
+ 
+ /*
+  * kdbgetulenv
+  *
+  *	This function will return the value of an unsigned long-valued
+  *	environment variable.
+  *
+  * Parameters:
+  *	match	A character string representing a numeric value
+  * Outputs:
+  *	*value  the unsigned long represntation of the env variable 'match'
+  * Returns:
+  *	Zero on success, a kdb diagnostic on failure.
+  * Locking:
+  *	No locking considerations required.
+  * Remarks:
+  */
+ 
+ int
+ kdbgetulenv(const char *match, unsigned long *value)
+ {
+ 	char *ep;
+ 
+ 	ep = kdbgetenv(match);
+ 	if (!ep) return KDB_NOTENV;
+ 	if (strlen(ep) == 0) return KDB_NOENVVALUE;
+ 
+ 	*value = simple_strtoul(ep, 0, 0);
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdbgetintenv
+  *
+  *	This function will return the value of an integer-valued
+  *	environment variable.
+  *
+  * Parameters:
+  *	match	A character string representing an integer-valued env variable
+  * Outputs:
+  *	*value  the integer representation of the environment variable 'match'
+  * Returns:
+  *	Zero on success, a kdb diagnostic on failure.
+  * Locking:
+  *	No locking considerations required.
+  * Remarks:
+  */
+ 
+ int
+ kdbgetintenv(const char *match, int *value) {
+ 	unsigned long val;
+ 	int           diag;
+ 
+ 	diag = kdbgetulenv(match, &val);
+ 	if (!diag) {
+ 		*value = (int) val;
+ 	}
+ 	return diag;
+ }
+ 
+ /*
+  * kdbgetularg
+  *
+  *	This function will convert a numeric string
+  *	into an unsigned long value.
+  *
+  * Parameters:
+  *	arg	A character string representing a numeric value
+  * Outputs:
+  *	*value  the unsigned long represntation of arg.
+  * Returns:
+  *	Zero on success, a kdb diagnostic on failure.
+  * Locking:
+  *	No locking considerations required.
+  * Remarks:
+  */
+ 
+ int
+ kdbgetularg(const char *arg, unsigned long *value)
+ {
+ 	char *endp;
+ 	unsigned long val;
+ 
+ 	val = simple_strtoul(arg, &endp, 0);
+ 
+ 	if (endp == arg) {
+ 		/*
+ 		 * Try base 16, for us folks too lazy to type the
+ 		 * leading 0x...
+ 		 */
+ 		val = simple_strtoul(arg, &endp, 16);
+ 		if (endp == arg)
+ 			return KDB_BADINT;
+ 	}
+ 
+ 	*value = val;
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_set
+  *
+  *	This function implements the 'set' command.  Alter an existing
+  *	environment variable or create a new one.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ int
+ kdb_set(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int i;
+ 	char *ep;
+ 	size_t varlen, vallen;
+ 
+ 	/*
+ 	 * we can be invoked two ways:
+ 	 *   set var=value    argv[1]="var", argv[2]="value"
+ 	 *   set var = value  argv[1]="var", argv[2]="=", argv[3]="value"
+ 	 * - if the latter, shift 'em down.
+ 	 */
+ 	if (argc == 3) {
+ 		argv[2] = argv[3];
+ 		argc--;
+ 	}
+ 
+ 	if (argc != 2)
+ 		return KDB_ARGCOUNT;
+ 
+ 	/*
+ 	 * Check for internal variables
+ 	 */
+ 	if (strcmp(argv[1], "KDBDEBUG") == 0) {
+ 		unsigned int debugflags;
+ 		char *cp;
+ 
+ 		debugflags = simple_strtoul(argv[2], &cp, 0);
+ 		if (cp == argv[2] || debugflags & ~KDB_DEBUG_FLAG_MASK) {
+ 			kdb_printf("kdb: illegal debug flags '%s'\n",
+ 				    argv[2]);
+ 			return 0;
+ 		}
+ 		kdb_flags = (kdb_flags & ~(KDB_DEBUG_FLAG_MASK << KDB_DEBUG_FLAG_SHIFT))
+ 			  | (debugflags << KDB_DEBUG_FLAG_SHIFT);
+ 
+ 		return 0;
+ 	}
+ 
+ 	/*
+ 	 * Tokenizer squashed the '=' sign.  argv[1] is variable
+ 	 * name, argv[2] = value.
+ 	 */
+ 	varlen = strlen(argv[1]);
+ 	vallen = strlen(argv[2]);
+ 	ep = kdballocenv(varlen + vallen + 2);
+ 	if (ep == (char *)0)
+ 		return KDB_ENVBUFFULL;
+ 
+ 	sprintf(ep, "%s=%s", argv[1], argv[2]);
+ 
+ 	ep[varlen+vallen+1]='\0';
+ 
+ 	for(i=0; i<__nenv; i++) {
+ 		if (__env[i]
+ 		 && ((strncmp(__env[i], argv[1], varlen)==0)
+ 		   && ((__env[i][varlen] == '\0')
+ 		    || (__env[i][varlen] == '=')))) {
+ 			__env[i] = ep;
+ 			return 0;
+ 		}
+ 	}
+ 
+ 	/*
+ 	 * Wasn't existing variable.  Fit into slot.
+ 	 */
+ 	for(i=0; i<__nenv-1; i++) {
+ 		if (__env[i] == (char *)0) {
+ 			__env[i] = ep;
+ 			return 0;
+ 		}
+ 	}
+ 
+ 	return KDB_ENVFULL;
+ }
+ 
+ /*
+  * kdbgetaddrarg
+  *
+  *	This function is responsible for parsing an
+  *	address-expression and returning the value of
+  *	the expression, symbol name, and offset to the caller.
+  *
+  *	The argument may consist of a numeric value (decimal or
+  *	hexidecimal), a symbol name, a register name (preceeded
+  *	by the percent sign), an environment variable with a numeric
+  *	value (preceeded by a dollar sign) or a simple arithmetic
+  *	expression consisting of a symbol name, +/-, and a numeric
+  *	constant value (offset).
+  *
+  * Parameters:
+  *	argc	- count of arguments in argv
+  *	argv	- argument vector
+  *	*nextarg - index to next unparsed argument in argv[]
+  *	regs	- Register state at time of KDB entry
+  * Outputs:
+  *	*value	- receives the value of the address-expression
+  *	*offset - receives the offset specified, if any
+  *	*name   - receives the symbol name, if any
+  *	*nextarg - index to next unparsed argument in argv[]
+  *
+  * Returns:
+  *	zero is returned on success, a kdb diagnostic code is
+  *      returned on error.
+  *
+  * Locking:
+  *	No locking requirements.
+  *
+  * Remarks:
+  *
+  */
+ 
+ int
+ kdbgetaddrarg(int argc, const char **argv, int *nextarg,
+ 	      kdb_machreg_t *value,  long *offset,
+ 	      char **name, struct pt_regs *regs)
+ {
+ 	kdb_machreg_t addr;
+ 	long	      off = 0;
+ 	int	      positive;
+ 	int	      diag;
+ 	int	      found = 0;
+ 	char	     *symname;
+ 	char	      symbol = '\0';
+ 	char	     *cp;
+ 	kdb_symtab_t   symtab;
+ 
+ 	/*
+ 	 * Process arguments which follow the following syntax:
+ 	 *
+ 	 *  symbol | numeric-address [+/- numeric-offset]
+ 	 *  %register
+ 	 *  $environment-variable
+ 	 */
+ 
+ 	if (*nextarg > argc) {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 
+ 	symname = (char *)argv[*nextarg];
+ 
+ 	/*
+ 	 * If there is no whitespace between the symbol
+ 	 * or address and the '+' or '-' symbols, we
+ 	 * remember the character and replace it with a
+ 	 * null so the symbol/value can be properly parsed
+ 	 */
+ 	if ((cp = strpbrk(symname, "+-")) != NULL) {
+ 		symbol = *cp;
+ 		*cp++ = '\0';
+ 	}
+ 
+ 	if (symname[0] == '$') {
+ 		diag = kdbgetulenv(&symname[1], &addr);
+ 		if (diag)
+ 			return diag;
+ 	} else if (symname[0] == '%') {
+ 		diag = kdba_getregcontents(&symname[1], regs, &addr);
+ 		if (diag)
+ 			return diag;
+ 	} else {
+ 		found = kdbgetsymval(symname, &symtab);
+ 		if (found) {
+ 			addr = symtab.sym_start;
+ 		} else {
+ 			diag = kdbgetularg(argv[*nextarg], &addr);
+ 			if (diag)
+ 				return diag;
+ 		}
+ 	}
+ 
+ 	if (!found)
+ 		found = kdbnearsym(addr, &symtab);
+ 
+ 	(*nextarg)++;
+ 
+ 	if (name)
+ 		*name = symname;
+ 	if (value)
+ 		*value = addr;
+ 	if (offset && name && *name)
+ 		*offset = addr - symtab.sym_start;
+ 
+ 	if ((*nextarg > argc)
+ 	 && (symbol == '\0'))
+ 		return 0;
+ 
+ 	/*
+ 	 * check for +/- and offset
+ 	 */
+ 
+ 	if (symbol == '\0') {
+ 		if ((argv[*nextarg][0] != '+')
+ 		 && (argv[*nextarg][0] != '-')) {
+ 			/*
+ 			 * Not our argument.  Return.
+ 			 */
+ 			return 0;
+ 		} else {
+ 			positive = (argv[*nextarg][0] == '+');
+ 			(*nextarg)++;
+ 		}
+ 	} else
+ 		positive = (symbol == '+');
+ 
+ 	/*
+ 	 * Now there must be an offset!
+ 	 */
+ 	if ((*nextarg > argc)
+ 	 && (symbol == '\0')) {
+ 		return KDB_INVADDRFMT;
+ 	}
+ 
+ 	if (!symbol) {
+ 		cp = (char *)argv[*nextarg];
+ 		(*nextarg)++;
+ 	}
+ 
+ 	diag = kdbgetularg(cp, &off);
+ 	if (diag)
+ 		return diag;
+ 
+ 	if (!positive)
+ 		off = -off;
+ 
+ 	if (offset)
+ 		*offset += off;
+ 
+ 	if (value)
+ 		*value += off;
+ 
+ 	return 0;
+ }
+ 
+ static void
+ kdb_cmderror(int diag)
+ {
+ 	int i;
+ 
+ 	if (diag >= 0) {
+ 		kdb_printf("no error detected\n");
+ 		return;
+ 	}
+ 
+ 	for(i=0; i<__nkdb_err; i++) {
+ 		if (kdbmsgs[i].km_diag == diag) {
+ 			kdb_printf("diag: %d: %s\n", diag, kdbmsgs[i].km_msg);
+ 			return;
+ 		}
+ 	}
+ 
+ 	kdb_printf("Unknown diag %d\n", -diag);
+ }
+ 
+ /*
+  * kdb_defcmd, kdb_defcmd2
+  *
+  *	This function implements the 'defcmd' command which defines one
+  *	command as a set of other commands, terminated by endefcmd.
+  *	kdb_defcmd processes the initial 'defcmd' command, kdb_defcmd2
+  *	is invoked from kdb_parse for the following commands until
+  *	'endefcmd'.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ struct defcmd_set {
+ 	int count;
+ 	int usable;
+ 	char *name;
+ 	char *usage;
+ 	char *help;
+ 	char **command;
+ };
+ static struct defcmd_set *defcmd_set;
+ static int defcmd_set_count;
+ static int defcmd_in_progress;
+ 
+ /* Forward references */
+ static int kdb_exec_defcmd(int argc, const char **argv, const char **envp, struct pt_regs *regs);
+ 
+ static int
+ kdb_defcmd2(const char *cmdstr, const char *argv0)
+ {
+ 	struct defcmd_set *s = defcmd_set + defcmd_set_count - 1;
+ 	char **save_command = s->command;
+ 	if (strcmp(argv0, "endefcmd") == 0) {
+ 		defcmd_in_progress = 0;
+ 		if (!s->count)
+ 			s->usable = 0;
+ 		if (s->usable)
+ 			kdb_register(s->name, kdb_exec_defcmd, s->usage, s->help, 0);
+ 		return 0;
+ 	}
+ 	if (!s->usable)
+ 		return KDB_NOTIMP;
+ 	s->command = kmalloc((s->count + 1) * sizeof(*(s->command)), GFP_KERNEL);
+ 	if (!s->command) {
+ 		kdb_printf("Could not allocate new kdb_defcmd table for %s\n", cmdstr);
+ 		s->usable = 0;
+ 		return KDB_NOTIMP;
+ 	}
+ 	memcpy(s->command, save_command, s->count * sizeof(*(s->command)));
+ 	s->command[s->count++] = kdb_strdup(cmdstr, GFP_KERNEL);
+ 	kfree(save_command);
+ 	return 0;
+ }
+ 
+ static int
+ kdb_defcmd(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	struct defcmd_set *save_defcmd_set = defcmd_set, *s;
+ 	if (argc != 3)
+ 		return KDB_ARGCOUNT;
+ 	if (defcmd_in_progress) {
+ 		kdb_printf("kdb: nested defcmd detected, assuming missing endefcmd\n");
+ 		kdb_defcmd2("endefcmd", "endefcmd");
+ 	}
+ 	defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set), GFP_KERNEL);
+ 	if (!defcmd_set) {
+ 		kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]);
+ 		defcmd_set = save_defcmd_set;
+ 		return KDB_NOTIMP;
+ 	}
+ 	memcpy(defcmd_set, save_defcmd_set, defcmd_set_count * sizeof(*defcmd_set));
+ 	kfree(save_defcmd_set);
+ 	s = defcmd_set + defcmd_set_count;
+ 	memset(s, 0, sizeof(*s));
+ 	s->usable = 1;
+ 	s->name = kdb_strdup(argv[1], GFP_KERNEL);
+ 	s->usage = kdb_strdup(argv[2], GFP_KERNEL);
+ 	s->help = kdb_strdup(argv[3], GFP_KERNEL);
+ 	if (s->usage[0] == '"') {
+ 		strcpy(s->usage, s->usage+1);
+ 		s->usage[strlen(s->usage)-1] = '\0';
+ 	}
+ 	if (s->help[0] == '"') {
+ 		strcpy(s->help, s->help+1);
+ 		s->help[strlen(s->help)-1] = '\0';
+ 	}
+ 	++defcmd_set_count;
+ 	defcmd_in_progress = 1;
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_exec_defcmd
+  *
+  *	Execute the set of commands associated with this defcmd name.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ static int
+ kdb_exec_defcmd(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int i, ret;
+ 	struct defcmd_set *s;
+ 	if (argc != 0)
+ 		return KDB_ARGCOUNT;
+ 	for (s = defcmd_set, i = 0; i < defcmd_set_count; ++i, ++s) {
+ 		if (strcmp(s->name, argv[0]) == 0)
+ 			break;
+ 	}
+ 	if (i == defcmd_set_count) {
+ 		kdb_printf("kdb_exec_defcmd: could not find commands for %s\n", argv[0]);
+ 		return KDB_NOTIMP;
+ 	}
+ 	for (i = 0; i < s->count; ++i) {
+ 		/* Recursive use of kdb_parse, do not use argv after this point */
+ 		argv = NULL;
+ 		kdb_printf("[%s]kdb> %s\n", s->name, s->command[i]);
+ 		if ((ret = kdb_parse(s->command[i], regs)))
+ 			return ret;
+ 	}
+ 	return 0;
+ }
+ 
+ /* Command history */
+ #define KDB_CMD_HISTORY_COUNT	32
+ #define CMD_BUFLEN		200	/* kdb_printf: max printline size == 256 */
+ static unsigned int cmd_head=0, cmd_tail=0;
+ static unsigned int cmdptr;
+ static char cmd_hist[KDB_CMD_HISTORY_COUNT][CMD_BUFLEN];
+ static char cmd_cur[CMD_BUFLEN];
+ 
+ /*
+  * kdb_parse
+  *
+  *	Parse the command line, search the command table for a
+  *	matching command and invoke the command function.
+  *	This function may be called recursively, if it is, the second call
+  *	will overwrite argv and cbuf.  It is the caller's responsibility to
+  *	save their argv if they recursively call kdb_parse().
+  *
+  * Parameters:
+  *      cmdstr	The input command line to be parsed.
+  *	regs	The registers at the time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Zero for success, a kdb diagnostic if failure.
+  * Locking:
+  * 	None.
+  * Remarks:
+  *	Limited to 20 tokens.
+  *
+  *	Real rudimentary tokenization. Basically only whitespace
+  *	is considered a token delimeter (but special consideration
+  *	is taken of the '=' sign as used by the 'set' command).
+  *
+  *	The algorithm used to tokenize the input string relies on
+  *	there being at least one whitespace (or otherwise useless)
+  *	character between tokens as the character immediately following
+  *	the token is altered in-place to a null-byte to terminate the
+  *	token string.
+  */
+ 
+ #define MAXARGC	20
+ 
+ int
+ kdb_parse(const char *cmdstr, struct pt_regs *regs)
+ {
+ 	static char *argv[MAXARGC];
+ 	static int  argc = 0;
+ 	static char cbuf[CMD_BUFLEN+2];
+ 	const char *cp;
+ 	char *cpp, quoted;
+ 	kdbtab_t *tp;
+ 	int i, escaped, ignore_errors = 0;
+ 
+ 	/*
+ 	 * First tokenize the command string.
+ 	 */
+ 	cp = cmdstr;
+ 
+ 	if (KDB_FLAG(CMD_INTERRUPT)) {
+ 		/* Previous command was interrupted, newline must not repeat the command */
+ 		KDB_FLAG_CLEAR(CMD_INTERRUPT);
+ 		argc = 0;	/* no repeat */
+ 	}
+ 
+ 	if (*cp != '\n' && *cp != '\0') {
+ 		argc = 0;
+ 		cpp = cbuf;
+ 		while (*cp) {
+ 			/* skip whitespace */
+ 			while (isspace(*cp)) cp++;
+ 			if ((*cp == '\0') || (*cp == '\n'))
+ 				break;
+ 			if (cpp >= cbuf + CMD_BUFLEN) {
+ 				kdb_printf("kdb_parse: command buffer overflow, command ignored\n%s\n", cmdstr);
+ 				return KDB_NOTFOUND;
+ 			}
+ 			if (argc >= MAXARGC - 1) {
+ 				kdb_printf("kdb_parse: too many arguments, command ignored\n%s\n", cmdstr);
+ 				return KDB_NOTFOUND;
+ 			}
+ 			argv[argc++] = cpp;
+ 			escaped = 0;
+ 			quoted = '\0';
+ 			/* Copy to next unquoted and unescaped whitespace or '=' */
+ 			while (*cp && *cp != '\n' && (escaped || quoted || !isspace(*cp))) {
+ 				if (cpp >= cbuf + CMD_BUFLEN)
+ 					break;
+ 				if (escaped) {
+ 					escaped = 0;
+ 					*cpp++ = *cp++;
+ 					continue;
+ 				}
+ 				if (*cp == '\\') {
+ 					escaped = 1;
+ 					++cp;
+ 					continue;
+ 				}
+ 				if (*cp == quoted) {
+ 					quoted = '\0';
+ 				} else if (*cp == '\'' || *cp == '"') {
+ 					quoted = *cp;
+ 				}
+ 				if ((*cpp = *cp++) == '=' && !quoted)
+ 					break;
+ 				++cpp;
+ 			}
+ 			*cpp++ = '\0';	/* Squash a ws or '=' character */
+ 		}
+ 	}
+ 	if (!argc)
+ 		return 0;
+ 	if (defcmd_in_progress) {
+ 		int result = kdb_defcmd2(cmdstr, argv[0]);
+ 		if (!defcmd_in_progress) {
+ 			argc = 0;	/* avoid repeat on endefcmd */
+ 			*(argv[0]) = '\0';
+ 		}
+ 		return result;
+ 	}
+ 	if (argv[0][0] == '-' && argv[0][1] && (argv[0][1] < '0' || argv[0][1] > '9')) {
+ 		ignore_errors = 1;
+ 		++argv[0];
+ 	}
+ 
+ 	for(tp=kdb_commands, i=0; i < kdb_max_commands; i++,tp++) {
+ 		if (tp->cmd_name) {
+ 			/*
+ 			 * If this command is allowed to be abbreviated,
+ 			 * check to see if this is it.
+ 			 */
+ 
+ 			if (tp->cmd_minlen
+ 			 && (strlen(argv[0]) <= tp->cmd_minlen)) {
+ 				if (strncmp(argv[0],
+ 					    tp->cmd_name,
+ 					    tp->cmd_minlen) == 0) {
+ 					break;
+ 				}
+ 			}
+ 
+ 			if (strcmp(argv[0], tp->cmd_name)==0) {
+ 				break;
+ 			}
+ 		}
+ 	}
+ 
+ 	/*
+ 	 * If we don't find a command by this name, see if the first
+ 	 * few characters of this match any of the known commands.
+ 	 * e.g., md1c20 should match md.
+ 	 */
+ 	if (i == kdb_max_commands) {
+ 		for(tp=kdb_commands, i=0; i < kdb_max_commands; i++,tp++) {
+ 			if (tp->cmd_name) {
+ 				if (strncmp(argv[0],
+ 					    tp->cmd_name,
+ 					    strlen(tp->cmd_name))==0) {
+ 					break;
+ 				}
+ 			}
+ 		}
+ 	}
+ 
+ 	if (i < kdb_max_commands) {
+ 		int result;
+ 		KDB_STATE_SET(CMD);
+ 		result = (*tp->cmd_func)(argc-1,
+ 				       (const char**)argv,
+ 				       (const char**)__env,
+ 				       regs);
+ 		if (result && ignore_errors && result > KDB_CMD_GO)
+ 			result = 0;
+ 		KDB_STATE_CLEAR(CMD);
+ 		switch (tp->cmd_repeat) {
+ 		case KDB_REPEAT_NONE:
+ 			argc = 0;
+ 			if (argv[0])
+ 				*(argv[0]) = '\0';
+ 			break;
+ 		case KDB_REPEAT_NO_ARGS:
+ 			argc = 1;
+ 			if (argv[1])
+ 				*(argv[1]) = '\0';
+ 			break;
+ 		case KDB_REPEAT_WITH_ARGS:
+ 			break;
+ 		}
+ 		return result;
+ 	}
+ 
+ 	/*
+ 	 * If the input with which we were presented does not
+ 	 * map to an existing command, attempt to parse it as an
+ 	 * address argument and display the result.   Useful for
+ 	 * obtaining the address of a variable, or the nearest symbol
+ 	 * to an address contained in a register.
+ 	 */
+ 	{
+ 		kdb_machreg_t value;
+ 		char *name = NULL;
+ 		long offset;
+ 		int nextarg = 0;
+ 
+ 		if (kdbgetaddrarg(0, (const char **)argv, &nextarg,
+ 				  &value, &offset, &name, regs)) {
+ 			return KDB_NOTFOUND;
+ 		}
+ 
+ 		kdb_printf("%s = ", argv[0]);
+ 		kdb_symbol_print(value, NULL, KDB_SP_DEFAULT);
+ 		kdb_printf("\n");
+ 		return 0;
+ 	}
+ }
+ 
+ 
+ static int
+ handle_ctrl_cmd(char *cmd)
+ {
+ #define CTRL_P	16
+ #define CTRL_N	14
+ 
+ 	/* initial situation */
+ 	if (cmd_head == cmd_tail) return 0;
+ 
+ 	switch(*cmd) {
+ 		case CTRL_P:
+ 			if (cmdptr != cmd_tail)
+ 				cmdptr = (cmdptr-1) % KDB_CMD_HISTORY_COUNT;
+ 			strncpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN);
+ 			return 1;
+ 		case CTRL_N:
+ 			if (cmdptr != cmd_head)
+ 				cmdptr = (cmdptr+1) % KDB_CMD_HISTORY_COUNT;
+ 			strncpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN);
+ 			return 1;
+ 	}
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_do_dump
+  *
+  *	Call the dump() function if the kernel is configured for LKCD.
+  * Inputs:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.  dump() may or may not return.
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ static void
+ kdb_do_dump(struct pt_regs *regs)
+ {
+ #if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
+ 	kdb_printf("Forcing dump (if configured)\n");
+ 	console_loglevel = 8;	/* to see the dump messages */
+ 	dump("kdb_do_dump", regs);
+ #endif
+ }
+ 
+ /*
+  * kdb_reboot
+  *
+  *	This function implements the 'reboot' command.  Reboot the system
+  *	immediately.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	Shouldn't return from this function.
+  */
+ 
+ int
+ kdb_reboot(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	machine_restart(0);
+ 	kdb_printf("Hmm, kdb_reboot did not reboot, spinning here\n");
+ 	while (1) {};
+ 	/* NOTREACHED */
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_local
+  *
+  *	The main code for kdb.  This routine is invoked on a specific
+  *	processor, it is not global.  The main kdb() routine ensures
+  *	that only one processor at a time is in this routine.  This
+  *	code is called with the real reason code on the first entry
+  *	to a kdb session, thereafter it is called with reason SWITCH,
+  *	even if the user goes back to the original cpu.
+  *
+  * Inputs:
+  *	reason		The reason KDB was invoked
+  *	error		The hardware-defined error code
+  *	regs		The exception frame at time of fault/breakpoint.  NULL
+  *			for reason SILENT, otherwise valid.
+  *	db_result	Result code from the break or debug point.
+  * Returns:
+  *	0	KDB was invoked for an event which it wasn't responsible
+  *	1	KDB handled the event for which it was invoked.
+  *	KDB_CMD_GO	User typed 'go'.
+  *	KDB_CMD_CPU	User switched to another cpu.
+  *	KDB_CMD_SS	Single step.
+  *	KDB_CMD_SSB	Single step until branch.
+  * Locking:
+  *	none
+  * Remarks:
+  *	none
+  */
+ 
+ extern char kdb_prompt_str[];
+ 
+ static int
+ kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, kdb_dbtrap_t db_result)
+ {
+ 	char		*cmdbuf;
+ 	int		diag;
+ 
+ 	kdb_go_count = 0;
+ 	if (reason != KDB_REASON_DEBUG &&
+ 	    reason != KDB_REASON_SILENT) {
+ 		kdb_printf("\nEntering kdb (current=0x%p, pid %d) ", (void *)current, current->pid);
+ #if defined(CONFIG_SMP)
+ 		kdb_printf("on processor %d ", smp_processor_id());
+ #endif
+ 	}
+ 
+ 	switch (reason) {
+ 	case KDB_REASON_DEBUG:
+ 	{
+ 		/*
+ 		 * If re-entering kdb after a single step
+ 		 * command, don't print the message.
+ 		 */
+ 		switch(db_result) {
+ 		case KDB_DB_BPT:
+ 			kdb_printf("\nEntering kdb (0x%p) ", (void *)current);
+ #if defined(CONFIG_SMP)
+ 			kdb_printf("on processor %d ", smp_processor_id());
+ #endif
+ 			kdb_printf("due to Debug @ " kdb_machreg_fmt "\n", kdba_getpc(regs));
+ 			break;
+ 		case KDB_DB_SSB:
+ 			/*
+ 			 * In the midst of ssb command. Just return.
+ 			 */
+ 			return KDB_CMD_SSB;	/* Continue with SSB command */
+ 
+ 			break;
+ 		case KDB_DB_SS:
+ 			break;
+ 		case KDB_DB_SSBPT:
+ 			return 1;	/* kdba_db_trap did the work */
+ 		default:
+ 			kdb_printf("kdb: Bad result from kdba_db_trap: %d\n",
+ 				   db_result);
+ 			break;
+ 		}
+ 
+ 	}
+ 		break;
+ 	case KDB_REASON_FAULT:
+ 		break;
+ 	case KDB_REASON_ENTER:
+ 		kdb_printf("due to KDB_ENTER()\n");
+ 		break;
+ 	case KDB_REASON_KEYBOARD:
+ 		kdb_printf("due to Keyboard Entry\n");
+ 		break;
+ 	case KDB_REASON_SWITCH:
+ 		kdb_printf("due to cpu switch\n");
+ 		if (KDB_STATE(GO_SWITCH)) {
+ 			KDB_STATE_CLEAR(GO_SWITCH);
+ 			return KDB_CMD_GO;
+ 		}
+ 		break;
+ 	case KDB_REASON_CALL:
+ 		if (!regs)
+ 			kdb_printf("kdb() called with no registers, restricted function");
+ 		kdb_printf("\n");
+ 		break;
+ 	case KDB_REASON_OOPS:
+ 		kdb_printf("Oops: %s\n", kdb_diemsg);
+ 		kdb_printf("due to oops @ " kdb_machreg_fmt "\n", kdba_getpc(regs));
+ 		kdba_dumpregs(regs, NULL, NULL);
+ 		break;
+ 	case KDB_REASON_NMI:
+ 		kdb_printf("due to NonMaskable Interrupt @ " kdb_machreg_fmt "\n",
+ 			  kdba_getpc(regs));
+ 		kdba_dumpregs(regs, NULL, NULL);
+ 		break;
+ 	case KDB_REASON_WATCHDOG:
+ 		kdb_printf("due to WatchDog Interrupt @ " kdb_machreg_fmt "\n",
+ 			  kdba_getpc(regs));
+ 		kdba_dumpregs(regs, NULL, NULL);
+ 		break;
+ 	case KDB_REASON_BREAK:
+ 		kdb_printf("due to Breakpoint @ " kdb_machreg_fmt "\n", kdba_getpc(regs));
+ 		/*
+ 		 * Determine if this breakpoint is one that we
+ 		 * are interested in.
+ 		 */
+ 		if (db_result != KDB_DB_BPT) {
+ 			kdb_printf("kdb: error return from kdba_bp_trap: %d\n", db_result);
+ 			return 0;	/* Not for us, dismiss it */
+ 		}
+ 		break;
+ 	case KDB_REASON_RECURSE:
+ 		kdb_printf("due to Recursion @ " kdb_machreg_fmt "\n", kdba_getpc(regs));
+ 		break;
+ 	case KDB_REASON_SILENT:
+ 		return KDB_CMD_GO;	/* Silent entry, silent exit */
+ 		break;
+ 	default:
+ 		kdb_printf("kdb: unexpected reason code: %d\n", reason);
+ 		return 0;	/* Not for us, dismiss it */
+ 	}
+ 
+ 	kdba_local_arch_setup();
+ 
+ 	kdb_current_task = current;
+ 
+ 	while (1) {
+ 		/*
+ 		 * Initialize pager context.
+ 		 */
+ 		kdb_nextline = 1;
+ 		KDB_STATE_CLEAR(SUPPRESS);
+ #ifdef KDB_HAVE_LONGJMP
+ 		/*
+ 		 * Use kdba_setjmp/kdba_longjmp to break out of
+ 		 * the pager early and to attempt to recover from kdb errors.
+ 		 */
+ 		KDB_STATE_CLEAR(LONGJMP);
+ 		if (kdba_setjmp(&kdbjmpbuf[smp_processor_id()])) {
+ 			/* Command aborted (usually in pager) */
+ 			continue;
+ 		}
+ 		else
+ 			KDB_STATE_SET(LONGJMP);
+ #endif	/* KDB_HAVE_LONGJMP */
+ 
+ 		cmdbuf = cmd_cur;
+ 		*cmdbuf = '\0';
+ 		*(cmd_hist[cmd_head])='\0';
+ 
+ 		if (KDB_FLAG(ONLY_DO_DUMP)) {
+ 			/* kdb is off but a catastrophic error requires a dump.
+ 			 * Take the dump and reboot.
+ 			 * Turn on logging so the kdb output appears in the log
+ 			 * buffer in the dump.
+ 			 */
+ 			const char *setargs[] = { "set", "LOGGING", "1" };
+ 			kdb_set(2, setargs, NULL, regs);
+ 			kdb_do_dump(regs);
+ 			kdb_reboot(0, NULL, NULL, regs);
+ 			/*NOTREACHED*/
+ 		}
+ 
+ do_full_getstr:
+ #if defined(CONFIG_SMP)
+ 		snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), smp_processor_id());
+ #else
+ 		snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"));
+ #endif
+ 		if (defcmd_in_progress)
+ 			strncat(kdb_prompt_str, "[defcmd]", CMD_BUFLEN);
+ 
+ 		/*
+ 		 * Fetch command from keyboard
+ 		 */
+ 		cmdbuf = kdb_getstr(cmdbuf, CMD_BUFLEN, kdb_prompt_str);
+ 		if (*cmdbuf != '\n') {
+ 			if (*cmdbuf < 32) {
+ 				if(cmdptr == cmd_head) {
+ 					strncpy(cmd_hist[cmd_head], cmd_cur, CMD_BUFLEN);
+ 					*(cmd_hist[cmd_head]+strlen(cmd_hist[cmd_head])-1) = '\0';
+ 				}
+ 				if(!handle_ctrl_cmd(cmdbuf))
+ 					*(cmd_cur+strlen(cmd_cur)-1) = '\0';
+ 				cmdbuf = cmd_cur;
+ 				goto do_full_getstr;
+ 			}
+ 			else
+ 				strncpy(cmd_hist[cmd_head], cmd_cur, CMD_BUFLEN);
+ 
+ 			cmd_head = (cmd_head+1) % KDB_CMD_HISTORY_COUNT;
+ 			if (cmd_head == cmd_tail) cmd_tail = (cmd_tail+1) % KDB_CMD_HISTORY_COUNT;
+ 
+ 		}
+ 
+ 		cmdptr = cmd_head;
+ 		diag = kdb_parse(cmdbuf, regs);
+ 		if (diag == KDB_NOTFOUND) {
+ 			kdb_printf("Unknown kdb command: '%s'\n", cmdbuf);
+ 			diag = 0;
+ 		}
+ 		if (diag == KDB_CMD_GO
+ 		 || diag == KDB_CMD_CPU
+ 		 || diag == KDB_CMD_SS
+ 		 || diag == KDB_CMD_SSB)
+ 			break;
+ 
+ 		if (diag)
+ 			kdb_cmderror(diag);
+ 	}
+ 
+ 	kdba_local_arch_cleanup();
+ 
+ 	return(diag);
+ }
+ 
+ 
+ /*
+  * kdb_print_state
+  *
+  *	Print the state data for the current processor for debugging.
+  *
+  * Inputs:
+  *	text		Identifies the debug point
+  *	value		Any integer value to be printed, e.g. reason code.
+  * Returns:
+  *	None.
+  * Locking:
+  *	none
+  * Remarks:
+  *	none
+  */
+ 
+ void kdb_print_state(const char *text, int value)
+ {
+ 	kdb_printf("state: %s cpu %d value %d initial %d state %x\n",
+ 		text, smp_processor_id(), value, kdb_initial_cpu, kdb_state[smp_processor_id()]);
+ }
+ 
+ /*
+  * kdb_previous_event
+  *
+  *	Return a count of cpus that are leaving kdb, i.e. the number
+  *	of processors that are still handling the previous kdb event.
+  *
+  * Inputs:
+  *	None.
+  * Returns:
+  *	Count of cpus in previous event.
+  * Locking:
+  *	none
+  * Remarks:
+  *	none
+  */
+ 
+ static int
+ kdb_previous_event(void)
+ {
+ 	int i, leaving = 0;
+ 	for (i = 0; i < NR_CPUS; ++i) {
+ 		if (KDB_STATE_CPU(LEAVING, i))
+ 			++leaving;
+ 	}
+ 	return(leaving);
+ }
+ 
+ /*
+  * kdb_wait_for_cpus
+  *
+  * Invoked once at the start of a kdb event, from the controlling cpu.  Wait a
+  * short period for the other cpus to enter kdb state.
+  *
+  * Inputs:
+  *	none
+  * Returns:
+  *	none
+  * Locking:
+  *	none
+  * Remarks:
+  *	none
+  */
+ 
+ int kdb_wait_for_cpus_secs = 10;		/* may be modified by ia64 MCA timeout */
+ 
+ static void
+ kdb_wait_for_cpus(void)
+ {
+ #ifdef	CONFIG_SMP
+ 	int online = 0, kdb_data = 0, prev_kdb_data = 0, i, time;
+ 	mdelay(100);
+ 	for (time = 0; time < kdb_wait_for_cpus_secs; ++time) {
+ 		online = 0;
+ 		kdb_data = 0;
+ 		for (i = 0; i < NR_CPUS; ++i) {
+ 			if (cpu_online(i)) {
+ 				++online;
+ 				if (kdb_running_process[i].seqno >= kdb_seqno - 1)
+ 					++kdb_data;
+ 			}
+ 		}
+ 		if (online == kdb_data)
+ 			break;
+ 		if (prev_kdb_data != kdb_data) {
+ 			kdb_nextline = 0;	/* no prompt yet */
+ 			kdb_printf("%d out of %d cpus in kdb, waiting for the rest\n",
+ 				kdb_data, online);
+ 			prev_kdb_data = kdb_data;
+ 		}
+ 		touch_nmi_watchdog();
+ 		mdelay(1000);
+ 	}
+ 	if (time) {
+ 		int wait = online - kdb_data;
+ 		if (wait == 0)
+ 			kdb_printf("All cpus are now in kdb\n");
+ 		else
+ 			kdb_printf("%d cpu%s not in kdb, %s state is unknown\n",
+ 					wait,
+ 					wait == 1 ? " is" : "s are",
+ 					wait == 1 ? "its" : "their");
+ 	}
+ #endif	/* CONFIG_SMP */
+ }
+ 
+ /*
+  * kdb_main_loop
+  *
+  * The main kdb loop.  After initial setup and assignment of the controlling
+  * cpu, all cpus are in this loop.  One cpu is in control and will issue the kdb
+  * prompt, the others will spin until 'go' or cpu switch.
+  *
+  * To get a consistent view of the kernel stacks for all processes, this routine
+  * is invoked from the main kdb code via an architecture specific routine.
+  * kdba_main_loop is responsible for making the kernel stacks consistent for all
+  * processes, there should be no difference between a blocked process and a
+  * running process as far as kdb is concerned.
+  *
+  * Inputs:
+  *	reason		The reason KDB was invoked
+  *	error		The hardware-defined error code
+  *	reason2		kdb's current reason code.  Initially error but can change
+  *			acording to kdb state.
+  *	db_result	Result code from break or debug point.
+  *	regs		The exception frame at time of fault/breakpoint.  If reason
+  *			is KDB_REASON_SILENT then regs is NULL, otherwise it
+  *			should always be valid.
+  * Returns:
+  *	0	KDB was invoked for an event which it wasn't responsible
+  *	1	KDB handled the event for which it was invoked.
+  * Locking:
+  *	none
+  * Remarks:
+  *	none
+  */
+ 
+ int
+ kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
+ 	      kdb_dbtrap_t db_result, struct pt_regs *regs)
+ {
+ 	int result = 1;
+ 	int wait_for_cpus = reason != KDB_REASON_SILENT;
+ 	/* Stay in kdb() until 'go', 'ss[b]' or an error */
+ 	while (1) {
+ 		/*
+ 		 * All processors except the one that is in control
+ 		 * will spin here.
+ 		 */
+ 		KDB_DEBUG_STATE("kdb_main_loop 1", reason);
+ 		while (KDB_STATE(HOLD_CPU)) {
+ 			/* state KDB is turned off by kdb_cpu to see if the
+ 			 * other cpus are still live, each cpu in this loop
+ 			 * turns it back on.
+ 			 */
+ 			if (!KDB_STATE(KDB)) {
+ 				KDB_STATE_SET(KDB);
+ 			}
+ 		}
+ 		KDB_STATE_CLEAR(SUPPRESS);
+ 		KDB_DEBUG_STATE("kdb_main_loop 2", reason);
+ 		if (KDB_STATE(LEAVING))
+ 			break;	/* Another cpu said 'go' */
+ 
+ 		if (wait_for_cpus) {
+ 			wait_for_cpus = 0;
+ 			kdb_wait_for_cpus();
+ 		}
+ 		/* Still using kdb, this processor is in control */
+ 		result = kdb_local(reason2, error, regs, db_result);
+ 		KDB_DEBUG_STATE("kdb_main_loop 3", result);
+ 
+ 		if (result == KDB_CMD_CPU) {
+ 			/* Cpu switch, hold the current cpu, release the target one. */
+ 			reason2 = KDB_REASON_SWITCH;
+ 			KDB_STATE_SET(HOLD_CPU);
+ 			KDB_STATE_CLEAR_CPU(HOLD_CPU, kdb_new_cpu);
+ 			continue;
+ 		}
+ 
+ 		if (result == KDB_CMD_SS) {
+ 			KDB_STATE_SET(DOING_SS);
+ 			break;
+ 		}
+ 
+ 		if (result == KDB_CMD_SSB) {
+ 			KDB_STATE_SET(DOING_SS);
+ 			KDB_STATE_SET(DOING_SSB);
+ 			break;
+ 		}
+ 
+ 		if (result && result != 1 && result != KDB_CMD_GO)
+ 			kdb_printf("\nUnexpected kdb_local return code %d\n", result);
+ 
+ 		KDB_DEBUG_STATE("kdb_main_loop 4", reason);
+ 		break;
+ 	}
+ 	if (KDB_STATE(DOING_SS))
+ 		KDB_STATE_CLEAR(SSBPT);
+ 	return(result);
+ }
+ 
+ /*
+  * kdb
+  *
+  *	This function is the entry point for the kernel debugger.  It
+  *	provides a command parser and associated support functions to
+  *	allow examination and control of an active kernel.
+  *
+  * 	This function may be invoked directly from any
+  *	point in the kernel by calling with reason == KDB_REASON_CALL
+  *
+  *	The breakpoint trap code should invoke this function with
+  *	one of KDB_REASON_BREAK (int 03) or KDB_REASON_DEBUG (debug register)
+  *
+  *	the die_if_kernel function should invoke this function with
+  *	KDB_REASON_OOPS.
+  *
+  *	The kernel fault handler should invoke this function with
+  *	reason == KDB_REASON_FAULT and error == trap vector #.
+  *
+  *	In single step mode, one cpu is released to run without
+  *	breakpoints.   Interrupts and NMI are reset to their original values,
+  *	the cpu is allowed to do one instruction which causes a trap
+  *	into kdb with KDB_REASON_DEBUG.
+  *
+  * Inputs:
+  *	reason		The reason KDB was invoked
+  *	error		The hardware-defined error code
+  *	regs		The exception frame at time of fault/breakpoint.  If reason
+  *			is KDB_REASON_SILENT then regs is NULL, otherwise it
+  *			should always be valid.
+  * Returns:
+  *	0	KDB was invoked for an event which it wasn't responsible
+  *	1	KDB handled the event for which it was invoked.
+  * Locking:
+  *	none
+  * Remarks:
+  *	No assumptions of system state.  This function may be invoked
+  *	with arbitrary locks held.  It will stop all other processors
+  *	in an SMP environment, disable all interrupts and does not use
+  *	the operating systems keyboard driver.
+  *
+  *	This code is reentrant but only for cpu switch.  Any other
+  *	reentrancy is an error, although kdb will attempt to recover.
+  *
+  *	At the start of a kdb session the initial processor is running
+  *	kdb() and the other processors can be doing anything.  When the
+  *	initial processor calls smp_kdb_stop() the other processors are
+  *	driven through kdb_ipi which calls kdb() with reason SWITCH.
+  *	That brings all processors into this routine, one with a "real"
+  *	reason code, the other with SWITCH.
+  *
+  *	Because the other processors are driven via smp_kdb_stop(),
+  *	they enter here from the NMI handler.  Until the other
+  *	processors exit from here and exit from kdb_ipi, they will not
+  *	take any more NMI requests.  The initial cpu will still take NMI.
+  *
+  *	Multiple race and reentrancy conditions, each with different
+  *	advoidance mechanisms.
+  *
+  *	Two cpus hit debug points at the same time.
+  *
+  *	  kdb_lock and kdb_initial_cpu ensure that only one cpu gets
+  *	  control of kdb.  The others spin on kdb_initial_cpu until
+  *	  they are driven through NMI into kdb_ipi.  When the initial
+  *	  cpu releases the others from NMI, they resume trying to get
+  *	  kdb_initial_cpu to start a new event.
+  *
+  *	A cpu is released from kdb and starts a new event before the
+  *	original event has completely ended.
+  *
+  *	  kdb_previous_event() prevents any cpu from entering
+  *	  kdb_initial_cpu state until the previous event has completely
+  *	  ended on all cpus.
+  *
+  *	An exception occurs inside kdb.
+  *
+  *	  kdb_initial_cpu detects recursive entry to kdb and attempts
+  *	  to recover.  The recovery uses longjmp() which means that
+  *	  recursive calls to kdb never return.  Beware of assumptions
+  *	  like
+  *
+  *	    ++depth;
+  *	    kdb();
+  *	    --depth;
+  *
+  *	  If the kdb call is recursive then longjmp takes over and
+  *	  --depth is never executed.
+  *
+  *	NMI handling.
+  *
+  *	  NMI handling is tricky.  The initial cpu is invoked by some kdb event,
+  *	  this event could be NMI driven but usually is not.  The other cpus are
+  *	  driven into kdb() via kdb_ipi which uses NMI so at the start the other
+  *	  cpus will not accept NMI.  Some operations such as SS release one cpu
+  *	  but hold all the others.  Releasing a cpu means it drops back to
+  *	  whatever it was doing before the kdb event, this means it drops out of
+  *	  kdb_ipi and hence out of NMI status.  But the software watchdog uses
+  *	  NMI and we do not want spurious watchdog calls into kdb.  kdba_read()
+  *	  resets the watchdog counters in its input polling loop, when a kdb
+  *	  command is running it is subject to NMI watchdog events.
+  *
+  *	  Another problem with NMI handling is the NMI used to drive the other
+  *	  cpus into kdb cannot be distinguished from the watchdog NMI.  State
+  *	  flag WAIT_IPI indicates that a cpu is waiting for NMI via kdb_ipi,
+  *	  if not set then software NMI is ignored by kdb_ipi.
+  *
+  *	Cpu switching.
+  *
+  *	  All cpus are in kdb (or they should be), all but one are
+  *	  spinning on KDB_STATE(HOLD_CPU).  Only one cpu is not in
+  *	  HOLD_CPU state, only that cpu can handle commands.
+  *
+  *	Go command entered.
+  *
+  *	  If necessary, go will switch to the initial cpu first.  If the event
+  *	  was caused by a software breakpoint (assumed to be global) that
+  *	  requires single-step to get over the breakpoint then only release the
+  *	  initial cpu, after the initial cpu has single-stepped the breakpoint
+  *	  then release the rest of the cpus.  If SSBPT is not required then
+  *	  release all the cpus at once.
+  */
+ 
+ int
+ kdb(kdb_reason_t reason, int error, struct pt_regs *regs)
+ {
+ 	kdb_intstate_t	int_state;	/* Interrupt state */
+ 	kdb_reason_t	reason2 = reason;
+ 	int		result = 1;	/* Default is kdb handled it */
+ 	int		ss_event;
+ 	kdb_dbtrap_t 	db_result=KDB_DB_NOBPT;
+ 
+ 	switch(reason) {
+ 	case KDB_REASON_OOPS:
+ 	case KDB_REASON_NMI:
+ 	case KDB_REASON_WATCHDOG:
+ 		KDB_FLAG_SET(CATASTROPHIC);	/* kernel state is dubious now */
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ 	if (kdb_continue_catastrophic > 2) {
+ 		kdb_printf("kdb_continue_catastrophic is out of range, setting to 2\n");
+ 		kdb_continue_catastrophic = 2;
+ 	}
+ 	if (!kdb_on && KDB_FLAG(CATASTROPHIC) && kdb_continue_catastrophic == 2) {
+ 		KDB_FLAG_SET(ONLY_DO_DUMP);
+ 	}
+ 	if (!kdb_on && !KDB_FLAG(ONLY_DO_DUMP))
+ 		return 0;
+ 
+ 	KDB_DEBUG_STATE("kdb 1", reason);
+ 	KDB_STATE_CLEAR(SUPPRESS);
+ 
+ 	/* Filter out userspace breakpoints first, no point in doing all
+ 	 * the kdb smp fiddling when it is really a gdb trap.
+ 	 * Save the single step status first, kdba_db_trap clears ss status.
+ 	 * kdba_b[dp]_trap sets SSBPT if required.
+ 	 */
+ 	ss_event = KDB_STATE(DOING_SS) || KDB_STATE(SSBPT);
+ #ifdef  CONFIG_CPU_XSCALE
+ 	if ( KDB_STATE(A_XSC_ICH) ) {
+ 		/* restore changed I_BIT */
+ 		KDB_STATE_CLEAR(A_XSC_ICH);
+ 		kdba_restore_retirq(regs, KDB_STATE(A_XSC_IRQ));
+ 		if ( !ss_event ) {
+ 			kdb_printf("Stranger!!! Why IRQ bit is changed====\n");
+ 		}
+ 	}
+ #endif
+ 	if (reason == KDB_REASON_BREAK) {
+ 		db_result = kdba_bp_trap(regs, error);	/* Only call this once */
+ 	}
+ 	if (reason == KDB_REASON_DEBUG) {
+ 		db_result = kdba_db_trap(regs, error);	/* Only call this once */
+ 	}
+ 
+ 	if ((reason == KDB_REASON_BREAK || reason == KDB_REASON_DEBUG)
+ 	 && db_result == KDB_DB_NOBPT) {
+ 		KDB_DEBUG_STATE("kdb 2", reason);
+ 		return 0;	/* Not one of mine */
+ 	}
+ 
+ 	/* Turn off single step if it was being used */
+ 	if (ss_event) {
+ 		kdba_clearsinglestep(regs);
+ 		/* Single step after a breakpoint removes the need for a delayed reinstall */
+ 		if (reason == KDB_REASON_BREAK || reason == KDB_REASON_DEBUG)
+ 			KDB_STATE_CLEAR(SSBPT);
+ 	}
+ 
+ 	/* kdb can validly reenter but only for certain well defined conditions */
+ 	if (reason == KDB_REASON_DEBUG
+ 	 && !KDB_STATE(HOLD_CPU)
+ 	 && ss_event)
+ 		KDB_STATE_SET(REENTRY);
+ 	else
+ 		KDB_STATE_CLEAR(REENTRY);
+ 
+ 	/* Wait for previous kdb event to completely exit before starting
+ 	 * a new event.
+ 	 */
+ 	while (kdb_previous_event())
+ 		;
+ 	KDB_DEBUG_STATE("kdb 3", reason);
+ 
+ 	/*
+ 	 * If kdb is already active, print a message and try to recover.
+ 	 * If recovery is not possible and recursion is allowed or
+ 	 * forced recursion without recovery is set then try to recurse
+ 	 * in kdb.  Not guaranteed to work but it makes an attempt at
+ 	 * debugging the debugger.
+ 	 */
+ 	if (reason != KDB_REASON_SWITCH) {
+ 		if (KDB_IS_RUNNING() && !KDB_STATE(REENTRY)) {
+ 			int recover = 1;
+ 			unsigned long recurse = 0;
+ 			kdb_printf("kdb: Debugger re-entered on cpu %d, new reason = %d\n",
+ 				smp_processor_id(), reason);
+ 			/* Should only re-enter from released cpu */
+ 
+ 			if (KDB_STATE(HOLD_CPU)) {
+ 				kdb_printf("     Strange, cpu %d should not be running\n", smp_processor_id());
+ 				recover = 0;
+ 			}
+ 			if (!KDB_STATE(CMD)) {
+ 				kdb_printf("     Not executing a kdb command\n");
+ 				recover = 0;
+ 			}
+ 			if (!KDB_STATE(LONGJMP)) {
+ 				kdb_printf("     No longjmp available for recovery\n");
+ 				recover = 0;
+ 			}
+ 			kdbgetulenv("RECURSE", &recurse);
+ 			if (recurse > 1) {
+ 				kdb_printf("     Forced recursion is set\n");
+ 				recover = 0;
+ 			}
+ 			if (recover) {
+ 				kdb_printf("     Attempting to abort command and recover\n");
+ #ifdef KDB_HAVE_LONGJMP
+ 				kdba_longjmp(&kdbjmpbuf[smp_processor_id()], 0);
+ #endif
+ 			}
+ 			if (recurse) {
+ 				if (KDB_STATE(RECURSE)) {
+ 					kdb_printf("     Already in recursive mode\n");
+ 				} else {
+ 					kdb_printf("     Attempting recursive mode\n");
+ 					KDB_STATE_SET(RECURSE);
+ 					KDB_STATE_SET(REENTRY);
+ 					reason2 = KDB_REASON_RECURSE;
+ 					recover = 1;
+ 				}
+ 			}
+ 			if (!recover) {
+ 				kdb_printf("     Cannot recover, allowing event to proceed\n");
+ 				return(0);
+ 			}
+ 		}
+ 	} else if (!KDB_IS_RUNNING()) {
+ 		kdb_printf("kdb: CPU switch without kdb running, I'm confused\n");
+ 		return(0);
+ 	}
+ 
+ 	/*
+ 	 * Disable interrupts, breakpoints etc. on this processor
+ 	 * during kdb command processing
+ 	 */
+ 	KDB_STATE_SET(KDB);
+ 	if (!ss_event) {
+ 		/* bh not re-enabled during single step */
+ 		local_bh_disable();
+ 	}
+ 	kdba_disableint(&int_state);
+ 	if (!KDB_STATE(KDB_CONTROL)) {
+ 		kdb_bp_remove_local();
+ 		kdba_disable_lbr();
+ 		KDB_STATE_SET(KDB_CONTROL);
+ 	}
+ 	else if (KDB_DEBUG(LBR))
+ 		kdba_print_lbr();
+ 
+ 	/*
+ 	 * If not entering the debugger due to CPU switch or single step
+ 	 * reentry, serialize access here.
+ 	 * The processors may race getting to this point - if,
+ 	 * for example, more than one processor hits a breakpoint
+ 	 * at the same time.   We'll serialize access to kdb here -
+ 	 * other processors will loop here, and the NMI from the stop
+ 	 * IPI will take them into kdb as switch candidates.  Once
+ 	 * the initial processor releases the debugger, the rest of
+ 	 * the processors will race for it.
+ 	 */
+ 	if (reason == KDB_REASON_SWITCH
+ 	 || KDB_STATE(REENTRY))
+ 		;	/* drop through */
+ 	else {
+ 		KDB_DEBUG_STATE("kdb 4", reason);
+ 		spin_lock(&kdb_lock);
+ 
+ 		while (KDB_IS_RUNNING() || kdb_previous_event()) {
+ 			spin_unlock(&kdb_lock);
+ 
+ 			while (KDB_IS_RUNNING() || kdb_previous_event())
+ 				;
+ 
+ 			spin_lock(&kdb_lock);
+ 		}
+ 		KDB_DEBUG_STATE("kdb 5", reason);
+ 
+ 		kdb_initial_cpu = smp_processor_id();
+ 		++kdb_seqno;
+ 		spin_unlock(&kdb_lock);
+ 		notifier_call_chain(&kdb_notifier_list, 1, NULL);
+ 	}
+ 
+ 	if (smp_processor_id() == kdb_initial_cpu
+ 	 && !KDB_STATE(REENTRY)) {
+ 		KDB_STATE_CLEAR(HOLD_CPU);
+ 		KDB_STATE_CLEAR(WAIT_IPI);
+ 		/*
+ 		 * Remove the global breakpoints.  This is only done
+ 		 * once from the initial processor on initial entry.
+ 		 */
+ 		kdb_bp_remove_global();
+ 
+ 		/*
+ 		 * If SMP, stop other processors.  The other processors
+ 		 * will enter kdb() with KDB_REASON_SWITCH and spin in
+ 		 * kdb_main_loop().
+ 		 */
+ 		KDB_DEBUG_STATE("kdb 6", reason);
+ 		if (smp_num_cpus > 1) {
+ 			int i;
+ 			for (i = 0; i < NR_CPUS; ++i) {
+ 				if (!cpu_online(i))
+ 					continue;
+ 				if (i != kdb_initial_cpu) {
+ 					KDB_STATE_SET_CPU(HOLD_CPU, i);
+ 					KDB_STATE_SET_CPU(WAIT_IPI, i);
+ 				}
+ 			}
+ 			KDB_DEBUG_STATE("kdb 7", reason);
+ 			smp_kdb_stop();
+ 			KDB_DEBUG_STATE("kdb 8", reason);
+ 		}
+ 	}
+ 
+ 	if (KDB_STATE(GO1)) {
+ 		kdb_bp_remove_global();		/* They were set for single-step purposes */
+ 		KDB_STATE_CLEAR(GO1);
+ 		reason = KDB_REASON_SILENT;	/* Now silently go */
+ 	}
+ 
+ 	/* Set up a consistent set of process stacks before talking to the user */
+ 	KDB_DEBUG_STATE("kdb 9", result);
+ 	result = kdba_main_loop(reason, reason2, error, db_result, regs);
+ 
+ 	KDB_DEBUG_STATE("kdb 10", result);
+ 	kdba_adjust_ip(reason, error, regs);
+ 	KDB_STATE_CLEAR(LONGJMP);
+ 	KDB_DEBUG_STATE("kdb 11", result);
+ 	/* go which requires single-step over a breakpoint must only release
+ 	 * one cpu.
+ 	 */
+ 	if (result == KDB_CMD_GO && KDB_STATE(SSBPT))
+ 		KDB_STATE_SET(GO1);
+ 
+ 	if (smp_processor_id() == kdb_initial_cpu &&
+ 	  !KDB_STATE(DOING_SS) &&
+ 	  !KDB_STATE(RECURSE)) {
+ 		/*
+ 		 * (Re)install the global breakpoints.  This is only done
+ 		 * once from the initial processor on go.
+ 		 */
+ 		KDB_DEBUG_STATE("kdb 12", reason);
+ 		kdb_bp_install_global(regs);
+ 		if (!KDB_STATE(GO1)) {
+ 			/*
+ 			 * Release all other cpus which will see KDB_STATE(LEAVING) is set.
+ 			 */
+ 			int i;
+ 			for (i = 0; i < NR_CPUS; ++i) {
+ 				if (KDB_STATE_CPU(KDB, i))
+ 					KDB_STATE_SET_CPU(LEAVING, i);
+ 				KDB_STATE_CLEAR_CPU(WAIT_IPI, i);
+ 				KDB_STATE_CLEAR_CPU(HOLD_CPU, i);
+ 			}
+ 			/* Wait until all the other processors leave kdb */
+ 			while (kdb_previous_event() != 1)
+ 				;
+ 			notifier_call_chain(&kdb_notifier_list, 0, NULL);
+ 			kdb_initial_cpu = -1;	/* release kdb control */
+ 			KDB_DEBUG_STATE("kdb 13", reason);
+ 		}
+ 	}
+ 
+ 	KDB_DEBUG_STATE("kdb 14", result);
+ 	kdba_restoreint(&int_state);
+ #ifdef  CONFIG_CPU_XSCALE
+ 	if ( smp_processor_id() == kdb_initial_cpu &&
+ 	     ( KDB_STATE(SSBPT) | KDB_STATE(DOING_SS) )
+ 	      ) {
+ 		kdba_setsinglestep(regs);
+ 		// disable IRQ in stack frame
+ 		KDB_STATE_SET(A_XSC_ICH);
+ 		if ( kdba_disable_retirq(regs) ) {
+ 			KDB_STATE_SET(A_XSC_IRQ);
+ 		}
+ 		else {
+ 			KDB_STATE_CLEAR(A_XSC_IRQ);
+ 		}
+ 	}
+ #endif
+ 
+ 	/* Only do this work if we are really leaving kdb */
+ 	if (!(KDB_STATE(DOING_SS) || KDB_STATE(SSBPT) || KDB_STATE(RECURSE))) {
+ 		KDB_DEBUG_STATE("kdb 15", result);
+ 		kdb_bp_install_local(regs);
+ 		kdba_enable_lbr();
+ 		local_bh_enable();
+ 		KDB_STATE_CLEAR(KDB_CONTROL);
+ 	}
+ 
+ 	KDB_DEBUG_STATE("kdb 16", result);
+ 	KDB_FLAG_CLEAR(CATASTROPHIC);
+ 	KDB_STATE_CLEAR(IP_ADJUSTED);	/* Re-adjust ip next time in */
+ 	KDB_STATE_CLEAR(KDB);		/* Main kdb state has been cleared */
+ 	KDB_STATE_CLEAR(RECURSE);
+ 	KDB_STATE_CLEAR(LEAVING);	/* No more kdb work after this */
+ 	KDB_DEBUG_STATE("kdb 17", reason);
+ 	return(result != 0);
+ }
+ 
+ /*
+  * kdb_mdr
+  *
+  *	This function implements the guts of the 'mdr' command.
+  *
+  *	mdr  <addr arg>,<byte count>
+  *
+  * Inputs:
+  *	addr	Start address
+  *	count	Number of bytes
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Always 0.  Any errors are detected and printed by kdb_getarea.
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ static int
+ kdb_mdr(kdb_machreg_t addr, unsigned int count)
+ {
+ 	unsigned char c;
+ 	while (count--) {
+ 		if (kdb_getarea(c, addr))
+ 			return(0);
+ 		kdb_printf("%02x", c);
+ 		addr++;
+ 	}
+ 	kdb_printf("\n");
+ 	return(0);
+ }
+ 
+ /*
+  * kdb_md
+  *
+  *	This function implements the 'md', 'md1', 'md2', 'md4', 'md8'
+  *	'mdr' and 'mds' commands.
+  *
+  *	md|mds  [<addr arg> [<line count> [<radix>]]]
+  *	mdWcN	[<addr arg> [<line count> [<radix>]]]
+  *		where W = is the width (1, 2, 4 or 8) and N is the count.
+  *		for eg., md1c20 reads 20 bytes, 1 at a time.
+  *	mdr  <addr arg>,<byte count>
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ int
+ kdb_md(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	static kdb_machreg_t last_addr;
+ 	static int last_radix, last_bytesperword, last_repeat;
+ 	int radix = 16, mdcount = 8, bytesperword = sizeof(kdb_machreg_t), repeat;
+ 	int nosect = 0;
+ 	char fmtchar, fmtstr[64];
+ 	kdb_machreg_t addr;
+ 	unsigned long word;
+ 	long offset = 0;
+ 	kdb_symtab_t symtab;
+ 	int symbolic = 0;
+ 	int valid = 0;
+ 
+ 	kdbgetintenv("MDCOUNT", &mdcount);
+ 	kdbgetintenv("RADIX", &radix);
+ 	kdbgetintenv("BYTESPERWORD", &bytesperword);
+ 
+ 	/* Assume 'md <addr>' and start with environment values */
+ 	repeat = mdcount * 16 / bytesperword;
+ 
+ 	if (strcmp(argv[0], "mdr") == 0) {
+ 		if (argc != 2)
+ 			return KDB_ARGCOUNT;
+ 		valid = 1;
+ 	} else if (isdigit(argv[0][2])) {
+ 		bytesperword = (int)(argv[0][2] - '0');
+ 		if (bytesperword == 0) {
+ 			bytesperword = last_bytesperword;
+ 			if (bytesperword == 0) {
+ 				bytesperword = 4;
+ 			}
+ 		}
+ 		last_bytesperword = bytesperword;
+ 		repeat = mdcount * 16 / bytesperword;
+ 		if (!argv[0][3])
+ 			valid = 1;
+ 		else if (argv[0][3] == 'c' && argv[0][4]) {
+ 			char *p;
+ 			repeat = simple_strtoul(argv[0]+4, &p, 10);
+ 			mdcount = ((repeat * bytesperword) + 15) / 16;
+ 			valid = !*p;
+ 		}
+ 		last_repeat = repeat;
+ 	} else if (strcmp(argv[0], "md") == 0)
+ 		valid = 1;
+ 	else if (strcmp(argv[0], "mds") == 0)
+ 		valid = 1;
+ 	if (!valid)
+ 		return KDB_NOTFOUND;
+ 
+ 	if (argc == 0) {
+ 		if (last_addr == 0)
+ 			return KDB_ARGCOUNT;
+ 		addr = last_addr;
+ 		radix = last_radix;
+ 		bytesperword = last_bytesperword;
+ 		repeat = last_repeat;
+ 		mdcount = ((repeat * bytesperword) + 15) / 16;
+ 	}
+ 
+ 	if (argc) {
+ 		kdb_machreg_t val;
+ 		int diag, nextarg = 1;
+ 		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+ 		if (diag)
+ 			return diag;
+ 		if (argc > nextarg+2)
+ 			return KDB_ARGCOUNT;
+ 
+ 		if (argc >= nextarg) {
+ 			diag = kdbgetularg(argv[nextarg], &val);
+ 			if (!diag) {
+ 				mdcount = (int) val;
+ 				repeat = mdcount * 16 / bytesperword;
+ 			}
+ 		}
+ 		if (argc >= nextarg+1) {
+ 			diag = kdbgetularg(argv[nextarg+1], &val);
+ 			if (!diag)
+ 				radix = (int) val;
+ 		}
+ 	}
+ 
+ 	if (strcmp(argv[0], "mdr") == 0) {
+ 		return(kdb_mdr(addr, mdcount));
+ 	}
+ 
+ 	switch (radix) {
+ 	case 10:
+ 		fmtchar = 'd';
+ 		break;
+ 	case 16:
+ 		fmtchar = 'x';
+ 		break;
+ 	case 8:
+ 		fmtchar = 'o';
+ 		break;
+ 	default:
+ 		return KDB_BADRADIX;
+ 	}
+ 
+ 	last_radix = radix;
+ 
+ 	if (bytesperword > sizeof(kdb_machreg_t))
+ 		return KDB_BADWIDTH;
+ 
+ 	switch (bytesperword) {
+ 	case 8:
+ 		sprintf(fmtstr, "%%16.16l%c ", fmtchar);
+ 		break;
+ 	case 4:
+ 		sprintf(fmtstr, "%%8.8l%c ", fmtchar);
+ 		break;
+ 	case 2:
+ 		sprintf(fmtstr, "%%4.4l%c ", fmtchar);
+ 		break;
+ 	case 1:
+ 		sprintf(fmtstr, "%%2.2l%c ", fmtchar);
+ 		break;
+ 	default:
+ 		return KDB_BADWIDTH;
+ 	}
+ 
+ 	last_repeat = repeat;
+ 	last_bytesperword = bytesperword;
+ 
+ 	if (strcmp(argv[0], "mds") == 0) {
+ 		symbolic = 1;
+ 		/* Do not save these changes as last_*, they are temporary mds
+ 		 * overrides.
+ 		 */
+ 		bytesperword = sizeof(kdb_machreg_t);
+ 		repeat = mdcount;
+ 		kdbgetintenv("NOSECT", &nosect);
+ 	}
+ 
+ 	/* Round address down modulo BYTESPERWORD */
+ 
+ 	addr &= ~(bytesperword-1);
+ 
+ 	while (repeat > 0) {
+ 		int	num = (symbolic?1 :(16 / bytesperword));
+ 		char	cbuf[32];
+ 		char	*c = cbuf;
+ 		int     i;
+ 
+ 		memset(cbuf, '\0', sizeof(cbuf));
+ 		kdb_printf(kdb_machreg_fmt0 " ", addr);
+ 
+ 		for(i = 0; i < num && repeat--; i++) {
+ 			if (kdb_getword(&word, addr, bytesperword))
+ 				return 0;
+ 
+ 			kdb_printf(fmtstr, word);
+ 			if (symbolic) {
+ 				kdbnearsym(word, &symtab);
+ 			}
+ 			else {
+ 				memset(&symtab, 0, sizeof(symtab));
+ 			}
+ 			if (symtab.sym_name) {
+ 				kdb_symbol_print(word, &symtab, 0);
+ 				if (!nosect) {
+ 					kdb_printf("\n");
+ 					kdb_printf("                       %s %s "
+ 						   kdb_machreg_fmt " " kdb_machreg_fmt " " kdb_machreg_fmt,
+ 						symtab.mod_name,
+ 						symtab.sec_name,
+ 						symtab.sec_start,
+ 						symtab.sym_start,
+ 						symtab.sym_end);
+ 				}
+ 				addr += bytesperword;
+ 			} else {
+ #define printable_char(addr) ({char __c = '\0'; unsigned long __addr = (addr); kdb_getarea(__c, __addr); isprint(__c) ? __c : '.';})
+ 				switch (bytesperword) {
+ 				case 8:
+ 					*c++ = printable_char(addr++);
+ 					*c++ = printable_char(addr++);
+ 					*c++ = printable_char(addr++);
+ 					*c++ = printable_char(addr++);
+ 				case 4:
+ 					*c++ = printable_char(addr++);
+ 					*c++ = printable_char(addr++);
+ 				case 2:
+ 					*c++ = printable_char(addr++);
+ 				case 1:
+ 					*c++ = printable_char(addr++);
+ 					break;
+ 				}
+ #undef printable_char
+ 			}
+ 		}
+ 		kdb_printf("%*s %s\n", (int)((num-i)*(2*bytesperword + 1)+1), " ", cbuf);
+ 	}
+ 	last_addr = addr;
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_mm
+  *
+  *	This function implements the 'mm' command.
+  *
+  *	mm address-expression new-value
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	mm works on machine words, mmW works on bytes.
+  */
+ 
+ int
+ kdb_mm(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int diag;
+ 	kdb_machreg_t addr;
+ 	long 	      offset = 0;
+ 	unsigned long contents;
+ 	int nextarg;
+ 	int width;
+ 
+ 	if (argv[0][2] && !isdigit(argv[0][2]))
+ 		return KDB_NOTFOUND;
+ 
+ 	if (argc < 2) {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+ 		return diag;
+ 
+ 	if (nextarg > argc)
+ 		return KDB_ARGCOUNT;
+ 
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &contents, NULL, NULL, regs)))
+ 		return diag;
+ 
+ 	if (nextarg != argc + 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	width = argv[0][2] ? (argv[0][2] - '0') : (sizeof(kdb_machreg_t));
+ 	if ((diag = kdb_putword(addr, contents, width)))
+ 		return(diag);
+ 
+ 	kdb_printf(kdb_machreg_fmt " = " kdb_machreg_fmt "\n", addr, contents);
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_go
+  *
+  *	This function implements the 'go' command.
+  *
+  *	go [address-expression]
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	KDB_CMD_GO for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ int
+ kdb_go(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	kdb_machreg_t addr;
+ 	int diag;
+ 	int nextarg;
+ 	long offset;
+ 
+ 	if (argc == 1) {
+ 		if (smp_processor_id() != kdb_initial_cpu) {
+ 			kdb_printf("go <address> must be issued from the initial cpu, do cpu %d first\n", kdb_initial_cpu);
+ 			return KDB_ARGCOUNT;
+ 		}
+ 		nextarg = 1;
+ 		diag = kdbgetaddrarg(argc, argv, &nextarg,
+ 				     &addr, &offset, NULL, regs);
+ 		if (diag)
+ 			return diag;
+ 
+ 		kdba_setpc(regs, addr);
+ 	} else if (argc)
+ 		return KDB_ARGCOUNT;
+ 
+ 	diag = KDB_CMD_GO;
+ 	if (KDB_FLAG(CATASTROPHIC)) {
+ 		kdb_printf("Catastrophic error detected\n");
+ 		kdb_printf("kdb_continue_catastrophic=%d, ",
+ 			kdb_continue_catastrophic);
+ 		if (kdb_continue_catastrophic == 0 && kdb_go_count++ == 0) {
+ 			kdb_printf("type go a second time if you really want to continue\n");
+ 			return 0;
+ 		}
+ 		if (kdb_continue_catastrophic == 2) {
+ 			kdb_do_dump(regs);
+ 			kdb_printf("forcing reboot\n");
+ 			kdb_reboot(0, NULL, NULL, regs);
+ 		}
+ 		kdb_printf("attempting to continue\n");
+ 	}
+ 	if (smp_processor_id() != kdb_initial_cpu) {
+ 		char buf[80];
+ 		kdb_printf("go was not issued from initial cpu, switching back to cpu %d\n", kdb_initial_cpu);
+ 		sprintf(buf, "cpu %d\n", kdb_initial_cpu);
+ 		/* Recursive use of kdb_parse, do not use argv after this point */
+ 		argv = NULL;
+ 		diag = kdb_parse(buf, regs);
+ 		if (diag == KDB_CMD_CPU)
+ 			KDB_STATE_SET_CPU(GO_SWITCH, kdb_initial_cpu);
+ 	}
+ 	return diag;
+ }
+ 
+ /*
+  * kdb_rd
+  *
+  *	This function implements the 'rd' command.
+  *
+  *	rd		display all general registers.
+  *	rd  c		display all control registers.
+  *	rd  d		display all debug registers.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ int
+ kdb_rd(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	/*
+ 	 */
+ 
+ 	if (argc == 0) {
+ 		return kdba_dumpregs(regs, NULL, NULL);
+ 	}
+ 
+ 	if (argc > 2) {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 
+ 	return kdba_dumpregs(regs, argv[1], argc==2 ? argv[2]: NULL);
+ }
+ 
+ /*
+  * kdb_rm
+  *
+  *	This function implements the 'rm' (register modify)  command.
+  *
+  *	rm register-name new-contents
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	Currently doesn't allow modification of control or
+  *	debug registers, nor does it allow modification
+  *	of model-specific registers (MSR).
+  */
+ 
+ int
+ kdb_rm(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int diag;
+ 	int ind = 0;
+ 	kdb_machreg_t contents;
+ 
+ 	if (argc != 2) {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 
+ 	/*
+ 	 * Allow presence or absence of leading '%' symbol.
+ 	 */
+ 
+ 	if (argv[1][0] == '%')
+ 		ind = 1;
+ 
+ 	diag = kdbgetularg(argv[2], &contents);
+ 	if (diag)
+ 		return diag;
+ 
+ 	diag = kdba_setregcontents(&argv[1][ind], regs, contents);
+ 	if (diag)
+ 		return diag;
+ 
+ 	return 0;
+ }
+ 
+ #if defined(CONFIG_MAGIC_SYSRQ)
+ /*
+  * kdb_sr
+  *
+  *	This function implements the 'sr' (SYSRQ key) command which
+  *	interfaces to the soi-disant MAGIC SYSRQ functionality.
+  *
+  *	sr <magic-sysrq-code>
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	None.
+  */
+ int
+ kdb_sr(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ #if 0
+ 	extern int sysrq_enabled;
+ 	if (argc != 1) {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 	if (!sysrq_enabled) {
+ 		kdb_printf("Auto activating sysrq\n");
+ 		sysrq_enabled = 1;
+ 	}
+ #else
+ 	struct sysrq_ctls_struct sysrq_ctls;
+ 	if (argc != 1) {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 	if (!sysrq_ctls.enabled) {
+ 		kdb_printf("Auto activating sysrq\n");
+ 		sysrq_ctls.enabled = 1;
+ 	}
+ #endif
+ 
+ 	handle_sysrq(*argv[1], regs, 0, 0);
+ 
+ 	return 0;
+ }
+ #endif	/* CONFIG_MAGIC_SYSRQ */
+ 
+ /*
+  * kdb_ef
+  *
+  *	This function implements the 'regs' (display exception frame)
+  *	command.  This command takes an address and expects to find
+  *	an exception frame at that address, formats and prints it.
+  *
+  *	regs address-expression
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	Not done yet.
+  */
+ 
+ int
+ kdb_ef(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int diag;
+ 	kdb_machreg_t   addr;
+ 	long		offset;
+ 	int nextarg;
+ 
+ 	if (argc == 1) {
+ 		nextarg = 1;
+ 		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+ 		if (diag)
+ 			return diag;
+ 
+ 		return kdba_dumpregs((struct pt_regs *)addr, NULL, NULL);
+ 	}
+ 
+ 	return KDB_ARGCOUNT;
+ }
+ 
+ #if defined(CONFIG_MODULES)
+ extern struct module *find_module(const char *);
+ extern void free_module(struct module *, int);
+ 
+ /*
+  * kdb_lsmod
+  *
+  *	This function implements the 'lsmod' command.  Lists currently
+  *	loaded kernel modules.
+  *
+  *	Mostly taken from userland lsmod.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *
+  */
+ 
+ int
+ kdb_lsmod(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	struct module *mod;
+ 	struct module_ref *mr;
+ 
+ 	if (argc != 0)
+ 		return KDB_ARGCOUNT;
+ 
+ 	kdb_printf("Module                  Size  modstruct     Used by\n");
+ 	for (mod = module_list; mod && mod->next ;mod = mod->next) {
+ 		kdb_printf("%-20s%8lu  0x%p  %4ld ", mod->name, mod->size, (void *)mod,
+ 			(long)atomic_read(&mod->uc.usecount));
+ 
+ 		if (mod->flags & MOD_DELETED)
+ 			kdb_printf(" (deleted)");
+ 		else if (mod->flags & MOD_INITIALIZING)
+ 			kdb_printf(" (initializing)");
+ 		else if (!(mod->flags & MOD_RUNNING))
+ 			kdb_printf(" (uninitialized)");
+ 		else {
+ 			if (mod->flags &  MOD_AUTOCLEAN)
+ 				kdb_printf(" (autoclean)");
+ 			if (!(mod->flags & MOD_USED_ONCE))
+ 				kdb_printf(" (unused)");
+ 		}
+ 
+ 		if (mod->refs) {
+ 			kdb_printf(" [ ");
+ 
+ 			mr = mod->refs;
+ 			while (mr) {
+ 				kdb_printf("%s ", mr->ref->name);
+ 				mr = mr->next_ref;
+ 			}
+ 
+ 			kdb_printf("]");
+ 		}
+ 
+ 		kdb_printf("\n");
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_rmmod
+  *
+  *	This function implements the 'rmmod' command.  Removes a given
+  *	kernel module.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	Danger: free_module() calls mod->cleanup().  If the cleanup routine
+  *	relies on interrupts then it will hang, kdb has interrupts disabled.
+  */
+ 
+ int
+ kdb_rmmod(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	struct module *mod;
+ 
+ 
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	kdb_printf("Attempting to remove module: [%s]\n", argv[1]);
+ 	if ((mod = find_module(argv[1])) == NULL) {
+ 		kdb_printf("Unable to find a module by that name\n");
+ 		return 0;
+ 	}
+ 
+ 	if (mod->refs != NULL || __MOD_IN_USE(mod)) {
+ 		kdb_printf("Module is in use, unable to unload\n");
+ 		return 0;
+ 	}
+ 
+ 	free_module(mod, 0);
+ 	kdb_printf("Module successfully unloaded\n");
+ 
+ 	return 0;
+ }
+ #endif	/* CONFIG_MODULES */
+ 
+ /*
+  * kdb_env
+  *
+  *	This function implements the 'env' command.  Display the current
+  *	environment variables.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ int
+ kdb_env(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int i;
+ 
+ 	for(i=0; i<__nenv; i++) {
+ 		if (__env[i]) {
+ 			kdb_printf("%s\n", __env[i]);
+ 		}
+ 	}
+ 
+ 	if (KDB_DEBUG(MASK))
+ 		kdb_printf("KDBFLAGS=0x%x\n", kdb_flags);
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_dmesg
+  *
+  *	This function implements the 'dmesg' command to display the contents
+  *	of the syslog buffer.
+  *
+  *	dmesg [lines]
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	None.
+  */
+ 
+ int
+ kdb_dmesg(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	char *syslog_data[4], *start, *end, c;
+ 	int diag, logging, logsize, lines = 0;
+ 
+ 	if (argc > 1)
+ 		return KDB_ARGCOUNT;
+ 	if (argc) {
+ 		char *cp;
+ 		lines = simple_strtoul(argv[1], &cp, 0);
+ 		if (*cp || lines < 0)
+ 			lines = 0;
+ 	}
+ 
+ 	/* disable LOGGING if set */
+ 	diag = kdbgetintenv("LOGGING", &logging);
+ 	if (!diag && logging) {
+ 		const char *setargs[] = { "set", "LOGGING", "0" };
+ 		kdb_set(2, setargs, envp, regs);
+ 	}
+ 
+ 	/* syslog_data[0,1] physical start, end+1.  syslog_data[2,3] logical start, end+1. */
+ 	kdb_syslog_data(syslog_data);
+ 	if (syslog_data[2] == syslog_data[3])
+ 		return 0;
+ 	logsize = syslog_data[1] - syslog_data[0];
+ 	start = syslog_data[0] + (syslog_data[2] - syslog_data[0]) % logsize;
+ 	end = syslog_data[0] + (syslog_data[3] - syslog_data[0]) % logsize;
+ #define KDB_WRAP(p) if (p < syslog_data[0]) p = syslog_data[1]-1; else if (p >= syslog_data[1]) p = syslog_data[0]
+ 	if (lines) {
+ 		char *p = end;
+ 		++lines;
+ 		do {
+ 			--p;
+ 			KDB_WRAP(p);
+ 			if (*p == '\n') {
+ 				if (--lines == 0) {
+ 					++p;
+ 					KDB_WRAP(p);
+ 					break;
+ 				}
+ 			}
+ 		} while (p != start);
+ 		start = p;
+ 	}
+ 	/* Do a line at a time (max 200 chars) to reduce protocol overhead */
+ 	c = '\0';
+ 	while(1) {
+ 		char *p;
+ 		int chars = 0;
+ 		if (!*start) {
+ 			while (!*start) {
+ 				++start;
+ 				KDB_WRAP(start);
+ 				if (start == end)
+ 					break;
+ 			}
+ 			if (start == end)
+ 				break;
+ 		}
+ 		p = start;
+ 		while (*start && chars < 200) {
+ 			c = *start;
+ 			++chars;
+ 			++start;
+ 			KDB_WRAP(start);
+ 			if (start == end || c == '\n')
+ 				break;
+ 		}
+ 		if (chars)
+ 			kdb_printf("%.*s", chars, p);
+ 		if (start == end)
+ 			break;
+ 	}
+ 	if (c != '\n')
+ 		kdb_printf("\n");
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_cpu
+  *
+  *	This function implements the 'cpu' command.
+  *
+  *	cpu	[<cpunum>]
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	KDB_CMD_CPU for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  *	All cpu's should be spinning in kdb().  However just in case
+  *	a cpu did not take the smp_kdb_stop NMI, check that a cpu
+  *	entered kdb() before passing control to it.
+  */
+ 
+ int
+ kdb_cpu(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	unsigned long cpunum;
+ 	int diag, first = 1, i;
+ 
+ 	/* ask the other cpus if they are still active */
+ 	for (i=0; i<NR_CPUS; i++) {
+ 		if (cpu_online(i))
+ 			KDB_STATE_CLEAR_CPU(KDB, i);
+ 	}
+ 	KDB_STATE_SET(KDB);
+ 	barrier();
+ 	/* wait for the other cpus to notice and set state KDB again,
+ 	 * see kdb_main_loop
+ 	 */
+ 	udelay(1000);
+ 
+ 	if (argc == 0) {
+ 		int i;
+ 
+ 		kdb_printf("Currently on cpu %d\n", smp_processor_id());
+ 		kdb_printf("Available cpus: ");
+ 		for (i=0; i<NR_CPUS; i++) {
+ 			if (cpu_online(i)) {
+ 				if (!first)
+ 					kdb_printf(", ");
+ 				first = 0;
+ 				kdb_printf("%d", i);
+ 				if (!KDB_STATE_CPU(KDB, i))
+ 					kdb_printf("*");
+ 			}
+ 		}
+ 		kdb_printf("\n");
+ 		return 0;
+ 	}
+ 
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	diag = kdbgetularg(argv[1], &cpunum);
+ 	if (diag)
+ 		return diag;
+ 
+ 	/*
+ 	 * Validate cpunum
+ 	 */
+ 	if ((cpunum > NR_CPUS)
+ 	 || !cpu_online(cpunum)
+ 	 || !KDB_STATE_CPU(KDB, cpunum))
+ 		return KDB_BADCPUNUM;
+ 
+ 	kdb_new_cpu = cpunum;
+ 
+ 	/*
+ 	 * Switch to other cpu
+ 	 */
+ 	return KDB_CMD_CPU;
+ }
+ 
+ /*
+  * kdb_ps
+  *
+  *	This function implements the 'ps' command which shows
+  *	a list of the active processes.
+  *
+  *	ps [DRSTZU]			All processes, optionally filtered by state
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ void
+ kdb_ps1(struct task_struct *p)
+ {
+ 	kdb_printf("0x%p %8d %8d  %d %4d   %c  0x%p %c%s\n",
+ 		   (void *)p, p->pid, p->parent->pid,
+ 		   kdb_task_has_cpu(p), kdb_process_cpu(p),
+ 		   (p->state == 0) ? 'R' :
+ 		     (p->state < 0) ? 'U' :
+ 		     (p->state & TASK_UNINTERRUPTIBLE) ? 'D' :
+ 		     (p->state & TASK_STOPPED || p->ptrace & PT_PTRACED) ? 'T' :
+ 		     (p->state & TASK_ZOMBIE) ? 'Z' :
+ 		     (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?',
+ 		   (void *)(&p->thread),
+ 		   (p == current) ? '*': ' ',
+ 		   p->comm);
+ 	if (kdb_task_has_cpu(p)) {
+ 		struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+ 		if (!krp->seqno || !krp->p)
+ 			kdb_printf("  Error: no saved data for this cpu\n");
+ 		else {
+ 			if (krp->seqno < kdb_seqno - 1)
+ 				kdb_printf("  Warning: process state is stale\n");
+ 			if (krp->p != p)
+ 				kdb_printf("  Error: does not match running process table (0x%p)\n", krp->p);
+ 		}
+ 	}
+ }
+ 
+ int
+ kdb_ps(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	struct task_struct *p;
+ 	unsigned long mask, cpu;
+ 
+ 	kdb_printf("%-*s      Pid   Parent [*] cpu State %-*s Command\n",
+ 		(int)(2*sizeof(void *))+2, "Task Addr",
+ 		(int)(2*sizeof(void *))+2, "Thread");
+ 	mask = kdb_task_state_string(argc, argv, envp);
+ 	/* Run the active tasks first */
+ 	for (cpu = 0; cpu < smp_num_cpus; ++cpu) {
+ 		p = kdb_active_task[cpu];
+ 		if (!kdb_task_state(p, mask))
+ 			continue;
+ 		kdb_ps1(p);
+ 	}
+ 	/* Now the real tasks */
+ 	for_each_process(p) {
+ 		if (!kdb_task_state(p, mask))
+ 			continue;
+ 		kdb_ps1(p);
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_pid
+  *
+  *	This function implements the 'pid' command which switches
+  *	the currently active process.
+  *
+  *	pid [<pid>]
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ 
+ int
+ kdb_pid(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	struct task_struct	*p;
+ 	unsigned long val;
+ 	int diag;
+ 
+ 	if (argc > 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	if (argc) {
+ 		diag = kdbgetularg(argv[1], &val);
+ 		if (diag)
+ 			return KDB_BADINT;
+ 	
+ 		p = find_task_by_pid((pid_t)val);
+ 		if (!p) {
+ 			kdb_printf("No task with pid=%d\n", (pid_t)val);
+ 			return 0;
+ 		}
+ 
+ 		kdb_current_task = p;
+ 	}
+ 
+ 	kdb_printf("KDB current process is %s(pid=%d)\n", kdb_current_task->comm, 
+ 		   kdb_current_task->pid);
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_ll
+  *
+  *	This function implements the 'll' command which follows a linked
+  *	list and executes an arbitrary command for each element.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ int
+ kdb_ll(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int diag;
+ 	kdb_machreg_t addr;
+ 	long 	      offset = 0;
+ 	kdb_machreg_t va;
+ 	unsigned long linkoffset;
+ 	int nextarg;
+ 	const char *command;
+ 
+ 	if (argc != 3) {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 
+ 	nextarg = 1;
+ 	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+ 	if (diag)
+ 		return diag;
+ 
+ 	diag = kdbgetularg(argv[2], &linkoffset);
+ 	if (diag)
+ 		return diag;
+ 
+ 	/*
+ 	 * Using the starting address as
+ 	 * the first element in the list, and assuming that
+ 	 * the list ends with a null pointer.
+ 	 */
+ 
+ 	va = addr;
+ 	if (!(command = kdb_strdup(argv[3], GFP_KERNEL))) {
+ 		kdb_printf("%s: cannot duplicate command\n", __FUNCTION__);
+ 		return 0;
+ 	}
+ 	/* Recursive use of kdb_parse, do not use argv after this point */
+ 	argv = NULL;
+ 
+ 	while (va) {
+ 		char buf[80];
+ 
+ 		sprintf(buf, "%s " kdb_machreg_fmt "\n", command, va);
+ 		diag = kdb_parse(buf, regs);
+ 		if (diag)
+ 			return diag;
+ 
+ 		addr = va + linkoffset;
+ 		if (kdb_getword(&va, addr, sizeof(va)))
+ 			return(0);
+ 	}
+ 	kfree(command);
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_sections_callback
+  *
+  *	Invoked from kallsyms_sections for each section.
+  *
+  * Inputs:
+  *	prevmod	Previous module name
+  *	modname	Module name
+  *	secname	Section name
+  *	secstart Start of section
+  *	secend	End of section
+  *	secflags Section flags
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Always zero
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ static int
+ kdb_sections_callback(void *token, const char *modname, const char *secname,
+ 		      ElfW(Addr) secstart, ElfW(Addr) secend, ElfW(Word) secflags)
+ {
+ 	const char **prevmod = (const char **)token;
+ 	if (*prevmod != modname) {
+ 		*prevmod = modname;
+ 		kdb_printf("\n%s", modname);
+ 	}
+ 	kdb_printf(" %s " kdb_elfw_addr_fmt0 " " kdb_elfw_addr_fmt0 " 0x%x",
+ 		secname, secstart, secend, secflags);
+ 	return(0);
+ }
+ 
+ /*
+  * kdb_sections
+  *
+  *	This function implements the 'sections' command which prints the
+  *	kernel and module sections.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ int
+ kdb_sections(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	char *prev_mod = NULL;
+ 	if (argc != 0) {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 	kallsyms_sections(&prev_mod, kdb_sections_callback);
+ 	kdb_printf("\n");	/* End last module */
+ 	return(0);
+ }
+ 
+ /*
+  * kdb_help
+  *
+  *	This function implements the 'help' and '?' commands.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ 
+ int
+ kdb_help(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	kdbtab_t *kt;
+ 
+ 	kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");
+ 	kdb_printf("----------------------------------------------------------\n");
+ 	for(kt=kdb_commands; kt->cmd_name; kt++) {
+ 		kdb_printf("%-15.15s %-20.20s %s\n", kt->cmd_name,
+ 			kt->cmd_usage, kt->cmd_help);
+ 	}
+ 	return 0;
+ }
+ 
+ extern int kdb_wake_up_process(struct task_struct * p);
+ 
+ /*
+  * kdb_kill
+  *
+  *	This function implements the 'kill' commands.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ int
+ kdb_kill(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ #ifdef	__KDB_HAVE_NEW_SCHEDULER
+ 	kdb_printf("kill command not implemented for new scheduler\n");
+ 	return KDB_NOTIMP;
+ #else	/* !__KDB_HAVE_NEW_SCHEDULER */
+ 	long sig, pid;
+ 	char *endp;
+ 	struct task_struct *p, *tg;
+ 	int find;
+ 	struct siginfo info;
+ 
+ 	if (argc!=2)
+ 		return KDB_ARGCOUNT;
+ 
+ 	sig = simple_strtol(argv[1], &endp, 0);
+ 	if (*endp)
+ 		return KDB_BADINT;
+ 	if (sig >= 0 ) {
+ 		kdb_printf("Invalid signal parameter.<-signal>\n");
+ 		return 0;
+ 	}
+ 	sig=-sig;
+ 
+ 	pid = simple_strtol(argv[2], &endp, 0);
+ 	if (*endp)
+ 		return KDB_BADINT;
+ 	if (pid <=0 ) {
+ 		kdb_printf("Process ID must be large than 0.\n");
+ 		return 0;
+ 	}
+ 
+ 	/* Find the process. */
+ 	find = 0;
+ 	for_each_task(p) {
+ 		if(p->pid == pid) {
+ 			find = 1;
+ 			break;
+ 		}
+ 	}
+ 	if (!find) {
+ 		kdb_printf("The specified process isn't found.\n");
+ 		return 0;
+ 	}
+ 	/* In case the process is not a thread group leader, find the leader. */
+ 	if ( p->tgid != p->pid) {
+ 		for_each_task(tg) {
+ 			if(tg->pid == p->tgid) {
+ 				p = tg;
+ 				break;
+ 			}
+ 		}
+ 	}
+ 	if (!spin_trylock(&p->sigmask_lock)) {
+ 		kdb_printf("Can't do kill command now.\n"
+ 			"The sigmask lock is held somewhere else in kernel, try again later\n");
+ 		return 0;
+ 	}
+ 	spin_unlock(&p->sigmask_lock);
+ 	if (!spin_trylock(&runqueue_lock)) {
+ 		kdb_printf("Can't do kill command now.\n"
+ 			"The runqueue lock is held somewhere else in kernel, try again later\n");
+ 		return 0;
+ 	}
+ 	spin_unlock(&runqueue_lock);
+ 	info.si_signo = sig;
+ 	info.si_errno = 0;
+ 	info.si_code = SI_USER;
+ 	info.si_pid = pid;	/* use same capabilities as process being signalled */
+ 	info.si_uid = 0;	/* kdb has root authority */
+ 	if(send_sig_info(sig, &info, p))
+ 		kdb_printf("Fail to deliver Signal %ld to process %ld.\n", sig, pid);
+ 	else
+ 		kdb_printf("Signal %ld is sent to process %ld.\n", sig, pid);
+ 	return 0;
+ #endif	/* __KDB_HAVE_NEW_SCHEDULER */
+ }
+ 
+ /*
+  * kdb_register_repeat
+  *
+  *	This function is used to register a kernel debugger command.
+  *
+  * Inputs:
+  *	cmd	Command name
+  *	func	Function to execute the command
+  *	usage	A simple usage string showing arguments
+  *	help	A simple help string describing command
+  *	repeat	Does the command auto repeat on enter?
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, one if a duplicate command.
+  * Locking:
+  *	none.
+  * Remarks:
+  *
+  */
+ 
+ #define kdb_command_extend 50	/* arbitrary */
+ int
+ kdb_register_repeat(char *cmd,
+ 		    kdb_func_t func,
+ 		    char *usage,
+ 		    char *help,
+ 		    short minlen,
+ 		    kdb_repeat_t repeat)
+ {
+ 	int i;
+ 	kdbtab_t *kp;
+ 
+ 	/*
+ 	 *  Brute force method to determine duplicates
+ 	 */
+ 	for (i=0, kp=kdb_commands; i<kdb_max_commands; i++, kp++) {
+ 		if (kp->cmd_name && (strcmp(kp->cmd_name, cmd)==0)) {
+ 			kdb_printf("Duplicate kdb command registered: '%s'\n",
+ 				   cmd);
+ 			return 1;
+ 		}
+ 	}
+ 
+ 	/*
+ 	 * Insert command into first available location in table
+ 	 */
+ 	for (i=0, kp=kdb_commands; i<kdb_max_commands; i++, kp++) {
+ 		if (kp->cmd_name == NULL) {
+ 			break;
+ 		}
+ 	}
+ 
+ 	if (i >= kdb_max_commands) {
+ 		kdbtab_t *new = kmalloc((kdb_max_commands + kdb_command_extend) * sizeof(*new), GFP_KERNEL);
+ 		if (!new) {
+ 			kdb_printf("Could not allocate new kdb_command table\n");
+ 			return 1;
+ 		}
+ 		if (kdb_commands) {
+ 			memcpy(new, kdb_commands, kdb_max_commands * sizeof(*new));
+ 			kfree(kdb_commands);
+ 		}
+ 		memset(new + kdb_max_commands, 0, kdb_command_extend * sizeof(*new));
+ 		kdb_commands = new;
+ 		kp = kdb_commands + kdb_max_commands;
+ 		kdb_max_commands += kdb_command_extend;
+ 	}
+ 
+ 	kp->cmd_name   = cmd;
+ 	kp->cmd_func   = func;
+ 	kp->cmd_usage  = usage;
+ 	kp->cmd_help   = help;
+ 	kp->cmd_flags  = 0;
+ 	kp->cmd_minlen = minlen;
+ 	kp->cmd_repeat = repeat;
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_register
+  *
+  *	Compatibility register function for commands that do not need to
+  *	specify a repeat state.  Equivalent to kdb_register_repeat with
+  *	KDB_REPEAT_NONE.
+  *
+  * Inputs:
+  *	cmd	Command name
+  *	func	Function to execute the command
+  *	usage	A simple usage string showing arguments
+  *	help	A simple help string describing command
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, one if a duplicate command.
+  * Locking:
+  *	none.
+  * Remarks:
+  *
+  */
+ 
+ int
+ kdb_register(char *cmd,
+ 	     kdb_func_t func,
+ 	     char *usage,
+ 	     char *help,
+ 	     short minlen)
+ {
+ 	return kdb_register_repeat(cmd, func, usage, help, minlen, KDB_REPEAT_NONE);
+ }
+ 
+ /*
+  * kdb_unregister
+  *
+  *	This function is used to unregister a kernel debugger command.
+  *	It is generally called when a module which implements kdb
+  *	commands is unloaded.
+  *
+  * Inputs:
+  *	cmd	Command name
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, one command not registered.
+  * Locking:
+  *	none.
+  * Remarks:
+  *
+  */
+ 
+ int
+ kdb_unregister(char *cmd)
+ {
+ 	int i;
+ 	kdbtab_t *kp;
+ 
+ 	/*
+ 	 *  find the command.
+ 	 */
+ 	for (i=0, kp=kdb_commands; i<kdb_max_commands; i++, kp++) {
+ 		if (kp->cmd_name && (strcmp(kp->cmd_name, cmd)==0)) {
+ 			kp->cmd_name = NULL;
+ 			return 0;
+ 		}
+ 	}
+ 
+ 	/*
+ 	 * Couldn't find it.
+ 	 */
+ 	return 1;
+ }
+ 
+ /*
+  * kdb_inittab
+  *
+  *	This function is called by the kdb_init function to initialize
+  *	the kdb command table.   It must be called prior to any other
+  *	call to kdb_register_repeat.
+  *
+  * Inputs:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  *
+  */
+ 
+ static void __init
+ kdb_inittab(void)
+ {
+ 	int i;
+ 	kdbtab_t *kp;
+ 	initcall_t *call;
+ 
+ 	for(i=0, kp=kdb_commands; i < kdb_max_commands; i++,kp++) {
+ 		kp->cmd_name = NULL;
+ 	}
+ 
+ 	kdb_register_repeat("md", kdb_md, "<vaddr>",   "Display Memory Contents, also mdWcN, e.g. md8c1", 1, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("mdr", kdb_md, "<vaddr> <bytes>", 	"Display Raw Memory", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("mds", kdb_md, "<vaddr>", 	"Display Memory Symbolically", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("mm", kdb_mm, "<vaddr> <contents>",   "Modify Memory Contents", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("id", kdb_id, "<vaddr>",   "Display Instructions", 1, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("go", kdb_go, "[<vaddr>]", "Continue Execution", 1, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("rd", kdb_rd, "",		"Display Registers", 1, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("rm", kdb_rm, "<reg> <contents>", "Modify Registers", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("ef", kdb_ef, "<vaddr>",   "Display exception frame", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("bt", kdb_bt, "[<vaddr>]", "Stack traceback", 1, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("btp", kdb_bt, "<pid>", 	"Display stack for process <pid>", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("bta", kdb_bt, "[DRSTZU]", 	"Display stack all processes", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("btc", kdb_bt, "", 	"Backtrace current process on each cpu", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("btt", kdb_bt, "<vaddr>", 	"Backtrace process given its struct task address", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("ll", kdb_ll, "<first-element> <linkoffset> <cmd>", "Execute cmd for each element in linked list", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("env", kdb_env, "", 	"Show environment variables", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("set", kdb_set, "", 	"Set environment variables", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("help", kdb_help, "", 	"Display Help Message", 1, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("?", kdb_help, "",         "Display Help Message", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("cpu", kdb_cpu, "<cpunum>","Switch to new cpu", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("ps", kdb_ps, "", 		"Display active task list", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("pid", kdb_pid, "<pidnum>",	"Switch to another task", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("reboot", kdb_reboot, "",  "Reboot the machine immediately", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("sections", kdb_sections, "",  "List kernel and module sections", 0, KDB_REPEAT_NONE);
+ #if defined(CONFIG_MODULES)
+ 	kdb_register_repeat("lsmod", kdb_lsmod, "",	"List loaded kernel modules", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("rmmod", kdb_rmmod, "<modname>", "Remove a kernel module", 0, KDB_REPEAT_NONE);
+ #endif
+ #if defined(CONFIG_MAGIC_SYSRQ)
+ 	kdb_register_repeat("sr", kdb_sr, "<key>",	"Magic SysRq key", 0, KDB_REPEAT_NONE);
+ #endif
+ 	kdb_register_repeat("dmesg", kdb_dmesg, "[lines]",	"Display syslog buffer", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"", "Define a set of commands, down to endefcmd", 0, KDB_REPEAT_NONE);
+ 	kdb_register_repeat("kill", kdb_kill, "<-signal> <pid>", "Send a signal to a process", 0, KDB_REPEAT_NONE);
+ 
+ 	/* Any kdb commands that are not in the base code but are required
+ 	 * earlier than normal initcall processing.
+ 	 */
+ 	call = &__kdb_initcall_start;
+ 	while (call < &__kdb_initcall_end) {
+ 		(*call)();
+ 		call++;
+ 	};
+ }
+ 
+ /*
+  * kdb_cmd_init
+  *
+  *	This function is called by the kdb_init function to execute any
+  *	commands defined in kdb_cmds.
+  *
+  * Inputs:
+  *	Commands in *kdb_cmds[];
+  * Outputs:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  *
+  */
+ 
+ static void __init
+ kdb_cmd_init(void)
+ {
+ 	int i, diag;
+ 	for (i = 0; kdb_cmds[i]; ++i) {
+ 		kdb_printf("kdb_cmd[%d]%s: %s",
+ 				i, defcmd_in_progress ? "[defcmd]" : "", kdb_cmds[i]);
+ 		diag = kdb_parse(kdb_cmds[i], NULL);
+ 		if (diag)
+ 			kdb_printf("command failed, kdb diag %d\n", diag);
+ 	}
+ 	if (defcmd_in_progress) {
+ 		kdb_printf("Incomplete 'defcmd' set, forcing endefcmd\n");
+ 		kdb_parse("endefcmd", NULL);
+ 	}
+ }
+ 
+ /*
+  * kdb_panic
+  *
+  *	Invoked via the panic_notifier_list.
+  *
+  * Inputs:
+  *	None.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Zero.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	When this function is called from panic(), the other cpus have already
+  *	been stopped.
+  *
+  */
+ 
+ static int
+ kdb_panic(struct notifier_block *self, unsigned long command, void *ptr)
+ {
+ 	KDB_FLAG_SET(CATASTROPHIC);	/* kernel state is dubious now */
+ 	KDB_ENTER();
+ 	return(0);
+ }
+ 
+ static struct notifier_block kdb_block = { kdb_panic, NULL, 0 };
+ 
+ /*
+  * kdb_init
+  *
+  * 	Initialize the kernel debugger environment.
+  *
+  * Parameters:
+  *	None.
+  * Returns:
+  *	None.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	None.
+  */
+ 
+ void __init
+ kdb_init(void)
+ {
+ 	/*
+ 	 * This must be called before any calls to kdb_printf.
+ 	 */
+ 	kdb_io_init();
+ 
+ 	kdb_inittab();		/* Initialize Command Table */
+ 	kdb_initbptab();	/* Initialize Breakpoint Table */
+ 	kdb_id_init();		/* Initialize Disassembler */
+ 	kdba_init();		/* Architecture Dependent Initialization */
+ 
+ 	/*
+ 	 * Use printk() to get message in log_buf[];
+ 	 */
+ 	printk("kdb version %d.%d%s by Keith Owens, Scott Lurndal. "\
+ 	       "Copyright SGI, All Rights Reserved\n",
+ 		KDB_MAJOR_VERSION, KDB_MINOR_VERSION, KDB_TEST_VERSION);
+ 
+ 	kdb_cmd_init();		/* Preset commands from kdb_cmds */
+ 	kdb(KDB_REASON_SILENT, 0, 0);	/* Activate any preset breakpoints on boot cpu */
+ 	notifier_chain_register(&panic_notifier_list, &kdb_block);
+ }
+ 
+ EXPORT_SYMBOL(kdb_register);
+ EXPORT_SYMBOL(kdb_register_repeat);
+ EXPORT_SYMBOL(kdb_unregister);
+ EXPORT_SYMBOL(kdb_getarea_size);
+ EXPORT_SYMBOL(kdb_putarea_size);
+ EXPORT_SYMBOL(kdb_getuserarea_size);
+ EXPORT_SYMBOL(kdb_putuserarea_size);
+ EXPORT_SYMBOL(kdb_getword);
+ EXPORT_SYMBOL(kdb_putword);
+ EXPORT_SYMBOL(kdbgetularg);
+ EXPORT_SYMBOL(kdbgetenv);
+ EXPORT_SYMBOL(kdbgetintenv);
+ EXPORT_SYMBOL(kdbgetaddrarg);
+ EXPORT_SYMBOL(kdb);
+ EXPORT_SYMBOL(kdb_on);
+ EXPORT_SYMBOL(kdb_seqno);
+ EXPORT_SYMBOL(kdb_initial_cpu);
+ EXPORT_SYMBOL(kdbgetsymval);
+ EXPORT_SYMBOL(kdbnearsym);
+ EXPORT_SYMBOL(kdb_printf);
+ EXPORT_SYMBOL(kdb_symbol_print);
+ EXPORT_SYMBOL(kdb_notifier_list);
+ EXPORT_SYMBOL(kdb_enter_debugger);
+ EXPORT_SYMBOL(kdb_current_task);
+ EXPORT_SYMBOL(kdba_dumpregs);
diff -c -r -N console-os/kdb/kdbsupport.c console-os-kdb/kdb/kdbsupport.c
*** console-os/kdb/kdbsupport.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/kdbsupport.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,860 ----
+ /*
+  * Kernel Debugger Architecture Independent Support Functions
+  *
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <stdarg.h>
+ #include <linux/config.h>
+ #include <linux/types.h>
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+ #include <linux/kallsyms.h>
+ #include <linux/stddef.h>
+ #include <linux/vmalloc.h>
+ #include <linux/highmem.h>
+ #include <asm/uaccess.h>
+ 
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ 
+ /*
+  * Symbol table functions.
+  */
+ 
+ /*
+  * kdbgetsymval
+  *
+  *	Return the address of the given symbol.
+  *
+  * Parameters:
+  * 	symname	Character string containing symbol name
+  *      symtab  Structure to receive results
+  * Outputs:
+  * Returns:
+  *	0	Symbol not found, symtab zero filled
+  *	1	Symbol mapped to module/symbol/section, data in symtab
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ int
+ kdbgetsymval(const char *symname, kdb_symtab_t *symtab)
+ {
+ 	memset(symtab, 0, sizeof(*symtab));
+ 	return(kallsyms_symbol_to_address(
+ 		symname,
+ 		NULL,
+ 		&symtab->mod_name,
+ 		&symtab->mod_start,
+ 		&symtab->mod_end,
+ 		&symtab->sec_name,
+ 		&symtab->sec_start,
+ 		&symtab->sec_end,
+ 		&symtab->sym_name,
+ 		&symtab->sym_start,
+ 		&symtab->sym_end));
+ }
+ 
+ /*
+  * kdbnearsym
+  *
+  *	Return the name of the symbol with the nearest address
+  *	less than 'addr'.
+  *
+  * Parameters:
+  * 	addr	Address to check for symbol near
+  *      symtab  Structure to receive results
+  * Outputs:
+  * Returns:
+  *	0	No sections contain this address, symtab zero filled
+  *	1	Address mapped to module/symbol/section, data in symtab
+  * Locking:
+  *	None.
+  * Remarks:
+  */
+ 
+ int
+ kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
+ {
+ 	int ret;
+ 	memset(symtab, 0, sizeof(*symtab));
+ 	ret = kallsyms_address_to_symbol(
+ 		addr,
+ 		&symtab->mod_name,
+ 		&symtab->mod_start,
+ 		&symtab->mod_end,
+ 		&symtab->sec_name,
+ 		&symtab->sec_start,
+ 		&symtab->sec_end,
+ 		&symtab->sym_name,
+ 		&symtab->sym_start,
+ 		&symtab->sym_end);
+ 	if (symtab->mod_name && *symtab->mod_name == '\0')
+ 		symtab->mod_name = "kernel";
+ 	return ret;
+ }
+ 
+ #if defined(CONFIG_SMP)
+ /*
+  * kdb_ipi
+  *
+  *	This function is called from the non-maskable interrupt
+  *	handler to handle a kdb IPI instruction.
+  *
+  * Inputs:
+  *	regs	= Exception frame pointer
+  * Outputs:
+  *	None.
+  * Returns:
+  *	0	- Did not handle NMI
+  *	1	- Handled NMI
+  * Locking:
+  *	None.
+  * Remarks:
+  *	Initially one processor is invoked in the kdb() code.  That
+  *	processor sends an ipi which drives this routine on the other
+  *	processors.  All this does is call kdb() with reason SWITCH.
+  *	This puts all processors into the kdb() routine and all the
+  *	code for breakpoints etc. is in one place.
+  *	One problem with the way the kdb NMI is sent, the NMI has no
+  *	identification that says it came from kdb.  If the cpu's kdb state is
+  *	marked as "waiting for kdb_ipi" then the NMI is treated as coming from
+  *	kdb, otherwise it is assumed to be for another reason and is ignored.
+  */
+ 
+ int
+ kdb_ipi(struct pt_regs *regs, void (*ack_interrupt)(void))
+ {
+ 	/* Do not print before checking and clearing WAIT_IPI, IPIs are
+ 	 * going all the time.
+ 	 */
+ 	if (KDB_STATE(WAIT_IPI)) {
+ 		/*
+ 		 * Stopping other processors via smp_kdb_stop().
+ 		 */
+ 		if (ack_interrupt)
+ 			(*ack_interrupt)();	/* Acknowledge the interrupt */
+ 		KDB_STATE_CLEAR(WAIT_IPI);
+ 		KDB_DEBUG_STATE("kdb_ipi 1", 0);
+ 		kdb(KDB_REASON_SWITCH, 0, regs);	/* Spin in kdb() */
+ 		KDB_DEBUG_STATE("kdb_ipi 2", 0);
+ 		return 1;
+ 	}
+ 	return 0;
+ }
+ #endif	/* CONFIG_SMP */
+ 
+ void
+ kdb_enablehwfault(void)
+ {
+ 	kdba_enable_mce();
+ }
+ 
+ /*
+  * kdb_get_next_ar
+  *
+  *	Get the next activation record from the stack.
+  *
+  * Inputs:
+  *	arend	Last byte +1 of the activation record.  sp for the first
+  *		frame, start of callee's activation record otherwise.
+  *	func	Start address of function.
+  *	pc	Current program counter within this function.  pc for
+  *		the first frame, caller's return address otherwise.
+  *	fp	Current frame pointer.  Register fp for the first
+  *		frame, oldfp otherwise.  0 if not known.
+  *	ss	Start of stack for the current process.
+  * Outputs:
+  *	ar	Activation record.
+  *	symtab	kallsyms symbol table data for the calling function.
+  * Returns:
+  *	1 if ar is usable, 0 if not.
+  * Locking:
+  *	None.
+  * Remarks:
+  *	Activation Record format, assuming a stack that grows down
+  *	(KDB_STACK_DIRECTION == -1).
+  *
+  *	+-----------------------------+   ^         =====================
+  *	| Return address, frame 3     |   |
+  *	+-----------------------------+   |
+  *	| Frame Pointer, frame 3      |>--'
+  *	+-----------------------------+<--.
+  *	| Locals and automatics,      |   |
+  *	| frame 2. (variable size)    |   |                 AR 2
+  *	+-----------------------------+   |
+  *	| Save registers,             |   |
+  *	| frame 2. (variable size)    |   |
+  *	+-----------------------------+   |
+  *	| Arguments to frame 1,       |   |
+  *	| (variable size)             |   |
+  *	+-----------------------------+   |         =====================
+  *	| Return address, frame 2     |   |
+  *	+-----------------------------+   |
+  *	| Frame Pointer, frame 2      |>--'
+  *	+-----------------------------+<--.
+  *	| Locals and automatics,      |   |
+  *	| frame 1. (variable size)    |   |                 AR 1
+  *	+-----------------------------+   |
+  *	| Save registers,             |   |
+  *	| frame 1. (variable size)    |   |
+  *	+-----------------------------+   |
+  *	| Arguments to frame 0,       |   |
+  *	| (variable size)             |   |
+  *	+-----------------------------+   |  -- (5) =====================
+  *	| Return address, frame 1     |   |
+  *	+-----------------------------+   |  -- (0)
+  *	| Frame Pointer, frame 1      |>--'
+  *	+-----------------------------+      -- (1), (2)
+  *	| Locals and automatics,      |
+  *	| frame 0. (variable size)    |                     AR 0
+  *	+-----------------------------+      -- (3)
+  *	| Save registers,             |
+  *	| frame 0. (variable size)    |
+  *	+-----------------------------+      -- (4) =====================
+  *
+  * The stack for the top frame can be in one of several states.
+  *  (0) Immediately on entry to the function, stack pointer (sp) is
+  *      here.
+  *  (1) If the function was compiled with frame pointers and the 'push
+  *      fp' instruction has been executed then the pointer to the
+  *      previous frame is on the stack.  However there is no guarantee
+  *      that this saved pointer is valid, the calling function might
+  *      not have frame pointers.  sp is adjusted by wordsize after
+  *      'push fp'.
+  *  (2) If the function was compiled with frame pointers and the 'copy
+  *      sp to fp' instruction has been executed then fp points here.
+  *  (3) If the function startup has 'adjust sp by 0xnn bytes' and that
+  *      instruction has been executed then sp has been adjusted by
+  *      0xnn bytes for local and automatic variables.
+  *  (4) If the function startup has one or more 'push reg' instructions
+  *      and any have been executed then sp has been adjusted by
+  *      wordsize bytes for each register saved.
+  *
+  * As the function exits it rewinds the stack, typically to (1) then (0).
+  *
+  * The stack entries for the lower frames is normally are in state (5).
+  *  (5) Arguments for the called frame are on to the stack.
+  * However lower frames can be incomplete if there is an interrupt in
+  * progress.
+  *
+  * An activation record runs from the return address for a function
+  * through to the return address for the next function or sp, whichever
+  * comes first.  For each activation record we extract :-
+  *
+  *   start    Address of the activation record.
+  *   end      Address of the last byte+1 in the activation record.
+  *   ret      Return address to caller.
+  *   oldfp    Frame pointer to previous frame, 0 if this function was
+  *            not compiled with frame pointers.
+  *   fp       Frame pointer for the current frame, 0 if this function
+  *            was not compiled with frame pointers or fp has not been
+  *            set yet.
+  *   arg0     Address of the first argument (in the previous activation
+  *            record).
+  *   locals   Bytes allocated to locals and automatics.
+  *   regs     Bytes allocated to saved registers.
+  *   args     Bytes allocated to arguments (in the previous activation
+  *            record).
+  *   setup    Bytes allocated to setup data on stack (return address,
+  *	      frame pointer).
+  *
+  * Although the kernel might be compiled with frame pointers, we still
+  * have to assume the worst and validate the frame.  Some calls from
+  * asm code to C code might not use frame pointers.  Third party binary
+  * only modules might be compiled without frame pointers, even when the
+  * rest of the kernel has frame pointers.  Some routines are always
+  * compiled with frame pointers, even if the overall kernel is not.  A
+  * routine compiled with frame pointers can be called from a routine
+  * without frame pointers, the previous "frame pointer" is saved on
+  * stack but it contains garbage.
+  *
+  * We check the object code to see if it saved a frame pointer and we
+  * validate that pointer.  Basically frame pointers are hints.
+  */
+ 
+ #define FORCE_ARG(ar,n)	(ar)->setup = (ar)->locals = (ar)->regs = \
+ 			(ar)->fp = (ar)->oldfp = (ar)->ret = 0; \
+ 			(ar)->start = (ar)->end - KDB_STACK_DIRECTION*(n)*sizeof(unsigned long);
+ 
+ int
+ kdb_get_next_ar(kdb_machreg_t arend, kdb_machreg_t func,
+ 		kdb_machreg_t pc, kdb_machreg_t fp, kdb_machreg_t ss,
+ 		kdb_ar_t *ar, kdb_symtab_t *symtab)
+ {
+ 	if (KDB_DEBUG(AR)) {
+ 		kdb_printf("kdb_get_next_ar: arend=0x%lx func=0x%lx pc=0x%lx fp=0x%lx\n",
+ 			arend, func, pc, fp);
+ 	}
+ 
+ 	memset(ar, 0, sizeof(*ar));
+ 	if (!kdbnearsym(pc, symtab)) {
+ 		symtab->sym_name = symtab->sec_name = "<unknown>";
+ 		symtab->mod_name = "kernel";
+ 		if (KDB_DEBUG(AR)) {
+ 			kdb_printf("kdb_get_next_ar: callee not in kernel\n");
+ 		}
+ 		pc = 0;
+ 	}
+ 
+ 	if (!kdba_prologue(symtab, pc, arend, fp, ss, 0, ar)) {
+ 		if (KDB_DEBUG(AR)) {
+ 			kdb_printf("kdb_get_next_ar: callee prologue failed\n");
+ 		}
+ 		return(0);
+ 	}
+ 	if (KDB_DEBUG(AR)) {
+ 		kdb_printf("kdb_get_next_ar: callee activation record\n");
+ 		kdb_printf("  start=0x%lx end=0x%lx ret=0x%lx oldfp=0x%lx fp=0x%lx\n",
+ 			ar->start, ar->end, ar->ret, ar->oldfp, ar->fp);
+ 		kdb_printf("  locals=%ld regs=%ld setup=%ld\n",
+ 			ar->locals, ar->regs, ar->setup);
+ 	}
+ 
+ 	if (ar->ret) {
+ 		/* Run the caller code to get arguments to callee function */
+ 		kdb_symtab_t	caller_symtab;
+ 		kdb_ar_t	caller_ar;
+ 		memset(&caller_ar, 0, sizeof(caller_ar));
+ 		if (!kdbnearsym(ar->ret, &caller_symtab)) {
+ 			if (KDB_DEBUG(AR)) {
+ 				kdb_printf("kdb_get_next_ar: caller not in kernel\n");
+ 			}
+ 		} else if (kdba_prologue(&caller_symtab, ar->ret,
+ 				ar->start, ar->oldfp, ss, 1, &caller_ar)) {
+ 				/* some caller data extracted */ ;
+ 		} else if (strcmp(symtab->sym_name, "do_exit") == 0) {
+ 			/* non-standard caller, force one argument */
+ 			FORCE_ARG(&caller_ar, 1);
+ 		} else if (KDB_DEBUG(AR)) {
+ 				kdb_printf("kdb_get_next_ar: caller prologue failed\n");
+ 		}
+ 		if (KDB_DEBUG(AR)) {
+ 			kdb_printf("kdb_get_next_ar: caller activation record\n");
+ 			kdb_printf("  start=0x%lx end=0x%lx ret=0x%lx"
+ 				   " oldfp=0x%lx fp=0x%lx\n",
+ 				caller_ar.start, caller_ar.end, caller_ar.ret,
+ 				caller_ar.oldfp, caller_ar.fp);
+ 			kdb_printf("  locals=%ld regs=%ld args=%ld setup=%ld\n",
+ 				caller_ar.locals, caller_ar.regs,
+ 				caller_ar.args, caller_ar.setup);
+ 		}
+ 		if (caller_ar.start) {
+ 			ar->args = KDB_STACK_DIRECTION*(caller_ar.end - caller_ar.start) -
+ 				(caller_ar.setup + caller_ar.locals + caller_ar.regs);
+ 			if (ar->args < 0)
+ 				ar->args = 0;
+ 			if (ar->args) {
+ 				ar->arg0 = ar->start -
+ 					KDB_STACK_DIRECTION*(ar->args - 4);
+ 				if (KDB_DEBUG(AR)) {
+ 					kdb_printf("  callee arg0=0x%lx args=%ld\n",
+ 						ar->arg0, ar->args);
+ 				}
+ 			}
+ 		}
+ 	}
+ 
+ 	return(1);
+ }
+ 
+ /*
+  * kdb_symbol_print
+  *
+  *	Standard method for printing a symbol name and offset.
+  * Inputs:
+  *	addr	Address to be printed.
+  *	symtab	Address of symbol data, if NULL this routine does its
+  *		own lookup.
+  *	punc	Punctuation for string, bit field.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Always 0.
+  * Locking:
+  *	none.
+  * Remarks:
+  *	The string and its punctuation is only printed if the address
+  *	is inside the kernel, except that the value is always printed
+  *	when requested.
+  */
+ 
+ void
+ kdb_symbol_print(kdb_machreg_t addr, const kdb_symtab_t *symtab_p, unsigned int punc)
+ {
+ 	kdb_symtab_t symtab, *symtab_p2;
+ 	if (symtab_p) {
+ 		symtab_p2 = (kdb_symtab_t *)symtab_p;
+ 	}
+ 	else {
+ 		symtab_p2 = &symtab;
+ 		kdbnearsym(addr, symtab_p2);
+ 	}
+ 	if (symtab_p2->sym_name || (punc & KDB_SP_VALUE)) {
+ 		;	/* drop through */
+ 	}
+ 	else {
+ 		return;
+ 	}
+ 	if (punc & KDB_SP_SPACEB) {
+ 		kdb_printf(" ");
+ 	}
+ 	if (punc & KDB_SP_VALUE) {
+ 		kdb_printf(kdb_machreg_fmt0, addr);
+ 	}
+ 	if (symtab_p2->sym_name) {
+ 		if (punc & KDB_SP_VALUE) {
+ 			kdb_printf(" ");
+ 		}
+ 		if (punc & KDB_SP_PAREN) {
+ 			kdb_printf("(");
+ 		}
+ 		if (strcmp(symtab_p2->mod_name, "kernel")) {
+ 			kdb_printf("[%s]", symtab_p2->mod_name);
+ 		}
+ 		kdb_printf("%s", symtab_p2->sym_name);
+ 		if (addr != symtab_p2->sym_start) {
+ 			kdb_printf("+0x%lx", addr - symtab_p2->sym_start);
+ 		}
+ 		if (punc & KDB_SP_SYMSIZE) {
+ 			kdb_printf("/0x%lx", symtab_p2->sym_end - symtab_p2->sym_start);
+ 		}
+ 		if (punc & KDB_SP_PAREN) {
+ 			kdb_printf(")");
+ 		}
+ 	}
+ 	if (punc & KDB_SP_SPACEA) {
+ 		kdb_printf(" ");
+ 	}
+ 	if (punc & KDB_SP_NEWLINE) {
+ 		kdb_printf("\n");
+ 	}
+ }
+ 
+ /*
+  * kdb_strdup
+  *
+  *	kdb equivalent of strdup, for disasm code.
+  * Inputs:
+  *	str	The string to duplicate.
+  *	type	Flags to kmalloc for the new string.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	Address of the new string, NULL if storage could not be allocated.
+  * Locking:
+  *	none.
+  * Remarks:
+  *	This is not in lib/string.c because it uses kmalloc which is not
+  *	available when string.o is used in boot loaders.
+  */
+ 
+ char *kdb_strdup(const char *str, int type)
+ {
+ 	int n = strlen(str)+1;
+ 	char *s = kmalloc(n, type);
+ 	if (!s) return NULL;
+ 	return strcpy(s, str);
+ }
+ 
+ /*
+  * kdb_getarea_size
+  *
+  *	Read an area of data.  The kdb equivalent of copy_from_user, with
+  *	kdb messages for invalid addresses.
+  * Inputs:
+  *	res	Pointer to the area to receive the result.
+  *	addr	Address of the area to copy.
+  *	size	Size of the area.
+  * Outputs:
+  *	none.
+  * Returns:
+  *	0 for success, < 0 for error.
+  * Locking:
+  *	none.
+  */
+ 
+ int kdb_getarea_size(void *res, unsigned long addr, size_t size)
+ {
+ 	int ret = kdba_getarea_size(res, addr, size);
+ 	if (ret) {
+ 		if (!KDB_STATE(SUPPRESS)) {
+ 			kdb_printf("kdb_getarea: Bad address 0x%lx\n", addr);
+ 			KDB_STATE_SET(SUPPRESS);
+ 		}
+ 		ret = KDB_BADADDR;
+ 	}
+ 	else {
+ 		KDB_STATE_CLEAR(SUPPRESS);
+ 	}
+ 	return(ret);
+ }
+ 
+ /*
+  * kdb_putarea_size
+  *
+  *	Write an area of data.  The kdb equivalent of copy_to_user, with
+  *	kdb messages for invalid addresses.
+  * Inputs:
+  *	addr	Address of the area to write to.
+  *	res	Pointer to the area holding the data.
+  *	size	Size of the area.
+  * Outputs:
+  *	none.
+  * Returns:
+  *	0 for success, < 0 for error.
+  * Locking:
+  *	none.
+  */
+ 
+ int kdb_putarea_size(unsigned long addr, void *res, size_t size)
+ {
+ 	int ret = kdba_putarea_size(addr, res, size);
+ 	if (ret) {
+ 		if (!KDB_STATE(SUPPRESS)) {
+ 			kdb_printf("kdb_putarea: Bad address 0x%lx\n", addr);
+ 			KDB_STATE_SET(SUPPRESS);
+ 		}
+ 		ret = KDB_BADADDR;
+ 	}
+ 	else {
+ 		KDB_STATE_CLEAR(SUPPRESS);
+ 	}
+ 	return(ret);
+ }
+ 
+ /*
+  * kdb_getword
+  *
+  * 	Read a binary value.  Unlike kdb_getarea, this treats data as numbers.
+  * Inputs:
+  *	word	Pointer to the word to receive the result.
+  *	addr	Address of the area to copy.
+  *	size	Size of the area.
+  * Outputs:
+  *	none.
+  * Returns:
+  *	0 for success, < 0 for error.
+  * Locking:
+  *	none.
+  */
+ 
+ int kdb_getword(unsigned long *word, unsigned long addr, size_t size)
+ {
+ 	int diag;
+ 	__u8  w1;
+ 	__u16 w2;
+ 	__u32 w4;
+ 	__u64 w8;
+ 	*word = 0;	/* Default value if addr or size is invalid */
+ 	switch (size) {
+ 	case 1:
+ 		if (!(diag = kdb_getarea(w1, addr)))
+ 			*word = w1;
+ 		break;
+ 	case 2:
+ 		if (!(diag = kdb_getarea(w2, addr)))
+ 			*word = w2;
+ 		break;
+ 	case 4:
+ 		if (!(diag = kdb_getarea(w4, addr)))
+ 			*word = w4;
+ 		break;
+ 	case 8:
+ 		if (size <= sizeof(*word)) {
+ 			if (!(diag = kdb_getarea(w8, addr)))
+ 				*word = w8;
+ 			break;
+ 		}
+ 		/* drop through */
+ 	default:
+ 		diag = KDB_BADWIDTH;
+ 		kdb_printf("kdb_getword: bad width %ld\n", (long) size);
+ 	}
+ 	return(diag);
+ }
+ 
+ /*
+  * kdb_putword
+  *
+  * 	Write a binary value.  Unlike kdb_putarea, this treats data as numbers.
+  * Inputs:
+  *	addr	Address of the area to write to..
+  *	word	The value to set.
+  *	size	Size of the area.
+  * Outputs:
+  *	none.
+  * Returns:
+  *	0 for success, < 0 for error.
+  * Locking:
+  *	none.
+  */
+ 
+ int kdb_putword(unsigned long addr, unsigned long word, size_t size)
+ {
+ 	int diag;
+ 	__u8  w1;
+ 	__u16 w2;
+ 	__u32 w4;
+ 	__u64 w8;
+ 	switch (size) {
+ 	case 1:
+ 		w1 = word;
+ 		diag = kdb_putarea(addr, w1);
+ 		break;
+ 	case 2:
+ 		w2 = word;
+ 		diag = kdb_putarea(addr, w2);
+ 		break;
+ 	case 4:
+ 		w4 = word;
+ 		diag = kdb_putarea(addr, w4);
+ 		break;
+ 	case 8:
+ 		if (size <= sizeof(word)) {
+ 			w8 = word;
+ 			diag = kdb_putarea(addr, w8);
+ 			break;
+ 		}
+ 		/* drop through */
+ 	default:
+ 		diag = KDB_BADWIDTH;
+ 		kdb_printf("kdb_putword: bad width %ld\n", (long) size);
+ 	}
+ 	return(diag);
+ }
+ 
+ /*
+  * kdb_task_state_string
+  *
+  * 	Convert a string containing any of the letters DRSTZU to a mask for
+  * 	the process state field and return the value.  If no argument is
+  * 	supplied, return ~0.
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  * Outputs:
+  *	none.
+  * Returns:
+  *	Mask for process state.
+  * Locking:
+  *	none.
+  */
+ 
+ #define UNRUNNABLE	(1UL << (8*sizeof(unsigned long) - 1))	/* unrunnable is < 0 */
+ #define RUNNING		(1UL << (8*sizeof(unsigned long) - 2))
+ #define TRACED		(1UL << (8*sizeof(unsigned long) - 3))
+ 
+ unsigned long
+ kdb_task_state_string(int argc, const char **argv, const char **envp)
+ {
+ 	long res = ~0;
+ 	if (argc >= 1) {
+ 		const char *s = argv[1];
+ 		res = 0;
+ 		while (*s) {
+ 			switch (*s) {
+ 			case 'D': res |= TASK_UNINTERRUPTIBLE; break;
+ 			case 'R': res |= RUNNING; break;
+ 			case 'S': res |= TASK_INTERRUPTIBLE; break;
+ 			case 'T': res |= TASK_STOPPED | TRACED; break;
+ 			case 'Z': res |= TASK_ZOMBIE; break;
+ 			case 'U': res |= UNRUNNABLE; break;
+ 			default:
+ 				  kdb_printf("kdb_task_state unknown flag '%c' ignored\n", *s);
+ 				  break;
+ 			}
+ 			++s;
+ 		}
+ 	}
+ 	return res;
+ }
+ 
+ /*
+  * kdb_task_state
+  *
+  * 	Return true if a process has the desired state given by the mask.
+  * Inputs:
+  *	p	struct task for the process
+  *	mask	mask from kdb_task_state_string to select processes
+  * Outputs:
+  *	none.
+  * Returns:
+  *	True if the process matches at least one criteria defined by the mask.
+  * Locking:
+  *	none.
+  */
+ 
+ unsigned long
+ kdb_task_state(const struct task_struct *p, unsigned long mask)
+ {
+ 	return ((mask & p->state) ||
+ 		(mask & RUNNING && p->state == 0) ||
+ 		(mask & TRACED && p->ptrace & PT_PTRACED));
+ }
+ 
+ struct kdb_running_process kdb_running_process[NR_CPUS];
+ 
+ /*
+  * kdb_save_running
+  *
+  * 	Save the state of a running process.  This is invoked on the current
+  * 	process on each cpu (assuming the cpu is responding).
+  * Inputs:
+  *	regs	struct pt_regs for the process
+  * Outputs:
+  *	Updates kdb_running_process[] for this cpu.
+  * Returns:
+  *	none.
+  * Locking:
+  *	none.
+  */
+ 
+ void
+ kdb_save_running(struct pt_regs *regs)
+ {
+ 	struct kdb_running_process *krp = kdb_running_process + smp_processor_id();
+ 	krp->p = current;
+ 	krp->regs = regs;
+ 	krp->seqno = kdb_seqno;
+ 	kdba_save_running(&(krp->arch), regs);
+ }
+ 
+ /*
+  * kdb_unsave_running
+  *
+  * 	Reverse the effect of kdb_save_running.
+  * Inputs:
+  *	regs	struct pt_regs for the process
+  * Outputs:
+  *	Updates kdb_running_process[] for this cpu.
+  * Returns:
+  *	none.
+  * Locking:
+  *	none.
+  */
+ 
+ void
+ kdb_unsave_running(struct pt_regs *regs)
+ {
+ 	struct kdb_running_process *krp = kdb_running_process + smp_processor_id();
+ 	kdba_unsave_running(&(krp->arch), regs);
+ 	krp->seqno = 0;
+ }
+ 
+ 
+ /*
+  * kdb_print_nameval
+  *
+  * 	Print a name and its value, converting the value to a symbol lookup
+  * 	if possible.
+  * Inputs:
+  *	name	field name to print
+  *	val	value of field
+  * Outputs:
+  *	none.
+  * Returns:
+  *	none.
+  * Locking:
+  *	none.
+  */
+ 
+ void
+ kdb_print_nameval(const char *name, unsigned long val)
+ {
+ 	kdb_symtab_t symtab;
+ 	kdb_printf("  %-11.11s ", name);
+ 	if (kdbnearsym(val, &symtab))
+ 		kdb_symbol_print(val, &symtab, KDB_SP_VALUE|KDB_SP_SYMSIZE|KDB_SP_NEWLINE);
+ 	else
+ 		kdb_printf("0x%lx\n", val);
+ }
+ 
+ static struct page * kdb_get_one_user_page(struct task_struct *tsk, unsigned long start,
+ 		int len, int write)
+ {
+ 	struct mm_struct *mm = tsk->mm;
+ 	unsigned int flags;
+ 	struct vm_area_struct *	vma;
+ 
+ 	/* shouldn't cross a page boundary. temporary restriction. */
+ 	if ((start & PAGE_MASK) != ((start+len) & PAGE_MASK)) {
+ 		kdb_printf("%s: crosses page boundary: addr=%08lx, len=%d\n", 
+ 			__FUNCTION__, start, len);
+ 		return NULL;
+ 	}
+ 
+ 	start = PAGE_ALIGN(start);
+ 	flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
+ 
+ 	vma = find_extend_vma(mm, start);
+ 
+ 	/* may be we can allow access to VM_IO pages inside KDB? */
+ 	if (!vma || (vma->vm_flags & VM_IO) || !(flags & vma->vm_flags))
+ 		return NULL;
+ 
+ 	return kdb_follow_page(mm, start, write);
+ }
+ 
+ int kdb_getuserarea_size(void *to, unsigned long from, size_t size)
+ {
+ 	struct page *page;
+ 	void * vaddr;
+ 
+ 	page = kdb_get_one_user_page(kdb_current_task, from, size, 0);
+ 	if (!page)
+ 		return size;
+ 
+ 	vaddr = kmap_atomic(page, KM_KDB);
+ 	memcpy(to, vaddr+ (from & (PAGE_SIZE - 1)), size);
+ 	kunmap_atomic(vaddr, KM_KDB);
+ 
+ 	return 0;
+ }
+ 
+ int kdb_putuserarea_size(unsigned long to, void *from, size_t size)
+ {
+ 	struct page *page;
+ 	void * vaddr;
+ 
+ 	page = kdb_get_one_user_page(kdb_current_task, to, size, 1);
+ 	if (!page)
+ 		return size;
+ 
+ 	vaddr = kmap_atomic(page, KM_KDB);
+ 	memcpy(vaddr+ (to & (PAGE_SIZE - 1)), from, size);
+ 	kunmap_atomic(vaddr, KM_KDB);
+ 
+ 	return 0;
+ }
diff -c -r -N console-os/kdb/Makefile console-os-kdb/kdb/Makefile
*** console-os/kdb/Makefile	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/Makefile	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,53 ----
+ #
+ # Copyright (c) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ #
+ # This program is free software; you can redistribute it and/or modify it
+ # under the terms of version 2 of the GNU General Public License as
+ # published by the Free Software Foundation.
+ #
+ # This program is distributed in the hope that it would be useful, but
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ #
+ # Further, this software is distributed without any warranty that it is
+ # free of the rightful claim of any third person regarding infringement
+ # or the like.  Any license provided herein, whether implied or
+ # otherwise, applies only to this software file.  Patent licenses, if
+ # any, provided herein do not apply to combinations of this program with
+ # other software, or any other product whatsoever.
+ #
+ # You should have received a copy of the GNU General Public License along
+ # with this program; if not, write the Free Software Foundation, Inc., 59
+ # Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ #
+ # Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ # Mountain View, CA  94043, or:
+ #
+ # http://www.sgi.com
+ #
+ # For further information regarding this notice, see:
+ #
+ # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ #
+ 
+ O_TARGET	:= kdb.o
+ export-objs	:= kdbmain.o kdb_io.o
+ obj-y		:= kdb_bt.o kdb_bp.o kdb_id.o kdbsupport.o gen-kdb_cmds.o kdbmain.o kdb_io.o
+ 
+ subdir-$(CONFIG_KDB_MODULES) := modules
+ obj-y += $(addsuffix /vmlinux-obj.o, $(subdir-y))
+ 
+ override CFLAGS := $(CFLAGS:%-pg=% )
+ 
+ EXTRA_CFLAGS += -I $(TOPDIR)/arch/$(ARCH)/kdb
+ 
+ include $(TOPDIR)/Rules.make
+ 
+ gen-kdb_cmds.c:	kdb_cmds Makefile
+ 	$(AWK) 'BEGIN {print "#include <linux/init.h>"} \
+ 		/^ *#/{next} \
+ 		/^[ \t]*$$/{next} \
+ 		{gsub(/"/, "\\\"", $$0); \
+ 		  print "static __initdata char kdb_cmd" cmds++ "[] = \"" $$0 "\\n\";"} \
+ 		END {print "char __initdata *kdb_cmds[] = {"; for (i = 0; i < cmds; ++i) {print "  kdb_cmd" i ","}; print("  0\n};");}' \
+ 		kdb_cmds > gen-kdb_cmds.c
diff -c -r -N console-os/kdb/modules/kdbm_pg.c console-os-kdb/kdb/modules/kdbm_pg.c
*** console-os/kdb/modules/kdbm_pg.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/modules/kdbm_pg.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,662 ----
+ /*
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/mm.h>
+ #include <linux/pagemap.h>
+ #include <linux/fs.h>
+ #include <linux/iobuf.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ #include <linux/blkdev.h>
+ #include <linux/ctype.h>
+ 
+ MODULE_AUTHOR("SGI");
+ MODULE_DESCRIPTION("Debug page information");
+ MODULE_LICENSE("GPL");
+ 
+ /* Standard Linux page stuff */
+ 
+ static char	*pg_flag_vals[] = {
+ 	"PG_locked", "PG_error", "PG_referenced", "PG_uptodate",
+ 	"PG_dirty", "PG_unused_5", "PG_lru", "PG_active",
+ 	"PG_slab", "PG_unused_9", "PG_skip", "PG_highmem",
+ 	"PG_checked", "PG_arch_1", "PG_reserved", "PG_launder",
+ 	NULL };
+ 
+ static char	*bh_state_vals[] = {
+ 	"Uptodate", "Dirty", "Lock", "Req",
+ 	"Mapped", "New", "Async", "Wait_IO",
+ 	"Launder", "Attached", "JBD",
+ 	/*XFS*/ "Delay",
+ 	"Private",
+ 	NULL };
+ 
+ static char *inode_flag_vals[] = {
+ 	"I_DIRTY_SYNC", "I_DIRTY_DATASYNC", "I_DIRTY_PAGES", "I_LOCK",
+ 	"I_FREEING", "I_CLEAR",
+ 	/*XFS*/ "I_NEW",
+ 	NULL };
+ 
+ static char	*map_flags(unsigned long flags, char *mapping[])
+ {
+ 	static	char	buffer[256];
+ 	int	index;
+ 	int	offset = 12;
+ 
+ 	buffer[0] = '\0';
+ 
+ 	for (index = 0; flags && mapping[index]; flags >>= 1, index++) {
+ 		if (flags & 1) {
+ 			if ((offset + strlen(mapping[index]) + 1) >= 80) {
+ 				strcat(buffer, "\n            ");
+ 				offset = 12;
+ 			} else if (offset > 12) {
+ 				strcat(buffer, " ");
+ 				offset++;
+ 			}
+ 			strcat(buffer, mapping[index]);
+ 			offset += strlen(mapping[index]);
+ 		}
+ 	}
+ 
+ 	return (buffer);
+ }
+ 
+ static char	*page_flags(unsigned long flags)
+ {
+ 	return(map_flags(flags, pg_flag_vals));
+ }
+ 
+ static int
+ kdbm_buffers(int argc, const char **argv, const char **envp,
+ 	struct pt_regs *regs)
+ {
+ 	struct buffer_head	bh;
+ 	unsigned long addr;
+ 	long	offset=0;
+ 	int nextarg;
+ 	int diag;
+ 	
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+ 	    (diag = kdb_getarea(bh, addr)))
+ 		return(diag);
+ 
+ 	kdb_printf("buffer_head at 0x%lx\n", addr);
+ 	kdb_printf("  next 0x%p bno %llu rsec %llu size %d dev 0x%x rdev 0x%x\n",
+ 		bh.b_next, (unsigned long long)bh.b_blocknr,
+ 		(unsigned long long)bh.b_rsector, bh.b_size,
+ 		bh.b_dev, bh.b_rdev);
+ 	kdb_printf("  count %d state 0x%lx [%s] b_list %d\n",
+ 		bh.b_count.counter, bh.b_state,
+ 		map_flags(bh.b_state, bh_state_vals), bh.b_list);
+ 	kdb_printf("  ftime %ld (%ld) b_next_free 0x%p b_prev_free 0x%p\n",
+ 		bh.b_flushtime, bh.b_flushtime - jiffies,
+ 		bh.b_next_free, bh.b_prev_free);
+ 	kdb_printf("  b_reqnext 0x%p b_data 0x%p\n",
+ 		bh.b_reqnext, bh.b_data);
+ 	kdb_printf("  b_inode_buffers.prev 0x%p b_inode_buffers.next 0x%p\n",
+ 		bh.b_inode_buffers.prev, bh.b_inode_buffers.next);
+ 	kdb_printf("  b_page 0x%p b_this_page 0x%p b_private 0x%p\n",
+ 		bh.b_page, bh.b_this_page, bh.b_private);
+ 	kdb_printf("  b_end_io ");
+ 	if (bh.b_end_io)
+ 		kdb_symbol_print(kdba_funcptr_value(bh.b_end_io), NULL, KDB_SP_VALUE);
+ 	else
+ 		kdb_printf("(NULL)");
+ 	kdb_printf("\n");
+ 
+ 	return 0;
+ }
+ 
+ static int
+ kdbm_page(int argc, const char **argv, const char **envp,
+ 	struct pt_regs *regs)
+ {
+ 	struct page	page;
+ 	unsigned long addr;
+ 	long	offset=0;
+ 	int nextarg;
+ 	int diag;
+ 	
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+ 	if (diag)
+ 		return diag;
+ 
+ 	if (addr < PAGE_OFFSET)
+ 		addr = (unsigned long) &mem_map[addr];
+ 
+ 	if ((diag = kdb_getarea(page, addr)))
+ 		return(diag);
+ 
+ 	kdb_printf("struct page at 0x%lx\n", addr);
+ 	kdb_printf("  next 0x%p prev 0x%p addr space 0x%p index %lu (offset 0x%x)\n",
+ 		   page.list.next, page.list.prev, page.mapping, page.index,
+ 		   (int)(page.index << PAGE_CACHE_SHIFT));
+ 	kdb_printf("  count %d flags %s\n",
+ 		   page.count.counter, page_flags(page.flags));
+ 	kdb_printf("  virtual 0x%p\n", page_address((struct page *)addr));
+ 	if (page.buffers)
+ 		kdb_printf("  buffers 0x%p\n", page.buffers);
+ 
+ 	return 0;
+ }
+ 
+ unsigned long
+ print_request(unsigned long addr)
+ {
+ 	struct request	rq;
+ 
+ 	if (kdb_getarea(rq, addr))
+ 		return(0);
+ 
+ 	kdb_printf("struct request at 0x%lx\n", addr);
+ 	kdb_printf("  rq_dev 0x%x cmd %d errors %d sector %llu nr_sectors %lu waiting 0x%p\n",
+ 			rq.rq_dev, rq.cmd, rq.errors,
+ 			(unsigned long long)rq.sector, rq.nr_sectors,
+ 			rq.waiting);
+ 
+ 	kdb_printf("  hsect %llu hnrsect %lu nrseg %u nrhwseg %u currnrsect %lu seq %d\n",
+ 			(unsigned long long)rq.hard_sector, rq.hard_nr_sectors,
+ 			rq.nr_segments, rq.nr_hw_segments,
+ 			rq.current_nr_sectors, rq.elevator_sequence);
+ 	kdb_printf("  ");
+ 	kdb_printf("bh 0x%p bhtail 0x%p req_q 0x%p\n\n",
+ 			rq.bh, rq.bhtail, rq.q);
+ 
+ 	return (unsigned long) rq.queue.next;
+ }
+ 
+ static int
+ kdbm_request(int argc, const char **argv, const char **envp,
+ 	struct pt_regs *regs)
+ {
+ 	long	offset=0;
+ 	unsigned long addr;
+ 	int nextarg;
+ 	int diag;
+ 	
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+ 	if (diag)
+ 		return diag;
+ 
+ 	print_request(addr);
+ 	return 0;
+ }
+ 
+ 
+ static int
+ kdbm_rqueue(int argc, const char **argv, const char **envp,
+ 	struct pt_regs *regs)
+ {
+ 	struct request_queue	rq;
+ 	unsigned long addr, head_addr, next;
+ 	long	offset=0;
+ 	int nextarg;
+ 	int i, diag;
+ 	
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+ 	    (diag = kdb_getarea(rq, addr)))
+ 		return(diag);
+ 
+ 	kdb_printf("struct request_queue at 0x%lx [%s]\n", addr,
+ 			rq.plugged ? "plugged" : "running");
+ 	kdb_printf(" read free %d list [0x%p, 0x%p]\n",
+ 			rq.rq[READ].count,
+ 			rq.rq[READ].free.prev,
+ 			rq.rq[READ].free.next);
+ 	kdb_printf(" write free %d list [0x%p, 0x%p]\n",
+ 			rq.rq[WRITE].count,
+ 			rq.rq[WRITE].free.prev,
+ 			rq.rq[WRITE].free.next);
+ 
+ 	i = 0;
+ 	next = (unsigned long)rq.queue_head.next;
+ 	head_addr = addr + offsetof(struct request_queue, queue_head);
+ 	kdb_printf(" request queue: %s\n", next == head_addr ?
+ 		"empty" : "");
+ 	while (next != head_addr) {
+ 		i++;
+ 		next = print_request(next);
+ 	}
+ 
+ 	if (i)
+ 		kdb_printf("%d requests found\n", i);
+ 
+ 	return 0;
+ }
+ 
+ 
+ static void
+ do_buffer(unsigned long addr)
+ {
+ 	struct buffer_head	bh;
+ 	
+ 	if (kdb_getarea(bh, addr))
+ 		return;
+ 
+ 	kdb_printf("bh 0x%lx bno %8llu [%s]\n", addr,
+ 		 (unsigned long long)bh.b_blocknr,
+ 		 map_flags(bh.b_state, bh_state_vals));
+ }
+ 
+ static int
+ kdbm_inode_pages(int argc, const char **argv, const char **envp,
+ 	struct pt_regs *regs)
+ {
+ 	struct inode *inode = NULL;
+ 	struct address_space *ap = NULL;
+ 	unsigned long addr, addr1 = 0;
+ 	long offset=0;
+ 	int nextarg;
+ 	int diag;
+ 	int which=0;
+ 
+ 	struct list_head *head, *curr;
+ 	
+ 	if (argc < 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+ 	if (diag)
+ 		goto out;
+ 
+ 	if (argc == 2) {
+ 		nextarg = 2;
+ 		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr1,
+ 					&offset, NULL, regs);
+ 		if (diag)
+ 			goto out;
+ 		kdb_printf("Looking for page index 0x%lx ... \n", addr1);
+ 	}
+ 
+ 	if (!(inode = kmalloc(sizeof(*inode), GFP_ATOMIC))) {
+ 		kdb_printf("kdbm_inode_pages: cannot kmalloc inode\n");
+ 		goto out;
+ 	}
+ 	if (!(ap = kmalloc(sizeof(*ap), GFP_ATOMIC))) {
+ 		kdb_printf("kdbm_inode_pages: cannot kmalloc ap\n");
+ 		goto out;
+ 	}
+ 	if ((diag = kdb_getarea(*inode, addr)))
+ 		goto out;
+ 	if (!inode->i_mapping) {
+ 		kdb_printf("inode has no mapping\n");
+ 		goto out;
+ 	}
+ 	if ((diag = kdb_getarea(*ap, (unsigned long) inode->i_mapping)))
+ 		goto out;
+ 	
+  again:
+ 	if (which == 0){
+ 	  which=1;
+ 	  head = &inode->i_mapping->clean_pages;
+ 	  kdb_printf("CLEAN  page_struct   index  cnt  flags\n");
+ 	} else if (which == 1) {
+ 	  which=2;
+ 	  head = &inode->i_mapping->dirty_pages;
+ 	  kdb_printf("DIRTY  page_struct   index  cnt  flags\n");
+ 	} else if (which == 2) {
+ 	  which=3;
+ 	  head = &inode->i_mapping->locked_pages;
+ 	  kdb_printf("LOCKED page_struct   index  cnt  flags\n");
+ 	} else {
+ 	  goto out;
+ 	}
+ 	
+ 	curr = head->next;
+ 	while (curr != head) {
+ 		struct page 	 page;
+ 		struct list_head curr_struct;
+ 
+ 		addr = (unsigned long) list_entry(curr, struct page, list);
+ 		if ((diag = kdb_getarea(page, addr)))
+ 			goto out;
+ 
+ 		if (!addr1 || page.index == addr1 ||
+ 			(addr1 == -1 && (page.flags & ( 1 << PG_locked))))
+ 		{
+ 			kdb_printf("    0x%lx    %6lu    %5d    0x%lx ",
+ 				addr, page.index, page.count.counter,
+ 				page.flags);
+ 			if (page.buffers)
+ 				do_buffer((unsigned long) page.buffers);
+ 			else
+ 				kdb_printf("bh [NULL]\n");
+ 		}
+ 
+ 		if ((diag = kdb_getarea(curr_struct, (unsigned long) curr)))
+ 			goto out;
+ 
+ 		curr = curr_struct.next;
+ 	}
+ 	goto again;
+  out:
+ 	if (inode)
+ 		kfree(inode);
+ 	if (ap)
+ 		kfree(ap);
+ 	return diag;
+ }
+ 
+ static int
+ kdbm_inode(int argc, const char **argv, const char **envp,
+ 	struct pt_regs *regs)
+ {
+ 	struct inode *inode = NULL;
+ 	unsigned long addr;
+ 	unsigned char *iaddr;
+ 	long	offset=0;
+ 	int nextarg;
+ 	int diag;
+ 	
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+ 		goto out;
+ 	if (!(inode = kmalloc(sizeof(*inode), GFP_ATOMIC))) {
+ 		kdb_printf("kdbm_inode: cannot kmalloc inode\n");
+ 		goto out;
+ 	}
+ 	if ((diag = kdb_getarea(*inode, addr)))
+ 		goto out;
+ 
+ 	kdb_printf("struct inode at  0x%lx\n", addr);
+ 
+ 	kdb_printf(" i_ino = %lu i_count = %u i_dev = 0x%x i_size %Ld\n",
+ 					inode->i_ino, atomic_read(&inode->i_count),
+ 					inode->i_dev, inode->i_size);
+ 
+ 	kdb_printf(" i_mode = 0%o  i_nlink = %d  i_rdev = 0x%x\n",
+ 					inode->i_mode, inode->i_nlink,
+ 					inode->i_rdev);
+ 
+ 	kdb_printf(" i_hash.nxt = 0x%p i_hash.prv = 0x%p\n",
+ 		list_entry(inode->i_hash.next, struct inode, i_hash),
+ 		list_entry(inode->i_hash.prev, struct inode, i_hash));
+ 
+ 	kdb_printf(" i_list.nxt = 0x%p i_list.prv = 0x%p\n",
+ 		list_entry(inode->i_list.next, struct inode, i_list),
+ 		list_entry(inode->i_list.prev, struct inode, i_list));
+ 
+ 	kdb_printf(" i_dentry.nxt = 0x%p i_dentry.prv = 0x%p\n",
+ 		list_entry(inode->i_dentry.next, struct dentry, d_alias),
+ 		list_entry(inode->i_dentry.prev, struct dentry, d_alias));
+ 
+ 	kdb_printf(" i_dirty_buffers.nxt = 0x%p i_dirty_buffers.prv = 0x%p\n",
+ 		list_entry(inode->i_dirty_buffers.next,
+ 				struct buffer_head, b_inode_buffers),
+ 		list_entry(inode->i_dirty_buffers.prev,
+ 				struct buffer_head, b_inode_buffers));
+ 
+ 	kdb_printf(" i_dirty_data_buffers.nxt = 0x%p i_dirty_data_buffers.prv = 0x%p\n",
+ 		list_entry(inode->i_dirty_data_buffers.next,
+ 				struct buffer_head, b_inode_buffers),
+ 		list_entry(inode->i_dirty_data_buffers.prev,
+ 				struct buffer_head, b_inode_buffers));
+ 
+ 	kdb_printf(" i_sb = 0x%p i_op = 0x%p i_data = 0x%lx nrpages = %lu\n",
+ 					inode->i_sb, inode->i_op,
+ 					addr + offsetof(struct inode, i_data),
+ 					inode->i_data.nrpages);
+ 	kdb_printf(" i_fop= 0x%p i_flock = 0x%p i_mapping = 0x%p\n",
+ 			   inode->i_fop, inode->i_flock, inode->i_mapping);
+ 	
+ 	kdb_printf(" i_flags 0x%x i_state 0x%lx [%s]",
+ 			   inode->i_flags, inode->i_state,
+ 			   map_flags(inode->i_state, inode_flag_vals));
+ 
+ 	iaddr  = (char *)addr;
+ 	iaddr += offsetof(struct inode, u);
+ 
+ 	kdb_printf("  fs specific info @ 0x%p\n", iaddr);
+ out:
+ 	if (inode)
+ 		kfree(inode);
+ 	return diag;
+ }
+ 
+ static int
+ kdbm_sb(int argc, const char **argv, const char **envp,
+ 	struct pt_regs *regs)
+ {
+ 	struct super_block *sb = NULL;
+ 	unsigned long addr;
+ 	long	offset=0;
+ 	int nextarg;
+ 	int diag;
+ 	
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+ 		goto out;
+ 	if (!(sb = kmalloc(sizeof(*sb), GFP_ATOMIC))) {
+ 		kdb_printf("kdbm_sb: cannot kmalloc sb\n");
+ 		goto out;
+ 	}
+ 	if ((diag = kdb_getarea(*sb, addr)))
+ 		goto out;
+ 
+ 	kdb_printf("struct super_block at  0x%lx\n", addr);
+ 	kdb_printf(" s_dev 0x%x blocksize 0x%lx\n", sb->s_dev, sb->s_blocksize);
+ 	kdb_printf(" s_flags 0x%lx s_root 0x%p\n", sb->s_flags, sb->s_root);
+ 	kdb_printf(" s_dirt %d s_dirty.next 0x%p s_dirty.prev 0x%p\n",
+ 		sb->s_dirt, sb->s_dirty.next, sb->s_dirty.prev);
+ 	kdb_printf(" s_locked_inodes.next 0x%p s_locked_inodes.prev 0x%p\n",
+ 		sb->s_locked_inodes.next, sb->s_locked_inodes.prev);
+ out:
+ 	if (sb)
+ 		kfree(sb);
+ 	return diag;
+ }
+ 
+ 
+ static int
+ kdbm_kiobuf(int argc, const char **argv, const char **envp,
+ 	struct pt_regs *regs)
+ {
+ 	struct kiobuf *kiobuf = NULL;
+ 	struct page page;
+ 	struct page **page_array = NULL;
+ 	unsigned long addr;
+ 	long offset=0;
+ 	int nextarg;
+ 	int diag;
+ 	int i, s;
+ 	
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+ 		goto out;
+ 	if (!(kiobuf = kmalloc(sizeof(*kiobuf), GFP_ATOMIC))) {
+ 		kdb_printf("kdbm_kiobuf: cannot kmalloc kiobuf\n");
+ 		goto out;
+ 	}
+ 	if ((diag = kdb_getarea(*kiobuf, addr)))
+ 		goto out;
+ 
+ 	kdb_printf("kiobuf at 0x%lx\n", addr);
+ 	kdb_printf("  nr_pages %d array_len %d offset 0x%x length 0x%x\n",
+ 		   kiobuf->nr_pages, kiobuf->array_len,
+ 		   kiobuf->offset, kiobuf->length);
+ 	kdb_printf("  errno %d\n", kiobuf->errno);
+ 	kdb_printf("    page_struct   page_addr     cnt  flags\n");
+ 	s = kiobuf->nr_pages*sizeof(*page_array);
+ 	if (!(page_array = kmalloc(s, GFP_ATOMIC))) {
+ 		kdb_printf("kdbm_kiobuf: cannot kmalloc page_array\n");
+ 		goto out;
+ 	}
+ 	if ((diag = kdb_getarea_size(page_array, (unsigned long)kiobuf->maplist, s)))
+ 		goto out;
+ 	kiobuf->maplist = page_array;
+ 	for (i = 0; i < kiobuf->nr_pages; i++) {
+ 		if ((diag = kdb_getarea(page, (unsigned long) kiobuf->maplist[i])))
+ 			goto out;
+ 		kdb_printf("    0x%p",  kiobuf->maplist[i]);
+ 		kdb_printf("    0x%p", page_address(kiobuf->maplist[i]));
+ 		kdb_printf("    %d    0x%lx\n", page.count.counter, page.flags);
+ 	}
+ out:
+ 	if (kiobuf)
+ 		kfree(kiobuf);
+ 	if (page_array)
+ 		kfree(page_array);
+ 	return diag;
+ }
+ 
+ #ifdef	CONFIG_X86
+ /* According to Steve Lord, this code is ix86 specific.  Patches to extend it to
+  * other architectures will be greatefully accepted.
+  */
+ static int
+ kdbm_memmap(int argc, const char **argv, const char **envp,
+         struct pt_regs *regs)
+ {
+ 	struct page	page;
+ 	int		i, page_count;
+ 	int		slab_count = 0;
+ 	int		dirty_count = 0;
+ 	int		locked_count = 0;
+ 	int		page_counts[9];
+ 	int		buffered_count = 0;
+ #ifdef buffer_delay
+ 	int		delay_count = 0;
+ #endif
+ 	int		diag;
+ 	unsigned long addr;
+ 
+ 	addr = (unsigned long)mem_map;
+ 	page_count = max_mapnr;
+ 	memset(page_counts, 0, sizeof(page_counts));
+ 
+ 	for (i = 0; i < page_count; i++) {
+ 		if ((diag = kdb_getarea(page, addr)))
+ 			return(diag);
+ 		addr += sizeof(page);
+ 
+ 		if (PageSlab(&page))
+ 			slab_count++;
+ 		if (PageDirty(&page))
+ 			dirty_count++;
+ 		if (PageLocked(&page))
+ 			locked_count++;
+ 		if (page.count.counter < 8)
+ 			page_counts[page.count.counter]++;
+ 		else
+ 			page_counts[8]++;
+ 		if (page.buffers) {
+ 			buffered_count++;
+ #ifdef buffer_delay
+ 			if (buffer_delay(page.buffers))
+ 				delay_count++;
+ #endif
+ 		}
+ 
+ 	}
+ 
+ 	kdb_printf("  Total pages:      %6d\n", page_count);
+ 	kdb_printf("  Slab pages:       %6d\n", slab_count);
+ 	kdb_printf("  Dirty pages:      %6d\n", dirty_count);
+ 	kdb_printf("  Locked pages:     %6d\n", locked_count);
+ 	kdb_printf("  Buffer pages:     %6d\n", buffered_count);
+ #ifdef buffer_delay
+ 	kdb_printf("  Delalloc pages:   %6d\n", delay_count);
+ #endif
+ 	for (i = 0; i < 8; i++) {
+ 		kdb_printf("  %d page count:     %6d\n",
+ 			i, page_counts[i]);
+ 	}
+ 	kdb_printf("  high page count:  %6d\n", page_counts[8]);
+ 	return 0;
+ }
+ #endif	/* CONFIG_X86 */
+ 
+ static int __init kdbm_pg_init(void)
+ {
+ 	kdb_register("kiobuf", kdbm_kiobuf, "<vaddr>", "Display kiobuf", 0);
+ 	kdb_register("page", kdbm_page, "<vaddr>", "Display page", 0);
+ 	kdb_register("inode", kdbm_inode, "<vaddr>", "Display inode", 0);
+ 	kdb_register("sb", kdbm_sb, "<vaddr>", "Display super_block", 0);
+ 	kdb_register("bh", kdbm_buffers, "<buffer head address>", "Display buffer", 0);
+ 	kdb_register("inode_pages", kdbm_inode_pages, "<inode *>", "Display pages in an inode", 0);
+ 	kdb_register("req", kdbm_request, "<vaddr>", "dump request struct", 0);
+ 	kdb_register("rqueue", kdbm_rqueue, "<vaddr>", "dump request queue", 0);
+ #ifdef	CONFIG_X86
+ 	kdb_register("memmap", kdbm_memmap, "", "page table summary", 0);
+ #endif
+ 
+ 	return 0;
+ }
+ 
+ 
+ static void __exit kdbm_pg_exit(void)
+ {
+ 	kdb_unregister("kiobuf");
+ 	kdb_unregister("page");
+ 	kdb_unregister("inode");
+ 	kdb_unregister("sb");
+ 	kdb_unregister("bh");
+ 	kdb_unregister("inode_pages");
+ 	kdb_unregister("req");
+ 	kdb_unregister("rqueue");
+ #ifdef	CONFIG_X86
+ 	kdb_unregister("memmap");
+ #endif
+ }
+ 
+ module_init(kdbm_pg_init)
+ module_exit(kdbm_pg_exit)
diff -c -r -N console-os/kdb/modules/kdbm_task.c console-os-kdb/kdb/modules/kdbm_task.c
*** console-os/kdb/modules/kdbm_task.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/modules/kdbm_task.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,209 ----
+ /*
+  * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/blkdev.h>
+ #include <linux/types.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/mm.h>
+ #include <linux/sched.h>
+ #include <asm/signal.h>
+ 
+ MODULE_AUTHOR("SGI");
+ MODULE_DESCRIPTION("Debug struct task and sigset information");
+ MODULE_LICENSE("GPL");
+ 
+ #ifdef __KDB_HAVE_NEW_SCHEDULER
+ static char *
+ kdb_cpus_allowed_string(struct task_struct *tp)
+ {
+ #ifndef CPUMASK_WORDCOUNT
+ 	static char maskbuf[BITS_PER_LONG/4+8];
+ 	sprintf(maskbuf, "0x%0lx", tp->cpus_allowed);
+ #else
+ 	int i, j;
+ 	static char maskbuf[CPUMASK_WORDCOUNT * BITS_PER_LONG / 4 + 8];
+ 
+ 	strcpy(maskbuf, "0x");
+ 	for (j=2, i=CPUMASK_WORDCOUNT-1; i >= 0; i--) {
+ 		j += sprintf(maskbuf + j, "%0lx", tp->cpus_allowed[i]);
+ 	}
+ #endif /* CPUMASK_WORDCOUNT */
+ 
+ 	return maskbuf;
+ }
+ #endif	/* __KDB_HAVE_NEW_SCHEDULER */
+ 
+ static int
+ kdbm_task(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	unsigned long	addr;
+ 	long		offset=0;
+ 	int		nextarg;
+ 	int		e = 0;
+ 	struct task_struct *tp = NULL;
+ 	
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((e = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) != 0)
+ 		return(e);
+ 
+ 	if (!(tp = kmalloc(sizeof(*tp), GFP_ATOMIC))) {
+ 	    kdb_printf("%s: cannot kmalloc tp\n", __FUNCTION__);
+ 	    goto out;
+ 	}
+ 	if ((e = kdb_getarea(*tp, addr))) {
+ 	    kdb_printf("%s: invalid task address\n", __FUNCTION__);
+ 	    goto out;
+ 	}
+ 
+ 	kdb_printf(
+ 	    "struct task at 0x%p, pid=%d flags=0x%lx state=%ld comm=\"%s\"\n",
+ 	    tp, tp->pid, tp->flags, tp->state, tp->comm);
+ 
+ 	kdb_printf("  cpu=%d policy=%lu ", kdb_process_cpu(tp), tp->policy);
+ #ifdef __KDB_HAVE_NEW_SCHEDULER
+ 	kdb_printf(
+ 	    "prio=%d static_prio=%d cpus_allowed=%s",
+ 	    tp->prio, tp->static_prio, kdb_cpus_allowed_string(tp));
+ #else
+ 	kdb_printf(
+ 	    "cpus_runnable=%lx cpus_allowed=%lx",
+ 	    tp->cpus_runnable, tp->cpus_allowed);
+ #endif
+ 	kdb_printf(" &thread=0x%p\n", &tp->thread);
+ 
+ 	kdb_printf("  need_resched=%ld ", tp->need_resched);
+ #ifdef __KDB_HAVE_NEW_SCHEDULER
+ 	kdb_printf(
+ 	    "sleep_timestamp=%lu time_slice=%u",
+ 	    tp->sleep_timestamp, tp->time_slice);
+ #else
+ 	kdb_printf(
+ 	    "counter=%ld nice=%ld",
+ 	    tp->counter, tp->nice);
+ #endif
+ 	kdb_printf(" lock_depth=%d\n", tp->lock_depth);
+ 
+ 	kdb_printf(
+ 	    "  fs=0x%p files=0x%p mm=0x%p nr_local_pages=%u\n",
+ 	    tp->fs, tp->files, tp->mm, tp->nr_local_pages);
+ 
+ 	kdb_printf(
+ 	    "  uid=%d euid=%d suid=%d fsuid=%d gid=%d egid=%d sgid=%d fsgid=%d\n",
+ 	    tp->uid, tp->euid, tp->suid, tp->fsuid, tp->gid, tp->egid, tp->sgid, tp->fsgid);
+ 
+ 	kdb_printf(
+ 	    "  user=0x%p locks=%d semundo=0x%p semsleeping=0x%p\n",
+ 	    tp->user, tp->locks, tp->semundo, tp->semsleeping);
+ 
+ 	kdb_printf(
+ 	    "  sig=0x%p &blocked=0x%p &sigpending=0x%p\n",
+ 	    tp->sig, &tp->blocked, &tp->sigpending);
+ 
+ 	kdb_printf(
+ 	    "  times.utime=%ld times_stime=%ld times_cutime=%ld times_cstime=%ld\n",
+ 	    tp->times.tms_utime, tp->times.tms_stime, tp->times.tms_cutime,
+ 	    tp->times.tms_cstime);
+ 
+ out:
+ 	if (tp)
+ 	    kfree(tp);
+ 	return e;
+ }
+ 
+ static int
+ kdbm_sigset(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	sigset_t	*sp = NULL;
+ 	unsigned long	addr;
+ 	long		offset=0;
+ 	int		nextarg;
+ 	int		e = 0;
+ 	int		i;
+ 	char		fmt[32];
+ 	
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ #ifndef _NSIG_WORDS
+         kdb_printf("unavailable on this platform, _NSIG_WORDS not defined.\n");
+ #else
+ 	nextarg = 1;
+ 	if ((e = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) != 0)
+ 		return(e);
+ 
+ 	if (!(sp = kmalloc(sizeof(*sp), GFP_ATOMIC))) {
+ 	    kdb_printf("%s: cannot kmalloc sp\n", __FUNCTION__);
+ 	    goto out;
+ 	}
+ 	if ((e = kdb_getarea(*sp, addr))) {
+ 	    kdb_printf("%s: invalid sigset address\n", __FUNCTION__);
+ 	    goto out;
+ 	}
+ 
+ 	sprintf(fmt, "[%%d]=0x%%0%dlx ", (int)sizeof(sp->sig[0])*2);
+ 	kdb_printf("sigset at 0x%p : ", sp);
+ 	for (i=_NSIG_WORDS-1; i >= 0; i--) {
+ 	    if (i == 0 || sp->sig[i]) {
+ 		kdb_printf(fmt, i, sp->sig[i]);
+ 	    }
+ 	}
+         kdb_printf("\n");
+ #endif /* _NSIG_WORDS */
+ 
+ out:
+ 	if (sp)
+ 	    kfree(sp);
+ 	return e;
+ }
+ 
+ static int __init kdbm_task_init(void)
+ {
+ 	kdb_register("task", kdbm_task, "<vaddr>", "Display task_struct", 0);
+ 	kdb_register("sigset", kdbm_sigset, "<vaddr>", "Display sigset_t", 0);
+ 	
+ 	return 0;
+ }
+ 
+ static void __exit kdbm_task_exit(void)
+ {
+ 	kdb_unregister("task");
+ 	kdb_unregister("sigset");
+ }
+ 
+ kdb_module_init(kdbm_task_init)
+ kdb_module_exit(kdbm_task_exit)
diff -c -r -N console-os/kdb/modules/kdbm_vm.c console-os-kdb/kdb/modules/kdbm_vm.c
*** console-os/kdb/modules/kdbm_vm.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/modules/kdbm_vm.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,696 ----
+ /*
+  * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+  * Mountain View, CA  94043, or:
+  *
+  * http://www.sgi.com
+  *
+  * For further information regarding this notice, see:
+  *
+  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+  */
+ 
+ #include <linux/blkdev.h>
+ #include <linux/types.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/mm.h>
+ 
+ #include <scsi.h>
+ #include <hosts.h>
+ 
+ MODULE_AUTHOR("SGI");
+ MODULE_DESCRIPTION("Debug VM information");
+ MODULE_LICENSE("GPL");
+ 
+ struct __vmflags {
+ 	unsigned long mask;
+ 	char *name;
+ } vmflags[] = {
+ 	{ VM_READ, "READ" },
+ 	{ VM_WRITE, "WRITE" },
+ 	{ VM_EXEC, "EXEC" },
+ 	{ VM_SHARED, "SHARED" },
+ 	{ VM_MAYREAD, "MAYREAD" },
+ 	{ VM_MAYWRITE, "MAYWRITE" },
+ 	{ VM_MAYEXEC, "MAYEXEC" },
+ 	{ VM_MAYSHARE, "MAYSHARE" },
+ 	{ VM_GROWSDOWN, "GROWSDOWN" },
+ 	{ VM_GROWSUP, "GROWSUP" },
+ 	{ VM_SHM, "SHM" },
+ 	{ VM_DENYWRITE, "DENYWRITE" },
+ 	{ VM_EXECUTABLE, "EXECUTABLE" },
+ 	{ VM_LOCKED, "LOCKED" },
+ 	{ VM_IO , "IO " },
+ 	{ 0, "" }
+ };
+ 
+ static int
+ kdbm_print_vm(struct vm_area_struct *vp, unsigned long addr, int verbose_flg)
+ {
+ 	struct __vmflags *tp;
+ 
+ 	kdb_printf("struct vm_area_struct at 0x%lx for %d bytes\n",
+ 		   addr, (int) sizeof (struct vm_area_struct));
+ 
+ 	kdb_printf("vm_start = 0x%p   vm_end = 0x%p\n", (void *) vp->vm_start,
+ 		   (void *) vp->vm_end);
+ 	kdb_printf("vm_page_prot = 0x%lx\n", pgprot_val(vp->vm_page_prot));
+ 
+ 	kdb_printf("vm_flags: ");
+ 	for (tp = vmflags; tp->mask; tp++) {
+ 		if (vp->vm_flags & tp->mask) {
+ 			kdb_printf(" %s", tp->name);
+ 		}
+ 	}
+ 	kdb_printf("\n");
+ 
+ 	if (!verbose_flg)
+ 		return 0;
+ 
+ 	kdb_printf("vm_mm = 0x%p\n", (void *) vp->vm_mm);
+ 	kdb_printf("vm_next = 0x%p\n", (void *) vp->vm_next);
+ 	kdb_printf("vm_next_share = 0x%p\n", (void *) vp->vm_next_share);
+ 	kdb_printf("vm_pprev_share = 0x%p\n", (void *) vp->vm_pprev_share);
+ 	kdb_printf("vm_ops = 0x%p\n", (void *) vp->vm_ops);
+ 	if (vp->vm_ops != NULL) {
+ 		kdb_printf("vm_ops->open = 0x%p\n", vp->vm_ops->open);
+ 		kdb_printf("vm_ops->close = 0x%p\n", vp->vm_ops->close);
+ 		kdb_printf("vm_ops->nopage = 0x%p\n", vp->vm_ops->nopage);
+ #ifdef HAVE_VMOP_MPROTECT
+ 		kdb_printf("vm_ops->mprotect = 0x%p\n", vp->vm_ops->mprotect);
+ #endif
+ 	}
+ 	kdb_printf("vm_pgoff = 0x%lx\n", vp->vm_pgoff);
+ 	kdb_printf("vm_file = 0x%p\n", (void *) vp->vm_file);
+ 	kdb_printf("vm_private_data = 0x%p\n", vp->vm_private_data);
+ 
+ 	return 0;
+ }
+ 
+ static int
+ kdbm_print_vmp(struct vm_area_struct *vp, int verbose_flg)
+ {
+ 	struct __vmflags *tp;
+ 
+ 	if (verbose_flg) {
+ 		kdb_printf("0x%lx:  ", (unsigned long) vp);
+ 	}
+ 
+ 	kdb_printf("0x%p  0x%p ", (void *) vp->vm_start, (void *) vp->vm_end);
+ 
+ 	for (tp = vmflags; tp->mask; tp++) {
+ 		if (vp->vm_flags & tp->mask) {
+ 			kdb_printf(" %s", tp->name);
+ 		}
+ 	}
+ 	kdb_printf("\n");
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdbm_vm
+  *
+  *     This function implements the 'vm' command.  Print a vm_area_struct.
+  *
+  *     vm [-v] <address>               Print vm_area_struct at <address>
+  *     vmp [-v] <pid>                  Print all vm_area_structs for <pid>
+  */
+ 
+ static int
+ kdbm_vm(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	unsigned long addr;
+ 	long offset = 0;
+ 	int nextarg;
+ 	int diag;
+ 	int verbose_flg = 0;
+ 
+ 	if (argc == 2) {
+ 		if (strcmp(argv[1], "-v") != 0) {
+ 			return KDB_ARGCOUNT;
+ 		}
+ 		verbose_flg = 1;
+ 	} else if (argc != 1) {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 
+ 	if (strcmp(argv[0], "vmp") == 0) {
+ 		struct task_struct *tp;
+ 		struct vm_area_struct *vp;
+ 		pid_t pid;
+ 
+ 		if ((diag = kdbgetularg(argv[argc], (unsigned long *) &pid)))
+ 			return diag;
+ 
+ 		for_each_task(tp) {
+ 			if (tp->pid == pid) {
+ 				if (tp->mm != NULL) {
+ 					if (verbose_flg)
+ 						kdb_printf
+ 						    ("vm_area_struct       ");
+ 					kdb_printf
+ 					    ("vm_start            vm_end              vm_flags\n");
+ 					vp = tp->mm->mmap;
+ 					while (vp != NULL) {
+ 						kdbm_print_vmp(vp, verbose_flg);
+ 						vp = vp->vm_next;
+ 					}
+ 				}
+ 				return 0;
+ 			}
+ 		}
+ 
+ 		kdb_printf("No process with pid == %d found\n", pid);
+ 
+ 	} else {
+ 		struct vm_area_struct v;
+ 
+ 		nextarg = argc;
+ 		if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset,
+ 					  NULL, regs))
+ 		    || (diag = kdb_getarea(v, addr)))
+ 			return (diag);
+ 
+ 		kdbm_print_vm(&v, addr, verbose_flg);
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ static int
+ kdbm_print_pte(pte_t * pte)
+ {
+ 	kdb_printf("0x%lx (", (unsigned long) pte_val(*pte));
+ 
+ 	if (pte_present(*pte)) {
+ 		if (pte_exec(*pte))
+ 			kdb_printf("X");
+ 		if (pte_write(*pte))
+ 			kdb_printf("W");
+ 		if (pte_read(*pte))
+ 			kdb_printf("R");
+ 		if (pte_young(*pte))
+ 			kdb_printf("A");
+ 		if (pte_dirty(*pte))
+ 			kdb_printf("D");
+ 
+ 	} else {
+ 		kdb_printf("OFFSET=0x%lx ", SWP_OFFSET(pte_to_swp_entry(*pte)));
+ 		kdb_printf("TYPE=0x%lx", SWP_TYPE(pte_to_swp_entry(*pte)));
+ 	}
+ 
+ 	kdb_printf(")");
+ 
+ 	/* final newline is output by caller of kdbm_print_pte() */
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * kdbm_pte
+  *
+  *     This function implements the 'pte' command.  Print all pte_t structures
+  *     that map to the given virtual address range for the given process.
+  *
+  *     pte <pid> <address> [<nbytes>]   Print all pte_t structures for virtual
+  *                                      <address> in address space of <pid>
+  */
+ 
+ static int
+ kdbm_pte(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	unsigned long addr;
+ 	unsigned long nbytes = 1;
+ 	long npgs;
+ 	int diag;
+ 	int found;
+ 	pid_t pid;
+ 	struct task_struct *tp;
+ 	pgd_t *pgd;
+ 	pmd_t *pmd;
+ 	pte_t *pte;
+ 
+ 	if (argc < 2 || argc > 3) {
+ 		return KDB_ARGCOUNT;
+ 	}
+ 
+ 	if ((diag = kdbgetularg(argv[1], (unsigned long *) &pid))) {
+ 		return diag;
+ 	}
+ 
+ 	found = 0;
+ 	for_each_task(tp) {
+ 		if (tp->pid == pid) {
+ 			if (tp->mm != NULL) {
+ 				found = 1;
+ 				break;
+ 			}
+ 			kdb_printf("task structure's mm field is NULL\n");
+ 			return 0;
+ 		}
+ 	}
+ 
+ 	if (!found) {
+ 		kdb_printf("No process with pid == %d found\n", pid);
+ 		return 0;
+ 	}
+ 
+ 	if ((diag = kdbgetularg(argv[2], &addr))) {
+ 		return diag;
+ 	}
+ 
+ 	if (argc == 3) {
+ 		if ((diag = kdbgetularg(argv[3], &nbytes))) {
+ 			return diag;
+ 		}
+ 	}
+ 
+ 	kdb_printf("vaddr              pte\n");
+ 
+ 	npgs = ((((addr & ~PAGE_MASK) + nbytes) + ~PAGE_MASK) >> PAGE_SHIFT);
+ 	while (npgs-- > 0) {
+ 
+ 		kdb_printf("0x%p ", (void *) (addr & PAGE_MASK));
+ 
+ 		pgd = pgd_offset(tp->mm, addr);
+ 		if (pgd_present(*pgd)) {
+ 			pmd = pmd_offset(pgd, addr);
+ 			if (pmd_present(*pmd)) {
+ 				pte = pte_offset(pmd, addr);
+ 				if (pte_present(*pte)) {
+ 					kdbm_print_pte(pte);
+ 				}
+ 			}
+ 		}
+ 
+ 		kdb_printf("\n");
+ 		addr += PAGE_SIZE;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ static int
+ kdbm_fp(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	struct file   f;
+ 	struct inode *i = NULL;
+ 	struct dentry d;
+ 	int	      nextarg;
+ 	unsigned long addr;
+ 	long	      offset;
+ 	int	      diag;
+ 
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+ 	    (diag = kdb_getarea(f, addr)) ||
+ 	    (diag = kdb_getarea(d, (unsigned long)f.f_dentry)))
+ 		goto out;
+ 	if (!(i = kmalloc(sizeof(*i), GFP_ATOMIC))) {
+ 		kdb_printf("kdbm_fp: cannot kmalloc inode\n");
+ 		goto out;
+ 	}
+ 	if ((diag = kdb_getarea(i, (unsigned long)d.d_inode)))
+ 		goto out;
+ 	
+ 	kdb_printf("name.name 0x%p  name.len  %d\n",
+ 		    d.d_name.name, d.d_name.len);
+ 
+ 	kdb_printf("File Pointer at 0x%lx\n", addr);
+ 
+ 	kdb_printf(" f_list.nxt = 0x%p f_list.prv = 0x%p\n",
+ 					f.f_list.next, f.f_list.prev);
+ 
+ 	kdb_printf(" f_dentry = 0x%p f_op = 0x%p\n",
+ 					f.f_dentry, f.f_op);
+ 
+ 	kdb_printf(" f_count = %d f_flags = 0x%x f_mode = 0x%x\n",
+ 					f.f_count.counter, f.f_flags, f.f_mode);
+ 
+ 	kdb_printf(" f_pos = %Ld f_reada = %ld f_ramax = %ld\n",
+ 					f.f_pos, f.f_reada, f.f_ramax);
+ 
+ 	kdb_printf(" f_raend = %ld f_ralen = %ld f_rawin = %ld\n\n",
+ 					f.f_raend, f.f_ralen, f.f_rawin);
+ 
+ 
+ 	kdb_printf("\nDirectory Entry at 0x%p\n", f.f_dentry);
+ 	kdb_printf(" d_name.len = %d d_name.name = 0x%p>\n",
+ 					d.d_name.len, d.d_name.name);
+ 
+ 	kdb_printf(" d_count = %d d_flags = 0x%x d_inode = 0x%p\n",
+ 					atomic_read(&d.d_count), d.d_flags, d.d_inode);
+ 
+ 	kdb_printf(" d_hash.nxt = 0x%p d_hash.prv = 0x%p\n",
+ 					d.d_hash.next, d.d_hash.prev);
+ 
+ 	kdb_printf(" d_lru.nxt = 0x%p d_lru.prv = 0x%p\n",
+ 					d.d_lru.next, d.d_lru.prev);
+ 
+ 	kdb_printf(" d_child.nxt = 0x%p d_child.prv = 0x%p\n",
+ 					d.d_child.next, d.d_child.prev);
+ 
+ 	kdb_printf(" d_subdirs.nxt = 0x%p d_subdirs.prv = 0x%p\n",
+ 					d.d_subdirs.next, d.d_subdirs.prev);
+ 
+ 	kdb_printf(" d_alias.nxt = 0x%p d_alias.prv = 0x%p\n",
+ 					d.d_alias.next, d.d_alias.prev);
+ 
+ 	kdb_printf(" d_op = 0x%p d_sb = 0x%p\n\n",
+ 					d.d_op, d.d_sb);
+ 
+ 
+ 	kdb_printf("\nInode Entry at 0x%p\n", d.d_inode);
+ 
+ 	kdb_printf(" i_mode = 0%o  i_nlink = %d  i_rdev = 0x%x\n",
+ 					i->i_mode, i->i_nlink, i->i_rdev);
+ 
+ 	kdb_printf(" i_ino = %ld i_count = %d i_dev = 0x%x\n",
+ 					i->i_ino, atomic_read(&i->i_count), i->i_dev);
+ 
+ 	kdb_printf(" i_hash.nxt = 0x%p i_hash.prv = 0x%p\n",
+ 					i->i_hash.next, i->i_hash.prev);
+ 
+ 	kdb_printf(" i_list.nxt = 0x%p i_list.prv = 0x%p\n",
+ 					i->i_list.next, i->i_list.prev);
+ 
+ 	kdb_printf(" i_dentry.nxt = 0x%p i_dentry.prv = 0x%p\n",
+ 					i->i_dentry.next, i->i_dentry.prev);
+ 
+ out:
+ 	if (i)
+ 		kfree(i);
+ 	return diag;
+ }
+ 
+ static int
+ kdbm_fl(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	struct file_lock  fl;
+ 	int               nextarg;
+ 	unsigned long     addr;
+ 	long              offset;
+ 	int               diag;
+ 
+ 
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+ 		(diag = kdb_getarea(fl, addr)))
+ 			return diag;
+ 
+ 	kdb_printf("File_lock at 0x%lx\n", addr);
+ 
+ 	kdb_printf(" fl_next = 0x%p fl_link.nxt = 0x%p fl_link.prv = 0x%p\n",
+ 			fl.fl_next, fl.fl_link.next, fl.fl_link.prev);
+ 	kdb_printf(" fl_block.nxt = 0x%p fl_block.prv = 0x%p\n",
+ 			fl.fl_block.next, fl.fl_block.prev);
+ 	kdb_printf(" fl_owner = 0x%p fl_pid = %d fl_wait = 0x%p\n",
+ 			fl.fl_owner, fl.fl_pid, &fl.fl_wait);
+ 	kdb_printf(" fl_file = 0x%p fl_flags = 0x%x\n",
+ 			fl.fl_file, fl.fl_flags);
+ 	kdb_printf(" fl_type = %d fl_start = 0x%llx fl_end = 0x%llx\n",
+ 			fl.fl_type, fl.fl_start, fl.fl_end);
+ 
+ 	kdb_printf(" fl_notify = 0x%p fl_insert = 0x%p fl_remove = 0x%p\n",
+ 			fl.fl_notify, fl.fl_insert, fl.fl_remove);
+ 
+ 	kdb_printf(" fl_fasync = 0x%p fl_break 0x%lx\n",
+ 			fl.fl_fasync, fl.fl_break_time);
+ 
+ 	return 0;
+ }
+ 
+ 
+ static int
+ kdbm_dentry(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	struct dentry d;
+ 	int	      nextarg;
+ 	unsigned long addr;
+ 	long	      offset;
+ 	int	      diag;
+ 	char          buf[256];
+ 
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+ 	    (diag = kdb_getarea(d, addr)))
+ 		return diag;
+ 	
+ 	
+ 	kdb_printf("Dentry at 0x%lx\n", addr);
+ 
+ 	if ((d.d_name.len > sizeof(buf)) || (diag = kdb_getarea_size(buf, (unsigned long)(d.d_name.name), d.d_name.len)))
+ 		kdb_printf(" d_name.len = %d d_name.name = 0x%p\n",
+ 					d.d_name.len, d.d_name.name);
+ 	else
+ 		kdb_printf(" d_name.len = %d d_name.name = 0x%p <%.*s>\n",
+ 					d.d_name.len, d.d_name.name,
+ 					(int)(d.d_name.len), d.d_name.name);
+ 	
+ 	kdb_printf(" d_count = %d d_flags = 0x%x d_inode = 0x%p\n",
+ 					atomic_read(&d.d_count), d.d_flags, d.d_inode);
+ 
+ 	kdb_printf(" d_parent = 0x%p\n", d.d_parent);
+ 
+ 	kdb_printf(" d_hash.nxt = 0x%p d_hash.prv = 0x%p\n",
+ 					d.d_hash.next, d.d_hash.prev);
+ 
+ 	kdb_printf(" d_lru.nxt = 0x%p d_lru.prv = 0x%p\n",
+ 					d.d_lru.next, d.d_lru.prev);
+ 
+ 	kdb_printf(" d_child.nxt = 0x%p d_child.prv = 0x%p\n",
+ 					d.d_child.next, d.d_child.prev);
+ 
+ 	kdb_printf(" d_subdirs.nxt = 0x%p d_subdirs.prv = 0x%p\n",
+ 					d.d_subdirs.next, d.d_subdirs.prev);
+ 
+ 	kdb_printf(" d_alias.nxt = 0x%p d_alias.prv = 0x%p\n",
+ 					d.d_alias.next, d.d_alias.prev);
+ 
+ 	kdb_printf(" d_op = 0x%p d_sb = 0x%p\n\n",
+ 					d.d_op, d.d_sb);
+ 
+ 	return 0;
+ }
+ 
+ static int
+ kdbm_sh(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int diag;
+ 	int nextarg;
+ 	unsigned long addr;
+ 	long	      offset =0L;
+ 	struct Scsi_Host sh;
+ 
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
+ 	    (diag = kdb_getarea(sh, addr)))
+ 		return diag;
+ 
+ 	kdb_printf("Scsi_Host at 0x%lx\n", addr);
+ 	kdb_printf("next = 0x%p   host_queue = 0x%p\n",
+ 		   sh.next, sh.host_queue);
+ 	kdb_printf("ehandler = 0x%p eh_wait = 0x%p  en_notify = 0x%p eh_action = 0x%p\n",
+ 		   sh.ehandler, sh.eh_wait, sh.eh_notify, sh.eh_action);
+ 	kdb_printf("eh_active = 0x%d host_wait = 0x%p hostt = 0x%p host_busy = %d\n",
+ 		   sh.eh_active, &sh.host_wait, sh.hostt, sh.host_active.counter);
+ 	kdb_printf("host_failed = %d  extra_bytes = %d  host_no = %d resetting = %d\n",
+ 		   sh.host_failed, sh.extra_bytes, sh.host_no, sh.resetting);
+ 	kdb_printf("max id/lun/channel = [%d/%d/%d]  this_id = %d\n",
+ 		   sh.max_id, sh.max_lun, sh.max_channel, sh.this_id);
+ 	kdb_printf("can_queue = %d cmd_per_lun = %d  sg_tablesize = %d u_isa_dma = %d\n",
+ 		   sh.can_queue, sh.cmd_per_lun, sh.sg_tablesize, sh.unchecked_isa_dma);
+ 	kdb_printf("host_blocked = %d  reverse_ordering = %d \n",
+ 		   sh.host_blocked, sh.reverse_ordering);
+ 
+ 	return 0;
+ }
+ 
+ static int
+ kdbm_sd(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int diag;
+ 	int nextarg;
+ 	unsigned long addr;
+ 	long offset =0L;
+ 	struct scsi_device *sd = NULL;
+ 
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+ 		goto out;
+ 	if (!(sd = kmalloc(sizeof(*sd), GFP_ATOMIC))) {
+ 		kdb_printf("kdbm_sd: cannot kmalloc sd\n");
+ 		goto out;
+ 	}
+ 	if ((diag = kdb_getarea(*sd, addr)))
+ 		goto out;
+ 
+ 	kdb_printf("scsi_device at 0x%lx\n", addr);
+ 	kdb_printf("next = 0x%p   prev = 0x%p  host = 0x%p\n",
+ 		   sd->next, sd->prev, sd->host);
+ 	kdb_printf("device_busy = %d   device_queue 0x%p\n",
+ 		   sd->device_busy, sd->device_queue);
+ 	kdb_printf("id/lun/chan = [%d/%d/%d]  single_lun = %d  device_blocked = %d\n",
+ 		   sd->id, sd->lun, sd->channel, sd->single_lun, sd->device_blocked);
+ 	kdb_printf("queue_depth = %d current_tag = %d  scsi_level = %d\n",
+ 		   sd->queue_depth, sd->current_tag, sd->scsi_level);
+ 	kdb_printf("%8.8s %16.16s %4.4s\n", sd->vendor, sd->model, sd->rev);
+ out:
+ 	if (sd)
+ 		kfree(sd);
+ 	return diag;
+ }
+ 
+ static char *
+ str_rq_status(int rq_status)
+ {
+ 	switch (rq_status) {
+ 	case RQ_INACTIVE:
+ 		return "RQ_INACTIVE";
+ 	case RQ_ACTIVE:
+ 		return "RQ_ACTIVE";
+ 	case RQ_SCSI_BUSY:
+ 		return "RQ_SCSI_BUSY";
+ 	case RQ_SCSI_DONE:
+ 		return "RQ_SCSI_DONE";
+ 	case RQ_SCSI_DISCONNECTING:
+ 		return "RQ_SCSI_DISCONNECTING";
+ 	default:
+ 		return "UNKNOWN";
+ 	}
+ }
+ 
+ static int
+ kdbm_sc(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int diag;
+ 	int nextarg;
+ 	unsigned long addr;
+ 	long offset =0L;
+ 	struct scsi_cmnd *sc = NULL;
+ 
+ 	if (argc != 1)
+ 		return KDB_ARGCOUNT;
+ 
+ 	nextarg = 1;
+ 	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
+ 		goto out;
+ 	if (!(sc = kmalloc(sizeof(*sc), GFP_ATOMIC))) {
+ 		kdb_printf("kdbm_sc: cannot kmalloc sc\n");
+ 		goto out;
+ 	}
+ 	if ((diag = kdb_getarea(*sc, addr)))
+ 		goto out;
+ 
+ 	kdb_printf("scsi_cmnd at 0x%lx\n", addr);
+ 	kdb_printf("host = 0x%p  state = %d  owner = %d  device = 0x%p\nb",
+ 		    sc->host, sc->state, sc->owner, sc->device);
+ 	kdb_printf("next = 0x%p  reset_chain = 0x%p  eh_state = %d done = 0x%p\n",
+ 		   sc->next, sc->reset_chain, sc->eh_state, sc->done);
+ 	kdb_printf("serial_number = %ld  serial_num_at_to = %ld retries = %d timeout = %d\n",
+ 		   sc->serial_number, sc->serial_number_at_timeout, sc->retries, sc->timeout);
+ 	kdb_printf("id/lun/cmnd = [%d/%d/%d]  cmd_len = %d  old_cmd_len = %d\n",
+ 		   sc->target, sc->lun, sc->channel, sc->cmd_len, sc->old_cmd_len);
+ 	kdb_printf("cmnd = [%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x]\n",
+ 		   sc->cmnd[0], sc->cmnd[1], sc->cmnd[2], sc->cmnd[3], sc->cmnd[4],
+ 		   sc->cmnd[5], sc->cmnd[6], sc->cmnd[7], sc->cmnd[8], sc->cmnd[9],
+ 		   sc->cmnd[10], sc->cmnd[11]);
+ 	kdb_printf("data_cmnd = [%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x/%2.2x]\n",
+ 		   sc->data_cmnd[0], sc->data_cmnd[1], sc->data_cmnd[2], sc->data_cmnd[3], sc->data_cmnd[4],
+ 		   sc->data_cmnd[5], sc->data_cmnd[6], sc->data_cmnd[7], sc->data_cmnd[8], sc->data_cmnd[9],
+ 		   sc->data_cmnd[10], sc->data_cmnd[11]);
+ 	kdb_printf("request_buffer = 0x%p  bh_next = 0x%p  request_bufflen = %d\n",
+ 		   sc->request_buffer, sc->bh_next, sc->request_bufflen);
+ 	kdb_printf("use_sg = %d  old_use_sg = %d sglist_len = %d abore_reason = %d\n",
+ 		   sc->use_sg, sc->old_use_sg, sc->sglist_len, sc->abort_reason);
+ 	kdb_printf("bufflen = %d  buffer = 0x%p  underflow = %d transfersize = %d\n",
+ 		   sc->bufflen, sc->buffer, sc->underflow, sc->transfersize);
+ 	kdb_printf("tag = %d pid = %ld\n",
+ 		   sc->tag, sc->pid);
+ 	kdb_printf("request struct\n");
+ 	kdb_printf("rq_status = %s  rq_dev = [%d/%d]  errors = %d  cmd = %d\n",
+ 		   str_rq_status(sc->request.rq_status),
+ 		   MAJOR(sc->request.rq_dev),
+ 		   MINOR(sc->request.rq_dev), sc->request.cmd,
+ 		   sc->request.errors);
+ 	kdb_printf("sector = %llu  nr_sectors = %lu  current_nr_sectors = %lu\n",
+ 		   (unsigned long long)sc->request.sector,
+ 		   sc->request.nr_sectors, sc->request.current_nr_sectors);
+ 	kdb_printf("buffer = 0x%p bh = 0x%p bhtail = 0x%p\n",
+ 		   sc->request.buffer, sc->request.bh, sc->request.bhtail);
+ 
+ out:
+ 	if (sc)
+ 		kfree(sc);
+ 	return diag;
+ }
+ 
+ static int __init kdbm_vm_init(void)
+ {
+ 	kdb_register("vm", kdbm_vm, "[-v] <vaddr>", "Display vm_area_struct", 0);
+ 	kdb_register("vmp", kdbm_vm, "[-v] <pid>", "Display all vm_area_struct for <pid>", 0);
+ 	kdb_register("pte", kdbm_pte, "<pid> <vaddr> [<nbytes>]", "Display pte_t", 0);
+ 	kdb_register("dentry", kdbm_dentry, "<dentry>", "Display interesting dentry stuff", 0);
+ 	kdb_register("filp", kdbm_fp, "<filp>", "Display interesting filp stuff", 0);
+ 	kdb_register("fl", kdbm_fl, "<fl>", "Display interesting file_lock stuff", 0);
+ 	kdb_register("sh", kdbm_sh, "<vaddr>", "Show scsi_host", 0);
+ 	kdb_register("sd", kdbm_sd, "<vaddr>", "Show scsi_device", 0);
+ 	kdb_register("sc", kdbm_sc, "<vaddr>", "Show scsi_cmnd", 0);
+ 	
+ 	return 0;
+ }
+ 
+ static void __exit kdbm_vm_exit(void)
+ {
+ 	kdb_unregister("vm");
+ 	kdb_unregister("vmp");
+ 	kdb_unregister("pte");
+ 	kdb_unregister("dentry");
+ 	kdb_unregister("filp");
+ 	kdb_unregister("fl");
+ 	kdb_unregister("sh");
+ 	kdb_unregister("sd");
+ 	kdb_unregister("sc");
+ }
+ 
+ module_init(kdbm_vm_init)
+ module_exit(kdbm_vm_exit)
diff -c -r -N console-os/kdb/modules/kdbm_x86.c console-os-kdb/kdb/modules/kdbm_x86.c
*** console-os/kdb/modules/kdbm_x86.c	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/modules/kdbm_x86.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,913 ----
+ /*
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of version 2 of the GNU General Public License
+  * as published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it would be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  *
+  * Further, this software is distributed without any warranty that it is
+  * free of the rightful claim of any third person regarding infringement
+  * or the like.  Any license provided herein, whether implied or
+  * otherwise, applies only to this software file.  Patent licenses, if
+  * any, provided herein do not apply to combinations of this program with
+  * other software, or any other product whatsoever.
+  *
+  * You should have received a copy of the GNU General Public
+  * License along with this program; if not, write the Free Software
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+  *
+  * Author: Vamsi Krishna S. <vamsi_krishna@in.ibm.com>
+  * (C) 2003 IBM Corporation.
+  */
+ 
+ #include <linux/types.h>
+ #include <linux/kdb.h>
+ #include <linux/kdbprivate.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/mm.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/desc.h>
+ #include <asm/debugreg.h>
+ 
+ MODULE_AUTHOR("Vamsi Krishna S./IBM");
+ MODULE_DESCRIPTION("x86 specific information (gdt/idt/ldt/page tables)");
+ MODULE_LICENSE("GPL");
+ 
+ typedef struct _kdb_desc {
+ 	unsigned short limit;
+ 	unsigned short base;
+ 	unsigned char base_h1;
+ 	unsigned char type:4;
+ 	unsigned char seg:1;
+ 	unsigned char dpl:2;
+ 	unsigned char present:1;
+ 	unsigned char limit_h:4;
+ 	unsigned char avl:2;
+ 	unsigned char db:1;
+ 	unsigned char g:1; /* granularity */
+ 	unsigned char base_h2;
+ } kdb_desc_t;
+ 
+ typedef struct _kdb_gate_desc {
+ 	unsigned short offset;
+ 	unsigned short sel;
+ 	unsigned char res;
+ 	unsigned char type:4;
+ 	unsigned char seg:1;
+ 	unsigned char dpl:2;
+ 	unsigned char present:1;
+ 	unsigned short offset_h;
+ } kdb_gate_desc_t;
+ 
+ #define KDB_SEL_MAX 			0x2000
+ #define KDB_IDT_MAX 			0x100
+ #define KDB_SYS_DESC_TYPE_TSS		0x01
+ #define KDB_SYS_DESC_TYPE_LDT		0x02
+ #define KDB_SYS_DESC_TYPE_TSSB		0x03
+ #define KDB_SYS_DESC_TYPE_CALLG		0x04
+ #define KDB_SYS_DESC_TYPE_TASKG		0x05
+ #define KDB_SYS_DESC_TYPE_INTG		0x06
+ #define KDB_SYS_DESC_TYPE_TRAPG		0x07
+ 
+ #define KDB_SYS_DESC_TYPE_TSS32 	0x09
+ #define KDB_SYS_DESC_TYPE_TSS32B	0x0b
+ #define KDB_SYS_DESC_TYPE_CALLG32	0x0c
+ #define KDB_SYS_DESC_TYPE_INTG32	0x0e
+ #define KDB_SYS_DESC_TYPE_TRAPG32	0x0f
+ 
+ #define KDB_SYS_DESC_OFFSET(d) ((unsigned long)(d->offset_h << 16 | d->offset))
+ #define KDB_SYS_DESC_CALLG_COUNT(d) ((unsigned int)(d->res & 0x0F))
+ 
+ #define KDB_SEG_DESC_TYPE_CODE		0x08
+ #define KDB_SEG_DESC_TYPE_CODE_R	0x02
+ #define KDB_SEG_DESC_TYPE_DATA_W	0x02
+ #define KDB_SEG_DESC_TYPE_CODE_C	0x02    /* conforming */
+ #define KDB_SEG_DESC_TYPE_DATA_D	0x02    /* expand-down */
+ #define KDB_SEG_DESC_TYPE_A		0x01	/* accessed */
+ 
+ #define KDB_SEG_DESC_BASE(d) ((unsigned long)(d->base_h2 << 24 | d->base_h1 << 16 | d->base))
+ #define _LIMIT(d) ((unsigned long)(d->limit_h << 16 | d->limit))
+ #define KDB_SEG_DESC_LIMIT(d) (d->g ? ((_LIMIT(d)+1) << 12) -1 : _LIMIT(d))
+  
+ /* helper functions to display system registers in verbose mode */
+ static void display_gdtr(void)
+ {
+ 	struct Xgt_desc_struct gdtr;
+ 	
+ 	__asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+ 	kdb_printf("gdtr.address = 0x%8.8lx, gdtr.size = 0x%x\n", gdtr.address, gdtr.size);
+ 
+ 	return;
+ }
+ 
+ static void display_ldtr(void)
+ {
+ 	struct Xgt_desc_struct gdtr;
+ 	unsigned long ldtr;
+ 	
+ 	__asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+ 	__asm__ __volatile__ ("sldt %0\n\t" : "=m"(ldtr));
+ 	
+ 	kdb_printf("ldtr = 0x%8.8lx ", ldtr);
+ 
+ 	if (ldtr < gdtr.size) {
+ 		kdb_desc_t *ldt_desc = (kdb_desc_t *)(gdtr.address + (ldtr & ~7));
+ 		kdb_printf("base=0x%8.8lx, limit=0x%8.8lx\n", KDB_SEG_DESC_BASE(ldt_desc), 
+ 				KDB_SEG_DESC_LIMIT(ldt_desc)); 
+ 	} else {
+ 		kdb_printf("invalid\n");
+ 	}
+ 
+ 	return;
+ }
+ 
+ static void display_idtr(void)
+ {
+ 	struct Xgt_desc_struct idtr;
+ 	__asm__ __volatile__ ("sidt %0\n\t" : "=m"(idtr));
+ 	kdb_printf("idtr.address = 0x%8.8lx, idtr.size = 0x%x\n", idtr.address, idtr.size);
+ 	return;	
+ }
+ 
+ static char *cr0_flags[] = {
+ 	"pe", "mp", "em", "ts", "et", "ne", NULL, NULL,
+ 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 	"wp", NULL, "am", NULL, NULL, NULL, NULL, NULL,
+ 	NULL, NULL, NULL, NULL, NULL, "nw", "cd", "pg"};
+ 
+ static void display_cr0(void)
+ {
+ 	kdb_machreg_t cr0;
+ 	int i;
+ 	__asm__ ("movl %%cr0,%0\n\t":"=r"(cr0));
+ 	kdb_printf("cr0=0x%08lx ", cr0);
+ 	for (i = 0; i < 32; i++) {
+ 		if (test_bit(i, &cr0) && cr0_flags[i])
+ 			kdb_printf("%s ", cr0_flags[i]);
+ 	}
+ 	kdb_printf("\n");
+ 	return;
+ }
+ 
+ static void display_cr3(void)
+ {
+ 	kdb_machreg_t cr3;
+ 	__asm__ ("movl %%cr3,%0\n\t":"=r"(cr3));
+ 	kdb_printf("cr3 = 0x%08lx ", cr3);
+ 	if (cr3 & 0x08)
+ 		kdb_printf("pwt ");
+ 	if (cr3 & 0x10)
+ 		kdb_printf("pcd ");
+ 	kdb_printf("pgdir=%8.8lx\n", cr3 & PAGE_MASK);
+ 	return;
+ }
+ 
+ static char *cr4_flags[] = {
+ 	"vme", "pvi", "tsd", "de", "pse", "pae", "mce", "pge", "pce"};
+ 
+ static void display_cr4(void)
+ {
+ 	kdb_machreg_t cr4;
+ 	int i;
+ 	__asm__ ("movl %%cr4,%0\n\t":"=r"(cr4));
+ 	kdb_printf("cr4 = 0x%08lx ", cr4);
+ 	for (i = 0; i < 9; i++) {
+ 		if (test_bit(i, &cr4))
+ 			kdb_printf("%s ", cr4_flags[i]);
+ 	}
+ 	kdb_printf("\n");
+ 	return;
+ }
+ 
+ static char *dr_type_name[] = { "exec", "write", "io", "rw" };
+ 
+ static void display_dr_status(int nr, int enabled, int local, int len, int type)
+ {
+ 	if (!enabled) {
+ 		kdb_printf("\tdebug register %d: not enabled\n", nr);
+ 		return;
+ 	}
+ 	
+ 	kdb_printf("\tdebug register %d: %s, len = %d, type = %s\n", 
+ 			nr,
+ 			local? " local":"global",
+ 			len,
+ 			dr_type_name[type]);
+ }
+ 
+ static void display_dr(void)
+ {
+ 	kdb_machreg_t dr0, dr1, dr2, dr3, dr6, dr7;
+ 	int dbnr, set;
+ 
+ 	__asm__ ("movl %%db0,%0\n\t":"=r"(dr0));
+ 	__asm__ ("movl %%db1,%0\n\t":"=r"(dr1));
+ 	__asm__ ("movl %%db2,%0\n\t":"=r"(dr2));
+ 	__asm__ ("movl %%db3,%0\n\t":"=r"(dr3));
+ 	__asm__ ("movl %%db6,%0\n\t":"=r"(dr6));
+ 	__asm__ ("movl %%db7,%0\n\t":"=r"(dr7));
+ 
+ 	kdb_printf("dr0 = 0x%08lx dr1 = 0x%08lx dr2 = 0x%08lx dr3 = 0x%08lx\n",
+ 		   dr0, dr1, dr2, dr3);
+ 	kdb_printf("dr6 = 0x%08lx ", dr6);
+ 	dbnr = dr6 & DR6_DR_MASK;
+ 	if (dbnr) {
+ 		int nr;
+ 		switch(dbnr) {
+ 		case 1:
+ 			nr = 0; break;
+ 		case 2:
+ 			nr = 1; break;
+ 		case 4:
+ 			nr = 2; break;
+ 		default:
+ 			nr = 3; break;
+ 		}
+ 		kdb_printf("debug register hit = %d", nr);
+ 	} else if (dr6 & DR_STEP) {
+ 		kdb_printf("single step");
+ 	} else if (dr6 & DR_SWITCH) {
+ 		kdb_printf("task switch");
+ 	}
+ 	kdb_printf("\n");
+ 
+ 	kdb_printf("dr7 = 0x%08lx\n", dr7);
+ 	set = DR7_L0(dr7) || DR7_G0(dr7);
+ 	display_dr_status(0, set, DR7_L0(dr7), DR7_LEN0(dr7), DR7_RW0(dr7));
+ 	set = DR7_L1(dr7) || DR7_G1(dr7);
+ 	display_dr_status(1, set, DR7_L1(dr7), DR7_LEN1(dr7), DR7_RW1(dr7));
+ 	set = DR7_L2(dr7) || DR7_G2(dr7);
+ 	display_dr_status(2, set, DR7_L2(dr7), DR7_LEN2(dr7), DR7_RW2(dr7));
+ 	set = DR7_L3(dr7) || DR7_G3(dr7);
+ 	display_dr_status(3, set, DR7_L3(dr7), DR7_LEN3(dr7), DR7_RW3(dr7));
+ }
+ 
+ static char *set_eflags[] = {
+ 	"carry", NULL, "parity",  NULL, "adjust",  NULL, "zero", "sign",
+ 	"trace", "intr-on", "dir", "overflow",  NULL, NULL, "nestedtask", NULL,
+ 	"resume", "vm", "align", "vif", "vip", "id", NULL, NULL,
+ 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+ 
+ static void display_eflags(unsigned long ef)
+ {
+ 	int i, iopl;
+ 	kdb_printf("eflags = 0x%08lx ", ef);
+ 	for (i = 0; i < 22; i++) {
+ 		if (test_bit(i, &ef) && set_eflags[i])
+ 			kdb_printf("%s ", set_eflags[i]);
+ 	}
+ 	
+ 	iopl = ((unsigned long)(ef & 0x00003000)) >> 12;
+ 	kdb_printf("iopl=%c\n", '0'+iopl);
+ 	return;
+ }
+ 
+ static void display_tss(struct tss_struct *t)
+ {
+ 	kdb_printf("    cs = %04x,  eip = 0x%8.8lx\n", t->es, t->eip);
+ 	kdb_printf("    ss = %04x,  esp = 0x%8.8lx\n", t->ss, t->esp);
+ 	kdb_printf("   ss0 = %04x, esp0 = 0x%8.8lx\n", t->ss0, t->esp0);
+ 	kdb_printf("   ss1 = %04x, esp1 = 0x%8.8lx\n", t->ss1, t->esp1);
+ 	kdb_printf("   ss2 = %04x, esp2 = 0x%8.8lx\n", t->ss2, t->esp2);
+ 	kdb_printf("   ldt = %04x, cr3 = 0x%8.8lx\n", t->ldt, t->__cr3);
+ 	kdb_printf("    ds = %04x, es = %04x fs = %04x gs = %04x\n", 
+ 			t->ds, t->es, t->fs, t->gs);
+ 	kdb_printf("   eax = 0x%8.8lx, ebx = 0x%8.8lx ecx = 0x%8.8lx edx = 0x%8.8lx\n", 
+ 			t->eax, t->ebx, t->ecx, t->edx);
+ 	kdb_printf("   esi = 0x%8.8lx, edi = 0x%8.8lx ebp = 0x%8.8lx\n", 
+ 			t->esi, t->edi, t->ebp);
+ }
+ 
+ static char *gate_desc_types[] = {
+ 	"invalid", "tss-avlb", "ldt", "tss-busy", 
+ 	"callgate", "taskgate", "intgate", "trapgate", 
+ 	"invalid", "tss32-avlb", "invalid", "tss32-busy", 
+ 	"callgate32", "invalid", "intgate32", "trapgate32",
+ 	NULL };
+ 	
+ static int
+ display_gate_desc(kdb_gate_desc_t * d)
+ {
+ 	kdb_printf("%-11s ", gate_desc_types[d->type]);
+ 
+ 	switch(d->type) {
+ 	case KDB_SYS_DESC_TYPE_LDT:
+ 		kdb_printf("base=0x%8.8lx limit=0x%8.8lx dpl=%d\n", 
+ 			KDB_SEG_DESC_BASE(((kdb_desc_t *)d)), 
+ 			KDB_SEG_DESC_LIMIT(((kdb_desc_t *)d)), d->dpl);
+ 		break;
+ 	case KDB_SYS_DESC_TYPE_TSS32:
+ 	case KDB_SYS_DESC_TYPE_TSS32B:
+ 	{
+ 		struct tss_struct *tss = (struct tss_struct *)KDB_SEG_DESC_BASE(((kdb_desc_t *)d)); 
+ 		kdb_printf("base=0x%8.8lx limit=0x%8.8lx dpl=%d\n", 
+ 			(unsigned long)tss, 
+ 			KDB_SEG_DESC_LIMIT(((kdb_desc_t *)d)), d->dpl);
+ 		display_tss(tss);	
+ 		break;
+ 	}
+ 	case KDB_SYS_DESC_TYPE_CALLG:
+ 		kdb_printf("sel=0x%4.4x off=0x%8.8lx dpl=%d wc=%d\n",
+ 			d->sel, KDB_SYS_DESC_OFFSET(d), d->dpl,
+ 			KDB_SYS_DESC_CALLG_COUNT(d));
+ 		break;
+ 	case KDB_SYS_DESC_TYPE_CALLG32:
+ 		kdb_printf("sel=0x%4.4x off=0x%8.8lx dpl=%d dwc=%d\n",
+ 			d->sel, KDB_SYS_DESC_OFFSET(d), d->dpl,
+ 			KDB_SYS_DESC_CALLG_COUNT(d));
+ 		break;
+ 	default:
+ 		kdb_printf("sel=0x%4.4x off=0x%8.8lx dpl=%d\n",
+ 			d->sel, KDB_SYS_DESC_OFFSET(d), d->dpl);
+ 		break;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ static int
+ display_seg_desc(kdb_desc_t * d)
+ {
+ 	unsigned char type = d->type;
+ 
+ 	if (type & KDB_SEG_DESC_TYPE_CODE) {
+ 		kdb_printf("%-7s base=0x%8.8lx limit=0x%8.8lx dpl=%d %c%c%c %s %s %s \n",
+ 			"code",
+ 			KDB_SEG_DESC_BASE(d), KDB_SEG_DESC_LIMIT(d),
+ 			d->dpl,
+ 			(type & KDB_SEG_DESC_TYPE_CODE_R)?'r':'-',
+ 			'-', 'x',
+ 			d->db ? "32b" : "16b",
+ 			(type & KDB_SEG_DESC_TYPE_A)?"ac":"",
+ 			(type & KDB_SEG_DESC_TYPE_CODE_C)?"conf":"");
+ 	}
+ 	else {
+ 		kdb_printf("%-7s base=0x%8.8lx limit=0x%8.8lx dpl=%d %c%c%c %s %s %s \n",
+ 			"data",
+ 			KDB_SEG_DESC_BASE(d), KDB_SEG_DESC_LIMIT(d),
+ 			d->dpl,
+ 			'r',
+ 			(type & KDB_SEG_DESC_TYPE_DATA_W)?'w':'-',
+ 			'-',
+ 			d->db ? "32b" : "16b",
+ 			(type & KDB_SEG_DESC_TYPE_A)?"ac":"",
+ 			(type & KDB_SEG_DESC_TYPE_DATA_D)?"down":"");
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ static int
+ kdb_parse_two_numbers(int argc, const char **argv, int *sel, int *count, int *last_sel, int *last_count)
+ {
+ 	int diag;
+ 
+ 	if (argc > 2)
+ 		return KDB_ARGCOUNT;
+ 
+ 	kdbgetintenv("MDCOUNT", count);
+ 
+ 	if (argc == 0) {
+ 		*sel = *last_sel;
+ 		if (*last_count)
+ 			*count = *last_count;
+ 	} else {
+ 		unsigned long val;
+ 
+ 		if (argc >= 1) {
+ 			diag = kdbgetularg(argv[1], &val);
+ 			if (diag)
+ 				return diag;
+ 			*sel = val;
+ 		}
+ 		if (argc >= 2) {
+ 			diag = kdbgetularg(argv[2], &val);
+ 			if (diag)
+ 				return diag;
+ 			*count = (int) val;
+ 			*last_count = (int) val;
+ 		} else if (*last_count) {
+ 			*count = *last_count;
+ 		}
+ 	}
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_gdt
+  *
+  *	This function implements the 'gdt' command.
+  *
+  *	gdt [<selector> [<line count>]]
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ static int
+ kdb_gdt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int sel = 0;
+ 	struct Xgt_desc_struct gdtr;
+ 	int diag, count = 8;
+ 	kdb_desc_t * gdt;
+ 	unsigned int max_sel;
+ 	static int last_sel = 0, last_count = 0;
+ 
+ 	diag = kdb_parse_two_numbers(argc, argv, &sel, &count, &last_sel, &last_count);
+ 	if (diag)
+ 		return diag;
+ 
+ 	__asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+ 	gdt = (kdb_desc_t *) gdtr.address;
+ 
+ 	max_sel = (gdtr.size + 1) / sizeof(kdb_desc_t);
+ 	if (sel >= max_sel) {
+ 		sel = 0;
+ 	}
+ 
+ 	if (sel + count > max_sel)
+ 		count = max_sel - sel;
+ 
+ 	while (count--) {
+ 		kdb_desc_t * d = &gdt[sel];
+ 		kdb_printf("0x%4.4x ", sel++);
+ 
+ 		if (!d->present) {
+ 			kdb_printf("not present\n");
+ 			continue;
+ 		}
+ 		if (d->seg)
+ 			display_seg_desc(d);
+ 		else
+ 			display_gate_desc((kdb_gate_desc_t *)d);
+ 	}
+ 
+ 	last_sel = sel;
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_ldt
+  *
+  *	This function implements the 'ldt' command.
+  *
+  *	ldt [<selector> [<line count>]]
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ static int
+ kdb_ldt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int sel = 0;
+ 	struct Xgt_desc_struct gdtr;
+ 	unsigned long ldtr = 0;
+ 	int diag, count = 8;
+ 	kdb_desc_t * ldt, *ldt_desc;
+ 	unsigned int max_sel;
+ 	static int last_sel = 0, last_count = 0;
+ 
+ 	diag = kdb_parse_two_numbers(argc, argv, &sel, &count, &last_sel, &last_count);
+ 	if (diag)
+ 		return diag;
+ 
+ 	if (strcmp(argv[0], "ldtp") == 0) {
+ 		kdb_printf("pid=%d, process=%s\n", kdb_current_task->pid, kdb_current_task->comm);
+ 		if (!kdb_current_task->mm || !kdb_current_task->mm->context.segments) {
+ 			kdb_printf("no special LDT for this process\n");
+ 			return 0;
+ 		}
+ 		ldt = kdb_current_task->mm->context.segments;
+ 		max_sel = LDT_ENTRIES;
+ 	} else {
+ 
+ 		/* sldt gives the GDT selector for the segment containing LDT */
+ 		__asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+ 		__asm__ __volatile__ ("sldt %0\n\t" : "=m"(ldtr));
+ 
+ 		if (ldtr > gdtr.size+1) {
+ 			kdb_printf("invalid ldtr\n");
+ 			return 0;
+ 		}
+ 
+ 		ldt_desc = (kdb_desc_t *)(gdtr.address + (ldtr & ~7));
+ 		ldt = (kdb_desc_t *) KDB_SEG_DESC_BASE(ldt_desc);
+ 		max_sel = (KDB_SEG_DESC_LIMIT(ldt_desc)+1) / sizeof(kdb_desc_t);
+ 	}
+ 
+ 	if (sel >= max_sel) {
+ 		sel = 0;
+ 	}
+ 
+ 	if (sel + count > max_sel)
+ 		count = max_sel - sel;
+ 
+ 	while (count--) {
+ 		kdb_desc_t * d = &ldt[sel];
+ 		kdb_printf("0x%4.4x ", sel++);
+ 
+ 		if (d->seg)
+ 			display_seg_desc(d);
+ 		else
+ 			display_gate_desc((kdb_gate_desc_t *)d);
+ 	}
+ 
+ 	last_sel = sel;
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_idt
+  *
+  *	This function implements the 'idt' command.
+  *
+  *	idt [<vector> [<line count>]]
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ static int
+ kdb_idt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	int vec = 0;
+ 	struct Xgt_desc_struct idtr;
+ 	int diag, count = 8;
+ 	kdb_gate_desc_t * idt;
+ 	unsigned int max_entries;
+ 	static int last_vec = 0, last_count = 0;
+ 
+ 	diag = kdb_parse_two_numbers(argc, argv, &vec, &count, &last_vec, &last_count);
+ 	if (diag)
+ 		return diag;
+ 
+ 	__asm__ __volatile__ ("sidt %0\n\t" : "=m"(idtr));
+ 	idt = (kdb_gate_desc_t *) idtr.address;
+ 
+ 	max_entries = (idtr.size+1) / sizeof(kdb_gate_desc_t);
+ 	if (vec >= max_entries) {
+ 		vec = 0;
+ 	}
+ 
+ 	if (vec + count > max_entries)
+ 		count = max_entries - vec;
+ 
+ 	while (count--) {
+ 		kdb_gate_desc_t * d = &idt[vec];
+ 		kdb_printf("0x%4.4x ", vec++);
+ 		if (!d->present) {
+ 			kdb_printf("not present\n");
+ 			continue;
+ 		}
+ 		if (d->seg) {
+ 			kdb_printf("invalid\n");
+ 			continue;
+ 		}
+ 		display_gate_desc(d);
+ 	}
+ 
+ 	last_vec = vec;
+ 
+ 	return 0;
+ }
+ 
+ #define _PAGE_PSE 0x080
+ 
+ static int
+ get_pagetables(unsigned long addr, pgd_t **pgdir, pmd_t **pgmiddle, pte_t **pte)
+ {
+ 	pgd_t * d;
+ 	pmd_t * m;
+ 	pte_t * t;
+ 
+ 	if (addr > PAGE_OFFSET) {
+ 		d = pgd_offset_k(addr);
+ 	} else {
+ 		kdb_printf("pid=%d, process=%s\n", kdb_current_task->pid, kdb_current_task->comm);
+ 		d = pgd_offset(kdb_current_task->mm, addr);
+ 	}
+ 
+ 	if (pgd_none(*d) || pgd_bad(*d)) {
+ 		*pgdir = NULL;
+ 		*pgmiddle = NULL;
+ 		*pte = NULL;
+ 		return 0;
+ 	} else {
+ 		*pgdir = d;
+ 	}
+ 
+ 	/* if _PAGE_PSE is set, pgdir points directly to the page. */
+ 	if (pgd_val(*d) & _PAGE_PSE) {
+ 		*pgmiddle = NULL;
+ 		*pte = NULL;
+ 		return 0;
+ 	}
+ 
+ 	m = pmd_offset(d, addr);
+ 	if (pmd_none(*m) || pmd_bad(*m)) {
+ 		*pgmiddle = NULL;
+ 		*pte = NULL;
+ 		return 0;
+ 	} else {
+ 		*pgmiddle = m;
+ 	}
+ 
+ 	t = pte_offset(m, addr);
+ 	if (pte_none(*t)) {
+ 		*pte = NULL;
+ 		return 0;
+ 	} else {
+ 	 	*pte = t;
+ 	}
+ 	kdb_printf("\naddr=%08lx, pgd=%08lx, pmd=%08lx, pte=%08lx\n",
+ 			addr,
+ 			(unsigned long) pgd_val(*d),
+ 			(unsigned long) pmd_val(*m),
+ 			(unsigned long) pte_val(*t));
+ 	return 0;
+ }
+ 
+ #define FORMAT_PGDIR(entry) \
+ 	kdb_printf("frame=%05lx %c %s %c %c %c %s %c %s %s \n",\
+ 			(entry >> PAGE_SHIFT), 				\
+ 			(entry & _PAGE_PRESENT)?'p':'n', 		\
+ 			(entry & _PAGE_RW)?"rw":"ro", 			\
+ 			(entry & _PAGE_USER)?'u':'s', 			\
+ 			(entry & _PAGE_ACCESSED)?'a':' ', 		\
+ 			' ', 						\
+ 			(entry & _PAGE_PSE)?"4M":"4K", 			\
+ 			(entry & _PAGE_GLOBAL)?'g':' ', 		\
+ 			(entry & _PAGE_PWT)?"wt":"wb", 			\
+ 			(entry & _PAGE_PCD)?"cd":"  ");
+ 
+ #define FORMAT_PTE(p, entry) \
+ 	kdb_printf("frame=%05lx %c%c%c %c %c %c %s %c %s %s\n",	\
+ 			(entry >> PAGE_SHIFT), 			\
+ 			(pte_read(p))? 'r':'-', 		\
+ 			(pte_write(p))? 'w':'-', 		\
+ 			(pte_exec(p))? 'x':'-', 		\
+ 			(pte_dirty(p))? 'd':' ', 		\
+ 			(pte_young(p))? 'a':' ', 		\
+ 			(entry & _PAGE_USER)? 'u':'s', 		\
+ 			"  ", 					\
+ 			(entry & _PAGE_GLOBAL)? 'g':' ',	\
+ 			(entry & _PAGE_PWT)? "wt":"wb", 	\
+ 			(entry & _PAGE_PCD)? "cd":"  ");
+ static int
+ display_pgdir(unsigned long addr, pgd_t *pgdir, int count)
+ {
+ 	unsigned long entry;
+ 	int i;
+ 	int index = pgdir - ((pgd_t *)(((unsigned long)pgdir) & PAGE_MASK));
+ 
+ 	count = min(count, PTRS_PER_PGD - index);
+ 	addr &= ~(PGDIR_SIZE-1);
+ 
+         for (i = 0; i < count; i++, pgdir++) {
+ 		entry = pgd_val(*pgdir);
+ 		kdb_printf("pgd: addr=%08lx ", addr);
+ 		if (pgd_none(*pgdir)) {
+ 			kdb_printf("pgdir not present\n");
+ 		} else {
+ 			FORMAT_PGDIR(entry);
+ 		}
+ 		addr += PGDIR_SIZE;
+ 	}
+ 	return i;
+ }
+ 
+ #if 0	/* for now, let's not print pgmiddle. */
+ static int
+ display_pgmiddle(unsigned long addr, pmd_t *pgmiddle, int count)
+ {
+ 	unsigned long entry;
+ 	int i;
+ 	int index = pgmiddle - ((pmd_t *)(((unsigned long)pgmiddle) & PAGE_MASK));
+ 
+ 	count = min(count, PTRS_PER_PMD - index);
+ 	addr &= ~(PMD_SIZE-1);
+ 
+ 	for (i = 0; i < count; i++, pgmiddle++) {
+ 		entry = pmd_val(*pgmiddle);
+ 		kdb_printf("pmd: addr=%08lx ", addr);
+ 		if (pmd_none(*pgmiddle)) {
+ 			kdb_printf("pgmiddle not present\n");
+ 		} else {
+ 			FORMAT_PGDIR(entry);
+ 		}
+ 		addr += PMD_SIZE;
+ 	}
+ 	return i;
+ }
+ #endif
+ 
+ static int
+ display_pte(unsigned long addr, pte_t *pte, int count)
+ {
+ 	unsigned long entry;
+ 	int i;
+ 	int index = pte - ((pte_t *)(((unsigned long)pte) & PAGE_MASK));
+ 
+ 	count = min(count, PTRS_PER_PTE - index);
+ 	addr &= PAGE_MASK;
+ 
+         for (i = 0; i < count; i++, pte++) {
+ 		entry = pte_val(*pte);
+ 		kdb_printf("pte: addr=%08lx ", addr);
+ 		if (pte_none(*pte)) {
+ 			kdb_printf("pte not present\n");
+ 		} else if (!pte_present(*pte)) {
+ 			kdb_printf("page swapped out. swp_offset=%08lx ", SWP_OFFSET(pte_to_swp_entry(*pte)));
+ 			kdb_printf("swp_type=%8lx", SWP_TYPE(pte_to_swp_entry(*pte)));
+ 		} else {
+ 			FORMAT_PTE(*pte, entry);
+ 		}
+ 		addr += PAGE_SIZE;
+ 	}
+ 	return i;
+ }
+ 
+ /*
+  * kdb_pte
+  *
+  *	This function implements the 'pte' command.
+  *
+  *	pte  <addr arg> [<line count>]
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  */
+ static int
+ kdb_pte(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	static unsigned long last_addr = 0, last_count = 0;
+ 	int count = 8;
+ 	unsigned long addr;
+ 	long	offset = 0;
+ 	pgd_t * pgdir;
+ 	pmd_t * pgmiddle;
+ 	pte_t * pte;
+ 
+ #ifdef CONFIG_X86_PAE
+ 	kdb_printf("This kernel is compiled with PAE support.");
+ 	return KDB_NOTIMP;
+ #endif
+ 	kdbgetintenv("MDCOUNT", &count);
+ 
+ 	if (argc == 0) {
+ 		if (last_addr == 0)
+ 			return KDB_ARGCOUNT;
+ 		addr = last_addr;
+ 		if (last_count)
+ 			count = last_count;
+ 	} else {
+ 		kdb_machreg_t val;
+ 		int diag, nextarg = 1;
+ 		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+ 		if (diag)
+ 			return diag;
+ 		if (argc > nextarg+1)
+ 			return KDB_ARGCOUNT;
+ 
+ 		if (argc >= nextarg) {
+ 			diag = kdbgetularg(argv[nextarg], &val);
+ 			if (!diag) {
+ 				count = (int) val;
+ 				last_count = count;
+ 			} else if (last_count) {
+ 				count = last_count;
+ 			}
+ 		}
+ 	}
+ 
+ 	/*
+ 	 * round off the addr to a page boundary.
+ 	 */
+         addr &= PAGE_MASK;
+ 
+         get_pagetables(addr, &pgdir, &pgmiddle, &pte);
+ 
+ 	if (pgdir)
+ 		display_pgdir(addr, pgdir, 1);
+ #if 0	/* for now, let's not print pgmiddle. */
+ 	   if (pgmiddle)
+ 		display_pgmiddle(addr, pgmiddle, 1);
+ #endif
+ 	if (pte) {
+ 		int displayed;
+ 		displayed = display_pte(addr, pte, count);
+ 		addr += (displayed << PAGE_SHIFT);
+ 	}
+ 	last_addr = addr;
+ 	return 0;
+ }
+ 
+ /*
+  * kdb_rdv
+  *
+  *	This function implements the 'rdv' command.
+  *	It displays all registers of the current processor
+  *	included control registers in verbose mode.
+  *
+  * Inputs:
+  *	argc	argument count
+  *	argv	argument vector
+  *	envp	environment vector
+  *	regs	registers at time kdb was entered.
+  * Outputs:
+  *	None.
+  * Returns:
+  *	zero for success, a kdb diagnostic if error
+  * Locking:
+  *	none.
+  * Remarks:
+  * 	This should have been an option to rd command say "rd v",
+  * 	but it is here as it is a non-essential x86-only command,
+  * 	that need not clutter arch/i386/kdb/kdbasupport.c.
+  */
+ static int
+ kdb_rdv(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+ {
+ 	kdba_dumpregs(regs, NULL, NULL);
+ 	kdb_printf("\n");
+ 	display_eflags(regs->eflags);
+ 	kdb_printf("\n");
+ 	display_gdtr();
+ 	display_idtr();
+ 	display_ldtr();
+ 	kdb_printf("\n");
+ 	display_cr0();
+ 	display_cr3();
+ 	display_cr4();
+ 	kdb_printf("\n");
+ 	display_dr();
+ 	return 0;
+ }
+ 
+ static int __init kdbm_x86_init(void)
+ {
+ 	kdb_register("rdv", kdb_rdv, NULL, "Display registers in verbose mode", 0);
+ 	kdb_register_repeat("gdt", kdb_gdt, "<sel> [<count>]", "Display GDT", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("idt", kdb_idt, "<int> [<count>]", "Display IDT", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("ldt", kdb_ldt, "<sel> [<count>]", "Display LDT", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("ptex", kdb_pte, "<addr> [<count>]", "Display pagetables", 0, KDB_REPEAT_NO_ARGS);
+ 	kdb_register_repeat("ldtp", kdb_ldt, "<sel> [<count>]", "Display Process LDT", 0, KDB_REPEAT_NO_ARGS);
+ 	return 0;
+ }
+ 
+ static void __exit kdbm_x86_exit(void)
+ {
+ 	kdb_unregister("rdv");
+ 	kdb_unregister("gdt");
+ 	kdb_unregister("ldt");
+ 	kdb_unregister("idt");
+ 	kdb_unregister("ptex");
+ 	kdb_unregister("ldtp");
+ }
+ 
+ module_init(kdbm_x86_init)
+ module_exit(kdbm_x86_exit)
diff -c -r -N console-os/kdb/modules/Makefile console-os-kdb/kdb/modules/Makefile
*** console-os/kdb/modules/Makefile	1969-12-31 16:00:00.000000000 -0800
--- console-os-kdb/kdb/modules/Makefile	2007-01-10 14:02:29.000000000 -0800
***************
*** 0 ****
--- 1,42 ----
+ #
+ # Copyright (c) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ #
+ # This program is free software; you can redistribute it and/or modify it
+ # under the terms of version 2 of the GNU General Public License as
+ # published by the Free Software Foundation.
+ #
+ # This program is distributed in the hope that it would be useful, but
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ #
+ # Further, this software is distributed without any warranty that it is
+ # free of the rightful claim of any third person regarding infringement
+ # or the like.  Any license provided herein, whether implied or
+ # otherwise, applies only to this software file.  Patent licenses, if
+ # any, provided herein do not apply to combinations of this program with
+ # other software, or any other product whatsoever.
+ #
+ # You should have received a copy of the GNU General Public License along
+ # with this program; if not, write the Free Software Foundation, Inc., 59
+ # Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ #
+ # Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ # Mountain View, CA  94043, or:
+ #
+ # http://www.sgi.com
+ #
+ # For further information regarding this notice, see:
+ #
+ # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ #
+ 
+ O_TARGET := vmlinux-obj.o
+ obj-$(CONFIG_KDB_MODULES) += kdbm_vm.o kdbm_pg.o kdbm_task.o
+ ifdef CONFIG_X86
+ obj-$(CONFIG_KDB_MODULES) += kdbm_x86.o
+ endif
+ CFLAGS_kdbm_vm.o	+= -I $(TOPDIR)/drivers/scsi
+ 
+ EXTRA_CFLAGS += -I $(TOPDIR)/arch/$(ARCH)/kdb
+ 
+ include $(TOPDIR)/Rules.make
diff -c -r -N console-os/kernel/kallsyms.c console-os-kdb/kernel/kallsyms.c
*** console-os/kernel/kallsyms.c	2006-11-20 12:24:28.000000000 -0800
--- console-os-kdb/kernel/kallsyms.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 19,24 ****
--- 19,443 ----
     Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    */
  
+ /*
+    This code uses the list of all kernel and module symbols to :-
+ 
+    * Find any non-stack symbol in a kernel or module.  Symbols do
+      not have to be exported for debugging.
+ 
+    * Convert an address to the module (or kernel) that owns it, the
+      section it is in and the nearest symbol.  This finds all non-stack
+      symbols, not just exported ones.
+ 
+    You need modutils >= 2.3.11 and a kernel with the kallsyms patch
+    which was compiled with CONFIG_KALLSYMS.
+  */
+ 
+ #include <linux/elf.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/kallsyms.h>
+ #include <linux/kdb.h>
+ 
+ /* These external symbols are only set on kernels compiled with
+  * CONFIG_KALLSYMS.
+  */
+ 
+ extern const char __start___kallsyms[];
+ extern const char __stop___kallsyms[];
+ 
+ static struct module **kallsyms_module_list;
+ 
+ static void kallsyms_get_module_list(void)
+ {
+ 	const struct kallsyms_header	*ka_hdr;
+ 	const struct kallsyms_section	*ka_sec;
+ 	const struct kallsyms_symbol	*ka_sym;
+ 	const char			*ka_str;
+ 	int i;
+ 	const char *p;
+ 
+ 	if (__start___kallsyms >= __stop___kallsyms)
+ 		return;
+ 	ka_hdr = (struct kallsyms_header *)__start___kallsyms;
+ 	ka_sec = (struct kallsyms_section *)
+ 		((char *)(ka_hdr) + ka_hdr->section_off);
+ 	ka_sym = (struct kallsyms_symbol *)
+ 		((char *)(ka_hdr) + ka_hdr->symbol_off);
+ 	ka_str = 
+ 		((char *)(ka_hdr) + ka_hdr->string_off);
+ 
+ 	for (i = 0; i < ka_hdr->symbols; kallsyms_next_sym(ka_hdr, ka_sym), ++i) {
+ 		p = ka_str + ka_sym->name_off;
+ 		if (strcmp(p, "module_list") == 0) {
+ 			if (ka_sym->symbol_addr)
+ 				kallsyms_module_list = (struct module **)(ka_sym->symbol_addr);
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ static inline void kallsyms_do_first_time(void)
+ {
+ 	static int first_time = 1;
+ 	if (first_time)
+ 		kallsyms_get_module_list();
+ 	first_time = 0;
+ }
+ 
+ /* A symbol can appear in more than one module.  A token is used to
+  * restart the scan at the next module, set the token to 0 for the
+  * first scan of each symbol.
+  */
+ 
+ int kallsyms_symbol_to_address(
+ 	const char	 *name,		/* Name to lookup */
+ 	unsigned long 	 *token,	/* Which module to start at */
+ 	const char	**mod_name,	/* Set to module name */
+ 	unsigned long 	 *mod_start,	/* Set to start address of module */
+ 	unsigned long 	 *mod_end,	/* Set to end address of module */
+ 	const char	**sec_name,	/* Set to section name */
+ 	unsigned long 	 *sec_start,	/* Set to start address of section */
+ 	unsigned long 	 *sec_end,	/* Set to end address of section */
+ 	const char	**sym_name,	/* Set to full symbol name */
+ 	unsigned long 	 *sym_start,	/* Set to start address of symbol */
+ 	unsigned long 	 *sym_end	/* Set to end address of symbol */
+ 	)
+ {
+ 	const struct kallsyms_header	*ka_hdr = NULL;	/* stupid gcc */
+ 	const struct kallsyms_section	*ka_sec;
+ 	const struct kallsyms_symbol	*ka_sym = NULL;
+ 	const char			*ka_str = NULL;
+ 	const struct module *m;
+ 	int i = 0, l;
+ 	const char *p, *pt_R;
+ 	char *p2;
+ 
+ 	kallsyms_do_first_time();
+ 	if (!kallsyms_module_list)
+ 		return(0);
+ 
+ 	/* Restart? */
+ 	m = *kallsyms_module_list;
+ 	if (token && *token) {
+ 		for (; m; m = m->next)
+ 			if ((unsigned long)m == *token)
+ 				break;
+ 		if (m)
+ 			m = m->next;
+ 	}
+ 
+ 	for (; m; m = m->next) {
+ 		if (!mod_member_present(m, kallsyms_start) || 
+ 		    !mod_member_present(m, kallsyms_end) ||
+ 		    m->kallsyms_start >= m->kallsyms_end)
+ 			continue;
+ 		ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
+ 		ka_sym = (struct kallsyms_symbol *)
+ 			((char *)(ka_hdr) + ka_hdr->symbol_off);
+ 		ka_str = 
+ 			((char *)(ka_hdr) + ka_hdr->string_off);
+ 		for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
+ 			p = ka_str + ka_sym->name_off;
+ 			if (strcmp(p, name) == 0)
+ 				break;
+ 			/* Unversioned requests match versioned names */
+ 			if (!(pt_R = strstr(p, "_R")))
+ 				continue;
+ 			l = strlen(pt_R);
+ 			if (l < 10)
+ 				continue;	/* Not _R.*xxxxxxxx */
+ 			(void)simple_strtoul(pt_R+l-8, &p2, 16);
+ 			if (*p2)
+ 				continue;	/* Not _R.*xxxxxxxx */
+ 			if (strncmp(p, name, pt_R-p) == 0)
+ 				break;	/* Match with version */
+ 		}
+ 		if (i < ka_hdr->symbols)
+ 			break;
+ 	}
+ 
+ 	if (token)
+ 		*token = (unsigned long)m;
+ 	if (!m)
+ 		return(0);	/* not found */
+ 
+ 	ka_sec = (const struct kallsyms_section *)
+ 		((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off);
+ 	*mod_name = *(m->name) ? m->name : "kernel";
+ 	*mod_start = ka_hdr->start;
+ 	*mod_end = ka_hdr->end;
+ 	*sec_name = ka_sec->name_off + ka_str;
+ 	*sec_start = ka_sec->start;
+ 	*sec_end = ka_sec->start + ka_sec->size;
+ 	*sym_name = ka_sym->name_off + ka_str;
+ 	*sym_start = ka_sym->symbol_addr;
+ 	if (i < ka_hdr->symbols-1) {
+ 		const struct kallsyms_symbol *ka_symn = ka_sym;
+ 		kallsyms_next_sym(ka_hdr, ka_symn);
+ 		*sym_end = ka_symn->symbol_addr;
+ 	}
+ 	else
+ 		*sym_end = *sec_end;
+ 	return(1);
+ }
+ 
+ int kallsyms_address_to_symbol(
+ 	unsigned long	  address,	/* Address to lookup */
+ 	const char	**mod_name,	/* Set to module name */
+ 	unsigned long 	 *mod_start,	/* Set to start address of module */
+ 	unsigned long 	 *mod_end,	/* Set to end address of module */
+ 	const char	**sec_name,	/* Set to section name */
+ 	unsigned long 	 *sec_start,	/* Set to start address of section */
+ 	unsigned long 	 *sec_end,	/* Set to end address of section */
+ 	const char	**sym_name,	/* Set to full symbol name */
+ 	unsigned long 	 *sym_start,	/* Set to start address of symbol */
+ 	unsigned long 	 *sym_end	/* Set to end address of symbol */
+ 	)
+ {
+ 	const struct kallsyms_header	*ka_hdr = NULL;	/* stupid gcc */
+ 	const struct kallsyms_section	*ka_sec = NULL;
+ 	const struct kallsyms_symbol	*ka_sym;
+ 	const char			*ka_str;
+ 	const struct module *m;
+ 	int i;
+ 	unsigned long end;
+ 
+ 	kallsyms_do_first_time();
+ 	if (!kallsyms_module_list)
+ 		return(0);
+ 
+ 	for (m = *kallsyms_module_list; m; m = m->next) {
+ 		if (!mod_member_present(m, kallsyms_start) || 
+ 		    !mod_member_present(m, kallsyms_end) ||
+ 		    m->kallsyms_start >= m->kallsyms_end)
+ 			continue;
+ 		ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
+ 		ka_sec = (const struct kallsyms_section *)
+ 			((char *)ka_hdr + ka_hdr->section_off);
+ 		/* Is the address in any section in this module? */
+ 		for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
+ 			if (ka_sec->start <= address &&
+ 			    (ka_sec->start + ka_sec->size) > address)
+ 				break;
+ 		}
+ 		if (i < ka_hdr->sections)
+ 			break;	/* Found a matching section */
+ 	}
+ 
+ 	if (!m)
+ 		return(0);	/* not found */
+ 
+ 	ka_sym = (struct kallsyms_symbol *)
+ 		((char *)(ka_hdr) + ka_hdr->symbol_off);
+ 	ka_str = 
+ 		((char *)(ka_hdr) + ka_hdr->string_off);
+ 	*mod_name = *(m->name) ? m->name : "kernel";
+ 	*mod_start = ka_hdr->start;
+ 	*mod_end = ka_hdr->end;
+ 	*sec_name = ka_sec->name_off + ka_str;
+ 	*sec_start = ka_sec->start;
+ 	*sec_end = ka_sec->start + ka_sec->size;
+ 	*sym_name = *sec_name;		/* In case we find no matching symbol */
+ 	*sym_start = *sec_start;
+ 	*sym_end = *sec_end;
+ 
+ 	for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
+ 		if (ka_sym->symbol_addr > address)
+ 			continue;
+ 		if (i < ka_hdr->symbols-1) {
+ 			const struct kallsyms_symbol *ka_symn = ka_sym;
+ 			kallsyms_next_sym(ka_hdr, ka_symn);
+ 			end = ka_symn->symbol_addr;
+ 		}
+ 		else
+ 			end = *sec_end;
+ 		if (end <= address)
+ 			continue;
+ 		if ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off
+ 		    != (char *)ka_sec)
+ 			continue;	/* wrong section */
+ 		*sym_name = ka_str + ka_sym->name_off;
+ 		*sym_start = ka_sym->symbol_addr;
+ 		*sym_end = end;
+ 		break;
+ 	}
+ 	return(1);
+ }
+ 
+ /* List all sections in all modules.  The callback routine is invoked with
+  * token, module name, section name, section start, section end, section flags.
+  */
+ int kallsyms_sections(void *token,
+ 		      int (*callback)(void *, const char *, const char *, ElfW(Addr), ElfW(Addr), ElfW(Word)))
+ {
+ 	const struct kallsyms_header	*ka_hdr = NULL;	/* stupid gcc */
+ 	const struct kallsyms_section	*ka_sec = NULL;
+ 	const char			*ka_str;
+ 	const struct module *m;
+ 	int i;
+ 
+ 	kallsyms_do_first_time();
+ 	if (!kallsyms_module_list)
+ 		return(0);
+ 
+ 	for (m = *kallsyms_module_list; m; m = m->next) {
+ 		if (!mod_member_present(m, kallsyms_start) || 
+ 		    !mod_member_present(m, kallsyms_end) ||
+ 		    m->kallsyms_start >= m->kallsyms_end)
+ 			continue;
+ 		ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
+ 		ka_sec = (const struct kallsyms_section *) ((char *)ka_hdr + ka_hdr->section_off);
+ 		ka_str = ((char *)(ka_hdr) + ka_hdr->string_off);
+ 		for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
+ 			if (callback(
+ 				token,
+ 				*(m->name) ? m->name : "kernel",
+ 				ka_sec->name_off + ka_str,
+ 				ka_sec->start,
+ 				ka_sec->start + ka_sec->size,
+ 				ka_sec->flags))
+ 				return(0);
+ 		}
+ 	}
+ 	return(1);
+ }
+ 
+ 
+ /* paramter prefix_name is a buffer provided by the caller, it must ends with '\0'. */
+ /* return the extra string together with the given prefix of a symbol name. */
+ /* return 0 means no prefix string is found. */
+ /* return >0 means prefix string is found. */
+ int kallsyms_symbol_complete(
+ 	char	 *prefix_name	/* Prefix of a symbol name to lookup */
+ 	)
+ {
+ 	const struct kallsyms_header	*ka_hdr = NULL;	/* stupid gcc */
+ 	const struct kallsyms_symbol	*ka_sym = NULL;
+ 	const char			*ka_str = NULL;
+ 	const struct module *m;
+ 	int i = 0;
+ 	int prefix_len=strlen(prefix_name);
+ 	int cur_pos=0, last_pos=0;
+ 	int find=0;
+ 	int number=0;
+ 	const char *p;
+ 
+ 	kallsyms_do_first_time();
+ 	if (!kallsyms_module_list)
+ 		return(0);
+ 
+ 	for (m = *kallsyms_module_list; m; m = m->next) {
+ 		if (!mod_member_present(m, kallsyms_start) ||
+ 		    !mod_member_present(m, kallsyms_end) ||
+ 		    m->kallsyms_start >= m->kallsyms_end)
+ 			continue;
+ 		ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
+ 		ka_sym = (struct kallsyms_symbol *)
+ 			((char *)(ka_hdr) + ka_hdr->symbol_off);
+ 		ka_str =
+ 			((char *)(ka_hdr) + ka_hdr->string_off);
+ 		for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
+ 			p = ka_str + ka_sym->name_off;
+ 			if (strncmp(p, prefix_name,prefix_len) == 0) {
+ 				++number;
+ 				if (find == 0) {
+ 					last_pos = strlen(p);
+ 					strncpy(prefix_name, p, last_pos+1);
+ 					find = 1;
+ 				}
+ 				else {
+ 					for (cur_pos = prefix_len ; cur_pos < last_pos; cur_pos++) {
+ 						if (*(p + cur_pos) == '\0'
+ 							|| *(p + cur_pos) != prefix_name[cur_pos]) {
+ 							last_pos = cur_pos;
+ 							prefix_name[cur_pos] = '\0';
+ 							break;
+ 						}
+ 					}
+ 				}
+ 			}
+ 		}
+ 	}
+ 
+ 	return number;
+ }
+ 
+ /* paramter prefix_name is a buffer provided by the caller, it must ends with '\0'. */
+ /* parameter flag = 0 means search from the head, flag = 1 means continue search. */
+ /* return a symbol string which matches the given prefix. */
+ /* return 0 means no prefix string is found. */
+ /* return >0 means prefix string is found. */
+ int kallsyms_symbol_next(
+ 	char	 *prefix_name,	/* Prefix of a symbol name to lookup */
+ 	int flag			/* Indicate if search from the head */
+ 	)
+ {
+ 	const struct kallsyms_header	*ka_hdr = NULL;	/* stupid gcc */
+ 	const char			*ka_str = NULL;
+ 	static const struct kallsyms_symbol	*ka_sym;
+ 	static const struct module *m;
+ 	static int i;
+ 	int prefix_len=strlen(prefix_name);
+ 	const char *p;
+ 
+ 	kallsyms_do_first_time();
+ 	if (!kallsyms_module_list)
+ 		return(0);
+ 
+ 	if(!flag) {
+ 		m = *kallsyms_module_list;
+ 	}
+ 
+ 	for (; m; m = m->next) {
+ 		if (!mod_member_present(m, kallsyms_start) ||
+ 		    !mod_member_present(m, kallsyms_end) ||
+ 		    m->kallsyms_start >= m->kallsyms_end)
+ 			continue;
+ 		ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
+ 		if(!flag) {
+ 			ka_sym = (struct kallsyms_symbol *)
+ 				((char *)(ka_hdr) + ka_hdr->symbol_off);
+ 			i = 0;
+ 		}
+ 		ka_str = ((char *)(ka_hdr) + ka_hdr->string_off);
+ 
+ 		for (; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
+ 			p = ka_str + ka_sym->name_off;
+ 			if (strncmp(p, prefix_name,prefix_len) == 0) {
+ 				strncpy(prefix_name, p, strlen(p)+1);
+ 				++i;
+ 				kallsyms_next_sym(ka_hdr, ka_sym);
+ 				return 1;
+ 			}
+ 		}
+ 	}
+ 
+ 	return 0;
+ }
+ #if 0
+ /* An example of using kallsyms data in a kernel debugger.
+ 
+    Copyright 2000 Keith Owens <kaos@ocs.com.au> April 2000
+ 
+    This file is part of the Linux modutils.
+ 
+    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 of the License, 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.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software Foundation,
+    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   */
+ 
  #ident "$Id: linux-2.4.9-kallsyms.patch,v 1.8 2002/02/11 18:34:53 arjanv Exp $"
  
  /*
***************
*** 304,306 ****
--- 723,726 ----
  	}
  	return(1);
  }
+ #endif
diff -c -r -N console-os/kernel/ksyms.c console-os-kdb/kernel/ksyms.c
*** console-os/kernel/ksyms.c	2006-11-20 12:24:28.000000000 -0800
--- console-os-kdb/kernel/ksyms.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 99,106 ****
  extern const char __stop___kallsyms[];
  EXPORT_SYMBOL(__start___kallsyms);
  EXPORT_SYMBOL(__stop___kallsyms);
! 
! 
  #endif
  
  /* process memory management */
--- 99,106 ----
  extern const char __stop___kallsyms[];
  EXPORT_SYMBOL(__start___kallsyms);
  EXPORT_SYMBOL(__stop___kallsyms);
! EXPORT_SYMBOL(kallsyms_symbol_to_address);
! EXPORT_SYMBOL(kallsyms_address_to_symbol);
  #endif
  
  /* process memory management */
***************
*** 673,678 ****
--- 673,683 ----
  EXPORT_SYMBOL(dump_stack);
  EXPORT_SYMBOL(lookup_symbol);
  
+ #if defined(CONFIG_KDB_USB)
+ #include <linux/kdb.h>
+ EXPORT_SYMBOL(kdb_usb_infos);
+ #endif
+ 
  EXPORT_SYMBOL_GPL(netdump_func);
  EXPORT_SYMBOL_GPL(netdump_mode);
  EXPORT_SYMBOL_GPL(netdump_register_hooks);
diff -c -r -N console-os/kernel/module.c console-os-kdb/kernel/module.c
*** console-os/kernel/module.c	2006-11-20 12:24:28.000000000 -0800
--- console-os-kdb/kernel/module.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 4,9 ****
--- 4,10 ----
  #include <asm/module.h>
  #include <linux/notifier.h>
  #include <asm/uaccess.h>
+ #include <linux/kallsyms.h>
  #include <linux/vmalloc.h>
  #include <linux/smp_lock.h>
  #include <asm/pgalloc.h>
***************
*** 1296,1301 ****
--- 1297,1328 ----
  	show:	s_show
  };
  
+ #define MODLIST_SIZE 4096
+ 
+ #if 0
+ /*
+  * this function isn't smp safe but that's not really a problem; it's
+  * called from oops context only and any locking could actually prevent
+  * the oops from going out; the line that is generated is informational
+  * only and should NEVER prevent the real oops from going out. 
+  */
+ void print_modules(void)
+ {
+ 	static char modlist[MODLIST_SIZE];
+ 	struct module *this_mod;
+ 	int pos = 0;
+ 
+ 	this_mod = module_list;
+ 	while (this_mod) {
+ 		if (this_mod->name)
+ 			pos += snprintf(modlist+pos, MODLIST_SIZE-pos-1, 
+ 					"%s ", this_mod->name);
+ 		this_mod = this_mod->next;
+ 	}
+ 	printk("%s\n",modlist);
+ }
+ #endif
+ 
  #else		/* CONFIG_MODULES */
  
  /* Dummy syscalls for people who don't want modules */
***************
*** 1341,1344 ****
--- 1368,1450 ----
  	return 1;
  }
  
+ #if 0
+ void print_modules(void)
+ {
+ }
+ #endif
+ 
  #endif	/* CONFIG_MODULES */
+ 
+ 
+ #if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
+ 
+ #define MAX_SYMBOL_SIZE 512
+ 
+ static void
+ address_to_exported_symbol(unsigned long address, const char **mod_name, 
+ 			   const char **sym_name, unsigned long *sym_start,
+ 			   unsigned long *sym_end)
+ {
+ 	struct module *this_mod;
+ 	int i;
+ 
+ 	for (this_mod = module_list; this_mod; this_mod = this_mod->next) {
+ 		/* walk the symbol list of this module. Only symbols
+ 		   who's address is smaller than the searched for address
+ 		   are relevant; and only if it's better than the best so far */
+ 		for (i = 0; i < this_mod->nsyms; i++)
+ 			if ((this_mod->syms[i].value <= address) &&
+ 			    (*sym_start < this_mod->syms[i].value)) {
+ 				*sym_start = this_mod->syms[i].value;
+ 				*sym_name  = this_mod->syms[i].name;
+ 				*mod_name  = this_mod->name;
+ 				if (i + 1 < this_mod->nsyms)
+ 					*sym_end = this_mod->syms[i+1].value;
+ 				else
+ 					*sym_end = (unsigned long) this_mod + this_mod->size;
+ 			}
+ 	}
+ }
+ 
+ void
+ print_symbol(const char *fmt, unsigned long address)
+ {
+ 	/* static to not take up stackspace; if we race here too bad */
+ 	static char buffer[MAX_SYMBOL_SIZE];
+ 
+ 	const char *mod_name = NULL, *sec_name = NULL, *sym_name = NULL;
+ 	unsigned long mod_start, mod_end, sec_start, sec_end,
+ 		sym_start, sym_end;
+ 	char *tag = "";
+ 	
+ 	memset(buffer, 0, MAX_SYMBOL_SIZE);
+ 
+ 	sym_start = 0;
+ 	if (!kallsyms_address_to_symbol(address, &mod_name, &mod_start, &mod_end, &sec_name, &sec_start, &sec_end, &sym_name, &sym_start, &sym_end)) {
+ 		tag = "E ";
+ 		address_to_exported_symbol(address, &mod_name, &sym_name, &sym_start, &sym_end);
+ 	}
+ 
+ 	if (sym_start) {
+ 		if (*mod_name)
+ 		    snprintf(buffer, MAX_SYMBOL_SIZE - 1, "%s%s+%#x/%#x [%s]",
+ 			 tag, sym_name,
+ 			 (unsigned int)(address - sym_start),
+ 			 (unsigned int)(sym_end - sym_start),
+ 			 mod_name);
+ 		else
+ 		    snprintf(buffer, MAX_SYMBOL_SIZE - 1, "%s%s+%#x/%#x",
+ 			 tag, sym_name,
+ 			 (unsigned int)(address - sym_start),
+ 			 (unsigned int)(sym_end - sym_start));
+ 		printk(fmt, buffer);
+ 	}
+ #if 0
+  else {
+ 		printk(fmt, "[unresolved]");
+ 	}
+ #endif
+ }
+ 
+ #endif
diff -c -r -N console-os/kernel/printk.c console-os-kdb/kernel/printk.c
*** console-os/kernel/printk.c	2006-11-20 12:24:28.000000000 -0800
--- console-os-kdb/kernel/printk.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 301,306 ****
--- 301,320 ----
  	return error;
  }
  
+ #ifdef	CONFIG_KDB
+ /* kdb dmesg command needs access to the syslog buffer.  do_syslog() uses locks
+  * so it cannot be used during debugging.  Just tell kdb where the start and
+  * end of the physical and logical logs are.  This is equivalent to do_syslog(3).
+  */
+ void kdb_syslog_data(char *syslog_data[4])
+ {
+ 	syslog_data[0] = log_buf;
+ 	syslog_data[1] = log_buf + sizeof(log_buf);
+ 	syslog_data[2] = log_buf + log_end - (logged_chars < LOG_BUF_LEN ? logged_chars : LOG_BUF_LEN);
+ 	syslog_data[3] = log_buf + log_end;
+ }
+ #endif
+ 
  asmlinkage long sys_syslog(int type, char * buf, int len)
  {
  	if ((type != 3) && !capable(CAP_SYS_ADMIN))
diff -c -r -N console-os/kernel/sched.c console-os-kdb/kernel/sched.c
*** console-os/kernel/sched.c	2006-11-20 12:24:28.000000000 -0800
--- console-os-kdb/kernel/sched.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 1458,1463 ****
--- 1458,1469 ----
  	}
  
  switch_tasks:
+ #ifdef        CONFIG_KDB
+ 	{
+ 		extern struct task_struct *kdb_active_task[];
+ 		kdb_active_task[smp_processor_id()] = next;
+ 	}
+ #endif
  	prefetch(next);
  	clear_tsk_need_resched(prev);
  
diff -c -r -N console-os/kernel/sysctl.c console-os-kdb/kernel/sysctl.c
*** console-os/kernel/sysctl.c	2006-11-20 12:24:28.000000000 -0800
--- console-os-kdb/kernel/sysctl.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 28,33 ****
--- 28,36 ----
  #include <linux/capability.h>
  #include <linux/smp_lock.h>
  #include <linux/init.h>
+ #ifdef	CONFIG_KDB
+ #include <linux/kdb.h>
+ #endif	/* CONFIG_KDB */
  #include <linux/sysrq.h>
  #include <linux/highuid.h>
  #include <linux/aio.h>
***************
*** 358,363 ****
--- 361,370 ----
  	{KERN_MEM_NMI_PANIC, "mem_nmi_panic", &mem_nmi_panic,
  	 sizeof(int), 0644, NULL, &proc_dointvec},
  #endif
+ #ifdef	CONFIG_KDB
+ 	{KERN_KDB, "kdb", &kdb_on, sizeof(int),
+ 	 0644, NULL, &proc_dointvec},
+ #endif	/* CONFIG_KDB */
  	{0}
  };
  
diff -c -r -N console-os/Makefile console-os-kdb/Makefile
*** console-os/Makefile	2007-01-09 18:00:45.000000000 -0800
--- console-os-kdb/Makefile	2007-01-10 14:02:29.000000000 -0800
***************
*** 138,143 ****
--- 138,148 ----
  LIBS		=$(TOPDIR)/lib/lib.a
  SUBDIRS		=kernel drivers mm fs net ipc lib crypto
  
+ ifeq ($(CONFIG_KDB),y)
+ CORE_FILES	+= kdb/kdb.o
+ SUBDIRS		+= kdb
+ endif
+ 
  DRIVERS-n :=
  DRIVERS-y :=
  DRIVERS-m :=
***************
*** 270,275 ****
--- 275,281 ----
  	scripts/lxdialog/*.o scripts/lxdialog/lxdialog \
  	.menuconfig.log \
  	include/asm \
+ 	kdb/gen-kdb_cmds.c \
  	.hdepend scripts/mkdep scripts/split-include scripts/docproc \
  	$(TOPDIR)/include/linux/modversions.h \
  	scripts/mkconfigs kernel/configs.c kernel/configs.o \
***************
*** 339,344 ****
--- 345,353 ----
  	@$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux3 > $(TMPPREFIX).tmp_kallsyms3.o
  endif
  	$(LD_VMLINUX) $(LD_VMLINUX_KALLSYMS) -o vmlinux
+ ifneq ($(TMPPREFIX),)
+ 	mv $(TMPPREFIX)vmlinux vmlinux
+ endif
  	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
  	@rm -f $(TMPPREFIX).tmp_vmlinux* $(TMPPREFIX).tmp_kallsyms*
  
diff -c -r -N console-os/mm/memory.c console-os-kdb/mm/memory.c
*** console-os/mm/memory.c	2006-11-20 12:24:30.000000000 -0800
--- console-os-kdb/mm/memory.c	2007-01-10 14:02:29.000000000 -0800
***************
*** 2079,2084 ****
--- 2079,2096 ----
  	return page;
  }
  
+ #ifdef CONFIG_KDB
+ struct page * kdb_follow_page(struct mm_struct *mm, unsigned long address, int write)
+ {
+       struct page *page = follow_page(mm, address, write);
+ 
+       if (!page)
+               return get_page_map(page);
+ 
+       return page;
+ }
+ #endif
+ 
  /*
   * Force in an entire range of pages from the current process's user VA,
   * and pin them in physical memory.  
