Update kdb patches.
authorAndreas Schwab <schwab@suse.de>
Mon, 18 Aug 2008 18:02:08 +0000 (18:02 +0000)
committerAndreas Schwab <schwab@suse.de>
Mon, 18 Aug 2008 18:02:08 +0000 (18:02 +0000)
suse-commit: 5f958a44099e0aa37de06cf197bb45d6147440f2

169 files changed:
Documentation/kdb/bt_x86 [new file with mode: 0644]
Documentation/kdb/kdb.mm [new file with mode: 0644]
Documentation/kdb/kdb_bp.man [new file with mode: 0644]
Documentation/kdb/kdb_bt.man [new file with mode: 0644]
Documentation/kdb/kdb_env.man [new file with mode: 0644]
Documentation/kdb/kdb_ll.man [new file with mode: 0644]
Documentation/kdb/kdb_md.man [new file with mode: 0644]
Documentation/kdb/kdb_ps.man [new file with mode: 0644]
Documentation/kdb/kdb_rd.man [new file with mode: 0644]
Documentation/kdb/kdb_sr.man [new file with mode: 0644]
Documentation/kdb/kdb_ss.man [new file with mode: 0644]
Documentation/kdb/slides [new file with mode: 0644]
Makefile
arch/ia64/Kconfig.debug
arch/ia64/Makefile
arch/ia64/include/asm/ansidecl.h [new file with mode: 0644]
arch/ia64/include/asm/bfd.h [new file with mode: 0644]
arch/ia64/include/asm/kdb.h [new file with mode: 0644]
arch/ia64/include/asm/kdb_break.h [new file with mode: 0644]
arch/ia64/include/asm/kdbprivate.h [new file with mode: 0644]
arch/ia64/include/asm/kmap_types.h
arch/ia64/include/asm/kregs.h
arch/ia64/kdb/ChangeLog [new file with mode: 0644]
arch/ia64/kdb/Makefile [new file with mode: 0644]
arch/ia64/kdb/cpu-ia64-opc.c [new file with mode: 0644]
arch/ia64/kdb/ia64-asmtab.c [new file with mode: 0644]
arch/ia64/kdb/ia64-asmtab.h [new file with mode: 0644]
arch/ia64/kdb/ia64-dis.c [new file with mode: 0644]
arch/ia64/kdb/ia64-opc.c [new file with mode: 0644]
arch/ia64/kdb/ia64-opc.h [new file with mode: 0644]
arch/ia64/kdb/ia64.h [new file with mode: 0644]
arch/ia64/kdb/kdb_cmds [new file with mode: 0644]
arch/ia64/kdb/kdba_bp.c [new file with mode: 0644]
arch/ia64/kdb/kdba_bt.c [new file with mode: 0644]
arch/ia64/kdb/kdba_fru.c [new file with mode: 0644]
arch/ia64/kdb/kdba_id.c [new file with mode: 0644]
arch/ia64/kdb/kdba_io.c [new file with mode: 0644]
arch/ia64/kdb/kdba_jmp.S [new file with mode: 0644]
arch/ia64/kdb/kdba_pod.c [new file with mode: 0644]
arch/ia64/kdb/kdba_support.c [new file with mode: 0644]
arch/ia64/kernel/head.S
arch/ia64/kernel/mca.c
arch/ia64/kernel/smp.c
arch/ia64/kernel/traps.c
arch/ia64/kernel/unwind.c
arch/x86/Kconfig.debug
arch/x86/Makefile
arch/x86/kdb/ChangeLog [new file with mode: 0644]
arch/x86/kdb/ChangeLog_32 [new file with mode: 0644]
arch/x86/kdb/ChangeLog_64 [new file with mode: 0644]
arch/x86/kdb/Makefile [new file with mode: 0644]
arch/x86/kdb/Makefile_32 [new file with mode: 0644]
arch/x86/kdb/Makefile_64 [new file with mode: 0644]
arch/x86/kdb/i386-dis.c [new file with mode: 0644]
arch/x86/kdb/kdb_cmds_32 [new file with mode: 0644]
arch/x86/kdb/kdb_cmds_64 [new file with mode: 0644]
arch/x86/kdb/kdba_bp_32.c [new file with mode: 0644]
arch/x86/kdb/kdba_bp_64.c [new file with mode: 0644]
arch/x86/kdb/kdba_bt.c [new file with mode: 0644]
arch/x86/kdb/kdba_id.c [new file with mode: 0644]
arch/x86/kdb/kdba_io.c [new file with mode: 0644]
arch/x86/kdb/kdba_support.c [new file with mode: 0644]
arch/x86/kdb/kdbasupport_32.c [new file with mode: 0644]
arch/x86/kdb/kdbasupport_64.c [new file with mode: 0644]
arch/x86/kdb/pc_keyb.h [new file with mode: 0644]
arch/x86/kdb/x86_64-dis.c [new file with mode: 0644]
arch/x86/kernel/crash.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/io_apic_32.c
arch/x86/kernel/io_apic_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/traps_32.c
arch/x86/kernel/traps_64.c
drivers/char/keyboard.c
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/usbkbd.c
drivers/serial/8250.c
drivers/serial/8250_early.c
drivers/serial/sn_console.c
drivers/usb/core/hcd.c
drivers/usb/core/hcd.h
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-q.c
fs/proc/mmu.c
fs/proc/proc_misc.c
include/asm-x86/ansidecl.h [new file with mode: 0644]
include/asm-x86/ansidecl_32.h [new file with mode: 0644]
include/asm-x86/ansidecl_64.h [new file with mode: 0644]
include/asm-x86/bfd.h [new file with mode: 0644]
include/asm-x86/bfd_32.h [new file with mode: 0644]
include/asm-x86/bfd_64.h [new file with mode: 0644]
include/asm-x86/irq_vectors.h
include/asm-x86/kdb.h [new file with mode: 0644]
include/asm-x86/kdbprivate.h [new file with mode: 0644]
include/asm-x86/kdebug.h
include/asm-x86/kmap_types.h
include/asm-x86/ptrace.h
include/linux/console.h
include/linux/dis-asm.h [new file with mode: 0644]
include/linux/kdb.h [new file with mode: 0644]
include/linux/kdbprivate.h [new file with mode: 0644]
include/linux/reboot.h
include/linux/sysctl.h
init/main.c
kdb/ChangeLog [new file with mode: 0644]
kdb/Makefile [new file with mode: 0644]
kdb/kdb_bp.c [new file with mode: 0644]
kdb/kdb_bt.c [new file with mode: 0644]
kdb/kdb_cmds [new file with mode: 0644]
kdb/kdb_id.c [new file with mode: 0644]
kdb/kdb_io.c [new file with mode: 0644]
kdb/kdbdereference.c [new file with mode: 0644]
kdb/kdbmain.c [new file with mode: 0644]
kdb/kdbsupport.c [new file with mode: 0644]
kdb/modules/Makefile [new file with mode: 0644]
kdb/modules/kdbm_debugtypes.c [new file with mode: 0644]
kdb/modules/kdbm_pg.c [new file with mode: 0644]
kdb/modules/kdbm_sched.c [new file with mode: 0644]
kdb/modules/kdbm_task.c [new file with mode: 0644]
kdb/modules/kdbm_vm.c [new file with mode: 0644]
kdb/modules/kdbm_x86.c [new file with mode: 0644]
kdb/modules/lcrash/README [new file with mode: 0644]
kdb/modules/lcrash/asm/README [new file with mode: 0644]
kdb/modules/lcrash/asm/kl_dump_ia64.h [new file with mode: 0644]
kdb/modules/lcrash/asm/kl_types.h [new file with mode: 0644]
kdb/modules/lcrash/kl_alloc.h [new file with mode: 0644]
kdb/modules/lcrash/kl_bfd.h [new file with mode: 0644]
kdb/modules/lcrash/kl_btnode.h [new file with mode: 0644]
kdb/modules/lcrash/kl_cmp.h [new file with mode: 0644]
kdb/modules/lcrash/kl_copt.h [new file with mode: 0644]
kdb/modules/lcrash/kl_debug.h [new file with mode: 0644]
kdb/modules/lcrash/kl_dump.h [new file with mode: 0644]
kdb/modules/lcrash/kl_dump_arch.h [new file with mode: 0644]
kdb/modules/lcrash/kl_dump_ia64.h [new file with mode: 0644]
kdb/modules/lcrash/kl_dwarfs.h [new file with mode: 0644]
kdb/modules/lcrash/kl_error.h [new file with mode: 0644]
kdb/modules/lcrash/kl_htnode.h [new file with mode: 0644]
kdb/modules/lcrash/kl_lib.h [new file with mode: 0644]
kdb/modules/lcrash/kl_libutil.h [new file with mode: 0644]
kdb/modules/lcrash/kl_mem.h [new file with mode: 0644]
kdb/modules/lcrash/kl_mem_ia64.h [new file with mode: 0644]
kdb/modules/lcrash/kl_module.h [new file with mode: 0644]
kdb/modules/lcrash/kl_queue.h [new file with mode: 0644]
kdb/modules/lcrash/kl_stabs.h [new file with mode: 0644]
kdb/modules/lcrash/kl_stringtab.h [new file with mode: 0644]
kdb/modules/lcrash/kl_sym.h [new file with mode: 0644]
kdb/modules/lcrash/kl_task.h [new file with mode: 0644]
kdb/modules/lcrash/kl_typeinfo.h [new file with mode: 0644]
kdb/modules/lcrash/kl_types.h [new file with mode: 0644]
kdb/modules/lcrash/klib.h [new file with mode: 0644]
kdb/modules/lcrash/lc_eval.h [new file with mode: 0644]
kernel/exit.c
kernel/kallsyms.c
kernel/kexec.c
kernel/module.c
kernel/panic.c
kernel/printk.c
kernel/sched.c
kernel/signal.c
kernel/sysctl_check.c
lib/bug.c
mm/hugetlb.c
mm/mmzone.c
mm/swapfile.c

diff --git a/Documentation/kdb/bt_x86 b/Documentation/kdb/bt_x86
new file mode 100644 (file)
index 0000000..e751392
--- /dev/null
@@ -0,0 +1,1837 @@
+Copyright Keith Owens, 2007.
+
+How the KDB backtrace for x86 works, how to diagnose problems and submit a bug
+==============================================================================
+
+Unlike ia64, x86 architectures do not mandate unwind information in the kernel.
+gcc will include some unwind information for C functions, but not for assembler
+code.  Attempts have been made to add unwind information to the assembler code
+by hand, with little success.  Eventually Linus rejected the x86 unwind code
+because it was breaking too often and destroying useful debugging data.
+
+Even if the x86 unwinder worked correctly, it would only give an accurate
+backtrace, it would not give function arguments. Needless to say, function
+arguments are what people really want.  To get function arguments requires much
+more support from the compiler than simple unwind data, the compiler has to
+track line by line where each argument is held and make that data available to
+the debugger.  Compiling with gcc -g will provide that information, but the
+resulting kernel is several times larger than normal.
+
+Although the gcc -g data can be stored on another machine, there are constructs
+in the kernel that cannot be tracked by this method.  i386 builds with 4K stacks
+and all x86_64 builds have multiple kernel stacks.  The compiler knows nothing
+about these extra stacks and cannot backtrace through them correctly.  The
+assembler code in arch/{i386,x86_64}/kernel/entry.S is a maze of twisty logic
+paths, some of which eventually jump to common labels.  Describing this twisty
+logic to an unwinder is very difficult, expecially when you try to describe
+where arguments and/or registers are held).
+
+KDB gets an accurate x86 backtrace and extracts the arguments by performing code
+decomposition and analysis at run time.  This avoids the need to bloat the
+running kernel to several times its normal size with gcc -g data.  KDB (unlike
+gdb) also knows about the additional kernel stacks and twisty assembler code
+paths.
+
+The x86 backtrace code for i386 is very similar to the x86_64 code, with 80%
+common code and data.  Most of the differences between the backtrace for the two
+architectures is due to the assembler code and stack handling.  To avoid code
+duplication between KDB patches, the x86 backtrace code is actually stored in
+the kdb common patch, in source kdb/kdba_bt_x86.c.  kdb/Makefile only builds
+kdba_bt_x86.o for i386 or x86_64.  Most of the code reads as if the architecture
+is x86_64, using register names like rsp and rip.  i386 is treated as a subset
+of x86_64, with fewer registers and printing the names as esp and eip.  When
+this documentation refers to rsp and rip, read it as esp and eip for i386.  The
+20% of code and data that is different in held in two large #ifdef sections,
+scan kdba_bt_x86.c for CONFIG_X86_64.  Be careful when changing anything in the
+architecture specific sections, you will need to review the other architecture
+to see if it needs changes as well.
+
+The idea behind the x86 backtrace is to trace one function at a time, which
+gives us the calling function.  Then apply the same algorithm to the calling
+function until you unwind to the first function in the process.  The starting
+point for tracing any process is to extract the current stack pointer and
+current instruction pointer (rsp and rip).  The way that these values are
+extracted varies between running tasks and blocked tasks, the method is
+described later (Process Starting Point) but ignore it for now, just assume that
+we have a starting rsp and rip.
+
+Given the instruction pointer (rip), we identify the start and end of the kernel
+or module function it is in, using the kernel symbol table.  This is easy for C
+code, it is significantly harder for assembler code because of the twisty code
+paths that branch to common labels.  The method of identifying the current
+function is described later (Identifying The Current Function) but ignore it for
+now, just assumes that we have the start and end address of the function plus
+its name.
+
+After the rip has been mapped to a function name with sensible start and end
+addresses, the next step is to analyse the code paths in that function.  KDB
+already has a built in disassembler (copied with slight modifications from
+binutils) which knows how to decode each x86 instruction.  Instead of
+duplicating that logic in kdba_bt_x86, it takes advantage of the fact that you
+can override the disassembler's print function, sending the output line to a
+buffer instead of printing it.  kdba_bt_x86 stills has to decode the buffer but
+that is a lot easier than decoding the x86 instruction set.
+
+The code analysis consists of two main passes.  There are example below of the
+analysis with basic block (bb) debugging activated (Examples of Basic Block
+Debugging Output).
+
+The first pass (bb_pass1) identifies all the basic blocks in the function.  For
+our purposes, a basic block has a single entry point and one or more exit
+points.  The start of the function is the start of basic block 0, all other
+blocks are the target of jump instructions (conditional or unconditional) from
+within the rest of the code.  A block ends with an unconditional jump or with a
+terminating instruction such as ret, iret, sysexit, sysret or ud2a (BUG).  A
+block can also end because the next instruction is the start of a new block
+(target of jmp or jcc), in this case there is an implied drop through from one
+block to the next.
+
+Although a call instruction also transfers control, it returns to the next
+instruction so call is not treated as a transfer.  Instead call is treated as a
+normal instruction with side effects, the scratch registers are cleared after a
+call.
+
+At the end of the first pass over the function we have a directed graph that
+starts at bb[0].  The nodes of the graph (bb_list[]) are the basic blocks with
+their start and end address.  The vertices are the jmp or jcc instructions
+(bb_jmp_list[]) that transfer control between blocks, plus any implied drop
+through transfers between consecutive blocks.  This graph can have cycles, many
+functions have loops in them which transfer control back to earlier in the code
+body.
+
+The second pass (bb_pass2) runs over the directed graph analysing the effect of
+each instruction on the register and memory state.  It is important to
+understand that the analysis in this pass is an abstract one, it does not use
+actual hex values for the register contents, instead it uses symbolic values.
+When the basic block code says that "register rsi contains value rax" it means
+that whatever value was in rax on entry to the function has also been copied to
+register rsi at this point in the logic flow.
+
+At an abstract level, all C functions start with exactly the same state, each
+register contains its own symbolic value (except for the stack pointer, see
+later) with no local stack variables defined yet.  Assembler functions tend to
+have unusual starting points, with some registers and/or memory contents defined
+differently on entry.  For example, ret_from_intr on i386 already has a struct
+pt_regs on its stack, ret_from_intr on x86_64 already has a partial struct
+pt_regs plus another two words stacked on top of it.  The special starting cases
+are listed in the arch specific bb_special_cases[].
+
+Once the input state of bb[0] has been defined (including any special cases),
+bb_pass2_do_changed_blocks() runs over all the nodes in bb_list[].  Each
+instruction in each block is analysed (Tracking the Effects of Instructions) to
+see what effect it has on the abstract register state, the analysis of each
+instruction is done in bb_usage().  An instruction can copy one register to
+another, it can copy a register to stack, move from stack to a register or it
+can invalidate the contents of a register or memory location.  A general rule in
+bb_usage() is that any operation whose results cannot be calculated in terms of
+an original input value gives an undefined result.  Remember that it is the
+abstract value that becomes undefined, moving a constant to a register gives a
+defined value for the view of the program but it is undefined as far as the
+abstract state is concerned.
+
+References to data on the stack are a little awkward because the stack pointer
+frequently changes.  To overcome this, kdba_bt_x86 defines a pseudo register
+called the 'original stack pointer' (osp).  This always represents the stack
+pointer on entry to the function, so on entry rsp contains osp+0x0.  As rsp is
+modified, it still points at osp, but its offset from osp changes.  Copying rsp
+to another register (e.g. mov %rsp,%rbp) copies the osp offset as well.  At the
+point that this function calls the next function down the stack, kdba_bt_x86
+knows the delta from osp to rsp.  Applying that delta to the actual value of the
+stack pointer gives the stack pointer value on input to the current function,
+that location contains the return address so we can go up one stack frame and
+repeat the process.
+
+After doing basic block analysis on the current function, kdba_bt_x86 knows what
+the abstract register and memory state is at the point this function was
+interrupted or it called the next function down the stack, this is the exit
+state.  For an interrupt the actual register values are saved in a struct
+pt_regs, for a call we have unwound from the KDB interrupt back to the called
+function so we have some idea of what the register values are in the called
+function.  The abstract exit state is merged with the known actual register
+values to derive the original stack pointer.  That in turn gives us any
+registers that were saved on stack.  The original stack pointer gives the return
+address from the calling function, go up one stack frame and repeat the
+analysis.
+
+
+Process Starting Point
+======================
+
+All backtrace code needs a starting point which defines at least the stack
+pointer and instruction pointer, it may define other registers as well.  The
+first part of kdba_bt_stack() extracts the starting point.  Processes can be in
+one of three states, running (currently on a cpu), blocked (sleeping or ready to
+run but not currently on a cpu) or unknown.
+
+For running processes, the current rsp and rip are dynamic.  Because KDB stops
+the entire machine by sending an interrupt to the other cpus, KDB can save the
+rsp and rip for each cpu at the point where KDB is entered.  This data is held
+in array kdb_running_process and is stored by kdb_save_running() and the arch
+specific kdba_save_running() functions.  When backtracing a running process, KDB
+uses the data in kdb_running_process as its starting point.
+
+For blocked processes we always have the saved rsp, it is held in the process's
+thread_info.  For i386 blocked processes, thread_info also contains the saved
+rip.  For x86_64 blocked processes, rip is no longer saved in thread_info, it is
+assumed that all blocked processes will resume at assembler label thread_return,
+so that rip is used on x86_64.  See arch specific kdba_bt_stack_rip().
+
+Unknown process state only occurs when the user does 'bt <stack_address>'.
+Unlike other bt commands, 'bt <stack_address>' does not identify any specific
+process, instead it identifies a kernel stack.  <stack_address> must be inside a
+valid kernel stack and must point to a saved rip from a call instruction.
+kdba_bt_x86.c uses the common kdba_get_stack_info() and arch specific
+kdba_get_stack_info_alternate() functions to check that the address falls within
+a valid kernel stack.  If the user gives a stack address that does not point to
+a saved rip from a call instruction then the backtrace will be garbage.
+
+
+Identifying The Current Function
+================================
+
+Given a rip value, KDB uses the kallsyms data to find the start of the function
+(first address <= rip) and the end of the function (next symbol in kallsyms).
+This works for plain C code because gcc only generates one label per function.
+It does not work for assembler code or for assembler code embedded in C
+functions, because the assembler labels appear as global entries in kallsyms.
+For example, arch/i386/kernel/entry.S has function ret_from_exception which
+contains three global labels ret_from_intr, check_userspace and
+resume_userspace.  If rip points to any of those global labels, KDB wants the
+start of the real function, i.e. ret_from_exception.  In addition, if rip points
+to ret_from_exception, KDB wants the end of the function to be after the last
+global label in that function, i.e. after resume_userspace.
+
+The simplest way to handle these unwanted global labels is to list the spurious
+assembler labels, which is done in the arch specific array bb_spurious.  After
+mapping rip to the nearest start and end labels from kallsyms, kdb_bb() works
+backwards until it finds a non-spurious label then works forwards to the next
+non-spurious label.  That gives a real start and end address and a real name for
+the current function.
+
+Note that this algorithm only applies in kdb_bb() when it maps rip to a suitable
+start and end address.  When disassembling the code, you will still see the
+spurious label names, users need to see the extra labels.  ret_from_exception on
+i386 disassembles like this (2.6.22) :-
+
+[0]kdb> id ret_from_exception
+0xc0102554 ret_from_exception:         cli
+0xc0102555 ret_from_intr:         mov    $0xfffff000,%ebp
+0xc010255a ret_from_intr+0x5:     and    %esp,%ebp
+0xc010255c check_userspace:         mov    0x34(%esp),%eax
+0xc0102560 check_userspace+0x4:     mov    0x30(%esp),%al
+0xc0102564 check_userspace+0x8:     and    $0x20003,%eax
+0xc0102569 check_userspace+0xd:     cmp    $0x3,%eax
+0xc010256c check_userspace+0x10:    jb     0xc010258c resume_kernel
+0xc0102572 check_userspace+0x16:    mov    %esi,%esi
+0xc0102574 resume_userspace:         cli
+0xc0102575 resume_userspace+0x1:     mov    0x8(%ebp),%ecx
+0xc0102578 resume_userspace+0x4:     and    $0xfe3e,%ecx
+0xc010257e resume_userspace+0xa:     jne    0xc01026f4 work_pending
+0xc0102584 resume_userspace+0x10:    jmp    0xc01026a7 restore_all
+0xc0102589 resume_userspace+0x15:    lea    0x0(%esi),%esi
+0xc010258c resume_kernel:         cli
+
+For the purposes of kdba_bt_x86.c, any rip from 0xc0102554 to 0xc0102589 needs
+to map to the range 0xc0102554 (start) to 0xc010258c (end) with function name
+ret_from_exception.  Therefore ret_from_intr, check_userspace and
+resume_userspace are listed in bb_spurious[] for i386 so those symbols are
+ignored.  The comments in bb_spurious[] list the function that encloses each
+spurious label, those comments are only for humans, they do not affect the code.
+
+Once rip has been mapped to non-spurious labels, the module name, function name,
+start and end address are stored in variables bb_mod_name, bb_func_name,
+bb_func_start, bb_func_end.  These variables are used throughout kdba_bt_x86.c
+for processing each function in turn.
+
+Watch for changes to assembler code, especially in arch/i386/kernel/entry.S,
+arch/x86_64/kernel/entry.S and arch/x86_64/ia32/ia32entry.S.  When new labels
+are added you may need to adjust bb_spurious[] for that architecture.  Running
+bb_all can help identify assembler labels that have been added or deleted.
+
+
+Tracking the Effects of Instructions
+====================================
+
+bb_pass2_do_changed_blocks() uses the KDB disassembler to decode the x86
+instructions to something a human can read.  bb_dis_pass2() is used as a print
+routine to store data for a single instruction in a buffer then
+bb_parse_buffer() starts the analysis.  Any instruction prefixes like lock or
+rep are stripped out.  The opcode string is isolated then up to 3 operands are
+extracted (imul can have 3 operands), these are src, dst and dst2.  The operand
+is matched against table bb_opcode_usage_all[] which lists all the instructions
+that actually appear in i386 and x86_64 kernels.  A lot of the x86 instrcution
+set is not used by the kernel so instructions such as SSE do not appear in
+bb_opcode_usage_all[].
+
+Each operand is decoded by bb_parse_operand() to see whether it has a segment
+prefix, displacement, base, index or scale.  An indirect call or jmp is
+identified.  Operands consisting only of a register are classified as 'reg'
+type, displacements starting with '$' are immediate values otherwise the operand
+refers to a memory location.  Any base or index register name is mapped to the
+abstract register name that contains it, this takes care of mapping (say) %ah to
+rax.
+
+After decoding the opcode and all its operands, bb_usage() decides what effect
+the instruction will have on the abstract state machine.  Some x86 instructions
+list all the affected registers in their operands and these can be handled as
+generic cases.  Alas many x86 instructions have side effects and change
+registers that are not listed in the operands, these have to be handled as
+special cases.  enum bb_operand_usage lists the generic and special cases.
+
+bb_usage() is basically one huge switch statement over the special values in
+enum bb_operand_usage.  For each special case it tracks the side effects of the
+instruction.  Once all the special cases have been handled and converted to
+generic cases then bb_usage() handles the generic cases.
+
+bb_usage() detects when a register is copied to another register, a register is
+copied to stack or a known stack value is copied to a register and updates the
+state data accordingly.  It is particularly important that all stack pointer
+updates and copies of the stack pointer are tracked, much of the saved state is
+on stack and can be accessed via any register that points to the stack, not just
+via rsp.
+
+i386 built with 4K stacks and all x86_64 builds have multiple kernel stacks.
+bb_usage() knows which instructions or locations are used to switch stacks and
+pretends that these instructions have no effect on the contents of rsp.  The
+higher level backtrace code knows how to handle stack switching, it is too
+complicated for basic block analysis.
+
+
+Transfer of Control Outside the Current Function
+================================================
+
+Ignoring call instructions, most C code does not transfer control outside the
+current function, IOW there are no jump instructions to instructions outside the
+function.  There are a few cases that this can occur for C code, inline
+assembler and tail recursion.
+
+Tail recursion occurs when a function ends by returning the value from a second
+function and that second function has exactly the same arguments and return
+value as the current function.  For example,
+
+    int bar(int i, char *p)
+    {
+        ... do some work and return an int ...
+    }
+
+    int foo(int i, char *p)
+    {
+        return bar(i, p);
+    }
+
+If tail recursion is active (gcc -foptimize-sibling-calls) then instead of foo
+calling bar, bar returning to foo then foo returning to its caller, gcc will end
+foo with a direct jmp to bar.  The source code says that something called foo
+but the stack trace will show bar is active, with no sign of foo on stack.  When
+bar returns it will use the return address from the code that called foo.
+
+bb_transfer() detects an unconditional jmp to code outside the function body and
+assumes that this represents tail recursion.  For tail recursion to work
+correctly, all the preserved registers must contain their original values,
+bb_sanity_check() validates this.  Any deviation from the expected state will
+stop basic block analysis and fall back on the old unreliable backtrace code.
+
+Besides tail recursion in C code, assembler code can jump to labels outside the
+current function.  Unfortunately this occurs all the time in the twisty
+assembler code and, to make things worse, many of these transfers are done with
+non-standard register or memory state.  bb_special_case() and the arch specific
+bb_special_cases[] handle all the known special cases, including what the
+register and/or memory state should be.  Any deviation from the expected state
+will stop basic block analysis and fall back on the old unreliable backtrace
+code.
+
+
+Locating Arguments
+==================
+
+Function arguments can be passed in registers or on stack.  The full ABI for
+passing arguments is described in
+
+  http://www.caldera.com/developers/devspecs/abi386-4.pdf
+  http://www.x86-64.org/documentation/abi.pdf
+
+The short description, ignoring special cases like passing structures by name
+and floating point arguments which tend not to apply to the kernel, is :-
+
+i386.   With -mpregparm=0, all arguments are passed on stack, except for
+        functions defined as FASTCALL, where the first 3 arguments are passed in
+        registers.
+
+        With -mregparm=3, the first 3 arguments are passed in registers except
+        for functions defined as asmlinkage or with variable number of
+        arguments, when arguments are still passed on stack.  -mpregparm=3 used
+        to be a config option, in recent kernels it is the default.
+
+        Arguments defined as long long (64 bit) are passed in two registers or
+        in two locations on stack.  Being passed in two pieces makes a 64 bit
+        argument look like two 32 bit arguments to KDB, it will be printed as
+        two separate arguments.
+
+        When compiled with -mregparm=3, if a 64 bit argument is argument number
+        2 then it will not be split between register and stack, instead it will
+        all be on stack and the third argument register will not be used.  This
+        makes it look like there is an extra argument in the list.  There is
+        nothing that KDB can do to detect these corner cases with 64 bit
+        arguments on i386, which is a pity because they can confuse users.
+
+        The preserved registers are ebx, ebp, esp, esi, edi.  Arguments are
+        passed in eax, edx, ecx.  The return value is in eax.
+
+x86_64. The first 6 arguments are passed in registers, the 7th and later
+        arguments are passed on stack.  Except for functions with a variable
+        number of arguments (e.g. printk) where all arguments are on stack
+        except for rax which contains the number of SSE arguments (always 0 for
+        the kernel).
+
+        The preserved registers are rbx, rbp, rsp, r12, r13, r14, r15.
+        Arguments are passed in rdi, rsi, rdx, rcx, r8, r9.  The return value is
+        in rax.
+
+For both architectures, kdba_bt detects an argument that is passed in a register
+by the fact that the function code reads from that argument type register while
+it contains its original value.  IOW, testing the value of rax, copying rax to
+another register or storing it on stack without first overwriting rax means that
+rax contains a useful input value.  Reading from memory which is above the
+original stack pointer means that there is a argument at that location on
+stack.
+
+There are some functions in the kernel whose definition contains arguments that
+are not actually used.  Typically these functions are instantiations of generic
+function definitions where some, but not all, instantiations use all the
+arguments.  For example, a filesystem function may take flags that are not used
+by this particular filesystem, but the function definition has to match the
+generic filesystem declarations.  If the unused arguments are at the end of the
+list then there is no way of telling from the object code that they exist, the
+function that does not use the trailing aguments will have no code that refers
+to them.  KDB will print a truncated argument list for this case.
+
+If the unused arguments are not at the end of the list then KDB can detect the
+presence of the unused arguments, because there is code that refers to later
+arguments.  KDB will print the unused argument, although gcc may have
+overwritten the register it is in, in which case KDB prints "invalid".
+
+Originally kdba_bt_x86 would detect that there was no reference to arguments in
+registers but there were still references to arguments on stack and assume that
+the function had all its arguments on stack.  Unfortunately this did not work
+with the large number of 'pass through' functions in the kernel.  A 'pass
+through' function is one which calls another function with roughly the same
+argument list and makes no other reference to the register arguments.  For
+example, ipv4_doint_and_flush_strategy() takes 7 arguments, calls
+devinet_conf_sysctl() with those 7 arguments in the same order and has no other
+reference to any of its arguments.
+
+Pass through functions do not touch the arguments that are passed in registers
+because they are already in the right location for the routine about to be
+called, so the pass through function has no code that references the argument
+registers.  No code means that kdba_bt_x86 cannot tell if the function has
+register arguments or not.  The arguments passed on stack must always be copied
+to the new stack frame, even for pass through functions, so the arguments on
+stack can always be detected.
+
+kdba_bt_x86 was changed to assume that if there are any arguments on stack then
+there are always arguments in registers, except for a list of functions that are
+known to be asmlinkage or to have a variable number of arguments.
+bb_assume_pass_through() ignores the known special cases, for other functions
+which have stack arguments but no register arguments it assumes the function is
+pass through and prints a warning about that assumption.
+
+The above heuristics mean that there is one case that kdba_bt_x86 cannot detect:
+pass through functions where all the arguments are in registers.  These have no
+argument references at all in their code, so they are printed with no arguments.
+All they do is call another function so this class of functions never fails, or
+if it does fail then it is due to something that is not argument related.  If
+the failure is further down the call stack then the arguments are printed at the
+next function down the stack, so the user still has the arguments.
+
+This list of limitations on getting the x86 arguments may seem to be a long one,
+but kdba_bt_x86 gives sensible results for most functions.  For kernel
+debugging, any arguments are far better than none at all.
+
+
+Kernel Stack Switching
+======================
+
+Understanding the unusual way that x86 kernel stacks are used is very important
+when diagnosing backtrace problems.  Every process has its own normal kernel
+stack, even processes that run entirely within the kernel such as kthread or the
+per cpu migration processes.  The normal stacks are 4K or 8K on i386 (depending
+on CONFIG_4KSTACKS) and 8K on x86_64.  The normal stacks are global, they are
+not tied to any cpu.
+
+For i386 with 8K stacks there are no other kernel stacks so there is no stack
+switching to worry about.
+
+For i386 with 4K process stacks, each cpu also has a 4K soft irq stack and a 4K
+hard irq stack.  It is possible for a process to be running on its own process
+stack, for the process to be interrupted by a soft irq which is then interrupted
+by a hard irq.  At that point the backtrace is split between the hard irq, the
+soft irq and the normal normal stacks.
+
+On x86_64, each cpu always has stacks for stackfault, doublefault, nmi, debug,
+mce and interrupts.  See Documentation/x86_64/kernel-stacks.
+
+The arch specific kdba_get_stack_info_alternate() function works out which stack
+the backtrace starts on, how big the stack is and how to switch to the next
+stack.  This information is stored in the kdb_activation_record and used by the
+higher level backtrace code to detect a stack switch.
+
+The normal stack has some padding at the end, this reflects the stack pointer
+when the process was created in the kernel.  kdba_bt_x86 cannot backtrace
+through this padding data, mainly because the code that set the nitial stack
+pointer no longer exists after boot.  ARCH_NORMAL_PADDING defines how many words
+to ignore at the end of the normal stack.
+
+
+Debugging KDB
+=============
+
+KDB has conditional debugging print statements scattered throughout the code.
+If KDB is not behaving as expected, you can turn on debugging and rerun the
+command.  Before debugging KDB, set LINES 10000 and capture the output via a
+serial console.  If using minicom, turn on word wrap (control-A W) and capture
+mode (control-A L).  If you are using a serial console via a serial to Ethernet
+interface using ssh or telnet, use the 'script' command to start the session.
+
+The various KDB_DEBUG_FLAG_* flags are listed in include/linux/kdbprivate.h.
+You set debug with 'set KDBDEBUG 0xnn' where nn is the or'd value of the desired
+flags.  'set KDBDEBUG 0' turns off KDB debugging.  When diagnosing x86 backtrace
+problems, the most useful debug flags are
+
+  KDB_DEBUG_FLAG_ARA            0x10    Activation record, arch specific
+  KDB_DEBUG_FLAG_BB_SUMM        0x04    Basic block analysis, summary only
+  KDB_DEBUG_FLAG_BB             0x20    All basic block analysis
+
+ARA prints information about the different kernel stacks as kdba_bt_x86 unwinds
+through the switched kernel stacks.  BB_SUMM prints a summary of the basic block
+analysis for each function, including the abstract exit state and the rollback
+calculations.  BB prints a huge amount of basic block debugging, you probably
+only want to turn this for the full backtrace on as a last resort.
+
+I find 'set KDBDEBUG 0x14' to be best to get an overview of a problem.  It gives
+both the kernel stack information plus the abstract state and actual location of
+data for each function.
+
+Command 'bb1' does a detailed debug session for a single function, bb1 takes a
+single parameter, the address of the exit point from the function, by number,
+not by name.  bb1 turns on KDB_DEBUG_FLAG_BB, does basic block analysis for the
+function that contains the exit point then resets the debug flags to their
+previous value.
+
+Command 'bb_all' runs through every function in the base kernel (not module
+functions) and does a basic block analysis of every function.  It also validates
+the various tables in kdba_bt_x86 where possible.  bb_all is meant for the KDB
+maintainer to check that all the base kernel function pass the sanity checks, it
+can also be used by end users when reporting a bug.  bb_all takes no parameters.
+It prints a '.' for every 100 functions it has analysed and allows for up to 20
+errors before giving up.  The output from bb_all also includes the config
+variables that affect basic block analysis plus any assumptions about 'pass
+through' functions.
+
+
+Submitting a Bug Report Against kdba_bt_x86
+===========================================
+
+Capture the KDB output via a serial console.
+
+set LINES 10000
+set BTSP 1
+set KDBDEBUG 0x14
+Reproduce the problem.
+set KDBDEBUG 0
+bb_all
+
+If you can identify the rip/eip where kdba_bt_x86 gets confused, run bb1 with
+that address.
+
+Find each set of output from kdba_get_stack_info in the trace, extract the last
+two lines and type those lines into KDB.  That will give a hex and symbolic dump
+of the raw kernel stacks.  For example, if the trace data is
+
+kdba_get_stack_info: esp=0xc04fbef8 cpu=0 task=c047b3e0
+kdba_get_stack_info: ar->stack
+    physical_start=0xc04fb000
+    physical_end=0xc04fc000
+    logical_start=0xc04fb038
+    logical_end=0xc04fc000
+    next=0xc04b4f44
+    id=hardirq_ctx
+    set MDCOUNT 1024
+    mds 0xc04fb000
+
+then type the last two lines into KDB.  Repeat this for each stack listed by
+kdba_get_stack_info on the failing backtrace.
+
+Send all the console output to the KDB maintainer.
+
+
+Examples of Basic Block Debugging Output
+========================================
+
+Example of the basic block analysis of fs/namei::getname() on i386.  Kernel
+2.6.22, i386, compiled with frame pointers, gcc 4.1.0.
+
+Basic block debugging is very verbose, so set a high number of output lines.
+You really need a reliable serial console to capture this amount of output.
+
+    [0]kdb> set LINES 10000
+
+A simple disassemble of getname().  This is not required for debugging purposes
+since each instruction is printed as part of basic block debugging, but this can
+be easier to read.
+
+    [0]kdb> id getname
+    0xc015cce8 getname:         push   %ebp
+    0xc015cce9 getname+0x1:     mov    %esp,%ebp
+    0xc015cceb getname+0x3:     push   %edi
+    0xc015ccec getname+0x4:     push   %esi
+    0xc015cced getname+0x5:     push   %ebx
+    0xc015ccee getname+0x6:     sub    $0x4,%esp
+    0xc015ccf1 getname+0x9:     mov    %eax,%edi
+    0xc015ccf3 getname+0xb:     mov    $0xd0,%edx
+    0xc015ccf8 getname+0x10:    mov    0xc04b2120,%eax
+    0xc015ccfd getname+0x15:    call   0xc0153009 kmem_cache_alloc
+    0xc015cd02 getname+0x1a:    mov    %eax,0xfffffff0(%ebp)
+    0xc015cd05 getname+0x1d:    mov    $0xfffffff4,%eax
+    0xc015cd0a getname+0x22:    cmpl   $0x0,0xfffffff0(%ebp)
+    0xc015cd0e getname+0x26:    je     0xc015cd7d getname+0x95
+    0xc015cd10 getname+0x28:    mov    %esp,%eax
+    0xc015cd12 getname+0x2a:    and    $0xfffff000,%eax
+    0xc015cd17 getname+0x2f:    cmpl   $0xffffffff,0x18(%eax)
+    0xc015cd1b getname+0x33:    je     0xc015cd39 getname+0x51
+    0xc015cd1d getname+0x35:    mov    $0xfffffff2,%esi
+    0xc015cd22 getname+0x3a:    cmp    $0xbfffffff,%edi
+    0xc015cd28 getname+0x40:    ja     0xc015cd60 getname+0x78
+    0xc015cd2a getname+0x42:    mov    $0xc0000000,%ebx
+    0xc015cd2f getname+0x47:    sub    %edi,%ebx
+    0xc015cd31 getname+0x49:    cmp    $0xfff,%ebx
+    0xc015cd37 getname+0x4f:    jbe    0xc015cd3e getname+0x56
+    0xc015cd39 getname+0x51:    mov    $0x1000,%ebx
+    0xc015cd3e getname+0x56:    mov    %ebx,%ecx
+    0xc015cd40 getname+0x58:    mov    %edi,%edx
+    0xc015cd42 getname+0x5a:    mov    0xfffffff0(%ebp),%eax
+    0xc015cd45 getname+0x5d:    call   0xc023dbb4 strncpy_from_user
+    0xc015cd4a getname+0x62:    cmp    $0x0,%eax
+    0xc015cd4d getname+0x65:    jle    0xc015cd5a getname+0x72
+    0xc015cd4f getname+0x67:    mov    $0xffffffdc,%esi
+    0xc015cd54 getname+0x6c:    cmp    %ebx,%eax
+    0xc015cd56 getname+0x6e:    jae    0xc015cd60 getname+0x78
+    0xc015cd58 getname+0x70:    jmp    0xc015cd71 getname+0x89
+    0xc015cd5a getname+0x72:    je     0xc015cd76 getname+0x8e
+    0xc015cd5c getname+0x74:    jge    0xc015cd71 getname+0x89
+    0xc015cd5e getname+0x76:    mov    %eax,%esi
+    0xc015cd60 getname+0x78:    mov    0xfffffff0(%ebp),%edx
+    0xc015cd63 getname+0x7b:    mov    0xc04b2120,%eax
+    0xc015cd68 getname+0x80:    call   0xc01521f1 kmem_cache_free
+    0xc015cd6d getname+0x85:    mov    %esi,%eax
+    0xc015cd6f getname+0x87:    jmp    0xc015cd7d getname+0x95
+    0xc015cd71 getname+0x89:    mov    0xfffffff0(%ebp),%eax
+    0xc015cd74 getname+0x8c:    jmp    0xc015cd7d getname+0x95
+    0xc015cd76 getname+0x8e:    mov    $0xfffffffe,%esi
+    0xc015cd7b getname+0x93:    jmp    0xc015cd60 getname+0x78
+    0xc015cd7d getname+0x95:    pop    %edx
+    0xc015cd7e getname+0x96:    pop    %ebx
+    0xc015cd7f getname+0x97:    pop    %esi
+    0xc015cd80 getname+0x98:    pop    %edi
+    0xc015cd81 getname+0x99:    pop    %ebp
+    0xc015cd82 getname+0x9a:    ret
+
+The bb1 command only one argument which must be an address, not a name.  bb1
+turns on full basic block debugging and analyses the function containing the
+supplied address.  Give bb1 the address of the exit point from this function,
+IOW the return address that is stored on stack due to a call from this function
+to the next function down the call stack.  Assume that getname() has called
+kmem_cache_free() and something went wrong in kmem_cache_free() or one of the
+functions that it calls.  The call to kmem_cache_free is at 0xc015cd68 and the
+return address on stack is the instruction after the call, i.e. 0xc015cd6d, so
+
+    [0]kdb> bb1 0xc015cd6d
+    bb_pass1: func_name getname func_start 0xc015cce8 func_end 0xc015cd83
+
+bb_pass1 has identified the function name and its start and end address.  For C
+functions these are just the function start address and the next symbol in
+kallsyms.  For Assembler code there may be spurious labels so the function name
+may not match the label prior to the address given to bb1.  For an example of
+that on i386, find the address of resume_userspace then pass that address to the
+bb1 KDB command.
+
+    bb_pass1: end
+      bb[0] start 0xc015cce8 end 0xc015cd38 drop_through 1
+      bb[1] start 0xc015cd39 end 0xc015cd3d drop_through 1
+      bb[2] start 0xc015cd3e end 0xc015cd58 drop_through 0
+      bb[3] start 0xc015cd5a end 0xc015cd5f drop_through 1
+      bb[4] start 0xc015cd60 end 0xc015cd6f drop_through 0
+      bb[5] start 0xc015cd71 end 0xc015cd74 drop_through 0
+      bb[6] start 0xc015cd76 end 0xc015cd7b drop_through 0
+      bb[7] start 0xc015cd7d end 0xc015cd82 drop_through 0
+      bb_jmp[0] from 0xc015cd0e to 0xc015cd7d drop_through 0
+      bb_jmp[1] from 0xc015cd1b to 0xc015cd39 drop_through 0
+      bb_jmp[2] from 0xc015cd28 to 0xc015cd60 drop_through 0
+      bb_jmp[3] from 0xc015cd37 to 0xc015cd3e drop_through 0
+      bb_jmp[4] from 0xc015cd4d to 0xc015cd5a drop_through 0
+      bb_jmp[5] from 0xc015cd56 to 0xc015cd60 drop_through 0
+      bb_jmp[6] from 0xc015cd58 to 0xc015cd71 drop_through 0
+      bb_jmp[7] from 0xc015cd5a to 0xc015cd76 drop_through 0
+      bb_jmp[8] from 0xc015cd5c to 0xc015cd71 drop_through 0
+      bb_jmp[9] from 0xc015cd6f to 0xc015cd7d drop_through 0
+      bb_jmp[10] from 0xc015cd74 to 0xc015cd7d drop_through 0
+      bb_jmp[11] from 0xc015cd7b to 0xc015cd60 drop_through 0
+      bb_jmp[12] from 0xc015cd38 to 0xc015cd39 drop_through 1
+      bb_jmp[13] from 0xc015cd3d to 0xc015cd3e drop_through 1
+      bb_jmp[14] from 0xc015cd5f to 0xc015cd60 drop_through 1
+
+After analysing the logic flow, we can see that getname() consists of 8 basic
+blocks (nodes in bb_list[]).  5 of these blocks end in unconditional jumps, the
+other 3 drop through to the next block.  There are 15 transfers of control
+(vertices in bb_jmp_list[]).  12 of these transfers are explicit jmp or jcc
+instructions, the other 3 are implicit transfers when dropping through from one
+block to the next.  The node list is sorted by start address, the vertex list is
+not sorted.
+
+Basic block 0 starts at the function start (0xc015cce8) and ends at 0xc015cd38.
+0xc015cd39 is the target of a jump instruction (0xc015cd1b: je 0xc015cd39) so
+0xc015cd39 starts a new block, which means that 0xc015cd38 becomes the end of
+the previous block.  Because bb[0] does not end in an explicit jmp instruction,
+there is a drop through from the end of bb[0] to the start of bb[1], see
+bb_jmp[12].
+
+    bb_pass2: start
+
+To get the most accurate results from pass2, try to scan the directed graph by
+only looking at nodes whose inputs are all defined.  Initially only process
+nodes with no missing inputs.
+
+      bb_pass2_do_changed_blocks: allow_missing 0
+
+      bb[0]
+      bb_reg_state c07282e0
+        rax = rax
+        rbx = rbx
+        rcx = rcx
+        rdx = rdx
+        rdi = rdi
+        rsi = rsi
+        rbp = rbp
+        rsp = osp+0x0
+
+The initial state for bb[0] is the same for all C functions.  Each register
+contains its own abstract value, except for rsp which is defined in terms of the
+original stack pointer (osp).
+
+     '0xc015cce8 getname:         push   %ebp'
+
+The first instruction of getname() saves the frame pointer.
+
+      opcode 'push' matched by 'push', usage 44
+      src  R: %ebp base_rc 8 (rbp)
+
+bb_usage() reports how the instruction was recognised and how its operands were
+decoded.  Although this is i386 (ebp), it is reported as rbp.  Using the x86_64
+names for registers throughout makes it easier to create common code for the two
+architecures.
+
+      rsp osp offset +0x0 -> -0x4
+
+A push instruction decrements rsp by 4 (i386) or 8 (x86_64) bytes.  rsp
+originally contained the original stack pointer (osp), now it contains the
+original stack pointer - 4.
+
+      *(rsp+0x0 osp-0x4) = rbp slot 0
+
+The stack location pointed to by *rsp now contains the original value of rbp.
+Since rsp contains (osp-0x4), *(osp-0x4) contains rbp.  It is slot 0 in the
+memory array associated with the register state.
+
+     '0xc015cce9 getname+0x1:     mov    %esp,%ebp'
+      opcode 'mov' matched by 'mov', usage 36
+      src  R: %esp base_rc 9 (rsp)
+      dst  R: %ebp base_rc 8 (rbp)
+      rbp = rsp (osp-0x4)
+
+Copy esp (rsp) to ebp (rbp).  rsp contained (osp-0x4) so rbp also contains
+(osp-0x4).  Any reference to data via either rbp or rsp will now be tracked as a
+stack location.
+
+     '0xc015cceb getname+0x3:     push   %edi'
+      opcode 'push' matched by 'push', usage 44
+      src  R: %edi base_rc 6 (rdi)
+      rsp osp offset -0x4 -> -0x8
+      *(rsp+0x0 osp-0x8) = rdi slot 1
+     '0xc015ccec getname+0x4:     push   %esi'
+      opcode 'push' matched by 'push', usage 44
+      src  R: %esi base_rc 7 (rsi)
+      rsp osp offset -0x8 -> -0xc
+      *(rsp+0x0 osp-0xc) = rsi slot 2
+     '0xc015cced getname+0x5:     push   %ebx'
+      opcode 'push' matched by 'push', usage 44
+      src  R: %ebx base_rc 3 (rbx)
+      rsp osp offset -0xc -> -0x10
+      *(rsp+0x0 osp-0x10) = rbx slot 3
+
+Push 3 registers to stack.  rsp is adjusted for each push and stack locations
+are assigned to contain the values of edi, esi and ebx.  This sequence is very
+common in i386 C functions.  edi, esi and ebx are preserved registers on i386,
+but gcc wants to use them for scratch space.  The original contents iof these
+registers must be saved on stack and restored before returning to our caller.
+
+     '0xc015ccee getname+0x6:     sub    $0x4,%esp'
+      opcode 'sub' matched by 'sub', usage 51
+      src  I: $0x4
+      dst  R: %esp base_rc 9 (rsp)
+      rsp osp offset -0x10 -> -0x14
+
+Subtract 4 bytes from esp.  This defines the local stack variables.  Sorry,
+names for local stack variables are not available to KDB.
+
+     '0xc015ccf1 getname+0x9:     mov    %eax,%edi'
+      opcode 'mov' matched by 'mov', usage 36
+      src  R: %eax base_rc 2 (rax)
+      dst  R: %edi base_rc 6 (rdi)
+      rdi = rax (rax)
+
+Having saved edi on stack, gcc now overwrites edi with eax.  At this point rax
+still contains its original value, so rdi now contains a copy of rax, as well as
+the original value which is still in rax.  This is a common sequence in C code.
+rax contains argument 0 but it is also a scratch register.  If the code needs to
+use argument 0 later then its value must be saved somewhere before executing any
+instruction that changes rax.  edi is a preserved register so its contents will
+not be changed by any function that we call, or if it is changed then it will be
+restored before returning to this function.
+
+rax is listed in the arch specific bb_param_reg[] list and the code is reading
+from rax while it still contains its original value.  The only way that makes
+any sense is when rax is an input argument to getname().  We note that fact in
+bb_reg_read().
+
+     '0xc015ccf3 getname+0xb:     mov    $0xd0,%edx'
+      opcode 'mov' matched by 'mov', usage 36
+      src  I: $0xd0
+      dst  R: %edx base_rc 5 (rdx)
+      rdx = undefined
+
+Moving an constant value to edx.  Although this is a constant, it does not refer
+to any of the original values that were supplied to this function.  Therefore
+rdx becomes undefined for the purposes of the code analysis.
+
+     '0xc015ccf8 getname+0x10:    mov    0xc04b2120,%eax'
+      opcode 'mov' matched by 'mov', usage 36
+      src  M: 0xc04b2120
+      dst  R: %eax base_rc 2 (rax)
+      rax = undefined
+
+Moving a constant value to eax makes rax undefined.
+
+     '0xc015ccfd getname+0x15:    call   0xc0153009 <kmem_cache_alloc>'
+      opcode 'call' matched by 'call', usage 17
+      src  M: 0xc0153009
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = rbx
+        rcx = rcx
+        rdx = undefined
+        rdi = rax
+        rsi = rsi
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+
+Basic block debugging prints the register and memory state when transfering
+control between blocks and when issuing call instructions.  The call state is
+mainly useful when C code calls assembler routines, especially if you are not
+sure what state the assembler code expects.  Not all of our assembler is as well
+documented as it could be :(
+
+      rax = undefined
+      rcx = undefined
+      rdx = undefined
+
+The i386 ABI says that some registers are preserved across calls, see the arch
+specific bb_preserved_reg[] list.  Any registers not in that list automatically
+become undefined after a call instruction.
+
+     '0xc015cd02 getname+0x1a:    mov    %eax,0xfffffff0(%ebp)'
+      opcode 'mov' matched by 'mov', usage 36
+      src  R: %eax base_rc 2 (rax)
+      dst  M: 0xfffffff0(%ebp) base_rc 8 (rbp)
+
+eax is the return value from the call, it is being saved at offset 0xfffffff0
+(-0x10) from ebp.  Since rbp contains (osp-0x4) the return value is being stored
+at (osp-0x14).  This is a stack location but we have no record of any data being
+held at that location, it is part of the local stack variables.
+
+     '0xc015cd05 getname+0x1d:    mov    $0xfffffff4,%eax'
+      opcode 'mov' matched by 'mov', usage 36
+      src  I: $0xfffffff4
+      dst  R: %eax base_rc 2 (rax)
+      rax = undefined
+     '0xc015cd0a getname+0x22:    cmpl   $0x0,0xfffffff0(%ebp)'
+      opcode 'cmpl' matched by 'cmp', usage 3
+      src  I: $0x0
+      dst  M: 0xfffffff0(%ebp) base_rc 8 (rbp)
+     '0xc015cd0e getname+0x26:    je     0xc015cd7d <getname+0x95>'
+      opcode 'je' matched by 'j', usage 28
+      src  M: 0xc015cd7d
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = rbx
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = rsi
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+
+Transfer of control, print the register and memory state.
+
+      matched: from 0xc015cd0e to 0xc015cd7d drop_through 0 bb_jmp[0]
+
+Which bb_jmp_list[] entry matches this transfer.
+
+      new state c07286b8
+
+The current abstract register and memory state is cloned at address c07286b8.
+This state becomes one of the inputs to the basic block whose start address is
+0xc015cd7d.
+
+     '0xc015cd10 getname+0x28:    mov    %esp,%eax'
+      opcode 'mov' matched by 'mov', usage 36
+      src  R: %esp base_rc 9 (rsp)
+      dst  R: %eax base_rc 2 (rax)
+      rax = rsp (osp-0x14)
+
+Copy rsp which contains (osp-0x14) to rax.  rax contains a valid stack pointer.
+
+     '0xc015cd12 getname+0x2a:    and    $0xfffff000,%eax'
+      opcode 'and' matched by 'and', usage 11
+      src  I: $0xfffff000
+      dst  R: %eax base_rc 2 (rax)
+      rax = undefined
+
+But not for long.
+
+     '0xc015cd17 getname+0x2f:    cmpl   $0xffffffff,0x18(%eax)'
+      opcode 'cmpl' matched by 'cmp', usage 3
+      src  I: $0xffffffff
+      dst  M: 0x18(%eax) base_rc 2 (rax)
+     '0xc015cd1b getname+0x33:    je     0xc015cd39 <getname+0x51>'
+      opcode 'je' matched by 'j', usage 28
+      src  M: 0xc015cd39
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = rbx
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = rsi
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+
+Another transfer of control, print the state.
+
+      matched: from 0xc015cd1b to 0xc015cd39 drop_through 0 bb_jmp[1]
+
+Which bb_jmp_list[] entry was used.
+
+      reuse bb_jmp[0]
+
+To save space, we only clone the state if it is different.  Otherwise we reuse
+the state from another vertex and bump the reference count.
+
+     '0xc015cd1d getname+0x35:    mov    $0xfffffff2,%esi'
+      opcode 'mov' matched by 'mov', usage 36
+      src  I: $0xfffffff2
+      dst  R: %esi base_rc 7 (rsi)
+      rsi = undefined
+
+Using esi as a scratch register, even though the i386 ABi says that esi is a
+preserved register.  Not to worry, the original value of rsi was saved on stack
+on entry and it will be restored before exit.
+
+     '0xc015cd22 getname+0x3a:    cmp    $0xbfffffff,%edi'
+      opcode 'cmp' matched by 'cmp', usage 3
+      src  I: $0xbfffffff
+      dst  R: %edi base_rc 6 (rdi)
+     '0xc015cd28 getname+0x40:    ja     0xc015cd60 <getname+0x78>'
+      opcode 'ja' matched by 'j', usage 28
+      src  M: 0xc015cd60
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = rbx
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd28 to 0xc015cd60 drop_through 0 bb_jmp[2]
+      new state c0728710
+
+This state is different from any states already saved, clone to a new entry.
+
+     '0xc015cd2a getname+0x42:    mov    $0xc0000000,%ebx'
+      opcode 'mov' matched by 'mov', usage 36
+      src  I: $0xc0000000
+      dst  R: %ebx base_rc 3 (rbx)
+      rbx = undefined
+     '0xc015cd2f getname+0x47:    sub    %edi,%ebx'
+      opcode 'sub' matched by 'sub', usage 51
+      src  R: %edi base_rc 6 (rdi)
+      dst  R: %ebx base_rc 3 (rbx)
+      rbx = undefined
+     '0xc015cd31 getname+0x49:    cmp    $0xfff,%ebx'
+      opcode 'cmp' matched by 'cmp', usage 3
+      src  I: $0xfff
+      dst  R: %ebx base_rc 3 (rbx)
+     '0xc015cd37 getname+0x4f:    jbe    0xc015cd3e <getname+0x56>'
+      opcode 'jbe' matched by 'j', usage 28
+      src  M: 0xc015cd3e
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd37 to 0xc015cd3e drop_through 0 bb_jmp[3]
+      new state c0728768
+
+This state is different from any states already saved, clone to a new entry.
+
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd38 to 0xc015cd39 drop_through 1 bb_jmp[12]
+      reuse bb_jmp[3]
+
+Basic block 0 drops through to basic block 1, treat it as an implicit transfer
+of control.  The state is the same as the previous jump instruction so reuse it
+and bump the reference count.
+
+That ends basic block 0, now pick the next block in the list that (a) needs to
+be scanned and (b) has all its input states defined.  In this case bb[1].
+
+      bb[1]
+
+bb[1] starts at 0xc015cd39 and has two paths that transfer control to it.
+bb_jmp[1] from an explicit jump at 0xc015cd1b and a drop through at bb_jmp[12].
+Where there is more than one input state we have to merge them and reconcile the
+final value.
+
+      first state c07286b8
+
+The first input state is stored at c07286b8.  Looking back through the trace we
+find that entry associated with bb_jmp[0], not bb_jmp[1] as expected.  However
+bb_jmp[1] reused the state that was stored for bb_jmp[0] so all is well.
+
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = rbx
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = rsi
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+
+The first state for bb[1].
+
+      merging state c0728768
+
+Now merge the second state, which is held at c0728768.
+
+      rbx = undefined
+      rsi = undefined
+
+The two states disagree on the values being tracked in rbx and rsi.  Compiler
+theory 101 says that if two or more paths to a basic block have different values
+for a register then that register cannot be relied on at the start of the block,
+so make it undefined.  The same logic applies to memory locations.
+
+      final state
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+
+After merging all the input states, this is the final starting state for bb[1].
+Now track what bb[1] does to the state.
+
+     '0xc015cd39 getname+0x51:    mov    $0x1000,%ebx'
+      opcode 'mov' matched by 'mov', usage 36
+      src  I: $0x1000
+      dst  R: %ebx base_rc 3 (rbx)
+      rbx = undefined
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd3d to 0xc015cd3e drop_through 1 bb_jmp[13]
+      reuse bb_jmp[3]
+
+bb[1] is a single instruction which drops through to bb[2].
+
+      bb[2]
+      first state c0728768
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      merging state c0728768
+
+bb[2] has two inputs, both vertices are pointing to input state c0728768.
+Merging an entry with itself has no effect.
+
+     '0xc015cd3e getname+0x56:    mov    %ebx,%ecx'
+      opcode 'mov' matched by 'mov', usage 36
+      src  R: %ebx base_rc 3 (rbx)
+      dst  R: %ecx base_rc 4 (rcx)
+      rcx = rbx (undefined)
+     '0xc015cd40 getname+0x58:    mov    %edi,%edx'
+      opcode 'mov' matched by 'mov', usage 36
+      src  R: %edi base_rc 6 (rdi)
+      dst  R: %edx base_rc 5 (rdx)
+      rdx = rdi (rax)
+     '0xc015cd42 getname+0x5a:    mov    0xfffffff0(%ebp),%eax'
+      opcode 'mov' matched by 'mov', usage 36
+      src  M: 0xfffffff0(%ebp) base_rc 8 (rbp)
+      dst  R: %eax base_rc 2 (rax)
+      rax = *(rbp-0x10) (osp-0x14)  rax = undefined
+     '0xc015cd45 getname+0x5d:    call   0xc023dbb4 <strncpy_from_user>'
+      opcode 'call' matched by 'call', usage 17
+      src  M: 0xc023dbb4
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = rax
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      rax = undefined
+      rcx = undefined
+      rdx = undefined
+     '0xc015cd4a getname+0x62:    cmp    $0x0,%eax'
+      opcode 'cmp' matched by 'cmp', usage 3
+      src  I: $0x0
+      dst  R: %eax base_rc 2 (rax)
+     '0xc015cd4d getname+0x65:    jle    0xc015cd5a <getname+0x72>'
+      opcode 'jle' matched by 'j', usage 28
+      src  M: 0xc015cd5a
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd4d to 0xc015cd5a drop_through 0 bb_jmp[4]
+      reuse bb_jmp[3]
+     '0xc015cd4f getname+0x67:    mov    $0xffffffdc,%esi'
+      opcode 'mov' matched by 'mov', usage 36
+      src  I: $0xffffffdc
+      dst  R: %esi base_rc 7 (rsi)
+      rsi = undefined
+     '0xc015cd54 getname+0x6c:    cmp    %ebx,%eax'
+      opcode 'cmp' matched by 'cmp', usage 3
+      src  R: %ebx base_rc 3 (rbx)
+      dst  R: %eax base_rc 2 (rax)
+     '0xc015cd56 getname+0x6e:    jae    0xc015cd60 <getname+0x78>'
+      opcode 'jae' matched by 'j', usage 28
+      src  M: 0xc015cd60
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd56 to 0xc015cd60 drop_through 0 bb_jmp[5]
+      reuse bb_jmp[3]
+     '0xc015cd58 getname+0x70:    jmp    0xc015cd71 <getname+0x89>'
+      opcode 'jmp' matched by 'j', usage 28
+      src  M: 0xc015cd71
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd58 to 0xc015cd71 drop_through 0 bb_jmp[6]
+      reuse bb_jmp[3]
+
+      bb[3]
+      first state c0728768
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+
+bb[3] only has one input, nothing to merge.
+
+     '0xc015cd5a getname+0x72:    je     0xc015cd76 <getname+0x8e>'
+      opcode 'je' matched by 'j', usage 28
+      src  M: 0xc015cd76
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd5a to 0xc015cd76 drop_through 0 bb_jmp[7]
+      reuse bb_jmp[3]
+     '0xc015cd5c getname+0x74:    jge    0xc015cd71 <getname+0x89>'
+      opcode 'jge' matched by 'j', usage 28
+      src  M: 0xc015cd71
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd5c to 0xc015cd71 drop_through 0 bb_jmp[8]
+      reuse bb_jmp[3]
+     '0xc015cd5e getname+0x76:    mov    %eax,%esi'
+      opcode 'mov' matched by 'mov', usage 36
+      src  R: %eax base_rc 2 (rax)
+      dst  R: %esi base_rc 7 (rsi)
+      rsi = rax (undefined)
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd5f to 0xc015cd60 drop_through 1 bb_jmp[14]
+      reuse bb_jmp[3]
+
+      bb[5]
+      first state c0728768
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      merging state c0728768
+     '0xc015cd71 getname+0x89:    mov    0xfffffff0(%ebp),%eax'
+      opcode 'mov' matched by 'mov', usage 36
+      src  M: 0xfffffff0(%ebp) base_rc 8 (rbp)
+      dst  R: %eax base_rc 2 (rax)
+      rax = *(rbp-0x10) (osp-0x14)  rax = undefined
+     '0xc015cd74 getname+0x8c:    jmp    0xc015cd7d <getname+0x95>'
+      opcode 'jmp' matched by 'j', usage 28
+      src  M: 0xc015cd7d
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd74 to 0xc015cd7d drop_through 0 bb_jmp[10]
+      reuse bb_jmp[3]
+
+      bb[6]
+      first state c0728768
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+     '0xc015cd76 getname+0x8e:    mov    $0xfffffffe,%esi'
+      opcode 'mov' matched by 'mov', usage 36
+      src  I: $0xfffffffe
+      dst  R: %esi base_rc 7 (rsi)
+      rsi = undefined
+     '0xc015cd7b getname+0x93:    jmp    0xc015cd60 <getname+0x78>'
+      opcode 'jmp' matched by 'j', usage 28
+      src  M: 0xc015cd60
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd7b to 0xc015cd60 drop_through 0 bb_jmp[11]
+      reuse bb_jmp[3]
+
+      bb[4]
+      first state c0728710
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = rbx
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      merging state c0728768
+      rbx = undefined
+      merging state c0728768
+      merging state c0728768
+
+bb[4] has 4 inputs, 3 of which have the same state.  One one path (state
+c0728710) rbx is defined, on the others (c0728768) rbx is undefined so the final
+state has rbx as undefined.
+
+      final state
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+     '0xc015cd60 getname+0x78:    mov    0xfffffff0(%ebp),%edx'
+      opcode 'mov' matched by 'mov', usage 36
+      src  M: 0xfffffff0(%ebp) base_rc 8 (rbp)
+      dst  R: %edx base_rc 5 (rdx)
+      rdx = *(rbp-0x10) (osp-0x14)  rdx = undefined
+     '0xc015cd63 getname+0x7b:    mov    0xc04b2120,%eax'
+      opcode 'mov' matched by 'mov', usage 36
+      src  M: 0xc04b2120
+      dst  R: %eax base_rc 2 (rax)
+      rax = undefined
+     '0xc015cd68 getname+0x80:    call   0xc01521f1 <kmem_cache_free>'
+      opcode 'call' matched by 'call', usage 17
+      src  M: 0xc01521f1
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      rax = undefined
+      rcx = undefined
+      rdx = undefined
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+     '0xc015cd6d getname+0x85:    mov    %esi,%eax'
+      opcode 'mov' matched by 'mov', usage 36
+      src  R: %esi base_rc 7 (rsi)
+      dst  R: %eax base_rc 2 (rax)
+      rax = rsi (undefined)
+     '0xc015cd6f getname+0x87:    jmp    0xc015cd7d <getname+0x95>'
+      opcode 'jmp' matched by 'j', usage 28
+      src  M: 0xc015cd7d
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      matched: from 0xc015cd6f to 0xc015cd7d drop_through 0 bb_jmp[9]
+      reuse bb_jmp[3]
+
+      bb[7]
+      first state c07286b8
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = rbx
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = rsi
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+      merging state c0728768
+      rbx = undefined
+      rsi = undefined
+      merging state c0728768
+      final state
+      bb_reg_state c0728658
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+     '0xc015cd7d getname+0x95:    pop    %edx'
+      opcode 'pop' matched by 'pop', usage 42
+      src  R: %edx base_rc 5 (rdx)
+      rdx = *(rsp+0x0) (osp-0x14)  rdx = undefined
+      rsp osp offset -0x14 -> -0x10
+
+This instruction is a bit misleading.  It looks like gcc is restoring a value
+from the stack *(osp-0x14) to edx, but we have no record of any useful data
+being stored at osp-0x14.  In fact gcc is just reducing the stack pointer by 4
+bytes to reverse the effect of 0xc015ccee: sub $0x4,%esp, the value popped into
+edx contains nothing useful.  Why gcc does pop instead of add $0x4,%esp is a
+puzzle, probably some micro optimization.
+
+     '0xc015cd7e getname+0x96:    pop    %ebx'
+      opcode 'pop' matched by 'pop', usage 42
+      src  R: %ebx base_rc 3 (rbx)
+      rbx = *(rsp+0x0) (osp-0x10) value rbx
+      rsp osp offset -0x10 -> -0xc
+      delete rbx from osp-0x10 slot 3
+
+This pop is doing something useful.  It is restoring the original value of the
+preserved register ebx from stack, reversing 0xc015cced: push %ebx.  Note that
+incrementing rsp from osp-0x10 to osp-0xc invalidates the data held in memory at
+osp-0x10, so we delete our record of it.
+
+     '0xc015cd7f getname+0x97:    pop    %esi'
+      opcode 'pop' matched by 'pop', usage 42
+      src  R: %esi base_rc 7 (rsi)
+      rsi = *(rsp+0x0) (osp-0xc) value rsi
+      rsp osp offset -0xc -> -0x8
+      delete rsi from osp-0xc slot 2
+     '0xc015cd80 getname+0x98:    pop    %edi'
+      opcode 'pop' matched by 'pop', usage 42
+      src  R: %edi base_rc 6 (rdi)
+      rdi = *(rsp+0x0) (osp-0x8) value rdi
+      rsp osp offset -0x8 -> -0x4
+      delete rdi from osp-0x8 slot 1
+
+Pop the other preserved registers, in reverse order to the push sequence at the
+start.
+
+     '0xc015cd81 getname+0x99:    pop    %ebp'
+      opcode 'pop' matched by 'pop', usage 42
+      src  R: %ebp base_rc 8 (rbp)
+      rbp = *(rsp+0x0) (osp-0x4) value rbp
+      rsp osp offset -0x4 -> +0x0
+      delete rbp from osp-0x4 slot 0
+
+Pop the previous frame pointer.
+
+     '0xc015cd82 getname+0x9a:    ret    '
+      opcode 'ret' matched by 'ret', usage 48
+
+When a ret instruction is executed, all the preserved registers must be back to
+their original value and the stack pointer must contain osp+0.
+bb_sanity_check() will complain and abort the backtrace if this is not true.  No
+complaints here.
+
+    bb_pass2: end bb_reg_params 1 bb_memory_params 0
+
+We identified one argument passed in a register (the read of rax at 0xc015ccf1)
+and no reference to memory locations above the stack frame.  So we have one
+argument being passed in a register and no arguments being passed on stack.
+This matches
+
+  char * getname(const char __user * filename)
+
+    bb_pass2: bb_exit_state at 0xc015cd6d
+      bb_reg_state c07287c0
+        rax = undefined
+        rbx = undefined
+        rcx = undefined
+        rdx = undefined
+        rdi = rax
+        rsi = undefined
+        rbp = osp-0x4
+        rsp = osp-0x14
+        slot 0 offset_address -0x4 rbp
+        slot 1 offset_address -0x8 rdi
+        slot 2 offset_address -0xc rsi
+        slot 3 offset_address -0x10 rbx
+
+We told bb1 that the exit address from this function is 0xc015cd6d.  The
+abstract state at this exit point was saved, it defines how we rollback the
+actual register values from the next function down the stack (kmem_cache_free)
+to get the actual register values on entry to this function (getname).  See
+bb_actual_rollback() which updates bb_actual[].
+
+Looking at the exit state above, we see that rsp contains the abstracte value
+osp-0x14.  It is a given that we have the actual value of rsp after the call
+from getname() to kmem_cache_free(), otherwise we would not have found the
+return address on stack and we would not be analysing getname().  Adding 0x14
+(the delta from osp to rsp) to our current actual rsp gives us the actual value
+of osp on entry to getname().
+
+The main aim of doing all this work is to track the function arguments so we can
+print them if possible.  getname() only has one argument which was passed in
+eax.  According to the abstract exit state, the original value of rax is
+currently in rdi, so by looking at the actual value of rdi from the next stack
+frame down we are able to get the argument to getname().
+
+It is not always possible to get register arguments, gcc will only preserve
+input arguments as long as it needs them so there may be no saved copy of
+arguments that are passed in register.  In this case, bt_print_one() prints
+"invalid".
+
+If basic block analysis detected any arguments were passed on stack, their
+contents can now be extracted based on the known value of the stack pointer.
+bt_print_one() prints the arguments, if BT_ARGS is non-zero then any argument
+that might be a kernel address is printed as a symbol.
+
+Once rsp has been rolled back to osp, we can calculate that actual address of
+the stack locations that contain useful data.  The previous values of rbp, rdi,
+rsi and rbx are then copied from those locations into bb_actual[].  That gives
+the values for those registers at the exit point from the function that called
+getname().  Go up one level and repeat the analysis.
+
+There are two references to rdi in the exit state, which can be confusing.
+
+        rdi = rax
+        slot 1 offset_address -0x8 rdi
+
+The first reference says that "register rdi contains the original value of rax",
+the second reference says that "*(osp-0x8) contains the original value of rdi".
+Do not confuse the two, one is by name, the other is by value.
+
+getname() is a fairly simple function, it has no loops.  __follow_mount is more
+complicated, it has loops as well as BUG() statements.
+
+    [0]kdb> id __follow_mount
+    0xc015be76 __follow_mount:         push   %ebp
+    0xc015be77 __follow_mount+0x1:     mov    %esp,%ebp
+    0xc015be79 __follow_mount+0x3:     push   %edi
+    0xc015be7a __follow_mount+0x4:     push   %esi
+    0xc015be7b __follow_mount+0x5:     push   %ebx
+    0xc015be7c __follow_mount+0x6:     mov    %eax,%esi
+    0xc015be7e __follow_mount+0x8:     xor    %edi,%edi
+    0xc015be80 __follow_mount+0xa:     jmp    0xc015beca __follow_mount+0x54
+    0xc015be82 __follow_mount+0xc:     mov    (%esi),%eax
+    0xc015be84 __follow_mount+0xe:     call   0xc0169664 lookup_mnt
+    0xc015be89 __follow_mount+0x13:    mov    %eax,%ebx
+    0xc015be8b __follow_mount+0x15:    test   %eax,%eax
+    0xc015be8d __follow_mount+0x17:    je     0xc015bed3 __follow_mount+0x5d
+    0xc015be8f __follow_mount+0x19:    mov    0x4(%esi),%eax
+    0xc015be92 __follow_mount+0x1c:    call   0xc0163de2 dput
+    0xc015be97 __follow_mount+0x21:    test   %edi,%edi
+    0xc015be99 __follow_mount+0x23:    je     0xc015bead __follow_mount+0x37
+    0xc015be9b __follow_mount+0x25:    mov    (%esi),%eax
+    0xc015be9d __follow_mount+0x27:    test   %eax,%eax
+    0xc015be9f __follow_mount+0x29:    je     0xc015bead __follow_mount+0x37
+    0xc015bea1 __follow_mount+0x2b:    movl   $0x0,0x64(%eax)
+    0xc015bea8 __follow_mount+0x32:    call   0xc016835b mntput_no_expire
+    0xc015bead __follow_mount+0x37:    mov    %ebx,(%esi)
+    0xc015beaf __follow_mount+0x39:    mov    0x10(%ebx),%eax
+    0xc015beb2 __follow_mount+0x3c:    test   %eax,%eax
+    0xc015beb4 __follow_mount+0x3e:    je     0xc015bec2 __follow_mount+0x4c
+    0xc015beb6 __follow_mount+0x40:    cmpl   $0x0,(%eax)
+    0xc015beb9 __follow_mount+0x43:    jne    0xc015bebf __follow_mount+0x49
+    0xc015bebb __follow_mount+0x45:    ud2a
+    0xc015bebd __follow_mount+0x47:    jmp    0xc015bebd __follow_mount+0x47
+    0xc015bebf __follow_mount+0x49:    lock incl (%eax)
+    0xc015bec2 __follow_mount+0x4c:    mov    %eax,0x4(%esi)
+    0xc015bec5 __follow_mount+0x4f:    mov    $0x1,%edi
+    0xc015beca __follow_mount+0x54:    mov    0x4(%esi),%edx
+    0xc015becd __follow_mount+0x57:    cmpl   $0x0,0x74(%edx)
+    0xc015bed1 __follow_mount+0x5b:    jne    0xc015be82 __follow_mount+0xc
+    0xc015bed3 __follow_mount+0x5d:    mov    %edi,%eax
+    0xc015bed5 __follow_mount+0x5f:    pop    %ebx
+    0xc015bed6 __follow_mount+0x60:    pop    %esi
+    0xc015bed7 __follow_mount+0x61:    pop    %edi
+    0xc015bed8 __follow_mount+0x62:    pop    %ebp
+    0xc015bed9 __follow_mount+0x63:    ret
+
+    [0]kdb> bb1 0xc015bed9
+    bb_pass1: func_name __follow_mount func_start 0xc015be76 func_end 0xc015beda
+    bb_pass1: end
+      bb[0] start 0xc015be76 end 0xc015be80 drop_through 0
+      bb[1] start 0xc015be82 end 0xc015beac drop_through 1
+      bb[2] start 0xc015bead end 0xc015bebb drop_through 0
+
+Note that the ud2a (BUG) instruction at 0xc015bebb ends bb[2].
+
+      bb[3] start 0xc015bebd end 0xc015bebd drop_through 0
+
+bb[3] is peculiar, it is a jmp to itself, nothing else refers to 0xc015bebd and
+you cannot drop through from the previous instruction because ud2a kills the
+kernel.  The i386 and x86_64 BUG() macros contain for(;;) after ud2a, for no
+good reason that I can see (is there old hardware that does not abort on ud2a?).
+ia64 and the generic versions of BUG() do not contain for(;;).  for(;;) after
+ud2a generates a branch to itself than can never be executed.
+
+      bb[4] start 0xc015bebf end 0xc015bec1 drop_through 1
+      bb[5] start 0xc015bec2 end 0xc015bec9 drop_through 1
+      bb[6] start 0xc015beca end 0xc015bed2 drop_through 1
+      bb[7] start 0xc015bed3 end 0xc015bed9 drop_through 0
+      bb_jmp[0] from 0xc015be80 to 0xc015beca drop_through 0
+      bb_jmp[1] from 0xc015be8d to 0xc015bed3 drop_through 0
+      bb_jmp[2] from 0xc015be99 to 0xc015bead drop_through 0
+      bb_jmp[3] from 0xc015be9f to 0xc015bead drop_through 0
+      bb_jmp[4] from 0xc015beb4 to 0xc015bec2 drop_through 0
+      bb_jmp[5] from 0xc015beb9 to 0xc015bebf drop_through 0
+      bb_jmp[6] from 0xc015bebd to 0xc015bebd drop_through 0
+      bb_jmp[7] from 0xc015bed1 to 0xc015be82 drop_through 0
+      bb_jmp[8] from 0xc015beac to 0xc015bead drop_through 1
+      bb_jmp[9] from 0xc015bec1 to 0xc015bec2 drop_through 1
+      bb_jmp[10] from 0xc015bec9 to 0xc015beca drop_through 1
+      bb_jmp[11] from 0xc015bed2 to 0xc015bed3 drop_through 1
+
+Apart from bb[0] and the special case bb[3], all the other blocks are part of a
+cycle.  That cycle goes bb[0] -> bb[6].  bb[6] -> {bb[1], bb[7]}.  bb[1] ->
+{bb[2], bb[7]}.  bb[2] -> {bb[4], bb[5]}.  bb[4] -> bb[5].  bb[5] -> bb[6] and
+back to the start.  bb[7] ends with 'ret', it does not feed into other blocks.
+
+    bb_pass2: start
+
+      bb_pass2_do_changed_blocks: allow_missing 0
+
+      bb[0]
+      [ ... detail snipped ... ]
+      matched: from 0xc015be80 to 0xc015beca drop_through 0 bb_jmp[0]
+      new state c07286d8
+
+      bb_pass2_do_changed_blocks: allow_missing 1
+
+Because of the cycle, only bb[0] can be processed with 0 missing inputs, all the
+other blocks have at least one missing input.  Call bb_pass2_do_changed_blocks()
+again, this time allowing one missing input per blocks.
+
+      bb[6]
+      first state c07286d8
+      [ ... detail snipped ... ]
+      matched: from 0xc015bed2 to 0xc015bed3 drop_through 1 bb_jmp[11]
+      reuse bb_jmp[7]
+
+      bb[7]
+      first state c0728730
+      [ ... detail snipped ... ]
+
+      bb[1]
+      first state c0728730
+      [ ... detail snipped ... ]
+      matched: from 0xc015beac to 0xc015bead drop_through 1 bb_jmp[8]
+      reuse bb_jmp[1]
+
+      bb[2]
+      first state c0728788
+      [ ... detail snipped ... ]
+      merging state c0728788
+      merging state c0728788
+      [ ... detail snipped ... ]
+      matched: from 0xc015beb9 to 0xc015bebf drop_through 0 bb_jmp[5]
+      reuse bb_jmp[1]
+
+      bb[4]
+      first state c0728788
+      [ ... detail snipped ... ]
+      matched: from 0xc015bec1 to 0xc015bec2 drop_through 1 bb_jmp[9]
+      reuse bb_jmp[1]
+
+      bb[5]
+      first state c0728788
+      [ ... detail snipped ... ]
+      merging state c0728788
+      [ ... detail snipped ... ]
+      matched: from 0xc015bec9 to 0xc015beca drop_through 1 bb_jmp[10]
+      reuse bb_jmp[1]
+
+      bb[6]
+      first state c07286d8
+      [ ... detail snipped ... ]
+      merging state c0728788
+      matched: from 0xc015bed2 to 0xc015bed3 drop_through 1 bb_jmp[11]
+      reuse bb_jmp[1]
+
+Note the rescan of bb[6].  The first scan only had one input from bb[0].  After
+traversing the cycle and getting back from bb[5] to bb[6], bb[6] now has more
+inputs so we need to rescan it.  With the additional input, the output state
+from bb[6] has changed since the first scan, which means that every block it
+feeds has to be rescanned.  bb[6] feeds bb[1] and bb[7].
+
+      bb[7]
+      first state c0728788
+      [ ... detail snipped ... ]
+      merging state c0728788
+      [ ... detail snipped ... ]
+
+bb[7] being rescanned, this time it has data for both its inputs.
+
+      bb[1]
+      first state c0728788
+      [ ... detail snipped ... ]
+      matched: from 0xc015beac to 0xc015bead drop_through 1 bb_jmp[8]
+      no state change
+
+bb[1] is being rescanned because the input from bb[6] has changed, however the
+rescan of bb[1] reports 'no state change', the changed input from bb[6] did not
+affect the final output state from bb[1].  Because the output state from bb[1]
+has not changed since the previous scan, there is no need to rescan bb[2], bb[7]
+or bb[4].  Since bb[4] is not being rescanned, there is no need to rescan bb[5]
+or bb[6] and the cycle is closed.
diff --git a/Documentation/kdb/kdb.mm b/Documentation/kdb/kdb.mm
new file mode 100644 (file)
index 0000000..81913a0
--- /dev/null
@@ -0,0 +1,492 @@
+.TH KDB 8 "September 21, 2005"
+.hy 0
+.SH NAME
+Built-in Kernel Debugger for Linux - v4.4
+.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 no longer supported.
+.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 control sequence \fB<esc>KDB\fP 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 console driver is still usable.
+.P
+\fBNote:\fR\ When the serial console sequence consists of multiple
+characters such as <esc>KDB then all but the last character are passed
+through to the application that is reading from the serial console.
+After exiting from kdb, you should use backspace to delete the rest of
+the control sequence.
+.P
+You can boot with kdb activated but without the ability to enter kdb
+via any keyboard sequence.
+In this mode, kdb will only be entered after a system failure.
+Booting with kdb=on-nokey will activate kdb but ignore keyboard
+sequences that would normally drop you into kdb.
+kdb=on-nokey is mainly useful when you are using a PC keyboard and your
+application needs to use the Pause key.
+You can also activate this mode by
+.nf
+  echo "2" > /proc/sys/kernel/kdb
+.fi
+.P
+If the console is sitting on the login prompt when you enter kdb, then
+the login command may switch into upper case mode.
+This is not a kdb bug, it is a "feature" of login - if the userid is
+all upper case then login assumes that you using a TeleType (circa
+1960) which does not have lower case characters.
+Wait 60 seconds for login to timeout and it will switch back to lower
+case mode.
+.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
+If you are using a USB keyboard then kdb commands cannot be entered
+until the kernel has initialised the USB subsystem and recognised the
+keyboard.
+Using kdb=early with a USB keyboard will not work, the USB subsystem is
+initialised too late.
+.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.
+A line whose first non-space character is '#' is printed and ignored.
+.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
+handlers       Control the display of IA64 MCA/INIT handlers
+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.
+mdp    Display memory based on a physical address
+mdr    Display raw memory contents
+mds    Display memory contents symbolically
+mm     Modify memory contents, words
+mmW    Modify memory contents, bytes
+per_cpu        Display per_cpu variables
+pid    Change the default process context
+ps     Display process status
+reboot Reboot the machine
+rd     Display register contents
+rm     Modify register contents
+rq     Display runqueue for one cpu
+rqa    Display runqueue for all cpus
+set    Add/change environment variable
+sr     Invoke SysReq commands
+ss     Single step a cpu
+ssb    Single step a cpu until a branch instruction
+stackdepth     Print the stack depth for selected processes
+summary        Summarize the system
+.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.
+\&'+' after a cpu number indicates a cpu for which kdb has some data, but
+that cpu is no longer responding to kdb, so you cannot switch to it.
+This could be a cpu that has failed after entering kdb, or the cpu may
+have saved its state for debugging then entered the prom, this is
+normal for an IA64 MCA event.
+\&'I' after a cpu number means that the cpu was idle before it entered
+kdb, it is unlikely to contain any useful data.
+\&'F' after a cpu number means that the cpu is offline.
+There is currenly no way to distinguish between cpus that used to be
+online but are now offline and cpus that were never online, the kernel
+does not maintain the information required to separate those two cases.
+.I cpu
+followed by a number will switch to that cpu, you cannot switch to
+a cpu marked '*', '+' or 'F'.
+This command is only available if the kernel was configured for SMP.
+.TP 8
+dmesg [lines] [adjust]
+Displays the system messages from the kernel buffer.
+If kdb logging is on, it is disabled by dmesg and is left as disabled.
+With no parameters or a zero value for 'lines', dmesg dumps the entire
+kernel buffer.
+If lines is specified and is positive, dmesg dumps the last 'lines'
+from the buffer.
+If lines is specified and is negative, dmesg dumps the first 'lines'
+from the buffer.
+If adjust is specified, adjust the starting point for the lines that
+are printed.
+When 'lines' is positive, move the starting point back by 'adjust'
+lines, when 'lines' is negative, move the starting point forward by
+\&'adjust' lines.
+.I dmesg -100
+will dump 100 lines, from the start of the buffer.
+.I dmesg 100
+will dump 100 lines, starting 100 lines from the end of the buffer,
+.I dmesg 100 100
+will dump 100 lines, starting 200 lines from the end of the buffer.
+.I dmesg -100 100
+will dump 100 lines, starting 100 lines from the start of the buffer.
+.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
+.P
+When used with no parameters, defcmd prints all the defined commands.
+.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
+handlers
+Control the display of IA64 MCA/INIT handlers.
+The IA64 MCA/INIT handlers run on separate tasks.
+During an MCA/INIT event, the active tasks are typically the handlers,
+rather than the original tasks, which is not very useful for debugging.
+By default, KDB hides the MCA/INIT handlers so commands such as ps and
+btc will display the original task.
+You can change this behaviour by using
+.I handlers show
+to display the MCA/INIT handlers instead of the original tasks or use
+.I handlers hide
+(the default) to hide the MCA/INIT handlers and display the original
+tasks.
+.I handlers status
+will list the address of the handler task and the original task for
+each cpu.
+\fBNote:\fR\ If the original task was running in user space or it
+failed any of the MCA/INIT verification tests then there is no original
+task to display.
+In this case, the handler will be displayed even if
+.I handlers hide
+is set and
+.I handlers status
+will not show an original task.
+.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
+per_cpu <variable_name> [<length>] [<cpu>]
+Display the values of a per_cpu variable, the variable_name is
+specified without the \fIper_cpu__\fR prefix.
+Length is the length of the variable, 1-8, if omitted or 0 it defaults
+to the size of the machine's register.
+To display the variable on a specific cpu, the third parameter is the
+cpu number.
+When the third parameter is omitted, the variable's value is printed
+from all cpus, except that zero values are suppressed.
+For each cpu, per_cpu prints the cpu number, the address of the
+variable and its value.
+.TP 8
+pid <number>
+Change the current process context, with no parameters it displays the
+current process.
+The current process is used to display registers, both kernel and user
+space.
+It is also used when dumping user pages.
+.I pid R
+resets to the original process that was running when kdb was entered.
+This command is useful if you have been looking at other processes and/or
+cpus and you want to get back to the original process.
+It does not switch cpus, it only resets the context to the original process.
+.TP 8
+reboot
+Reboot the system, with no attempt to do a clean close down.
+.TP 8
+rq <cpu>
+Display the runqueues for the specified cpu.
+.TP 8
+rqa
+Display the runqueues for all cpus.
+.TP 8
+stackdepth <percentage>
+Print the stack usage for processes using more than the specified
+percentage of their stack.
+If percentage is not supplied, it defaults to 60.
+This command is only implemented on i386 and ia64 architectures,
+patches for other architectures will be gratefully accepted.
+.TP 8
+summary
+Print a summary of the system, including the time (no timezone is
+applied), uname information and various critical system counters.
+.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,ps,rd,sr,ss}.man
diff --git a/Documentation/kdb/kdb_bp.man b/Documentation/kdb/kdb_bp.man
new file mode 100644 (file)
index 0000000..a1b0dc4
--- /dev/null
@@ -0,0 +1,197 @@
+.TH BD 1 "July 12, 2004"
+.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.
+A breakpoint-number of \fI*\fR will disable all break points.
+.P
+The
+.B be
+command will re-enable a disabled breakpoint.
+A breakpoint-number of \fI*\fR will enable all break points.
+.P
+The
+.B bc
+command will clear a breakpoint from the breakpoint table.
+A breakpoint-number of \fI*\fR will clear all break points.
+.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 --git a/Documentation/kdb/kdb_bt.man b/Documentation/kdb/kdb_bt.man
new file mode 100644 (file)
index 0000000..c32961b
--- /dev/null
@@ -0,0 +1,315 @@
+.TH BT 1 "July 20, 2007"
+.SH NAME
+bt \- Stack Traceback command
+.SH SYNOPSIS
+bt [ <stack-frame-address> ]
+.LP
+btp <pid>
+.LP
+btt <struct-task-address>
+.LP
+bta [ DRSTZUIMA ]
+.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.
+On x86 architecture, \fIstack-frame-address\fP must be the stack address of a
+saved \fB%eip\fP (\fB%rip\fP for x86_64) value from a \fBcall\fP instruction.
+.P
+The \fBbtp\fP command will analyze the stack for the given
+process identification (see the \fBps\fP command).
+\fBbtp\fP sets the current process for any following register display or update
+commands.
+.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.
+\fBbtt\fP sets the current process for any following register display or update
+commands.
+.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 useful processes.
+If a parameter is specified, it is a single string consisting of the
+letters D, R, S, T, Z, U, I, M and A in any order.
+See the kdb \fBps\fR man page for more details.
+\fBbta\fP does not change the current process.
+.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.
+\fBbtc\fP with no arguments does not change the current process.
+\fBbtc\fP with a cpu number sets the current process for any following register
+display or update commands.
+.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 stack frame.
+.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
+If environment variable NOSECT is set to 0 then the next line contains
+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 (not available on 2.6 kernels).
+.IP * 3
+The start address of the section (not available on 2.6 kernels).
+.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
+.P
+On architectures that use nested stacks, the backtrace will indicate a
+switch to a new stack by printing a line of equal signs and the type of
+stack.
+.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
+Unfortunately the 2.6 kernel does not provide the information required
+to locate the start of the section, which makes it very difficult to
+perform a reliable objdump on a module.
+.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
+Some architectures pass parameters in registers; ia64, x86_64 and i386 (with
+gcc flag -mregparm) fall into this category.
+On these architectures, the compiler may reuse input parameter registers as
+scratch space.
+For example, if a function takes a pointer to a structure and only accesses one
+field in that structure, the compiler may calculate the address of the field by
+adding a value to the input register.
+Once the input register has been updated, it no longer points to the
+start of the structure, but to some field within it.
+This also occurs with array pointers, the compiler may update the input pointer
+directly, leaving it pointing to some element of the array instead of the start
+of the array.
+Always treat parameter values that have been passed in registers with extreme
+suspicion, the compiler may have changed the value.
+The x86 backtrace can generally identify register parameters that are no longer
+valid, it prints them as 'invalid' instead of as a misleading number.
+The ia64 backtrace cannot identify parameter registers that have been
+overwritten.
+.P
+x86 architectures do not have full unwind information in the kernel.
+The KDB backtrace on x86 performs code decomposition and analysis to track the
+frames on the call stack (including stack switches) and to locate parameters.
+if this code analysis does not yield a valid result, KDB falls back on the old
+method of scanning the process stack and printing anything that looks like a
+kernel address.
+This old method is unreliable (it produces lots of false positives in the
+trace) and cannot track parameters at all, so no parameters are printed.
+If you get an x86 backtrace that falls back to the old method, read
+Documentation/kdb/bt_x86 and follow the steps listed to get diagnostics and to
+submit a bug report.
+.P
+There are a lot of functions in the kernel which take some arguments then do
+nothing except call another function with the same initial arguments, sometimes
+adding parameters at the end.  For example\ :-
+.nf
+.na
+.ft CW
+
+int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
+                                 void __user *oldval, size_t __user *oldlenp,
+                                 void __user *newval, size_t newlen)
+{
+       int ret = devinet_conf_sysctl(table, name, nlen, oldval, oldlenp,
+                                     newval, newlen);
+
+       if (ret == 1)
+               rt_cache_flush(0);
+
+       return ret;
+}
+.ad b
+.fi
+.P
+ipv4_doint_and_flush_strategy() passes all its parameters directly to
+devinet_conf_sysctl() and makes no other use of those parameters,
+so ipv4_doint_and_flush_strategy is a 'pass through' function.
+The x86_64 calling sequence mandates that the first 6 parameters are passed in
+registers, with other parameters being passed on stack.
+The i386 calling sequence with -mregparm=3 (which is the default since about
+2.6.18) passes the first 3 parameters in registers, with other parameters being
+passed on stack.
+The only exceptions to the above calling sequence are for functions declared as
+asmlinkage or functions with a variable number of parameters (e.g. printk).
+.P
+When a pass through function calls another function, the first 3 (i386) or 6
+(x86) parameters are already in their correct registers so the pass through
+function does not need to access the registers, which means that there are no
+references to these registers in the assembler code for the function.
+Users still want to see those arguments so the x86 backtrace has to assume that
+if\ :-
+.IP * 2
+There are parameters passed on the stack and
+.IP *
+There are no code references to parameters passed in registers and
+.IP *
+The function is not a known asmlinkage or variadic function, then
+there are pass through register arguments.
+.P
+The x86 backtrace will warn you when it makes this assumption, like this\ :-
+.nf
+.na
+.ft CW
+
+  <function_name> has memory parameters but no register parameters.
+  Assuming it is a 'pass through' function that does not refer to its register
+  parameters and setting <n> register parameters
+.ad b
+.fi
+.P
+The above 3 line message is only printed once, any future assumptions will
+print a shorter message.
+.P
+The \fBbt\fP command may print more or less arguments for a function
+than that function accepts.
+For x86, trailing arguments that are passed in but not used by the function
+will not be printed, resulting in fewer arguments than expected.
+For ia64, the hardware does not distinguish between input and local registers,
+some local registers may be printed as function arguments, resulting in more
+arguments than expected.
+.P
+On i386, 64 bit arguments (long long) occupy two adjacent 32 bit fields.
+There is no way for KDB to tell that this has occurred, so 64 bit arguments
+will be printed as two separate 32 bit arguments.
+.SH ENVIRONMENT
+The \fBBTARGS\fP environment variable governs the maximum number
+of arguments that are printed for any single function.
+On IA64 hardware, there is no difference between input and local registers, the
+first \fBBTARGS\fP registers are printed, up to the total limit of input plus
+local registers.
+Use a large value for \fBBTARGS\fP if you want to see the local registers on
+IA64.
+.PP
+If the \fBBTSP\fP environment variable is non-zero then the entire backtrace is
+printed, otherwise only the backtrace to the point of the last interrupt is
+printed.
+Printing the entire backtrace with 'set\ BTSP\ 1' is useful for diagnosing
+problems with the backtrace algorithms.
+In addition, when BTSP is non-zero, each backtrace frame may print extra lines
+giving information about the stack pointers, this is architecture specific.
+.PP
+If the \fBBTSYMARG\fP environment variable is non-zero then any
+arguments that fall within the kernel or modules are converted to symbols.
+.PP
+If the \fBNOSECT\fP environment variable is non-zero then the
+section information is suppressed.
+The default is NOSECT=1 so section data is suppressed; use set\ NOSECT=0
+to see section information.
+.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.
+.PP
+\fBbt\fR with no parameters uses the \fBPS\fR environment variable, see
+the kdb \fBps\fR man page.
+.SH SMP CONSIDERATIONS
+None.
+.SH EXAMPLES
+.nf
+.na
+.ft CW
+[0]kdb> bt
+Stack traceback for pid 2873
+0xc2efc0f0     2873     2836  1    0   R  0xc2efc2a0 *mount
+esp        eip        Function (args)
+0xf65a3c88 0xc0201f9f xfs_mount_validate_sb (0xf68bcb08, 0xf68bcb48, 0x0)
+0xf65a3c94 0xc0202f17 xfs_readsb+0x9d (0xf68bcb08, 0x0)
+0xf65a3cc0 0xc020a72e xfs_mount+0x21d (invalid, 0xf68bc2f0, 0x0)
+0xf65a3cf4 0xc021a84a vfs_mount+0x1a (invalid)
+0xf65a3d04 0xc021a721 xfs_fs_fill_super+0x76 (0xf76b6200, invalid, invalid)
+0xf65a3d78 0xc015ad81 get_sb_bdev+0xd4 (invalid, invalid, invalid, 0xf7257000, 0xc021a6ab, 0xf7594b38)
+  xfs_fs_get_sb has memory parameters but no register parameters.
+  Assuming it is a 'pass through' function that does not refer to its register
+  parameters and setting 3 register parameters
+0xf65a3db4 0xc0219a3a xfs_fs_get_sb+0x21 (invalid, invalid, invalid, 0xf7257000, 0xf7594b38)
+0xf65a3dcc 0xc015a992 vfs_kern_mount+0x41 (0xc04847e0, 0x0, 0xf68e9000, 0xf7257000)
+0xf65a3df0 0xc015aa11 do_kern_mount+0x38 (0xf6818000, 0x0, 0xf68e9000, 0xf7257000)
+0xf65a3e10 0xc016c8b0 do_mount+0x5df (0xf68e9000, 0xf65d6000, 0xf6818000, 0xc0ed0000, 0xf7257000)
+0xf65a3f90 0xc016c996 sys_mount+0x6f (0x8069b50, 0x8069b60, 0x8069b70, 0xc0ed0000, 0x8069ba0)
+0xf65a3fb4 0xc0102646 sysenter_past_esp+0x5f (invalid, invalid, invalid, 0x73, 0x246, 0xbfe52f50)
diff --git a/Documentation/kdb/kdb_env.man b/Documentation/kdb/kdb_env.man
new file mode 100644 (file)
index 0000000..aed5175
--- /dev/null
@@ -0,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 --git a/Documentation/kdb/kdb_ll.man b/Documentation/kdb/kdb_ll.man
new file mode 100644 (file)
index 0000000..57a1a1b
--- /dev/null
@@ -0,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 --git a/Documentation/kdb/kdb_md.man b/Documentation/kdb/kdb_md.man
new file mode 100644 (file)
index 0000000..1913f2c
--- /dev/null
@@ -0,0 +1,136 @@
+.TH MD 1 "August 4, 2004"
+.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
+mdp \fIphysical-address-expression\fP,\fIbytes\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 mdp
+command displays the contents of physical memory, starting at the
+specified physical address for the specified number of bytes.
+The address is preceded by 'phys'.
+.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
+NOSECT
+If the \fBNOSECT\fP environment variable is non-zero then the
+section information is suppressed.
+The default is NOSECT=1 so section data is suppressed; use set\ NOSECT=0
+to see section information.
+.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 --git a/Documentation/kdb/kdb_ps.man b/Documentation/kdb/kdb_ps.man
new file mode 100644 (file)
index 0000000..99f9267
--- /dev/null
@@ -0,0 +1,96 @@
+.TH PS 1 "September 14, 2004"
+.SH NAME
+ps \- Display processes
+.SH SYNOPSIS
+ps [ DRSTCZEUIMA ]
+.SH DESCRIPTION
+The
+.B ps
+command displays the 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.
+.P
+Without any parameters, \fBps\fP displays all the interesting
+processes, excluding idle tasks and sleeping system daemons.
+If a parameter is specified, it is a single string consisting of the
+letters D, R, S, T, C, Z, E, U, I and M, 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.
+The states are\ :-
+.P
+.DS
+.TS
+box, center;
+l | l
+l | l.
+D      Uninterruptible sleep
+R      Running
+S      Interruptible sleep
+T      Stopped
+C      Traced
+Z      Zombie
+E      Dead
+U      Unrunnable
+I      Idle task
+M      Sleeping system daemon
+A      All
+.TE
+.DE
+.P
+For state R (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.
+.P
+The idle task is run on each cpu when there is no work for that cpu to do.
+Unless the idle task is servicing an interrupt, there is no point in
+printing the idle task.
+An idle task that is not servicing a interrupt is marked as state I,
+while servicing an interrupt it is in state R.
+By default, idle tasks are not printed, use \fBps\ I\fR to print them.
+If the idle tasks are not being printed, the start of the \fBps\R
+output contains a list of which cpus are idle.
+.P
+Each cpu has one or more system daemons to handle per cpu work such as
+soft irqs.
+A system daemon (idenified by a NULL mm pointer) that is sleeping is
+marked as state M.
+These processes rarely have any useful data and generate a lot of
+output on large machines, so sleeping system daemons are not printed by
+default.
+Use \fBps\ M\fR to print them.
+.P
+At the start of the \fBps\fR output is a line giving the cpu status,
+see the kdb \fBcpu\fR command.
+.SH LIMITATIONS
+None.
+.SH ENVIRONMENT
+.TP 8
+PS
+This environment variable (default=DRSTCZEU) is used when \fBps\fR
+is issued with no parameters.
+
+.SH SMP CONSIDERATIONS
+None.
+.SH EXAMPLES
+.TP 8
+\fBps\fR
+displays the useful tasks, suppressing idle tasks and sleeping
+system daemons.
+
+.TP 8
+\fBps\ RD\fR
+displays only tasks that are running or are in an uninterruptible
+sleep.
+
+.TP 8
+\fBps\ DRSTCZEUIM\fR
+displays all tasks.
+
+.TP 8
+\fBps\ A\fR
+displays all tasks.
+This is easier than remembering DRSTCZEUIM.
+
diff --git a/Documentation/kdb/kdb_rd.man b/Documentation/kdb/kdb_rd.man
new file mode 100644 (file)
index 0000000..3e9c95e
--- /dev/null
@@ -0,0 +1,170 @@
+.TH RD 1 "September 20, 2005"
+.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.
+If the bt* or pid commands have been used to change the current process then
+.B rd
+and
+.B rm
+may not be able to display any registers.
+'n' argument is only used for XScale platform to identify the desired
+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
+On IA64, the parameter to
+.B rd
+can be d (debug registers), u (user registers at most recent entry to kernel),
+i (interrupt registers), %isr (current interrupt status), s (stacked
+registers), k (kernel registers).  You can also specify these individual
+registers -
+psr,
+ifs,
+ip,
+unat,
+pfs,
+rsc,
+rnat,
+bsps,
+pr,
+ldrs,
+ccv,
+fpsr,
+b0,
+b6,
+b7,
+r1,
+r2,
+r3,
+r8,
+r9,
+r10,
+r11,
+r12,
+r13,
+r14,
+r15,
+r16,
+r17,
+r18,
+r19,
+r20,
+r21,
+r22,
+r23,
+r24,
+r25,
+r26,
+r27,
+r28,
+r29,
+r30,
+r31.
+.B rm
+can change any of the individual registers or the stacked registers.
+.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 from kdb's current task.
+
+.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 --git a/Documentation/kdb/kdb_sr.man b/Documentation/kdb/kdb_sr.man
new file mode 100644 (file)
index 0000000..54b34e1
--- /dev/null
@@ -0,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 --git a/Documentation/kdb/kdb_ss.man b/Documentation/kdb/kdb_ss.man
new file mode 100644 (file)
index 0000000..f178680
--- /dev/null
@@ -0,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 --git a/Documentation/kdb/slides b/Documentation/kdb/slides
new file mode 100644 (file)
index 0000000..a9e77ae
--- /dev/null
@@ -0,0 +1,1382 @@
+#! /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
+               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
index 85c9295..f7ed9ca 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -625,6 +625,7 @@ export mod_strip_cmd
 
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
+core-$(CONFIG_KDB) += kdb/
 
 vmlinux-dirs   := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
                     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
index de9d507..4cb04a9 100644 (file)
@@ -56,9 +56,106 @@ config IA64_DEBUG_IRQ
          and restore instructions.  It's useful for tracking down spinlock
          problems, but slow!  If you're unsure, select N.
 
+config KDB
+       bool "Built-in Kernel Debugger support"
+       depends on DEBUG_KERNEL
+       select KALLSYMS
+       select KALLSYMS_ALL
+       help
+         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 key sequence <escape>KDB on the serial port will cause the
+         kernel debugger to be entered with input from the serial port and
+         output to the serial console.  If unsure, say N.
+
+config KDB_MODULES
+       tristate "KDB modules"
+       depends on KDB
+       help
+         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.
+
+config KDB_OFF
+       bool "KDB off by default"
+       depends on KDB
+       help
+         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.
+
+config KDB_CONTINUE_CATASTROPHIC
+       int "KDB continues after catastrophic errors"
+       depends on KDB
+       default "0"
+       help
+         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_LKCD_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.
+
+config KDB_USB
+       bool "Support for USB Keyboard in KDB (OHCI and/or EHCI only)"
+       depends on KDB && (USB_OHCI_HCD || USB_UHCI_HCD)
+       help
+         If you want to use kdb from USB keyboards then say Y here.  If you
+         say N then kdb can only be used from a PC (AT) keyboard or a serial
+         console.
+
+config KDB_HARDWARE_BREAKPOINTS
+       bool "Enable hardware breakpoints in KDB"
+       depends on KDB
+       default y
+       help
+         If you say Y here, KDB will allow you to use the IA64
+         hardware watchpoint feature (via the bph and bpha
+         commands).  Currently, only data breakpoints are
+         implemented.
+
 config SYSVIPC_COMPAT
        bool
        depends on COMPAT && SYSVIPC
        default y
 
+config KDB_KDUMP
+       bool "Support for Kdump in KDB"
+       depends on KDB
+       select KEXEC
+       default N
+       help
+         If you want to take Kdump kernel vmcore from KDB then say Y here.
+         Of imsire. say N.
+
 endmenu
index 905d25b..b432ff1 100644 (file)
@@ -60,6 +60,7 @@ core-$(CONFIG_IA64_SGI_SN2)   += arch/ia64/sn/
 core-$(CONFIG_IA64_SGI_UV)     += arch/ia64/uv/
 core-$(CONFIG_KVM)             += arch/ia64/kvm/
 
+drivers-$(CONFIG_KDB)          += arch/$(ARCH)/kdb/
 drivers-$(CONFIG_PCI)          += arch/ia64/pci/
 drivers-$(CONFIG_IA64_HP_SIM)  += arch/ia64/hp/sim/
 drivers-$(CONFIG_IA64_HP_ZX1)  += arch/ia64/hp/common/ arch/ia64/hp/zx1/
diff --git a/arch/ia64/include/asm/ansidecl.h b/arch/ia64/include/asm/ansidecl.h
new file mode 100644 (file)
index 0000000..2033011
--- /dev/null
@@ -0,0 +1,383 @@
+/* ANSI and traditional C compatability macros
+   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+   Macro               ANSI C definition       Traditional C definition
+   -----               ---- - ----------       ----------- - ----------
+   ANSI_PROTOTYPES     1                       not defined
+   PTR                 `void *'                `char *'
+   PTRCONST            `void *const'           `char *'
+   LONG_DOUBLE         `long double'           `double'
+   const               not defined             `'
+   volatile            not defined             `'
+   signed              not defined             `'
+   VA_START(ap, var)   va_start(ap, var)       va_start(ap)
+
+   Note that it is safe to write "void foo();" indicating a function
+   with no return value, in all K+R compilers we have been able to test.
+
+   For declaring functions with prototypes, we also provide these:
+
+   PARAMS ((prototype))
+   -- for functions which take a fixed number of arguments.  Use this
+   when declaring the function.  When defining the function, write a
+   K+R style argument list.  For example:
+
+       char *strcpy PARAMS ((char *dest, char *source));
+       ...
+       char *
+       strcpy (dest, source)
+            char *dest;
+            char *source;
+       { ... }
+
+
+   VPARAMS ((prototype, ...))
+   -- for functions which take a variable number of arguments.  Use
+   PARAMS to declare the function, VPARAMS to define it.  For example:
+
+       int printf PARAMS ((const char *format, ...));
+       ...
+       int
+       printf VPARAMS ((const char *format, ...))
+       {
+          ...
+       }
+
+   For writing functions which take variable numbers of arguments, we
+   also provide the VA_OPEN, VA_CLOSE, and VA_FIXEDARG macros.  These
+   hide the differences between K+R <varargs.h> and C89 <stdarg.h> more
+   thoroughly than the simple VA_START() macro mentioned above.
+
+   VA_OPEN and VA_CLOSE are used *instead of* va_start and va_end.
+   Immediately after VA_OPEN, put a sequence of VA_FIXEDARG calls
+   corresponding to the list of fixed arguments.  Then use va_arg
+   normally to get the variable arguments, or pass your va_list object
+   around.  You do not declare the va_list yourself; VA_OPEN does it
+   for you.
+
+   Here is a complete example:
+
+       int
+       printf VPARAMS ((const char *format, ...))
+       {
+          int result;
+
+          VA_OPEN (ap, format);
+          VA_FIXEDARG (ap, const char *, format);
+
+          result = vfprintf (stdout, format, ap);
+          VA_CLOSE (ap);
+
+          return result;
+       }
+
+
+   You can declare variables either before or after the VA_OPEN,
+   VA_FIXEDARG sequence.  Also, VA_OPEN and VA_CLOSE are the beginning
+   and end of a block.  They must appear at the same nesting level,
+   and any variables declared after VA_OPEN go out of scope at
+   VA_CLOSE.  Unfortunately, with a K+R compiler, that includes the
+   argument list.  You can have multiple instances of VA_OPEN/VA_CLOSE
+   pairs in a single function in case you need to traverse the
+   argument list more than once.
+
+   For ease of writing code which uses GCC extensions but needs to be
+   portable to other compilers, we provide the GCC_VERSION macro that
+   simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
+   wrappers around __attribute__.  Also, __extension__ will be #defined
+   to nothing if it doesn't work.  See below.
+
+   This header also defines a lot of obsolete macros:
+   CONST, VOLATILE, SIGNED, PROTO, EXFUN, DEFUN, DEFUN_VOID,
+   AND, DOTS, NOARGS.  Don't use them.  */
+
+#ifndef        _ANSIDECL_H
+#define _ANSIDECL_H    1
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+/* Using MACRO(x,y) in cpp #if conditionals does not work with some
+   older preprocessors.  Thus we can't define something like this:
+
+#define HAVE_GCC_VERSION(MAJOR, MINOR) \
+  (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR)))
+
+and then test "#if HAVE_GCC_VERSION(2,7)".
+
+So instead we use the macro below and test it against specific values.  */
+
+/* This macro simplifies testing whether we are using gcc, and if it
+   is of a particular minimum version. (Both major & minor numbers are
+   significant.)  This macro will evaluate to 0 if we are not using
+   gcc at all.  */
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif /* GCC_VERSION */
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus))
+/* 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__.  */
+/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other
+   C++ compilers, does not define __STDC__, though it acts as if this
+   was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
+
+#define ANSI_PROTOTYPES        1
+#define PTR            void *
+#define PTRCONST       void *const
+#define LONG_DOUBLE    long double
+
+/* PARAMS is often defined elsewhere (e.g. by libintl.h), so wrap it in
+   a #ifndef.  */
+#ifndef PARAMS
+#define PARAMS(ARGS)           ARGS
+#endif
+
+#define VPARAMS(ARGS)          ARGS
+#define VA_START(VA_LIST, VAR) va_start(VA_LIST, VAR)
+
+/* variadic function helper macros */
+/* "struct Qdmy" swallows the semicolon after VA_OPEN/VA_FIXEDARG's
+   use without inhibiting further decls and without declaring an
+   actual variable.  */
+#define VA_OPEN(AP, VAR)       { va_list AP; va_start(AP, VAR); { struct Qdmy
+#define VA_CLOSE(AP)           } va_end(AP); }
+#define VA_FIXEDARG(AP, T, N)  struct Qdmy
+
+#undef const
+#undef volatile
+#undef signed
+
+#ifdef __KERNEL__
+#ifndef        __STDC_VERSION__
+#define        __STDC_VERSION__ 0
+#endif
+#endif /* __KERNEL__ */
+
+/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
+   it too, but it's not in C89.  */
+#undef inline
+#if __STDC_VERSION__ > 199901L
+/* it's a keyword */
+#else
+# if GCC_VERSION >= 2007
+#  define inline __inline__   /* __inline__ prevents -pedantic warnings */
+# else
+#  define inline  /* nothing */
+# endif
+#endif
+
+/* These are obsolete.  Do not use.  */
+#ifndef IN_GCC
+#define CONST          const
+#define VOLATILE       volatile
+#define SIGNED         signed
+
+#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)
+#define AND            ,
+#define DOTS           , ...
+#define NOARGS         void
+#endif /* ! IN_GCC */
+
+#else  /* Not ANSI C.  */
+
+#undef  ANSI_PROTOTYPES
+#define PTR            char *
+#define PTRCONST       PTR
+#define LONG_DOUBLE    double
+
+#define PARAMS(args)           ()
+#define VPARAMS(args)          (va_alist) va_dcl
+#define VA_START(va_list, var) va_start(va_list)
+
+#define VA_OPEN(AP, VAR)               { va_list AP; va_start(AP); { struct Qdmy
+#define VA_CLOSE(AP)                   } va_end(AP); }
+#define VA_FIXEDARG(AP, TYPE, NAME)    TYPE NAME = va_arg(AP, TYPE)
+
+/* some systems define these in header files for non-ansi mode */
+#undef const
+#undef volatile
+#undef signed
+#undef inline
+#define const
+#define volatile
+#define signed
+#define inline
+
+#ifndef IN_GCC
+#define CONST
+#define VOLATILE
+#define SIGNED
+
+#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()
+#define AND            ;
+#define DOTS
+#define NOARGS
+#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 (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+/* Attribute __malloc__ on functions was valid as of gcc 2.96. */
+#ifndef ATTRIBUTE_MALLOC
+# if (GCC_VERSION >= 2096)
+#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+#  define ATTRIBUTE_MALLOC
+# endif /* GNUC >= 2.96 */
+#endif /* ATTRIBUTE_MALLOC */
+
+/* Attributes on labels were valid as of gcc 2.93. */
+#ifndef ATTRIBUTE_UNUSED_LABEL
+# if (!defined (__cplusplus) && GCC_VERSION >= 2093)
+#  define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
+# else
+#  define ATTRIBUTE_UNUSED_LABEL
+# endif /* !__cplusplus && GNUC >= 2.93 */
+#endif /* ATTRIBUTE_UNUSED_LABEL */
+
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif /* ATTRIBUTE_UNUSED */
+
+/* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the
+   identifier name.  */
+#if ! defined(__cplusplus) || (GCC_VERSION >= 3004)
+# define ARG_UNUSED(NAME) NAME ATTRIBUTE_UNUSED
+#else /* !__cplusplus || GNUC >= 3.4 */
+# define ARG_UNUSED(NAME) NAME
+#endif /* !__cplusplus || GNUC >= 3.4 */
+
+#ifndef ATTRIBUTE_NORETURN
+#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#endif /* ATTRIBUTE_NORETURN */
+
+/* Attribute `nonnull' was valid as of gcc 3.3.  */
+#ifndef ATTRIBUTE_NONNULL
+# if (GCC_VERSION >= 3003)
+#  define ATTRIBUTE_NONNULL(m) __attribute__ ((__nonnull__ (m)))
+# else
+#  define ATTRIBUTE_NONNULL(m)
+# endif /* GNUC >= 3.3 */
+#endif /* ATTRIBUTE_NONNULL */
+
+/* Attribute `pure' was valid as of gcc 3.0.  */
+#ifndef ATTRIBUTE_PURE
+# if (GCC_VERSION >= 3000)
+#  define ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+#  define ATTRIBUTE_PURE
+# endif /* GNUC >= 3.0 */
+#endif /* ATTRIBUTE_PURE */
+
+/* Use ATTRIBUTE_PRINTF when the format specifier must not be NULL.
+   This was the case for the `printf' format attribute by itself
+   before GCC 3.3, but as of 3.3 we need to add the `nonnull'
+   attribute to retain this behavior.  */
+#ifndef ATTRIBUTE_PRINTF
+#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) ATTRIBUTE_NONNULL(m)
+#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 */
+
+/* Use ATTRIBUTE_FPTR_PRINTF when the format attribute is to be set on
+   a function pointer.  Format attributes were allowed on function
+   pointers as of gcc 3.1.  */
+#ifndef ATTRIBUTE_FPTR_PRINTF
+# if (GCC_VERSION >= 3001)
+#  define ATTRIBUTE_FPTR_PRINTF(m, n) ATTRIBUTE_PRINTF(m, n)
+# else
+#  define ATTRIBUTE_FPTR_PRINTF(m, n)
+# endif /* GNUC >= 3.1 */
+# define ATTRIBUTE_FPTR_PRINTF_1 ATTRIBUTE_FPTR_PRINTF(1, 2)
+# define ATTRIBUTE_FPTR_PRINTF_2 ATTRIBUTE_FPTR_PRINTF(2, 3)
+# define ATTRIBUTE_FPTR_PRINTF_3 ATTRIBUTE_FPTR_PRINTF(3, 4)
+# define ATTRIBUTE_FPTR_PRINTF_4 ATTRIBUTE_FPTR_PRINTF(4, 5)
+# define ATTRIBUTE_FPTR_PRINTF_5 ATTRIBUTE_FPTR_PRINTF(5, 6)
+#endif /* ATTRIBUTE_FPTR_PRINTF */
+
+/* Use ATTRIBUTE_NULL_PRINTF when the format specifier may be NULL.  A
+   NULL format specifier was allowed as of gcc 3.3.  */
+#ifndef ATTRIBUTE_NULL_PRINTF
+# if (GCC_VERSION >= 3003)
+#  define ATTRIBUTE_NULL_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
+# else
+#  define ATTRIBUTE_NULL_PRINTF(m, n)
+# endif /* GNUC >= 3.3 */
+# define ATTRIBUTE_NULL_PRINTF_1 ATTRIBUTE_NULL_PRINTF(1, 2)
+# define ATTRIBUTE_NULL_PRINTF_2 ATTRIBUTE_NULL_PRINTF(2, 3)
+# define ATTRIBUTE_NULL_PRINTF_3 ATTRIBUTE_NULL_PRINTF(3, 4)
+# define ATTRIBUTE_NULL_PRINTF_4 ATTRIBUTE_NULL_PRINTF(4, 5)
+# define ATTRIBUTE_NULL_PRINTF_5 ATTRIBUTE_NULL_PRINTF(5, 6)
+#endif /* ATTRIBUTE_NULL_PRINTF */
+
+/* Attribute `sentinel' was valid as of gcc 3.5.  */
+#ifndef ATTRIBUTE_SENTINEL
+# if (GCC_VERSION >= 3005)
+#  define ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__))
+# else
+#  define ATTRIBUTE_SENTINEL
+# endif /* GNUC >= 3.5 */
+#endif /* ATTRIBUTE_SENTINEL */
+
+
+#ifndef ATTRIBUTE_ALIGNED_ALIGNOF
+# if (GCC_VERSION >= 3000)
+#  define ATTRIBUTE_ALIGNED_ALIGNOF(m) __attribute__ ((__aligned__ (__alignof__ (m))))
+# else
+#  define ATTRIBUTE_ALIGNED_ALIGNOF(m)
+# endif /* GNUC >= 3.0 */
+#endif /* ATTRIBUTE_ALIGNED_ALIGNOF */
+
+/* We use __extension__ in some places to suppress -pedantic warnings
+   about GCC extensions.  This feature didn't work properly before
+   gcc 2.8.  */
+#if GCC_VERSION < 2008
+#define __extension__
+#endif
+
+#endif /* ansidecl.h   */
diff --git a/arch/ia64/include/asm/bfd.h b/arch/ia64/include/asm/bfd.h
new file mode 100644 (file)
index 0000000..11ceefc
--- /dev/null
@@ -0,0 +1,5089 @@
+/* DO NOT EDIT!  -*- buffer-read-only: t -*-  This file is automatically
+   generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c",
+   "bfdio.c", "bfdwin.c", "section.c", "archures.c", "reloc.c",
+   "syms.c", "bfd.c", "archive.c", "corefile.c", "targets.c", "format.c",
+   "linker.c" and "simple.c".
+   Run "make headers" in your build bfd/ to regenerate.  */
+
+/* Main header file for the bfd library -- portable access to object files.
+
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+   Contributed by Cygnus Support.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __KERNEL__
+#include <asm/ansidecl.h>
+#else  /* __KERNEL__ */
+#include "ansidecl.h"
+#include "symcat.h"
+#endif /* __KERNEL__ */
+#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+#ifndef SABER
+/* This 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 XCONCAT2 macro will
+   cause the inner CONCAT2 macros to be evaluated first, producing
+   still-valid pp-tokens.  Then the final concatenation can be done.  */
+#undef CONCAT4
+#define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d))
+#endif
+#endif
+
+/* The word size used by BFD on the host.  This may be 64 with a 32
+   bit target if the host is 64 bit, or if other 64 bit targets have
+   been selected with --enable-targets, or if --enable-64-bit-bfd.  */
+#define BFD_ARCH_SIZE 64
+
+/* The word size of the default bfd target.  */
+#define BFD_DEFAULT_TARGET_SIZE 64
+
+#define BFD_HOST_64BIT_LONG 1
+#define BFD_HOST_LONG_LONG 1
+#if 1
+#define BFD_HOST_64_BIT long
+#define BFD_HOST_U_64_BIT unsigned long
+typedef BFD_HOST_64_BIT bfd_int64_t;
+typedef BFD_HOST_U_64_BIT bfd_uint64_t;
+#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;
+
+/* Boolean type used in bfd.  Too many systems define their own
+   versions of "boolean" for us to safely typedef a "boolean" of
+   our own.  Using an enum for "bfd_boolean" has its own set of
+   problems, with strange looking casts required to avoid warnings
+   on some older compilers.  Thus we just use an int.
+
+   General rule: Functions which are bfd_boolean return TRUE on
+   success and FALSE on failure (unless they're a predicate).  */
+
+typedef int bfd_boolean;
+#undef FALSE
+#undef TRUE
+#define FALSE 0
+#define TRUE 1
+
+#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 HALF_BFD_SIZE_TYPE \
+  (((bfd_size_type) 1) << (8 * sizeof (bfd_size_type) / 2))
+
+#ifndef BFD_HOST_64_BIT
+/* Fall back on a 32 bit type.  The idea is to make these types always
+   available for function return types, but in the case that
+   BFD_HOST_64_BIT is undefined such a function should abort or
+   otherwise signal an error.  */
+typedef bfd_signed_vma bfd_int64_t;
+typedef bfd_vma bfd_uint64_t;
+#endif
+
+/* An offset into a file.  BFD always uses the largest possible offset
+   based on the build time availability of fseek, fseeko, or fseeko64.  */
+typedef BFD_HOST_64_BIT file_ptr;
+typedef unsigned BFD_HOST_64_BIT ufile_ptr;
+
+extern void bfd_sprintf_vma (bfd *, char *, bfd_vma);
+extern void bfd_fprintf_vma (bfd *, void *, bfd_vma);
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+#define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+typedef int (*bfd_qsort_closure_func) (const void *, const void *, const void *);
+extern void bfd_qsort (void *base, bfd_size_type nmemb, bfd_size_type size,
+                      bfd_qsort_closure_func cmp, void *closure);
+\f
+/* File formats.  */
+
+typedef enum bfd_format
+{
+  bfd_unknown = 0,     /* File format is unknown.  */
+  bfd_object,          /* Linker/assembler/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
+
+/* The sections in this BFD specify a memory page.  */
+#define HAS_LOAD_PAGE 0x1000
+
+/* This BFD has been created by the linker and doesn't correspond
+   to any input file.  */
+#define BFD_LINKER_CREATED 0x2000
+\f
+/* 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.  */
+  union
+  {
+    file_ptr pos;
+    bfd *abfd;
+  } u;                 /* bfd* or file position.  */
+  int namidx;          /* Index into string table.  */
+};
+\f
+/* Linenumber stuff.  */
+typedef struct lineno_cache_entry
+{
+  unsigned int line_number;    /* Linenumber from start of function.  */
+  union
+  {
+    struct bfd_symbol *sym;    /* Function name.  */
+    bfd_vma offset;                    /* Offset into section.  */
+  } u;
+}
+alent;
+\f
+/* Object and core file sections.  */
+
+#define        align_power(addr, align)        \
+  (((addr) + ((bfd_vma) 1 << (align)) - 1) & ((bfd_vma) -1 << (align)))
+
+typedef struct bfd_section *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_lma(bfd, ptr) ((ptr)->lma + 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) ((ptr)->size)
+#define bfd_get_section_size(ptr) ((ptr)->size)
+#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 = 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)
+/* Find the address one past the end of SEC.  */
+#define bfd_get_section_limit(bfd, sec) \
+  (((sec)->rawsize ? (sec)->rawsize : (sec)->size) \
+   / bfd_octets_per_byte (bfd))
+
+typedef struct stat stat_type;
+\f
+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 (int);
+\f
+/* 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)
+    (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
+   /* An objalloc for this hash table.  This is a struct objalloc *,
+     but we use void * to avoid requiring the inclusion of objalloc.h.  */
+  void *memory;
+};
+
+/* Initialize a hash table.  */
+extern bfd_boolean bfd_hash_table_init
+  (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 bfd_boolean bfd_hash_table_init_n
+  (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
+  (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
+  (struct bfd_hash_table *, const char *, bfd_boolean create,
+   bfd_boolean copy);
+
+/* Replace an entry in a hash table.  */
+extern void bfd_hash_replace
+  (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
+  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
+
+/* Grab some space for a hash table entry.  */
+extern void *bfd_hash_allocate
+  (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
+  (struct bfd_hash_table *,
+   bfd_boolean (*) (struct bfd_hash_entry *, void *),
+   void *info);
+
+/* Allows the default size of a hash table to be configured. New hash
+   tables allocated using bfd_hash_table_init will be created with
+   this size.  */
+extern void bfd_hash_set_default_size (bfd_size_type);
+
+/* This structure is used to keep track of stabs in sections
+   information while linking.  */
+
+struct stab_info
+{
+  /* A hash table used to hold stabs strings.  */
+  struct bfd_strtab_hash *strings;
+  /* The header file hash table.  */
+  struct bfd_hash_table includes;
+  /* The first .stabstr section.  */
+  struct bfd_section *stabstr;
+};
+
+#define COFF_SWAP_TABLE (void *) &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_bread (void *, bfd_size_type, bfd *);
+extern bfd_size_type bfd_bwrite (const void *, bfd_size_type, bfd *);
+extern int bfd_seek (bfd *, file_ptr, int);
+extern file_ptr bfd_tell (bfd *);
+extern int bfd_flush (bfd *);
+extern int bfd_stat (bfd *, struct stat *);
+
+/* Deprecated old routines.  */
+#if __GNUC__
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD)                           \
+  (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__),     \
+   bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD)                          \
+  (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__),    \
+   bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#else
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD)                           \
+  (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \
+   bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD)                          \
+  (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\
+   bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#endif
+extern void warn_deprecated (const char *, const char *, int, const char *);
+
+/* 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_family_coff(abfd) \
+  (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \
+   bfd_get_flavour (abfd) == bfd_target_xcoff_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_dynamic_symcount(abfd) ((abfd)->dynsymcount)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE)
+
+extern bfd_boolean bfd_cache_close
+  (bfd *abfd);
+/* NB: This declaration should match the autogenerated one in libbfd.h.  */
+
+extern bfd_boolean bfd_cache_close_all (void);
+
+extern bfd_boolean bfd_record_phdr
+  (bfd *, unsigned long, bfd_boolean, flagword, bfd_boolean, bfd_vma,
+   bfd_boolean, bfd_boolean, unsigned int, struct bfd_section **);
+
+/* Byte swapping routines.  */
+
+bfd_uint64_t bfd_getb64 (const void *);
+bfd_uint64_t bfd_getl64 (const void *);
+bfd_int64_t bfd_getb_signed_64 (const void *);
+bfd_int64_t bfd_getl_signed_64 (const void *);
+bfd_vma bfd_getb32 (const void *);
+bfd_vma bfd_getl32 (const void *);
+bfd_signed_vma bfd_getb_signed_32 (const void *);
+bfd_signed_vma bfd_getl_signed_32 (const void *);
+bfd_vma bfd_getb16 (const void *);
+bfd_vma bfd_getl16 (const void *);
+bfd_signed_vma bfd_getb_signed_16 (const void *);
+bfd_signed_vma bfd_getl_signed_16 (const void *);
+void bfd_putb64 (bfd_uint64_t, void *);
+void bfd_putl64 (bfd_uint64_t, void *);
+void bfd_putb32 (bfd_vma, void *);
+void bfd_putl32 (bfd_vma, void *);
+void bfd_putb16 (bfd_vma, void *);
+void bfd_putl16 (bfd_vma, void *);
+
+/* Byte swapping routines which take size and endiannes as arguments.  */
+
+bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean);
+void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean);
+
+extern bfd_boolean bfd_section_already_linked_table_init (void);
+extern void bfd_section_already_linked_table_free (void);
+\f
+/* Externally visible ECOFF routines.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct bfd_symbol;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value
+  (bfd * abfd);
+extern bfd_boolean bfd_ecoff_set_gp_value
+  (bfd *abfd, bfd_vma gp_value);
+extern bfd_boolean bfd_ecoff_set_regmasks
+  (bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+   unsigned long *cprmask);
+extern void *bfd_ecoff_debug_init
+  (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
+  (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+   const struct ecoff_debug_swap *output_swap, struct bfd_link_info *);
+extern bfd_boolean bfd_ecoff_debug_accumulate
+  (void *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 bfd_boolean bfd_ecoff_debug_accumulate_other
+  (void *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 bfd_boolean bfd_ecoff_debug_externals
+  (bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap, bfd_boolean relocatable,
+   bfd_boolean (*get_extr) (struct bfd_symbol *, struct ecoff_extr *),
+   void (*set_index) (struct bfd_symbol *, bfd_size_type));
+extern bfd_boolean bfd_ecoff_debug_one_external
+  (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
+  (bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap);
+extern bfd_boolean bfd_ecoff_write_debug
+  (bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap, file_ptr where);
+extern bfd_boolean bfd_ecoff_write_accumulated_debug
+  (void *handle, bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap,
+   struct bfd_link_info *info, file_ptr where);
+
+/* Externally visible ELF routines.  */
+
+struct bfd_link_needed_list
+{
+  struct bfd_link_needed_list *next;
+  bfd *by;
+  const char *name;
+};
+
+enum dynamic_lib_link_class {
+  DYN_NORMAL = 0,
+  DYN_AS_NEEDED = 1,
+  DYN_DT_NEEDED = 2,
+  DYN_NO_ADD_NEEDED = 4,
+  DYN_NO_NEEDED = 8
+};
+
+extern bfd_boolean bfd_elf_record_link_assignment
+  (bfd *, struct bfd_link_info *, const char *, bfd_boolean,
+   bfd_boolean);
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_elf_get_bfd_needed_list
+  (bfd *, struct bfd_link_needed_list **);
+extern bfd_boolean bfd_elf_size_dynamic_sections
+  (bfd *, const char *, const char *, const char *, const char * const *,
+   struct bfd_link_info *, struct bfd_section **,
+   struct bfd_elf_version_tree *);
+extern bfd_boolean bfd_elf_size_dynsym_hash_dynstr
+  (bfd *, struct bfd_link_info *);
+extern void bfd_elf_set_dt_needed_name
+  (bfd *, const char *);
+extern const char *bfd_elf_get_dt_soname
+  (bfd *);
+extern void bfd_elf_set_dyn_lib_class
+  (bfd *, int);
+extern int bfd_elf_get_dyn_lib_class
+  (bfd *);
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_elf_discard_info
+  (bfd *, struct bfd_link_info *);
+extern unsigned int _bfd_elf_default_action_discarded
+  (struct bfd_section *);
+
+/* Return an upper bound on the number of bytes required to store a
+   copy of ABFD's program header table entries.  Return -1 if an error
+   occurs; bfd_get_error will return an appropriate code.  */
+extern long bfd_get_elf_phdr_upper_bound
+  (bfd *abfd);
+
+/* Copy ABFD's program header table entries to *PHDRS.  The entries
+   will be stored as an array of Elf_Internal_Phdr structures, as
+   defined in include/elf/internal.h.  To find out how large the
+   buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+   Return the number of program header table entries read, or -1 if an
+   error occurs; bfd_get_error will return an appropriate code.  */
+extern int bfd_get_elf_phdrs
+  (bfd *abfd, void *phdrs);
+
+/* Create a new BFD as if by bfd_openr.  Rather than opening a file,
+   reconstruct an ELF file by reading the segments out of remote memory
+   based on the ELF file header at EHDR_VMA and the ELF program headers it
+   points to.  If not null, *LOADBASEP is filled in with the difference
+   between the VMAs from which the segments were read, and the VMAs the
+   file headers (and hence BFD's idea of each section's VMA) put them at.
+
+   The function TARGET_READ_MEMORY is called to copy LEN bytes from the
+   remote memory at target address VMA into the local buffer at MYADDR; it
+   should return zero on success or an `errno' code on failure.  TEMPL must
+   be a BFD for an ELF target with the word size and byte order found in
+   the remote memory.  */
+extern bfd *bfd_elf_bfd_from_remote_memory
+  (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep,
+   int (*target_read_memory) (bfd_vma vma, bfd_byte *myaddr, int len));
+
+/* Return the arch_size field of an elf bfd, or -1 if not elf.  */
+extern int bfd_get_arch_size
+  (bfd *);
+
+/* Return TRUE if address "naturally" sign extends, or -1 if not elf.  */
+extern int bfd_get_sign_extend_vma
+  (bfd *);
+
+extern struct bfd_section *_bfd_elf_tls_setup
+  (bfd *, struct bfd_link_info *);
+
+extern void _bfd_fix_excluded_sec_syms
+  (bfd *, struct bfd_link_info *);
+
+extern bfd_boolean bfd_m68k_elf32_create_embedded_relocs
+  (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *,
+   char **);
+
+extern bfd_boolean bfd_bfin_elf32_create_embedded_relocs
+  (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *,
+   char **);
+
+/* SunOS shared library support routines for the linker.  */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_sunos_record_link_assignment
+  (bfd *, struct bfd_link_info *, const char *);
+extern bfd_boolean bfd_sunos_size_dynamic_sections
+  (bfd *, struct bfd_link_info *, struct bfd_section **,
+   struct bfd_section **, struct bfd_section **);
+
+/* Linux shared library support routines for the linker.  */
+
+extern bfd_boolean bfd_i386linux_size_dynamic_sections
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_m68klinux_size_dynamic_sections
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_sparclinux_size_dynamic_sections
+  (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.  */
+  void *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
+  (bfd_window *);
+extern void bfd_free_window
+  (bfd_window *);
+extern bfd_boolean bfd_get_file_window
+  (bfd *, file_ptr, bfd_size_type, bfd_window *, bfd_boolean);
+
+/* XCOFF support routines for the linker.  */
+
+extern bfd_boolean bfd_xcoff_link_record_set
+  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_size_type);
+extern bfd_boolean bfd_xcoff_import_symbol
+  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_vma,
+   const char *, const char *, const char *, unsigned int);
+extern bfd_boolean bfd_xcoff_export_symbol
+  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *);
+extern bfd_boolean bfd_xcoff_link_count_reloc
+  (bfd *, struct bfd_link_info *, const char *);
+extern bfd_boolean bfd_xcoff_record_link_assignment
+  (bfd *, struct bfd_link_info *, const char *);
+extern bfd_boolean bfd_xcoff_size_dynamic_sections
+  (bfd *, struct bfd_link_info *, const char *, const char *,
+   unsigned long, unsigned long, unsigned long, bfd_boolean,
+   int, bfd_boolean, bfd_boolean, struct bfd_section **, bfd_boolean);
+extern bfd_boolean bfd_xcoff_link_generate_rtinit
+  (bfd *, const char *, const char *, bfd_boolean);
+
+/* XCOFF support routines for ar.  */
+extern bfd_boolean bfd_xcoff_ar_archive_set_magic
+  (bfd *, char *);
+
+/* Externally visible COFF routines.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern bfd_boolean bfd_coff_get_syment
+  (bfd *, struct bfd_symbol *, struct internal_syment *);
+
+extern bfd_boolean bfd_coff_get_auxent
+  (bfd *, struct bfd_symbol *, int, union internal_auxent *);
+
+extern bfd_boolean bfd_coff_set_symbol_class
+  (bfd *, struct bfd_symbol *, unsigned int);
+
+extern bfd_boolean bfd_m68k_coff_create_embedded_relocs
+  (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **);
+
+/* ARM Interworking support.  Called from linker.  */
+extern bfd_boolean bfd_arm_allocate_interworking_sections
+  (struct bfd_link_info *);
+
+extern bfd_boolean bfd_arm_process_before_allocation
+  (bfd *, struct bfd_link_info *, int);
+
+extern bfd_boolean bfd_arm_get_bfd_for_interworking
+  (bfd *, struct bfd_link_info *);
+
+/* PE ARM Interworking support.  Called from linker.  */
+extern bfd_boolean bfd_arm_pe_allocate_interworking_sections
+  (struct bfd_link_info *);
+
+extern bfd_boolean bfd_arm_pe_process_before_allocation
+  (bfd *, struct bfd_link_info *, int);
+
+extern bfd_boolean bfd_arm_pe_get_bfd_for_interworking
+  (bfd *, struct bfd_link_info *);
+
+/* ELF ARM Interworking support.  Called from linker.  */
+extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections
+  (struct bfd_link_info *);
+
+extern bfd_boolean bfd_elf32_arm_process_before_allocation
+  (bfd *, struct bfd_link_info *, int);
+
+void bfd_elf32_arm_set_target_relocs
+  (struct bfd_link_info *, int, char *, int, int);
+
+extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
+  (bfd *, struct bfd_link_info *);
+
+extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd
+  (bfd *, struct bfd_link_info *);
+
+/* ELF ARM mapping symbol support */
+extern bfd_boolean bfd_is_arm_mapping_symbol_name
+  (const char * name);
+
+/* ARM Note section processing.  */
+extern bfd_boolean bfd_arm_merge_machines
+  (bfd *, bfd *);
+
+extern bfd_boolean bfd_arm_update_notes
+  (bfd *, const char *);
+
+extern unsigned int bfd_arm_get_mach_from_notes
+  (bfd *, const char *);
+
+/* TI COFF load page support.  */
+extern void bfd_ticoff_set_section_load_page
+  (struct bfd_section *, int);
+
+extern int bfd_ticoff_get_section_load_page
+  (struct bfd_section *);
+
+/* H8/300 functions.  */
+extern bfd_vma bfd_h8300_pad_address
+  (bfd *, bfd_vma);
+
+/* IA64 Itanium code generation.  Called from linker.  */
+extern void bfd_elf32_ia64_after_parse
+  (int);
+
+extern void bfd_elf64_ia64_after_parse
+  (int);
+
+/* 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 coff_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;
+};
+
+extern struct coff_comdat_info *bfd_coff_get_comdat_section
+  (bfd *, struct bfd_section *);
+
+/* Extracted from init.c.  */
+void bfd_init (void);
+
+/* Extracted from opncls.c.  */
+bfd *bfd_fopen (const char *filename, const char *target,
+    const char *mode, int fd);
+
+bfd *bfd_openr (const char *filename, const char *target);
+
+bfd *bfd_fdopenr (const char *filename, const char *target, int fd);
+
+bfd *bfd_openstreamr (const char *, const char *, void *);
+
+bfd *bfd_openr_iovec (const char *filename, const char *target,
+    void *(*open) (struct bfd *nbfd,
+    void *open_closure),
+    void *open_closure,
+    file_ptr (*pread) (struct bfd *nbfd,
+    void *stream,
+    void *buf,
+    file_ptr nbytes,
+    file_ptr offset),
+    int (*close) (struct bfd *nbfd,
+    void *stream));
+
+bfd *bfd_openw (const char *filename, const char *target);
+
+bfd_boolean bfd_close (bfd *abfd);
+
+bfd_boolean bfd_close_all_done (bfd *);
+
+bfd *bfd_create (const char *filename, bfd *templ);
+
+bfd_boolean bfd_make_writable (bfd *abfd);
+
+bfd_boolean bfd_make_readable (bfd *abfd);
+
+unsigned long bfd_calc_gnu_debuglink_crc32
+   (unsigned long crc, const unsigned char *buf, bfd_size_type len);
+
+char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir);
+
+struct bfd_section *bfd_create_gnu_debuglink_section
+   (bfd *abfd, const char *filename);
+
+bfd_boolean bfd_fill_in_gnu_debuglink_section
+   (bfd *abfd, struct bfd_section *sect, const char *filename);
+
+/* Extracted from libbfd.c.  */
+
+/* Byte swapping macros for user section data.  */
+
+#define bfd_put_8(abfd, val, ptr) \
+  ((void) (*((unsigned char *) (ptr)) = (val) & 0xff))
+#define bfd_put_signed_8 \
+  bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+  (*(unsigned char *) (ptr) & 0xff)
+#define bfd_get_signed_8(abfd, ptr) \
+  (((*(unsigned char *) (ptr) & 0xff) ^ 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_vma) 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))
+
+/* Aliases for the above, which should eventually go away.  */
+
+#define H_PUT_64  bfd_h_put_64
+#define H_PUT_32  bfd_h_put_32
+#define H_PUT_16  bfd_h_put_16
+#define H_PUT_8   bfd_h_put_8
+#define H_PUT_S64 bfd_h_put_signed_64
+#define H_PUT_S32 bfd_h_put_signed_32
+#define H_PUT_S16 bfd_h_put_signed_16
+#define H_PUT_S8  bfd_h_put_signed_8
+#define H_GET_64  bfd_h_get_64
+#define H_GET_32  bfd_h_get_32
+#define H_GET_16  bfd_h_get_16
+#define H_GET_8   bfd_h_get_8
+#define H_GET_S64 bfd_h_get_signed_64
+#define H_GET_S32 bfd_h_get_signed_32
+#define H_GET_S16 bfd_h_get_signed_16
+#define H_GET_S8  bfd_h_get_signed_8
+
+
+/* Extracted from bfdio.c.  */
+long bfd_get_mtime (bfd *abfd);
+
+long bfd_get_size (bfd *abfd);
+
+/* Extracted from bfdwin.c.  */
+/* Extracted from section.c.  */
+typedef struct bfd_section
+{
+  /* 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;
+
+  /* A unique sequence number.  */
+  int id;
+
+  /* Which section in the bfd; 0..n-1 as sections are created in a bfd.  */
+  int index;
+
+  /* The next section in the list belonging to the BFD, or NULL.  */
+  struct bfd_section *next;
+
+  /* The previous section in the list belonging to the BFD, or NULL.  */
+  struct bfd_section *prev;
+
+  /* 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
+
+  /* A signal to the OS that the section contains read only data.  */
+#define SEC_READONLY   0x008
+
+  /* The section contains code only.  */
+#define SEC_CODE       0x010
+
+  /* The section contains data only.  */
+#define SEC_DATA       0x020
+
+  /* The section will reside in ROM.  */
+#define SEC_ROM        0x040
+
+  /* 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 0x080
+
+  /* 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 0x100
+
+  /* An instruction to the linker to not output the section
+     even if it has information which would normally be written.  */
+#define SEC_NEVER_LOAD 0x200
+
+  /* The section contains thread local data.  */
+#define SEC_THREAD_LOCAL 0x400
+
+  /* The section has GOT references.  This flag is only for the
+     linker, and is currently only used by the elf32-hppa back end.
+     It will be set if global offset table references were detected
+     in this section, which indicate to the linker that the section
+     contains PIC code, and must be handled specially when doing a
+     static link.  */
+#define SEC_HAS_GOT_REF 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 0x1000
+
+  /* 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 0x2000
+
+  /* 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 0x4000
+
+  /* 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 0x8000
+
+  /* The contents of this section are to be sorted based on the sum of
+     the symbol and addend values specified by the associated relocation
+     entries.  Entries without associated relocation entries will be
+     appended to the end of the section in an unspecified order.  */
+#define SEC_SORT_ENTRIES 0x10000
+
+  /* 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 0x20000
+
+  /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+     should handle duplicate sections.  */
+#define SEC_LINK_DUPLICATES 0x40000
+
+  /* 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 0x80000
+
+  /* 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 0x100000
+
+  /* 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 \
+  (SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE)
+
+  /* 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 0x200000
+
+  /* This section should not be subject to garbage collection.  */
+#define SEC_KEEP 0x400000
+
+  /* This section contains "short" data, and should be placed
+     "near" the GP.  */
+#define SEC_SMALL_DATA 0x800000
+
+  /* Attempt to merge identical entities in the section.
+     Entity size is given in the entsize field.  */
+#define SEC_MERGE 0x1000000
+
+  /* If given with SEC_MERGE, entities to merge are zero terminated
+     strings where entsize specifies character size instead of fixed
+     size entries.  */
+#define SEC_STRINGS 0x2000000
+
+  /* This section contains data about section groups.  */
+#define SEC_GROUP 0x4000000
+
+  /* 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 0x10000000
+
+  /* This section contains data which may be shared with other
+     executables or shared objects. This is for COFF only.  */
+#define SEC_COFF_SHARED 0x20000000
+
+  /* When a section with this flag is being linked, then if the size of
+     the input section is less than a page, it should not cross a page
+     boundary.  If the size of the input section is one page or more,
+     it should be aligned on a page boundary.  This is for TI
+     TMS320C54X only.  */
+#define SEC_TIC54X_BLOCK 0x40000000
+
+  /* Conditionally link this section; do not link if there are no
+     references found to any symbol in the section.  This is for TI
+     TMS320C54X only.  */
+#define SEC_TIC54X_CLINK 0x80000000
+
+  /*  End of section flags.  */
+
+  /* Some internal packed boolean fields.  */
+
+  /* See the vma field.  */
+  unsigned int user_set_vma : 1;
+
+  /* A mark flag used by some of the linker backends.  */
+  unsigned int linker_mark : 1;
+
+  /* Another mark flag used by some of the linker backends.  Set for
+     output sections that have an input section.  */
+  unsigned int linker_has_input : 1;
+
+  /* Mark flags used by some linker backends for garbage collection.  */
+  unsigned int gc_mark : 1;
+  unsigned int gc_mark_from_eh : 1;
+
+  /* The following flags are used by the ELF linker. */
+
+  /* Mark sections which have been allocated to segments.  */
+  unsigned int segment_mark : 1;
+
+  /* Type of sec_info information.  */
+  unsigned int sec_info_type:3;
+#define ELF_INFO_TYPE_NONE      0
+#define ELF_INFO_TYPE_STABS     1
+#define ELF_INFO_TYPE_MERGE     2
+#define ELF_INFO_TYPE_EH_FRAME  3
+#define ELF_INFO_TYPE_JUST_SYMS 4
+
+  /* Nonzero if this section uses RELA relocations, rather than REL.  */
+  unsigned int use_rela_p:1;
+
+  /* Bits used by various backends.  The generic code doesn't touch
+     these fields.  */
+
+  /* Nonzero if this section has TLS related relocations.  */
+  unsigned int has_tls_reloc:1;
+
+  /* Nonzero if this section has a gp reloc.  */
+  unsigned int has_gp_reloc:1;
+
+  /* Nonzero if this section needs the relax finalize pass.  */
+  unsigned int need_finalize_relax:1;
+
+  /* Whether relocations have been processed.  */
+  unsigned int reloc_done : 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 octets, as it will be output.
+     Contains a value even if the section has no contents (e.g., the
+     size of <<.bss>>).  */
+  bfd_size_type size;
+
+  /* For input sections, the original size on disk of the section, in
+     octets.  This field is used by the linker relaxation code.  It is
+     currently only set for sections where the linker relaxation scheme
+     doesn't cache altered section and reloc contents (stabs, eh_frame,
+     SEC_MERGE, some coff relaxing targets), and thus the original size
+     needs to be kept to read the section multiple times.
+     For output sections, rawsize holds the section size calculated on
+     a previous linker relaxation pass.  */
+  bfd_size_type rawsize;
+
+  /* If this section is going to be output, then this value is the
+     offset in *bytes* into the output section of the first byte in the
+     input section (byte ==> smallest addressable unit on the
+     target).  In most cases, if this was going to start at the
+     100th octet (8-bit quantity) in the output section, this value
+     would be 100.  However, if the target byte size is 16 bits
+     (bfd_octets_per_byte is "2"), this value would be 50.  */
+  bfd_vma output_offset;
+
+  /* The output section through which to map on output.  */
+  struct bfd_section *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.  */
+  void *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;
+
+  /* Entity size for merging purposes.  */
+  unsigned int entsize;
+
+  /* Points to the kept section if this section is a link-once section,
+     and is discarded.  */
+  struct bfd_section *kept_section;
+
+  /* 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;
+
+  void *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 bfd_symbol *symbol;
+  struct bfd_symbol **symbol_ptr_ptr;
+
+  /* Early in the link process, map_head and map_tail are used to build
+     a list of input sections attached to an output section.  Later,
+     output sections use these fields for a list of bfd_link_order
+     structs.  */
+  union {
+    struct bfd_link_order *link_order;
+    struct bfd_section *s;
+  } map_head, map_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 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 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 asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+/* Pointer to the indirect section.  */
+extern asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+#define bfd_is_const_section(SEC)              \
+ (   ((SEC) == bfd_abs_section_ptr)            \
+  || ((SEC) == bfd_und_section_ptr)            \
+  || ((SEC) == bfd_com_section_ptr)            \
+  || ((SEC) == bfd_ind_section_ptr))
+
+extern const struct bfd_symbol * const bfd_abs_symbol;
+extern const struct bfd_symbol * const bfd_com_symbol;
+extern const struct bfd_symbol * const bfd_und_symbol;
+extern const struct bfd_symbol * const bfd_ind_symbol;
+
+/* Macros to handle insertion and deletion of a bfd's sections.  These
+   only handle the list pointers, ie. do not adjust section_count,
+   target_index etc.  */
+#define bfd_section_list_remove(ABFD, S) \
+  do                                                   \
+    {                                                  \
+      asection *_s = S;                                \
+      asection *_next = _s->next;                      \
+      asection *_prev = _s->prev;                      \
+      if (_prev)                                       \
+        _prev->next = _next;                           \
+      else                                             \
+        (ABFD)->sections = _next;                      \
+      if (_next)                                       \
+        _next->prev = _prev;                           \
+      else                                             \
+        (ABFD)->section_last = _prev;                  \
+    }                                                  \
+  while (0)
+#define bfd_section_list_append(ABFD, S) \
+  do                                                   \
+    {                                                  \
+      asection *_s = S;                                \
+      bfd *_abfd = ABFD;                               \
+      _s->next = NULL;                                 \
+      if (_abfd->section_last)                         \
+        {                                              \
+          _s->prev = _abfd->section_last;              \
+          _abfd->section_last->next = _s;              \
+        }                                              \
+      else                                             \
+        {                                              \
+          _s->prev = NULL;                             \
+          _abfd->sections = _s;                        \
+        }                                              \
+      _abfd->section_last = _s;                        \
+    }                                                  \
+  while (0)
+#define bfd_section_list_prepend(ABFD, S) \
+  do                                                   \
+    {                                                  \
+      asection *_s = S;                                \
+      bfd *_abfd = ABFD;                               \
+      _s->prev = NULL;                                 \
+      if (_abfd->sections)                             \
+        {                                              \
+          _s->next = _abfd->sections;                  \
+          _abfd->sections->prev = _s;                  \
+        }                                              \
+      else                                             \
+        {                                              \
+          _s->next = NULL;                             \
+          _abfd->section_last = _s;                    \
+        }                                              \
+      _abfd->sections = _s;                            \
+    }                                                  \
+  while (0)
+#define bfd_section_list_insert_after(ABFD, A, S) \
+  do                                                   \
+    {                                                  \
+      asection *_a = A;                                \
+      asection *_s = S;                                \
+      asection *_next = _a->next;                      \
+      _s->next = _next;                                \
+      _s->prev = _a;                                   \
+      _a->next = _s;                                   \
+      if (_next)                                       \
+        _next->prev = _s;                              \
+      else                                             \
+        (ABFD)->section_last = _s;                     \
+    }                                                  \
+  while (0)
+#define bfd_section_list_insert_before(ABFD, B, S) \
+  do                                                   \
+    {                                                  \
+      asection *_b = B;                                \
+      asection *_s = S;                                \
+      asection *_prev = _b->prev;                      \
+      _s->prev = _prev;                                \
+      _s->next = _b;                                   \
+      _b->prev = _s;                                   \
+      if (_prev)                                       \
+        _prev->next = _s;                              \
+      else                                             \
+        (ABFD)->sections = _s;                         \
+    }                                                  \
+  while (0)
+#define bfd_section_removed_from_list(ABFD, S) \
+  ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S))
+
+#define BFD_FAKE_SECTION(SEC, FLAGS, SYM, SYM_PTR, NAME, IDX)          \
+  /* name, id,  index, next, prev, flags, user_set_vma,            */  \
+  { NAME,  IDX, 0,     NULL, NULL, FLAGS, 0,                           \
+                                                                       \
+  /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh,      */  \
+     0,           0,                1,       0,                        \
+                                                                       \
+  /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc,       */  \
+     0,            0,             0,          0,                       \
+                                                                       \
+  /* has_gp_reloc, need_finalize_relax, reloc_done,                */  \
+     0,            0,                   0,                             \
+                                                                       \
+  /* vma, lma, size, rawsize                                       */  \
+     0,   0,   0,    0,                                                \
+                                                                       \
+  /* output_offset, output_section,              alignment_power,  */  \
+     0,             (struct bfd_section *) &SEC, 0,                    \
+                                                                       \
+  /* relocation, orelocation, reloc_count, filepos, rel_filepos,   */  \
+     NULL,       NULL,        0,           0,       0,                 \
+                                                                       \
+  /* line_filepos, userdata, contents, lineno, lineno_count,       */  \
+     0,            NULL,     NULL,     NULL,   0,                      \
+                                                                       \
+  /* entsize, kept_section, moving_line_filepos,                    */ \
+     0,       NULL,          0,                                        \
+                                                                       \
+  /* target_index, used_by_bfd, constructor_chain, owner,          */  \
+     0,            NULL,        NULL,              NULL,               \
+                                                                       \
+  /* symbol,                                                       */  \
+     (struct bfd_symbol *) SYM,                                        \
+                                                                       \
+  /* symbol_ptr_ptr,                                               */  \
+     (struct bfd_symbol **) SYM_PTR,                                   \
+                                                                       \
+  /* map_head, map_tail                                            */  \
+     { NULL }, { NULL }                                                \
+    }
+
+void bfd_section_list_clear (bfd *);
+
+asection *bfd_get_section_by_name (bfd *abfd, const char *name);
+
+asection *bfd_get_section_by_name_if
+   (bfd *abfd,
+    const char *name,
+    bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj),
+    void *obj);
+
+char *bfd_get_unique_section_name
+   (bfd *abfd, const char *templat, int *count);
+
+asection *bfd_make_section_old_way (bfd *abfd, const char *name);
+
+asection *bfd_make_section_anyway_with_flags
+   (bfd *abfd, const char *name, flagword flags);
+
+asection *bfd_make_section_anyway (bfd *abfd, const char *name);
+
+asection *bfd_make_section_with_flags
+   (bfd *, const char *name, flagword flags);
+
+asection *bfd_make_section (bfd *, const char *name);
+
+bfd_boolean bfd_set_section_flags
+   (bfd *abfd, asection *sec, flagword flags);
+
+void bfd_map_over_sections
+   (bfd *abfd,
+    void (*func) (bfd *abfd, asection *sect, void *obj),
+    void *obj);
+
+asection *bfd_sections_find_if
+   (bfd *abfd,
+    bfd_boolean (*operation) (bfd *abfd, asection *sect, void *obj),
+    void *obj);
+
+bfd_boolean bfd_set_section_size
+   (bfd *abfd, asection *sec, bfd_size_type val);
+
+bfd_boolean bfd_set_section_contents
+   (bfd *abfd, asection *section, const void *data,
+    file_ptr offset, bfd_size_type count);
+
+bfd_boolean bfd_get_section_contents
+   (bfd *abfd, asection *section, void *location, file_ptr offset,
+    bfd_size_type count);
+
+bfd_boolean bfd_malloc_and_get_section
+   (bfd *abfd, asection *section, bfd_byte **buf);
+
+bfd_boolean bfd_copy_private_section_data
+   (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))
+bfd_boolean bfd_generic_is_group_section (bfd *, const asection *sec);
+
+bfd_boolean bfd_generic_discard_group (bfd *abfd, asection *group);
+
+/* Extracted from archures.c.  */
+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
+#define bfd_mach_mcf5200  9
+#define bfd_mach_mcf5206e 10
+#define bfd_mach_mcf5307  11
+#define bfd_mach_mcf5407  12
+#define bfd_mach_mcf528x  13
+#define bfd_mach_mcfv4e   14
+#define bfd_mach_mcf521x   15
+#define bfd_mach_mcf5249   16
+#define bfd_mach_mcf547x   17
+#define bfd_mach_mcf548x   18
+  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_or32,      /* OpenRISC 32 */
+
+  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.  */
+#define bfd_mach_sparc_v8plusb         9 /* with cheetah add'ns.  */
+#define bfd_mach_sparc_v9b             10 /* with cheetah 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_v9b \
+   && (mach) != bfd_mach_sparc_sparclite_le)
+/* Nonzero if MACH is a 64 bit sparc architecture.  */
+#define bfd_mach_sparc_64bit_p(mach) \
+  ((mach) >= bfd_mach_sparc_v9 && (mach) != bfd_mach_sparc_v8plusb)
+  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_mips4120              4120
+#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_mips5400              5400
+#define bfd_mach_mips5500              5500
+#define bfd_mach_mips6000              6000
+#define bfd_mach_mips7000              7000
+#define bfd_mach_mips8000              8000
+#define bfd_mach_mips9000              9000
+#define bfd_mach_mips10000             10000
+#define bfd_mach_mips12000             12000
+#define bfd_mach_mips16                16
+#define bfd_mach_mips5                 5
+#define bfd_mach_mips_sb1              12310201 /* octal 'SB', 01 */
+#define bfd_mach_mipsisa32             32
+#define bfd_mach_mipsisa32r2           33
+#define bfd_mach_mipsisa64             64
+#define bfd_mach_mipsisa64r2           65
+  bfd_arch_i386,      /* Intel 386 */
+#define bfd_mach_i386_i386 1
+#define bfd_mach_i386_i8086 2
+#define bfd_mach_i386_i386_intel_syntax 3
+#define bfd_mach_x86_64 64
+#define bfd_mach_x86_64_intel_syntax 65
+  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_convex,    /* Convex */
+  bfd_arch_m88k,      /* Motorola 88xxx */
+  bfd_arch_m98k,      /* Motorola 98xxx */
+  bfd_arch_pyramid,   /* Pyramid Technology */
+  bfd_arch_h8300,     /* Renesas H8/300 (formerly Hitachi H8/300) */
+#define bfd_mach_h8300    1
+#define bfd_mach_h8300h   2
+#define bfd_mach_h8300s   3
+#define bfd_mach_h8300hn  4
+#define bfd_mach_h8300sn  5
+#define bfd_mach_h8300sx  6
+#define bfd_mach_h8300sxn 7
+  bfd_arch_pdp11,     /* DEC PDP-11 */
+  bfd_arch_powerpc,   /* PowerPC */
+#define bfd_mach_ppc           32
+#define bfd_mach_ppc64         64
+#define bfd_mach_ppc_403       403
+#define bfd_mach_ppc_403gc     4030
+#define bfd_mach_ppc_505       505
+#define bfd_mach_ppc_601       601
+#define bfd_mach_ppc_602       602
+#define bfd_mach_ppc_603       603
+#define bfd_mach_ppc_ec603e    6031
+#define bfd_mach_ppc_604       604
+#define bfd_mach_ppc_620       620
+#define bfd_mach_ppc_630       630
+#define bfd_mach_ppc_750       750
+#define bfd_mach_ppc_860       860
+#define bfd_mach_ppc_a35       35
+#define bfd_mach_ppc_rs64ii    642
+#define bfd_mach_ppc_rs64iii   643
+#define bfd_mach_ppc_7400      7400
+#define bfd_mach_ppc_e500      500
+  bfd_arch_rs6000,    /* IBM RS/6000 */
+#define bfd_mach_rs6k          6000
+#define bfd_mach_rs6k_rs1      6001
+#define bfd_mach_rs6k_rsc      6003
+#define bfd_mach_rs6k_rs2      6002
+  bfd_arch_hppa,      /* HP PA RISC */
+#define bfd_mach_hppa10        10
+#define bfd_mach_hppa11        11
+#define bfd_mach_hppa20        20
+#define bfd_mach_hppa20w       25
+  bfd_arch_d10v,      /* Mitsubishi D10V */
+#define bfd_mach_d10v          1
+#define bfd_mach_d10v_ts2      2
+#define bfd_mach_d10v_ts3      3
+  bfd_arch_d30v,      /* Mitsubishi D30V */
+  bfd_arch_dlx,       /* DLX */
+  bfd_arch_m68hc11,   /* Motorola 68HC11 */
+  bfd_arch_m68hc12,   /* Motorola 68HC12 */
+#define bfd_mach_m6812_default 0
+#define bfd_mach_m6812         1
+#define bfd_mach_m6812s        2
+  bfd_arch_z8k,       /* Zilog Z8000 */
+#define bfd_mach_z8001         1
+#define bfd_mach_z8002         2
+  bfd_arch_h8500,     /* Renesas H8/500 (formerly Hitachi H8/500) */
+  bfd_arch_sh,        /* Renesas / SuperH SH (formerly Hitachi SH) */
+#define bfd_mach_sh            1
+#define bfd_mach_sh2        0x20
+#define bfd_mach_sh_dsp     0x2d
+#define bfd_mach_sh2a       0x2a
+#define bfd_mach_sh2a_nofpu 0x2b
+#define bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu 0x2a1
+#define bfd_mach_sh2a_nofpu_or_sh3_nommu 0x2a2
+#define bfd_mach_sh2a_or_sh4  0x2a3
+#define bfd_mach_sh2a_or_sh3e 0x2a4
+#define bfd_mach_sh2e       0x2e
+#define bfd_mach_sh3        0x30
+#define bfd_mach_sh3_nommu  0x31
+#define bfd_mach_sh3_dsp    0x3d
+#define bfd_mach_sh3e       0x3e
+#define bfd_mach_sh4        0x40
+#define bfd_mach_sh4_nofpu  0x41
+#define bfd_mach_sh4_nommu_nofpu  0x42
+#define bfd_mach_sh4a       0x4a
+#define bfd_mach_sh4a_nofpu 0x4b
+#define bfd_mach_sh4al_dsp  0x4d
+#define bfd_mach_sh5        0x50
+  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_unknown   0
+#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
+#define bfd_mach_arm_5TE       9
+#define bfd_mach_arm_XScale    10
+#define bfd_mach_arm_ep9312    11
+#define bfd_mach_arm_iWMMXt    12
+  bfd_arch_ns32k,     /* National Semiconductors ns32000 */
+  bfd_arch_w65,       /* WDC 65816 */
+  bfd_arch_tic30,     /* Texas Instruments TMS320C30 */
+  bfd_arch_tic4x,     /* Texas Instruments TMS320C3X/4X */
+#define bfd_mach_tic3x         30
+#define bfd_mach_tic4x         40
+  bfd_arch_tic54x,    /* Texas Instruments TMS320C54X */
+  bfd_arch_tic80,     /* TI TMS320c80 (MVP) */
+  bfd_arch_v850,      /* NEC V850 */
+#define bfd_mach_v850          1
+#define bfd_mach_v850e         'E'
+#define bfd_mach_v850e1        '1'
+  bfd_arch_arc,       /* ARC Cores */
+#define bfd_mach_arc_5         5
+#define bfd_mach_arc_6         6
+#define bfd_mach_arc_7         7
+#define bfd_mach_arc_8         8
+ bfd_arch_m32c,     /* Renesas M16C/M32C.  */
+#define bfd_mach_m16c        0x75
+#define bfd_mach_m32c        0x78
+  bfd_arch_m32r,      /* Renesas M32R (formerly Mitsubishi M32R/D) */
+#define bfd_mach_m32r          1 /* For backwards compatibility.  */
+#define bfd_mach_m32rx         'x'
+#define bfd_mach_m32r2         '2'
+  bfd_arch_mn10200,   /* Matsushita MN10200 */
+  bfd_arch_mn10300,   /* Matsushita MN10300 */
+#define bfd_mach_mn10300               300
+#define bfd_mach_am33          330
+#define bfd_mach_am33_2        332
+  bfd_arch_fr30,
+#define bfd_mach_fr30          0x46523330
+  bfd_arch_frv,
+#define bfd_mach_frv           1
+#define bfd_mach_frvsimple     2
+#define bfd_mach_fr300         300
+#define bfd_mach_fr400         400
+#define bfd_mach_fr450         450
+#define bfd_mach_frvtomcat     499     /* fr500 prototype */
+#define bfd_mach_fr500         500
+#define bfd_mach_fr550         550
+  bfd_arch_mcore,
+  bfd_arch_ia64,      /* HP/Intel ia64 */
+#define bfd_mach_ia64_elf64    64
+#define bfd_mach_ia64_elf32    32
+  bfd_arch_ip2k,      /* Ubicom IP2K microcontrollers. */
+#define bfd_mach_ip2022        1
+#define bfd_mach_ip2022ext     2
+ bfd_arch_iq2000,     /* Vitesse IQ2000.  */
+#define bfd_mach_iq2000        1
+#define bfd_mach_iq10          2
+  bfd_arch_mt,
+#define bfd_mach_ms1           1
+#define bfd_mach_mrisc2        2
+#define bfd_mach_ms2           3
+  bfd_arch_pj,
+  bfd_arch_avr,       /* Atmel AVR microcontrollers.  */
+#define bfd_mach_avr1          1
+#define bfd_mach_avr2          2
+#define bfd_mach_avr3          3
+#define bfd_mach_avr4          4
+#define bfd_mach_avr5          5
+  bfd_arch_bfin,        /* ADI Blackfin */
+#define bfd_mach_bfin          1
+  bfd_arch_cr16c,       /* National Semiconductor CompactRISC. */
+#define bfd_mach_cr16c         1
+  bfd_arch_crx,       /*  National Semiconductor CRX.  */
+#define bfd_mach_crx           1
+  bfd_arch_cris,      /* Axis CRIS */
+#define bfd_mach_cris_v0_v10   255
+#define bfd_mach_cris_v32      32
+#define bfd_mach_cris_v10_v32  1032
+  bfd_arch_s390,      /* IBM s390 */
+#define bfd_mach_s390_31       31
+#define bfd_mach_s390_64       64
+  bfd_arch_openrisc,  /* OpenRISC */
+  bfd_arch_mmix,      /* Donald Knuth's educational processor.  */
+  bfd_arch_xstormy16,
+#define bfd_mach_xstormy16     1
+  bfd_arch_msp430,    /* Texas Instruments MSP430 architecture.  */
+#define bfd_mach_msp11          11
+#define bfd_mach_msp110         110
+#define bfd_mach_msp12          12
+#define bfd_mach_msp13          13
+#define bfd_mach_msp14          14
+#define bfd_mach_msp15          15
+#define bfd_mach_msp16          16
+#define bfd_mach_msp21          21
+#define bfd_mach_msp31          31
+#define bfd_mach_msp32          32
+#define bfd_mach_msp33          33
+#define bfd_mach_msp41          41
+#define bfd_mach_msp42          42
+#define bfd_mach_msp43          43
+#define bfd_mach_msp44          44
+  bfd_arch_xtensa,    /* Tensilica's Xtensa cores.  */
+#define bfd_mach_xtensa        1
+   bfd_arch_maxq,     /* Dallas MAXQ 10/20 */
+#define bfd_mach_maxq10    10
+#define bfd_mach_maxq20    20
+  bfd_arch_z80,
+#define bfd_mach_z80strict      1 /* No undocumented opcodes.  */
+#define bfd_mach_z80            3 /* With ixl, ixh, iyl, and iyh.  */
+#define bfd_mach_z80full        7 /* All undocumented instructions.  */
+#define bfd_mach_r800           11 /* R800: successor with multiplication.  */
+  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.
+     The default arch should be the first entry for an arch so that
+     all the entries for that arch can be accessed via <<next>>.  */
+  bfd_boolean the_default;
+  const struct bfd_arch_info * (*compatible)
+    (const struct bfd_arch_info *a, const struct bfd_arch_info *b);
+
+  bfd_boolean (*scan) (const struct bfd_arch_info *, const char *);
+
+  const struct bfd_arch_info *next;
+}
+bfd_arch_info_type;
+
+const char *bfd_printable_name (bfd *abfd);
+
+const bfd_arch_info_type *bfd_scan_arch (const char *string);
+
+const char **bfd_arch_list (void);
+
+const bfd_arch_info_type *bfd_arch_get_compatible
+   (const bfd *abfd, const bfd *bbfd, bfd_boolean accept_unknowns);
+
+void bfd_set_arch_info (bfd *abfd, const bfd_arch_info_type *arg);
+
+enum bfd_architecture bfd_get_arch (bfd *abfd);
+
+unsigned long bfd_get_mach (bfd *abfd);
+
+unsigned int bfd_arch_bits_per_byte (bfd *abfd);
+
+unsigned int bfd_arch_bits_per_address (bfd *abfd);
+
+const bfd_arch_info_type *bfd_get_arch_info (bfd *abfd);
+
+const bfd_arch_info_type *bfd_lookup_arch
+   (enum bfd_architecture arch, unsigned long machine);
+
+const char *bfd_printable_arch_mach
+   (enum bfd_architecture arch, unsigned long machine);
+
+unsigned int bfd_octets_per_byte (bfd *abfd);
+
+unsigned int bfd_arch_mach_octets_per_byte
+   (enum bfd_architecture arch, unsigned long machine);
+
+/* Extracted from reloc.c.  */
+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 bfd_symbol **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 value overflows when considered as a signed
+     number one bit larger than the field.  ie. A bitfield of N bits
+     is allowed to represent -2**n to 2**n-1.  */
+  complain_overflow_bitfield,
+
+  /* Complain if the value overflows when considered as a 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.  */
+  bfd_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 accommodated (e.g., i960 callj
+     instructions).  */
+  bfd_reloc_status_type (*special_function)
+    (bfd *, arelent *, struct bfd_symbol *, void *, asection *,
+     bfd *, char **);
+
+  /* The textual name of the relocation type.  */
+  char *name;
+
+  /* Some formats record a relocation addend in the section contents
+     rather than with the relocation.  For ELF formats this is the
+     distinction between USE_REL and USE_RELA (though the code checks
+     for USE_REL == 1/0).  The value of this field is TRUE if the
+     addend is recorded with the section contents; when performing a
+     partial link (ld -r) the section contents (the data) will be
+     modified.  The value of this field is FALSE if addends are
+     recorded with the relocation (in arelent.addend); when performing
+     a partial link the relocation will be modified.
+     All relocations for all ELF USE_RELA targets should set this field
+     to FALSE (values of TRUE should be looked on with suspicion).
+     However, the converse is not true: not all relocations of all ELF
+     USE_REL targets set this field to TRUE.  Why this is so is peculiar
+     to each particular target.  For relocs that aren't used in partial
+     links (e.g. GOT stuff) it doesn't matter what this is set to.  */
+  bfd_boolean partial_inplace;
+
+  /* src_mask selects the part of the instruction (or data) to be used
+     in the relocation sum.  If the target relocations don't have an
+     addend in the reloc, eg. ELF USE_REL, src_mask will normally equal
+     dst_mask to extract the addend from the section contents.  If
+     relocations do have an addend in the reloc, eg. ELF USE_RELA, this
+     field should be zero.  Non-zero values for ELF USE_RELA targets are
+     bogus as in those cases the value in the dst_mask part of the
+     section contents should be treated as garbage.  */
+  bfd_vma src_mask;
+
+  /* dst_mask selects which parts of the instruction (or data) are
+     replaced with a relocated value.  */
+  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.  */
+  bfd_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 != NULL)                                 \
+      {                                                 \
+        if (bfd_is_com_section (symbol->section))       \
+          {                                             \
+            relocation = 0;                             \
+          }                                             \
+        else                                            \
+          {                                             \
+            relocation = symbol->value;                 \
+          }                                             \
+      }                                                 \
+  }
+
+unsigned int bfd_get_reloc_size (reloc_howto_type *);
+
+typedef struct relent_chain
+{
+  arelent relent;
+  struct relent_chain *next;
+}
+arelent_chain;
+
+bfd_reloc_status_type bfd_check_overflow
+   (enum complain_overflow how,
+    unsigned int bitsize,
+    unsigned int rightshift,
+    unsigned int addrsize,
+    bfd_vma relocation);
+
+bfd_reloc_status_type bfd_perform_relocation
+   (bfd *abfd,
+    arelent *reloc_entry,
+    void *data,
+    asection *input_section,
+    bfd *output_bfd,
+    char **error_message);
+
+bfd_reloc_status_type bfd_install_relocation
+   (bfd *abfd,
+    arelent *reloc_entry,
+    void *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,
+
+/* Section relative relocations.  Some targets need this for DWARF2.  */
+  BFD_RELOC_32_SECREL,
+
+/* 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_64_PLT_PCREL,
+  BFD_RELOC_32_PLT_PCREL,
+  BFD_RELOC_24_PLT_PCREL,
+  BFD_RELOC_16_PLT_PCREL,
+  BFD_RELOC_8_PLT_PCREL,
+  BFD_RELOC_64_PLTOFF,
+  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_UA16,
+  BFD_RELOC_SPARC_UA32,
+  BFD_RELOC_SPARC_UA64,
+
+/* 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_PLT32,
+  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,
+
+/* SPARC TLS relocations  */
+  BFD_RELOC_SPARC_TLS_GD_HI22,
+  BFD_RELOC_SPARC_TLS_GD_LO10,
+  BFD_RELOC_SPARC_TLS_GD_ADD,
+  BFD_RELOC_SPARC_TLS_GD_CALL,
+  BFD_RELOC_SPARC_TLS_LDM_HI22,
+  BFD_RELOC_SPARC_TLS_LDM_LO10,
+  BFD_RELOC_SPARC_TLS_LDM_ADD,
+  BFD_RELOC_SPARC_TLS_LDM_CALL,
+  BFD_RELOC_SPARC_TLS_LDO_HIX22,
+  BFD_RELOC_SPARC_TLS_LDO_LOX10,
+  BFD_RELOC_SPARC_TLS_LDO_ADD,
+  BFD_RELOC_SPARC_TLS_IE_HI22,
+  BFD_RELOC_SPARC_TLS_IE_LO10,
+  BFD_RELOC_SPARC_TLS_IE_LD,
+  BFD_RELOC_SPARC_TLS_IE_LDX,
+  BFD_RELOC_SPARC_TLS_IE_ADD,
+  BFD_RELOC_SPARC_TLS_LE_HIX22,
+  BFD_RELOC_SPARC_TLS_LE_LOX10,
+  BFD_RELOC_SPARC_TLS_DTPMOD32,
+  BFD_RELOC_SPARC_TLS_DTPMOD64,
+  BFD_RELOC_SPARC_TLS_DTPOFF32,
+  BFD_RELOC_SPARC_TLS_DTPOFF64,
+  BFD_RELOC_SPARC_TLS_TPOFF32,
+  BFD_RELOC_SPARC_TLS_TPOFF64,
+
+/* 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)  */
+  BFD_RELOC_ALPHA_LITERAL,
+  BFD_RELOC_ALPHA_ELF_LITERAL,
+  BFD_RELOC_ALPHA_LITUSE,
+
+/* 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,
+
+/* The GPREL_HI/LO relocations together form a 32-bit offset from the
+GP register.  */
+  BFD_RELOC_ALPHA_GPREL_HI16,
+  BFD_RELOC_ALPHA_GPREL_LO16,
+
+/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must
+share a common GP, and the target address is adjusted for
+STO_ALPHA_STD_GPLOAD.  */
+  BFD_RELOC_ALPHA_BRSGP,
+
+/* Alpha thread-local storage relocations.  */
+  BFD_RELOC_ALPHA_TLSGD,
+  BFD_RELOC_ALPHA_TLSLDM,
+  BFD_RELOC_ALPHA_DTPMOD64,
+  BFD_RELOC_ALPHA_GOTDTPREL16,
+  BFD_RELOC_ALPHA_DTPREL64,
+  BFD_RELOC_ALPHA_DTPREL_HI16,
+  BFD_RELOC_ALPHA_DTPREL_LO16,
+  BFD_RELOC_ALPHA_DTPREL16,
+  BFD_RELOC_ALPHA_GOTTPREL16,
+  BFD_RELOC_ALPHA_TPREL64,
+  BFD_RELOC_ALPHA_TPREL_HI16,
+  BFD_RELOC_ALPHA_TPREL_LO16,
+  BFD_RELOC_ALPHA_TPREL16,
+
+/* 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,
+
+/* High 16 bits of 32-bit pc-relative value  */
+  BFD_RELOC_HI16_PCREL,
+
+/* High 16 bits of 32-bit pc-relative value, adjusted  */
+  BFD_RELOC_HI16_S_PCREL,
+
+/* Low 16 bits of pc-relative value  */
+  BFD_RELOC_LO16_PCREL,
+
+/* MIPS16 high 16 bits of 32-bit value.  */
+  BFD_RELOC_MIPS16_HI16,
+
+/* MIPS16 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_MIPS16_HI16_S,
+
+/* MIPS16 low 16 bits.  */
+  BFD_RELOC_MIPS16_LO16,
+
+/* Relocation against a MIPS literal section.  */
+  BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations.  */
+  BFD_RELOC_MIPS_GOT16,
+  BFD_RELOC_MIPS_CALL16,
+  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,
+  BFD_RELOC_MIPS_SHIFT5,
+  BFD_RELOC_MIPS_SHIFT6,
+  BFD_RELOC_MIPS_INSERT_A,
+  BFD_RELOC_MIPS_INSERT_B,
+  BFD_RELOC_MIPS_DELETE,
+  BFD_RELOC_MIPS_HIGHEST,
+  BFD_RELOC_MIPS_HIGHER,
+  BFD_RELOC_MIPS_SCN_DISP,
+  BFD_RELOC_MIPS_REL16,
+  BFD_RELOC_MIPS_RELGOT,
+  BFD_RELOC_MIPS_JALR,
+  BFD_RELOC_MIPS_TLS_DTPMOD32,
+  BFD_RELOC_MIPS_TLS_DTPREL32,
+  BFD_RELOC_MIPS_TLS_DTPMOD64,
+  BFD_RELOC_MIPS_TLS_DTPREL64,
+  BFD_RELOC_MIPS_TLS_GD,
+  BFD_RELOC_MIPS_TLS_LDM,
+  BFD_RELOC_MIPS_TLS_DTPREL_HI16,
+  BFD_RELOC_MIPS_TLS_DTPREL_LO16,
+  BFD_RELOC_MIPS_TLS_GOTTPREL,
+  BFD_RELOC_MIPS_TLS_TPREL32,
+  BFD_RELOC_MIPS_TLS_TPREL64,
+  BFD_RELOC_MIPS_TLS_TPREL_HI16,
+  BFD_RELOC_MIPS_TLS_TPREL_LO16,
+
+
+/* Fujitsu Frv Relocations.  */
+  BFD_RELOC_FRV_LABEL16,
+  BFD_RELOC_FRV_LABEL24,
+  BFD_RELOC_FRV_LO16,
+  BFD_RELOC_FRV_HI16,
+  BFD_RELOC_FRV_GPREL12,
+  BFD_RELOC_FRV_GPRELU12,
+  BFD_RELOC_FRV_GPREL32,
+  BFD_RELOC_FRV_GPRELHI,
+  BFD_RELOC_FRV_GPRELLO,
+  BFD_RELOC_FRV_GOT12,
+  BFD_RELOC_FRV_GOTHI,
+  BFD_RELOC_FRV_GOTLO,
+  BFD_RELOC_FRV_FUNCDESC,
+  BFD_RELOC_FRV_FUNCDESC_GOT12,
+  BFD_RELOC_FRV_FUNCDESC_GOTHI,
+  BFD_RELOC_FRV_FUNCDESC_GOTLO,
+  BFD_RELOC_FRV_FUNCDESC_VALUE,
+  BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
+  BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
+  BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+  BFD_RELOC_FRV_GOTOFF12,
+  BFD_RELOC_FRV_GOTOFFHI,
+  BFD_RELOC_FRV_GOTOFFLO,
+  BFD_RELOC_FRV_GETTLSOFF,
+  BFD_RELOC_FRV_TLSDESC_VALUE,
+  BFD_RELOC_FRV_GOTTLSDESC12,
+  BFD_RELOC_FRV_GOTTLSDESCHI,
+  BFD_RELOC_FRV_GOTTLSDESCLO,
+  BFD_RELOC_FRV_TLSMOFF12,
+  BFD_RELOC_FRV_TLSMOFFHI,
+  BFD_RELOC_FRV_TLSMOFFLO,
+  BFD_RELOC_FRV_GOTTLSOFF12,
+  BFD_RELOC_FRV_GOTTLSOFFHI,
+  BFD_RELOC_FRV_GOTTLSOFFLO,
+  BFD_RELOC_FRV_TLSOFF,
+  BFD_RELOC_FRV_TLSDESC_RELAX,
+  BFD_RELOC_FRV_GETTLSOFF_RELAX,
+  BFD_RELOC_FRV_TLSOFF_RELAX,
+  BFD_RELOC_FRV_TLSMOFF,
+
+
+/* This is a 24bit GOT-relative reloc for the mn10300.  */
+  BFD_RELOC_MN10300_GOTOFF24,
+
+/* This is a 32bit GOT-relative reloc for the mn10300, offset by two bytes
+in the instruction.  */
+  BFD_RELOC_MN10300_GOT32,
+
+/* This is a 24bit GOT-relative reloc for the mn10300, offset by two bytes
+in the instruction.  */
+  BFD_RELOC_MN10300_GOT24,
+
+/* This is a 16bit GOT-relative reloc for the mn10300, offset by two bytes
+in the instruction.  */
+  BFD_RELOC_MN10300_GOT16,
+
+/* Copy symbol at runtime.  */
+  BFD_RELOC_MN10300_COPY,
+
+/* Create GOT entry.  */
+  BFD_RELOC_MN10300_GLOB_DAT,
+
+/* Create PLT entry.  */
+  BFD_RELOC_MN10300_JMP_SLOT,
+
+/* Adjust by program base.  */
+  BFD_RELOC_MN10300_RELATIVE,
+
+
+/* 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,
+  BFD_RELOC_386_TLS_TPOFF,
+  BFD_RELOC_386_TLS_IE,
+  BFD_RELOC_386_TLS_GOTIE,
+  BFD_RELOC_386_TLS_LE,
+  BFD_RELOC_386_TLS_GD,
+  BFD_RELOC_386_TLS_LDM,
+  BFD_RELOC_386_TLS_LDO_32,
+  BFD_RELOC_386_TLS_IE_32,
+  BFD_RELOC_386_TLS_LE_32,
+  BFD_RELOC_386_TLS_DTPMOD32,
+  BFD_RELOC_386_TLS_DTPOFF32,
+  BFD_RELOC_386_TLS_TPOFF32,
+
+/* x86-64/elf relocations  */
+  BFD_RELOC_X86_64_GOT32,
+  BFD_RELOC_X86_64_PLT32,
+  BFD_RELOC_X86_64_COPY,
+  BFD_RELOC_X86_64_GLOB_DAT,
+  BFD_RELOC_X86_64_JUMP_SLOT,
+  BFD_RELOC_X86_64_RELATIVE,
+  BFD_RELOC_X86_64_GOTPCREL,
+  BFD_RELOC_X86_64_32S,
+  BFD_RELOC_X86_64_DTPMOD64,
+  BFD_RELOC_X86_64_DTPOFF64,
+  BFD_RELOC_X86_64_TPOFF64,
+  BFD_RELOC_X86_64_TLSGD,
+  BFD_RELOC_X86_64_TLSLD,
+  BFD_RELOC_X86_64_DTPOFF32,
+  BFD_RELOC_X86_64_GOTTPOFF,
+  BFD_RELOC_X86_64_TPOFF32,
+  BFD_RELOC_X86_64_GOTOFF64,
+  BFD_RELOC_X86_64_GOTPC32,
+  BFD_RELOC_X86_64_GOT64,
+  BFD_RELOC_X86_64_GOTPCREL64,
+  BFD_RELOC_X86_64_GOTPC64,
+  BFD_RELOC_X86_64_GOTPLT64,
+  BFD_RELOC_X86_64_PLTOFF64,
+
+/* 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,
+
+/* PDP11 relocations  */
+  BFD_RELOC_PDP11_DISP_8_PCREL,
+  BFD_RELOC_PDP11_DISP_6_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,
+  BFD_RELOC_PPC64_HIGHER,
+  BFD_RELOC_PPC64_HIGHER_S,
+  BFD_RELOC_PPC64_HIGHEST,
+  BFD_RELOC_PPC64_HIGHEST_S,
+  BFD_RELOC_PPC64_TOC16_LO,
+  BFD_RELOC_PPC64_TOC16_HI,
+  BFD_RELOC_PPC64_TOC16_HA,
+  BFD_RELOC_PPC64_TOC,
+  BFD_RELOC_PPC64_PLTGOT16,
+  BFD_RELOC_PPC64_PLTGOT16_LO,
+  BFD_RELOC_PPC64_PLTGOT16_HI,
+  BFD_RELOC_PPC64_PLTGOT16_HA,
+  BFD_RELOC_PPC64_ADDR16_DS,
+  BFD_RELOC_PPC64_ADDR16_LO_DS,
+  BFD_RELOC_PPC64_GOT16_DS,
+  BFD_RELOC_PPC64_GOT16_LO_DS,
+  BFD_RELOC_PPC64_PLT16_LO_DS,
+  BFD_RELOC_PPC64_SECTOFF_DS,
+  BFD_RELOC_PPC64_SECTOFF_LO_DS,
+  BFD_RELOC_PPC64_TOC16_DS,
+  BFD_RELOC_PPC64_TOC16_LO_DS,
+  BFD_RELOC_PPC64_PLTGOT16_DS,
+  BFD_RELOC_PPC64_PLTGOT16_LO_DS,
+
+/* PowerPC and PowerPC64 thread-local storage relocations.  */
+  BFD_RELOC_PPC_TLS,
+  BFD_RELOC_PPC_DTPMOD,
+  BFD_RELOC_PPC_TPREL16,
+  BFD_RELOC_PPC_TPREL16_LO,
+  BFD_RELOC_PPC_TPREL16_HI,
+  BFD_RELOC_PPC_TPREL16_HA,
+  BFD_RELOC_PPC_TPREL,
+  BFD_RELOC_PPC_DTPREL16,
+  BFD_RELOC_PPC_DTPREL16_LO,
+  BFD_RELOC_PPC_DTPREL16_HI,
+  BFD_RELOC_PPC_DTPREL16_HA,
+  BFD_RELOC_PPC_DTPREL,
+  BFD_RELOC_PPC_GOT_TLSGD16,
+  BFD_RELOC_PPC_GOT_TLSGD16_LO,
+  BFD_RELOC_PPC_GOT_TLSGD16_HI,
+  BFD_RELOC_PPC_GOT_TLSGD16_HA,
+  BFD_RELOC_PPC_GOT_TLSLD16,
+  BFD_RELOC_PPC_GOT_TLSLD16_LO,
+  BFD_RELOC_PPC_GOT_TLSLD16_HI,
+  BFD_RELOC_PPC_GOT_TLSLD16_HA,
+  BFD_RELOC_PPC_GOT_TPREL16,
+  BFD_RELOC_PPC_GOT_TPREL16_LO,
+  BFD_RELOC_PPC_GOT_TPREL16_HI,
+  BFD_RELOC_PPC_GOT_TPREL16_HA,
+  BFD_RELOC_PPC_GOT_DTPREL16,
+  BFD_RELOC_PPC_GOT_DTPREL16_LO,
+  BFD_RELOC_PPC_GOT_DTPREL16_HI,
+  BFD_RELOC_PPC_GOT_DTPREL16_HA,
+  BFD_RELOC_PPC64_TPREL16_DS,
+  BFD_RELOC_PPC64_TPREL16_LO_DS,
+  BFD_RELOC_PPC64_TPREL16_HIGHER,
+  BFD_RELOC_PPC64_TPREL16_HIGHERA,
+  BFD_RELOC_PPC64_TPREL16_HIGHEST,
+  BFD_RELOC_PPC64_TPREL16_HIGHESTA,
+  BFD_RELOC_PPC64_DTPREL16_DS,
+  BFD_RELOC_PPC64_DTPREL16_LO_DS,
+  BFD_RELOC_PPC64_DTPREL16_HIGHER,
+  BFD_RELOC_PPC64_DTPREL16_HIGHERA,
+  BFD_RELOC_PPC64_DTPREL16_HIGHEST,
+  BFD_RELOC_PPC64_DTPREL16_HIGHESTA,
+
+/* IBM 370/390 relocations  */
+  BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a constructor 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,
+
+/* ARM 26 bit pc-relative branch.  The lowest bit must be zero and is
+not stored in the instruction.  The 2nd lowest bit comes from a 1 bit
+field in the instruction.  */
+  BFD_RELOC_ARM_PCREL_BLX,
+
+/* Thumb 22 bit pc-relative branch.  The lowest bit must be zero and is
+not stored in the instruction.  The 2nd lowest bit comes from a 1 bit
+field in the instruction.  */
+  BFD_RELOC_THUMB_PCREL_BLX,
+
+/* ARM 26-bit pc-relative branch for an unconditional BL or BLX instruction.  */
+  BFD_RELOC_ARM_PCREL_CALL,
+
+/* ARM 26-bit pc-relative branch for B or conditional BL instruction.  */
+  BFD_RELOC_ARM_PCREL_JUMP,
+
+/* Thumb 7-, 9-, 12-, 20-, 23-, and 25-bit pc-relative branches.
+The lowest bit must be zero and is not stored in the instruction.
+Note that the corresponding ELF R_ARM_THM_JUMPnn constant has an
+"nn" one smaller in all cases.  Note further that BRANCH23
+corresponds to R_ARM_THM_CALL.  */
+  BFD_RELOC_THUMB_PCREL_BRANCH7,
+  BFD_RELOC_THUMB_PCREL_BRANCH9,
+  BFD_RELOC_THUMB_PCREL_BRANCH12,
+  BFD_RELOC_THUMB_PCREL_BRANCH20,
+  BFD_RELOC_THUMB_PCREL_BRANCH23,
+  BFD_RELOC_THUMB_PCREL_BRANCH25,
+
+/* 12-bit immediate offset, used in ARM-format ldr and str instructions.  */
+  BFD_RELOC_ARM_OFFSET_IMM,
+
+/* 5-bit immediate offset, used in Thumb-format ldr and str instructions.  */
+  BFD_RELOC_ARM_THUMB_OFFSET,
+
+/* Pc-relative or absolute relocation depending on target.  Used for
+entries in .init_array sections.  */
+  BFD_RELOC_ARM_TARGET1,
+
+/* Read-only segment base relative address.  */
+  BFD_RELOC_ARM_ROSEGREL32,
+
+/* Data segment base relative address.  */
+  BFD_RELOC_ARM_SBREL32,
+
+/* This reloc is used for references to RTTI data from exception handling
+tables.  The actual definition depends on the target.  It may be a
+pc-relative or some form of GOT-indirect relocation.  */
+  BFD_RELOC_ARM_TARGET2,
+
+/* 31-bit PC relative address.  */
+  BFD_RELOC_ARM_PREL31,
+
+/* Relocations for setting up GOTs and PLTs for shared libraries.  */
+  BFD_RELOC_ARM_JUMP_SLOT,
+  BFD_RELOC_ARM_GLOB_DAT,
+  BFD_RELOC_ARM_GOT32,
+  BFD_RELOC_ARM_PLT32,
+  BFD_RELOC_ARM_RELATIVE,
+  BFD_RELOC_ARM_GOTOFF,
+  BFD_RELOC_ARM_GOTPC,
+
+/* ARM thread-local storage relocations.  */
+  BFD_RELOC_ARM_TLS_GD32,
+  BFD_RELOC_ARM_TLS_LDO32,
+  BFD_RELOC_ARM_TLS_LDM32,
+  BFD_RELOC_ARM_TLS_DTPOFF32,
+  BFD_RELOC_ARM_TLS_DTPMOD32,
+  BFD_RELOC_ARM_TLS_TPOFF32,
+  BFD_RELOC_ARM_TLS_IE32,
+  BFD_RELOC_ARM_TLS_LE32,
+
+/* 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_T32_IMMEDIATE,
+  BFD_RELOC_ARM_T32_IMM12,
+  BFD_RELOC_ARM_T32_ADD_PC12,
+  BFD_RELOC_ARM_SHIFT_IMM,
+  BFD_RELOC_ARM_SMC,
+  BFD_RELOC_ARM_SWI,
+  BFD_RELOC_ARM_MULTI,
+  BFD_RELOC_ARM_CP_OFF_IMM,
+  BFD_RELOC_ARM_CP_OFF_IMM_S2,
+  BFD_RELOC_ARM_T32_CP_OFF_IMM,
+  BFD_RELOC_ARM_T32_CP_OFF_IMM_S2,
+  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_T32_OFFSET_U8,
+  BFD_RELOC_ARM_T32_OFFSET_IMM,
+  BFD_RELOC_ARM_HWLITERAL,
+  BFD_RELOC_ARM_THUMB_ADD,
+  BFD_RELOC_ARM_THUMB_IMM,
+  BFD_RELOC_ARM_THUMB_SHIFT,
+
+/* Renesas / SuperH SH relocs.  Not all of these appear in object files.  */
+  BFD_RELOC_SH_PCDISP8BY2,
+  BFD_RELOC_SH_PCDISP12BY2,
+  BFD_RELOC_SH_IMM3,
+  BFD_RELOC_SH_IMM3U,
+  BFD_RELOC_SH_DISP12,
+  BFD_RELOC_SH_DISP12BY2,
+  BFD_RELOC_SH_DISP12BY4,
+  BFD_RELOC_SH_DISP12BY8,
+  BFD_RELOC_SH_DISP20,
+  BFD_RELOC_SH_DISP20BY8,
+  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,
+  BFD_RELOC_SH_LOOP_START,
+  BFD_RELOC_SH_LOOP_END,
+  BFD_RELOC_SH_COPY,
+  BFD_RELOC_SH_GLOB_DAT,
+  BFD_RELOC_SH_JMP_SLOT,
+  BFD_RELOC_SH_RELATIVE,
+  BFD_RELOC_SH_GOTPC,
+  BFD_RELOC_SH_GOT_LOW16,
+  BFD_RELOC_SH_GOT_MEDLOW16,
+  BFD_RELOC_SH_GOT_MEDHI16,
+  BFD_RELOC_SH_GOT_HI16,
+  BFD_RELOC_SH_GOTPLT_LOW16,
+  BFD_RELOC_SH_GOTPLT_MEDLOW16,
+  BFD_RELOC_SH_GOTPLT_MEDHI16,
+  BFD_RELOC_SH_GOTPLT_HI16,
+  BFD_RELOC_SH_PLT_LOW16,
+  BFD_RELOC_SH_PLT_MEDLOW16,
+  BFD_RELOC_SH_PLT_MEDHI16,
+  BFD_RELOC_SH_PLT_HI16,
+  BFD_RELOC_SH_GOTOFF_LOW16,
+  BFD_RELOC_SH_GOTOFF_MEDLOW16,
+  BFD_RELOC_SH_GOTOFF_MEDHI16,
+  BFD_RELOC_SH_GOTOFF_HI16,
+  BFD_RELOC_SH_GOTPC_LOW16,
+  BFD_RELOC_SH_GOTPC_MEDLOW16,
+  BFD_RELOC_SH_GOTPC_MEDHI16,
+  BFD_RELOC_SH_GOTPC_HI16,
+  BFD_RELOC_SH_COPY64,
+  BFD_RELOC_SH_GLOB_DAT64,
+  BFD_RELOC_SH_JMP_SLOT64,
+  BFD_RELOC_SH_RELATIVE64,
+  BFD_RELOC_SH_GOT10BY4,
+  BFD_RELOC_SH_GOT10BY8,
+  BFD_RELOC_SH_GOTPLT10BY4,
+  BFD_RELOC_SH_GOTPLT10BY8,
+  BFD_RELOC_SH_GOTPLT32,
+  BFD_RELOC_SH_SHMEDIA_CODE,
+  BFD_RELOC_SH_IMMU5,
+  BFD_RELOC_SH_IMMS6,
+  BFD_RELOC_SH_IMMS6BY32,
+  BFD_RELOC_SH_IMMU6,
+  BFD_RELOC_SH_IMMS10,
+  BFD_RELOC_SH_IMMS10BY2,
+  BFD_RELOC_SH_IMMS10BY4,
+  BFD_RELOC_SH_IMMS10BY8,
+  BFD_RELOC_SH_IMMS16,
+  BFD_RELOC_SH_IMMU16,
+  BFD_RELOC_SH_IMM_LOW16,
+  BFD_RELOC_SH_IMM_LOW16_PCREL,
+  BFD_RELOC_SH_IMM_MEDLOW16,
+  BFD_RELOC_SH_IMM_MEDLOW16_PCREL,
+  BFD_RELOC_SH_IMM_MEDHI16,
+  BFD_RELOC_SH_IMM_MEDHI16_PCREL,
+  BFD_RELOC_SH_IMM_HI16,
+  BFD_RELOC_SH_IMM_HI16_PCREL,
+  BFD_RELOC_SH_PT_16,
+  BFD_RELOC_SH_TLS_GD_32,
+  BFD_RELOC_SH_TLS_LD_32,
+  BFD_RELOC_SH_TLS_LDO_32,
+  BFD_RELOC_SH_TLS_IE_32,
+  BFD_RELOC_SH_TLS_LE_32,
+  BFD_RELOC_SH_TLS_DTPMOD32,
+  BFD_RELOC_SH_TLS_DTPOFF32,
+  BFD_RELOC_SH_TLS_TPOFF32,
+
+/* ARC Cores 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,
+
+/* ADI Blackfin 16 bit immediate absolute reloc.  */
+  BFD_RELOC_BFIN_16_IMM,
+
+/* ADI Blackfin 16 bit immediate absolute reloc higher 16 bits.  */
+  BFD_RELOC_BFIN_16_HIGH,
+
+/* ADI Blackfin 'a' part of LSETUP.  */
+  BFD_RELOC_BFIN_4_PCREL,
+
+/* ADI Blackfin.  */
+  BFD_RELOC_BFIN_5_PCREL,
+
+/* ADI Blackfin 16 bit immediate absolute reloc lower 16 bits.  */
+  BFD_RELOC_BFIN_16_LOW,
+
+/* ADI Blackfin.  */
+  BFD_RELOC_BFIN_10_PCREL,
+
+/* ADI Blackfin 'b' part of LSETUP.  */
+  BFD_RELOC_BFIN_11_PCREL,
+
+/* ADI Blackfin.  */
+  BFD_RELOC_BFIN_12_PCREL_JUMP,
+
+/* ADI Blackfin Short jump, pcrel.  */
+  BFD_RELOC_BFIN_12_PCREL_JUMP_S,
+
+/* ADI Blackfin Call.x not implemented.  */
+  BFD_RELOC_BFIN_24_PCREL_CALL_X,
+
+/* ADI Blackfin Long Jump pcrel.  */
+  BFD_RELOC_BFIN_24_PCREL_JUMP_L,
+
+/* ADI Blackfin GOT relocation.  */
+  BFD_RELOC_BFIN_GOT,
+
+/* ADI Blackfin PLTPC relocation.  */
+  BFD_RELOC_BFIN_PLTPC,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_PUSH,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_CONST,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_ADD,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_SUB,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_MULT,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_DIV,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_MOD,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_LSHIFT,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_RSHIFT,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_AND,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_OR,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_XOR,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_LAND,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_LOR,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_LEN,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_NEG,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_COMP,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_PAGE,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_HWPAGE,
+
+/* ADI Blackfin arithmetic relocation.  */
+  BFD_ARELOC_BFIN_ADDR,
+
+/* 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,
+
+/* DLX relocs  */
+  BFD_RELOC_DLX_HI16_S,
+
+/* DLX relocs  */
+  BFD_RELOC_DLX_LO16,
+
+/* DLX relocs  */
+  BFD_RELOC_DLX_JMP26,
+
+/* Renesas M16C/M32C Relocations.  */
+  BFD_RELOC_M32C_HI8,
+
+/* Renesas M32R (formerly 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,
+
+/* For PIC.  */
+  BFD_RELOC_M32R_GOT24,
+  BFD_RELOC_M32R_26_PLTREL,
+  BFD_RELOC_M32R_COPY,
+  BFD_RELOC_M32R_GLOB_DAT,
+  BFD_RELOC_M32R_JMP_SLOT,
+  BFD_RELOC_M32R_RELATIVE,
+  BFD_RELOC_M32R_GOTOFF,
+  BFD_RELOC_M32R_GOTOFF_HI_ULO,
+  BFD_RELOC_M32R_GOTOFF_HI_SLO,
+  BFD_RELOC_M32R_GOTOFF_LO,
+  BFD_RELOC_M32R_GOTPC24,
+  BFD_RELOC_M32R_GOT16_HI_ULO,
+  BFD_RELOC_M32R_GOT16_HI_SLO,
+  BFD_RELOC_M32R_GOT16_LO,
+  BFD_RELOC_M32R_GOTPC_HI_ULO,
+  BFD_RELOC_M32R_GOTPC_HI_SLO,
+  BFD_RELOC_M32R_GOTPC_LO,
+
+/* 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-contiguously 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-contiguously 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,
+
+/* Used for relaxing indirect function calls.  */
+  BFD_RELOC_V850_LONGCALL,
+
+/* Used for relaxing indirect jumps.  */
+  BFD_RELOC_V850_LONGJUMP,
+
+/* Used to maintain alignment whilst relaxing.  */
+  BFD_RELOC_V850_ALIGN,
+
+/* This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu
+instructions.  */
+  BFD_RELOC_V850_LO16_SPLIT_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 7bit reloc for the tms320c54x, where the least
+significant 7 bits of a 16 bit word are placed into the least
+significant 7 bits of the opcode.  */
+  BFD_RELOC_TIC54X_PARTLS7,
+
+/* This is a 9bit DP reloc for the tms320c54x, where the most
+significant 9 bits of a 16 bit word are placed into the least
+significant 9 bits of the opcode.  */
+  BFD_RELOC_TIC54X_PARTMS9,
+
+/* This is an extended address 23-bit reloc for the tms320c54x.  */
+  BFD_RELOC_TIC54X_23,
+
+/* This is a 16-bit reloc for the tms320c54x, where the least
+significant 16 bits of a 23-bit extended address are placed into
+the opcode.  */
+  BFD_RELOC_TIC54X_16_OF_23,
+
+/* This is a reloc for the tms320c54x, where the most
+significant 7 bits of a 23-bit extended address are placed into
+the opcode.  */
+  BFD_RELOC_TIC54X_MS7_OF_23,
+
+/* 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 are relocations for the GETA instruction.  */
+  BFD_RELOC_MMIX_GETA,
+  BFD_RELOC_MMIX_GETA_1,
+  BFD_RELOC_MMIX_GETA_2,
+  BFD_RELOC_MMIX_GETA_3,
+
+/* These are relocations for a conditional branch instruction.  */
+  BFD_RELOC_MMIX_CBRANCH,
+  BFD_RELOC_MMIX_CBRANCH_J,
+  BFD_RELOC_MMIX_CBRANCH_1,
+  BFD_RELOC_MMIX_CBRANCH_2,
+  BFD_RELOC_MMIX_CBRANCH_3,
+
+/* These are relocations for the PUSHJ instruction.  */
+  BFD_RELOC_MMIX_PUSHJ,
+  BFD_RELOC_MMIX_PUSHJ_1,
+  BFD_RELOC_MMIX_PUSHJ_2,
+  BFD_RELOC_MMIX_PUSHJ_3,
+  BFD_RELOC_MMIX_PUSHJ_STUBBABLE,
+
+/* These are relocations for the JMP instruction.  */
+  BFD_RELOC_MMIX_JMP,
+  BFD_RELOC_MMIX_JMP_1,
+  BFD_RELOC_MMIX_JMP_2,
+  BFD_RELOC_MMIX_JMP_3,
+
+/* This is a relocation for a relative address as in a GETA instruction or
+a branch.  */
+  BFD_RELOC_MMIX_ADDR19,
+
+/* This is a relocation for a relative address as in a JMP instruction.  */
+  BFD_RELOC_MMIX_ADDR27,
+
+/* This is a relocation for an instruction field that may be a general
+register or a value 0..255.  */
+  BFD_RELOC_MMIX_REG_OR_BYTE,
+
+/* This is a relocation for an instruction field that may be a general
+register.  */
+  BFD_RELOC_MMIX_REG,
+
+/* This is a relocation for two instruction fields holding a register and
+an offset, the equivalent of the relocation.  */
+  BFD_RELOC_MMIX_BASE_PLUS_OFFSET,
+
+/* This relocation is an assertion that the expression is not allocated as
+a global register.  It does not modify contents.  */
+  BFD_RELOC_MMIX_LOCAL,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative
+short offset into 7 bits.  */
+  BFD_RELOC_AVR_7_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative
+short offset into 12 bits.  */
+  BFD_RELOC_AVR_13_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually
+program memory address) into 16 bits.  */
+  BFD_RELOC_AVR_16_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+data memory address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_LO8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of data memory address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HI8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of program memory address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HH8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually data memory address) into 8 bit immediate value of SUBI insn.  */
+  BFD_RELOC_AVR_LO8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of data memory address) into 8 bit immediate value of
+SUBI insn.  */
+  BFD_RELOC_AVR_HI8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(most high 8 bit of program memory address) into 8 bit immediate value
+of LDI or SUBI insn.  */
+  BFD_RELOC_AVR_HH8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+command address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_LO8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of command address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HI8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of command address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HH8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually command address) into 8 bit immediate value of SUBI insn.  */
+  BFD_RELOC_AVR_LO8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of 16 bit command address) into 8 bit immediate value
+of SUBI insn.  */
+  BFD_RELOC_AVR_HI8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 6 bit of 22 bit command address) into 8 bit immediate
+value of SUBI insn.  */
+  BFD_RELOC_AVR_HH8_LDI_PM_NEG,
+
+/* This is a 32 bit reloc for the AVR that stores 23 bit value
+into 22 bits.  */
+  BFD_RELOC_AVR_CALL,
+
+/* This is a 16 bit reloc for the AVR that stores all needed bits
+for absolute addressing with ldi with overflow check to linktime  */
+  BFD_RELOC_AVR_LDI,
+
+/* This is a 6 bit reloc for the AVR that stores offset for ldd/std
+instructions  */
+  BFD_RELOC_AVR_6,
+
+/* This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw
+instructions  */
+  BFD_RELOC_AVR_6_ADIW,
+
+/* Direct 12 bit.  */
+  BFD_RELOC_390_12,
+
+/* 12 bit GOT offset.  */
+  BFD_RELOC_390_GOT12,
+
+/* 32 bit PC relative PLT address.  */
+  BFD_RELOC_390_PLT32,
+
+/* Copy symbol at runtime.  */
+  BFD_RELOC_390_COPY,
+
+/* Create GOT entry.  */
+  BFD_RELOC_390_GLOB_DAT,
+
+/* Create PLT entry.  */
+  BFD_RELOC_390_JMP_SLOT,
+
+/* Adjust by program base.  */
+  BFD_RELOC_390_RELATIVE,
+
+/* 32 bit PC relative offset to GOT.  */
+  BFD_RELOC_390_GOTPC,
+
+/* 16 bit GOT offset.  */
+  BFD_RELOC_390_GOT16,
+
+/* PC relative 16 bit shifted by 1.  */
+  BFD_RELOC_390_PC16DBL,
+
+/* 16 bit PC rel. PLT shifted by 1.  */
+  BFD_RELOC_390_PLT16DBL,
+
+/* PC relative 32 bit shifted by 1.  */
+  BFD_RELOC_390_PC32DBL,
+
+/* 32 bit PC rel. PLT shifted by 1.  */
+  BFD_RELOC_390_PLT32DBL,
+
+/* 32 bit PC rel. GOT shifted by 1.  */
+  BFD_RELOC_390_GOTPCDBL,
+
+/* 64 bit GOT offset.  */
+  BFD_RELOC_390_GOT64,
+
+/* 64 bit PC relative PLT address.  */
+  BFD_RELOC_390_PLT64,
+
+/* 32 bit rel. offset to GOT entry.  */
+  BFD_RELOC_390_GOTENT,
+
+/* 64 bit offset to GOT.  */
+  BFD_RELOC_390_GOTOFF64,
+
+/* 12-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT12,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT16,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT32,
+
+/* 64-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT64,
+
+/* 32-bit rel. offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLTENT,
+
+/* 16-bit rel. offset from the GOT to a PLT entry.  */
+  BFD_RELOC_390_PLTOFF16,
+
+/* 32-bit rel. offset from the GOT to a PLT entry.  */
+  BFD_RELOC_390_PLTOFF32,
+
+/* 64-bit rel. offset from the GOT to a PLT entry.  */
+  BFD_RELOC_390_PLTOFF64,
+
+/* s390 tls relocations.  */
+  BFD_RELOC_390_TLS_LOAD,
+  BFD_RELOC_390_TLS_GDCALL,
+  BFD_RELOC_390_TLS_LDCALL,
+  BFD_RELOC_390_TLS_GD32,
+  BFD_RELOC_390_TLS_GD64,
+  BFD_RELOC_390_TLS_GOTIE12,
+  BFD_RELOC_390_TLS_GOTIE32,
+  BFD_RELOC_390_TLS_GOTIE64,
+  BFD_RELOC_390_TLS_LDM32,
+  BFD_RELOC_390_TLS_LDM64,
+  BFD_RELOC_390_TLS_IE32,
+  BFD_RELOC_390_TLS_IE64,
+  BFD_RELOC_390_TLS_IEENT,
+  BFD_RELOC_390_TLS_LE32,
+  BFD_RELOC_390_TLS_LE64,
+  BFD_RELOC_390_TLS_LDO32,
+  BFD_RELOC_390_TLS_LDO64,
+  BFD_RELOC_390_TLS_DTPMOD,
+  BFD_RELOC_390_TLS_DTPOFF,
+  BFD_RELOC_390_TLS_TPOFF,
+
+/* Long displacement extension.  */
+  BFD_RELOC_390_20,
+  BFD_RELOC_390_GOT20,
+  BFD_RELOC_390_GOTPLT20,
+  BFD_RELOC_390_TLS_GOTIE20,
+
+/* Scenix IP2K - 9-bit register number / data address  */
+  BFD_RELOC_IP2K_FR9,
+
+/* Scenix IP2K - 4-bit register/data bank number  */
+  BFD_RELOC_IP2K_BANK,
+
+/* Scenix IP2K - low 13 bits of instruction word address  */
+  BFD_RELOC_IP2K_ADDR16CJP,
+
+/* Scenix IP2K - high 3 bits of instruction word address  */
+  BFD_RELOC_IP2K_PAGE3,
+
+/* Scenix IP2K - ext/low/high 8 bits of data address  */
+  BFD_RELOC_IP2K_LO8DATA,
+  BFD_RELOC_IP2K_HI8DATA,
+  BFD_RELOC_IP2K_EX8DATA,
+
+/* Scenix IP2K - low/high 8 bits of instruction word address  */
+  BFD_RELOC_IP2K_LO8INSN,
+  BFD_RELOC_IP2K_HI8INSN,
+
+/* Scenix IP2K - even/odd PC modifier to modify snb pcl.0  */
+  BFD_RELOC_IP2K_PC_SKIP,
+
+/* Scenix IP2K - 16 bit word address in text section.  */
+  BFD_RELOC_IP2K_TEXT,
+
+/* Scenix IP2K - 7-bit sp or dp offset  */
+  BFD_RELOC_IP2K_FR_OFFSET,
+
+/* Scenix VPE4K coprocessor - data/insn-space addressing  */
+  BFD_RELOC_VPE4KMATH_DATA,
+  BFD_RELOC_VPE4KMATH_INSN,
+
+/* 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 inheritance 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,
+
+/* Intel IA64 Relocations.  */
+  BFD_RELOC_IA64_IMM14,
+  BFD_RELOC_IA64_IMM22,
+  BFD_RELOC_IA64_IMM64,
+  BFD_RELOC_IA64_DIR32MSB,
+  BFD_RELOC_IA64_DIR32LSB,
+  BFD_RELOC_IA64_DIR64MSB,
+  BFD_RELOC_IA64_DIR64LSB,
+  BFD_RELOC_IA64_GPREL22,
+  BFD_RELOC_IA64_GPREL64I,
+  BFD_RELOC_IA64_GPREL32MSB,
+  BFD_RELOC_IA64_GPREL32LSB,
+  BFD_RELOC_IA64_GPREL64MSB,
+  BFD_RELOC_IA64_GPREL64LSB,
+  BFD_RELOC_IA64_LTOFF22,
+  BFD_RELOC_IA64_LTOFF64I,
+  BFD_RELOC_IA64_PLTOFF22,
+  BFD_RELOC_IA64_PLTOFF64I,
+  BFD_RELOC_IA64_PLTOFF64MSB,
+  BFD_RELOC_IA64_PLTOFF64LSB,
+  BFD_RELOC_IA64_FPTR64I,
+  BFD_RELOC_IA64_FPTR32MSB,
+  BFD_RELOC_IA64_FPTR32LSB,
+  BFD_RELOC_IA64_FPTR64MSB,
+  BFD_RELOC_IA64_FPTR64LSB,
+  BFD_RELOC_IA64_PCREL21B,
+  BFD_RELOC_IA64_PCREL21BI,
+  BFD_RELOC_IA64_PCREL21M,
+  BFD_RELOC_IA64_PCREL21F,
+  BFD_RELOC_IA64_PCREL22,
+  BFD_RELOC_IA64_PCREL60B,
+  BFD_RELOC_IA64_PCREL64I,
+  BFD_RELOC_IA64_PCREL32MSB,
+  BFD_RELOC_IA64_PCREL32LSB,
+  BFD_RELOC_IA64_PCREL64MSB,
+  BFD_RELOC_IA64_PCREL64LSB,
+  BFD_RELOC_IA64_LTOFF_FPTR22,
+  BFD_RELOC_IA64_LTOFF_FPTR64I,
+  BFD_RELOC_IA64_LTOFF_FPTR32MSB,
+  BFD_RELOC_IA64_LTOFF_FPTR32LSB,
+  BFD_RELOC_IA64_LTOFF_FPTR64MSB,
+  BFD_RELOC_IA64_LTOFF_FPTR64LSB,
+  BFD_RELOC_IA64_SEGREL32MSB,
+  BFD_RELOC_IA64_SEGREL32LSB,
+  BFD_RELOC_IA64_SEGREL64MSB,
+  BFD_RELOC_IA64_SEGREL64LSB,
+  BFD_RELOC_IA64_SECREL32MSB,
+  BFD_RELOC_IA64_SECREL32LSB,
+  BFD_RELOC_IA64_SECREL64MSB,
+  BFD_RELOC_IA64_SECREL64LSB,
+  BFD_RELOC_IA64_REL32MSB,
+  BFD_RELOC_IA64_REL32LSB,
+  BFD_RELOC_IA64_REL64MSB,
+  BFD_RELOC_IA64_REL64LSB,
+  BFD_RELOC_IA64_LTV32MSB,
+  BFD_RELOC_IA64_LTV32LSB,
+  BFD_RELOC_IA64_LTV64MSB,
+  BFD_RELOC_IA64_LTV64LSB,
+  BFD_RELOC_IA64_IPLTMSB,
+  BFD_RELOC_IA64_IPLTLSB,
+  BFD_RELOC_IA64_COPY,
+  BFD_RELOC_IA64_LTOFF22X,
+  BFD_RELOC_IA64_LDXMOV,
+  BFD_RELOC_IA64_TPREL14,
+  BFD_RELOC_IA64_TPREL22,
+  BFD_RELOC_IA64_TPREL64I,
+  BFD_RELOC_IA64_TPREL64MSB,
+  BFD_RELOC_IA64_TPREL64LSB,
+  BFD_RELOC_IA64_LTOFF_TPREL22,
+  BFD_RELOC_IA64_DTPMOD64MSB,
+  BFD_RELOC_IA64_DTPMOD64LSB,
+  BFD_RELOC_IA64_LTOFF_DTPMOD22,
+  BFD_RELOC_IA64_DTPREL14,
+  BFD_RELOC_IA64_DTPREL22,
+  BFD_RELOC_IA64_DTPREL64I,
+  BFD_RELOC_IA64_DTPREL32MSB,
+  BFD_RELOC_IA64_DTPREL32LSB,
+  BFD_RELOC_IA64_DTPREL64MSB,
+  BFD_RELOC_IA64_DTPREL64LSB,
+  BFD_RELOC_IA64_LTOFF_DTPREL22,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bit high part of an absolute address.  */
+  BFD_RELOC_M68HC11_HI8,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bit low part of an absolute address.  */
+  BFD_RELOC_M68HC11_LO8,
+
+/* Motorola 68HC11 reloc.
+This is the 3 bit of a value.  */
+  BFD_RELOC_M68HC11_3B,
+
+/* Motorola 68HC11 reloc.
+This reloc marks the beginning of a jump/call instruction.
+It is used for linker relaxation to correctly identify beginning
+of instruction and change some branches to use PC-relative
+addressing mode.  */
+  BFD_RELOC_M68HC11_RL_JUMP,
+
+/* Motorola 68HC11 reloc.
+This reloc marks a group of several instructions that gcc generates
+and for which the linker relaxation pass can modify and/or remove
+some of them.  */
+  BFD_RELOC_M68HC11_RL_GROUP,
+
+/* Motorola 68HC11 reloc.
+This is the 16-bit lower part of an address.  It is used for 'call'
+instruction to specify the symbol address without any special
+transformation (due to memory bank window).  */
+  BFD_RELOC_M68HC11_LO16,
+
+/* Motorola 68HC11 reloc.
+This is a 8-bit reloc that specifies the page number of an address.
+It is used by 'call' instruction to specify the page number of
+the symbol.  */
+  BFD_RELOC_M68HC11_PAGE,
+
+/* Motorola 68HC11 reloc.
+This is a 24-bit reloc that represents the address with a 16-bit
+value and a 8-bit page number.  The symbol address is transformed
+to follow the 16K memory bank of 68HC12 (seen as mapped in the window).  */
+  BFD_RELOC_M68HC11_24,
+
+/* Motorola 68HC12 reloc.
+This is the 5 bits of a value.  */
+  BFD_RELOC_M68HC12_5B,
+
+/* NS CR16C Relocations.  */
+  BFD_RELOC_16C_NUM08,
+  BFD_RELOC_16C_NUM08_C,
+  BFD_RELOC_16C_NUM16,
+  BFD_RELOC_16C_NUM16_C,
+  BFD_RELOC_16C_NUM32,
+  BFD_RELOC_16C_NUM32_C,
+  BFD_RELOC_16C_DISP04,
+  BFD_RELOC_16C_DISP04_C,
+  BFD_RELOC_16C_DISP08,
+  BFD_RELOC_16C_DISP08_C,
+  BFD_RELOC_16C_DISP16,
+  BFD_RELOC_16C_DISP16_C,
+  BFD_RELOC_16C_DISP24,
+  BFD_RELOC_16C_DISP24_C,
+  BFD_RELOC_16C_DISP24a,
+  BFD_RELOC_16C_DISP24a_C,
+  BFD_RELOC_16C_REG04,
+  BFD_RELOC_16C_REG04_C,
+  BFD_RELOC_16C_REG04a,
+  BFD_RELOC_16C_REG04a_C,
+  BFD_RELOC_16C_REG14,
+  BFD_RELOC_16C_REG14_C,
+  BFD_RELOC_16C_REG16,
+  BFD_RELOC_16C_REG16_C,
+  BFD_RELOC_16C_REG20,
+  BFD_RELOC_16C_REG20_C,
+  BFD_RELOC_16C_ABS20,
+  BFD_RELOC_16C_ABS20_C,
+  BFD_RELOC_16C_ABS24,
+  BFD_RELOC_16C_ABS24_C,
+  BFD_RELOC_16C_IMM04,
+  BFD_RELOC_16C_IMM04_C,
+  BFD_RELOC_16C_IMM16,
+  BFD_RELOC_16C_IMM16_C,
+  BFD_RELOC_16C_IMM20,
+  BFD_RELOC_16C_IMM20_C,
+  BFD_RELOC_16C_IMM24,
+  BFD_RELOC_16C_IMM24_C,
+  BFD_RELOC_16C_IMM32,
+  BFD_RELOC_16C_IMM32_C,
+
+/* NS CRX Relocations.  */
+  BFD_RELOC_CRX_REL4,
+  BFD_RELOC_CRX_REL8,
+  BFD_RELOC_CRX_REL8_CMP,
+  BFD_RELOC_CRX_REL16,
+  BFD_RELOC_CRX_REL24,
+  BFD_RELOC_CRX_REL32,
+  BFD_RELOC_CRX_REGREL12,
+  BFD_RELOC_CRX_REGREL22,
+  BFD_RELOC_CRX_REGREL28,
+  BFD_RELOC_CRX_REGREL32,
+  BFD_RELOC_CRX_ABS16,
+  BFD_RELOC_CRX_ABS32,
+  BFD_RELOC_CRX_NUM8,
+  BFD_RELOC_CRX_NUM16,
+  BFD_RELOC_CRX_NUM32,
+  BFD_RELOC_CRX_IMM16,
+  BFD_RELOC_CRX_IMM32,
+  BFD_RELOC_CRX_SWITCH8,
+  BFD_RELOC_CRX_SWITCH16,
+  BFD_RELOC_CRX_SWITCH32,
+
+/* These relocs are only used within the CRIS assembler.  They are not
+(at present) written to any object files.  */
+  BFD_RELOC_CRIS_BDISP8,
+  BFD_RELOC_CRIS_UNSIGNED_5,
+  BFD_RELOC_CRIS_SIGNED_6,
+  BFD_RELOC_CRIS_UNSIGNED_6,
+  BFD_RELOC_CRIS_SIGNED_8,
+  BFD_RELOC_CRIS_UNSIGNED_8,
+  BFD_RELOC_CRIS_SIGNED_16,
+  BFD_RELOC_CRIS_UNSIGNED_16,
+  BFD_RELOC_CRIS_LAPCQ_OFFSET,
+  BFD_RELOC_CRIS_UNSIGNED_4,
+
+/* Relocs used in ELF shared libraries for CRIS.  */
+  BFD_RELOC_CRIS_COPY,
+  BFD_RELOC_CRIS_GLOB_DAT,
+  BFD_RELOC_CRIS_JUMP_SLOT,
+  BFD_RELOC_CRIS_RELATIVE,
+
+/* 32-bit offset to symbol-entry within GOT.  */
+  BFD_RELOC_CRIS_32_GOT,
+
+/* 16-bit offset to symbol-entry within GOT.  */
+  BFD_RELOC_CRIS_16_GOT,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_CRIS_32_GOTPLT,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_CRIS_16_GOTPLT,
+
+/* 32-bit offset to symbol, relative to GOT.  */
+  BFD_RELOC_CRIS_32_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to GOT.  */
+  BFD_RELOC_CRIS_32_PLT_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to this relocation.  */
+  BFD_RELOC_CRIS_32_PLT_PCREL,
+
+/* Intel i860 Relocations.  */
+  BFD_RELOC_860_COPY,
+  BFD_RELOC_860_GLOB_DAT,
+  BFD_RELOC_860_JUMP_SLOT,
+  BFD_RELOC_860_RELATIVE,
+  BFD_RELOC_860_PC26,
+  BFD_RELOC_860_PLT26,
+  BFD_RELOC_860_PC16,
+  BFD_RELOC_860_LOW0,
+  BFD_RELOC_860_SPLIT0,
+  BFD_RELOC_860_LOW1,
+  BFD_RELOC_860_SPLIT1,
+  BFD_RELOC_860_LOW2,
+  BFD_RELOC_860_SPLIT2,
+  BFD_RELOC_860_LOW3,
+  BFD_RELOC_860_LOGOT0,
+  BFD_RELOC_860_SPGOT0,
+  BFD_RELOC_860_LOGOT1,
+  BFD_RELOC_860_SPGOT1,
+  BFD_RELOC_860_LOGOTOFF0,
+  BFD_RELOC_860_SPGOTOFF0,
+  BFD_RELOC_860_LOGOTOFF1,
+  BFD_RELOC_860_SPGOTOFF1,
+  BFD_RELOC_860_LOGOTOFF2,
+  BFD_RELOC_860_LOGOTOFF3,
+  BFD_RELOC_860_LOPC,
+  BFD_RELOC_860_HIGHADJ,
+  BFD_RELOC_860_HAGOT,
+  BFD_RELOC_860_HAGOTOFF,
+  BFD_RELOC_860_HAPC,
+  BFD_RELOC_860_HIGH,
+  BFD_RELOC_860_HIGOT,
+  BFD_RELOC_860_HIGOTOFF,
+
+/* OpenRISC Relocations.  */
+  BFD_RELOC_OPENRISC_ABS_26,
+  BFD_RELOC_OPENRISC_REL_26,
+
+/* H8 elf Relocations.  */
+  BFD_RELOC_H8_DIR16A8,
+  BFD_RELOC_H8_DIR16R8,
+  BFD_RELOC_H8_DIR24A8,
+  BFD_RELOC_H8_DIR24R8,
+  BFD_RELOC_H8_DIR32A16,
+
+/* Sony Xstormy16 Relocations.  */
+  BFD_RELOC_XSTORMY16_REL_12,
+  BFD_RELOC_XSTORMY16_12,
+  BFD_RELOC_XSTORMY16_24,
+  BFD_RELOC_XSTORMY16_FPTR16,
+
+/* Relocations used by VAX ELF.  */
+  BFD_RELOC_VAX_GLOB_DAT,
+  BFD_RELOC_VAX_JMP_SLOT,
+  BFD_RELOC_VAX_RELATIVE,
+
+/* Morpho MT - 16 bit immediate relocation.  */
+  BFD_RELOC_MT_PC16,
+
+/* Morpho MT - Hi 16 bits of an address.  */
+  BFD_RELOC_MT_HI16,
+
+/* Morpho MT - Low 16 bits of an address.  */
+  BFD_RELOC_MT_LO16,
+
+/* Morpho MT - Used to tell the linker which vtable entries are used.  */
+  BFD_RELOC_MT_GNU_VTINHERIT,
+
+/* Morpho MT - Used to tell the linker which vtable entries are used.  */
+  BFD_RELOC_MT_GNU_VTENTRY,
+
+/* Morpho MT - 8 bit immediate relocation.  */
+  BFD_RELOC_MT_PCINSN8,
+
+/* msp430 specific relocation codes  */
+  BFD_RELOC_MSP430_10_PCREL,
+  BFD_RELOC_MSP430_16_PCREL,
+  BFD_RELOC_MSP430_16,
+  BFD_RELOC_MSP430_16_PCREL_BYTE,
+  BFD_RELOC_MSP430_16_BYTE,
+  BFD_RELOC_MSP430_2X_PCREL,
+  BFD_RELOC_MSP430_RL_PCREL,
+
+/* IQ2000 Relocations.  */
+  BFD_RELOC_IQ2000_OFFSET_16,
+  BFD_RELOC_IQ2000_OFFSET_21,
+  BFD_RELOC_IQ2000_UHI16,
+
+/* Special Xtensa relocation used only by PLT entries in ELF shared
+objects to indicate that the runtime linker should set the value
+to one of its own internal functions or data structures.  */
+  BFD_RELOC_XTENSA_RTLD,
+
+/* Xtensa relocations for ELF shared objects.  */
+  BFD_RELOC_XTENSA_GLOB_DAT,
+  BFD_RELOC_XTENSA_JMP_SLOT,
+  BFD_RELOC_XTENSA_RELATIVE,
+
+/* Xtensa relocation used in ELF object files for symbols that may require
+PLT entries.  Otherwise, this is just a generic 32-bit relocation.  */
+  BFD_RELOC_XTENSA_PLT,
+
+/* Xtensa relocations to mark the difference of two local symbols.
+These are only needed to support linker relaxation and can be ignored
+when not relaxing.  The field is set to the value of the difference
+assuming no relaxation.  The relocation encodes the position of the
+first symbol so the linker can determine whether to adjust the field
+value.  */
+  BFD_RELOC_XTENSA_DIFF8,
+  BFD_RELOC_XTENSA_DIFF16,
+  BFD_RELOC_XTENSA_DIFF32,
+
+/* Generic Xtensa relocations for instruction operands.  Only the slot
+number is encoded in the relocation.  The relocation applies to the
+last PC-relative immediate operand, or if there are no PC-relative
+immediates, to the last immediate operand.  */
+  BFD_RELOC_XTENSA_SLOT0_OP,
+  BFD_RELOC_XTENSA_SLOT1_OP,
+  BFD_RELOC_XTENSA_SLOT2_OP,
+  BFD_RELOC_XTENSA_SLOT3_OP,
+  BFD_RELOC_XTENSA_SLOT4_OP,
+  BFD_RELOC_XTENSA_SLOT5_OP,
+  BFD_RELOC_XTENSA_SLOT6_OP,
+  BFD_RELOC_XTENSA_SLOT7_OP,
+  BFD_RELOC_XTENSA_SLOT8_OP,
+  BFD_RELOC_XTENSA_SLOT9_OP,
+  BFD_RELOC_XTENSA_SLOT10_OP,
+  BFD_RELOC_XTENSA_SLOT11_OP,
+  BFD_RELOC_XTENSA_SLOT12_OP,
+  BFD_RELOC_XTENSA_SLOT13_OP,
+  BFD_RELOC_XTENSA_SLOT14_OP,
+
+/* Alternate Xtensa relocations.  Only the slot is encoded in the
+relocation.  The meaning of these relocations is opcode-specific.  */
+  BFD_RELOC_XTENSA_SLOT0_ALT,
+  BFD_RELOC_XTENSA_SLOT1_ALT,
+  BFD_RELOC_XTENSA_SLOT2_ALT,
+  BFD_RELOC_XTENSA_SLOT3_ALT,
+  BFD_RELOC_XTENSA_SLOT4_ALT,
+  BFD_RELOC_XTENSA_SLOT5_ALT,
+  BFD_RELOC_XTENSA_SLOT6_ALT,
+  BFD_RELOC_XTENSA_SLOT7_ALT,
+  BFD_RELOC_XTENSA_SLOT8_ALT,
+  BFD_RELOC_XTENSA_SLOT9_ALT,
+  BFD_RELOC_XTENSA_SLOT10_ALT,
+  BFD_RELOC_XTENSA_SLOT11_ALT,
+  BFD_RELOC_XTENSA_SLOT12_ALT,
+  BFD_RELOC_XTENSA_SLOT13_ALT,
+  BFD_RELOC_XTENSA_SLOT14_ALT,
+
+/* Xtensa relocations for backward compatibility.  These have all been
+replaced by BFD_RELOC_XTENSA_SLOT0_OP.  */
+  BFD_RELOC_XTENSA_OP0,
+  BFD_RELOC_XTENSA_OP1,
+  BFD_RELOC_XTENSA_OP2,
+
+/* Xtensa relocation to mark that the assembler expanded the
+instructions from an original target.  The expansion size is
+encoded in the reloc size.  */
+  BFD_RELOC_XTENSA_ASM_EXPAND,
+
+/* Xtensa relocation to mark that the linker should simplify
+assembler-expanded instructions.  This is commonly used
+internally by the linker after analysis of a
+BFD_RELOC_XTENSA_ASM_EXPAND.  */
+  BFD_RELOC_XTENSA_ASM_SIMPLIFY,
+
+/* 8 bit signed offset in (ix+d) or (iy+d).  */
+  BFD_RELOC_Z80_DISP8,
+
+/* DJNZ offset.  */
+  BFD_RELOC_Z8K_DISP7,
+
+/* CALR offset.  */
+  BFD_RELOC_Z8K_CALLR,
+
+/* 4 bit value.  */
+  BFD_RELOC_Z8K_IMM4L,
+  BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *bfd_reloc_type_lookup
+   (bfd *abfd, bfd_reloc_code_real_type code);
+
+const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code);
+
+/* Extracted from syms.c.  */
+
+typedef struct bfd_symbol
+{
+  /* 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 arbitrary
+     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
+
+  /* This symbol is thread local.  Used in ELF.  */
+#define BSF_THREAD_LOCAL  0x40000
+
+  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 bfd_section *section;
+
+  /* Back end special data.  */
+  union
+    {
+      void *p;
+      bfd_vma i;
+    }
+  udata;
+}
+asymbol;
+
+#define bfd_get_symtab_upper_bound(abfd) \
+     BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+
+bfd_boolean bfd_is_local_label (bfd *abfd, asymbol *sym);
+
+bfd_boolean bfd_is_local_label_name (bfd *abfd, const char *name);
+
+#define bfd_is_local_label_name(abfd, name) \
+  BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+
+bfd_boolean bfd_is_target_special_symbol (bfd *abfd, asymbol *sym);
+
+#define bfd_is_target_special_symbol(abfd, sym) \
+  BFD_SEND (abfd, _bfd_is_target_special_symbol, (abfd, sym))
+
+#define bfd_canonicalize_symtab(abfd, location) \
+  BFD_SEND (abfd, _bfd_canonicalize_symtab, (abfd, location))
+
+bfd_boolean bfd_set_symtab
+   (bfd *abfd, asymbol **location, unsigned int count);
+
+void bfd_print_symbol_vandf (bfd *abfd, void *file, asymbol *symbol);
+
+#define bfd_make_empty_symbol(abfd) \
+  BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+
+asymbol *_bfd_generic_make_empty_symbol (bfd *);
+
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+  BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+
+int bfd_decode_symclass (asymbol *symbol);
+
+bfd_boolean bfd_is_undefined_symclass (int symclass);
+
+void bfd_symbol_info (asymbol *symbol, symbol_info *ret);
+
+bfd_boolean bfd_copy_private_symbol_data
+   (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))
+
+/* Extracted from bfd.c.  */
+struct bfd
+{
+  /* A unique identifier of the BFD  */
+  unsigned int id;
+
+  /* The filename the application opened the BFD with.  */
+  const char *filename;
+
+  /* A pointer to the target jump table.  */
+  const struct bfd_target *xvec;
+
+  /* The IOSTREAM, and corresponding IO vector that provide access
+     to the file backing the BFD.  */
+  void *iostream;
+  const struct bfd_iovec *iovec;
+
+  /* Is the file descriptor being cached?  That is, can it be closed as
+     needed, and re-opened when accessed later?  */
+  bfd_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.  */
+  bfd_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...  */
+  ufile_ptr where;
+
+  /* ... and here: (``once'' means at least once).  */
+  bfd_boolean opened_once;
+
+  /* Set if we have a locally maintained mtime value, rather than
+     getting it from the file each time.  */
+  bfd_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 with which the BFD was opened.  */
+  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.  */
+  ufile_ptr origin;
+
+  /* Remember when output has begun, to stop strange things
+     from happening.  */
+  bfd_boolean output_has_begun;
+
+  /* A hash table for section names.  */
+  struct bfd_hash_table section_htab;
+
+  /* Pointer to linked list of sections.  */
+  struct bfd_section *sections;
+
+  /* The last section on the section list.  */
+  struct bfd_section *section_last;
+
+  /* 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 bfd_symbol  **outsymbols;
+
+  /* Used for slurped dynamic symbol tables.  */
+  unsigned int dynsymcount;
+
+  /* Pointer to structure which contains architecture information.  */
+  const struct bfd_arch_info *arch_info;
+
+  /* Flag set if symbols from this BFD should not be exported.  */
+  bfd_boolean no_export;
+
+  /* Stuff only useful for archives.  */
+  void *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.  */
+  bfd_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 mmo_data_struct *mmo_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;
+      struct mach_o_data_struct *mach_o_data;
+      struct mach_o_fat_data_struct *mach_o_fat_data;
+      struct bfd_pef_data_struct *pef_data;
+      struct bfd_pef_xlib_data_struct *pef_xlib_data;
+      struct bfd_sym_data_struct *sym_data;
+      void *any;
+    }
+  tdata;
+
+  /* Used by the application to hold private data.  */
+  void *usrdata;
+
+  /* Where all the allocated stuff under this BFD goes.  This is a
+     struct objalloc *, but we use void * to avoid requiring the inclusion
+     of objalloc.h.  */
+  void *memory;
+};
+
+typedef enum bfd_error
+{
+  bfd_error_no_error = 0,
+  bfd_error_system_call,
+  bfd_error_invalid_target,
+  bfd_error_wrong_format,
+  bfd_error_wrong_object_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 (void);
+
+void bfd_set_error (bfd_error_type error_tag);
+
+const char *bfd_errmsg (bfd_error_type error_tag);
+
+void bfd_perror (const char *message);
+
+typedef void (*bfd_error_handler_type) (const char *, ...);
+
+bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type);
+
+void bfd_set_error_program_name (const char *);
+
+bfd_error_handler_type bfd_get_error_handler (void);
+
+long bfd_get_reloc_upper_bound (bfd *abfd, asection *sect);
+
+long bfd_canonicalize_reloc
+   (bfd *abfd, asection *sec, arelent **loc, asymbol **syms);
+
+void bfd_set_reloc
+   (bfd *abfd, asection *sec, arelent **rel, unsigned int count);
+
+bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags);
+
+int bfd_get_arch_size (bfd *abfd);
+
+int bfd_get_sign_extend_vma (bfd *abfd);
+
+bfd_boolean bfd_set_start_address (bfd *abfd, bfd_vma vma);
+
+unsigned int bfd_get_gp_size (bfd *abfd);
+
+void bfd_set_gp_size (bfd *abfd, unsigned int i);
+
+bfd_vma bfd_scan_vma (const char *string, const char **end, int base);
+
+bfd_boolean bfd_copy_private_header_data (bfd *ibfd, bfd *obfd);
+
+#define bfd_copy_private_header_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_copy_private_header_data, \
+               (ibfd, obfd))
+bfd_boolean bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd);
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+               (ibfd, obfd))
+bfd_boolean bfd_merge_private_bfd_data (bfd *ibfd, bfd *obfd);
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+               (ibfd, obfd))
+bfd_boolean bfd_set_private_flags (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))
+
+#define bfd_find_line(abfd, syms, sym, file, line) \
+       BFD_SEND (abfd, _bfd_find_line, \
+                 (abfd, syms, sym, file, line))
+
+#define bfd_find_inliner_info(abfd, file, func, line) \
+       BFD_SEND (abfd, _bfd_find_inliner_info, \
+                 (abfd, file, func, line))
+
+#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_merge_sections(abfd, link_info) \
+       BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
+#define bfd_is_group_section(abfd, sec) \
+       BFD_SEND (abfd, _bfd_is_group_section, (abfd, sec))
+
+#define bfd_discard_group(abfd, sec) \
+       BFD_SEND (abfd, _bfd_discard_group, (abfd, sec))
+
+#define bfd_link_hash_table_create(abfd) \
+       BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_hash_table_free(abfd, hash) \
+       BFD_SEND (abfd, _bfd_link_hash_table_free, (hash))
+
+#define bfd_link_add_symbols(abfd, info) \
+       BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_link_just_syms(abfd, sec, info) \
+       BFD_SEND (abfd, _bfd_link_just_syms, (sec, 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_synthetic_symtab(abfd, count, syms, dyncount, dynsyms, ret) \
+       BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, count, syms, \
+                                                   dyncount, dynsyms, ret))
+
+#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
+  (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *,
+   bfd_boolean, asymbol **);
+
+bfd_boolean bfd_alt_mach_code (bfd *abfd, int alternative);
+
+struct bfd_preserve
+{
+  void *marker;
+  void *tdata;
+  flagword flags;
+  const struct bfd_arch_info *arch_info;
+  struct bfd_section *sections;
+  struct bfd_section *section_last;
+  unsigned int section_count;
+  struct bfd_hash_table section_htab;
+};
+
+bfd_boolean bfd_preserve_save (bfd *, struct bfd_preserve *);
+
+void bfd_preserve_restore (bfd *, struct bfd_preserve *);
+
+void bfd_preserve_finish (bfd *, struct bfd_preserve *);
+
+/* Extracted from archive.c.  */
+symindex bfd_get_next_mapent
+   (bfd *abfd, symindex previous, carsym **sym);
+
+bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head);
+
+bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous);
+
+/* Extracted from corefile.c.  */
+const char *bfd_core_file_failing_command (bfd *abfd);
+
+int bfd_core_file_failing_signal (bfd *abfd);
+
+bfd_boolean core_file_matches_executable_p
+   (bfd *core_bfd, bfd *exec_bfd);
+
+/* Extracted from targets.c.  */
+#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_xcoff_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,
+  bfd_target_mmo_flavour,
+  bfd_target_mach_o_flavour,
+  bfd_target_pef_flavour,
+  bfd_target_pef_xlib_flavour,
+  bfd_target_sym_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
+{
+  /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc.  */
+  char *name;
+
+ /* The "flavour" of a back end is a general indication about
+    the contents of a file.  */
+  enum bfd_flavour flavour;
+
+  /* The order of bytes within the data area of a file.  */
+  enum bfd_endian byteorder;
+
+ /* The order of bytes within the header parts of a file.  */
+  enum bfd_endian header_byteorder;
+
+  /* A mask of all the flags which an executable may have set -
+     from the set <<BFD_NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>.  */
+  flagword object_flags;
+
+ /* A mask of all the flags which a section may have set - from
+    the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>.  */
+  flagword section_flags;
+
+ /* The character normally found at the front of a symbol.
+    (if any), perhaps `_'.  */
+  char symbol_leading_char;
+
+ /* The pad character for file names within an archive header.  */
+  char ar_pad_char;
+
+  /* The maximum number of characters in an archive header.  */
+  unsigned short ar_max_namelen;
+
+  /* Entries for byte swapping for data. These are different from the
+     other entry points, since they don't take a BFD as the first argument.
+     Certain other handlers could do the same.  */
+  bfd_uint64_t   (*bfd_getx64) (const void *);
+  bfd_int64_t    (*bfd_getx_signed_64) (const void *);
+  void           (*bfd_putx64) (bfd_uint64_t, void *);
+  bfd_vma        (*bfd_getx32) (const void *);
+  bfd_signed_vma (*bfd_getx_signed_32) (const void *);
+  void           (*bfd_putx32) (bfd_vma, void *);
+  bfd_vma        (*bfd_getx16) (const void *);
+  bfd_signed_vma (*bfd_getx_signed_16) (const void *);
+  void           (*bfd_putx16) (bfd_vma, void *);
+
+  /* Byte swapping for the headers.  */
+  bfd_uint64_t   (*bfd_h_getx64) (const void *);
+  bfd_int64_t    (*bfd_h_getx_signed_64) (const void *);
+  void           (*bfd_h_putx64) (bfd_uint64_t, void *);
+  bfd_vma        (*bfd_h_getx32) (const void *);
+  bfd_signed_vma (*bfd_h_getx_signed_32) (const void *);
+  void           (*bfd_h_putx32) (bfd_vma, void *);
+  bfd_vma        (*bfd_h_getx16) (const void *);
+  bfd_signed_vma (*bfd_h_getx_signed_16) (const void *);
+  void           (*bfd_h_putx16) (bfd_vma, void *);
+
+  /* Format dependent routines: these are vectors of entry points
+     within the target vector structure, one for each format to check.  */
+
+  /* Check the format of a file being read.  Return a <<bfd_target *>> or zero.  */
+  const struct bfd_target *(*_bfd_check_format[bfd_type_end]) (bfd *);
+
+  /* Set the format of a file being written.  */
+  bfd_boolean (*_bfd_set_format[bfd_type_end]) (bfd *);
+
+  /* Write cached information into a file being written, at <<bfd_close>>.  */
+  bfd_boolean (*_bfd_write_contents[bfd_type_end]) (bfd *);
+
+
+  /* Generic entry points.  */
+#define BFD_JUMP_TABLE_GENERIC(NAME) \
+  NAME##_close_and_cleanup, \
+  NAME##_bfd_free_cached_info, \
+  NAME##_new_section_hook, \
+  NAME##_get_section_contents, \
+  NAME##_get_section_contents_in_window
+
+  /* Called when the BFD is being closed to do any necessary cleanup.  */
+  bfd_boolean (*_close_and_cleanup) (bfd *);
+  /* Ask the BFD to free all cached information.  */
+  bfd_boolean (*_bfd_free_cached_info) (bfd *);
+  /* Called when a new section is created.  */
+  bfd_boolean (*_new_section_hook) (bfd *, sec_ptr);
+  /* Read the contents of a section.  */
+  bfd_boolean (*_bfd_get_section_contents)
+    (bfd *, sec_ptr, void *, file_ptr, bfd_size_type);
+  bfd_boolean (*_bfd_get_section_contents_in_window)
+    (bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type);
+
+  /* Entry points to copy private data.  */
+#define BFD_JUMP_TABLE_COPY(NAME) \
+  NAME##_bfd_copy_private_bfd_data, \
+  NAME##_bfd_merge_private_bfd_data, \
+  _bfd_generic_init_private_section_data, \
+  NAME##_bfd_copy_private_section_data, \
+  NAME##_bfd_copy_private_symbol_data, \
+  NAME##_bfd_copy_private_header_data, \
+  NAME##_bfd_set_private_flags, \
+  NAME##_bfd_print_private_bfd_data
+
+  /* Called to copy BFD general private data from one object file
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_bfd_data) (bfd *, bfd *);
+  /* Called to merge BFD general private data from one object file
+     to a common output file when linking.  */
+  bfd_boolean (*_bfd_merge_private_bfd_data) (bfd *, bfd *);
+  /* Called to initialize BFD private section data from one object file
+     to another.  */
+#define bfd_init_private_section_data(ibfd, isec, obfd, osec, link_info) \
+  BFD_SEND (obfd, _bfd_init_private_section_data, (ibfd, isec, obfd, osec, link_info))
+  bfd_boolean (*_bfd_init_private_section_data)
+    (bfd *, sec_ptr, bfd *, sec_ptr, struct bfd_link_info *);
+  /* Called to copy BFD private section data from one object file
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_section_data)
+    (bfd *, sec_ptr, bfd *, sec_ptr);
+  /* Called to copy BFD private symbol data from one symbol
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_symbol_data)
+    (bfd *, asymbol *, bfd *, asymbol *);
+  /* Called to copy BFD private header data from one object file
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_header_data)
+    (bfd *, bfd *);
+  /* Called to set private backend flags.  */
+  bfd_boolean (*_bfd_set_private_flags) (bfd *, flagword);
+
+  /* Called to print private BFD data.  */
+  bfd_boolean (*_bfd_print_private_bfd_data) (bfd *, void *);
+
+  /* Core file entry points.  */
+#define BFD_JUMP_TABLE_CORE(NAME) \
+  NAME##_core_file_failing_command, \
+  NAME##_core_file_failing_signal, \
+  NAME##_core_file_matches_executable_p
+
+  char *      (*_core_file_failing_command) (bfd *);
+  int         (*_core_file_failing_signal) (bfd *);
+  bfd_boolean (*_core_file_matches_executable_p) (bfd *, bfd *);
+
+  /* Archive entry points.  */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME) \
+  NAME##_slurp_armap, \
+  NAME##_slurp_extended_name_table, \
+  NAME##_construct_extended_name_table, \
+  NAME##_truncate_arname, \
+  NAME##_write_armap, \
+  NAME##_read_ar_hdr, \
+  NAME##_openr_next_archived_file, \
+  NAME##_get_elt_at_index, \
+  NAME##_generic_stat_arch_elt, \
+  NAME##_update_armap_timestamp
+
+  bfd_boolean (*_bfd_slurp_armap) (bfd *);
+  bfd_boolean (*_bfd_slurp_extended_name_table) (bfd *);
+  bfd_boolean (*_bfd_construct_extended_name_table)
+    (bfd *, char **, bfd_size_type *, const char **);
+  void        (*_bfd_truncate_arname) (bfd *, const char *, char *);
+  bfd_boolean (*write_armap)
+    (bfd *, unsigned int, struct orl *, unsigned int, int);
+  void *      (*_bfd_read_ar_hdr_fn) (bfd *);
+  bfd *       (*openr_next_archived_file) (bfd *, bfd *);
+#define bfd_get_elt_at_index(b,i) BFD_SEND (b, _bfd_get_elt_at_index, (b,i))
+  bfd *       (*_bfd_get_elt_at_index) (bfd *, symindex);
+  int         (*_bfd_stat_arch_elt) (bfd *, struct stat *);
+  bfd_boolean (*_bfd_update_armap_timestamp) (bfd *);
+
+  /* Entry points used for symbols.  */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME) \
+  NAME##_get_symtab_upper_bound, \
+  NAME##_canonicalize_symtab, \
+  NAME##_make_empty_symbol, \
+  NAME##_print_symbol, \
+  NAME##_get_symbol_info, \
+  NAME##_bfd_is_local_label_name, \
+  NAME##_bfd_is_target_special_symbol, \
+  NAME##_get_lineno, \
+  NAME##_find_nearest_line, \
+  _bfd_generic_find_line, \
+  NAME##_find_inliner_info, \
+  NAME##_bfd_make_debug_symbol, \
+  NAME##_read_minisymbols, \
+  NAME##_minisymbol_to_symbol
+
+  long        (*_bfd_get_symtab_upper_bound) (bfd *);
+  long        (*_bfd_canonicalize_symtab)
+    (bfd *, struct bfd_symbol **);
+  struct bfd_symbol *
+              (*_bfd_make_empty_symbol) (bfd *);
+  void        (*_bfd_print_symbol)
+    (bfd *, void *, struct bfd_symbol *, 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)
+    (bfd *, struct bfd_symbol *, symbol_info *);
+#define bfd_get_symbol_info(b,p,e) BFD_SEND (b, _bfd_get_symbol_info, (b,p,e))
+  bfd_boolean (*_bfd_is_local_label_name) (bfd *, const char *);
+  bfd_boolean (*_bfd_is_target_special_symbol) (bfd *, asymbol *);
+  alent *     (*_get_lineno) (bfd *, struct bfd_symbol *);
+  bfd_boolean (*_bfd_find_nearest_line)
+    (bfd *, struct bfd_section *, struct bfd_symbol **, bfd_vma,
+     const char **, const char **, unsigned int *);
+  bfd_boolean (*_bfd_find_line)
+    (bfd *, struct bfd_symbol **, struct bfd_symbol *,
+     const char **, unsigned int *);
+  bfd_boolean (*_bfd_find_inliner_info)
+    (bfd *, const char **, const char **, unsigned int *);
+ /* 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)
+    (bfd *, void *, unsigned long size);
+#define bfd_read_minisymbols(b, d, m, s) \
+  BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+  long        (*_read_minisymbols)
+    (bfd *, bfd_boolean, void **, 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)
+    (bfd *, bfd_boolean, const void *, asymbol *);
+
+  /* Routines for relocs.  */
+#define BFD_JUMP_TABLE_RELOCS(NAME) \
+  NAME##_get_reloc_upper_bound, \
+  NAME##_canonicalize_reloc, \
+  NAME##_bfd_reloc_type_lookup
+
+  long        (*_get_reloc_upper_bound) (bfd *, sec_ptr);
+  long        (*_bfd_canonicalize_reloc)
+    (bfd *, sec_ptr, arelent **, struct bfd_symbol **);
+  /* See documentation on reloc types.  */
+  reloc_howto_type *
+              (*reloc_type_lookup) (bfd *, bfd_reloc_code_real_type);
+
+  /* Routines used when writing an object file.  */
+#define BFD_JUMP_TABLE_WRITE(NAME) \
+  NAME##_set_arch_mach, \
+  NAME##_set_section_contents
+
+  bfd_boolean (*_bfd_set_arch_mach)
+    (bfd *, enum bfd_architecture, unsigned long);
+  bfd_boolean (*_bfd_set_section_contents)
+    (bfd *, sec_ptr, const void *, file_ptr, bfd_size_type);
+
+  /* Routines used by the linker.  */
+#define BFD_JUMP_TABLE_LINK(NAME) \
+  NAME##_sizeof_headers, \
+  NAME##_bfd_get_relocated_section_contents, \
+  NAME##_bfd_relax_section, \
+  NAME##_bfd_link_hash_table_create, \
+  NAME##_bfd_link_hash_table_free, \
+  NAME##_bfd_link_add_symbols, \
+  NAME##_bfd_link_just_syms, \
+  NAME##_bfd_final_link, \
+  NAME##_bfd_link_split_section, \
+  NAME##_bfd_gc_sections, \
+  NAME##_bfd_merge_sections, \
+  NAME##_bfd_is_group_section, \
+  NAME##_bfd_discard_group, \
+  NAME##_section_already_linked \
+
+  int         (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
+  bfd_byte *  (*_bfd_get_relocated_section_contents)
+    (bfd *, struct bfd_link_info *, struct bfd_link_order *,
+     bfd_byte *, bfd_boolean, struct bfd_symbol **);
+
+  bfd_boolean (*_bfd_relax_section)
+    (bfd *, struct bfd_section *, struct bfd_link_info *, bfd_boolean *);
+
+  /* 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) (bfd *);
+
+  /* Release the memory associated with the linker hash table.  */
+  void        (*_bfd_link_hash_table_free) (struct bfd_link_hash_table *);
+
+  /* Add symbols from this object file into the hash table.  */
+  bfd_boolean (*_bfd_link_add_symbols) (bfd *, struct bfd_link_info *);
+
+  /* Indicate that we are only retrieving symbol values from this section.  */
+  void        (*_bfd_link_just_syms) (asection *, struct bfd_link_info *);
+
+  /* Do a link based on the link_order structures attached to each
+     section of the BFD.  */
+  bfd_boolean (*_bfd_final_link) (bfd *, struct bfd_link_info *);
+
+  /* Should this section be split up into smaller pieces during linking.  */
+  bfd_boolean (*_bfd_link_split_section) (bfd *, struct bfd_section *);
+
+  /* Remove sections that are not referenced from the output.  */
+  bfd_boolean (*_bfd_gc_sections) (bfd *, struct bfd_link_info *);
+
+  /* Attempt to merge SEC_MERGE sections.  */
+  bfd_boolean (*_bfd_merge_sections) (bfd *, struct bfd_link_info *);
+
+  /* Is this section a member of a group?  */
+  bfd_boolean (*_bfd_is_group_section) (bfd *, const struct bfd_section *);
+
+  /* Discard members of a group.  */
+  bfd_boolean (*_bfd_discard_group) (bfd *, struct bfd_section *);
+
+  /* Check if SEC has been already linked during a reloceatable or
+     final link.  */
+  void (*_section_already_linked) (bfd *, struct bfd_section *);
+
+  /* Routines to handle dynamic symbols and relocs.  */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
+  NAME##_get_dynamic_symtab_upper_bound, \
+  NAME##_canonicalize_dynamic_symtab, \
+  NAME##_get_synthetic_symtab, \
+  NAME##_get_dynamic_reloc_upper_bound, \
+  NAME##_canonicalize_dynamic_reloc
+
+  /* Get the amount of memory required to hold the dynamic symbols.  */
+  long        (*_bfd_get_dynamic_symtab_upper_bound) (bfd *);
+  /* Read in the dynamic symbols.  */
+  long        (*_bfd_canonicalize_dynamic_symtab)
+    (bfd *, struct bfd_symbol **);
+  /* Create synthetized symbols.  */
+  long        (*_bfd_get_synthetic_symtab)
+    (bfd *, long, struct bfd_symbol **, long, struct bfd_symbol **,
+     struct bfd_symbol **);
+  /* Get the amount of memory required to hold the dynamic relocs.  */
+  long        (*_bfd_get_dynamic_reloc_upper_bound) (bfd *);
+  /* Read in the dynamic relocs.  */
+  long        (*_bfd_canonicalize_dynamic_reloc)
+    (bfd *, arelent **, struct bfd_symbol **);
+
+  /* Opposite endian version of this target.  */
+  const struct bfd_target * alternative_target;
+
+  /* Data for use by back-end routines, which isn't
+     generic enough to belong in this structure.  */
+  const void *backend_data;
+
+} bfd_target;
+
+bfd_boolean bfd_set_default_target (const char *name);
+
+const bfd_target *bfd_find_target (const char *target_name, bfd *abfd);
+
+const char ** bfd_target_list (void);
+
+const bfd_target *bfd_search_for_target
+   (int (*search_func) (const bfd_target *, void *),
+    void *);
+
+/* Extracted from format.c.  */
+bfd_boolean bfd_check_format (bfd *abfd, bfd_format format);
+
+bfd_boolean bfd_check_format_matches
+   (bfd *abfd, bfd_format format, char ***matching);
+
+bfd_boolean bfd_set_format (bfd *abfd, bfd_format format);
+
+const char *bfd_format_string (bfd_format format);
+
+/* Extracted from linker.c.  */
+bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec);
+
+#define bfd_link_split_section(abfd, sec) \
+       BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
+
+void bfd_section_already_linked (bfd *abfd, asection *sec);
+
+#define bfd_section_already_linked(abfd, sec) \
+       BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+
+/* Extracted from simple.c.  */
+bfd_byte *bfd_simple_get_relocated_section_contents
+   (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/arch/ia64/include/asm/kdb.h b/arch/ia64/include/asm/kdb.h
new file mode 100644 (file)
index 0000000..0dd8645
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _ASM_KDB_H
+#define _ASM_KDB_H
+
+/*
+ * Kernel Debugger Architecture Dependent Global Headers
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+/*
+ * 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.
+ */
+#include <asm/kdb_break.h>             /* break numbers are separated for CONFIG_KDB_LOCK */
+#define __KDB_ENTER2(b)        asm("\tbreak.m "#b"\n")
+#define __KDB_ENTER1(b)        __KDB_ENTER2(b)
+#define KDB_ENTER()            do {if (kdb_on && !KDB_IS_RUNNING()) { __KDB_ENTER1(KDB_BREAK_ENTER); }} while(0)
+#define KDB_ENTER_SLAVE()      do {if (kdb_on) { __KDB_ENTER1(KDB_BREAK_ENTER_SLAVE); }} while(0)
+
+       /*
+        * Needed for exported symbols.
+        */
+typedef unsigned long kdb_machreg_t;
+
+#define kdb_machreg_fmt                "0x%lx"
+#define kdb_machreg_fmt0       "0x%016lx"
+#define kdb_bfd_vma_fmt                "0x%lx"
+#define kdb_bfd_vma_fmt0       "0x%016lx"
+#define kdb_elfw_addr_fmt      "0x%lx"
+#define kdb_elfw_addr_fmt0     "0x%016lx"
+
+static inline unsigned long
+kdba_funcptr_value(void *fp)
+{
+       /* ia64 function descriptor, first word is address of code */
+       return *(unsigned long *)fp;
+}
+
+#endif /* !_ASM_KDB_H */
diff --git a/arch/ia64/include/asm/kdb_break.h b/arch/ia64/include/asm/kdb_break.h
new file mode 100644 (file)
index 0000000..6f65329
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _ASM_KDB_BREAK_H
+#define _ASM_KDB_BREAK_H
+
+/*
+ * Kernel Debugger Architecture Dependent Global Headers
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+/*
+ * Break numbers are used by CONFIG_KDB_LOCK code.  They need to be seperated
+ * from asm/kdb.h to let spinlock code build without pulling in all of the kdb
+ * headers.
+ */
+
+#define KDB_BREAK_BREAK                0x80100         /* kdb breakpoint in kernel */
+#define KDB_BREAK_ENTER                0x80101         /* KDB_ENTER(), single event or monarch */
+#define KDB_BREAK_ENTER_SLAVE  0x80102         /* KDB_ENTER_SLAVE(), concurrent slave events */
+
+#endif /* !_ASM_KDB_BREAK_H */
diff --git a/arch/ia64/include/asm/kdbprivate.h b/arch/ia64/include/asm/kdbprivate.h
new file mode 100644 (file)
index 0000000..ad9ef91
--- /dev/null
@@ -0,0 +1,124 @@
+#ifndef _ASM_KDBPRIVATE_H
+#define _ASM_KDBPRIVATE_H
+
+/*
+ * Kernel Debugger Architecture Dependent Private Headers
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+/* Definition of an machine instruction.
+ * Takes care of VLIW processors like Itanium
+ */
+
+typedef struct {
+       unsigned long inst[2];
+} 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=ia64", "BYTESPERWORD=4", "IDCOUNT=8"
+
+/*
+ * Support for IA64 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;
+
+#define getprsregs(regs)        ((struct switch_stack *)regs -1)
+
+/* bkpt support using break inst instead of IBP reg */
+
+/*
+ * Define certain specific instructions
+ */
+#define BREAK_INSTR             (long)(KDB_BREAK_BREAK << (5+6))
+#define INST_SLOT0_MASK         (0x1ffffffffffL << 5)
+
+#define BKPTMODE_DATAR  3
+#define BKPTMODE_IO     2
+#define BKPTMODE_DATAW  1
+#define BKPTMODE_INST   0
+
+/* Some of the fault registers needed by kdb but not passed with
+ * regs or switch stack.
+ */
+typedef struct fault_regs {
+       unsigned long   isr ;
+       unsigned long   ifa ;
+       unsigned long   iim ;
+       unsigned long   itir ;
+} fault_regs_t ;
+
+/*
+ * Support for setjmp/longjmp
+ */
+
+/* __jmp_buf definition copied from libc/sysdeps/unix/sysv/linux/ia64/bits/setjmp.h */
+
+#define _JBLEN  70
+
+typedef struct __kdb_jmp_buf {
+       unsigned long   __jmp_buf[_JBLEN];
+} kdb_jmp_buf __attribute__ ((aligned (16)));
+
+extern int kdba_setjmp(kdb_jmp_buf *);
+extern void kdba_longjmp(kdb_jmp_buf *, int);
+#define kdba_setjmp kdba_setjmp
+
+extern kdb_jmp_buf *kdbjmpbuf;
+
+/* Arch specific data saved for running processes */
+
+struct kdba_running_process {
+       struct switch_stack *sw;
+};
+
+extern void kdba_save_running(struct kdba_running_process *, struct pt_regs *);
+extern void kdba_unsave_running(struct kdba_running_process *, struct pt_regs *);
+
+/* kdba wrappers which want to save switch stack will call unw_init_running().
+ * That routine only takes a void* so pack the interrupt data into a structure.
+ */
+
+#include <linux/interrupt.h>   /* for irqreturn_t */
+
+enum kdba_serial_console {
+       KDBA_SC_NONE = 0,
+       KDBA_SC_STANDARD,
+       KDBA_SC_SGI_L1,
+};
+
+extern enum kdba_serial_console kdba_serial_console;
+
+#define KDB_RUNNING_PROCESS_ORIGINAL kdb_running_process_save
+extern struct kdb_running_process *kdb_running_process_save; /* [NR_CPUS] */
+
+extern void kdba_wait_for_cpus(void);
+
+#endif /* !_ASM_KDBPRIVATE_H */
index 5d1658a..8d347d6 100644 (file)
@@ -22,7 +22,8 @@ D(9)  KM_IRQ0,
 D(10)  KM_IRQ1,
 D(11)  KM_SOFTIRQ0,
 D(12)  KM_SOFTIRQ1,
-D(13)  KM_TYPE_NR
+D(13)  KM_KDB,
+D(14)  KM_TYPE_NR
 };
 
 #undef D
index aefcdfe..cbb91e9 100644 (file)
@@ -72,7 +72,7 @@
 /* A mask of PSR bits that we generally don't want to inherit across a clone2() or an
    execve().  Only list flags here that need to be cleared/set for BOTH clone2() and
    execve().  */
-#define IA64_PSR_BITS_TO_CLEAR (IA64_PSR_MFL | IA64_PSR_MFH | IA64_PSR_DB | IA64_PSR_LP | \
+#define IA64_PSR_BITS_TO_CLEAR (IA64_PSR_MFL | IA64_PSR_MFH | IA64_PSR_LP | \
                                 IA64_PSR_TB  | IA64_PSR_ID  | IA64_PSR_DA | IA64_PSR_DD | \
                                 IA64_PSR_SS  | IA64_PSR_ED  | IA64_PSR_IA)
 #define IA64_PSR_BITS_TO_SET   (IA64_PSR_DFH | IA64_PSR_SP)
diff --git a/arch/ia64/kdb/ChangeLog b/arch/ia64/kdb/ChangeLog
new file mode 100644 (file)
index 0000000..a3b2d9b
--- /dev/null
@@ -0,0 +1,1063 @@
+2008-08-14 Jay Lan  <jlan@sgi.com>
+
+       * Support 'kdump' command to take a kdump vmcore from KDB,
+           Dan Aloni (da-x@monatomic.org),
+           Jason Xiao (jidong.xiao@gmail.com),
+           Jay Lan (jlan@sgi.com)
+       * kdb-v4.4-2.6.27-rc2-ia64-2.
+
+2008-08-06 Jay Lan  <jlan@sgi.com>
+
+       * Fix up the NULL pointer deference issue in ohci_kdb_poll_char,
+         Jason Xiao <jidong.xiao@gmail.com>
+       * kdb-v4.4-2.6.27-rc2-ia64-1.
+
+2008-07-18 Jay Lan  <jlan@sgi.com>
+
+       * support Hardware Breakpoint (bph/bpha) commands
+         IA64: Greg Banks <gnb@sgi.com>
+         X86:  Konstantin Baydarov <kbaidarov@ru.mvista.com>
+       * kdb-v4.4-2.6.26-ia64-2.
+
+2008-07-14 Jay Lan  <jlan@sgi.com>
+
+        * kdb-v4.4-2.6.26-ia64-1.
+
+2008-07-11 Jay Lan  <jlan@sgi.com>
+
+        * New commands and some fixups and enhancements,
+          Joe Korty <joe.korty@ccur.com>
+          John Blackwood <john.blackwood@ccur.com>
+          Jim Houston <jim.houston@ccur.com>
+          - Use the non-sleeping copy_from_user_atomic.
+          - Enhance kdb_cmderror diagnostic output.
+          - Expand the KDB 'duplicate command' error message.
+          - Touch NMI watchdog in various KDB busy-loops.
+          - Support IMB HS20 Blade 8843 platform.
+          - Display exactly which cpus needed an NMI to get them into kdb.
+          - Better document that kdb's 'ps A' command can be used to show
+            _all_ processes and threads
+          - Suppress KDB boottime INFO messages if quiet boot.
+          - Add a KDB breakpoint to the OOPs path.
+          - Add CONFIG_DISCONTIGMEM support to kdbm_memmap.
+          - Extend the KDB task command to handle CONFIG_NUMA fields.
+          - Extend the KDB vm command to support NUMA stuff.
+          - Create the KDB mempolicy command.
+          - Create a pgdat command for KDB.
+          - Fix a hang on boot on some i386 systems.
+        * kdb-v4.4-2.6.26-rc9-ia64-1.
+
+2008-06-30 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc8-ia64-1.
+
+2008-06-25 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc7-ia64-1.
+
+2008-06-06 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc5-ia64-1.
+
+2008-05-30 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc4-ia64-1.
+
+2008-05-20 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc3-ia64-1.
+
+2008-05-13 Jay Lan  <jlan@sgi.com>
+
+       * XPC support removed from KDB due to XPC changes to 2.6.26-rc1.
+        * kdb-v4.4-2.6.26-rc1-ia64-1.
+
+2008-04-17 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.25-ia64-1.
+
+2008-03-16 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.25-rc6-ia64-1.
+
+2008-03-03 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.25-rc3-ia64-1.
+
+2008-02-26 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.25-rc2-ia64-1.
+
+2008-02-19 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.25-rc1-ia64-1.
+
+2008-02-01 Jay Lan  <jlan@sgi.com>
+
+       * Backed out USB UHCI support since it caused dropped characters and
+          broke OHCI.
+       * Restored "archkdbcommon" commands for x86. It was lost at the x86
+         merge.
+       * Detecting if the HC was "busy", Aaron Young <ayoung@sgi.com>
+       * kdb-v4.4-2.6.24-ia64-2.
+
+2008-01-29 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.24-ia64-1.
+
+2008-01-22 Jay Lan  <jlan@sgi.com>
+
+       * USB UHCI kdb support, Konstantin Baydarov <kbaidarov@ru.mvista.com>
+       * kdb-v4.4-2.6.24-rc8-ia64-3.
+
+2008-01-18 Jay Lan  <jlan@sgi.com>
+
+       * USB EHCI kdb support,  Aaron Young <ayoung@sgi.com>
+       * kdb-v4.4-2.6.24-rc8-ia64-2.
+
+2008-01-18 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.24-rc8-ia64-1.
+
+2008-01-07 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.24-rc7-ia64-1.
+
+2007-12-21 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.24-rc6-ia64-1.
+
+2007-12-12 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.24-rc5-ia64-1.
+
+2007-12-05 Jay Lan  <jlan@sgi.com>
+
+       * Fixed a 'sysctl table check failed' problem.
+       * kdb v4.4-2.6.24-rc4-ia64-1.
+
+2007-11-26 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.24-rc3-ia64-1.
+
+2007-11-13 Jay Lan  <jlan@sgi.com>
+
+       * Back ported "New KDB USB interface" from Aaron Young in
+         v4.4-2.6.23-ia64-2 to 2.6.24 kdb patchset.
+       * kdb v4.4-2.6.24-rc2-ia64-2.
+
+2007-11-12 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.24-rc2-ia64-1.
+
+2007-11-09 Jay Lan  <jlan@sgi.com>
+
+       * Rebase to 2.6.24-rc1 kernel
+       *   - merged kdb-v4.4-2.6.23-i386-1 and kdb-v4.4-2.6.23-x86_64-1
+       *     into kdb-v4.4-2.6.24-rc1-x86-1
+       *   - Fields "done", "sglist_len", and "pid" are removed from
+       *     struct scsi_cmnd. Thus, these fields are no longer displayed
+       *     on "sc" command.
+       * kdb v4.4-2.6.24-rc1-ia64-1.
+
+2007-11-08 Jay Lan  <jlan@sgi.com>
+
+       * New KDB USB interface,  Aaron Young <ayoung@sgi.com>
+       *  1. This patch allows KDB to work with any Host Contoller driver
+       *     and call the correct HC driver poll routine (as long as the
+       *     HC driver provides a .kdb_poll_char routine via it's
+       *     associated hc_driver struct).
+       *  2. Hotplugged keyboards are now recognized by KDB.
+       *  3. Currently KDB can only make use of 1 USB type keyboard.
+       *     New code can handle up to 8 attached keyboards - input is
+       *     multiplexed from all of them while in kdb.
+       * kdb v4.4-2.6.23-ia64-2.
+
+2007-10-24 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-ia64-1.
+
+2007-09-26 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc8-ia64-1.
+
+2007-09-21 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc7-ia64-1.
+
+2007-09-19 Jay Lan  <jlan@sgi.com>
+
+       * Get into KDB successfully if multiple cpus are in MCA. <rja@sgi.com>
+       * kdb v4.4-2.6.23-rc6-ia64-2.
+
+2007-09-12 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc6-ia64-1.
+
+2007-09-06 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc5-ia64-1.
+
+2007-08-30 Keith Owens  <kaos@sgi.com>
+
+       * New i386/x86_64 backtrace requires that kdb_save_running() does not
+         exit until after kdb_main_loop() has completed.
+       * kdb v4.4-2.6.23-rc4-ia64-2.
+
+2007-08-30 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc4-ia64-1.
+
+2007-08-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.23-rc3-ia64-1.
+
+2007-08-07 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc2-ia64-1.
+
+2007-07-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.23-rc1-ia64-1.
+
+2007-07-09 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-ia64-1.
+
+2007-07-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc7-ia64-1.
+
+2007-06-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc5-ia64-1.
+
+2007-06-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc4-ia64-1.
+
+2007-05-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc3-ia64-1.
+
+2007-05-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc2-ia64-1.
+
+2007-05-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc1-ia64-1.
+
+2007-04-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-ia64-1.
+
+2007-04-16 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc7-ia64-1.
+
+2007-04-10 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc6-ia64-1.
+
+2007-04-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc5-ia64-1.
+
+2007-03-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc4-ia64-1.
+
+2007-03-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc3-ia64-1.
+
+2007-03-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc2-ia64-1.
+
+2007-03-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc1-ia64-1.
+
+2007-03-01 Keith Owens  <kaos@sgi.com>
+
+       * Remove sparse warnings.
+       * kdb v4.4-2.6.20-ia64-3.
+
+2007-02-16 Keith Owens  <kaos@sgi.com>
+
+       * Initialise variable bits of struct disassemble_info each time.
+       * kdb v4.4-2.6.20-ia64-2.
+
+2007-02-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-ia64-1.
+
+2007-02-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc7-ia64-1.
+
+2007-01-08 Keith Owens  <kaos@sgi.com>
+
+       * Detect calls via PLT and decode the target address.
+       * kdb v4.4-2.6.20-rc4-ia64-2.
+
+2007-01-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc4-ia64-1.
+
+2007-01-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc3-ia64-1.
+
+2006-12-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc1-ia64-1.
+
+2006-12-07 Keith Owens  <kaos@sgi.com>
+
+       * Export kdba_dumpregs.
+       * kdb v4.4-2.6.19-ia64-2.
+
+2006-11-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-ia64-1.
+
+2006-11-27 Keith Owens  <kaos@sgi.com>
+
+       * Only use VT keyboard if the command line allows it and ACPI indicates
+         that there is an i8042.
+       * kdb v4.4-2.6.19-rc6-ia64-2.
+
+2006-11-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc6-ia64-1.
+
+2006-11-09 Keith Owens  <kaos@sgi.com>
+
+       * Only use VT console if the command line allows it.
+       * kdb v4.4-2.6.19-rc5-ia64-2.
+
+2006-11-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc5-ia64-1.
+
+2006-11-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc4-ia64-1.
+
+2006-10-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc3-ia64-1.
+
+2006-10-24 Keith Owens  <kaos@sgi.com>
+
+       * Remove redundant regs and envp parameters.
+       * kdb v4.4-2.6.19-rc2-ia64-2.
+
+2006-10-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc2-ia64-1.
+
+2006-10-09 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc1-ia64-1.
+
+2006-10-06 Keith Owens  <kaos@sgi.com>
+
+       * Remove #include <linux/config.h>
+       * kdb v4.4-2.6.18-ia64-2.
+
+2006-09-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-ia64-1.
+
+2006-09-15 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc7-ia64-1.
+
+2006-08-29 Keith Owens  <kaos@sgi.com>
+
+       * Rewrite all backtrace code.
+       * kdb v4.4-2.6.18-rc5-ia64-2.
+
+2006-08-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc5-ia64-1.
+
+2006-08-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc4-ia64-1.
+
+2006-08-04 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc3-ia64-1.
+
+2006-07-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc2-ia64-1.
+
+2006-07-12 Keith Owens  <kaos@sgi.com>
+
+       * Remove dead KDB_REASON codes.
+       * sparse cleanups.
+       * kdb v4.4-2.6.18-rc1-ia64-2.
+
+2006-07-07 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc1-ia64-1.
+
+2006-07-04 Keith Owens  <kaos@sgi.com>
+
+       * Delete kdba_enable_lbr, kdba_disable_lbr, kdba_print_lbr,
+         page_fault_mca.  Only ever implemented on x86, difficult to maintain
+         and rarely used in the field.
+       * Replace #ifdef KDB_HAVE_LONGJMP with #ifdef kdba_setjmp.
+       * kdb v4.4-2.6.17-ia64-2.
+
+2006-06-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-ia64-1.
+
+2006-05-25 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc5-ia64-1.
+
+2006-05-15 Keith Owens  <kaos@sgi.com>
+
+       * Refresh bfd related files from binutils 2.16.91.0.2.
+       * kdb v4.4-2.6.17-rc4-ia64-2.
+
+2006-05-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc4-ia64-1.
+
+2006-04-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc3-ia64-1.
+
+2006-04-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc2-ia64-1.
+
+2006-04-11 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc1-ia64-1.
+
+2006-03-30 Keith Owens  <kaos@sgi.com>
+
+       * Change CONFIG_LKCD to CONFIG_LKCD_DUMP.
+       * kdb v4.4-2.6.16-ia64-3.
+
+2006-03-24 Keith Owens  <kaos@sgi.com>
+
+       * Use INIT to interrupt cpus that do not respond to a normal kdb IPI.
+       * Remove KDBA_MCA_TRACE from arch/ia64/kernel/mca.c.
+       * kdb v4.4-2.6.16-ia64-2.
+
+2006-03-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.16-ia64-1.
+
+2006-03-14 Nathan Scott  <nathans@sgi.com>
+
+       * kdb v4.4-2.6.16-rc6-ia64-1.
+
+2006-02-28 Nathan Scott  <nathans@sgi.com>
+
+       * kdb v4.4-2.6.16-rc5-ia64-1.
+
+2006-02-20 Nathan Scott  <nathans@sgi.com>
+
+       * kdb v4.4-2.6.16-rc4-ia64-1.
+
+2006-02-07 Keith Owens  <kaos@sgi.com>
+
+       * Change kdb_running_process_save from a static array to a pointer.
+         gcc 4.0 objects to forward declarations for arrays with an incomplete
+         type.
+       * kdb v4.4-2.6.16-rc2-ia64-3.
+
+2006-02-06 Keith Owens  <kaos@sgi.com>
+
+       * Change CONFIG_CRASH_DUMP to CONFIG_LKCD.
+       * kdb v4.4-2.6.16-rc2-ia64-2.
+
+2006-02-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.16-rc2-ia64-1.
+
+2006-02-01 Keith Owens  <kaos@sgi.com>
+
+       * Handlers: check that the task is in kernel space before looking at
+         the thread_info bits.
+       * Expose kdb_running_process_save[] so 'pid R' can get the original
+         process, even when the MCA/INIT handlers are being used.
+       * kdb v4.4-2.6.16-rc1-ia64-3.
+
+2006-01-19 Keith Owens  <kaos@sgi.com>
+
+       * Add back some kdb changes to xpc_main that were lost due to a patch
+         conflict.
+       * kdb v4.4-2.6.16-rc1-ia64-2.
+
+2006-01-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.16-rc1-ia64-1.
+
+2006-01-10 Keith Owens  <kaos@sgi.com>
+
+       * Build kdba_pod for generic as well as sn2 kernels and test at run
+         time if the platform is sn2.
+       * kdb v4.4-2.6.15-ia64-3.
+
+2006-01-08 Keith Owens  <kaos@sgi.com>
+
+       * Convert xpc to use DIE_KDEBUG_ENTER and DIE_KDEBUG_LEAVE.
+       * Add debug option for xpc.
+       * break.b always sets a debug trap number of 0 , so pass that to kdb as
+         well as the normal kdb traaps.
+       * kdb v4.4-2.6.15-ia64-2.
+
+2006-01-04 Keith Owens  <kaos@sgi.com>
+
+       * Remove some inlines and the last vestige of CONFIG_NUMA_REPLICATE.
+       * Read the keyboard acknowledgment after sending a character.  SuSE
+         Bugzilla 60240.
+       * kdb v4.4-2.6.15-ia64-1.
+
+2005-12-25 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc7-ia64-1.
+
+2005-12-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc6-ia64-1.
+
+2005-12-06 Keith Owens  <kaos@sgi.com>
+
+       * Use RECOVERY flag in MCA handler.
+       * kdb v4.4-2.6.15-rc5-ia64-2.
+
+2005-12-05 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc5-ia64-1.
+
+2005-12-02 Keith Owens  <kaos@sgi.com>
+
+       * Reinstate hook for debug trap, the patch chunk was accidentally
+         dropped in 2.6.15-rc1.
+       * kdb v4.4-2.6.15-rc4-ia64-1.
+
+2005-11-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc3-ia64-1.
+
+2005-11-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc2-ia64-1.
+
+2005-11-15 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc1-ia64-1.
+
+2005-10-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.14-ia64-1.
+
+2005-10-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.14-rc5-ia64-1.
+
+2005-10-11 Keith Owens  <kaos@sgi.com>
+
+       * Handle removal of USB keyboard.  Aaron Young, SGI
+       * kdb v4.4-2.6.14-rc4-ia64-1.
+
+2005-10-04 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.14-rc3-ia64-1.
+
+2005-09-21 Keith Owens  <kaos@sgi.com>
+
+       * Support kdb_current_task in register display and modify commands.
+       * kdb v4.4-2.6.14-rc2-ia64-1.
+
+2005-09-20 Keith Owens  <kaos@sgi.com>
+
+       * Coexist with kprobes.
+       * Coexist with MCA/INIT rewrite.
+       * Add KDB_ENTER_SLAVE to handle concurrent entry to kdb from multiple
+         cpus.
+       * Add handlers command to control whether the MCA/INIT task or the
+         original task is displayed.
+       * Namespace clean up, remove unused kdba_sw_interrupt.
+       * kdb v4.4-2.6.14-rc1-ia64-1.
+
+2005-08-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-ia64-1.
+
+2005-08-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc7-ia64-1.
+
+2005-08-08 Keith Owens  <kaos@sgi.com>
+
+       * Add minstate command.
+       * kdb v4.4-2.6.13-rc6-ia64-1.
+
+2005-08-02 Keith Owens  <kaos@sgi.com>
+
+       * Replace hard coded kdb declarations with #include <asm/sections>.
+       * kdb v4.4-2.6.13-rc5-ia64-1.
+
+2005-07-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc4-ia64-1.
+
+2005-07-22 Keith Owens  <kaos@sgi.com>
+
+       * Handle INIT delivered while in physical mode.
+       * kdb v4.4-2.6.13-rc3-ia64-2.
+
+2005-07-19 Keith Owens  <kaos@sgi.com>
+
+       * Add support for USB keyboard (OHCI only).  Aaron Young, SGI.
+       * kdb v4.4-2.6.13-rc3-ia64-1.
+
+2005-07-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc2-ia64-1.
+
+2005-07-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc1-ia64-1.
+
+2005-06-18 Keith Owens  <kaos@sgi.com>
+
+       * Standard IA64 code now works around break.b setting cr.iim to 0
+         instead of the break number.  Remove the kdb workaround.
+       * kdb v4.4-2.6.12-ia64-1.
+
+2005-06-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc6-ia64-1.
+
+2005-05-25 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc5-ia64-1.
+
+2005-05-24 Keith Owens  <kaos@sgi.com>
+
+       * break.b sets cr.iim to 0 instead of the break number.  Deal with it.
+       * kdb v4.4-2.6.12-rc4-ia64-3.
+
+2005-05-14 Keith Owens  <kaos@sgi.com>
+
+       * Correct MCA path after calling kdba_mca_bspstore_fixup().
+         Mark Larson, SGI.
+       * Tell the user that MCA/INIT is recoverable so kdb is not entered.
+       * kdb v4.4-2.6.12-rc4-ia64-2.
+
+2005-05-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc4-ia64-1.
+
+2005-04-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc3-ia64-1.
+
+2005-04-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc2-ia64-1.
+
+2005-04-04 Keith Owens  <kaos@sgi.com>
+
+       * More tweaks to cope with invalid old bspstore in MCA handler.
+       * kdb v4.4-2.6.12-rc1-ia64-2.
+
+2005-03-29 Keith Owens  <kaos@sgi.com>
+
+       * Replace __copy_to_user with __copy_to_user_inatomic.
+       * MCA handler, do not use old_bspstore if it is in region 4 or below.
+       * kdb v4.4-2.6.12-rc1-ia64-1.
+
+2005-03-08 Keith Owens  <kaos@sgi.com>
+
+       * Coexistence patches for lkcd.  Jason Uhlenkott, SGI.
+       * kdb v4.4-2.6.11-ia64-2.
+
+2005-03-03 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.11-ia64-1.
+
+2005-02-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.11-rc4-ia64-1.
+
+2005-02-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.11-rc3-bk4-ia64-1.
+
+2005-02-03 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.11-rc3-ia64-1.
+
+2005-01-27 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.11-rc2-ia64-1.
+
+2005-01-20 Keith Owens  <kaos@sgi.com>
+
+       * MCA and INIT stacks moved to per-cpu area.
+       * kdb-v4.4-2.6.11-rc1-bk7-ia64-1.
+
+2005-01-12 Keith Owens  <kaos@sgi.com>
+
+       * ia64_spinlock_contention_pre3_4_end is in base kernel, remove from kdb.
+       * Use last ditch allocator if unwind cannot allocate memory.
+       * kdb-v4.4-2.6.11-rc1-ia64-1.
+
+2004-12-25 Keith Owens  <kaos@sgi.com>
+
+       * Add cpuinfo command.
+       * kdb-v4.4-2.6.10-ia64-1.
+
+2004-12-07 Keith Owens  <kaos@sgi.com>
+
+       * Clean up error path in kdba_mca_init.
+       * kdb-v4.4-2.6.10-rc3-ia64-1.
+
+2004-11-15 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.10-rc2-ia64-1.
+
+2004-10-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.10-rc1-ia64-1.
+
+2004-10-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.9-ia64-1.
+
+2004-10-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.9-rc4-ia64-1.
+
+2004-10-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.9-rc3-ia64-1.
+
+2004-09-30 Keith Owens  <kaos@sgi.com>
+
+       * Add stackdepth command.
+       * kdb-v4.4-2.6.9-rc2-ia64-3.
+
+2004-09-16 Keith Owens  <kaos@sgi.com>
+
+       * Fixes for current in region 5 instead of 7 (idle task on cpu 0).
+       * kdb-v4.4-2.6.9-rc2-ia64-2.
+
+2004-09-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.9-rc2-ia64-1.
+
+2004-08-27 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.9-rc1-ia64-1.
+
+2004-08-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.8-ia64-1.
+
+2004-08-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.8-rc4-ia64-1.
+
+2004-08-04 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.8-rc3-ia64-1.
+
+2004-07-18 Keith Owens  <kaos@sgi.com>
+
+       * New config name for SN serial console.
+       * kdb-v4.4-2.6.8-rc2-ia64-1.
+
+2004-07-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.8-rc1-ia64-1.
+
+2004-06-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb-v4.4-2.6.7-ia64-040629-1.
+
+2004-06-16 Keith Owens  <kaos@sgi.com>
+
+       * Coexist with 2.6.7-ia64-040619.
+       * kdb-v4.4-2.6.7-ia64-040619-1.
+
+2004-06-16 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.7-ia64-1.
+
+2004-06-10 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.7-rc3-ia64-1.
+
+2004-06-09 Keith Owens  <kaos@sgi.com>
+
+       * Namespace clean up.  Mark code/variables as static when it is only
+         used in one file, delete dead code/variables.
+       * Saved interrupt state requires long, not int.
+       * kdb v4.4-2.6.7-rc2-ia64-3.
+
+2004-06-08 Keith Owens  <kaos@sgi.com>
+
+       * Whitespace clean up, no code changes.
+       * kdb v4.4-2.6.7-rc2-2.
+
+2004-06-07 Keith Owens  <kaos@sgi.com>
+
+       * Force KALLSYMS and KALLSYMS_ALL for CONFIG_KDB.
+       * kdb v4.4-2.6.7-rc2-1.
+
+2004-06-06 Keith Owens  <kaos@sgi.com>
+
+       * Add standard archkdb commands.
+       * Move kdb_{get,put}userarea_size definitions to linux/kdb.h.
+       * kdb v4.4-2.6.6-ia64-040521-2.
+
+2004-05-25 Keith Owens  <kaos@sgi.com>
+
+       * Update Kconfig text.
+       * kdb v4.4-2.6.6-ia64-040521-1.
+
+2004-05-23 Keith Owens  <kaos@sgi.com>
+
+       * Move bfd.h and ansidecl.h from arch/$(ARCH)/kdb to include/asm-$(ARCH).
+       * ia64-opc.c needs kdbprivate.h after common reorganisation.
+       * Update copyright notices.
+       * kdb v4.4-2.6.6-ia64-1.
+
+2004-05-60 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.6-rc3-ia64-1.
+
+2004-05-60 Keith Owens  <kaos@sgi.com>
+
+       * Tweak WAR for backtrace through contended spinlocks.
+       * kdb v4.3-2.6.6-rc2-ia64-1.
+
+2004-04-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.6-rc1-ia64-1.
+
+2004-04-15 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.5-ia64-040413-1.
+
+2004-03-06 Keith Owens  <kaos@sgi.com>
+
+       * Use kdb_print for unwind debugging.
+       * kdb v4.3-2.6.4-rc2-ia64-1.
+
+2004-02-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.4-rc1-ia64-1.
+
+2004-02-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.3-ia64-1.
+
+2004-02-17 Keith Owens  <kaos@sgi.com>
+
+       * Reconcile 2.6-test versions from Xavier Bru (Bull), Greg Banks (SGI),
+         Jim Houston (Concurrent Computer Corp).
+       * Reconcile with kdb v4.3-2.4.23-ia64-0312??-1.
+       * Reconcile with salinfo changes.
+       * Port WAR for backtrace from spinlock contention from 2.4 to 2.6.
+       * Merge PGS FIFO tweak with SERIAL_IO_MEM and concurrent support for
+         multiple consoles (no USB consoles yet).
+       * Update pt_regs output to match the order of struct pt_regs.
+       * KDB wrappers for interrupts handlers now return the handler's return code.
+       * tpa and tpav commands from Anonymous.
+       * Reconcile with mca changes.
+       * Upgrade to 2.6.3-rc3.
+       * kdb v4.3-2.6.3-rc3-ia64-1.
+
+2003-10-22 Xavier Bru   <xavier.bru@bull.net>
+       * Merge to 2.6.0-test7
+2003-10-20 Philippe Garrigues <Philippe.Garrigues@bull.net>
+       * Enable FIFO in UART
+2003-09-08 Xavier Bru   <xavier.bru@bull.net>
+       * Merge to 2.6.0-test4
+2003-03-21 Xavier Bru <xavier.bru@bull.net>
+       * Merge kdb v4.0 on 2.5.64 ia64
+       * new kernel parameters support
+       * new kallsyms support
+
+2003-10-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.4.23-pre8-cset-1.1069.1.143-to-1.1108-ia64-1.
+
+2003-10-03 Keith Owens  <kaos@sgi.com>
+
+       * After MCA, copy the saved RSE registers from ia64_mca_bspstore to the
+         stack of the failing process.
+       * Abort backtrace when we hit IVT, no unwind data which confuses
+         unw_unwind().
+       * Workaround for backtrace through spinlock contention called from leaf
+         functions.
+       * kdb v4.3-2.4.22-ia64-030909-1.
+
+2003-07-20 Keith Owens  <kaos@sgi.com>
+
+       * MCA rendezvous timeout affects kdb_wait_for_cpus_secs.
+       * Support SGI L1 console.
+       * kdb v4.3-2.4.21-ia64-030702-2.
+
+2003-07-08 Keith Owens  <kaos@sgi.com>
+
+       * print_symbol() in mca.c does something useful when kdb is installed.
+       * Unwind and SAL changes removed from kdb, they are in the base kernel.
+       * kdb v4.3-2.4.21-ia64-030702-1.
+
+2003-06-20 Keith Owens  <kaos@sgi.com>
+
+       * Add CONFIG_KDB_CONTINUE_CATASTROPHIC.
+       * Do not send IPI if the machine state does not require them.
+       * Correct definition of KDB_ENTER().
+       * Workaround for broken init monarch handler.
+       * Monarch cpu must get to kdb, even if it was interrupted in user space.
+       * Unwind fixes.
+       * Generalize ia64_spinlock_contention name.
+       * Add kdba_fru for SN machines.
+       * Correct test for cpu number.
+       * kdb v4.3-2.4.20-ia64-020821-1.
+
+2003-05-02 Keith Owens  <kaos@sgi.com>
+
+       * Add kdba_fp_value().
+       * Limit backtrace size to catch loops.
+       * Print spinlock name in ia64_spinlock_contention.
+       * Tweak INIT slave stack lock and handler.
+       * Add read/write access to user pages.  Vamsi Krishna S., IBM
+       * Rename cpu_is_online to cpu_online, as in 2.5.
+       * Clean up USB keyboard support.
+       * Clean up serial console support.
+       * kdb v4.2-2.4.20-ia64-020821-1.
+
+2003-04-04 Keith Owens  <kaos@sgi.com>
+
+       * Add support for INIT slave interrupts.
+       * Tell SAL to always rendezvous on MCA.
+       * No lock on SAL rendezvous call.
+       * Include unwind.c from 2.4.21-pre5.
+       * Rename cpu_online to cpu_is_online.
+       * Workarounds for scheduler bugs.
+       * kdb v4.1-2.4.20-ia64-020821-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 support for MCA events (both main and rendezvous) plus INIT
+         monarch event.
+       * Correct decode of brl.
+       * Move kdba_print_nameval to common code.
+       * Generalize kdba unwind handlers.
+       * Fix decode of sal records (fix included in later ia64 kernels).
+       * Handle multiple pt_regs in stack (fix included in later ia64 kernels).
+       * Clean up debug code in unwind (fix included in later ia64 kernels).
+       * Move kdb break numbers to their own file so it can be used in asm.
+       * kdb v4.0-2.4.20-ia64-021210-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.
+       * Add commands to dump struct pt_regs and switch_stack.
+       * Handle padding from unw_init_running for switch_stack.
+       * Add dummy kdba_local_arch_setup/kdba_local_arch_cleanup.
+       * Warning for pod mode.
+       * 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-ia64-021210-1.
+
+2003-01-23 Keith Owens  <kaos@sgi.com>
+
+       * Upgrade to 2.4.20-ia64-021210.
+       * kdb v2.5-2.4.20-ia64-021210-1.
+
+2002-11-14 Keith Owens  <kaos@sgi.com>
+
+       * General clean up of handling for breakpoints and single stepping over
+         software breakpoints.
+       * kdb v2.5-2.4.19-ia64-020821-1.
+
+2002-10-31 Keith Owens  <kaos@sgi.com>
+
+       * Remove kdb_eframe_t.
+       * Sanity check if we have pt_regs.
+       * Remove kdba_getcurrentframe().
+       * Comments for coexistence with O(1) scheduler.
+       * kdb v2.4-2.4.19-ia64-020821-1.
+
+2002-10-15 Keith Owens  <kaos@sgi.com>
+
+       * Minimize differences between patches for 2.4 and 2.5 kernels.
+       * kdb v2.3-2.4.19-ia64-020821-2.
+
+2002-08-10 Keith Owens  <kaos@sgi.com>
+
+       * Verify rw address for instruction breakpoint.
+       * Replace kdb_port with kdb_serial to support memory mapped I/O.
+         David Mosberger.
+         Note: This needs kdb v2.3-2.4.18-common-2 or later.
+       * kdb v2.3-2.4.18-ia64-020722-2.
+
+2002-08-07 Keith Owens  <kaos@sgi.com>
+
+       * Upgrade to 2.4.18-ia64-020722.
+       * Remove individual SGI copyrights, the general SGI copyright applies.
+       * Clean up disassembly layout.  Hugh Dickins, Keith Owens.
+       * Remove fixed KDB_MAX_COMMANDS size.
+       * Add set_fs() around __copy_to_user on kernel addresses.
+         Randolph Chung.
+       * Position ia64 for CONFIG_NUMA_REPLICATE.
+       * Stacked registers modification support.  Sebastien Lelarge.
+       * USB keyboard support.  Sebastien Lelarge.
+       * kdb v2.3-2.4.18-ia64-020722-1.
+
+2002-03-20 Keith Owens  <kaos@sgi.com>
+
+       * Sync with 2.4.17-sn2.
+       * Add pod command.
+
+2002-02-20 Keith Owens  <kaos@sgi.com>
+
+       * Call kdb from mca handler.  Jenna S. Hall, Intel.
+       * kdb v2.1-2.4.17-ia64-011226-2.
+
+2002-01-18 Keith Owens  <kaos@sgi.com>
+
+       * Replace kdb_get/putword with kdb_get/putarea functions.
+       * Wrap kdb references in #ifdef CONFIG_KDB.
+       * Delete sample i386 code.
+       * Refuse to update kernel text on NUMA systems.
+       * Reject hardware breakpoints, not supported yet.
+       * kdb v2.1-2.4.17-ia64-011226-1.
+
+2002-01-07 Keith Owens  <kaos@sgi.com>
+
+       * Split kdb for ia64 as kdb v2.0-2.4.17-ia64-011226-1.
diff --git a/arch/ia64/kdb/Makefile b/arch/ia64/kdb/Makefile
new file mode 100644 (file)
index 0000000..bc0ab60
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+#
+
+obj-y   := kdba_bt.o kdba_bp.o kdba_io.o kdba_support.o \
+           cpu-ia64-opc.o ia64-dis.o ia64-opc.o kdba_id.o kdba_jmp.o
+
+# fru does not compile on 2.6.
+# obj-$(CONFIG_IA64_SGI_SN2) += kdba_fru.o
+obj-$(CONFIG_IA64_SGI_SN2) += kdba_pod.o
+obj-$(CONFIG_IA64_GENERIC) += kdba_pod.o
+
+override CFLAGS := $(CFLAGS:%-pg=% )
+
+AFLAGS_kdba_jmp.o += $(AFLAGS_KERNEL)
+
+USE_STANDARD_AS_RULE   := true
diff --git a/arch/ia64/kdb/cpu-ia64-opc.c b/arch/ia64/kdb/cpu-ia64-opc.c
new file mode 100644 (file)
index 0000000..8cba8fe
--- /dev/null
@@ -0,0 +1,598 @@
+/* Copyright 1998, 1999, 2000, 2001, 2002, 2003
+   Free Software Foundation, Inc.
+   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+/* Logically, this code should be part of libopcode but since some of
+   the operand insertion/extraction functions help bfd to implement
+   relocations, this code is included as part of cpu-ia64.c.  This
+   avoids circular dependencies between libopcode and libbfd and also
+   obviates the need for applications to link in libopcode when all
+   they really want is libbfd.
+
+   --davidm Mon Apr 13 22:14:02 1998 */
+
+#ifdef __KERNEL__
+#include "ia64-opc.h"
+#else  /* __KERNEL__ */
+#include "../opcodes/ia64-opc.h"
+#endif /* __KERNEL__ */
+
+#define NELEMS(a)  ((int) (sizeof (a) / sizeof ((a)[0])))
+
+static const char*
+ins_rsvd (const struct ia64_operand *self ATTRIBUTE_UNUSED,
+         ia64_insn value ATTRIBUTE_UNUSED, ia64_insn *code ATTRIBUTE_UNUSED)
+{
+  return "internal error---this shouldn't happen";
+}
+
+static const char*
+ext_rsvd (const struct ia64_operand *self ATTRIBUTE_UNUSED,
+         ia64_insn code ATTRIBUTE_UNUSED, ia64_insn *valuep ATTRIBUTE_UNUSED)
+{
+  return "internal error---this shouldn't happen";
+}
+
+static const char*
+ins_const (const struct ia64_operand *self ATTRIBUTE_UNUSED,
+          ia64_insn value ATTRIBUTE_UNUSED, ia64_insn *code ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+static const char*
+ext_const (const struct ia64_operand *self ATTRIBUTE_UNUSED,
+          ia64_insn code ATTRIBUTE_UNUSED, ia64_insn *valuep ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+static const char*
+ins_reg (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  if (value >= 1u << self->field[0].bits)
+    return "register number out of range";
+
+  *code |= value << self->field[0].shift;
+  return 0;
+}
+
+static const char*
+ext_reg (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  *valuep = ((code >> self->field[0].shift)
+            & ((1u << self->field[0].bits) - 1));
+  return 0;
+}
+
+static const char*
+ins_immu (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  ia64_insn new = 0;
+  int i;
+
+  for (i = 0; i < NELEMS (self->field) && self->field[i].bits; ++i)
+    {
+      new |= ((value & ((((ia64_insn) 1) << self->field[i].bits) - 1))
+             << self->field[i].shift);
+      value >>= self->field[i].bits;
+    }
+  if (value)
+    return "integer operand out of range";
+
+  *code |= new;
+  return 0;
+}
+
+static const char*
+ext_immu (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  BFD_HOST_U_64_BIT value = 0;
+  int i, bits = 0, total = 0;
+
+  for (i = 0; i < NELEMS (self->field) && self->field[i].bits; ++i)
+    {
+      bits = self->field[i].bits;
+      value |= ((code >> self->field[i].shift)
+               & ((((BFD_HOST_U_64_BIT) 1) << bits) - 1)) << total;
+      total += bits;
+    }
+  *valuep = value;
+  return 0;
+}
+
+static const char*
+ins_immus8 (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  if (value & 0x7)
+    return "value not an integer multiple of 8";
+  return ins_immu (self, value >> 3, code);
+}
+
+static const char*
+ext_immus8 (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  const char *result;
+
+  result = ext_immu (self, code, valuep);
+  if (result)
+    return result;
+
+  *valuep = *valuep << 3;
+  return 0;
+}
+
+static const char*
+ins_imms_scaled (const struct ia64_operand *self, ia64_insn value,
+                ia64_insn *code, int scale)
+{
+  BFD_HOST_64_BIT svalue = value, sign_bit = 0;
+  ia64_insn new = 0;
+  int i;
+
+  svalue >>= scale;
+
+  for (i = 0; i < NELEMS (self->field) && self->field[i].bits; ++i)
+    {
+      new |= ((svalue & ((((ia64_insn) 1) << self->field[i].bits) - 1))
+             << self->field[i].shift);
+      sign_bit = (svalue >> (self->field[i].bits - 1)) & 1;
+      svalue >>= self->field[i].bits;
+    }
+  if ((!sign_bit && svalue != 0) || (sign_bit && svalue != -1))
+    return "integer operand out of range";
+
+  *code |= new;
+  return 0;
+}
+
+static const char*
+ext_imms_scaled (const struct ia64_operand *self, ia64_insn code,
+                ia64_insn *valuep, int scale)
+{
+  int i, bits = 0, total = 0;
+  BFD_HOST_64_BIT val = 0, sign;
+
+  for (i = 0; i < NELEMS (self->field) && self->field[i].bits; ++i)
+    {
+      bits = self->field[i].bits;
+      val |= ((code >> self->field[i].shift)
+             & ((((BFD_HOST_U_64_BIT) 1) << bits) - 1)) << total;
+      total += bits;
+    }
+  /* sign extend: */
+  sign = (BFD_HOST_64_BIT) 1 << (total - 1);
+  val = (val ^ sign) - sign;
+
+  *valuep = (val << scale);
+  return 0;
+}
+
+static const char*
+ins_imms (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  return ins_imms_scaled (self, value, code, 0);
+}
+
+static const char*
+ins_immsu4 (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  value = ((value & 0xffffffff) ^ 0x80000000) - 0x80000000;
+
+  return ins_imms_scaled (self, value, code, 0);
+}
+
+static const char*
+ext_imms (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  return ext_imms_scaled (self, code, valuep, 0);
+}
+
+static const char*
+ins_immsm1 (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  --value;
+  return ins_imms_scaled (self, value, code, 0);
+}
+
+static const char*
+ins_immsm1u4 (const struct ia64_operand *self, ia64_insn value,
+             ia64_insn *code)
+{
+  value = ((value & 0xffffffff) ^ 0x80000000) - 0x80000000;
+
+  --value;
+  return ins_imms_scaled (self, value, code, 0);
+}
+
+static const char*
+ext_immsm1 (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  const char *res = ext_imms_scaled (self, code, valuep, 0);
+
+  ++*valuep;
+  return res;
+}
+
+static const char*
+ins_imms1 (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  return ins_imms_scaled (self, value, code, 1);
+}
+
+static const char*
+ext_imms1 (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  return ext_imms_scaled (self, code, valuep, 1);
+}
+
+static const char*
+ins_imms4 (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  return ins_imms_scaled (self, value, code, 4);
+}
+
+static const char*
+ext_imms4 (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  return ext_imms_scaled (self, code, valuep, 4);
+}
+
+static const char*
+ins_imms16 (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  return ins_imms_scaled (self, value, code, 16);
+}
+
+static const char*
+ext_imms16 (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  return ext_imms_scaled (self, code, valuep, 16);
+}
+
+static const char*
+ins_cimmu (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  ia64_insn mask = (((ia64_insn) 1) << self->field[0].bits) - 1;
+  return ins_immu (self, value ^ mask, code);
+}
+
+static const char*
+ext_cimmu (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  const char *result;
+  ia64_insn mask;
+
+  mask = (((ia64_insn) 1) << self->field[0].bits) - 1;
+  result = ext_immu (self, code, valuep);
+  if (!result)
+    {
+      mask = (((ia64_insn) 1) << self->field[0].bits) - 1;
+      *valuep ^= mask;
+    }
+  return result;
+}
+
+static const char*
+ins_cnt (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  --value;
+  if (value >= ((BFD_HOST_U_64_BIT) 1) << self->field[0].bits)
+    return "count out of range";
+
+  *code |= value << self->field[0].shift;
+  return 0;
+}
+
+static const char*
+ext_cnt (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  *valuep = ((code >> self->field[0].shift)
+            & ((((BFD_HOST_U_64_BIT) 1) << self->field[0].bits) - 1)) + 1;
+  return 0;
+}
+
+static const char*
+ins_cnt2b (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  --value;
+
+  if (value > 2)
+    return "count must be in range 1..3";
+
+  *code |= value << self->field[0].shift;
+  return 0;
+}
+
+static const char*
+ext_cnt2b (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  *valuep = ((code >> self->field[0].shift) & 0x3) + 1;
+  return 0;
+}
+
+static const char*
+ins_cnt2c (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  switch (value)
+    {
+    case 0:    value = 0; break;
+    case 7:    value = 1; break;
+    case 15:   value = 2; break;
+    case 16:   value = 3; break;
+    default:   return "count must be 0, 7, 15, or 16";
+    }
+  *code |= value << self->field[0].shift;
+  return 0;
+}
+
+static const char*
+ext_cnt2c (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  ia64_insn value;
+
+  value = (code >> self->field[0].shift) & 0x3;
+  switch (value)
+    {
+    case 0: value =  0; break;
+    case 1: value =  7; break;
+    case 2: value = 15; break;
+    case 3: value = 16; break;
+    }
+  *valuep = value;
+  return 0;
+}
+
+static const char*
+ins_inc3 (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
+{
+  BFD_HOST_64_BIT val = value;
+  BFD_HOST_U_64_BIT sign = 0;
+
+  if (val < 0)
+    {
+      sign = 0x4;
+      value = -value;
+    }
+  switch (value)
+    {
+    case  1:   value = 3; break;
+    case  4:   value = 2; break;
+    case  8:   value = 1; break;
+    case 16:   value = 0; break;
+    default:   return "count must be +/- 1, 4, 8, or 16";
+    }
+  *code |= (sign | value) << self->field[0].shift;
+  return 0;
+}
+
+static const char*
+ext_inc3 (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
+{
+  BFD_HOST_64_BIT val;
+  int negate;
+
+  val = (code >> self->field[0].shift) & 0x7;
+  negate = val & 0x4;
+  switch (val & 0x3)
+    {
+    case 0: val = 16; break;
+    case 1: val =  8; break;
+    case 2: val =  4; break;
+    case 3: val =  1; break;
+    }
+  if (negate)
+    val = -val;
+
+  *valuep = val;
+  return 0;
+}
+
+#define CST    IA64_OPND_CLASS_CST
+#define REG    IA64_OPND_CLASS_REG
+#define IND    IA64_OPND_CLASS_IND
+#define ABS    IA64_OPND_CLASS_ABS
+#define REL    IA64_OPND_CLASS_REL
+
+#define SDEC   IA64_OPND_FLAG_DECIMAL_SIGNED
+#define UDEC   IA64_OPND_FLAG_DECIMAL_UNSIGNED
+
+const struct ia64_operand elf64_ia64_operands[IA64_OPND_COUNT] =
+  {
+    /* constants: */
+    { CST, ins_const, ext_const, "NIL",                {{ 0, 0}}, 0, "<none>" },
+    { CST, ins_const, ext_const, "ar.csd",     {{ 0, 0}}, 0, "ar.csd" },
+    { CST, ins_const, ext_const, "ar.ccv",     {{ 0, 0}}, 0, "ar.ccv" },
+    { CST, ins_const, ext_const, "ar.pfs",     {{ 0, 0}}, 0, "ar.pfs" },
+    { CST, ins_const, ext_const, "1",          {{ 0, 0}}, 0, "1" },
+    { CST, ins_const, ext_const, "8",          {{ 0, 0}}, 0, "8" },
+    { CST, ins_const, ext_const, "16",         {{ 0, 0}}, 0, "16" },
+    { CST, ins_const, ext_const, "r0",         {{ 0, 0}}, 0, "r0" },
+    { CST, ins_const, ext_const, "ip",         {{ 0, 0}}, 0, "ip" },
+    { CST, ins_const, ext_const, "pr",         {{ 0, 0}}, 0, "pr" },
+    { CST, ins_const, ext_const, "pr.rot",     {{ 0, 0}}, 0, "pr.rot" },
+    { CST, ins_const, ext_const, "psr",                {{ 0, 0}}, 0, "psr" },
+    { CST, ins_const, ext_const, "psr.l",      {{ 0, 0}}, 0, "psr.l" },
+    { CST, ins_const, ext_const, "psr.um",     {{ 0, 0}}, 0, "psr.um" },
+
+    /* register operands: */
+    { REG, ins_reg,   ext_reg, "ar", {{ 7, 20}}, 0,            /* AR3 */
+      "an application register" },
+    { REG, ins_reg,   ext_reg,  "b", {{ 3,  6}}, 0,            /* B1 */
+      "a branch register" },
+    { REG, ins_reg,   ext_reg,  "b", {{ 3, 13}}, 0,            /* B2 */
+      "a branch register"},
+    { REG, ins_reg,   ext_reg, "cr", {{ 7, 20}}, 0,            /* CR */
+      "a control register"},
+    { REG, ins_reg,   ext_reg,  "f", {{ 7,  6}}, 0,            /* F1 */
+      "a floating-point register" },
+    { REG, ins_reg,   ext_reg,  "f", {{ 7, 13}}, 0,            /* F2 */
+      "a floating-point register" },
+    { REG, ins_reg,   ext_reg,  "f", {{ 7, 20}}, 0,            /* F3 */
+      "a floating-point register" },
+    { REG, ins_reg,   ext_reg,  "f", {{ 7, 27}}, 0,            /* F4 */
+      "a floating-point register" },
+    { REG, ins_reg,   ext_reg,  "p", {{ 6,  6}}, 0,            /* P1 */
+      "a predicate register" },
+    { REG, ins_reg,   ext_reg,  "p", {{ 6, 27}}, 0,            /* P2 */
+      "a predicate register" },
+    { REG, ins_reg,   ext_reg,  "r", {{ 7,  6}}, 0,            /* R1 */
+      "a general register" },
+    { REG, ins_reg,   ext_reg,  "r", {{ 7, 13}}, 0,            /* R2 */
+      "a general register" },
+    { REG, ins_reg,   ext_reg,  "r", {{ 7, 20}}, 0,            /* R3 */
+      "a general register" },
+    { REG, ins_reg,   ext_reg,  "r", {{ 2, 20}}, 0,            /* R3_2 */
+      "a general register r0-r3" },
+
+    /* indirect operands: */
+    { IND, ins_reg,   ext_reg, "cpuid", {{7, 20}}, 0,          /* CPUID_R3 */
+      "a cpuid register" },
+    { IND, ins_reg,   ext_reg, "dbr",   {{7, 20}}, 0,          /* DBR_R3 */
+      "a dbr register" },
+    { IND, ins_reg,   ext_reg, "dtr",   {{7, 20}}, 0,          /* DTR_R3 */
+      "a dtr register" },
+    { IND, ins_reg,   ext_reg, "itr",   {{7, 20}}, 0,          /* ITR_R3 */
+      "an itr register" },
+    { IND, ins_reg,   ext_reg, "ibr",   {{7, 20}}, 0,          /* IBR_R3 */
+      "an ibr register" },
+    { IND, ins_reg,   ext_reg, "",      {{7, 20}}, 0,          /* MR3 */
+      "an indirect memory address" },
+    { IND, ins_reg,   ext_reg, "msr",   {{7, 20}}, 0,          /* MSR_R3 */
+      "an msr register" },
+    { IND, ins_reg,   ext_reg, "pkr",   {{7, 20}}, 0,          /* PKR_R3 */
+      "a pkr register" },
+    { IND, ins_reg,   ext_reg, "pmc",   {{7, 20}}, 0,          /* PMC_R3 */
+      "a pmc register" },
+    { IND, ins_reg,   ext_reg, "pmd",   {{7, 20}}, 0,          /* PMD_R3 */
+      "a pmd register" },
+    { IND, ins_reg,   ext_reg, "rr",    {{7, 20}}, 0,          /* RR_R3 */
+      "an rr register" },
+
+    /* immediate operands: */
+    { ABS, ins_cimmu, ext_cimmu, 0, {{ 5, 20 }}, UDEC,         /* CCNT5 */
+      "a 5-bit count (0-31)" },
+    { ABS, ins_cnt,   ext_cnt,   0, {{ 2, 27 }}, UDEC,         /* CNT2a */
+      "a 2-bit count (1-4)" },
+    { ABS, ins_cnt2b, ext_cnt2b, 0, {{ 2, 27 }}, UDEC,         /* CNT2b */
+      "a 2-bit count (1-3)" },
+    { ABS, ins_cnt2c, ext_cnt2c, 0, {{ 2, 30 }}, UDEC,         /* CNT2c */
+      "a count (0, 7, 15, or 16)" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 5, 14}}, UDEC,          /* CNT5 */
+      "a 5-bit count (0-31)" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 6, 27}}, UDEC,          /* CNT6 */
+      "a 6-bit count (0-63)" },
+    { ABS, ins_cimmu, ext_cimmu, 0, {{ 6, 20}}, UDEC,          /* CPOS6a */
+      "a 6-bit bit pos (0-63)" },
+    { ABS, ins_cimmu, ext_cimmu, 0, {{ 6, 14}}, UDEC,          /* CPOS6b */
+      "a 6-bit bit pos (0-63)" },
+    { ABS, ins_cimmu, ext_cimmu, 0, {{ 6, 31}}, UDEC,          /* CPOS6c */
+      "a 6-bit bit pos (0-63)" },
+    { ABS, ins_imms,  ext_imms,  0, {{ 1, 36}}, SDEC,          /* IMM1 */
+      "a 1-bit integer (-1, 0)" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 2, 13}}, UDEC,          /* IMMU2 */
+      "a 2-bit unsigned (0-3)" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 7, 13}}, 0,             /* IMMU7a */
+      "a 7-bit unsigned (0-127)" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 7, 20}}, 0,             /* IMMU7b */
+      "a 7-bit unsigned (0-127)" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 7, 13}}, UDEC,          /* SOF */
+      "a frame size (register count)" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 7, 20}}, UDEC,          /* SOL */
+      "a local register count" },
+    { ABS, ins_immus8,ext_immus8,0, {{ 4, 27}}, UDEC,          /* SOR */
+      "a rotating register count (integer multiple of 8)" },
+    { ABS, ins_imms,  ext_imms,  0,                            /* IMM8 */
+      {{ 7, 13}, { 1, 36}}, SDEC,
+      "an 8-bit integer (-128-127)" },
+    { ABS, ins_immsu4,  ext_imms,  0,                          /* IMM8U4 */
+      {{ 7, 13}, { 1, 36}}, SDEC,
+      "an 8-bit signed integer for 32-bit unsigned compare (-128-127)" },
+    { ABS, ins_immsm1,  ext_immsm1,  0,                                /* IMM8M1 */
+      {{ 7, 13}, { 1, 36}}, SDEC,
+      "an 8-bit integer (-127-128)" },
+    { ABS, ins_immsm1u4,  ext_immsm1,  0,                      /* IMM8M1U4 */
+      {{ 7, 13}, { 1, 36}}, SDEC,
+      "an 8-bit integer for 32-bit unsigned compare (-127-(-1),1-128,0x100000000)" },
+    { ABS, ins_immsm1,  ext_immsm1,  0,                                /* IMM8M1U8 */
+      {{ 7, 13}, { 1, 36}}, SDEC,
+      "an 8-bit integer for 64-bit unsigned compare (-127-(-1),1-128,0x10000000000000000)" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 2, 33}, { 7, 20}}, 0,   /* IMMU9 */
+      "a 9-bit unsigned (0-511)" },
+    { ABS, ins_imms,  ext_imms,  0,                            /* IMM9a */
+      {{ 7,  6}, { 1, 27}, { 1, 36}}, SDEC,
+      "a 9-bit integer (-256-255)" },
+    { ABS, ins_imms,  ext_imms, 0,                             /* IMM9b */
+      {{ 7, 13}, { 1, 27}, { 1, 36}}, SDEC,
+      "a 9-bit integer (-256-255)" },
+    { ABS, ins_imms,  ext_imms, 0,                             /* IMM14 */
+      {{ 7, 13}, { 6, 27}, { 1, 36}}, SDEC,
+      "a 14-bit integer (-8192-8191)" },
+    { ABS, ins_imms1, ext_imms1, 0,                            /* IMM17 */
+      {{ 7,  6}, { 8, 24}, { 1, 36}}, 0,
+      "a 17-bit integer (-65536-65535)" },
+    { ABS, ins_immu,  ext_immu,  0, {{20,  6}, { 1, 36}}, 0,   /* IMMU21 */
+      "a 21-bit unsigned" },
+    { ABS, ins_imms,  ext_imms,  0,                            /* IMM22 */
+      {{ 7, 13}, { 9, 27}, { 5, 22}, { 1, 36}}, SDEC,
+      "a 22-bit signed integer" },
+    { ABS, ins_immu,  ext_immu,  0,                            /* IMMU24 */
+      {{21,  6}, { 2, 31}, { 1, 36}}, 0,
+      "a 24-bit unsigned" },
+    { ABS, ins_imms16,ext_imms16,0, {{27,  6}, { 1, 36}}, 0,   /* IMM44 */
+      "a 44-bit unsigned (least 16 bits ignored/zeroes)" },
+    { ABS, ins_rsvd,  ext_rsvd,        0, {{0,  0}}, 0,                /* IMMU62 */
+      "a 62-bit unsigned" },
+    { ABS, ins_rsvd,  ext_rsvd,        0, {{0,  0}}, 0,                /* IMMU64 */
+      "a 64-bit unsigned" },
+    { ABS, ins_inc3,  ext_inc3,  0, {{ 3, 13}}, SDEC,          /* INC3 */
+      "an increment (+/- 1, 4, 8, or 16)" },
+    { ABS, ins_cnt,   ext_cnt,   0, {{ 4, 27}}, UDEC,          /* LEN4 */
+      "a 4-bit length (1-16)" },
+    { ABS, ins_cnt,   ext_cnt,   0, {{ 6, 27}}, UDEC,          /* LEN6 */
+      "a 6-bit length (1-64)" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 4, 20}},        0,              /* MBTYPE4 */
+      "a mix type (@rev, @mix, @shuf, @alt, or @brcst)" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 8, 20}},        0,              /* MBTYPE8 */
+      "an 8-bit mix type" },
+    { ABS, ins_immu,  ext_immu,  0, {{ 6, 14}}, UDEC,          /* POS6 */
+      "a 6-bit bit pos (0-63)" },
+    { REL, ins_imms4, ext_imms4, 0, {{ 7,  6}, { 2, 33}}, 0,   /* TAG13 */
+      "a branch tag" },
+    { REL, ins_imms4, ext_imms4, 0, {{ 9, 24}}, 0,             /* TAG13b */
+      "a branch tag" },
+    { REL, ins_imms4, ext_imms4, 0, {{20,  6}, { 1, 36}}, 0,   /* TGT25 */
+      "a branch target" },
+    { REL, ins_imms4, ext_imms4, 0,                            /* TGT25b */
+      {{ 7,  6}, {13, 20}, { 1, 36}}, 0,
+      "a branch target" },
+    { REL, ins_imms4, ext_imms4, 0, {{20, 13}, { 1, 36}}, 0,   /* TGT25c */
+      "a branch target" },
+    { REL, ins_rsvd, ext_rsvd, 0, {{0, 0}}, 0,                  /* TGT64  */
+      "a branch target" },
+
+    { ABS, ins_const, ext_const, 0, {{0, 0}}, 0,               /* LDXMOV */
+      "ldxmov target" },
+  };
diff --git a/arch/ia64/kdb/ia64-asmtab.c b/arch/ia64/kdb/ia64-asmtab.c
new file mode 100644 (file)
index 0000000..9e0a790
--- /dev/null
@@ -0,0 +1,8585 @@
+/* This file is automatically generated by ia64-gen.  Do not edit!  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+static const char * const ia64_strings[] = {
+  "", "0", "1", "a", "acq", "add", "addl", "addp4", "adds", "alloc", "and",
+  "andcm", "b", "bias", "br", "break", "brl", "brp", "bsw", "c", "call",
+  "cexit", "chk", "cloop", "clr", "clrrrb", "cmp", "cmp4", "cmp8xchg16",
+  "cmpxchg1", "cmpxchg2", "cmpxchg4", "cmpxchg8", "cond", "cover", "ctop",
+  "czx1", "czx2", "d", "dep", "dpnt", "dptk", "e", "epc", "eq", "excl",
+  "exit", "exp", "extr", "f", "fabs", "fadd", "famax", "famin", "fand",
+  "fandcm", "fault", "fc", "fchkf", "fclass", "fclrf", "fcmp", "fcvt",
+  "fetchadd4", "fetchadd8", "few", "fill", "flushrs", "fma", "fmax",
+  "fmerge", "fmin", "fmix", "fmpy", "fms", "fneg", "fnegabs", "fnma",
+  "fnmpy", "fnorm", "for", "fpabs", "fpack", "fpamax", "fpamin", "fpcmp",
+  "fpcvt", "fpma", "fpmax", "fpmerge", "fpmin", "fpmpy", "fpms", "fpneg",
+  "fpnegabs", "fpnma", "fpnmpy", "fprcpa", "fprsqrta", "frcpa", "frsqrta",
+  "fselect", "fsetc", "fsub", "fswap", "fsxt", "fwb", "fx", "fxor", "fxu",
+  "g", "ga", "ge", "getf", "geu", "gt", "gtu", "h", "hint", "hu", "i", "ia",
+  "imp", "invala", "itc", "itr", "l", "ld1", "ld16", "ld2", "ld4", "ld8",
+  "ldf", "ldf8", "ldfd", "ldfe", "ldfp8", "ldfpd", "ldfps", "ldfs", "le",
+  "leu", "lfetch", "loadrs", "loop", "lr", "lt", "ltu", "lu", "m", "many",
+  "mf", "mix1", "mix2", "mix4", "mov", "movl", "mux1", "mux2", "nc", "ne",
+  "neq", "nge", "ngt", "nl", "nle", "nlt", "nm", "nop", "nr", "ns", "nt1",
+  "nt2", "nta", "nz", "or", "orcm", "ord", "pack2", "pack4", "padd1",
+  "padd2", "padd4", "pavg1", "pavg2", "pavgsub1", "pavgsub2", "pcmp1",
+  "pcmp2", "pcmp4", "pmax1", "pmax2", "pmin1", "pmin2", "pmpy2", "pmpyshr2",
+  "popcnt", "pr", "probe", "psad1", "pshl2", "pshl4", "pshladd2", "pshr2",
+  "pshr4", "pshradd2", "psub1", "psub2", "psub4", "ptc", "ptr", "r", "raz",
+  "rel", "ret", "rfi", "rsm", "rum", "rw", "s", "s0", "s1", "s2", "s3",
+  "sa", "se", "setf", "shl", "shladd", "shladdp4", "shr", "shrp", "sig",
+  "spill", "spnt", "sptk", "srlz", "ssm", "sss", "st1", "st16", "st2",
+  "st4", "st8", "stf", "stf8", "stfd", "stfe", "stfs", "sub", "sum", "sxt1",
+  "sxt2", "sxt4", "sync", "tak", "tbit", "thash", "tnat", "tpa", "trunc",
+  "ttag", "u", "unc", "unord", "unpack1", "unpack2", "unpack4", "uss",
+  "uus", "uuu", "w", "wexit", "wtop", "x", "xchg1", "xchg2", "xchg4",
+  "xchg8", "xf", "xma", "xmpy", "xor", "xuf", "z", "zxt1", "zxt2", "zxt4",
+};
+
+static const struct ia64_dependency
+dependencies[] = {
+  { "ALAT", 0, 0, 0, -1, NULL, },
+  { "AR[BSP]", 26, 0, 2, 17, NULL, },
+  { "AR[BSPSTORE]", 26, 0, 2, 18, NULL, },
+  { "AR[CFLG]", 26, 0, 2, 27, NULL, },
+  { "AR[CCV]", 26, 0, 2, 32, NULL, },
+  { "AR[CSD]", 26, 0, 2, 25, NULL, },
+  { "AR[EC]", 26, 0, 2, 66, NULL, },
+  { "AR[EFLAG]", 26, 0, 2, 24, NULL, },
+  { "AR[FCR]", 26, 0, 2, 21, NULL, },
+  { "AR[FDR]", 26, 0, 2, 30, NULL, },
+  { "AR[FIR]", 26, 0, 2, 29, NULL, },
+  { "AR[FPSR].sf0.controls", 30, 0, 2, -1, NULL, },
+  { "AR[FPSR].sf1.controls", 30, 0, 2, -1, NULL, },
+  { "AR[FPSR].sf2.controls", 30, 0, 2, -1, NULL, },
+  { "AR[FPSR].sf3.controls", 30, 0, 2, -1, NULL, },
+  { "AR[FPSR].sf0.flags", 30, 0, 2, -1, NULL, },
+  { "AR[FPSR].sf1.flags", 30, 0, 2, -1, NULL, },
+  { "AR[FPSR].sf2.flags", 30, 0, 2, -1, NULL, },
+  { "AR[FPSR].sf3.flags", 30, 0, 2, -1, NULL, },
+  { "AR[FPSR].traps", 30, 0, 2, -1, NULL, },
+  { "AR[FPSR].rv", 30, 0, 2, -1, NULL, },
+  { "AR[FSR]", 26, 0, 2, 28, NULL, },
+  { "AR[ITC]", 26, 0, 2, 44, NULL, },
+  { "AR[K%], % in 0 - 7", 1, 0, 2, -1, NULL, },
+  { "AR[LC]", 26, 0, 2, 65, NULL, },
+  { "AR[PFS]", 26, 0, 2, 64, NULL, },
+  { "AR[PFS]", 26, 0, 2, 64, NULL, },
+  { "AR[PFS]", 26, 0, 0, 64, NULL, },
+  { "AR[RNAT]", 26, 0, 2, 19, NULL, },
+  { "AR[RSC]", 26, 0, 2, 16, NULL, },
+  { "AR[SSD]", 26, 0, 2, 26, NULL, },
+  { "AR[UNAT]{%}, % in 0 - 63", 2, 0, 2, -1, NULL, },
+  { "AR%, % in 8-15, 20, 22-23, 31, 33-35, 37-39, 41-43, 45-47, 67-111", 3, 0, 0, -1, NULL, },
+  { "AR%, % in 48-63, 112-127", 4, 0, 2, -1, NULL, },
+  { "BR%, % in 0 - 7", 5, 0, 2, -1, NULL, },
+  { "BR%, % in 0 - 7", 5, 0, 0, -1, NULL, },
+  { "BR%, % in 0 - 7", 5, 0, 2, -1, NULL, },
+  { "CFM", 6, 0, 2, -1, NULL, },
+  { "CFM", 6, 0, 2, -1, NULL, },
+  { "CFM", 6, 0, 2, -1, NULL, },
+  { "CFM", 6, 0, 2, -1, NULL, },
+  { "CFM", 6, 0, 0, -1, NULL, },
+  { "CPUID#", 7, 0, 5, -1, NULL, },
+  { "CR[CMCV]", 27, 0, 3, 74, NULL, },
+  { "CR[DCR]", 27, 0, 3, 0, NULL, },
+  { "CR[EOI]", 27, 0, 7, 67, "SC Section 10.8.3.4", },
+  { "CR[GPTA]", 27, 0, 3, 9, NULL, },
+  { "CR[IFA]", 27, 0, 1, 20, NULL, },
+  { "CR[IFA]", 27, 0, 3, 20, NULL, },
+  { "CR[IFS]", 27, 0, 3, 23, NULL, },
+  { "CR[IFS]", 27, 0, 1, 23, NULL, },
+  { "CR[IFS]", 27, 0, 1, 23, NULL, },
+  { "CR[IHA]", 27, 0, 3, 25, NULL, },
+  { "CR[IIM]", 27, 0, 3, 24, NULL, },
+  { "CR[IIP]", 27, 0, 3, 19, NULL, },
+  { "CR[IIP]", 27, 0, 1, 19, NULL, },
+  { "CR[IIPA]", 27, 0, 3, 22, NULL, },
+  { "CR[IPSR]", 27, 0, 3, 16, NULL, },
+  { "CR[IPSR]", 27, 0, 1, 16, NULL, },
+  { "CR[IRR%], % in 0 - 3", 8, 0, 3, -1, NULL, },
+  { "CR[ISR]", 27, 0, 3, 17, NULL, },
+  { "CR[ITIR]", 27, 0, 3, 21, NULL, },
+  { "CR[ITIR]", 27, 0, 1, 21, NULL, },
+  { "CR[ITM]", 27, 0, 3, 1, NULL, },
+  { "CR[ITV]", 27, 0, 3, 72, NULL, },
+  { "CR[IVA]", 27, 0, 4, 2, NULL, },
+  { "CR[IVR]", 27, 0, 7, 65, "SC Section 10.8.3.2", },
+  { "CR[LID]", 27, 0, 7, 64, "SC Section 10.8.3.1", },
+  { "CR[LRR%], % in 0 - 1", 9, 0, 3, -1, NULL, },
+  { "CR[PMV]", 27, 0, 3, 73, NULL, },
+  { "CR[PTA]", 27, 0, 3, 8, NULL, },
+  { "CR[TPR]", 27, 0, 3, 66, NULL, },
+  { "CR[TPR]", 27, 0, 7, 66, "SC Section 10.8.3.3", },
+  { "CR%, % in 3-7, 10-15, 18, 26-63, 75-79, 82-127", 10, 0, 0, -1, NULL, },
+  { "DBR#", 11, 0, 2, -1, NULL, },
+  { "DBR#", 11, 0, 3, -1, NULL, },
+  { "DTC", 0, 0, 3, -1, NULL, },
+  { "DTC", 0, 0, 2, -1, NULL, },
+  { "DTC", 0, 0, 0, -1, NULL, },
+  { "DTC", 0, 0, 2, -1, NULL, },
+  { "DTC_LIMIT*", 0, 0, 2, -1, NULL, },
+  { "DTR", 0, 0, 3, -1, NULL, },
+  { "DTR", 0, 0, 2, -1, NULL, },
+  { "DTR", 0, 0, 3, -1, NULL, },
+  { "DTR", 0, 0, 0, -1, NULL, },
+  { "DTR", 0, 0, 2, -1, NULL, },
+  { "FR%, % in 0 - 1", 12, 0, 0, -1, NULL, },
+  { "FR%, % in 2 - 127", 13, 0, 2, -1, NULL, },
+  { "FR%, % in 2 - 127", 13, 0, 0, -1, NULL, },
+  { "GR0", 14, 0, 0, -1, NULL, },
+  { "GR%, % in 1 - 127", 15, 0, 0, -1, NULL, },
+  { "GR%, % in 1 - 127", 15, 0, 2, -1, NULL, },
+  { "IBR#", 16, 0, 2, -1, NULL, },
+  { "InService*", 17, 0, 3, -1, NULL, },
+  { "InService*", 17, 0, 2, -1, NULL, },
+  { "InService*", 17, 0, 2, -1, NULL, },
+  { "IP", 0, 0, 0, -1, NULL, },
+  { "ITC", 0, 0, 4, -1, NULL, },
+  { "ITC", 0, 0, 2, -1, NULL, },
+  { "ITC", 0, 0, 0, -1, NULL, },
+  { "ITC", 0, 0, 4, -1, NULL, },
+  { "ITC", 0, 0, 2, -1, NULL, },
+  { "ITC_LIMIT*", 0, 0, 2, -1, NULL, },
+  { "ITR", 0, 0, 2, -1, NULL, },
+  { "ITR", 0, 0, 4, -1, NULL, },
+  { "ITR", 0, 0, 2, -1, NULL, },
+  { "ITR", 0, 0, 0, -1, NULL, },
+  { "ITR", 0, 0, 4, -1, NULL, },
+  { "memory", 0, 0, 0, -1, NULL, },
+  { "MSR#", 18, 0, 5, -1, NULL, },
+  { "PKR#", 19, 0, 3, -1, NULL, },
+  { "PKR#", 19, 0, 0, -1, NULL, },
+  { "PKR#", 19, 0, 2, -1, NULL, },
+  { "PKR#", 19, 0, 2, -1, NULL, },
+  { "PMC#", 20, 0, 2, -1, NULL, },
+  { "PMC#", 20, 0, 7, -1, "SC+3 Section 12.1.1", },
+  { "PMD#", 21, 0, 2, -1, NULL, },
+  { "PR0", 0, 0, 0, -1, NULL, },
+  { "PR%, % in 1 - 15", 22, 0, 2, -1, NULL, },
+  { "PR%, % in 1 - 15", 22, 0, 2, -1, NULL, },
+  { "PR%, % in 1 - 15", 22, 0, 0, -1, NULL, },
+  { "PR%, % in 16 - 62", 23, 0, 2, -1, NULL, },
+  { "PR%, % in 16 - 62", 23, 0, 2, -1, NULL, },
+  { "PR%, % in 16 - 62", 23, 0, 0, -1, NULL, },
+  { "PR63", 24, 0, 2, -1, NULL, },
+  { "PR63", 24, 0, 2, -1, NULL, },
+  { "PR63", 24, 0, 0, -1, NULL, },
+  { "PSR.ac", 28, 0, 1, 3, NULL, },
+  { "PSR.ac", 28, 0, 3, 3, NULL, },
+  { "PSR.ac", 28, 0, 2, 3, NULL, },
+  { "PSR.be", 28, 0, 1, 1, NULL, },
+  { "PSR.be", 28, 0, 3, 1, NULL, },
+  { "PSR.be", 28, 0, 2, 1, NULL, },
+  { "PSR.bn", 28, 0, 2, 44, NULL, },
+  { "PSR.cpl", 28, 0, 1, 32, NULL, },
+  { "PSR.da", 28, 0, 3, 38, NULL, },
+  { "PSR.db", 28, 0, 3, 24, NULL, },
+  { "PSR.db", 28, 0, 2, 24, NULL, },
+  { "PSR.db", 28, 0, 3, 24, NULL, },
+  { "PSR.dd", 28, 0, 3, 39, NULL, },
+  { "PSR.dfh", 28, 0, 3, 19, NULL, },
+  { "PSR.dfh", 28, 0, 2, 19, NULL, },
+  { "PSR.dfl", 28, 0, 3, 18, NULL, },
+  { "PSR.dfl", 28, 0, 2, 18, NULL, },
+  { "PSR.di", 28, 0, 3, 22, NULL, },
+  { "PSR.di", 28, 0, 2, 22, NULL, },
+  { "PSR.dt", 28, 0, 3, 17, NULL, },
+  { "PSR.dt", 28, 0, 2, 17, NULL, },
+  { "PSR.ed", 28, 0, 3, 43, NULL, },
+  { "PSR.i", 28, 0, 2, 14, NULL, },
+  { "PSR.i", 28, 0, 3, 14, NULL, },
+  { "PSR.ia", 28, 0, 0, 14, NULL, },
+  { "PSR.ic", 28, 0, 2, 13, NULL, },
+  { "PSR.ic", 28, 0, 3, 13, NULL, },
+  { "PSR.id", 28, 0, 0, 14, NULL, },
+  { "PSR.is", 28, 0, 0, 14, NULL, },
+  { "PSR.it", 28, 0, 3, 14, NULL, },
+  { "PSR.lp", 28, 0, 2, 25, NULL, },
+  { "PSR.lp", 28, 0, 3, 25, NULL, },
+  { "PSR.lp", 28, 0, 3, 25, NULL, },
+  { "PSR.mc", 28, 0, 0, 35, NULL, },
+  { "PSR.mfh", 28, 0, 2, 5, NULL, },
+  { "PSR.mfl", 28, 0, 2, 4, NULL, },
+  { "PSR.pk", 28, 0, 3, 15, NULL, },
+  { "PSR.pk", 28, 0, 2, 15, NULL, },
+  { "PSR.pp", 28, 0, 2, 21, NULL, },
+  { "PSR.ri", 28, 0, 0, 41, NULL, },
+  { "PSR.rt", 28, 0, 2, 27, NULL, },
+  { "PSR.rt", 28, 0, 3, 27, NULL, },
+  { "PSR.rt", 28, 0, 3, 27, NULL, },
+  { "PSR.si", 28, 0, 2, 23, NULL, },
+  { "PSR.si", 28, 0, 3, 23, NULL, },
+  { "PSR.sp", 28, 0, 2, 20, NULL, },
+  { "PSR.sp", 28, 0, 3, 20, NULL, },
+  { "PSR.ss", 28, 0, 3, 40, NULL, },
+  { "PSR.tb", 28, 0, 3, 26, NULL, },
+  { "PSR.tb", 28, 0, 2, 26, NULL, },
+  { "PSR.up", 28, 0, 2, 2, NULL, },
+  { "RR#", 25, 0, 3, -1, NULL, },
+  { "RR#", 25, 0, 2, -1, NULL, },
+  { "RSE", 29, 0, 2, -1, NULL, },
+  { "ALAT", 0, 1, 0, -1, NULL, },
+  { "AR[BSP]", 26, 1, 2, 17, NULL, },
+  { "AR[BSPSTORE]", 26, 1, 2, 18, NULL, },
+  { "AR[CCV]", 26, 1, 2, 32, NULL, },
+  { "AR[CFLG]", 26, 1, 2, 27, NULL, },
+  { "AR[CSD]", 26, 1, 2, 25, NULL, },
+  { "AR[EC]", 26, 1, 2, 66, NULL, },
+  { "AR[EFLAG]", 26, 1, 2, 24, NULL, },
+  { "AR[FCR]", 26, 1, 2, 21, NULL, },
+  { "AR[FDR]", 26, 1, 2, 30, NULL, },
+  { "AR[FIR]", 26, 1, 2, 29, NULL, },
+  { "AR[FPSR].sf0.controls", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf1.controls", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf2.controls", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf3.controls", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf0.flags", 30, 1, 0, -1, NULL, },
+  { "AR[FPSR].sf0.flags", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf0.flags", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf1.flags", 30, 1, 0, -1, NULL, },
+  { "AR[FPSR].sf1.flags", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf1.flags", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf2.flags", 30, 1, 0, -1, NULL, },
+  { "AR[FPSR].sf2.flags", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf2.flags", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf3.flags", 30, 1, 0, -1, NULL, },
+  { "AR[FPSR].sf3.flags", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].sf3.flags", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].rv", 30, 1, 2, -1, NULL, },
+  { "AR[FPSR].traps", 30, 1, 2, -1, NULL, },
+  { "AR[FSR]", 26, 1, 2, 28, NULL, },
+  { "AR[ITC]", 26, 1, 2, 44, NULL, },
+  { "AR[K%], % in 0 - 7", 1, 1, 2, -1, NULL, },
+  { "AR[LC]", 26, 1, 2, 65, NULL, },
+  { "AR[PFS]", 26, 1, 0, 64, NULL, },
+  { "AR[PFS]", 26, 1, 2, 64, NULL, },
+  { "AR[PFS]", 26, 1, 2, 64, NULL, },
+  { "AR[RNAT]", 26, 1, 2, 19, NULL, },
+  { "AR[RSC]", 26, 1, 2, 16, NULL, },
+  { "AR[UNAT]{%}, % in 0 - 63", 2, 1, 2, -1, NULL, },
+  { "AR%, % in 8-15, 20, 22-23, 31, 33-35, 37-39, 41-43, 45-47, 67-111", 3, 1, 0, -1, NULL, },
+  { "AR%, % in 48 - 63, 112-127", 4, 1, 2, -1, NULL, },
+  { "BR%, % in 0 - 7", 5, 1, 2, -1, NULL, },
+  { "BR%, % in 0 - 7", 5, 1, 2, -1, NULL, },
+  { "BR%, % in 0 - 7", 5, 1, 2, -1, NULL, },
+  { "BR%, % in 0 - 7", 5, 1, 0, -1, NULL, },
+  { "CFM", 6, 1, 2, -1, NULL, },
+  { "CPUID#", 7, 1, 0, -1, NULL, },
+  { "CR[CMCV]", 27, 1, 2, 74, NULL, },
+  { "CR[DCR]", 27, 1, 2, 0, NULL, },
+  { "CR[EOI]", 27, 1, 7, 67, "SC Section 10.8.3.4", },
+  { "CR[GPTA]", 27, 1, 2, 9, NULL, },
+  { "CR[IFA]", 27, 1, 2, 20, NULL, },
+  { "CR[IFS]", 27, 1, 2, 23, NULL, },
+  { "CR[IHA]", 27, 1, 2, 25, NULL, },
+  { "CR[IIM]", 27, 1, 2, 24, NULL, },
+  { "CR[IIP]", 27, 1, 2, 19, NULL, },
+  { "CR[IIPA]", 27, 1, 2, 22, NULL, },
+  { "CR[IPSR]", 27, 1, 2, 16, NULL, },
+  { "CR[IRR%], % in 0 - 3", 8, 1, 2, -1, NULL, },
+  { "CR[ISR]", 27, 1, 2, 17, NULL, },
+  { "CR[ITIR]", 27, 1, 2, 21, NULL, },
+  { "CR[ITM]", 27, 1, 2, 1, NULL, },
+  { "CR[ITV]", 27, 1, 2, 72, NULL, },
+  { "CR[IVA]", 27, 1, 2, 2, NULL, },
+  { "CR[IVR]", 27, 1, 7, 65, "SC", },
+  { "CR[LID]", 27, 1, 7, 64, "SC", },
+  { "CR[LRR%], % in 0 - 1", 9, 1, 2, -1, NULL, },
+  { "CR[PMV]", 27, 1, 2, 73, NULL, },
+  { "CR[PTA]", 27, 1, 2, 8, NULL, },
+  { "CR[TPR]", 27, 1, 2, 66, NULL, },
+  { "CR%, % in 3-7, 10-15, 18, 26-63, 75-79, 82-127", 10, 1, 0, -1, NULL, },
+  { "DBR#", 11, 1, 2, -1, NULL, },
+  { "DTC", 0, 1, 0, -1, NULL, },
+  { "DTC", 0, 1, 2, -1, NULL, },
+  { "DTC", 0, 1, 2, -1, NULL, },
+  { "DTC_LIMIT*", 0, 1, 2, -1, NULL, },
+  { "DTR", 0, 1, 2, -1, NULL, },
+  { "DTR", 0, 1, 2, -1, NULL, },
+  { "DTR", 0, 1, 2, -1, NULL, },
+  { "DTR", 0, 1, 0, -1, NULL, },
+  { "FR%, % in 0 - 1", 12, 1, 0, -1, NULL, },
+  { "FR%, % in 2 - 127", 13, 1, 2, -1, NULL, },
+  { "GR0", 14, 1, 0, -1, NULL, },
+  { "GR%, % in 1 - 127", 15, 1, 2, -1, NULL, },
+  { "IBR#", 16, 1, 2, -1, NULL, },
+  { "InService*", 17, 1, 7, -1, "SC", },
+  { "IP", 0, 1, 0, -1, NULL, },
+  { "ITC", 0, 1, 0, -1, NULL, },
+  { "ITC", 0, 1, 2, -1, NULL, },
+  { "ITC", 0, 1, 2, -1, NULL, },
+  { "ITR", 0, 1, 2, -1, NULL, },
+  { "ITR", 0, 1, 2, -1, NULL, },
+  { "ITR", 0, 1, 0, -1, NULL, },
+  { "memory", 0, 1, 0, -1, NULL, },
+  { "MSR#", 18, 1, 7, -1, "SC", },
+  { "PKR#", 19, 1, 0, -1, NULL, },
+  { "PKR#", 19, 1, 0, -1, NULL, },
+  { "PKR#", 19, 1, 2, -1, NULL, },
+  { "PMC#", 20, 1, 2, -1, NULL, },
+  { "PMD#", 21, 1, 2, -1, NULL, },
+  { "PR0", 0, 1, 0, -1, NULL, },
+  { "PR%, % in 1 - 15", 22, 1, 0, -1, NULL, },
+  { "PR%, % in 1 - 15", 22, 1, 0, -1, NULL, },
+  { "PR%, % in 1 - 15", 22, 1, 2, -1, NULL, },
+  { "PR%, % in 1 - 15", 22, 1, 2, -1, NULL, },
+  { "PR%, % in 16 - 62", 23, 1, 0, -1, NULL, },
+  { "PR%, % in 16 - 62", 23, 1, 0, -1, NULL, },
+  { "PR%, % in 16 - 62", 23, 1, 2, -1, NULL, },
+  { "PR%, % in 16 - 62", 23, 1, 2, -1, NULL, },
+  { "PR63", 24, 1, 0, -1, NULL, },
+  { "PR63", 24, 1, 0, -1, NULL, },
+  { "PR63", 24, 1, 2, -1, NULL, },
+  { "PR63", 24, 1, 2, -1, NULL, },
+  { "PSR.ac", 28, 1, 2, 3, NULL, },
+  { "PSR.be", 28, 1, 2, 1, NULL, },
+  { "PSR.bn", 28, 1, 2, 44, NULL, },
+  { "PSR.cpl", 28, 1, 2, 32, NULL, },
+  { "PSR.da", 28, 1, 2, 38, NULL, },
+  { "PSR.db", 28, 1, 2, 24, NULL, },
+  { "PSR.dd", 28, 1, 2, 39, NULL, },
+  { "PSR.dfh", 28, 1, 2, 19, NULL, },
+  { "PSR.dfl", 28, 1, 2, 18, NULL, },
+  { "PSR.di", 28, 1, 2, 22, NULL, },
+  { "PSR.dt", 28, 1, 2, 17, NULL, },
+  { "PSR.ed", 28, 1, 2, 43, NULL, },
+  { "PSR.i", 28, 1, 2, 14, NULL, },
+  { "PSR.ia", 28, 1, 2, 14, NULL, },
+  { "PSR.ic", 28, 1, 2, 13, NULL, },
+  { "PSR.id", 28, 1, 2, 14, NULL, },
+  { "PSR.is", 28, 1, 2, 14, NULL, },
+  { "PSR.it", 28, 1, 2, 14, NULL, },
+  { "PSR.lp", 28, 1, 2, 25, NULL, },
+  { "PSR.mc", 28, 1, 2, 35, NULL, },
+  { "PSR.mfh", 28, 1, 0, 5, NULL, },
+  { "PSR.mfh", 28, 1, 2, 5, NULL, },
+  { "PSR.mfh", 28, 1, 2, 5, NULL, },
+  { "PSR.mfl", 28, 1, 0, 4, NULL, },
+  { "PSR.mfl", 28, 1, 2, 4, NULL, },
+  { "PSR.mfl", 28, 1, 2, 4, NULL, },
+  { "PSR.pk", 28, 1, 2, 15, NULL, },
+  { "PSR.pp", 28, 1, 2, 21, NULL, },
+  { "PSR.ri", 28, 1, 2, 41, NULL, },
+  { "PSR.rt", 28, 1, 2, 27, NULL, },
+  { "PSR.si", 28, 1, 2, 23, NULL, },
+  { "PSR.sp", 28, 1, 2, 20, NULL, },
+  { "PSR.ss", 28, 1, 2, 40, NULL, },
+  { "PSR.tb", 28, 1, 2, 26, NULL, },
+  { "PSR.up", 28, 1, 2, 2, NULL, },
+  { "RR#", 25, 1, 2, -1, NULL, },
+  { "RSE", 29, 1, 2, -1, NULL, },
+  { "PR63", 24, 2, 6, -1, NULL, },
+};
+
+static const unsigned short dep0[] = {
+  96, 267, 2139, 2312,
+};
+
+static const unsigned short dep1[] = {
+  40, 41, 96, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2312, 4135,
+  20613,
+};
+
+static const unsigned short dep2[] = {
+  96, 267, 2165, 2166, 2168, 2169, 2171, 2172, 2174, 2329, 2332, 2333, 2336,
+  2337, 2340, 2341,
+};
+
+static const unsigned short dep3[] = {
+  40, 41, 96, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2329, 2332,
+  2333, 2336, 2337, 2340, 2341, 4135, 20613,
+};
+
+static const unsigned short dep4[] = {
+  96, 267, 22645, 22646, 22648, 22649, 22651, 22652, 22654, 22809, 22812, 22813,
+  22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep5[] = {
+  40, 41, 96, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135, 20613,
+  22809, 22812, 22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep6[] = {
+  96, 267, 2165, 2166, 2168, 2169, 2171, 2172, 2174, 2329, 2330, 2332, 2334,
+  2336, 2338, 2340,
+};
+
+static const unsigned short dep7[] = {
+  40, 41, 96, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2329, 2330,
+  2333, 2334, 2337, 2338, 2341, 4135, 20613,
+};
+
+static const unsigned short dep8[] = {
+  96, 267, 2165, 2166, 2168, 2169, 2171, 2172, 2174, 2329, 2331, 2333, 2335,
+  2337, 2339, 2341,
+};
+
+static const unsigned short dep9[] = {
+  40, 41, 96, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2329, 2331,
+  2332, 2335, 2336, 2339, 2340, 4135, 20613,
+};
+
+static const unsigned short dep10[] = {
+  96, 267, 2165, 2166, 2168, 2169, 2171, 2172, 2174, 2329, 2330, 2331, 2332,
+  2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341,
+};
+
+static const unsigned short dep11[] = {
+  40, 41, 96, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2329, 2330,
+  2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 4135, 20613,
+
+};
+
+static const unsigned short dep12[] = {
+  96, 267, 2379,
+};
+
+static const unsigned short dep13[] = {
+  40, 41, 96, 156, 174, 175, 267, 2082, 2083, 2165, 2167, 2168, 2170, 2171,
+  2173, 2174, 4135,
+};
+
+static const unsigned short dep14[] = {
+  96, 155, 267, 310, 2379, 28852, 29002,
+};
+
+static const unsigned short dep15[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+  22, 23, 24, 25, 26, 28, 29, 30, 31, 32, 33, 40, 41, 96, 144, 156, 174, 175,
+  267, 310, 2082, 2083, 2165, 2167, 2168, 2170, 2171, 2173, 2174, 4135, 28852,
+  29002,
+};
+
+static const unsigned short dep16[] = {
+  1, 6, 40, 96, 134, 182, 187, 226, 267, 297, 2379, 28852, 29002,
+};
+
+static const unsigned short dep17[] = {
+  1, 25, 27, 38, 40, 41, 96, 156, 158, 159, 174, 175, 182, 187, 226, 267, 297,
+  2082, 2083, 2165, 2167, 2168, 2170, 2171, 2173, 2174, 4135, 28852, 29002,
+
+};
+
+static const unsigned short dep18[] = {
+  1, 40, 51, 96, 182, 226, 233, 267, 28852, 29002,
+};
+
+static const unsigned short dep19[] = {
+  1, 38, 40, 41, 96, 153, 174, 182, 226, 233, 267, 4135, 28852, 29002,
+};
+
+static const unsigned short dep20[] = {
+  40, 96, 226, 267,
+};
+
+static const unsigned short dep21[] = {
+  96, 174, 226, 267,
+};
+
+static const unsigned short dep22[] = {
+  1, 40, 96, 128, 129, 131, 132, 133, 134, 135, 138, 139, 140, 141, 142, 143,
+  144, 145, 146, 147, 148, 150, 151, 152, 153, 154, 155, 156, 159, 160, 161,
+  162, 163, 164, 165, 166, 169, 170, 171, 172, 173, 174, 175, 176, 177, 182,
+  226, 267, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306,
+  307, 308, 309, 310, 311, 312, 313, 315, 316, 318, 319, 320, 321, 322, 323,
+  324, 325, 326, 327, 328, 28852, 29002,
+};
+
+static const unsigned short dep23[] = {
+  1, 38, 40, 41, 50, 51, 55, 58, 72, 96, 134, 174, 182, 226, 267, 294, 295,
+  296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310,
+  311, 312, 313, 315, 316, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327,
+  328, 4135, 28852, 29002,
+};
+
+static const unsigned short dep24[] = {
+  96, 133, 267, 296,
+};
+
+static const unsigned short dep25[] = {
+  96, 134, 174, 267, 296,
+};
+
+static const unsigned short dep26[] = {
+  96, 134, 267, 297,
+};
+
+static const unsigned short dep27[] = {
+  25, 26, 96, 97, 100, 104, 107, 134, 156, 174, 267, 297,
+};
+
+static const unsigned short dep28[] = {
+  40, 41, 96, 174, 267, 2165, 2167, 2168, 2170, 2171, 2173, 2174, 4135,
+};
+
+static const unsigned short dep29[] = {
+  1, 25, 40, 96, 182, 214, 215, 226, 267, 2082, 2270, 2273, 2379, 28852, 29002,
+
+};
+
+static const unsigned short dep30[] = {
+  1, 6, 38, 40, 41, 96, 134, 156, 174, 175, 182, 214, 216, 226, 267, 2082, 2083,
+  2165, 2167, 2168, 2170, 2171, 2173, 2174, 2271, 2273, 4135, 28852, 29002,
+
+};
+
+static const unsigned short dep31[] = {
+  96, 267,
+};
+
+static const unsigned short dep32[] = {
+  96, 174, 267, 2082, 2084,
+};
+
+static const unsigned short dep33[] = {
+  40, 41, 96, 156, 174, 175, 267, 2165, 2167, 2168, 2170, 2171, 2173, 2174,
+  4135,
+};
+
+static const unsigned short dep34[] = {
+  6, 37, 38, 39, 96, 124, 125, 187, 226, 267, 292, 293, 2379,
+};
+
+static const unsigned short dep35[] = {
+  6, 37, 40, 41, 96, 156, 174, 175, 187, 226, 267, 292, 293, 331, 2165, 2167,
+  2168, 2170, 2171, 2173, 2174, 4135,
+};
+
+static const unsigned short dep36[] = {
+  24, 96, 213, 267, 2379,
+};
+
+static const unsigned short dep37[] = {
+  24, 40, 41, 96, 156, 174, 175, 213, 267, 2165, 2167, 2168, 2170, 2171, 2173,
+  2174, 4135,
+};
+
+static const unsigned short dep38[] = {
+  6, 24, 37, 38, 39, 96, 124, 125, 187, 213, 226, 267, 292, 293, 2379,
+};
+
+static const unsigned short dep39[] = {
+  6, 24, 37, 40, 41, 96, 156, 174, 175, 187, 213, 226, 267, 292, 293, 331, 2165,
+  2167, 2168, 2170, 2171, 2173, 2174, 4135,
+};
+
+static const unsigned short dep40[] = {
+  1, 6, 38, 40, 41, 96, 134, 156, 174, 175, 182, 214, 216, 226, 267, 2165, 2167,
+  2168, 2170, 2171, 2173, 2174, 2271, 2273, 4135, 28852, 29002,
+};
+
+static const unsigned short dep41[] = {
+  96, 174, 267,
+};
+
+static const unsigned short dep42[] = {
+  15, 96, 196, 197, 267, 2135, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+  22645, 22646, 22647, 22649, 22650, 22652, 22653, 22809, 22812, 22813, 22816,
+  22817, 22820, 22821,
+};
+
+static const unsigned short dep43[] = {
+  11, 19, 20, 40, 41, 96, 174, 196, 198, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751, 22809, 22812,
+  22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep44[] = {
+  15, 16, 17, 18, 96, 196, 197, 199, 200, 202, 203, 205, 206, 267, 2135, 2310,
+  18593, 18594, 18746, 18747, 18749, 18750, 22645, 22646, 22647, 22649, 22650,
+  22652, 22653, 22809, 22812, 22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep45[] = {
+  11, 12, 13, 14, 19, 20, 40, 41, 96, 174, 196, 198, 199, 201, 202, 204, 205,
+  207, 267, 2134, 2135, 2136, 2165, 2166, 2169, 2172, 2310, 4135, 16524, 16526,
+  18746, 18748, 18749, 18751, 22809, 22812, 22813, 22816, 22817, 22820, 22821,
+
+};
+
+static const unsigned short dep46[] = {
+  16, 96, 199, 200, 267, 2135, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+  22645, 22646, 22647, 22649, 22650, 22652, 22653, 22809, 22812, 22813, 22816,
+  22817, 22820, 22821,
+};
+
+static const unsigned short dep47[] = {
+  12, 19, 20, 40, 41, 96, 174, 199, 201, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751, 22809, 22812,
+  22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep48[] = {
+  17, 96, 202, 203, 267, 2135, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+  22645, 22646, 22647, 22649, 22650, 22652, 22653, 22809, 22812, 22813, 22816,
+  22817, 22820, 22821,
+};
+
+static const unsigned short dep49[] = {
+  13, 19, 20, 40, 41, 96, 174, 202, 204, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751, 22809, 22812,
+  22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep50[] = {
+  18, 96, 205, 206, 267, 2135, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+  22645, 22646, 22647, 22649, 22650, 22652, 22653, 22809, 22812, 22813, 22816,
+  22817, 22820, 22821,
+};
+
+static const unsigned short dep51[] = {
+  14, 19, 20, 40, 41, 96, 174, 205, 207, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751, 22809, 22812,
+  22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep52[] = {
+  15, 96, 196, 197, 267, 2135, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+
+};
+
+static const unsigned short dep53[] = {
+  11, 19, 20, 40, 41, 96, 174, 196, 198, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751,
+};
+
+static const unsigned short dep54[] = {
+  15, 16, 17, 18, 96, 196, 197, 199, 200, 202, 203, 205, 206, 267, 2135, 2310,
+  18593, 18594, 18746, 18747, 18749, 18750,
+};
+
+static const unsigned short dep55[] = {
+  11, 12, 13, 14, 19, 20, 40, 41, 96, 174, 196, 198, 199, 201, 202, 204, 205,
+  207, 267, 2134, 2135, 2136, 2165, 2166, 2169, 2172, 2310, 4135, 16524, 16526,
+  18746, 18748, 18749, 18751,
+};
+
+static const unsigned short dep56[] = {
+  16, 96, 199, 200, 267, 2135, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+
+};
+
+static const unsigned short dep57[] = {
+  12, 19, 20, 40, 41, 96, 174, 199, 201, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751,
+};
+
+static const unsigned short dep58[] = {
+  17, 96, 202, 203, 267, 2135, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+
+};
+
+static const unsigned short dep59[] = {
+  13, 19, 20, 40, 41, 96, 174, 202, 204, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751,
+};
+
+static const unsigned short dep60[] = {
+  18, 96, 205, 206, 267, 2135, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+
+};
+
+static const unsigned short dep61[] = {
+  14, 19, 20, 40, 41, 96, 174, 205, 207, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751,
+};
+
+static const unsigned short dep62[] = {
+  96, 267, 2135, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+};
+
+static const unsigned short dep63[] = {
+  40, 41, 96, 174, 267, 2134, 2135, 2136, 2165, 2166, 2169, 2172, 2310, 4135,
+  16524, 16526, 18746, 18748, 18749, 18751,
+};
+
+static const unsigned short dep64[] = {
+  11, 96, 192, 267,
+};
+
+static const unsigned short dep65[] = {
+  11, 40, 41, 96, 174, 192, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep66[] = {
+  11, 40, 41, 96, 174, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep67[] = {
+  12, 96, 193, 267,
+};
+
+static const unsigned short dep68[] = {
+  11, 40, 41, 96, 174, 193, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep69[] = {
+  13, 96, 194, 267,
+};
+
+static const unsigned short dep70[] = {
+  11, 40, 41, 96, 174, 194, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep71[] = {
+  14, 96, 195, 267,
+};
+
+static const unsigned short dep72[] = {
+  11, 40, 41, 96, 174, 195, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep73[] = {
+  15, 96, 197, 198, 267,
+};
+
+static const unsigned short dep74[] = {
+  40, 41, 96, 174, 197, 198, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep75[] = {
+  40, 41, 96, 174, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep76[] = {
+  16, 96, 200, 201, 267,
+};
+
+static const unsigned short dep77[] = {
+  40, 41, 96, 174, 200, 201, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep78[] = {
+  17, 96, 203, 204, 267,
+};
+
+static const unsigned short dep79[] = {
+  40, 41, 96, 174, 203, 204, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep80[] = {
+  18, 96, 206, 207, 267,
+};
+
+static const unsigned short dep81[] = {
+  40, 41, 96, 174, 206, 207, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep82[] = {
+  15, 19, 20, 40, 41, 96, 156, 174, 175, 267, 2165, 2166, 2169, 2172, 4135,
+
+};
+
+static const unsigned short dep83[] = {
+  15, 16, 19, 20, 40, 41, 96, 156, 174, 175, 267, 2165, 2166, 2169, 2172, 4135,
+
+};
+
+static const unsigned short dep84[] = {
+  15, 17, 19, 20, 40, 41, 96, 156, 174, 175, 267, 2165, 2166, 2169, 2172, 4135,
+
+};
+
+static const unsigned short dep85[] = {
+  15, 18, 19, 20, 40, 41, 96, 156, 174, 175, 267, 2165, 2166, 2169, 2172, 4135,
+
+};
+
+static const unsigned short dep86[] = {
+  15, 96, 196, 197, 267,
+};
+
+static const unsigned short dep87[] = {
+  11, 19, 20, 40, 41, 96, 174, 196, 198, 267, 2165, 2166, 2169, 2172, 4135,
+
+};
+
+static const unsigned short dep88[] = {
+  15, 16, 17, 18, 96, 196, 197, 199, 200, 202, 203, 205, 206, 267,
+};
+
+static const unsigned short dep89[] = {
+  11, 12, 13, 14, 19, 20, 40, 41, 96, 174, 196, 198, 199, 201, 202, 204, 205,
+  207, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep90[] = {
+  16, 96, 199, 200, 267,
+};
+
+static const unsigned short dep91[] = {
+  12, 19, 20, 40, 41, 96, 174, 199, 201, 267, 2165, 2166, 2169, 2172, 4135,
+
+};
+
+static const unsigned short dep92[] = {
+  17, 96, 202, 203, 267,
+};
+
+static const unsigned short dep93[] = {
+  13, 19, 20, 40, 41, 96, 174, 202, 204, 267, 2165, 2166, 2169, 2172, 4135,
+
+};
+
+static const unsigned short dep94[] = {
+  18, 96, 205, 206, 267,
+};
+
+static const unsigned short dep95[] = {
+  14, 19, 20, 40, 41, 96, 174, 205, 207, 267, 2165, 2166, 2169, 2172, 4135,
+
+};
+
+static const unsigned short dep96[] = {
+  15, 96, 196, 197, 267, 2165, 2166, 2167, 2169, 2170, 2172, 2173, 2329, 2332,
+  2333, 2336, 2337, 2340, 2341,
+};
+
+static const unsigned short dep97[] = {
+  11, 19, 20, 40, 41, 96, 174, 196, 198, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2329, 2332, 2333, 2336, 2337, 2340, 2341, 4135, 16524, 16526,
+
+};
+
+static const unsigned short dep98[] = {
+  15, 16, 17, 18, 96, 196, 197, 199, 200, 202, 203, 205, 206, 267, 2165, 2166,
+  2167, 2169, 2170, 2172, 2173, 2329, 2332, 2333, 2336, 2337, 2340, 2341,
+};
+
+static const unsigned short dep99[] = {
+  11, 12, 13, 14, 19, 20, 40, 41, 96, 174, 196, 198, 199, 201, 202, 204, 205,
+  207, 267, 2134, 2135, 2136, 2165, 2166, 2169, 2172, 2329, 2332, 2333, 2336,
+  2337, 2340, 2341, 4135, 16524, 16526,
+};
+
+static const unsigned short dep100[] = {
+  16, 96, 199, 200, 267, 2165, 2166, 2167, 2169, 2170, 2172, 2173, 2329, 2332,
+  2333, 2336, 2337, 2340, 2341,
+};
+
+static const unsigned short dep101[] = {
+  12, 19, 20, 40, 41, 96, 174, 199, 201, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2329, 2332, 2333, 2336, 2337, 2340, 2341, 4135, 16524, 16526,
+
+};
+
+static const unsigned short dep102[] = {
+  17, 96, 202, 203, 267, 2165, 2166, 2167, 2169, 2170, 2172, 2173, 2329, 2332,
+  2333, 2336, 2337, 2340, 2341,
+};
+
+static const unsigned short dep103[] = {
+  13, 19, 20, 40, 41, 96, 174, 202, 204, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2329, 2332, 2333, 2336, 2337, 2340, 2341, 4135, 16524, 16526,
+
+};
+
+static const unsigned short dep104[] = {
+  18, 96, 205, 206, 267, 2165, 2166, 2167, 2169, 2170, 2172, 2173, 2329, 2332,
+  2333, 2336, 2337, 2340, 2341,
+};
+
+static const unsigned short dep105[] = {
+  14, 19, 20, 40, 41, 96, 174, 205, 207, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 2329, 2332, 2333, 2336, 2337, 2340, 2341, 4135, 16524, 16526,
+
+};
+
+static const unsigned short dep106[] = {
+  15, 96, 196, 197, 267, 22645, 22646, 22647, 22649, 22650, 22652, 22653, 22809,
+  22812, 22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep107[] = {
+  11, 19, 20, 40, 41, 96, 174, 196, 198, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 4135, 16524, 16526, 22809, 22812, 22813, 22816, 22817, 22820,
+  22821,
+};
+
+static const unsigned short dep108[] = {
+  15, 16, 17, 18, 96, 196, 197, 199, 200, 202, 203, 205, 206, 267, 22645, 22646,
+  22647, 22649, 22650, 22652, 22653, 22809, 22812, 22813, 22816, 22817, 22820,
+  22821,
+};
+
+static const unsigned short dep109[] = {
+  11, 12, 13, 14, 19, 20, 40, 41, 96, 174, 196, 198, 199, 201, 202, 204, 205,
+  207, 267, 2134, 2135, 2136, 2165, 2166, 2169, 2172, 4135, 16524, 16526, 22809,
+  22812, 22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep110[] = {
+  16, 96, 199, 200, 267, 22645, 22646, 22647, 22649, 22650, 22652, 22653, 22809,
+  22812, 22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep111[] = {
+  12, 19, 20, 40, 41, 96, 174, 199, 201, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 4135, 16524, 16526, 22809, 22812, 22813, 22816, 22817, 22820,
+  22821,
+};
+
+static const unsigned short dep112[] = {
+  17, 96, 202, 203, 267, 22645, 22646, 22647, 22649, 22650, 22652, 22653, 22809,
+  22812, 22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep113[] = {
+  13, 19, 20, 40, 41, 96, 174, 202, 204, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 4135, 16524, 16526, 22809, 22812, 22813, 22816, 22817, 22820,
+  22821,
+};
+
+static const unsigned short dep114[] = {
+  18, 96, 205, 206, 267, 22645, 22646, 22647, 22649, 22650, 22652, 22653, 22809,
+  22812, 22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep115[] = {
+  14, 19, 20, 40, 41, 96, 174, 205, 207, 267, 2134, 2135, 2136, 2165, 2166,
+  2169, 2172, 4135, 16524, 16526, 22809, 22812, 22813, 22816, 22817, 22820,
+  22821,
+};
+
+static const unsigned short dep116[] = {
+  96, 267, 2165, 2166, 2167, 2169, 2170, 2172, 2173, 2329, 2332, 2333, 2336,
+  2337, 2340, 2341,
+};
+
+static const unsigned short dep117[] = {
+  40, 41, 96, 174, 267, 2134, 2135, 2136, 2165, 2166, 2169, 2172, 2329, 2332,
+  2333, 2336, 2337, 2340, 2341, 4135, 16524, 16526,
+};
+
+static const unsigned short dep118[] = {
+  96, 267, 22645, 22646, 22647, 22649, 22650, 22652, 22653, 22809, 22812, 22813,
+  22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep119[] = {
+  40, 41, 96, 174, 267, 2134, 2135, 2136, 2165, 2166, 2169, 2172, 4135, 16524,
+  16526, 22809, 22812, 22813, 22816, 22817, 22820, 22821,
+};
+
+static const unsigned short dep120[] = {
+  19, 20, 40, 41, 96, 174, 267, 2134, 2135, 2136, 2165, 2166, 2169, 2172, 2310,
+  4135, 16524, 16526, 18746, 18748, 18749, 18751,
+};
+
+static const unsigned short dep121[] = {
+  40, 41, 96, 156, 174, 175, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172,
+  4135, 20613,
+};
+
+static const unsigned short dep122[] = {
+  96, 267, 2083, 2084, 2271, 2272,
+};
+
+static const unsigned short dep123[] = {
+  40, 41, 96, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2270, 2272,
+  4135, 20613,
+};
+
+static const unsigned short dep124[] = {
+  40, 41, 96, 174, 267, 2082, 2084, 2165, 2166, 2169, 2172, 2312, 4135, 20613,
+
+};
+
+static const unsigned short dep125[] = {
+  96, 267, 14454, 14456, 14457, 14459, 14460, 14462, 14620, 14621, 14624, 14625,
+  14628, 14629,
+};
+
+static const unsigned short dep126[] = {
+  40, 41, 96, 174, 267, 2137, 2138, 2139, 4135, 14620, 14621, 14624, 14625,
+  14628, 14629, 20613, 24693, 24694, 24697, 24700,
+};
+
+static const unsigned short dep127[] = {
+  96, 121, 123, 124, 126, 267, 288, 289, 292, 293,
+};
+
+static const unsigned short dep128[] = {
+  40, 41, 96, 174, 267, 288, 289, 292, 293, 4135, 24693, 24694, 24697, 24700,
+
+};
+
+static const unsigned short dep129[] = {
+  40, 41, 96, 174, 267, 2165, 2166, 2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep130[] = {
+  40, 41, 96, 118, 121, 124, 174, 267, 2312, 4135, 20613, 24693,
+};
+
+static const unsigned short dep131[] = {
+  6, 24, 26, 27, 96, 187, 213, 216, 267, 2081, 2269,
+};
+
+static const unsigned short dep132[] = {
+  40, 41, 96, 174, 187, 213, 215, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172,
+  2269, 4135, 20613,
+};
+
+static const unsigned short dep133[] = {
+  6, 24, 25, 26, 40, 41, 96, 174, 267, 2081, 2165, 2166, 2169, 2172, 2312, 4135,
+  20613,
+};
+
+static const unsigned short dep134[] = {
+  0, 40, 41, 96, 156, 174, 175, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep135[] = {
+  0, 96, 181, 267,
+};
+
+static const unsigned short dep136[] = {
+  0, 40, 41, 96, 156, 174, 175, 181, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep137[] = {
+  40, 41, 96, 174, 181, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep138[] = {
+  2, 28, 96, 183, 217, 267, 28852, 29002,
+};
+
+static const unsigned short dep139[] = {
+  1, 2, 28, 29, 96, 168, 169, 174, 183, 217, 267, 28852, 29002,
+};
+
+static const unsigned short dep140[] = {
+  1, 28, 29, 38, 40, 41, 96, 168, 169, 174, 183, 217, 267, 4135, 28852, 29002,
+
+};
+
+static const unsigned short dep141[] = {
+  0, 40, 41, 96, 174, 181, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep142[] = {
+  1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+  28, 29, 30, 31, 96, 182, 183, 184, 185, 186, 188, 189, 190, 191, 192, 193,
+  194, 195, 197, 198, 200, 201, 203, 204, 206, 207, 208, 209, 210, 211, 217,
+  218, 219, 267, 2071, 2081, 2260, 2269, 28852, 29002,
+};
+
+static const unsigned short dep143[] = {
+  29, 40, 41, 96, 134, 174, 182, 183, 184, 185, 186, 188, 189, 190, 191, 192,
+  193, 194, 195, 197, 198, 200, 201, 203, 204, 206, 207, 208, 209, 210, 211,
+  217, 218, 219, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2260, 2269,
+  4135, 20613, 28852, 29002,
+};
+
+static const unsigned short dep144[] = {
+  96, 267, 14463, 14465, 14466, 14468, 14497, 14498, 14513, 14630, 14631, 14651,
+  14652, 14654, 14655, 14664,
+};
+
+static const unsigned short dep145[] = {
+  40, 41, 96, 173, 174, 267, 2165, 2166, 2169, 2172, 4135, 14630, 14631, 14651,
+  14652, 14654, 14655, 14664,
+};
+
+static const unsigned short dep146[] = {
+  14463, 14465, 14466, 14468, 14497, 14498, 14513, 14630, 14631, 14651, 14652,
+  14654, 14655, 14664,
+};
+
+static const unsigned short dep147[] = {
+  173, 14630, 14631, 14651, 14652, 14654, 14655, 14664,
+};
+
+static const unsigned short dep148[] = {
+  96, 267, 14464, 14465, 14467, 14468, 14476, 14477, 14478, 14479, 14480, 14481,
+  14482, 14483, 14485, 14488, 14489, 14497, 14498, 14499, 14500, 14501, 14506,
+  14507, 14508, 14509, 14513, 14630, 14631, 14637, 14638, 14639, 14640, 14642,
+  14644, 14651, 14652, 14654, 14655, 14656, 14657, 14660, 14661, 14664,
+};
+
+static const unsigned short dep149[] = {
+  40, 41, 72, 96, 134, 174, 267, 2165, 2166, 2169, 2172, 4135, 14630, 14631,
+  14637, 14638, 14639, 14640, 14642, 14644, 14651, 14652, 14654, 14655, 14656,
+  14657, 14660, 14661, 14664,
+};
+
+static const unsigned short dep150[] = {
+  1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+  28, 29, 30, 31, 40, 41, 96, 134, 171, 174, 267, 2071, 2081, 2165, 2166, 2169,
+  2172, 2312, 4135, 20613, 28852,
+};
+
+static const unsigned short dep151[] = {
+  43, 44, 45, 46, 47, 48, 49, 50, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62, 63,
+  64, 65, 67, 69, 70, 71, 72, 93, 95, 96, 228, 229, 230, 231, 232, 233, 234,
+  235, 236, 237, 238, 240, 241, 242, 243, 244, 246, 248, 249, 250, 266, 267,
+  2116, 2295,
+};
+
+static const unsigned short dep152[] = {
+  40, 41, 95, 96, 134, 153, 174, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+  237, 238, 240, 241, 242, 243, 244, 246, 248, 249, 250, 266, 267, 2137, 2138,
+  2139, 2165, 2166, 2169, 2172, 2295, 4135, 20613,
+};
+
+static const unsigned short dep153[] = {
+  59, 94, 96, 239, 266, 267, 2139, 2312,
+};
+
+static const unsigned short dep154[] = {
+  40, 41, 43, 44, 46, 48, 49, 51, 52, 53, 54, 56, 57, 60, 61, 63, 64, 65, 66,
+  67, 69, 70, 71, 93, 94, 96, 134, 153, 174, 239, 266, 267, 2107, 2116, 2165,
+  2166, 2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep155[] = {
+  2, 28, 41, 96, 183, 217, 226, 267, 2139, 2312, 28852, 29002,
+};
+
+static const unsigned short dep156[] = {
+  2, 25, 26, 28, 29, 38, 40, 41, 96, 168, 169, 174, 183, 217, 226, 267, 2312,
+  4135, 20613, 28852, 29002,
+};
+
+static const unsigned short dep157[] = {
+  96, 128, 129, 131, 132, 136, 137, 140, 141, 142, 143, 144, 145, 146, 147,
+  149, 152, 153, 157, 158, 161, 162, 163, 164, 165, 167, 168, 170, 171, 172,
+  173, 175, 176, 177, 267, 294, 295, 299, 301, 302, 303, 304, 306, 308, 312,
+  315, 316, 318, 319, 320, 321, 323, 324, 325, 327, 328,
+};
+
+static const unsigned short dep158[] = {
+  40, 41, 72, 96, 134, 174, 267, 294, 295, 299, 301, 302, 303, 304, 306, 308,
+  312, 315, 316, 318, 319, 320, 321, 323, 324, 325, 327, 328, 2137, 2138, 2139,
+  2165, 2166, 2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep159[] = {
+  96, 127, 129, 130, 132, 161, 162, 177, 267, 294, 295, 315, 316, 318, 319,
+  328,
+};
+
+static const unsigned short dep160[] = {
+  40, 41, 96, 173, 174, 267, 294, 295, 315, 316, 318, 319, 328, 2137, 2138,
+  2139, 2165, 2166, 2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep161[] = {
+  40, 41, 96, 129, 132, 134, 137, 138, 141, 143, 145, 147, 149, 150, 152, 156,
+  157, 159, 160, 161, 162, 164, 165, 167, 169, 170, 172, 174, 176, 177, 267,
+  2165, 2166, 2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep162[] = {
+  40, 41, 96, 129, 132, 161, 162, 174, 177, 267, 2165, 2166, 2169, 2172, 2312,
+  4135, 20613,
+};
+
+static const unsigned short dep163[] = {
+  40, 41, 75, 76, 81, 83, 96, 110, 134, 163, 174, 178, 267, 2137, 2138, 2139,
+  2165, 2166, 2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep164[] = {
+  40, 41, 75, 76, 81, 83, 96, 110, 134, 135, 136, 138, 139, 163, 174, 178, 267,
+  2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep165[] = {
+  76, 77, 96, 100, 101, 254, 255, 267, 269, 270,
+};
+
+static const unsigned short dep166[] = {
+  40, 41, 47, 62, 77, 79, 85, 96, 98, 101, 134, 153, 174, 178, 254, 255, 267,
+  269, 270, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep167[] = {
+  40, 41, 47, 62, 77, 79, 96, 98, 101, 103, 105, 134, 153, 174, 178, 254, 255,
+  267, 269, 270, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep168[] = {
+  96, 267, 12466, 12467, 12617,
+};
+
+static const unsigned short dep169[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135,
+  12617, 20613,
+};
+
+static const unsigned short dep170[] = {
+  96, 267, 6218, 6219, 6396,
+};
+
+static const unsigned short dep171[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135,
+  6396, 20613,
+};
+
+static const unsigned short dep172[] = {
+  96, 267, 6236, 6409,
+};
+
+static const unsigned short dep173[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135,
+  6409, 20613,
+};
+
+static const unsigned short dep174[] = {
+  96, 267, 6254, 6255, 6256, 6257, 6420, 6422, 8469,
+};
+
+static const unsigned short dep175[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135,
+  6257, 6421, 6422, 8303, 8468, 20613,
+};
+
+static const unsigned short dep176[] = {
+  96, 267, 6258, 6259, 6423,
+};
+
+static const unsigned short dep177[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135,
+  6423, 20613,
+};
+
+static const unsigned short dep178[] = {
+  96, 267, 6260, 6424,
+};
+
+static const unsigned short dep179[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135,
+  6424, 20613,
+};
+
+static const unsigned short dep180[] = {
+  96, 267, 10349, 10515,
+};
+
+static const unsigned short dep181[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135,
+  10515, 20613,
+};
+
+static const unsigned short dep182[] = {
+  76, 77, 81, 82, 96, 100, 101, 254, 255, 257, 258, 267, 269, 270,
+};
+
+static const unsigned short dep183[] = {
+  40, 41, 47, 62, 77, 79, 82, 85, 96, 98, 101, 134, 153, 174, 178, 254, 255,
+  257, 259, 267, 269, 270, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135, 20613,
+
+};
+
+static const unsigned short dep184[] = {
+  76, 77, 96, 100, 101, 103, 104, 254, 255, 267, 269, 270, 271, 272,
+};
+
+static const unsigned short dep185[] = {
+  40, 41, 47, 62, 77, 79, 96, 98, 101, 103, 105, 134, 153, 174, 178, 254, 255,
+  267, 269, 270, 271, 272, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135, 20613,
+
+};
+
+static const unsigned short dep186[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2312,
+  4135, 12467, 20613,
+};
+
+static const unsigned short dep187[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2312,
+  4135, 6218, 20613,
+};
+
+static const unsigned short dep188[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2312,
+  4135, 6236, 20613,
+};
+
+static const unsigned short dep189[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2312,
+  4135, 6256, 8302, 20613,
+};
+
+static const unsigned short dep190[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2312,
+  4135, 6258, 20613,
+};
+
+static const unsigned short dep191[] = {
+  40, 41, 96, 134, 173, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172,
+  2312, 4135, 6259, 6260, 20613,
+};
+
+static const unsigned short dep192[] = {
+  40, 41, 96, 134, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2312,
+  4135, 10349, 20613,
+};
+
+static const unsigned short dep193[] = {
+  40, 41, 96, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2312, 4135,
+  6186, 20613,
+};
+
+static const unsigned short dep194[] = {
+  76, 78, 79, 96, 97, 98, 99, 253, 254, 267, 268, 269,
+};
+
+static const unsigned short dep195[] = {
+  40, 41, 77, 78, 82, 84, 96, 99, 101, 103, 106, 134, 174, 178, 253, 255, 267,
+  268, 270, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep196[] = {
+  76, 78, 79, 80, 96, 97, 98, 99, 102, 253, 254, 256, 267, 268, 269,
+};
+
+static const unsigned short dep197[] = {
+  40, 41, 77, 78, 80, 82, 84, 96, 99, 101, 102, 103, 106, 134, 174, 178, 253,
+  255, 256, 267, 268, 270, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135, 20613,
+
+};
+
+static const unsigned short dep198[] = {
+  76, 78, 79, 83, 84, 85, 96, 97, 98, 99, 253, 254, 259, 260, 267, 268, 269,
+
+};
+
+static const unsigned short dep199[] = {
+  40, 41, 77, 78, 82, 84, 96, 99, 101, 134, 174, 178, 253, 255, 258, 260, 267,
+  268, 270, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep200[] = {
+  76, 78, 79, 96, 97, 98, 99, 105, 106, 107, 253, 254, 267, 268, 269, 272, 273,
+
+};
+
+static const unsigned short dep201[] = {
+  40, 41, 77, 78, 96, 99, 101, 103, 106, 134, 174, 178, 253, 255, 267, 268,
+  270, 271, 273, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep202[] = {
+  40, 41, 46, 70, 96, 174, 178, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172,
+  2312, 4135, 20613,
+};
+
+static const unsigned short dep203[] = {
+  40, 41, 96, 174, 178, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2312,
+  4135, 20613,
+};
+
+static const unsigned short dep204[] = {
+  40, 41, 76, 81, 83, 96, 134, 174, 178, 267, 2137, 2138, 2139, 2165, 2166,
+  2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep205[] = {
+  40, 41, 96, 156, 174, 175, 267, 2134, 2135, 2136, 2137, 2138, 2139, 2165,
+  2166, 2169, 2172, 4135, 16524, 16526, 20613,
+};
+
+static const unsigned short dep206[] = {
+  40, 41, 76, 81, 83, 96, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172,
+  4135, 20613,
+};
+
+static const unsigned short dep207[] = {
+  40, 41, 77, 78, 96, 99, 134, 174, 253, 255, 267, 268, 270, 2137, 2138, 2139,
+  2165, 2166, 2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep208[] = {
+  40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136, 138,
+  139, 146, 163, 174, 178, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2312,
+  4135, 20613,
+};
+
+static const unsigned short dep209[] = {
+  5, 96, 186, 267, 2139, 2312,
+};
+
+static const unsigned short dep210[] = {
+  40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136, 138,
+  139, 146, 163, 174, 178, 186, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172,
+  2312, 4135, 20613,
+};
+
+static const unsigned short dep211[] = {
+  40, 41, 44, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136,
+  138, 139, 146, 148, 163, 174, 178, 267, 2137, 2138, 2139, 2165, 2166, 2169,
+  2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep212[] = {
+  0, 96, 181, 267, 2139, 2312,
+};
+
+static const unsigned short dep213[] = {
+  0, 40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136,
+  138, 139, 146, 163, 174, 178, 181, 267, 2137, 2138, 2139, 2165, 2166, 2169,
+  2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep214[] = {
+  0, 40, 41, 44, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135,
+  136, 138, 139, 146, 148, 163, 174, 178, 181, 267, 2137, 2138, 2139, 2165,
+  2166, 2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep215[] = {
+  31, 40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136,
+  138, 139, 146, 163, 174, 178, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172,
+  2312, 4135, 20613,
+};
+
+static const unsigned short dep216[] = {
+  0, 96, 181, 267, 2312, 26714,
+};
+
+static const unsigned short dep217[] = {
+  0, 96, 108, 181, 267, 274,
+};
+
+static const unsigned short dep218[] = {
+  0, 40, 41, 75, 76, 81, 83, 96, 110, 127, 128, 130, 131, 134, 135, 136, 138,
+  139, 146, 163, 174, 178, 181, 267, 274, 2137, 2138, 2139, 2165, 2166, 2169,
+  2172, 4135, 20613,
+};
+
+static const unsigned short dep219[] = {
+  0, 5, 40, 41, 75, 76, 81, 83, 96, 110, 127, 128, 130, 131, 134, 135, 136,
+  138, 139, 146, 163, 174, 178, 181, 267, 274, 2137, 2138, 2139, 2165, 2166,
+  2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep220[] = {
+  0, 31, 96, 108, 181, 219, 267, 274,
+};
+
+static const unsigned short dep221[] = {
+  0, 40, 41, 75, 76, 81, 83, 96, 110, 127, 128, 130, 131, 134, 135, 136, 138,
+  139, 146, 163, 174, 178, 181, 219, 267, 274, 2137, 2138, 2139, 2165, 2166,
+  2169, 2172, 4135, 20613,
+};
+
+static const unsigned short dep222[] = {
+  0, 96, 108, 181, 267, 274, 2139, 2312,
+};
+
+static const unsigned short dep223[] = {
+  0, 4, 40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135,
+  136, 138, 139, 146, 163, 174, 178, 181, 267, 274, 2137, 2138, 2139, 2165,
+  2166, 2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep224[] = {
+  0, 4, 5, 40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135,
+  136, 138, 139, 146, 163, 174, 178, 181, 267, 274, 2137, 2138, 2139, 2165,
+  2166, 2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep225[] = {
+  0, 40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136,
+  138, 139, 146, 163, 174, 178, 181, 267, 274, 2137, 2138, 2139, 2165, 2166,
+  2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep226[] = {
+  40, 41, 96, 174, 267, 2134, 2135, 2136, 2165, 2166, 2169, 2172, 2312, 4135,
+  16524, 16526, 20613,
+};
+
+static const unsigned short dep227[] = {
+  0, 40, 41, 75, 76, 81, 83, 96, 110, 127, 128, 130, 131, 134, 135, 136, 138,
+  139, 146, 163, 174, 178, 181, 267, 274, 2137, 2138, 2139, 2165, 2166, 2169,
+  2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep228[] = {
+  0, 31, 96, 108, 181, 219, 267, 274, 2139, 2312,
+};
+
+static const unsigned short dep229[] = {
+  0, 40, 41, 75, 76, 81, 83, 96, 110, 127, 128, 130, 131, 134, 135, 136, 138,
+  139, 146, 163, 174, 178, 181, 219, 267, 274, 2137, 2138, 2139, 2165, 2166,
+  2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep230[] = {
+  40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136, 138,
+  139, 146, 163, 174, 178, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2310,
+  4135, 16524, 16526, 18746, 18748, 18749, 18751, 20613,
+};
+
+static const unsigned short dep231[] = {
+  40, 41, 44, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136,
+  138, 139, 146, 148, 163, 174, 178, 267, 2137, 2138, 2139, 2165, 2166, 2169,
+  2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751, 20613,
+};
+
+static const unsigned short dep232[] = {
+  0, 96, 181, 267, 2135, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+};
+
+static const unsigned short dep233[] = {
+  0, 40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136,
+  138, 139, 146, 163, 174, 178, 181, 267, 2137, 2138, 2139, 2165, 2166, 2169,
+  2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751, 20613,
+};
+
+static const unsigned short dep234[] = {
+  0, 40, 41, 44, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135,
+  136, 138, 139, 146, 148, 163, 174, 178, 181, 267, 2137, 2138, 2139, 2165,
+  2166, 2169, 2172, 2310, 4135, 16524, 16526, 18746, 18748, 18749, 18751, 20613,
+
+};
+
+static const unsigned short dep235[] = {
+  0, 96, 181, 267, 2136, 2310, 18593, 18594, 18746, 18747, 18749, 18750,
+};
+
+static const unsigned short dep236[] = {
+  96, 267, 2135, 2139, 2310, 2312, 18593, 18594, 18746, 18747, 18749, 18750,
+
+};
+
+static const unsigned short dep237[] = {
+  40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136, 138,
+  139, 146, 163, 174, 178, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2310,
+  2312, 4135, 16524, 16526, 18746, 18748, 18749, 18751, 20613,
+};
+
+static const unsigned short dep238[] = {
+  40, 41, 44, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136,
+  138, 139, 146, 148, 163, 174, 178, 267, 2137, 2138, 2139, 2165, 2166, 2169,
+  2172, 2310, 2312, 4135, 16524, 16526, 18746, 18748, 18749, 18751, 20613,
+};
+
+static const unsigned short dep239[] = {
+  0, 96, 181, 267, 2135, 2139, 2310, 2312, 18593, 18594, 18746, 18747, 18749,
+  18750,
+};
+
+static const unsigned short dep240[] = {
+  0, 40, 41, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135, 136,
+  138, 139, 146, 163, 174, 178, 181, 267, 2137, 2138, 2139, 2165, 2166, 2169,
+  2172, 2310, 2312, 4135, 16524, 16526, 18746, 18748, 18749, 18751, 20613,
+};
+
+static const unsigned short dep241[] = {
+  0, 40, 41, 44, 75, 76, 81, 83, 96, 108, 110, 127, 128, 130, 131, 134, 135,
+  136, 138, 139, 146, 148, 163, 174, 178, 181, 267, 2137, 2138, 2139, 2165,
+  2166, 2169, 2172, 2310, 2312, 4135, 16524, 16526, 18746, 18748, 18749, 18751,
+  20613,
+};
+
+static const unsigned short dep242[] = {
+  0, 96, 181, 267, 2136, 2139, 2310, 2312, 18593, 18594, 18746, 18747, 18749,
+  18750,
+};
+
+static const unsigned short dep243[] = {
+  0, 40, 41, 75, 76, 81, 83, 96, 110, 127, 128, 130, 131, 134, 135, 136, 138,
+  139, 146, 163, 174, 178, 181, 267, 274, 2134, 2135, 2136, 2137, 2138, 2139,
+  2165, 2166, 2169, 2172, 4135, 16524, 16526, 20613,
+};
+
+static const unsigned short dep244[] = {
+  40, 41, 75, 96, 134, 148, 174, 267, 2165, 2166, 2169, 2172, 4135,
+};
+
+static const unsigned short dep245[] = {
+  40, 41, 75, 96, 134, 135, 139, 148, 174, 267, 2165, 2166, 2169, 2172, 4135,
+
+};
+
+static const unsigned short dep246[] = {
+  40, 41, 75, 96, 134, 148, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172,
+  2312, 4135, 20613,
+};
+
+static const unsigned short dep247[] = {
+  40, 41, 75, 96, 134, 135, 139, 148, 174, 267, 2137, 2138, 2139, 2165, 2166,
+  2169, 2172, 2312, 4135, 20613,
+};
+
+static const unsigned short dep248[] = {
+  40, 41, 96, 174, 267, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2310, 4135,
+  16524, 16526, 18746, 18748, 18749, 18751, 20613,
+};
+
+static const unsigned short dep249[] = {
+  0, 40, 41, 75, 76, 81, 83, 96, 110, 127, 128, 130, 131, 134, 135, 136, 138,
+  139, 146, 163, 174, 178, 181, 267, 274, 2134, 2135, 2136, 2137, 2138, 2139,
+  2165, 2166, 2169, 2172, 2312, 4135, 16524, 16526, 20613,
+};
+
+static const unsigned short dep250[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+  22, 24, 26, 27, 28, 29, 30, 31, 96, 182, 183, 184, 185, 186, 187, 188, 189,
+  190, 191, 192, 193, 194, 195, 197, 198, 200, 201, 203, 204, 206, 207, 208,
+  209, 210, 211, 213, 216, 217, 218, 219, 267, 2071, 2081, 2139, 2260, 2269,
+  2312, 28852, 29002,
+};
+
+static const unsigned short dep251[] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+  22, 24, 25, 26, 28, 29, 30, 31, 40, 41, 96, 134, 171, 174, 182, 183, 184,
+  185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 197, 198, 200, 201,
+  203, 204, 206, 207, 208, 209, 210, 211, 213, 215, 217, 218, 219, 267, 2071,
+  2081, 2137, 2138, 2139, 2165, 2166, 2169, 2172, 2260, 2269, 2312, 4135, 20613,
+  28852, 29002,
+};
+
+#define NELS(X) (sizeof(X)/sizeof(X[0]))
+static const struct ia64_opcode_dependency
+op_dependencies[] = {
+  { NELS(dep1), dep1, NELS(dep0), dep0, },
+  { NELS(dep3), dep3, NELS(dep2), dep2, },
+  { NELS(dep5), dep5, NELS(dep4), dep4, },
+  { NELS(dep7), dep7, NELS(dep6), dep6, },
+  { NELS(dep9), dep9, NELS(dep8), dep8, },
+  { NELS(dep11), dep11, NELS(dep10), dep10, },
+  { NELS(dep13), dep13, NELS(dep12), dep12, },
+  { NELS(dep15), dep15, NELS(dep14), dep14, },
+  { NELS(dep17), dep17, NELS(dep16), dep16, },
+  { NELS(dep19), dep19, NELS(dep18), dep18, },
+  { NELS(dep21), dep21, NELS(dep20), dep20, },
+  { NELS(dep23), dep23, NELS(dep22), dep22, },
+  { NELS(dep25), dep25, NELS(dep24), dep24, },
+  { NELS(dep27), dep27, NELS(dep26), dep26, },
+  { NELS(dep28), dep28, NELS(dep12), dep12, },
+  { NELS(dep30), dep30, NELS(dep29), dep29, },
+  { NELS(dep32), dep32, NELS(dep31), dep31, },
+  { NELS(dep33), dep33, NELS(dep12), dep12, },
+  { NELS(dep35), dep35, NELS(dep34), dep34, },
+  { NELS(dep37), dep37, NELS(dep36), dep36, },
+  { NELS(dep39), dep39, NELS(dep38), dep38, },
+  { NELS(dep40), dep40, NELS(dep29), dep29, },
+  { NELS(dep41), dep41, NELS(dep31), dep31, },
+  { NELS(dep43), dep43, NELS(dep42), dep42, },
+  { NELS(dep45), dep45, NELS(dep44), dep44, },
+  { NELS(dep47), dep47, NELS(dep46), dep46, },
+  { NELS(dep49), dep49, NELS(dep48), dep48, },
+  { NELS(dep51), dep51, NELS(dep50), dep50, },
+  { NELS(dep53), dep53, NELS(dep52), dep52, },
+  { NELS(dep55), dep55, NELS(dep54), dep54, },
+  { NELS(dep57), dep57, NELS(dep56), dep56, },
+  { NELS(dep59), dep59, NELS(dep58), dep58, },
+  { NELS(dep61), dep61, NELS(dep60), dep60, },
+  { NELS(dep63), dep63, NELS(dep62), dep62, },
+  { NELS(dep65), dep65, NELS(dep64), dep64, },
+  { NELS(dep66), dep66, NELS(dep31), dep31, },
+  { NELS(dep68), dep68, NELS(dep67), dep67, },
+  { NELS(dep70), dep70, NELS(dep69), dep69, },
+  { NELS(dep72), dep72, NELS(dep71), dep71, },
+  { NELS(dep74), dep74, NELS(dep73), dep73, },
+  { NELS(dep75), dep75, NELS(dep31), dep31, },
+  { NELS(dep77), dep77, NELS(dep76), dep76, },
+  { NELS(dep79), dep79, NELS(dep78), dep78, },
+  { NELS(dep81), dep81, NELS(dep80), dep80, },
+  { NELS(dep82), dep82, NELS(dep31), dep31, },
+  { NELS(dep83), dep83, NELS(dep31), dep31, },
+  { NELS(dep84), dep84, NELS(dep31), dep31, },
+  { NELS(dep85), dep85, NELS(dep31), dep31, },
+  { NELS(dep87), dep87, NELS(dep86), dep86, },
+  { NELS(dep89), dep89, NELS(dep88), dep88, },
+  { NELS(dep91), dep91, NELS(dep90), dep90, },
+  { NELS(dep93), dep93, NELS(dep92), dep92, },
+  { NELS(dep95), dep95, NELS(dep94), dep94, },
+  { NELS(dep97), dep97, NELS(dep96), dep96, },
+  { NELS(dep99), dep99, NELS(dep98), dep98, },
+  { NELS(dep101), dep101, NELS(dep100), dep100, },
+  { NELS(dep103), dep103, NELS(dep102), dep102, },
+  { NELS(dep105), dep105, NELS(dep104), dep104, },
+  { NELS(dep107), dep107, NELS(dep106), dep106, },
+  { NELS(dep109), dep109, NELS(dep108), dep108, },
+  { NELS(dep111), dep111, NELS(dep110), dep110, },
+  { NELS(dep113), dep113, NELS(dep112), dep112, },
+  { NELS(dep115), dep115, NELS(dep114), dep114, },
+  { NELS(dep117), dep117, NELS(dep116), dep116, },
+  { NELS(dep119), dep119, NELS(dep118), dep118, },
+  { NELS(dep120), dep120, NELS(dep62), dep62, },
+  { NELS(dep121), dep121, NELS(dep31), dep31, },
+  { NELS(dep123), dep123, NELS(dep122), dep122, },
+  { NELS(dep124), dep124, NELS(dep0), dep0, },
+  { NELS(dep126), dep126, NELS(dep125), dep125, },
+  { NELS(dep128), dep128, NELS(dep127), dep127, },
+  { NELS(dep129), dep129, NELS(dep0), dep0, },
+  { NELS(dep130), dep130, NELS(dep0), dep0, },
+  { NELS(dep132), dep132, NELS(dep131), dep131, },
+  { NELS(dep133), dep133, NELS(dep0), dep0, },
+  { NELS(dep134), dep134, NELS(dep31), dep31, },
+  { NELS(dep136), dep136, NELS(dep135), dep135, },
+  { NELS(dep137), dep137, NELS(dep135), dep135, },
+  { NELS(dep139), dep139, NELS(dep138), dep138, },
+  { NELS(dep140), dep140, NELS(dep138), dep138, },
+  { NELS(dep141), dep141, NELS(dep135), dep135, },
+  { NELS(dep143), dep143, NELS(dep142), dep142, },
+  { NELS(dep145), dep145, NELS(dep144), dep144, },
+  { NELS(dep147), dep147, NELS(dep146), dep146, },
+  { NELS(dep149), dep149, NELS(dep148), dep148, },
+  { NELS(dep150), dep150, NELS(dep0), dep0, },
+  { NELS(dep152), dep152, NELS(dep151), dep151, },
+  { NELS(dep154), dep154, NELS(dep153), dep153, },
+  { NELS(dep156), dep156, NELS(dep155), dep155, },
+  { NELS(dep158), dep158, NELS(dep157), dep157, },
+  { NELS(dep160), dep160, NELS(dep159), dep159, },
+  { NELS(dep161), dep161, NELS(dep0), dep0, },
+  { NELS(dep162), dep162, NELS(dep0), dep0, },
+  { NELS(dep163), dep163, NELS(dep0), dep0, },
+  { NELS(dep164), dep164, NELS(dep31), dep31, },
+  { NELS(dep166), dep166, NELS(dep165), dep165, },
+  { NELS(dep167), dep167, NELS(dep165), dep165, },
+  { NELS(dep169), dep169, NELS(dep168), dep168, },
+  { NELS(dep171), dep171, NELS(dep170), dep170, },
+  { NELS(dep173), dep173, NELS(dep172), dep172, },
+  { NELS(dep175), dep175, NELS(dep174), dep174, },
+  { NELS(dep177), dep177, NELS(dep176), dep176, },
+  { NELS(dep179), dep179, NELS(dep178), dep178, },
+  { NELS(dep181), dep181, NELS(dep180), dep180, },
+  { NELS(dep183), dep183, NELS(dep182), dep182, },
+  { NELS(dep185), dep185, NELS(dep184), dep184, },
+  { NELS(dep186), dep186, NELS(dep0), dep0, },
+  { NELS(dep187), dep187, NELS(dep0), dep0, },
+  { NELS(dep188), dep188, NELS(dep0), dep0, },
+  { NELS(dep189), dep189, NELS(dep0), dep0, },
+  { NELS(dep190), dep190, NELS(dep0), dep0, },
+  { NELS(dep191), dep191, NELS(dep0), dep0, },
+  { NELS(dep192), dep192, NELS(dep0), dep0, },
+  { NELS(dep193), dep193, NELS(dep0), dep0, },
+  { NELS(dep195), dep195, NELS(dep194), dep194, },
+  { NELS(dep197), dep197, NELS(dep196), dep196, },
+  { NELS(dep199), dep199, NELS(dep198), dep198, },
+  { NELS(dep201), dep201, NELS(dep200), dep200, },
+  { NELS(dep202), dep202, NELS(dep0), dep0, },
+  { NELS(dep203), dep203, NELS(dep0), dep0, },
+  { NELS(dep204), dep204, NELS(dep0), dep0, },
+  { NELS(dep205), dep205, NELS(dep31), dep31, },
+  { NELS(dep206), dep206, NELS(dep31), dep31, },
+  { NELS(dep207), dep207, NELS(dep194), dep194, },
+  { NELS(dep208), dep208, NELS(dep0), dep0, },
+  { NELS(dep210), dep210, NELS(dep209), dep209, },
+  { NELS(dep211), dep211, NELS(dep0), dep0, },
+  { NELS(dep213), dep213, NELS(dep212), dep212, },
+  { NELS(dep214), dep214, NELS(dep212), dep212, },
+  { NELS(dep215), dep215, NELS(dep0), dep0, },
+  { NELS(dep213), dep213, NELS(dep216), dep216, },
+  { NELS(dep218), dep218, NELS(dep217), dep217, },
+  { NELS(dep219), dep219, NELS(dep217), dep217, },
+  { NELS(dep221), dep221, NELS(dep220), dep220, },
+  { NELS(dep223), dep223, NELS(dep222), dep222, },
+  { NELS(dep224), dep224, NELS(dep222), dep222, },
+  { NELS(dep225), dep225, NELS(dep222), dep222, },
+  { NELS(dep226), dep226, NELS(dep0), dep0, },
+  { NELS(dep227), dep227, NELS(dep222), dep222, },
+  { NELS(dep229), dep229, NELS(dep228), dep228, },
+  { NELS(dep230), dep230, NELS(dep62), dep62, },
+  { NELS(dep231), dep231, NELS(dep62), dep62, },
+  { NELS(dep233), dep233, NELS(dep232), dep232, },
+  { NELS(dep234), dep234, NELS(dep232), dep232, },
+  { NELS(dep233), dep233, NELS(dep235), dep235, },
+  { NELS(dep237), dep237, NELS(dep236), dep236, },
+  { NELS(dep238), dep238, NELS(dep236), dep236, },
+  { NELS(dep240), dep240, NELS(dep239), dep239, },
+  { NELS(dep241), dep241, NELS(dep239), dep239, },
+  { NELS(dep240), dep240, NELS(dep242), dep242, },
+  { NELS(dep243), dep243, NELS(dep217), dep217, },
+  { NELS(dep244), dep244, NELS(dep31), dep31, },
+  { NELS(dep245), dep245, NELS(dep31), dep31, },
+  { NELS(dep246), dep246, NELS(dep0), dep0, },
+  { NELS(dep247), dep247, NELS(dep0), dep0, },
+  { NELS(dep248), dep248, NELS(dep62), dep62, },
+  { NELS(dep249), dep249, NELS(dep222), dep222, },
+  { 0, NULL, 0, NULL, },
+  { NELS(dep251), dep251, NELS(dep250), dep250, },
+};
+
+static const struct ia64_completer_table
+completer_table[] = {
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 88 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 88 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 576, -1, 0, 1, 6 },
+  { 0x0, 0x0, 0, 639, -1, 0, 1, 17 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 157 },
+  { 0x0, 0x0, 0, 738, -1, 0, 1, 17 },
+  { 0x0, 0x0, 0, 2164, -1, 0, 1, 10 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 9 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 13 },
+  { 0x1, 0x1, 0, -1, -1, 13, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, 2372, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, 1122, -1, 0, 1, 122 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 44 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 78 },
+  { 0x0, 0x0, 0, 2212, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, 2439, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, 2216, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, 2218, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, 2448, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, 2451, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, 2473, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, 2476, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 24 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 24 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 24 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 24 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 35 },
+  { 0x0, 0x0, 0, 2484, -1, 0, 1, 29 },
+  { 0x0, 0x0, 0, 1391, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 157 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 77 },
+  { 0x0, 0x0, 0, 1439, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1448, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1457, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1459, -1, 0, 1, 125 },
+  { 0x0, 0x0, 0, 1461, -1, 0, 1, 125 },
+  { 0x0, 0x0, 0, 1470, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1479, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1488, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1497, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1506, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1515, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1525, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1535, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1545, -1, 0, 1, 124 },
+  { 0x0, 0x0, 0, 1554, -1, 0, 1, 140 },
+  { 0x0, 0x0, 0, 1560, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1566, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1572, -1, 0, 1, 140 },
+  { 0x0, 0x0, 0, 1578, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1584, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1590, -1, 0, 1, 140 },
+  { 0x0, 0x0, 0, 1596, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1602, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1608, -1, 0, 1, 140 },
+  { 0x0, 0x0, 0, 1614, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1620, -1, 0, 1, 140 },
+  { 0x0, 0x0, 0, 1626, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1632, -1, 0, 1, 140 },
+  { 0x0, 0x0, 0, 1638, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1644, -1, 0, 1, 140 },
+  { 0x0, 0x0, 0, 1650, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1656, -1, 0, 1, 145 },
+  { 0x0, 0x0, 0, 1660, -1, 0, 1, 151 },
+  { 0x0, 0x0, 0, 1664, -1, 0, 1, 153 },
+  { 0x0, 0x0, 0, 1668, -1, 0, 1, 153 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 79 },
+  { 0x0, 0x0, 0, 256, -1, 0, 1, 40 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 67 },
+  { 0x1, 0x1, 0, 1148, -1, 20, 1, 67 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 68 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 69 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 69 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 70 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 71 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 72 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 86 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 87 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 89 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 90 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 91 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 92 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 97 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 98 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 99 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 100 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 101 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 102 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 103 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 106 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 107 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 108 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 109 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 110 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 111 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 112 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 113 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 158 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 158 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 158 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 71 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 157 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2824, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2825, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2176, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2177, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2839, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2840, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2841, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2842, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2843, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2826, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, 2827, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 11 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 84 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 83 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x1, 0x1, 0, -1, -1, 13, 1, 0 },
+  { 0x0, 0x0, 0, 2845, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 84 },
+  { 0x0, 0x0, 0, 1948, -1, 0, 1, 131 },
+  { 0x0, 0x0, 0, 1950, -1, 0, 1, 138 },
+  { 0x0, 0x0, 0, 1952, -1, 0, 1, 132 },
+  { 0x0, 0x0, 0, 1954, -1, 0, 1, 132 },
+  { 0x0, 0x0, 0, 1956, -1, 0, 1, 131 },
+  { 0x0, 0x0, 0, 1958, -1, 0, 1, 138 },
+  { 0x0, 0x0, 0, 1960, -1, 0, 1, 131 },
+  { 0x0, 0x0, 0, 1962, -1, 0, 1, 138 },
+  { 0x0, 0x0, 0, 1965, -1, 0, 1, 131 },
+  { 0x0, 0x0, 0, 1968, -1, 0, 1, 138 },
+  { 0x0, 0x0, 0, 1971, -1, 0, 1, 150 },
+  { 0x0, 0x0, 0, 1972, -1, 0, 1, 156 },
+  { 0x0, 0x0, 0, 1973, -1, 0, 1, 150 },
+  { 0x0, 0x0, 0, 1974, -1, 0, 1, 156 },
+  { 0x0, 0x0, 0, 1975, -1, 0, 1, 150 },
+  { 0x0, 0x0, 0, 1976, -1, 0, 1, 156 },
+  { 0x0, 0x0, 0, 1977, -1, 0, 1, 150 },
+  { 0x0, 0x0, 0, 1978, -1, 0, 1, 156 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 82 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 120 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 118 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 120 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 119 },
+  { 0x0, 0x0, 0, 1669, -1, 0, 1, 136 },
+  { 0x0, 0x0, 0, 1670, -1, 0, 1, 136 },
+  { 0x0, 0x0, 0, 1671, -1, 0, 1, 136 },
+  { 0x0, 0x0, 0, 1672, -1, 0, 1, 136 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 0, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 1, 223, -1, 0, 1, 12 },
+  { 0x1, 0x1, 2, -1, -1, 27, 1, 12 },
+  { 0x0, 0x0, 3, -1, 1322, 0, 0, -1 },
+  { 0x0, 0x0, 3, -1, 1323, 0, 0, -1 },
+  { 0x1, 0x1, 3, 2715, 1432, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2716, 1441, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2717, 1450, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2718, 1463, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2719, 1472, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2720, 1481, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2721, 1490, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2722, 1499, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2723, 1508, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2724, 1517, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2725, 1527, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2726, 1537, 33, 1, 127 },
+  { 0x1, 0x1, 3, 2727, 1550, 33, 1, 142 },
+  { 0x1, 0x1, 3, 2728, 1556, 33, 1, 147 },
+  { 0x1, 0x1, 3, 2729, 1562, 33, 1, 147 },
+  { 0x1, 0x1, 3, 2730, 1568, 33, 1, 142 },
+  { 0x1, 0x1, 3, 2731, 1574, 33, 1, 147 },
+  { 0x1, 0x1, 3, 2732, 1580, 33, 1, 147 },
+  { 0x1, 0x1, 3, 2733, 1586, 33, 1, 142 },
+  { 0x1, 0x1, 3, 2734, 1592, 33, 1, 147 },
+  { 0x1, 0x1, 3, 2735, 1598, 33, 1, 147 },
+  { 0x1, 0x1, 3, 2736, 1604, 33, 1, 142 },
+  { 0x1, 0x1, 3, 2737, 1610, 33, 1, 147 },
+  { 0x1, 0x1, 3, 2738, 1616, 33, 1, 142 },
+  { 0x1, 0x1, 3, 2739, 1622, 33, 1, 147 },
+  { 0x1, 0x1, 3, 2740, 1628, 33, 1, 142 },
+  { 0x1, 0x1, 3, 2741, 1634, 33, 1, 147 },
+  { 0x1, 0x1, 3, 2742, 1640, 33, 1, 142 },
+  { 0x1, 0x1, 3, 2743, 1646, 33, 1, 147 },
+  { 0x1, 0x1, 3, 2744, 1652, 33, 1, 147 },
+  { 0x1, 0x1, 3, -1, -1, 27, 1, 40 },
+  { 0x0, 0x0, 4, 2178, 1407, 0, 1, 135 },
+  { 0x0, 0x0, 4, 2179, 1409, 0, 1, 135 },
+  { 0x0, 0x0, 4, 2180, 1411, 0, 1, 134 },
+  { 0x0, 0x0, 4, 2181, 1413, 0, 1, 134 },
+  { 0x0, 0x0, 4, 2182, 1415, 0, 1, 134 },
+  { 0x0, 0x0, 4, 2183, 1417, 0, 1, 134 },
+  { 0x0, 0x0, 4, 2184, 1419, 0, 1, 134 },
+  { 0x0, 0x0, 4, 2185, 1421, 0, 1, 134 },
+  { 0x0, 0x0, 4, 2186, 1423, 0, 1, 134 },
+  { 0x0, 0x0, 4, 2187, 1425, 0, 1, 134 },
+  { 0x0, 0x0, 4, 2188, 1427, 0, 1, 136 },
+  { 0x0, 0x0, 4, 2189, 1429, 0, 1, 136 },
+  { 0x1, 0x1, 4, -1, 1436, 33, 1, 130 },
+  { 0x5, 0x5, 4, 534, 1435, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1445, 33, 1, 130 },
+  { 0x5, 0x5, 4, 535, 1444, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1454, 33, 1, 130 },
+  { 0x5, 0x5, 4, 536, 1453, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1458, 32, 1, 125 },
+  { 0x1, 0x1, 4, -1, 1460, 32, 1, 125 },
+  { 0x1, 0x1, 4, -1, 1467, 33, 1, 130 },
+  { 0x5, 0x5, 4, 537, 1466, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1476, 33, 1, 130 },
+  { 0x5, 0x5, 4, 538, 1475, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1485, 33, 1, 130 },
+  { 0x5, 0x5, 4, 539, 1484, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1494, 33, 1, 130 },
+  { 0x5, 0x5, 4, 540, 1493, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1503, 33, 1, 130 },
+  { 0x5, 0x5, 4, 541, 1502, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1512, 33, 1, 130 },
+  { 0x5, 0x5, 4, 542, 1511, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1522, 33, 1, 130 },
+  { 0x5, 0x5, 4, 1018, 1520, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1532, 33, 1, 130 },
+  { 0x5, 0x5, 4, 1019, 1530, 32, 1, 124 },
+  { 0x1, 0x1, 4, -1, 1542, 33, 1, 130 },
+  { 0x5, 0x5, 4, 1020, 1540, 32, 1, 124 },
+  { 0x1, 0x21, 10, 1991, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 1992, -1, 12, 1, 3 },
+  { 0x1, 0x21, 10, 410, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2048, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, -1, 2049, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2050, 0, 0, -1 },
+  { 0x0, 0x0, 10, 1995, -1, 0, 1, 3 },
+  { 0x1, 0x1, 10, 1996, -1, 12, 1, 3 },
+  { 0x1, 0x1, 10, 1997, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 1998, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, 420, -1, 0, 1, 3 },
+  { 0x1, 0x1, 10, 2054, -1, 12, 1, 3 },
+  { 0x1, 0x1, 10, 424, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2056, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, 428, -1, 0, 1, 3 },
+  { 0x1, 0x1, 10, 2058, -1, 12, 1, 3 },
+  { 0x1, 0x1, 10, 432, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2060, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, 436, -1, 0, 1, 3 },
+  { 0x1, 0x1, 10, 2062, -1, 12, 1, 3 },
+  { 0x1, 0x1, 10, 440, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2064, -1, 12, 1, 3 },
+  { 0x1, 0x21, 10, 2011, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2012, -1, 12, 1, 3 },
+  { 0x1, 0x21, 10, 450, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2070, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, -1, 2071, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2072, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2075, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2076, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2077, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2078, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2079, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2080, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2081, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2082, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2083, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2084, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2085, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2086, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2087, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2088, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2089, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2090, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2091, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2092, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2093, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2094, 0, 0, -1 },
+  { 0x1, 0x21, 10, 2015, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2016, -1, 12, 1, 3 },
+  { 0x1, 0x21, 10, 458, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2096, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, -1, 2097, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2098, 0, 0, -1 },
+  { 0x0, 0x0, 10, 2019, -1, 0, 1, 3 },
+  { 0x1, 0x1, 10, 2020, -1, 12, 1, 3 },
+  { 0x1, 0x1, 10, 2021, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2022, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, 468, -1, 0, 1, 3 },
+  { 0x1, 0x1, 10, 2102, -1, 12, 1, 3 },
+  { 0x1, 0x1, 10, 472, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2104, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, 476, -1, 0, 1, 3 },
+  { 0x1, 0x1, 10, 2106, -1, 12, 1, 3 },
+  { 0x1, 0x1, 10, 480, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2108, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, 484, -1, 0, 1, 3 },
+  { 0x1, 0x1, 10, 2110, -1, 12, 1, 3 },
+  { 0x1, 0x1, 10, 488, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2112, -1, 12, 1, 3 },
+  { 0x1, 0x21, 10, 2035, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2036, -1, 12, 1, 3 },
+  { 0x1, 0x21, 10, 498, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 10, 2118, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, -1, 2119, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2120, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2123, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2124, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2125, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2126, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2127, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2128, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2129, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2130, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2131, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2132, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2133, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2134, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2135, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2136, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2137, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2138, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2139, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2140, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2141, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2142, 0, 0, -1 },
+  { 0x1, 0x1, 10, 2039, -1, 36, 1, 3 },
+  { 0x1000001, 0x1000001, 10, 2040, -1, 12, 1, 3 },
+  { 0x1, 0x1, 10, 2041, -1, 36, 1, 3 },
+  { 0x1000001, 0x1000001, 10, 2042, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, -1, 2143, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2145, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2147, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2149, 0, 0, -1 },
+  { 0x1, 0x1, 10, 2043, -1, 36, 1, 3 },
+  { 0x1000001, 0x1000001, 10, 2044, -1, 12, 1, 3 },
+  { 0x1, 0x1, 10, 2045, -1, 36, 1, 3 },
+  { 0x1000001, 0x1000001, 10, 2046, -1, 12, 1, 3 },
+  { 0x0, 0x0, 10, -1, 2151, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2153, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2155, 0, 0, -1 },
+  { 0x0, 0x0, 10, -1, 2157, 0, 0, -1 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x200001, 0x4200001, 11, 1993, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 298, -1, 33, 1, 3 },
+  { 0x0, 0x0, 11, 2051, -1, 0, 1, 3 },
+  { 0x1, 0x1, 11, 2052, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 1999, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x0, 0x0, 11, 306, -1, 0, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x200001, 0x200001, 11, 2001, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 308, -1, 33, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 2003, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x0, 0x0, 11, 310, -1, 0, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x200001, 0x200001, 11, 2005, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 312, -1, 33, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 2007, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x0, 0x0, 11, 314, -1, 0, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x200001, 0x200001, 11, 2009, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 316, -1, 33, 1, 3 },
+  { 0x0, 0x0, 11, 2065, -1, 0, 1, 3 },
+  { 0x1, 0x1, 11, 2066, -1, 12, 1, 3 },
+  { 0x1, 0x1, 11, 2067, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 11, 2068, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x200001, 0x4200001, 11, 2013, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 320, -1, 33, 1, 3 },
+  { 0x0, 0x0, 11, 2073, -1, 0, 1, 3 },
+  { 0x1, 0x1, 11, 2074, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x200001, 0x4200001, 11, 2017, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 346, -1, 33, 1, 3 },
+  { 0x0, 0x0, 11, 2099, -1, 0, 1, 3 },
+  { 0x1, 0x1, 11, 2100, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 2023, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x0, 0x0, 11, 354, -1, 0, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x200001, 0x200001, 11, 2025, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 356, -1, 33, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 2027, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x0, 0x0, 11, 358, -1, 0, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x200001, 0x200001, 11, 2029, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 360, -1, 33, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 2031, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x0, 0x0, 11, 362, -1, 0, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x200001, 0x200001, 11, 2033, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 364, -1, 33, 1, 3 },
+  { 0x0, 0x0, 11, 2113, -1, 0, 1, 3 },
+  { 0x1, 0x1, 11, 2114, -1, 12, 1, 3 },
+  { 0x1, 0x1, 11, 2115, -1, 33, 1, 3 },
+  { 0x200001, 0x200001, 11, 2116, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x200001, 0x4200001, 11, 2037, -1, 12, 1, 3 },
+  { 0x2, 0x3, 11, -1, -1, 37, 1, 5 },
+  { 0x1, 0x1, 11, 368, -1, 33, 1, 3 },
+  { 0x0, 0x0, 11, 2121, -1, 0, 1, 3 },
+  { 0x1, 0x1, 11, 2122, -1, 12, 1, 3 },
+  { 0x1, 0x1, 11, -1, -1, 36, 1, 5 },
+  { 0x1, 0x1, 11, -1, -1, 36, 1, 5 },
+  { 0x1, 0x1, 11, -1, -1, 36, 1, 5 },
+  { 0x1, 0x1, 11, -1, -1, 36, 1, 5 },
+  { 0x1, 0x1, 11, 2144, -1, 36, 1, 3 },
+  { 0x1000001, 0x1000001, 11, 2146, -1, 12, 1, 3 },
+  { 0x1, 0x1, 11, 2148, -1, 36, 1, 3 },
+  { 0x1000001, 0x1000001, 11, 2150, -1, 12, 1, 3 },
+  { 0x1, 0x1, 11, -1, -1, 36, 1, 5 },
+  { 0x1, 0x1, 11, -1, -1, 36, 1, 5 },
+  { 0x1, 0x1, 11, -1, -1, 36, 1, 5 },
+  { 0x1, 0x1, 11, -1, -1, 36, 1, 5 },
+  { 0x1, 0x1, 11, 2152, -1, 36, 1, 3 },
+  { 0x1000001, 0x1000001, 11, 2154, -1, 12, 1, 3 },
+  { 0x1, 0x1, 11, 2156, -1, 36, 1, 3 },
+  { 0x1000001, 0x1000001, 11, 2158, -1, 12, 1, 3 },
+  { 0x0, 0x0, 12, -1, -1, 0, 1, 14 },
+  { 0x0, 0x0, 12, -1, -1, 0, 1, 14 },
+  { 0x0, 0x0, 12, -1, -1, 0, 1, 14 },
+  { 0x1, 0x1, 13, 270, 1434, 34, 1, 124 },
+  { 0x1, 0x1, 13, 272, 1443, 34, 1, 124 },
+  { 0x1, 0x1, 13, 274, 1452, 34, 1, 124 },
+  { 0x1, 0x1, 13, 278, 1465, 34, 1, 124 },
+  { 0x1, 0x1, 13, 280, 1474, 34, 1, 124 },
+  { 0x1, 0x1, 13, 282, 1483, 34, 1, 124 },
+  { 0x1, 0x1, 13, 284, 1492, 34, 1, 124 },
+  { 0x1, 0x1, 13, 286, 1501, 34, 1, 124 },
+  { 0x1, 0x1, 13, 288, 1510, 34, 1, 124 },
+  { 0x1, 0x1, 13, 290, 1519, 34, 1, 124 },
+  { 0x1, 0x1, 13, 292, 1529, 34, 1, 124 },
+  { 0x1, 0x1, 13, 294, 1539, 34, 1, 124 },
+  { 0x0, 0x0, 19, -1, 777, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 778, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 779, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 780, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 781, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 782, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 783, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 784, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 785, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 786, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 787, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 788, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 789, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 790, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 791, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 792, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 793, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 794, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 795, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 796, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 797, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 798, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 799, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 800, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 801, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 802, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 803, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 804, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 805, 0, 0, -1 },
+  { 0x0, 0x0, 19, -1, 806, 0, 0, -1 },
+  { 0x0, 0x0, 20, -1, 2793, 0, 0, -1 },
+  { 0x0, 0x0, 20, -1, 2794, 0, 0, -1 },
+  { 0x0, 0x0, 20, -1, 2809, 0, 0, -1 },
+  { 0x0, 0x0, 20, -1, 2810, 0, 0, -1 },
+  { 0x0, 0x0, 20, -1, 2815, 0, 0, -1 },
+  { 0x0, 0x0, 20, -1, 2816, 0, 0, -1 },
+  { 0x0, 0x0, 21, 813, 2805, 0, 0, -1 },
+  { 0x0, 0x0, 21, 814, 2807, 0, 0, -1 },
+  { 0x0, 0x0, 23, -1, 2803, 0, 0, -1 },
+  { 0x0, 0x0, 23, -1, 2804, 0, 0, -1 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, 1254, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 6 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 7 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 8 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 15 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, 1275, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 18 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 19 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 20 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, 1308, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 17 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 35, 1, 21 },
+  { 0x1, 0x1, 24, -1, -1, 33, 1, 76 },
+  { 0x1, 0x1, 24, -1, -1, 33, 1, 76 },
+  { 0x1, 0x1, 24, 1324, 1437, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1325, 1446, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1326, 1455, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1327, 1468, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1328, 1477, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1329, 1486, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1330, 1495, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1331, 1504, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1332, 1513, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1333, 1523, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1334, 1533, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1335, 1543, 35, 1, 130 },
+  { 0x1, 0x1, 24, 1336, 1552, 35, 1, 144 },
+  { 0x1, 0x1, 24, 1337, 1558, 35, 1, 149 },
+  { 0x1, 0x1, 24, 1338, 1564, 35, 1, 149 },
+  { 0x1, 0x1, 24, 1339, 1570, 35, 1, 144 },
+  { 0x1, 0x1, 24, 1340, 1576, 35, 1, 149 },
+  { 0x1, 0x1, 24, 1341, 1582, 35, 1, 149 },
+  { 0x1, 0x1, 24, 1342, 1588, 35, 1, 144 },
+  { 0x1, 0x1, 24, 1343, 1594, 35, 1, 149 },
+  { 0x1, 0x1, 24, 1344, 1600, 35, 1, 149 },
+  { 0x1, 0x1, 24, 1345, 1606, 35, 1, 144 },
+  { 0x1, 0x1, 24, 1346, 1612, 35, 1, 149 },
+  { 0x1, 0x1, 24, 1347, 1618, 35, 1, 144 },
+  { 0x1, 0x1, 24, 1348, 1624, 35, 1, 149 },
+  { 0x1, 0x1, 24, 1349, 1630, 35, 1, 144 },
+  { 0x1, 0x1, 24, 1350, 1636, 35, 1, 149 },
+  { 0x1, 0x1, 24, 1351, 1642, 35, 1, 144 },
+  { 0x1, 0x1, 24, 1352, 1648, 35, 1, 149 },
+  { 0x1, 0x1, 24, 1353, 1654, 35, 1, 149 },
+  { 0x0, 0x0, 33, 2787, 2785, 0, 0, -1 },
+  { 0x0, 0x0, 33, 2790, 2788, 0, 0, -1 },
+  { 0x0, 0x0, 33, 2796, 2795, 0, 0, -1 },
+  { 0x0, 0x0, 33, 2798, 2797, 0, 0, -1 },
+  { 0x0, 0x0, 33, 2812, 2811, 0, 0, -1 },
+  { 0x0, 0x0, 33, 2814, 2813, 0, 0, -1 },
+  { 0x0, 0x0, 35, -1, 2806, 0, 0, -1 },
+  { 0x0, 0x0, 35, -1, 2808, 0, 0, -1 },
+  { 0x1, 0x1, 38, -1, 2256, 37, 1, 29 },
+  { 0x1, 0x1, 38, -1, 2315, 37, 1, 29 },
+  { 0x0, 0x0, 38, -1, 2318, 0, 0, -1 },
+  { 0x1, 0x1, 38, -1, -1, 37, 1, 29 },
+  { 0x1, 0x1, 38, -1, 2323, 37, 1, 29 },
+  { 0x0, 0x0, 38, -1, 2326, 0, 0, -1 },
+  { 0x1, 0x1, 38, -1, -1, 37, 1, 29 },
+  { 0x0, 0x0, 38, -1, 2329, 0, 0, -1 },
+  { 0x1, 0x1, 38, -1, -1, 37, 1, 29 },
+  { 0x1, 0x1, 38, -1, 2332, 37, 1, 29 },
+  { 0x1, 0x1, 38, -1, 2335, 37, 1, 29 },
+  { 0x1, 0x1, 38, -1, 2368, 37, 1, 29 },
+  { 0x3, 0x3, 38, -1, -1, 30, 1, 137 },
+  { 0x0, 0x0, 38, 1124, -1, 0, 1, 95 },
+  { 0x0, 0x0, 38, -1, -1, 0, 1, 104 },
+  { 0x0, 0x0, 38, 1130, -1, 0, 1, 116 },
+  { 0x3, 0x3, 38, -1, -1, 30, 1, 155 },
+  { 0x0, 0x0, 38, 1131, -1, 0, 1, 40 },
+  { 0x0, 0x0, 40, -1, 955, 0, 0, -1 },
+  { 0x0, 0x0, 40, -1, 963, 0, 0, -1 },
+  { 0x0, 0x0, 40, 1133, 959, 0, 0, -1 },
+  { 0x3, 0x3, 40, -1, 604, 33, 1, 6 },
+  { 0x18000001, 0x18000001, 40, -1, 612, 6, 1, 7 },
+  { 0x3, 0x3, 40, 1134, 608, 33, 1, 6 },
+  { 0x0, 0x0, 40, -1, 967, 0, 0, -1 },
+  { 0x3, 0x3, 40, -1, 624, 33, 1, 8 },
+  { 0x0, 0x0, 40, -1, 971, 0, 0, -1 },
+  { 0x3, 0x3, 40, -1, 636, 33, 1, 15 },
+  { 0x0, 0x0, 40, -1, 976, 0, 0, -1 },
+  { 0x0, 0x0, 40, -1, 980, 0, 0, -1 },
+  { 0x3, 0x3, 40, -1, 659, 33, 1, 17 },
+  { 0x3, 0x3, 40, -1, 663, 33, 1, 17 },
+  { 0x0, 0x0, 40, -1, 984, 0, 0, -1 },
+  { 0x0, 0x0, 40, -1, 988, 0, 0, -1 },
+  { 0x3, 0x3, 40, -1, 683, 33, 1, 18 },
+  { 0x18000001, 0x18000001, 40, -1, 687, 6, 1, 18 },
+  { 0x0, 0x0, 40, -1, 992, 0, 0, -1 },
+  { 0x3, 0x3, 40, -1, 699, 33, 1, 19 },
+  { 0x0, 0x0, 40, -1, 996, 0, 0, -1 },
+  { 0x0, 0x0, 40, -1, 1000, 0, 0, -1 },
+  { 0x3, 0x3, 40, -1, 719, 33, 1, 20 },
+  { 0x18000001, 0x18000001, 40, -1, 723, 6, 1, 20 },
+  { 0x0, 0x0, 40, -1, 1004, 0, 0, -1 },
+  { 0x3, 0x3, 40, -1, 735, 33, 1, 21 },
+  { 0x0, 0x0, 40, -1, 1009, 0, 0, -1 },
+  { 0x0, 0x0, 40, -1, 1013, 0, 0, -1 },
+  { 0x3, 0x3, 40, -1, 758, 33, 1, 17 },
+  { 0x3, 0x3, 40, -1, 762, 33, 1, 17 },
+  { 0x0, 0x0, 40, -1, 1017, 0, 0, -1 },
+  { 0x3, 0x3, 40, -1, 774, 33, 1, 21 },
+  { 0x0, 0x0, 41, 833, 954, 0, 0, -1 },
+  { 0x0, 0x0, 41, 834, 962, 0, 0, -1 },
+  { 0x0, 0x0, 41, 835, 958, 0, 0, -1 },
+  { 0x1, 0x1, 41, 836, 603, 34, 1, 6 },
+  { 0x10000001, 0x10000001, 41, 837, 611, 6, 1, 7 },
+  { 0x1, 0x1, 41, 838, 607, 34, 1, 6 },
+  { 0x0, 0x0, 41, 839, 966, 0, 0, -1 },
+  { 0x1, 0x1, 41, 840, 623, 34, 1, 8 },
+  { 0x0, 0x0, 41, 841, 970, 0, 0, -1 },
+  { 0x1, 0x1, 41, 842, 635, 34, 1, 15 },
+  { 0x0, 0x0, 41, 843, 975, 0, 0, -1 },
+  { 0x0, 0x0, 41, 844, 979, 0, 0, -1 },
+  { 0x1, 0x1, 41, 845, 658, 34, 1, 17 },
+  { 0x1, 0x1, 41, 846, 662, 34, 1, 17 },
+  { 0x0, 0x0, 41, 847, 983, 0, 0, -1 },
+  { 0x0, 0x0, 41, 848, 987, 0, 0, -1 },
+  { 0x1, 0x1, 41, 849, 682, 34, 1, 18 },
+  { 0x10000001, 0x10000001, 41, 850, 686, 6, 1, 18 },
+  { 0x0, 0x0, 41, 851, 991, 0, 0, -1 },
+  { 0x1, 0x1, 41, 852, 698, 34, 1, 19 },
+  { 0x0, 0x0, 41, 853, 995, 0, 0, -1 },
+  { 0x0, 0x0, 41, 854, 999, 0, 0, -1 },
+  { 0x1, 0x1, 41, 855, 718, 34, 1, 20 },
+  { 0x10000001, 0x10000001, 41, 856, 722, 6, 1, 20 },
+  { 0x0, 0x0, 41, 857, 1003, 0, 0, -1 },
+  { 0x1, 0x1, 41, 858, 734, 34, 1, 21 },
+  { 0x0, 0x0, 41, 859, 1008, 0, 0, -1 },
+  { 0x0, 0x0, 41, 860, 1012, 0, 0, -1 },
+  { 0x1, 0x1, 41, 861, 757, 34, 1, 17 },
+  { 0x1, 0x1, 41, 862, 761, 34, 1, 17 },
+  { 0x0, 0x0, 41, 863, 1016, 0, 0, -1 },
+  { 0x1, 0x1, 41, 864, 773, 34, 1, 21 },
+  { 0x800001, 0x800001, 41, -1, 1138, 4, 1, 16 },
+  { 0x1, 0x1, 41, 2202, 1136, 4, 1, 16 },
+  { 0x1, 0x1, 41, 939, 1141, 4, 1, 22 },
+  { 0x2, 0x3, 41, -1, 1146, 20, 1, 67 },
+  { 0x1, 0x1, 41, 2203, 1144, 21, 1, 67 },
+  { 0x0, 0x0, 42, -1, -1, 0, 1, 80 },
+  { 0x0, 0x0, 42, -1, -1, 0, 1, 80 },
+  { 0x0, 0x0, 42, -1, -1, 0, 1, 123 },
+  { 0x1, 0x1, 44, 1354, 295, 38, 1, 1 },
+  { 0x1, 0x1, 44, 1355, 297, 38, 1, 1 },
+  { 0x0, 0x0, 44, -1, 300, 0, 0, -1 },
+  { 0x0, 0x0, 44, -1, 414, 0, 0, -1 },
+  { 0x1, 0x1, 44, 1359, 317, 38, 1, 1 },
+  { 0x1, 0x1, 44, 1360, 319, 38, 1, 1 },
+  { 0x0, 0x0, 44, -1, 322, 0, 0, -1 },
+  { 0x0, 0x0, 44, -1, 454, 0, 0, -1 },
+  { 0x0, 0x0, 44, -1, 324, 0, 0, -1 },
+  { 0x0, 0x0, 44, -1, 342, 0, 0, -1 },
+  { 0x1, 0x1, 44, 1366, 343, 38, 1, 1 },
+  { 0x1, 0x1, 44, 1367, 345, 38, 1, 1 },
+  { 0x0, 0x0, 44, -1, 348, 0, 0, -1 },
+  { 0x0, 0x0, 44, -1, 462, 0, 0, -1 },
+  { 0x1, 0x1, 44, 1371, 365, 38, 1, 1 },
+  { 0x1, 0x1, 44, 1372, 367, 38, 1, 1 },
+  { 0x0, 0x0, 44, -1, 370, 0, 0, -1 },
+  { 0x0, 0x0, 44, -1, 502, 0, 0, -1 },
+  { 0x0, 0x0, 44, -1, 372, 0, 0, -1 },
+  { 0x0, 0x0, 44, -1, 390, 0, 0, -1 },
+  { 0x0, 0x0, 44, 1230, 2263, 0, 0, -1 },
+  { 0x0, 0x0, 44, 1231, 2271, 0, 1, 54 },
+  { 0x0, 0x0, 44, 1232, 2938, 0, 1, 54 },
+  { 0x0, 0x0, 44, 1233, 2339, 0, 0, -1 },
+  { 0x0, 0x0, 44, 1234, -1, 0, 1, 49 },
+  { 0x0, 0x0, 44, 1102, -1, 0, 1, 0 },
+  { 0x0, 0x0, 44, 1103, -1, 0, 1, 0 },
+  { 0x0, 0x0, 44, 1104, -1, 0, 1, 0 },
+  { 0x1, 0x1, 45, -1, 1658, 30, 1, 152 },
+  { 0x1, 0x1, 45, 945, 1657, 30, 1, 151 },
+  { 0x1, 0x1, 45, -1, 1662, 30, 1, 154 },
+  { 0x1, 0x1, 45, 946, 1661, 30, 1, 153 },
+  { 0x1, 0x1, 45, -1, 1666, 30, 1, 154 },
+  { 0x1, 0x1, 45, 947, 1665, 30, 1, 153 },
+  { 0x3, 0x3, 46, -1, 1142, 3, 1, 22 },
+  { 0x1, 0x1, 47, 2223, -1, 30, 1, 137 },
+  { 0x1, 0x1, 47, 2254, -1, 30, 1, 155 },
+  { 0x0, 0x0, 49, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 49, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 49, -1, -1, 0, 1, 40 },
+  { 0x1, 0x1, 56, -1, 1659, 31, 1, 152 },
+  { 0x1, 0x1, 56, -1, 1663, 31, 1, 154 },
+  { 0x1, 0x1, 56, -1, 1667, 31, 1, 154 },
+  { 0x0, 0x0, 56, -1, -1, 0, 1, 94 },
+  { 0x2, 0x3, 56, -1, -1, 27, 1, 94 },
+  { 0x1, 0x1, 56, -1, -1, 28, 1, 94 },
+  { 0x0, 0x0, 65, 14, 574, 0, 1, 6 },
+  { 0x0, 0x0, 65, 1255, 577, 0, 1, 6 },
+  { 0x1, 0x1, 65, 1256, 579, 33, 1, 6 },
+  { 0x1, 0x1, 65, 1257, 581, 34, 1, 6 },
+  { 0x3, 0x3, 65, 1258, 583, 33, 1, 6 },
+  { 0x0, 0x0, 65, 1259, 585, 0, 1, 6 },
+  { 0x1, 0x1, 65, 1260, 587, 33, 1, 6 },
+  { 0x1, 0x1, 65, 1261, 589, 34, 1, 6 },
+  { 0x3, 0x3, 65, 1262, 591, 33, 1, 6 },
+  { 0x1, 0x1, 65, 1263, 593, 6, 1, 7 },
+  { 0x8000001, 0x8000001, 65, 1264, 595, 6, 1, 7 },
+  { 0x10000001, 0x10000001, 65, 1265, 597, 6, 1, 7 },
+  { 0x18000001, 0x18000001, 65, 1266, 599, 6, 1, 7 },
+  { 0x0, 0x0, 65, 1267, 613, 0, 1, 8 },
+  { 0x1, 0x1, 65, 1268, 615, 33, 1, 8 },
+  { 0x1, 0x1, 65, 1269, 617, 34, 1, 8 },
+  { 0x3, 0x3, 65, 1270, 619, 33, 1, 8 },
+  { 0x0, 0x0, 65, 1271, 625, 0, 1, 15 },
+  { 0x1, 0x1, 65, 1272, 627, 33, 1, 15 },
+  { 0x1, 0x1, 65, 1273, 629, 34, 1, 15 },
+  { 0x3, 0x3, 65, 1274, 631, 33, 1, 15 },
+  { 0x0, 0x0, 65, 15, 637, 0, 1, 17 },
+  { 0x0, 0x0, 65, 1276, 640, 0, 1, 17 },
+  { 0x1, 0x1, 65, 1277, 642, 33, 1, 17 },
+  { 0x1, 0x1, 65, 1278, 644, 34, 1, 17 },
+  { 0x3, 0x3, 65, 1279, 646, 33, 1, 17 },
+  { 0x0, 0x0, 65, 1280, 648, 0, 1, 17 },
+  { 0x1, 0x1, 65, 1281, 650, 33, 1, 17 },
+  { 0x1, 0x1, 65, 1282, 652, 34, 1, 17 },
+  { 0x3, 0x3, 65, 1283, 654, 33, 1, 17 },
+  { 0x0, 0x0, 65, 1284, 664, 0, 1, 18 },
+  { 0x1, 0x1, 65, 1285, 666, 33, 1, 18 },
+  { 0x1, 0x1, 65, 1286, 668, 34, 1, 18 },
+  { 0x3, 0x3, 65, 1287, 670, 33, 1, 18 },
+  { 0x1, 0x1, 65, 1288, 672, 6, 1, 18 },
+  { 0x8000001, 0x8000001, 65, 1289, 674, 6, 1, 18 },
+  { 0x10000001, 0x10000001, 65, 1290, 676, 6, 1, 18 },
+  { 0x18000001, 0x18000001, 65, 1291, 678, 6, 1, 18 },
+  { 0x0, 0x0, 65, 1292, 688, 0, 1, 19 },
+  { 0x1, 0x1, 65, 1293, 690, 33, 1, 19 },
+  { 0x1, 0x1, 65, 1294, 692, 34, 1, 19 },
+  { 0x3, 0x3, 65, 1295, 694, 33, 1, 19 },
+  { 0x0, 0x0, 65, 1296, 700, 0, 1, 20 },
+  { 0x1, 0x1, 65, 1297, 702, 33, 1, 20 },
+  { 0x1, 0x1, 65, 1298, 704, 34, 1, 20 },
+  { 0x3, 0x3, 65, 1299, 706, 33, 1, 20 },
+  { 0x1, 0x1, 65, 1300, 708, 6, 1, 20 },
+  { 0x8000001, 0x8000001, 65, 1301, 710, 6, 1, 20 },
+  { 0x10000001, 0x10000001, 65, 1302, 712, 6, 1, 20 },
+  { 0x18000001, 0x18000001, 65, 1303, 714, 6, 1, 20 },
+  { 0x0, 0x0, 65, 1304, 724, 0, 1, 21 },
+  { 0x1, 0x1, 65, 1305, 726, 33, 1, 21 },
+  { 0x1, 0x1, 65, 1306, 728, 34, 1, 21 },
+  { 0x3, 0x3, 65, 1307, 730, 33, 1, 21 },
+  { 0x0, 0x0, 65, 17, 736, 0, 1, 17 },
+  { 0x0, 0x0, 65, 1309, 739, 0, 1, 17 },
+  { 0x1, 0x1, 65, 1310, 741, 33, 1, 17 },
+  { 0x1, 0x1, 65, 1311, 743, 34, 1, 17 },
+  { 0x3, 0x3, 65, 1312, 745, 33, 1, 17 },
+  { 0x0, 0x0, 65, 1313, 747, 0, 1, 17 },
+  { 0x1, 0x1, 65, 1314, 749, 33, 1, 17 },
+  { 0x1, 0x1, 65, 1315, 751, 34, 1, 17 },
+  { 0x3, 0x3, 65, 1316, 753, 33, 1, 17 },
+  { 0x0, 0x0, 65, 1317, 763, 0, 1, 21 },
+  { 0x1, 0x1, 65, 1318, 765, 33, 1, 21 },
+  { 0x1, 0x1, 65, 1319, 767, 34, 1, 21 },
+  { 0x3, 0x3, 65, 1320, 769, 33, 1, 21 },
+  { 0x3, 0x3, 66, 543, 1521, 33, 1, 129 },
+  { 0x3, 0x3, 66, 544, 1531, 33, 1, 129 },
+  { 0x3, 0x3, 66, 545, 1541, 33, 1, 129 },
+  { 0x0, 0x0, 66, -1, 1546, 0, 1, 140 },
+  { 0x0, 0x0, 66, -1, 1547, 0, 1, 145 },
+  { 0x0, 0x0, 66, -1, 1548, 0, 1, 145 },
+  { 0x0, 0x0, 107, 1028, 2311, 0, 0, -1 },
+  { 0x0, 0x0, 107, 1029, 2830, 0, 1, 29 },
+  { 0x0, 0x0, 107, 1030, 2352, 0, 0, -1 },
+  { 0x0, 0x0, 107, 1031, 2834, 0, 1, 29 },
+  { 0x0, 0x0, 109, -1, 2313, 0, 0, -1 },
+  { 0x1, 0x1, 109, -1, 2831, 27, 1, 29 },
+  { 0x0, 0x0, 109, -1, 2354, 0, 0, -1 },
+  { 0x1, 0x1, 109, -1, 2835, 27, 1, 29 },
+  { 0x0, 0x0, 110, 1033, -1, 0, 1, 115 },
+  { 0x1, 0x1, 111, -1, -1, 27, 1, 115 },
+  { 0x0, 0x0, 112, 1064, 2860, 0, 1, 1 },
+  { 0x0, 0x0, 112, 1065, 2863, 0, 1, 1 },
+  { 0x0, 0x0, 112, 1206, 303, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1207, 307, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1167, 430, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1168, 438, 0, 0, -1 },
+  { 0x0, 0x0, 112, -1, 446, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1066, 2876, 0, 1, 1 },
+  { 0x0, 0x0, 112, 1067, 2879, 0, 1, 1 },
+  { 0x0, 0x0, 112, -1, 328, 0, 0, -1 },
+  { 0x0, 0x0, 112, -1, 332, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1215, 333, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1216, 337, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1068, 2900, 0, 1, 1 },
+  { 0x0, 0x0, 112, 1069, 2903, 0, 1, 1 },
+  { 0x0, 0x0, 112, 1219, 351, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1220, 355, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1180, 478, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1181, 486, 0, 0, -1 },
+  { 0x0, 0x0, 112, -1, 494, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1373, 2914, 0, 1, 1 },
+  { 0x0, 0x0, 112, 1374, 2916, 0, 1, 1 },
+  { 0x0, 0x0, 112, -1, 376, 0, 0, -1 },
+  { 0x0, 0x0, 112, -1, 380, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1228, 381, 0, 0, -1 },
+  { 0x0, 0x0, 112, 1229, 385, 0, 0, -1 },
+  { 0x0, 0x0, 112, -1, 2281, 0, 0, -1 },
+  { 0x1, 0x9, 112, -1, 2285, 33, 1, 54 },
+  { 0x1, 0x9, 112, -1, 2947, 33, 1, 54 },
+  { 0x2, 0x3, 112, 1390, 2348, 27, 1, 49 },
+  { 0x1, 0x1, 114, 1356, 2861, 37, 1, 1 },
+  { 0x1, 0x1, 114, 1357, 2864, 37, 1, 1 },
+  { 0x1, 0x1, 114, 1361, 2877, 37, 1, 1 },
+  { 0x1, 0x1, 114, 1362, 2880, 37, 1, 1 },
+  { 0x1, 0x1, 114, 1368, 2901, 37, 1, 1 },
+  { 0x1, 0x1, 114, 1369, 2904, 37, 1, 1 },
+  { 0x0, 0x0, 114, -1, 2924, 0, 1, 1 },
+  { 0x0, 0x0, 114, -1, 2925, 0, 1, 1 },
+  { 0x0, 0x0, 115, 1105, 2856, 0, 1, 1 },
+  { 0x0, 0x0, 115, 1106, 2858, 0, 1, 1 },
+  { 0x0, 0x0, 115, 1165, 301, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1166, 305, 0, 0, -1 },
+  { 0x0, 0x0, 115, -1, 434, 0, 0, -1 },
+  { 0x0, 0x0, 115, -1, 442, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1210, 444, 0, 0, -1 },
+  { 0x0, 0x0, 115, -1, 2874, 0, 1, 1 },
+  { 0x0, 0x0, 115, -1, 2875, 0, 1, 1 },
+  { 0x0, 0x0, 115, 1213, 326, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1214, 330, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1174, 335, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1175, 339, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1109, 2896, 0, 1, 1 },
+  { 0x0, 0x0, 115, 1110, 2898, 0, 1, 1 },
+  { 0x0, 0x0, 115, 1178, 349, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1179, 353, 0, 0, -1 },
+  { 0x0, 0x0, 115, -1, 482, 0, 0, -1 },
+  { 0x0, 0x0, 115, -1, 490, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1223, 492, 0, 0, -1 },
+  { 0x0, 0x0, 115, -1, 2912, 0, 1, 1 },
+  { 0x0, 0x0, 115, -1, 2913, 0, 1, 1 },
+  { 0x0, 0x0, 115, 1226, 374, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1227, 378, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1187, 383, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1188, 387, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1060, 2279, 0, 0, -1 },
+  { 0x0, 0x0, 115, 1061, 2283, 0, 1, 54 },
+  { 0x0, 0x0, 115, 1062, 2946, 0, 1, 54 },
+  { 0x0, 0x0, 115, 1063, 2347, 0, 1, 49 },
+  { 0x1, 0x1, 115, -1, -1, 27, 1, 0 },
+  { 0x1, 0x1, 115, -1, -1, 27, 1, 0 },
+  { 0x1, 0x1, 115, -1, -1, 27, 1, 0 },
+  { 0x1, 0x1, 116, -1, 2857, 37, 1, 1 },
+  { 0x1, 0x1, 116, -1, 2859, 37, 1, 1 },
+  { 0x0, 0x0, 116, -1, 2884, 0, 1, 1 },
+  { 0x0, 0x0, 116, -1, 2885, 0, 1, 1 },
+  { 0x1, 0x1, 116, -1, 2897, 37, 1, 1 },
+  { 0x1, 0x1, 116, -1, 2899, 37, 1, 1 },
+  { 0x0, 0x0, 116, -1, 2922, 0, 1, 1 },
+  { 0x0, 0x0, 116, -1, 2923, 0, 1, 1 },
+  { 0x0, 0x0, 117, 1158, -1, 0, 1, 0 },
+  { 0x0, 0x0, 117, 1159, -1, 0, 1, 0 },
+  { 0x0, 0x0, 117, 1160, -1, 0, 1, 0 },
+  { 0x3, 0x3, 117, 1118, -1, 34, 1, 33 },
+  { 0x3, 0x3, 117, 1119, -1, 34, 1, 40 },
+  { 0x1, 0x1, 119, -1, -1, 35, 1, 33 },
+  { 0x1, 0x1, 119, -1, -1, 35, 1, 40 },
+  { 0x0, 0x0, 120, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 120, -1, -1, 0, 1, 66 },
+  { 0x1, 0x1, 120, -1, -1, 36, 1, 122 },
+  { 0x0, 0x0, 120, -1, -1, 0, 1, 40 },
+  { 0x1, 0x1, 120, -1, -1, 27, 1, 96 },
+  { 0x0, 0x0, 120, -1, -1, 0, 1, 105 },
+  { 0x0, 0x0, 120, -1, -1, 0, 1, 73 },
+  { 0x0, 0x0, 120, -1, -1, 0, 1, 73 },
+  { 0x0, 0x0, 120, -1, -1, 0, 1, 74 },
+  { 0x0, 0x0, 120, -1, -1, 0, 1, 40 },
+  { 0x1, 0x1, 120, -1, -1, 27, 1, 117 },
+  { 0x1, 0x1, 120, -1, -1, 27, 1, 40 },
+  { 0x0, 0x0, 120, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 121, -1, 2786, 0, 0, -1 },
+  { 0x0, 0x0, 121, -1, 2789, 0, 0, -1 },
+  { 0x1, 0x1, 122, -1, -1, 35, 1, 16 },
+  { 0x1, 0x1, 122, -1, -1, 35, 1, 16 },
+  { 0x1, 0x1, 122, -1, -1, 35, 1, 16 },
+  { 0x1, 0x1, 122, -1, -1, 35, 1, 16 },
+  { 0x1, 0x1, 122, -1, -1, 35, 1, 22 },
+  { 0x1, 0x1, 122, -1, -1, 35, 1, 22 },
+  { 0x1, 0x1, 122, -1, -1, 35, 1, 22 },
+  { 0x1, 0x1, 122, -1, -1, 35, 1, 22 },
+  { 0x1, 0x1, 122, -1, -1, 23, 1, 67 },
+  { 0x1, 0x1, 122, -1, -1, 23, 1, 67 },
+  { 0x1, 0x1, 122, -1, -1, 23, 1, 67 },
+  { 0x1, 0x1, 122, -1, -1, 23, 1, 67 },
+  { 0x1, 0x1, 122, 900, -1, 23, 1, 67 },
+  { 0x9, 0x9, 122, 901, -1, 20, 1, 67 },
+  { 0x0, 0x0, 126, 2165, -1, 0, 1, 0 },
+  { 0x0, 0x0, 126, 2166, -1, 0, 1, 0 },
+  { 0x1, 0x1, 126, -1, -1, 28, 1, 33 },
+  { 0x1, 0x1, 126, -1, -1, 27, 1, 33 },
+  { 0x1, 0x1, 126, -1, -1, 29, 1, 0 },
+  { 0x1, 0x1, 126, -1, -1, 29, 1, 0 },
+  { 0x1, 0x1, 126, -1, -1, 29, 1, 0 },
+  { 0x1, 0x1, 126, -1, -1, 29, 1, 0 },
+  { 0x0, 0x0, 126, -1, -1, 0, 1, 114 },
+  { 0x1, 0x1, 126, -1, -1, 29, 1, 0 },
+  { 0x1, 0x1, 126, -1, -1, 29, 1, 0 },
+  { 0x1, 0x1, 126, -1, -1, 29, 1, 0 },
+  { 0x0, 0x0, 126, 1116, -1, 0, 1, 33 },
+  { 0x0, 0x0, 126, 1244, -1, 0, 1, 40 },
+  { 0x0, 0x0, 140, 1194, 2852, 0, 1, 1 },
+  { 0x0, 0x0, 140, 1195, 2854, 0, 1, 1 },
+  { 0x0, 0x0, 140, 1036, 302, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1037, 422, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1076, 311, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1077, 315, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1078, 443, 0, 0, -1 },
+  { 0x0, 0x0, 140, -1, 2872, 0, 1, 1 },
+  { 0x0, 0x0, 140, -1, 2873, 0, 1, 1 },
+  { 0x0, 0x0, 140, 1081, 325, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1082, 329, 0, 0, -1 },
+  { 0x0, 0x0, 140, -1, 336, 0, 0, -1 },
+  { 0x0, 0x0, 140, -1, 340, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1198, 2892, 0, 1, 1 },
+  { 0x0, 0x0, 140, 1199, 2894, 0, 1, 1 },
+  { 0x0, 0x0, 140, 1049, 350, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1050, 470, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1089, 359, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1090, 363, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1091, 491, 0, 0, -1 },
+  { 0x0, 0x0, 140, -1, 2910, 0, 1, 1 },
+  { 0x0, 0x0, 140, -1, 2911, 0, 1, 1 },
+  { 0x0, 0x0, 140, 1094, 373, 0, 0, -1 },
+  { 0x0, 0x0, 140, 1095, 377, 0, 0, -1 },
+  { 0x0, 0x0, 140, -1, 384, 0, 0, -1 },
+  { 0x0, 0x0, 140, -1, 388, 0, 0, -1 },
+  { 0x0, 0x0, 140, 2974, 2267, 0, 0, -1 },
+  { 0x1, 0x1, 140, 2975, 2275, 33, 1, 54 },
+  { 0x1, 0x1, 140, 2976, 2940, 33, 1, 54 },
+  { 0x0, 0x0, 140, 2977, 2341, 0, 0, -1 },
+  { 0x1, 0x1, 140, 2978, -1, 28, 1, 49 },
+  { 0x1, 0x1, 141, -1, 2853, 37, 1, 1 },
+  { 0x1, 0x1, 141, -1, 2855, 37, 1, 1 },
+  { 0x0, 0x0, 141, -1, 2882, 0, 1, 1 },
+  { 0x0, 0x0, 141, -1, 2883, 0, 1, 1 },
+  { 0x1, 0x1, 141, -1, 2893, 37, 1, 1 },
+  { 0x1, 0x1, 141, -1, 2895, 37, 1, 1 },
+  { 0x0, 0x0, 141, -1, 2920, 0, 1, 1 },
+  { 0x0, 0x0, 141, -1, 2921, 0, 1, 1 },
+  { 0x1, 0x1, 144, 899, 1140, 3, 1, 22 },
+  { 0x0, 0x0, 145, 2167, -1, 0, 1, 33 },
+  { 0x0, 0x0, 146, 905, 2846, 0, 1, 1 },
+  { 0x0, 0x0, 146, 906, 2849, 0, 1, 1 },
+  { 0x0, 0x0, 146, -1, 304, 0, 0, -1 },
+  { 0x0, 0x0, 146, -1, 426, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1038, 309, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1039, 313, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1040, 445, 0, 0, -1 },
+  { 0x0, 0x0, 146, 909, 2866, 0, 1, 1 },
+  { 0x0, 0x0, 146, 910, 2869, 0, 1, 1 },
+  { 0x0, 0x0, 146, 1043, 327, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1044, 331, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1083, 334, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1084, 338, 0, 0, -1 },
+  { 0x0, 0x0, 146, 915, 2886, 0, 1, 1 },
+  { 0x0, 0x0, 146, 916, 2889, 0, 1, 1 },
+  { 0x0, 0x0, 146, -1, 352, 0, 0, -1 },
+  { 0x0, 0x0, 146, -1, 474, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1051, 357, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1052, 361, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1053, 493, 0, 0, -1 },
+  { 0x0, 0x0, 146, 919, 2906, 0, 1, 1 },
+  { 0x0, 0x0, 146, 920, 2908, 0, 1, 1 },
+  { 0x0, 0x0, 146, 1056, 375, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1057, 379, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1096, 382, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1097, 386, 0, 0, -1 },
+  { 0x0, 0x0, 146, 1189, 2265, 0, 0, -1 },
+  { 0x1, 0x1, 146, 1190, 2273, 36, 1, 54 },
+  { 0x1, 0x1, 146, 1191, 2939, 36, 1, 54 },
+  { 0x0, 0x0, 146, 1192, 2340, 0, 0, -1 },
+  { 0x1, 0x1, 146, 1193, -1, 27, 1, 49 },
+  { 0x1, 0x1, 147, -1, 2848, 37, 1, 1 },
+  { 0x1, 0x1, 147, -1, 2851, 37, 1, 1 },
+  { 0x1, 0x1, 147, -1, 2868, 37, 1, 1 },
+  { 0x1, 0x1, 147, -1, 2871, 37, 1, 1 },
+  { 0x1, 0x1, 147, -1, 2888, 37, 1, 1 },
+  { 0x1, 0x1, 147, -1, 2891, 37, 1, 1 },
+  { 0x0, 0x0, 147, -1, 2918, 0, 1, 1 },
+  { 0x0, 0x0, 147, -1, 2919, 0, 1, 1 },
+  { 0x0, 0x0, 148, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 148, 1117, -1, 0, 1, 40 },
+  { 0x0, 0x0, 149, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 149, -1, -1, 0, 1, 66 },
+  { 0x0, 0x0, 149, -1, 2926, 0, 1, 63 },
+  { 0x0, 0x0, 149, -1, 2927, 0, 1, 63 },
+  { 0x0, 0x0, 149, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 149, -1, -1, 0, 1, 81 },
+  { 0x0, 0x0, 149, -1, -1, 0, 1, 81 },
+  { 0x0, 0x0, 149, -1, -1, 0, 1, 85 },
+  { 0x0, 0x0, 149, -1, -1, 0, 1, 40 },
+  { 0x1, 0x1, 150, -1, 575, 12, 1, 6 },
+  { 0x1, 0x1, 150, -1, 578, 12, 1, 6 },
+  { 0x200001, 0x200001, 150, -1, 580, 12, 1, 6 },
+  { 0x400001, 0x400001, 150, -1, 582, 12, 1, 6 },
+  { 0x600001, 0x600001, 150, -1, 584, 12, 1, 6 },
+  { 0x1, 0x1, 150, -1, 586, 12, 1, 6 },
+  { 0x200001, 0x200001, 150, -1, 588, 12, 1, 6 },
+  { 0x400001, 0x400001, 150, -1, 590, 12, 1, 6 },
+  { 0x600001, 0x600001, 150, -1, 592, 12, 1, 6 },
+  { 0x41, 0x41, 150, -1, 594, 6, 1, 7 },
+  { 0x8000041, 0x8000041, 150, -1, 596, 6, 1, 7 },
+  { 0x10000041, 0x10000041, 150, -1, 598, 6, 1, 7 },
+  { 0x18000041, 0x18000041, 150, -1, 600, 6, 1, 7 },
+  { 0x1, 0x1, 150, -1, 614, 12, 1, 8 },
+  { 0x200001, 0x200001, 150, -1, 616, 12, 1, 8 },
+  { 0x400001, 0x400001, 150, -1, 618, 12, 1, 8 },
+  { 0x600001, 0x600001, 150, -1, 620, 12, 1, 8 },
+  { 0x1, 0x1, 150, -1, 626, 12, 1, 15 },
+  { 0x200001, 0x200001, 150, -1, 628, 12, 1, 15 },
+  { 0x400001, 0x400001, 150, -1, 630, 12, 1, 15 },
+  { 0x600001, 0x600001, 150, -1, 632, 12, 1, 15 },
+  { 0x1, 0x1, 150, -1, 638, 12, 1, 17 },
+  { 0x1, 0x1, 150, -1, 641, 12, 1, 17 },
+  { 0x200001, 0x200001, 150, -1, 643, 12, 1, 17 },
+  { 0x400001, 0x400001, 150, -1, 645, 12, 1, 17 },
+  { 0x600001, 0x600001, 150, -1, 647, 12, 1, 17 },
+  { 0x1, 0x1, 150, -1, 649, 12, 1, 17 },
+  { 0x200001, 0x200001, 150, -1, 651, 12, 1, 17 },
+  { 0x400001, 0x400001, 150, -1, 653, 12, 1, 17 },
+  { 0x600001, 0x600001, 150, -1, 655, 12, 1, 17 },
+  { 0x1, 0x1, 150, -1, 665, 12, 1, 18 },
+  { 0x200001, 0x200001, 150, -1, 667, 12, 1, 18 },
+  { 0x400001, 0x400001, 150, -1, 669, 12, 1, 18 },
+  { 0x600001, 0x600001, 150, -1, 671, 12, 1, 18 },
+  { 0x41, 0x41, 150, -1, 673, 6, 1, 18 },
+  { 0x8000041, 0x8000041, 150, -1, 675, 6, 1, 18 },
+  { 0x10000041, 0x10000041, 150, -1, 677, 6, 1, 18 },
+  { 0x18000041, 0x18000041, 150, -1, 679, 6, 1, 18 },
+  { 0x1, 0x1, 150, -1, 689, 12, 1, 19 },
+  { 0x200001, 0x200001, 150, -1, 691, 12, 1, 19 },
+  { 0x400001, 0x400001, 150, -1, 693, 12, 1, 19 },
+  { 0x600001, 0x600001, 150, -1, 695, 12, 1, 19 },
+  { 0x1, 0x1, 150, -1, 701, 12, 1, 20 },
+  { 0x200001, 0x200001, 150, -1, 703, 12, 1, 20 },
+  { 0x400001, 0x400001, 150, -1, 705, 12, 1, 20 },
+  { 0x600001, 0x600001, 150, -1, 707, 12, 1, 20 },
+  { 0x41, 0x41, 150, -1, 709, 6, 1, 20 },
+  { 0x8000041, 0x8000041, 150, -1, 711, 6, 1, 20 },
+  { 0x10000041, 0x10000041, 150, -1, 713, 6, 1, 20 },
+  { 0x18000041, 0x18000041, 150, -1, 715, 6, 1, 20 },
+  { 0x1, 0x1, 150, -1, 725, 12, 1, 21 },
+  { 0x200001, 0x200001, 150, -1, 727, 12, 1, 21 },
+  { 0x400001, 0x400001, 150, -1, 729, 12, 1, 21 },
+  { 0x600001, 0x600001, 150, -1, 731, 12, 1, 21 },
+  { 0x1, 0x1, 150, -1, 737, 12, 1, 17 },
+  { 0x1, 0x1, 150, -1, 740, 12, 1, 17 },
+  { 0x200001, 0x200001, 150, -1, 742, 12, 1, 17 },
+  { 0x400001, 0x400001, 150, -1, 744, 12, 1, 17 },
+  { 0x600001, 0x600001, 150, -1, 746, 12, 1, 17 },
+  { 0x1, 0x1, 150, -1, 748, 12, 1, 17 },
+  { 0x200001, 0x200001, 150, -1, 750, 12, 1, 17 },
+  { 0x400001, 0x400001, 150, -1, 752, 12, 1, 17 },
+  { 0x600001, 0x600001, 150, -1, 754, 12, 1, 17 },
+  { 0x1, 0x1, 150, -1, 764, 12, 1, 21 },
+  { 0x200001, 0x200001, 150, -1, 766, 12, 1, 21 },
+  { 0x400001, 0x400001, 150, -1, 768, 12, 1, 21 },
+  { 0x600001, 0x600001, 150, -1, 770, 12, 1, 21 },
+  { 0x0, 0x0, 155, -1, -1, 0, 1, 124 },
+  { 0x0, 0x0, 159, 775, -1, 0, 1, 75 },
+  { 0x0, 0x0, 159, 776, -1, 0, 1, 75 },
+  { 0x9, 0x9, 159, -1, 1438, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1447, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1456, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1469, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1478, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1487, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1496, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1505, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1514, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1524, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1534, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1544, 32, 1, 130 },
+  { 0x9, 0x9, 159, -1, 1553, 32, 1, 144 },
+  { 0x9, 0x9, 159, -1, 1559, 32, 1, 149 },
+  { 0x9, 0x9, 159, -1, 1565, 32, 1, 149 },
+  { 0x9, 0x9, 159, -1, 1571, 32, 1, 144 },
+  { 0x9, 0x9, 159, -1, 1577, 32, 1, 149 },
+  { 0x9, 0x9, 159, -1, 1583, 32, 1, 149 },
+  { 0x9, 0x9, 159, -1, 1589, 32, 1, 144 },
+  { 0x9, 0x9, 159, -1, 1595, 32, 1, 149 },
+  { 0x9, 0x9, 159, -1, 1601, 32, 1, 149 },
+  { 0x9, 0x9, 159, -1, 1607, 32, 1, 144 },
+  { 0x9, 0x9, 159, -1, 1613, 32, 1, 149 },
+  { 0x9, 0x9, 159, -1, 1619, 32, 1, 144 },
+  { 0x9, 0x9, 159, -1, 1625, 32, 1, 149 },
+  { 0x9, 0x9, 159, -1, 1631, 32, 1, 144 },
+  { 0x9, 0x9, 159, -1, 1637, 32, 1, 149 },
+  { 0x9, 0x9, 159, -1, 1643, 32, 1, 144 },
+  { 0x9, 0x9, 159, -1, 1649, 32, 1, 149 },
+  { 0x9, 0x9, 159, -1, 1655, 32, 1, 149 },
+  { 0x0, 0x0, 160, 1235, 296, 0, 0, -1 },
+  { 0x0, 0x0, 160, 1236, 412, 0, 0, -1 },
+  { 0x1, 0x1, 160, -1, 2862, 38, 1, 1 },
+  { 0x1, 0x1, 160, 907, 2865, 38, 1, 1 },
+  { 0x0, 0x0, 160, 908, 413, 0, 0, -1 },
+  { 0x0, 0x0, 160, 1237, 318, 0, 0, -1 },
+  { 0x0, 0x0, 160, 1238, 452, 0, 0, -1 },
+  { 0x1, 0x1, 160, -1, 2878, 38, 1, 1 },
+  { 0x1, 0x1, 160, 911, 2881, 38, 1, 1 },
+  { 0x0, 0x0, 160, 912, 453, 0, 0, -1 },
+  { 0x0, 0x0, 160, 913, 323, 0, 0, -1 },
+  { 0x0, 0x0, 160, 914, 341, 0, 0, -1 },
+  { 0x0, 0x0, 160, 1239, 344, 0, 0, -1 },
+  { 0x0, 0x0, 160, 1240, 460, 0, 0, -1 },
+  { 0x1, 0x1, 160, -1, 2902, 38, 1, 1 },
+  { 0x1, 0x1, 160, 917, 2905, 38, 1, 1 },
+  { 0x0, 0x0, 160, 918, 461, 0, 0, -1 },
+  { 0x0, 0x0, 160, -1, 366, 0, 0, -1 },
+  { 0x0, 0x0, 160, -1, 500, 0, 0, -1 },
+  { 0x1, 0x1, 160, -1, 2915, 38, 1, 1 },
+  { 0x1, 0x1, 160, 921, 2917, 38, 1, 1 },
+  { 0x0, 0x0, 160, 922, 501, 0, 0, -1 },
+  { 0x0, 0x0, 160, 923, 371, 0, 0, -1 },
+  { 0x0, 0x0, 160, 924, 389, 0, 0, -1 },
+  { 0x0, 0x0, 161, 1397, 2287, 0, 0, -1 },
+  { 0x0, 0x0, 161, 1398, 2295, 0, 1, 54 },
+  { 0x0, 0x0, 161, 1399, 2956, 0, 1, 54 },
+  { 0x0, 0x0, 161, 1400, 2343, 0, 0, -1 },
+  { 0x1, 0x1, 161, 1401, -1, 29, 1, 49 },
+  { 0x0, 0x0, 162, -1, 2305, 0, 0, -1 },
+  { 0x1, 0x9, 162, -1, 2309, 33, 1, 54 },
+  { 0x1, 0x9, 162, -1, 2965, 33, 1, 54 },
+  { 0x6, 0x7, 162, -1, 2350, 27, 1, 49 },
+  { 0x0, 0x0, 163, 1383, 2303, 0, 0, -1 },
+  { 0x0, 0x0, 163, 1384, 2307, 0, 1, 54 },
+  { 0x0, 0x0, 163, 1385, 2964, 0, 1, 54 },
+  { 0x1, 0x1, 163, 1386, 2349, 29, 1, 49 },
+  { 0x1, 0x1, 164, 1404, -1, 27, 1, 33 },
+  { 0x0, 0x0, 165, 2159, 2291, 0, 0, -1 },
+  { 0x1, 0x1, 165, 2160, 2299, 33, 1, 54 },
+  { 0x1, 0x1, 165, 2161, 2958, 33, 1, 54 },
+  { 0x0, 0x0, 165, 2162, 2345, 0, 0, -1 },
+  { 0x3, 0x3, 165, 2163, -1, 28, 1, 49 },
+  { 0x0, 0x0, 166, 1392, 2289, 0, 0, -1 },
+  { 0x1, 0x1, 166, 1393, 2297, 36, 1, 54 },
+  { 0x1, 0x1, 166, 1394, 2957, 36, 1, 54 },
+  { 0x0, 0x0, 166, 1395, 2344, 0, 0, -1 },
+  { 0x5, 0x5, 166, 1396, -1, 27, 1, 49 },
+  { 0x0, 0x0, 167, -1, 2928, 0, 1, 63 },
+  { 0x0, 0x0, 167, -1, 2929, 0, 1, 63 },
+  { 0x1, 0x1, 169, -1, -1, 28, 1, 33 },
+  { 0x1, 0x1, 170, 2745, -1, 27, 1, 33 },
+  { 0x1, 0x1, 170, 2746, -1, 27, 1, 33 },
+  { 0x1, 0x1, 171, 1685, -1, 28, 1, 135 },
+  { 0x1, 0x1, 171, 1686, -1, 28, 1, 135 },
+  { 0x1, 0x1, 171, 1687, -1, 28, 1, 135 },
+  { 0x1, 0x1, 171, 1688, -1, 28, 1, 135 },
+  { 0x1, 0x1, 171, 1689, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1690, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1691, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1692, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1693, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1694, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1695, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1696, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1697, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1698, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1699, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1700, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1701, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1702, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1703, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1704, -1, 28, 1, 134 },
+  { 0x1, 0x1, 171, 1705, -1, 28, 1, 136 },
+  { 0x1, 0x1, 171, 1706, -1, 28, 1, 136 },
+  { 0x1, 0x1, 171, 1707, -1, 28, 1, 136 },
+  { 0x1, 0x1, 171, 1708, -1, 28, 1, 136 },
+  { 0x1, 0x1, 171, 1709, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1710, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1711, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1712, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1713, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1714, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1715, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1716, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1717, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1718, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1719, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1720, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1721, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1722, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1723, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1724, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1725, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1726, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1727, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1728, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1729, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1730, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1731, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1732, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1733, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1734, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1735, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1736, -1, 28, 1, 125 },
+  { 0x1, 0x1, 171, 1737, -1, 28, 1, 125 },
+  { 0x1, 0x1, 171, 1738, -1, 28, 1, 125 },
+  { 0x1, 0x1, 171, 1739, -1, 28, 1, 125 },
+  { 0x1, 0x1, 171, 1740, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1741, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1742, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1743, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1744, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1745, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1746, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1747, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1748, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1749, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1750, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1751, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1752, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1753, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1754, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1755, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1756, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1757, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1758, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1759, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1760, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1761, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1762, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1763, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1764, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1765, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1766, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1767, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1768, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1769, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1770, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1771, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1772, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1773, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1774, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1775, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1776, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1777, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1778, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1779, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1780, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1781, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1782, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1783, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1784, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1785, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1786, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1787, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1788, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1789, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1790, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1791, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1792, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1793, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1794, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1795, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1796, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1797, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1798, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1799, -1, 28, 1, 129 },
+  { 0x1, 0x1, 171, 1800, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1801, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1802, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1803, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1804, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1805, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1806, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1807, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1808, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1809, -1, 28, 1, 129 },
+  { 0x1, 0x1, 171, 1810, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1811, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1812, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1813, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1814, -1, 28, 1, 126 },
+  { 0x1, 0x1, 171, 1815, -1, 28, 1, 127 },
+  { 0x1, 0x1, 171, 1816, -1, 28, 1, 128 },
+  { 0x1, 0x1, 171, 1817, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1818, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1819, -1, 28, 1, 129 },
+  { 0x1, 0x1, 171, 1820, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1821, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1822, -1, 28, 1, 130 },
+  { 0x1, 0x1, 171, 1823, -1, 28, 1, 124 },
+  { 0x1, 0x1, 171, 1824, -1, 28, 1, 140 },
+  { 0x1, 0x1, 171, 1825, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1826, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1827, -1, 28, 1, 141 },
+  { 0x1, 0x1, 171, 1828, -1, 28, 1, 142 },
+  { 0x1, 0x1, 171, 1829, -1, 28, 1, 143 },
+  { 0x1, 0x1, 171, 1830, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1831, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1832, -1, 28, 1, 140 },
+  { 0x1, 0x1, 171, 1833, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1834, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1835, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1836, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1837, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1838, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1839, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1840, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1841, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1842, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1843, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1844, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1845, -1, 28, 1, 141 },
+  { 0x1, 0x1, 171, 1846, -1, 28, 1, 142 },
+  { 0x1, 0x1, 171, 1847, -1, 28, 1, 143 },
+  { 0x1, 0x1, 171, 1848, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1849, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1850, -1, 28, 1, 140 },
+  { 0x1, 0x1, 171, 1851, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1852, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1853, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1854, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1855, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1856, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1857, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1858, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1859, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1860, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1861, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1862, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1863, -1, 28, 1, 141 },
+  { 0x1, 0x1, 171, 1864, -1, 28, 1, 142 },
+  { 0x1, 0x1, 171, 1865, -1, 28, 1, 143 },
+  { 0x1, 0x1, 171, 1866, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1867, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1868, -1, 28, 1, 140 },
+  { 0x1, 0x1, 171, 1869, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1870, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1871, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1872, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1873, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1874, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1875, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1876, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1877, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1878, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1879, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1880, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1881, -1, 28, 1, 141 },
+  { 0x1, 0x1, 171, 1882, -1, 28, 1, 142 },
+  { 0x1, 0x1, 171, 1883, -1, 28, 1, 143 },
+  { 0x1, 0x1, 171, 1884, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1885, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1886, -1, 28, 1, 140 },
+  { 0x1, 0x1, 171, 1887, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1888, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1889, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1890, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1891, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1892, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1893, -1, 28, 1, 141 },
+  { 0x1, 0x1, 171, 1894, -1, 28, 1, 142 },
+  { 0x1, 0x1, 171, 1895, -1, 28, 1, 143 },
+  { 0x1, 0x1, 171, 1896, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1897, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1898, -1, 28, 1, 140 },
+  { 0x1, 0x1, 171, 1899, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1900, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1901, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1902, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1903, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1904, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1905, -1, 28, 1, 141 },
+  { 0x1, 0x1, 171, 1906, -1, 28, 1, 142 },
+  { 0x1, 0x1, 171, 1907, -1, 28, 1, 143 },
+  { 0x1, 0x1, 171, 1908, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1909, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1910, -1, 28, 1, 140 },
+  { 0x1, 0x1, 171, 1911, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1912, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1913, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1914, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1915, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1916, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1917, -1, 28, 1, 141 },
+  { 0x1, 0x1, 171, 1918, -1, 28, 1, 142 },
+  { 0x1, 0x1, 171, 1919, -1, 28, 1, 143 },
+  { 0x1, 0x1, 171, 1920, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1921, -1, 28, 1, 144 },
+  { 0x1, 0x1, 171, 1922, -1, 28, 1, 140 },
+  { 0x1, 0x1, 171, 1923, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1924, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1925, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1926, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1927, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1928, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1929, -1, 28, 1, 146 },
+  { 0x1, 0x1, 171, 1930, -1, 28, 1, 147 },
+  { 0x1, 0x1, 171, 1931, -1, 28, 1, 148 },
+  { 0x1, 0x1, 171, 1932, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1933, -1, 28, 1, 149 },
+  { 0x1, 0x1, 171, 1934, -1, 28, 1, 145 },
+  { 0x1, 0x1, 171, 1673, -1, 28, 1, 151 },
+  { 0x1, 0x1, 171, 1674, -1, 28, 1, 152 },
+  { 0x1, 0x1, 171, 1675, -1, 28, 1, 152 },
+  { 0x1, 0x1, 171, 1676, -1, 28, 1, 151 },
+  { 0x1, 0x1, 171, 1677, -1, 28, 1, 153 },
+  { 0x1, 0x1, 171, 1678, -1, 28, 1, 154 },
+  { 0x1, 0x1, 171, 1679, -1, 28, 1, 154 },
+  { 0x1, 0x1, 171, 1680, -1, 28, 1, 153 },
+  { 0x1, 0x1, 171, 1681, -1, 28, 1, 153 },
+  { 0x1, 0x1, 171, 1682, -1, 28, 1, 154 },
+  { 0x1, 0x1, 171, 1683, -1, 28, 1, 154 },
+  { 0x1, 0x1, 171, 1684, -1, 28, 1, 153 },
+  { 0x1, 0x1, 171, 1979, -1, 28, 1, 136 },
+  { 0x1, 0x1, 171, 1980, -1, 28, 1, 136 },
+  { 0x1, 0x1, 171, 1981, -1, 28, 1, 136 },
+  { 0x1, 0x1, 171, 1982, -1, 28, 1, 136 },
+  { 0x1, 0x1, 172, 1935, -1, 29, 1, 151 },
+  { 0x1, 0x1, 172, 1936, -1, 29, 1, 152 },
+  { 0x1, 0x1, 172, 1937, -1, 29, 1, 152 },
+  { 0x1, 0x1, 172, 1938, -1, 29, 1, 151 },
+  { 0x1, 0x1, 172, 1939, -1, 29, 1, 153 },
+  { 0x1, 0x1, 172, 1940, -1, 29, 1, 154 },
+  { 0x1, 0x1, 172, 1941, -1, 29, 1, 154 },
+  { 0x1, 0x1, 172, 1942, -1, 29, 1, 153 },
+  { 0x1, 0x1, 172, 1943, -1, 29, 1, 153 },
+  { 0x1, 0x1, 172, 1944, -1, 29, 1, 154 },
+  { 0x1, 0x1, 172, 1945, -1, 29, 1, 154 },
+  { 0x1, 0x1, 172, 1946, -1, 29, 1, 153 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 135 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 135 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 135 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 135 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 134 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 136 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 136 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 136 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 136 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 269, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2224, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 271, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2225, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 273, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2226, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 125 },
+  { 0x3, 0x3, 173, 275, -1, 28, 1, 125 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 125 },
+  { 0x3, 0x3, 173, 276, -1, 28, 1, 125 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 277, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2227, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 279, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2228, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 281, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2229, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 283, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2230, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 285, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2231, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 287, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2232, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 129 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 289, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2233, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 129 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 291, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2234, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 126 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 127 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 128 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 129 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 293, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 130 },
+  { 0x3, 0x3, 173, 2235, -1, 28, 1, 124 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 140 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 141 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 142 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 143 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, 2236, -1, 28, 1, 140 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2237, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2238, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 141 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 142 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 143 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, 2239, -1, 28, 1, 140 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2240, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2241, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 141 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 142 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 143 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, 2242, -1, 28, 1, 140 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2243, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2244, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 141 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 142 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 143 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, 2245, -1, 28, 1, 140 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2246, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 141 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 142 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 143 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, 2247, -1, 28, 1, 140 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2248, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 141 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 142 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 143 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, 2249, -1, 28, 1, 140 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2250, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 141 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 142 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 143 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 144 },
+  { 0x3, 0x3, 173, 2251, -1, 28, 1, 140 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2252, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 146 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 147 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 148 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 149 },
+  { 0x3, 0x3, 173, 2253, -1, 28, 1, 145 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 151 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 152 },
+  { 0x3, 0x3, 173, 933, -1, 28, 1, 152 },
+  { 0x3, 0x3, 173, 934, -1, 28, 1, 151 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 153 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 154 },
+  { 0x3, 0x3, 173, 935, -1, 28, 1, 154 },
+  { 0x3, 0x3, 173, 936, -1, 28, 1, 153 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 153 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 154 },
+  { 0x3, 0x3, 173, 937, -1, 28, 1, 154 },
+  { 0x3, 0x3, 173, 938, -1, 28, 1, 153 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 131 },
+  { 0x3, 0x3, 173, 2190, -1, 28, 1, 131 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 138 },
+  { 0x3, 0x3, 173, 2191, -1, 28, 1, 138 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 132 },
+  { 0x3, 0x3, 173, 2192, -1, 28, 1, 132 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 132 },
+  { 0x3, 0x3, 173, 2193, -1, 28, 1, 132 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 131 },
+  { 0x3, 0x3, 173, 2194, -1, 28, 1, 131 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 138 },
+  { 0x3, 0x3, 173, 2195, -1, 28, 1, 138 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 131 },
+  { 0x3, 0x3, 173, 2196, -1, 28, 1, 131 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 138 },
+  { 0x3, 0x3, 173, 2197, -1, 28, 1, 138 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 131 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 133 },
+  { 0x3, 0x3, 173, 2198, -1, 28, 1, 131 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 138 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 139 },
+  { 0x3, 0x3, 173, 2199, -1, 28, 1, 138 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 150 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 156 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 150 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 156 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 150 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 156 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 150 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 156 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 150 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 156 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 136 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 136 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 136 },
+  { 0x3, 0x3, 173, -1, -1, 28, 1, 136 },
+  { 0x0, 0x0, 174, -1, 392, 0, 0, -1 },
+  { 0x0, 0x0, 174, -1, 394, 0, 0, -1 },
+  { 0x0, 0x0, 174, 3004, 2968, 0, 1, 1 },
+  { 0x0, 0x0, 174, 3005, 2969, 0, 1, 1 },
+  { 0x0, 0x0, 174, -1, 400, 0, 0, -1 },
+  { 0x0, 0x0, 174, -1, 402, 0, 0, -1 },
+  { 0x0, 0x0, 174, 3008, 2972, 0, 1, 1 },
+  { 0x0, 0x0, 174, 3009, 2973, 0, 1, 1 },
+  { 0x11, 0x31, 175, 2847, 407, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 408, 12, 1, 4 },
+  { 0x11, 0x31, 175, 2047, 409, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 411, 12, 1, 4 },
+  { 0x1, 0x1, 175, -1, 415, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 175, -1, 416, 12, 1, 4 },
+  { 0x11, 0x11, 175, -1, 417, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 418, 12, 1, 4 },
+  { 0x1, 0x1, 175, 2053, 419, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 175, -1, 421, 12, 1, 4 },
+  { 0x11, 0x11, 175, 2055, 423, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 425, 12, 1, 4 },
+  { 0x1, 0x1, 175, 2057, 427, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 175, -1, 429, 12, 1, 4 },
+  { 0x11, 0x11, 175, 2059, 431, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 433, 12, 1, 4 },
+  { 0x1, 0x1, 175, 2061, 435, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 175, -1, 437, 12, 1, 4 },
+  { 0x11, 0x11, 175, 2063, 439, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 441, 12, 1, 4 },
+  { 0x11, 0x31, 175, 2867, 447, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 448, 12, 1, 4 },
+  { 0x11, 0x31, 175, 2069, 449, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 451, 12, 1, 4 },
+  { 0x11, 0x31, 175, 2887, 455, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 456, 12, 1, 4 },
+  { 0x11, 0x31, 175, 2095, 457, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 459, 12, 1, 4 },
+  { 0x1, 0x1, 175, -1, 463, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 175, -1, 464, 12, 1, 4 },
+  { 0x11, 0x11, 175, -1, 465, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 466, 12, 1, 4 },
+  { 0x1, 0x1, 175, 2101, 467, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 175, -1, 469, 12, 1, 4 },
+  { 0x11, 0x11, 175, 2103, 471, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 473, 12, 1, 4 },
+  { 0x1, 0x1, 175, 2105, 475, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 175, -1, 477, 12, 1, 4 },
+  { 0x11, 0x11, 175, 2107, 479, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 481, 12, 1, 4 },
+  { 0x1, 0x1, 175, 2109, 483, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 175, -1, 485, 12, 1, 4 },
+  { 0x11, 0x11, 175, 2111, 487, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 489, 12, 1, 4 },
+  { 0x11, 0x31, 175, 2907, 495, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 496, 12, 1, 4 },
+  { 0x11, 0x31, 175, 2117, 497, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 175, -1, 499, 12, 1, 4 },
+  { 0x1, 0x1, 175, -1, 503, 33, 1, 4 },
+  { 0x200001, 0x200001, 175, -1, 504, 12, 1, 4 },
+  { 0x1, 0x1, 175, -1, 505, 33, 1, 4 },
+  { 0x200001, 0x200001, 175, -1, 506, 12, 1, 4 },
+  { 0x1, 0x1, 175, -1, 511, 33, 1, 4 },
+  { 0x200001, 0x200001, 175, -1, 512, 12, 1, 4 },
+  { 0x1, 0x1, 175, -1, 513, 33, 1, 4 },
+  { 0x200001, 0x200001, 175, -1, 514, 12, 1, 4 },
+  { 0x2200001, 0x6200001, 176, 2850, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, 1994, -1, 33, 1, 4 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x4200001, 0x4200001, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x1, 0x1, 176, 2000, -1, 37, 1, 4 },
+  { 0x2200001, 0x2200001, 176, -1, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, 2002, -1, 33, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x1, 0x1, 176, 2004, -1, 37, 1, 4 },
+  { 0x2200001, 0x2200001, 176, -1, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, 2006, -1, 33, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x1, 0x1, 176, 2008, -1, 37, 1, 4 },
+  { 0x2200001, 0x2200001, 176, -1, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, 2010, -1, 33, 1, 4 },
+  { 0x1, 0x1, 176, -1, -1, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, -1, -1, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 176, -1, -1, 12, 1, 4 },
+  { 0x2200001, 0x6200001, 176, 2870, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, 2014, -1, 33, 1, 4 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x4200001, 0x4200001, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x200001, 0x200001, 176, -1, -1, 12, 1, 5 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x200001, 0x200001, 176, -1, -1, 12, 1, 5 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x200001, 0x200001, 176, -1, -1, 12, 1, 5 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x200001, 0x200001, 176, -1, -1, 12, 1, 5 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x2200001, 0x6200001, 176, 2890, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, 2018, -1, 33, 1, 4 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x4200001, 0x4200001, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x1, 0x1, 176, 2024, -1, 37, 1, 4 },
+  { 0x2200001, 0x2200001, 176, -1, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, 2026, -1, 33, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x1, 0x1, 176, 2028, -1, 37, 1, 4 },
+  { 0x2200001, 0x2200001, 176, -1, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, 2030, -1, 33, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x1, 0x1, 176, 2032, -1, 37, 1, 4 },
+  { 0x2200001, 0x2200001, 176, -1, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, 2034, -1, 33, 1, 4 },
+  { 0x1, 0x1, 176, -1, -1, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, -1, -1, 33, 1, 4 },
+  { 0x2200001, 0x2200001, 176, -1, -1, 12, 1, 4 },
+  { 0x2200001, 0x6200001, 176, 2909, -1, 12, 1, 4 },
+  { 0x11, 0x11, 176, 2038, -1, 33, 1, 4 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x4200001, 0x4200001, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 37, 1, 4 },
+  { 0x2000001, 0x2000001, 176, -1, -1, 12, 1, 4 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x200001, 0x200001, 176, -1, -1, 12, 1, 5 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x200001, 0x200001, 176, -1, -1, 12, 1, 5 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x200001, 0x200001, 176, -1, -1, 12, 1, 5 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 33, 1, 5 },
+  { 0x200001, 0x200001, 176, -1, -1, 12, 1, 5 },
+  { 0x0, 0x0, 176, -1, -1, 0, 1, 5 },
+  { 0x1, 0x1, 176, -1, -1, 12, 1, 5 },
+  { 0x9, 0x9, 176, -1, -1, 33, 1, 5 },
+  { 0x1, 0x1, 176, 395, -1, 33, 1, 4 },
+  { 0x1200001, 0x1200001, 176, -1, -1, 12, 1, 5 },
+  { 0x200001, 0x200001, 176, 396, -1, 12, 1, 4 },
+  { 0x9, 0x9, 176, -1, -1, 33, 1, 5 },
+  { 0x1, 0x1, 176, 397, -1, 33, 1, 4 },
+  { 0x1200001, 0x1200001, 176, -1, -1, 12, 1, 5 },
+  { 0x200001, 0x200001, 176, 398, -1, 12, 1, 4 },
+  { 0x9, 0x9, 176, -1, -1, 33, 1, 5 },
+  { 0x1, 0x1, 176, 403, -1, 33, 1, 4 },
+  { 0x1200001, 0x1200001, 176, -1, -1, 12, 1, 5 },
+  { 0x200001, 0x200001, 176, 404, -1, 12, 1, 4 },
+  { 0x9, 0x9, 176, -1, -1, 33, 1, 5 },
+  { 0x1, 0x1, 176, 405, -1, 33, 1, 4 },
+  { 0x1200001, 0x1200001, 176, -1, -1, 12, 1, 5 },
+  { 0x200001, 0x200001, 176, 406, -1, 12, 1, 4 },
+  { 0x0, 0x0, 177, -1, 2293, 0, 0, -1 },
+  { 0x9, 0x9, 177, -1, 2301, 33, 1, 49 },
+  { 0x9, 0x9, 177, -1, 2959, 33, 1, 49 },
+  { 0x0, 0x0, 177, -1, 2346, 0, 0, -1 },
+  { 0x7, 0x7, 177, -1, -1, 27, 1, 49 },
+  { 0x1, 0x1, 197, -1, -1, 27, 1, 10 },
+  { 0x1, 0x1, 211, -1, -1, 29, 1, 0 },
+  { 0x1, 0x1, 211, -1, -1, 29, 1, 0 },
+  { 0x2, 0x3, 211, 1151, -1, 27, 1, 33 },
+  { 0x0, 0x0, 211, 1152, -1, 0, 1, 33 },
+  { 0x0, 0x0, 211, 1153, -1, 0, 1, 0 },
+  { 0x0, 0x0, 211, 1154, -1, 0, 1, 0 },
+  { 0x0, 0x0, 211, 1155, -1, 0, 1, 0 },
+  { 0x0, 0x0, 211, 1156, -1, 0, 1, 0 },
+  { 0x0, 0x0, 211, 2988, -1, 0, 1, 93 },
+  { 0x0, 0x0, 211, 2989, -1, 0, 1, 93 },
+  { 0x0, 0x0, 211, 2990, 949, 0, 0, -1 },
+  { 0x1, 0x1, 212, -1, -1, 27, 1, 0 },
+  { 0x1, 0x1, 212, -1, -1, 27, 1, 0 },
+  { 0x1, 0x1, 213, -1, 1408, 32, 1, 135 },
+  { 0x1, 0x1, 213, -1, 1410, 32, 1, 135 },
+  { 0x1, 0x1, 213, -1, 1412, 32, 1, 134 },
+  { 0x1, 0x1, 213, -1, 1414, 32, 1, 134 },
+  { 0x1, 0x1, 213, -1, 1416, 32, 1, 134 },
+  { 0x1, 0x1, 213, -1, 1418, 32, 1, 134 },
+  { 0x1, 0x1, 213, -1, 1420, 32, 1, 134 },
+  { 0x1, 0x1, 213, -1, 1422, 32, 1, 134 },
+  { 0x1, 0x1, 213, -1, 1424, 32, 1, 134 },
+  { 0x1, 0x1, 213, -1, 1426, 32, 1, 134 },
+  { 0x1, 0x1, 213, -1, 1428, 32, 1, 136 },
+  { 0x1, 0x1, 213, -1, 1430, 32, 1, 136 },
+  { 0x1, 0x1, 213, -1, 1947, 32, 1, 131 },
+  { 0x1, 0x1, 213, -1, 1949, 32, 1, 138 },
+  { 0x1, 0x1, 213, -1, 1951, 32, 1, 132 },
+  { 0x1, 0x1, 213, -1, 1953, 32, 1, 132 },
+  { 0x1, 0x1, 213, -1, 1955, 32, 1, 131 },
+  { 0x1, 0x1, 213, -1, 1957, 32, 1, 138 },
+  { 0x1, 0x1, 213, -1, 1959, 32, 1, 131 },
+  { 0x1, 0x1, 213, -1, 1961, 32, 1, 138 },
+  { 0x1, 0x1, 213, 2749, 1963, 32, 1, 131 },
+  { 0x1, 0x1, 213, 2750, 1966, 32, 1, 138 },
+  { 0x0, 0x0, 214, -1, 2791, 0, 0, -1 },
+  { 0x0, 0x0, 214, -1, 2792, 0, 0, -1 },
+  { 0x0, 0x0, 214, -1, 2817, 0, 0, -1 },
+  { 0x5, 0x5, 214, -1, 2820, 20, 1, 67 },
+  { 0x0, 0x0, 218, 2175, 948, 0, 0, -1 },
+  { 0x0, 0x0, 219, -1, 1121, 0, 0, -1 },
+  { 0x0, 0x0, 219, -1, 1246, 0, 0, -1 },
+  { 0x0, 0x0, 219, -1, -1, 0, 1, 121 },
+  { 0x0, 0x0, 219, -1, -1, 0, 1, 66 },
+  { 0x1, 0x1, 219, 815, 2255, 36, 1, 65 },
+  { 0x1, 0x1, 219, 816, 2314, 36, 1, 65 },
+  { 0x0, 0x0, 219, 817, 2317, 0, 0, -1 },
+  { 0x1, 0x1, 219, 818, -1, 36, 1, 65 },
+  { 0x0, 0x0, 219, 1405, -1, 0, 1, 33 },
+  { 0x1, 0x1, 219, 819, 2322, 36, 1, 65 },
+  { 0x0, 0x0, 219, 820, 2325, 0, 0, -1 },
+  { 0x1, 0x1, 219, 821, -1, 36, 1, 65 },
+  { 0x0, 0x0, 219, 822, 2328, 0, 0, -1 },
+  { 0x1, 0x1, 219, 823, -1, 36, 1, 65 },
+  { 0x1, 0x1, 219, 824, 2331, 36, 1, 65 },
+  { 0x1, 0x1, 219, 825, 2334, 36, 1, 65 },
+  { 0x0, 0x0, 219, 1406, -1, 0, 1, 33 },
+  { 0x1, 0x1, 219, 826, 2367, 36, 1, 65 },
+  { 0x1, 0x1, 219, 827, -1, 31, 1, 137 },
+  { 0x1, 0x1, 219, 226, 1431, 32, 1, 126 },
+  { 0x1, 0x1, 219, 227, 1440, 32, 1, 126 },
+  { 0x1, 0x1, 219, 228, 1449, 32, 1, 126 },
+  { 0x1, 0x1, 219, 229, 1462, 32, 1, 126 },
+  { 0x1, 0x1, 219, 230, 1471, 32, 1, 126 },
+  { 0x1, 0x1, 219, 231, 1480, 32, 1, 126 },
+  { 0x1, 0x1, 219, 232, 1489, 32, 1, 126 },
+  { 0x1, 0x1, 219, 233, 1498, 32, 1, 126 },
+  { 0x1, 0x1, 219, 234, 1507, 32, 1, 126 },
+  { 0x1, 0x1, 219, 235, 1516, 32, 1, 126 },
+  { 0x1, 0x1, 219, 236, 1526, 32, 1, 126 },
+  { 0x1, 0x1, 219, 237, 1536, 32, 1, 126 },
+  { 0x1, 0x1, 219, 238, 1549, 32, 1, 141 },
+  { 0x1, 0x1, 219, 239, 1555, 32, 1, 146 },
+  { 0x1, 0x1, 219, 240, 1561, 32, 1, 146 },
+  { 0x1, 0x1, 219, 241, 1567, 32, 1, 141 },
+  { 0x1, 0x1, 219, 242, 1573, 32, 1, 146 },
+  { 0x1, 0x1, 219, 243, 1579, 32, 1, 146 },
+  { 0x1, 0x1, 219, 244, 1585, 32, 1, 141 },
+  { 0x1, 0x1, 219, 245, 1591, 32, 1, 146 },
+  { 0x1, 0x1, 219, 246, 1597, 32, 1, 146 },
+  { 0x1, 0x1, 219, 247, 1603, 32, 1, 141 },
+  { 0x1, 0x1, 219, 248, 1609, 32, 1, 146 },
+  { 0x1, 0x1, 219, 249, 1615, 32, 1, 141 },
+  { 0x1, 0x1, 219, 250, 1621, 32, 1, 146 },
+  { 0x1, 0x1, 219, 251, 1627, 32, 1, 141 },
+  { 0x1, 0x1, 219, 252, 1633, 32, 1, 146 },
+  { 0x1, 0x1, 219, 253, 1639, 32, 1, 141 },
+  { 0x1, 0x1, 219, 254, 1645, 32, 1, 146 },
+  { 0x1, 0x1, 219, 255, 1651, 32, 1, 146 },
+  { 0x1, 0x1, 219, 831, -1, 31, 1, 155 },
+  { 0x0, 0x0, 220, 2370, -1, 0, 1, 65 },
+  { 0x0, 0x0, 220, 2371, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 25, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2373, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2374, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2375, -1, 0, 1, 44 },
+  { 0x0, 0x0, 220, 2376, -1, 0, 1, 39 },
+  { 0x1, 0x1, 220, 2377, -1, 12, 1, 58 },
+  { 0x0, 0x0, 220, 2378, -1, 0, 1, 53 },
+  { 0x1000001, 0x1000001, 220, 2379, -1, 12, 1, 58 },
+  { 0x1, 0x1, 220, 2380, -1, 36, 1, 53 },
+  { 0x200001, 0x200001, 220, 2381, -1, 12, 1, 58 },
+  { 0x1, 0x1, 220, 2382, -1, 33, 1, 53 },
+  { 0x1200001, 0x1200001, 220, 2383, -1, 12, 1, 48 },
+  { 0x9, 0x9, 220, 2384, -1, 33, 1, 48 },
+  { 0x0, 0x0, 220, 2385, -1, 0, 1, 58 },
+  { 0x0, 0x0, 220, 2386, -1, 0, 1, 53 },
+  { 0x0, 0x0, 220, 2387, -1, 0, 1, 58 },
+  { 0x0, 0x0, 220, 2388, -1, 0, 1, 53 },
+  { 0x0, 0x0, 220, 2389, -1, 0, 1, 58 },
+  { 0x0, 0x0, 220, 2390, -1, 0, 1, 53 },
+  { 0x0, 0x0, 220, 2391, -1, 0, 1, 48 },
+  { 0x0, 0x0, 220, 2392, -1, 0, 1, 48 },
+  { 0x1, 0x1, 220, 2393, -1, 12, 1, 58 },
+  { 0x0, 0x0, 220, 2394, -1, 0, 1, 53 },
+  { 0x200001, 0x1200001, 220, 2395, -1, 12, 1, 58 },
+  { 0x1, 0x9, 220, 2396, -1, 33, 1, 53 },
+  { 0x0, 0x0, 220, 2397, -1, 0, 1, 58 },
+  { 0x0, 0x0, 220, 2398, -1, 0, 1, 53 },
+  { 0x0, 0x0, 220, 2399, -1, 0, 1, 58 },
+  { 0x0, 0x0, 220, 2400, -1, 0, 1, 53 },
+  { 0x1, 0x1, 220, 2401, -1, 12, 1, 58 },
+  { 0x0, 0x0, 220, 2402, -1, 0, 1, 53 },
+  { 0x1000001, 0x1000001, 220, 2403, -1, 12, 1, 58 },
+  { 0x1, 0x1, 220, 2404, -1, 36, 1, 53 },
+  { 0x200001, 0x200001, 220, 2405, -1, 12, 1, 58 },
+  { 0x1, 0x1, 220, 2406, -1, 33, 1, 53 },
+  { 0x1200001, 0x1200001, 220, 2407, -1, 12, 1, 48 },
+  { 0x9, 0x9, 220, 2408, -1, 33, 1, 48 },
+  { 0x0, 0x0, 220, 2409, -1, 0, 1, 58 },
+  { 0x0, 0x0, 220, 2410, -1, 0, 1, 53 },
+  { 0x0, 0x0, 220, 2411, -1, 0, 1, 58 },
+  { 0x0, 0x0, 220, 2412, -1, 0, 1, 53 },
+  { 0x0, 0x0, 220, 2413, -1, 0, 1, 58 },
+  { 0x0, 0x0, 220, 2414, -1, 0, 1, 53 },
+  { 0x0, 0x0, 220, 2415, -1, 0, 1, 48 },
+  { 0x0, 0x0, 220, 2416, -1, 0, 1, 48 },
+  { 0x1, 0x1, 220, 2417, -1, 12, 1, 58 },
+  { 0x0, 0x0, 220, 2418, -1, 0, 1, 53 },
+  { 0x200001, 0x1200001, 220, 2419, -1, 12, 1, 58 },
+  { 0x1, 0x9, 220, 2420, -1, 33, 1, 53 },
+  { 0x0, 0x0, 220, 2421, -1, 0, 1, 58 },
+  { 0x0, 0x0, 220, 2422, -1, 0, 1, 53 },
+  { 0x0, 0x0, 220, 2423, -1, 0, 1, 58 },
+  { 0x0, 0x0, 220, 2424, -1, 0, 1, 53 },
+  { 0x1, 0x1, 220, 2425, -1, 28, 1, 28 },
+  { 0x0, 0x0, 220, 2426, -1, 0, 1, 28 },
+  { 0x3, 0x3, 220, 2427, -1, 27, 1, 28 },
+  { 0x1, 0x1, 220, 2428, -1, 27, 1, 28 },
+  { 0x0, 0x0, 220, 2429, -1, 0, 1, 65 },
+  { 0x0, 0x0, 220, 2430, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2431, -1, 0, 1, 28 },
+  { 0x1, 0x1, 220, 2432, -1, 36, 1, 65 },
+  { 0x1, 0x1, 220, 2433, -1, 37, 1, 28 },
+  { 0x0, 0x0, 220, 2434, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2435, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2436, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2437, -1, 0, 1, 65 },
+  { 0x0, 0x0, 220, 2438, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 37, -1, 0, 1, 28 },
+  { 0x1, 0x1, 220, 2440, -1, 36, 1, 65 },
+  { 0x1, 0x1, 220, 2441, -1, 37, 1, 28 },
+  { 0x0, 0x0, 220, 2442, -1, 0, 1, 28 },
+  { 0x1, 0x1, 220, 2443, -1, 36, 1, 65 },
+  { 0x1, 0x1, 220, 2444, -1, 37, 1, 28 },
+  { 0x0, 0x0, 220, 2445, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2446, -1, 0, 1, 65 },
+  { 0x0, 0x0, 220, 2447, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 42, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2449, -1, 0, 1, 65 },
+  { 0x0, 0x0, 220, 2450, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 43, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2452, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2453, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2454, -1, 0, 1, 48 },
+  { 0x1, 0x1, 220, 2455, -1, 27, 1, 48 },
+  { 0x1, 0x1, 220, 2456, -1, 28, 1, 48 },
+  { 0x3, 0x3, 220, 2457, -1, 27, 1, 48 },
+  { 0x1, 0x1, 220, 2458, -1, 29, 1, 48 },
+  { 0x5, 0x5, 220, 2459, -1, 27, 1, 48 },
+  { 0x3, 0x3, 220, 2460, -1, 28, 1, 48 },
+  { 0x7, 0x7, 220, 2461, -1, 27, 1, 48 },
+  { 0x0, 0x0, 220, 2462, -1, 0, 1, 48 },
+  { 0x0, 0x0, 220, 2463, -1, 0, 1, 48 },
+  { 0x0, 0x0, 220, 2464, -1, 0, 1, 48 },
+  { 0x0, 0x0, 220, 2465, -1, 0, 1, 48 },
+  { 0x1, 0x1, 220, 2466, -1, 28, 1, 28 },
+  { 0x0, 0x0, 220, 2467, -1, 0, 1, 28 },
+  { 0x3, 0x3, 220, 2468, -1, 27, 1, 28 },
+  { 0x1, 0x1, 220, 2469, -1, 27, 1, 28 },
+  { 0x0, 0x0, 220, 2470, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2471, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2472, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 52, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2474, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2475, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 57, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 2477, -1, 0, 1, 23 },
+  { 0x0, 0x0, 220, 2478, -1, 0, 1, 23 },
+  { 0x0, 0x0, 220, 2479, -1, 0, 1, 23 },
+  { 0x0, 0x0, 220, 2480, -1, 0, 1, 23 },
+  { 0x0, 0x0, 220, 2481, -1, 0, 1, 34 },
+  { 0x0, 0x0, 220, 2482, -1, 0, 1, 65 },
+  { 0x0, 0x0, 220, 2483, -1, 0, 1, 28 },
+  { 0x0, 0x0, 220, 64, -1, 0, 1, 28 },
+  { 0x1, 0x1, 221, 2485, -1, 34, 1, 65 },
+  { 0x1, 0x1, 221, 2486, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2487, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2488, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2489, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2490, -1, 34, 1, 45 },
+  { 0x1, 0x1, 221, 2491, -1, 34, 1, 41 },
+  { 0x400001, 0x400001, 221, 2492, -1, 12, 1, 60 },
+  { 0x1, 0x1, 221, 2493, -1, 34, 1, 55 },
+  { 0x1400001, 0x1400001, 221, 2494, -1, 12, 1, 60 },
+  { 0x5, 0x5, 221, 2495, -1, 34, 1, 55 },
+  { 0x600001, 0x600001, 221, 2496, -1, 12, 1, 60 },
+  { 0x3, 0x3, 221, 2497, -1, 33, 1, 55 },
+  { 0x1600001, 0x1600001, 221, 2498, -1, 12, 1, 50 },
+  { 0xb, 0xb, 221, 2499, -1, 33, 1, 50 },
+  { 0x1, 0x1, 221, 2500, -1, 34, 1, 60 },
+  { 0x1, 0x1, 221, 2501, -1, 34, 1, 55 },
+  { 0x1, 0x1, 221, 2502, -1, 34, 1, 60 },
+  { 0x1, 0x1, 221, 2503, -1, 34, 1, 55 },
+  { 0x1, 0x1, 221, 2504, -1, 34, 1, 60 },
+  { 0x1, 0x1, 221, 2505, -1, 34, 1, 55 },
+  { 0x1, 0x1, 221, 2506, -1, 34, 1, 50 },
+  { 0x1, 0x1, 221, 2507, -1, 34, 1, 50 },
+  { 0x400001, 0x400001, 221, 2508, -1, 12, 1, 60 },
+  { 0x1, 0x1, 221, 2509, -1, 34, 1, 55 },
+  { 0x600001, 0x1600001, 221, 2510, -1, 12, 1, 60 },
+  { 0x3, 0xb, 221, 2511, -1, 33, 1, 55 },
+  { 0x1, 0x1, 221, 2512, -1, 34, 1, 60 },
+  { 0x1, 0x1, 221, 2513, -1, 34, 1, 55 },
+  { 0x1, 0x1, 221, 2514, -1, 34, 1, 60 },
+  { 0x1, 0x1, 221, 2515, -1, 34, 1, 55 },
+  { 0x400001, 0x400001, 221, 2516, -1, 12, 1, 60 },
+  { 0x1, 0x1, 221, 2517, -1, 34, 1, 55 },
+  { 0x1400001, 0x1400001, 221, 2518, -1, 12, 1, 60 },
+  { 0x5, 0x5, 221, 2519, -1, 34, 1, 55 },
+  { 0x600001, 0x600001, 221, 2520, -1, 12, 1, 60 },
+  { 0x3, 0x3, 221, 2521, -1, 33, 1, 55 },
+  { 0x1600001, 0x1600001, 221, 2522, -1, 12, 1, 50 },
+  { 0xb, 0xb, 221, 2523, -1, 33, 1, 50 },
+  { 0x1, 0x1, 221, 2524, -1, 34, 1, 60 },
+  { 0x1, 0x1, 221, 2525, -1, 34, 1, 55 },
+  { 0x1, 0x1, 221, 2526, -1, 34, 1, 60 },
+  { 0x1, 0x1, 221, 2527, -1, 34, 1, 55 },
+  { 0x1, 0x1, 221, 2528, -1, 34, 1, 60 },
+  { 0x1, 0x1, 221, 2529, -1, 34, 1, 55 },
+  { 0x1, 0x1, 221, 2530, -1, 34, 1, 50 },
+  { 0x1, 0x1, 221, 2531, -1, 34, 1, 50 },
+  { 0x400001, 0x400001, 221, 2532, -1, 12, 1, 60 },
+  { 0x1, 0x1, 221, 2533, -1, 34, 1, 55 },
+  { 0x600001, 0x1600001, 221, 2534, -1, 12, 1, 60 },
+  { 0x3, 0xb, 221, 2535, -1, 33, 1, 55 },
+  { 0x1, 0x1, 221, 2536, -1, 34, 1, 60 },
+  { 0x1, 0x1, 221, 2537, -1, 34, 1, 55 },
+  { 0x1, 0x1, 221, 2538, -1, 34, 1, 60 },
+  { 0x1, 0x1, 221, 2539, -1, 34, 1, 55 },
+  { 0x41, 0x41, 221, 2540, -1, 28, 1, 30 },
+  { 0x1, 0x1, 221, 2541, -1, 34, 1, 30 },
+  { 0x83, 0x83, 221, 2542, -1, 27, 1, 30 },
+  { 0x81, 0x81, 221, 2543, -1, 27, 1, 30 },
+  { 0x1, 0x1, 221, 2544, -1, 34, 1, 65 },
+  { 0x1, 0x1, 221, 2545, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2546, -1, 34, 1, 30 },
+  { 0x5, 0x5, 221, 2547, -1, 34, 1, 65 },
+  { 0x9, 0x9, 221, 2548, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2549, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2550, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2551, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2552, -1, 34, 1, 65 },
+  { 0x1, 0x1, 221, 2553, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2554, -1, 34, 1, 30 },
+  { 0x5, 0x5, 221, 2555, -1, 34, 1, 65 },
+  { 0x9, 0x9, 221, 2556, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2557, -1, 34, 1, 30 },
+  { 0x5, 0x5, 221, 2558, -1, 34, 1, 65 },
+  { 0x9, 0x9, 221, 2559, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2560, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2561, -1, 34, 1, 65 },
+  { 0x1, 0x1, 221, 2562, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2563, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2564, -1, 34, 1, 65 },
+  { 0x1, 0x1, 221, 2565, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2566, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2567, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2568, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2569, -1, 34, 1, 50 },
+  { 0x81, 0x81, 221, 2570, -1, 27, 1, 50 },
+  { 0x41, 0x41, 221, 2571, -1, 28, 1, 50 },
+  { 0x83, 0x83, 221, 2572, -1, 27, 1, 50 },
+  { 0x21, 0x21, 221, 2573, -1, 29, 1, 50 },
+  { 0x85, 0x85, 221, 2574, -1, 27, 1, 50 },
+  { 0x43, 0x43, 221, 2575, -1, 28, 1, 50 },
+  { 0x87, 0x87, 221, 2576, -1, 27, 1, 50 },
+  { 0x1, 0x1, 221, 2577, -1, 34, 1, 50 },
+  { 0x1, 0x1, 221, 2578, -1, 34, 1, 50 },
+  { 0x1, 0x1, 221, 2579, -1, 34, 1, 50 },
+  { 0x1, 0x1, 221, 2580, -1, 34, 1, 50 },
+  { 0x41, 0x41, 221, 2581, -1, 28, 1, 30 },
+  { 0x1, 0x1, 221, 2582, -1, 34, 1, 30 },
+  { 0x83, 0x83, 221, 2583, -1, 27, 1, 30 },
+  { 0x81, 0x81, 221, 2584, -1, 27, 1, 30 },
+  { 0x1, 0x1, 221, 2585, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2586, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2587, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2588, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2589, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2590, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2591, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2592, -1, 34, 1, 25 },
+  { 0x1, 0x1, 221, 2593, -1, 34, 1, 25 },
+  { 0x1, 0x1, 221, 2594, -1, 34, 1, 25 },
+  { 0x1, 0x1, 221, 2595, -1, 34, 1, 25 },
+  { 0x1, 0x1, 221, 2596, -1, 34, 1, 36 },
+  { 0x1, 0x1, 221, 2597, -1, 34, 1, 65 },
+  { 0x1, 0x1, 221, 2598, -1, 34, 1, 30 },
+  { 0x1, 0x1, 221, 2599, -1, 34, 1, 30 },
+  { 0x1, 0x1, 222, 2600, -1, 35, 1, 65 },
+  { 0x1, 0x1, 222, 2601, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2602, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2603, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2604, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2605, -1, 35, 1, 46 },
+  { 0x1, 0x1, 222, 2606, -1, 35, 1, 42 },
+  { 0x800001, 0x800001, 222, 2607, -1, 12, 1, 61 },
+  { 0x1, 0x1, 222, 2608, -1, 35, 1, 56 },
+  { 0x1800001, 0x1800001, 222, 2609, -1, 12, 1, 61 },
+  { 0x3, 0x3, 222, 2610, -1, 35, 1, 56 },
+  { 0xa00001, 0xa00001, 222, 2611, -1, 12, 1, 61 },
+  { 0x5, 0x5, 222, 2612, -1, 33, 1, 56 },
+  { 0x1a00001, 0x1a00001, 222, 2613, -1, 12, 1, 51 },
+  { 0xd, 0xd, 222, 2614, -1, 33, 1, 51 },
+  { 0x1, 0x1, 222, 2615, -1, 35, 1, 61 },
+  { 0x1, 0x1, 222, 2616, -1, 35, 1, 56 },
+  { 0x1, 0x1, 222, 2617, -1, 35, 1, 61 },
+  { 0x1, 0x1, 222, 2618, -1, 35, 1, 56 },
+  { 0x1, 0x1, 222, 2619, -1, 35, 1, 61 },
+  { 0x1, 0x1, 222, 2620, -1, 35, 1, 56 },
+  { 0x1, 0x1, 222, 2621, -1, 35, 1, 51 },
+  { 0x1, 0x1, 222, 2622, -1, 35, 1, 51 },
+  { 0x800001, 0x800001, 222, 2623, -1, 12, 1, 61 },
+  { 0x1, 0x1, 222, 2624, -1, 35, 1, 56 },
+  { 0xa00001, 0x1a00001, 222, 2625, -1, 12, 1, 61 },
+  { 0x5, 0xd, 222, 2626, -1, 33, 1, 56 },
+  { 0x1, 0x1, 222, 2627, -1, 35, 1, 61 },
+  { 0x1, 0x1, 222, 2628, -1, 35, 1, 56 },
+  { 0x1, 0x1, 222, 2629, -1, 35, 1, 61 },
+  { 0x1, 0x1, 222, 2630, -1, 35, 1, 56 },
+  { 0x800001, 0x800001, 222, 2631, -1, 12, 1, 61 },
+  { 0x1, 0x1, 222, 2632, -1, 35, 1, 56 },
+  { 0x1800001, 0x1800001, 222, 2633, -1, 12, 1, 61 },
+  { 0x3, 0x3, 222, 2634, -1, 35, 1, 56 },
+  { 0xa00001, 0xa00001, 222, 2635, -1, 12, 1, 61 },
+  { 0x5, 0x5, 222, 2636, -1, 33, 1, 56 },
+  { 0x1a00001, 0x1a00001, 222, 2637, -1, 12, 1, 51 },
+  { 0xd, 0xd, 222, 2638, -1, 33, 1, 51 },
+  { 0x1, 0x1, 222, 2639, -1, 35, 1, 61 },
+  { 0x1, 0x1, 222, 2640, -1, 35, 1, 56 },
+  { 0x1, 0x1, 222, 2641, -1, 35, 1, 61 },
+  { 0x1, 0x1, 222, 2642, -1, 35, 1, 56 },
+  { 0x1, 0x1, 222, 2643, -1, 35, 1, 61 },
+  { 0x1, 0x1, 222, 2644, -1, 35, 1, 56 },
+  { 0x1, 0x1, 222, 2645, -1, 35, 1, 51 },
+  { 0x1, 0x1, 222, 2646, -1, 35, 1, 51 },
+  { 0x800001, 0x800001, 222, 2647, -1, 12, 1, 61 },
+  { 0x1, 0x1, 222, 2648, -1, 35, 1, 56 },
+  { 0xa00001, 0x1a00001, 222, 2649, -1, 12, 1, 61 },
+  { 0x5, 0xd, 222, 2650, -1, 33, 1, 56 },
+  { 0x1, 0x1, 222, 2651, -1, 35, 1, 61 },
+  { 0x1, 0x1, 222, 2652, -1, 35, 1, 56 },
+  { 0x1, 0x1, 222, 2653, -1, 35, 1, 61 },
+  { 0x1, 0x1, 222, 2654, -1, 35, 1, 56 },
+  { 0x81, 0x81, 222, 2655, -1, 28, 1, 31 },
+  { 0x1, 0x1, 222, 2656, -1, 35, 1, 31 },
+  { 0x103, 0x103, 222, 2657, -1, 27, 1, 31 },
+  { 0x101, 0x101, 222, 2658, -1, 27, 1, 31 },
+  { 0x1, 0x1, 222, 2659, -1, 35, 1, 65 },
+  { 0x1, 0x1, 222, 2660, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2661, -1, 35, 1, 31 },
+  { 0x3, 0x3, 222, 2662, -1, 35, 1, 65 },
+  { 0x5, 0x5, 222, 2663, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2664, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2665, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2666, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2667, -1, 35, 1, 65 },
+  { 0x1, 0x1, 222, 2668, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2669, -1, 35, 1, 31 },
+  { 0x3, 0x3, 222, 2670, -1, 35, 1, 65 },
+  { 0x5, 0x5, 222, 2671, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2672, -1, 35, 1, 31 },
+  { 0x3, 0x3, 222, 2673, -1, 35, 1, 65 },
+  { 0x5, 0x5, 222, 2674, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2675, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2676, -1, 35, 1, 65 },
+  { 0x1, 0x1, 222, 2677, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2678, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2679, -1, 35, 1, 65 },
+  { 0x1, 0x1, 222, 2680, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2681, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2682, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2683, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2684, -1, 35, 1, 51 },
+  { 0x101, 0x101, 222, 2685, -1, 27, 1, 51 },
+  { 0x81, 0x81, 222, 2686, -1, 28, 1, 51 },
+  { 0x103, 0x103, 222, 2687, -1, 27, 1, 51 },
+  { 0x41, 0x41, 222, 2688, -1, 29, 1, 51 },
+  { 0x105, 0x105, 222, 2689, -1, 27, 1, 51 },
+  { 0x83, 0x83, 222, 2690, -1, 28, 1, 51 },
+  { 0x107, 0x107, 222, 2691, -1, 27, 1, 51 },
+  { 0x1, 0x1, 222, 2692, -1, 35, 1, 51 },
+  { 0x1, 0x1, 222, 2693, -1, 35, 1, 51 },
+  { 0x1, 0x1, 222, 2694, -1, 35, 1, 51 },
+  { 0x1, 0x1, 222, 2695, -1, 35, 1, 51 },
+  { 0x81, 0x81, 222, 2696, -1, 28, 1, 31 },
+  { 0x1, 0x1, 222, 2697, -1, 35, 1, 31 },
+  { 0x103, 0x103, 222, 2698, -1, 27, 1, 31 },
+  { 0x101, 0x101, 222, 2699, -1, 27, 1, 31 },
+  { 0x1, 0x1, 222, 2700, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2701, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2702, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2703, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2704, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2705, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2706, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2707, -1, 35, 1, 26 },
+  { 0x1, 0x1, 222, 2708, -1, 35, 1, 26 },
+  { 0x1, 0x1, 222, 2709, -1, 35, 1, 26 },
+  { 0x1, 0x1, 222, 2710, -1, 35, 1, 26 },
+  { 0x1, 0x1, 222, 2711, -1, 35, 1, 37 },
+  { 0x1, 0x1, 222, 2712, -1, 35, 1, 65 },
+  { 0x1, 0x1, 222, 2713, -1, 35, 1, 31 },
+  { 0x1, 0x1, 222, 2714, -1, 35, 1, 31 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 65 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, 2209, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 47 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 43 },
+  { 0xc00001, 0xc00001, 223, -1, -1, 12, 1, 62 },
+  { 0x3, 0x3, 223, 2930, -1, 34, 1, 57 },
+  { 0x1c00001, 0x1c00001, 223, -1, -1, 12, 1, 62 },
+  { 0x7, 0x7, 223, 2931, -1, 34, 1, 57 },
+  { 0xe00001, 0xe00001, 223, -1, -1, 12, 1, 62 },
+  { 0x7, 0x7, 223, 2932, -1, 33, 1, 57 },
+  { 0x1e00001, 0x1e00001, 223, -1, -1, 12, 1, 52 },
+  { 0xf, 0xf, 223, 2933, -1, 33, 1, 52 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 62 },
+  { 0x3, 0x3, 223, 2934, -1, 34, 1, 57 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 62 },
+  { 0x3, 0x3, 223, 2935, -1, 34, 1, 57 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 62 },
+  { 0x3, 0x3, 223, 2936, -1, 34, 1, 57 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 52 },
+  { 0x3, 0x3, 223, 2937, -1, 34, 1, 52 },
+  { 0xc00001, 0xc00001, 223, -1, -1, 12, 1, 62 },
+  { 0x3, 0x3, 223, 2942, -1, 34, 1, 57 },
+  { 0xe00001, 0x1e00001, 223, -1, -1, 12, 1, 62 },
+  { 0x7, 0xf, 223, 2943, -1, 33, 1, 57 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 62 },
+  { 0x3, 0x3, 223, 2944, -1, 34, 1, 57 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 62 },
+  { 0x3, 0x3, 223, 2945, -1, 34, 1, 57 },
+  { 0xc00001, 0xc00001, 223, -1, -1, 12, 1, 62 },
+  { 0x3, 0x3, 223, 2948, -1, 34, 1, 57 },
+  { 0x1c00001, 0x1c00001, 223, -1, -1, 12, 1, 62 },
+  { 0x7, 0x7, 223, 2949, -1, 34, 1, 57 },
+  { 0xe00001, 0xe00001, 223, -1, -1, 12, 1, 62 },
+  { 0x7, 0x7, 223, 2950, -1, 33, 1, 57 },
+  { 0x1e00001, 0x1e00001, 223, -1, -1, 12, 1, 52 },
+  { 0xf, 0xf, 223, 2951, -1, 33, 1, 52 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 62 },
+  { 0x3, 0x3, 223, 2952, -1, 34, 1, 57 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 62 },
+  { 0x3, 0x3, 223, 2953, -1, 34, 1, 57 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 62 },
+  { 0x3, 0x3, 223, 2954, -1, 34, 1, 57 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 52 },
+  { 0x3, 0x3, 223, 2955, -1, 34, 1, 52 },
+  { 0xc00001, 0xc00001, 223, -1, -1, 12, 1, 62 },
+  { 0x3, 0x3, 223, 2960, -1, 34, 1, 57 },
+  { 0xe00001, 0x1e00001, 223, -1, -1, 12, 1, 62 },
+  { 0x7, 0xf, 223, 2961, -1, 33, 1, 57 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 62 },
+  { 0x3, 0x3, 223, 2962, -1, 34, 1, 57 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 62 },
+  { 0x3, 0x3, 223, 2963, -1, 34, 1, 57 },
+  { 0xc1, 0xc1, 223, -1, -1, 28, 1, 32 },
+  { 0x3, 0x3, 223, 2828, -1, 34, 1, 32 },
+  { 0x183, 0x183, 223, -1, -1, 27, 1, 32 },
+  { 0x181, 0x181, 223, 2829, -1, 27, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 65 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, 2210, -1, 34, 1, 32 },
+  { 0x7, 0x7, 223, -1, -1, 34, 1, 65 },
+  { 0xb, 0xb, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, 2211, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 65 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, 2214, -1, 34, 1, 32 },
+  { 0x7, 0x7, 223, -1, -1, 34, 1, 65 },
+  { 0xb, 0xb, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, 2215, -1, 34, 1, 32 },
+  { 0x7, 0x7, 223, -1, -1, 34, 1, 65 },
+  { 0xb, 0xb, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, 2217, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 65 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, 2219, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 65 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, 2220, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 52 },
+  { 0x181, 0x181, 223, -1, -1, 27, 1, 52 },
+  { 0xc1, 0xc1, 223, -1, -1, 28, 1, 52 },
+  { 0x183, 0x183, 223, -1, -1, 27, 1, 52 },
+  { 0x61, 0x61, 223, -1, -1, 29, 1, 52 },
+  { 0x185, 0x185, 223, -1, -1, 27, 1, 52 },
+  { 0xc3, 0xc3, 223, -1, -1, 28, 1, 52 },
+  { 0x187, 0x187, 223, -1, -1, 27, 1, 52 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 52 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 52 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 52 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 52 },
+  { 0xc1, 0xc1, 223, -1, -1, 28, 1, 32 },
+  { 0x3, 0x3, 223, 2832, -1, 34, 1, 32 },
+  { 0x183, 0x183, 223, -1, -1, 27, 1, 32 },
+  { 0x181, 0x181, 223, 2833, -1, 27, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 27 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 27 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 27 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 27 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 38 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 65 },
+  { 0x3, 0x3, 223, -1, -1, 34, 1, 32 },
+  { 0x3, 0x3, 223, 2222, -1, 34, 1, 32 },
+  { 0x3, 0x3, 224, 522, 1433, 32, 1, 128 },
+  { 0x3, 0x3, 224, 523, 1442, 32, 1, 128 },
+  { 0x3, 0x3, 224, 524, 1451, 32, 1, 128 },
+  { 0x3, 0x3, 224, 525, 1464, 32, 1, 128 },
+  { 0x3, 0x3, 224, 526, 1473, 32, 1, 128 },
+  { 0x3, 0x3, 224, 527, 1482, 32, 1, 128 },
+  { 0x3, 0x3, 224, 528, 1491, 32, 1, 128 },
+  { 0x3, 0x3, 224, 529, 1500, 32, 1, 128 },
+  { 0x3, 0x3, 224, 530, 1509, 32, 1, 128 },
+  { 0x3, 0x3, 224, 531, 1518, 32, 1, 128 },
+  { 0x3, 0x3, 224, 532, 1528, 32, 1, 128 },
+  { 0x3, 0x3, 224, 533, 1538, 32, 1, 128 },
+  { 0x3, 0x3, 224, 546, 1551, 32, 1, 143 },
+  { 0x3, 0x3, 224, 547, 1557, 32, 1, 148 },
+  { 0x3, 0x3, 224, 548, 1563, 32, 1, 148 },
+  { 0x3, 0x3, 224, 549, 1569, 32, 1, 143 },
+  { 0x3, 0x3, 224, 550, 1575, 32, 1, 148 },
+  { 0x3, 0x3, 224, 551, 1581, 32, 1, 148 },
+  { 0x3, 0x3, 224, 552, 1587, 32, 1, 143 },
+  { 0x3, 0x3, 224, 553, 1593, 32, 1, 148 },
+  { 0x3, 0x3, 224, 554, 1599, 32, 1, 148 },
+  { 0x3, 0x3, 224, 555, 1605, 32, 1, 143 },
+  { 0x3, 0x3, 224, 556, 1611, 32, 1, 148 },
+  { 0x3, 0x3, 224, 557, 1617, 32, 1, 143 },
+  { 0x3, 0x3, 224, 558, 1623, 32, 1, 148 },
+  { 0x3, 0x3, 224, 559, 1629, 32, 1, 143 },
+  { 0x3, 0x3, 224, 560, 1635, 32, 1, 148 },
+  { 0x3, 0x3, 224, 561, 1641, 32, 1, 143 },
+  { 0x3, 0x3, 224, 562, 1647, 32, 1, 148 },
+  { 0x3, 0x3, 224, 563, 1653, 32, 1, 148 },
+  { 0x1, 0x1, 225, -1, -1, 28, 1, 33 },
+  { 0x1, 0x1, 225, -1, -1, 28, 1, 33 },
+  { 0x0, 0x0, 232, 940, -1, 0, 1, 137 },
+  { 0x0, 0x0, 232, 941, -1, 0, 1, 155 },
+  { 0x1, 0x1, 233, -1, 1964, 33, 1, 133 },
+  { 0x1, 0x1, 233, -1, 1967, 33, 1, 139 },
+  { 0x0, 0x0, 233, -1, 1969, 0, 1, 150 },
+  { 0x0, 0x0, 233, -1, 1970, 0, 1, 156 },
+  { 0x0, 0x0, 234, 865, 953, 0, 0, -1 },
+  { 0x0, 0x0, 234, 866, 961, 0, 0, -1 },
+  { 0x0, 0x0, 234, 867, 957, 0, 0, -1 },
+  { 0x1, 0x1, 234, 868, 602, 33, 1, 6 },
+  { 0x8000001, 0x8000001, 234, 869, 610, 6, 1, 7 },
+  { 0x1, 0x1, 234, 870, 606, 33, 1, 6 },
+  { 0x0, 0x0, 234, 871, 965, 0, 0, -1 },
+  { 0x1, 0x1, 234, 872, 622, 33, 1, 8 },
+  { 0x0, 0x0, 234, 873, 969, 0, 0, -1 },
+  { 0x1, 0x1, 234, 874, 634, 33, 1, 15 },
+  { 0x0, 0x0, 234, 875, 974, 0, 0, -1 },
+  { 0x0, 0x0, 234, 876, 978, 0, 0, -1 },
+  { 0x1, 0x1, 234, 877, 657, 33, 1, 17 },
+  { 0x1, 0x1, 234, 878, 661, 33, 1, 17 },
+  { 0x0, 0x0, 234, 879, 982, 0, 0, -1 },
+  { 0x0, 0x0, 234, 880, 986, 0, 0, -1 },
+  { 0x1, 0x1, 234, 881, 681, 33, 1, 18 },
+  { 0x8000001, 0x8000001, 234, 882, 685, 6, 1, 18 },
+  { 0x0, 0x0, 234, 883, 990, 0, 0, -1 },
+  { 0x1, 0x1, 234, 884, 697, 33, 1, 19 },
+  { 0x0, 0x0, 234, 885, 994, 0, 0, -1 },
+  { 0x0, 0x0, 234, 886, 998, 0, 0, -1 },
+  { 0x1, 0x1, 234, 887, 717, 33, 1, 20 },
+  { 0x8000001, 0x8000001, 234, 888, 721, 6, 1, 20 },
+  { 0x0, 0x0, 234, 889, 1002, 0, 0, -1 },
+  { 0x1, 0x1, 234, 890, 733, 33, 1, 21 },
+  { 0x0, 0x0, 234, 891, 1007, 0, 0, -1 },
+  { 0x0, 0x0, 234, 892, 1011, 0, 0, -1 },
+  { 0x1, 0x1, 234, 893, 756, 33, 1, 17 },
+  { 0x1, 0x1, 234, 894, 760, 33, 1, 17 },
+  { 0x0, 0x0, 234, 895, 1015, 0, 0, -1 },
+  { 0x1, 0x1, 234, 896, 772, 33, 1, 21 },
+  { 0x0, 0x0, 235, 2753, 952, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2754, 960, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2755, 956, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2756, 601, 0, 1, 6 },
+  { 0x1, 0x1, 235, 2757, 609, 6, 1, 7 },
+  { 0x0, 0x0, 235, 2758, 605, 0, 1, 6 },
+  { 0x0, 0x0, 235, 2759, 964, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2760, 621, 0, 1, 8 },
+  { 0x0, 0x0, 235, 2761, 968, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2762, 633, 0, 1, 15 },
+  { 0x0, 0x0, 235, 2763, 973, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2764, 977, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2765, 656, 0, 1, 17 },
+  { 0x0, 0x0, 235, 2766, 660, 0, 1, 17 },
+  { 0x0, 0x0, 235, 2767, 981, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2768, 985, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2769, 680, 0, 1, 18 },
+  { 0x1, 0x1, 235, 2770, 684, 6, 1, 18 },
+  { 0x0, 0x0, 235, 2771, 989, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2772, 696, 0, 1, 19 },
+  { 0x0, 0x0, 235, 2773, 993, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2774, 997, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2775, 716, 0, 1, 20 },
+  { 0x1, 0x1, 235, 2776, 720, 6, 1, 20 },
+  { 0x0, 0x0, 235, 2777, 1001, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2778, 732, 0, 1, 21 },
+  { 0x0, 0x0, 235, 2779, 1006, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2780, 1010, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2781, 755, 0, 1, 17 },
+  { 0x0, 0x0, 235, 2782, 759, 0, 1, 17 },
+  { 0x0, 0x0, 235, 2783, 1014, 0, 0, -1 },
+  { 0x0, 0x0, 235, 2784, 771, 0, 1, 21 },
+  { 0x1, 0x1, 235, 897, 1137, 27, 1, 16 },
+  { 0x0, 0x0, 235, 898, 1135, 0, 1, 16 },
+  { 0x0, 0x0, 235, 1202, 1139, 0, 1, 22 },
+  { 0x0, 0x1, 235, 1147, 1145, 20, 1, 67 },
+  { 0x0, 0x0, 235, 111, 1143, 0, 1, 67 },
+  { 0x1, 0x1, 238, -1, -1, 29, 1, 0 },
+  { 0x0, 0x0, 238, -1, -1, 0, 1, 0 },
+  { 0x1, 0x1, 238, 2984, -1, 27, 1, 0 },
+  { 0x1, 0x1, 238, 2985, -1, 27, 1, 0 },
+  { 0x1, 0x1, 238, 2986, -1, 27, 1, 0 },
+  { 0x1, 0x1, 238, 2987, -1, 27, 1, 0 },
+  { 0x0, 0x0, 260, -1, 2310, 0, 0, -1 },
+  { 0x0, 0x0, 260, -1, 2312, 0, 0, -1 },
+  { 0x1, 0x1, 260, -1, -1, 28, 1, 29 },
+  { 0x1, 0x1, 260, -1, -1, 28, 1, 29 },
+  { 0x0, 0x0, 260, -1, 2351, 0, 0, -1 },
+  { 0x0, 0x0, 260, -1, 2353, 0, 0, -1 },
+  { 0x1, 0x1, 260, -1, -1, 28, 1, 29 },
+  { 0x1, 0x1, 260, -1, -1, 28, 1, 29 },
+  { 0x0, 0x0, 262, 23, -1, 0, 1, 0 },
+  { 0x0, 0x0, 262, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 262, -1, -1, 0, 1, 0 },
+  { 0x0, 0x1, 262, -1, -1, 29, 1, 0 },
+  { 0x0, 0x1, 262, -1, -1, 29, 1, 0 },
+  { 0x0, 0x1, 262, -1, -1, 29, 1, 0 },
+  { 0x0, 0x1, 262, -1, -1, 29, 1, 0 },
+  { 0x0, 0x1, 262, -1, -1, 29, 1, 0 },
+  { 0x0, 0x0, 262, 180, -1, 0, 1, 0 },
+  { 0x0, 0x1, 262, -1, -1, 29, 1, 0 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 299, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 321, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 347, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 369, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 64 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 64 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 64 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 64 },
+  { 0x0, 0x0, 263, -1, 2262, 0, 0, -1 },
+  { 0x0, 0x0, 263, -1, 2264, 0, 0, -1 },
+  { 0x0, 0x0, 263, -1, 2266, 0, 0, -1 },
+  { 0x0, 0x0, 263, -1, 2268, 0, 0, -1 },
+  { 0x1, 0x1, 263, -1, 2270, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, 2272, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, 2274, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, 2276, 12, 1, 49 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 49 },
+  { 0x0, 0x0, 263, -1, 2278, 0, 0, -1 },
+  { 0x0, 0x0, 263, -1, 2280, 0, 0, -1 },
+  { 0x1, 0x1, 263, -1, 2282, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, 2284, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 59 },
+  { 0x0, 0x0, 263, -1, 2286, 0, 0, -1 },
+  { 0x0, 0x0, 263, -1, 2288, 0, 0, -1 },
+  { 0x0, 0x0, 263, -1, 2290, 0, 0, -1 },
+  { 0x0, 0x0, 263, -1, 2292, 0, 0, -1 },
+  { 0x1, 0x1, 263, -1, 2294, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, 2296, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, 2298, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, 2300, 12, 1, 49 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 49 },
+  { 0x0, 0x0, 263, -1, 2302, 0, 0, -1 },
+  { 0x0, 0x0, 263, -1, 2304, 0, 0, -1 },
+  { 0x1, 0x1, 263, -1, 2306, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, 2308, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 59 },
+  { 0x1, 0x1, 263, -1, -1, 12, 1, 59 },
+  { 0x1, 0x1, 263, 391, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 393, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 507, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 509, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 399, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 401, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 515, -1, 12, 1, 2 },
+  { 0x1, 0x1, 263, 517, -1, 12, 1, 2 },
+  { 0x0, 0x0, 264, -1, 2269, 0, 0, -1 },
+  { 0x9, 0x9, 264, -1, 2277, 33, 1, 49 },
+  { 0x9, 0x9, 264, -1, 2941, 33, 1, 49 },
+  { 0x0, 0x0, 264, 1381, 2342, 0, 0, -1 },
+  { 0x3, 0x3, 264, 1382, -1, 27, 1, 49 },
+  { 0x0, 0x0, 268, 2822, -1, 0, 1, 0 },
+  { 0x3, 0x3, 269, -1, -1, 27, 1, 0 },
+  { 0x3, 0x3, 269, -1, -1, 27, 1, 0 },
+  { 0x3, 0x3, 269, -1, -1, 27, 1, 0 },
+  { 0x3, 0x3, 269, -1, -1, 27, 1, 0 },
+  { 0x1, 0x1, 270, 2980, -1, 28, 1, 0 },
+  { 0x1, 0x1, 270, 2981, -1, 28, 1, 0 },
+  { 0x1, 0x1, 270, 2982, -1, 28, 1, 0 },
+  { 0x1, 0x1, 270, 2983, -1, 28, 1, 0 },
+  { 0x1, 0x1, 271, -1, -1, 27, 1, 93 },
+  { 0x1, 0x1, 271, -1, -1, 27, 1, 93 },
+  { 0x0, 0x0, 271, -1, 950, 0, 0, -1 },
+  { 0x0, 0x0, 272, 2993, 2799, 0, 0, -1 },
+  { 0x0, 0x0, 272, 2994, 2801, 0, 0, -1 },
+  { 0x0, 0x0, 273, -1, 2800, 0, 0, -1 },
+  { 0x0, 0x0, 273, -1, 2802, 0, 0, -1 },
+  { 0x0, 0x0, 274, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 274, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 274, -1, -1, 0, 1, 40 },
+  { 0x0, 0x0, 279, -1, -1, 0, 1, 33 },
+  { 0x0, 0x0, 283, -1, 2316, 0, 1, 29 },
+  { 0x0, 0x0, 284, -1, -1, 0, 1, 0 },
+  { 0x0, 0x0, 284, -1, -1, 0, 1, 71 },
+  { 0x0, 0x0, 284, 1983, 2966, 0, 1, 1 },
+  { 0x0, 0x0, 284, 1984, 2967, 0, 1, 1 },
+  { 0x0, 0x0, 284, -1, 508, 0, 0, -1 },
+  { 0x0, 0x0, 284, -1, 510, 0, 0, -1 },
+  { 0x0, 0x0, 284, 1987, 2970, 0, 1, 1 },
+  { 0x0, 0x0, 284, 1988, 2971, 0, 1, 1 },
+  { 0x0, 0x0, 284, -1, 516, 0, 0, -1 },
+  { 0x0, 0x0, 284, -1, 518, 0, 0, -1 },
+};
+
+static const struct ia64_main_table
+main_table[] = {
+  { 5, 1, 1, 0x0000010000000000ull, 0x000001eff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 0, },
+  { 5, 1, 1, 0x0000010008000000ull, 0x000001eff8000000ull, { 24, 25, 26, 4, 0 }, 0x0, 1, },
+  { 5, 7, 1, 0x0000000000000000ull, 0x0000000000000000ull, { 24, 66, 27, 0, 0 }, 0x0, 2, },
+  { 5, 7, 1, 0x0000000000000000ull, 0x0000000000000000ull, { 24, 63, 26, 0, 0 }, 0x0, 3, },
+  { 6, 1, 1, 0x0000012000000000ull, 0x000001e000000000ull, { 24, 66, 27, 0, 0 }, 0x0, 4, },
+  { 7, 1, 1, 0x0000010040000000ull, 0x000001eff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 5, },
+  { 7, 1, 1, 0x0000010c00000000ull, 0x000001ee00000000ull, { 24, 63, 26, 0, 0 }, 0x0, 6, },
+  { 8, 1, 1, 0x0000010800000000ull, 0x000001ee00000000ull, { 24, 63, 26, 0, 0 }, 0x0, 7, },
+  { 9, 3, 1, 0x0000002c00000000ull, 0x000001ee00000000ull, { 24, 3, 52, 53, 54 }, 0x221, 8, },
+  { 9, 3, 1, 0x0000002c00000000ull, 0x000001ee00000000ull, { 24, 52, 53, 54, 0 }, 0x261, 9, },
+  { 10, 1, 1, 0x0000010060000000ull, 0x000001eff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 10, },
+  { 10, 1, 1, 0x0000010160000000ull, 0x000001eff8000000ull, { 24, 55, 26, 0, 0 }, 0x0, 11, },
+  { 11, 1, 1, 0x0000010068000000ull, 0x000001eff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 12, },
+  { 11, 1, 1, 0x0000010168000000ull, 0x000001eff8000000ull, { 24, 55, 26, 0, 0 }, 0x0, 13, },
+  { 14, 4, 0, 0x0000000100000000ull, 0x000001eff80011ffull, { 16, 0, 0, 0, 0 }, 0x40, 951, },
+  { 14, 4, 0, 0x0000000100000000ull, 0x000001eff80011c0ull, { 16, 0, 0, 0, 0 }, 0x0, 807, },
+  { 14, 4, 0, 0x0000000100000000ull, 0x000001eff80011c0ull, { 16, 0, 0, 0, 0 }, 0x40, 808, },
+  { 14, 4, 0, 0x0000000108000100ull, 0x000001eff80011c0ull, { 16, 0, 0, 0, 0 }, 0x200, 2200, },
+  { 14, 4, 0, 0x0000000108000100ull, 0x000001eff80011c0ull, { 16, 0, 0, 0, 0 }, 0x240, 2201, },
+  { 14, 4, 1, 0x0000002100000000ull, 0x000001ef00001000ull, { 15, 16, 0, 0, 0 }, 0x0, 564, },
+  { 14, 4, 1, 0x0000002100000000ull, 0x000001ef00001000ull, { 15, 16, 0, 0, 0 }, 0x40, 565, },
+  { 14, 4, 0, 0x0000008000000000ull, 0x000001ee000011ffull, { 81, 0, 0, 0, 0 }, 0x40, 972, },
+  { 14, 4, 0, 0x0000008000000000ull, 0x000001ee000011c0ull, { 81, 0, 0, 0, 0 }, 0x0, 809, },
+  { 14, 4, 0, 0x0000008000000000ull, 0x000001ee000011c0ull, { 81, 0, 0, 0, 0 }, 0x40, 810, },
+  { 14, 4, 0, 0x0000008000000080ull, 0x000001ee000011c0ull, { 81, 0, 0, 0, 0 }, 0x210, 2991, },
+  { 14, 4, 0, 0x0000008000000080ull, 0x000001ee000011c0ull, { 81, 0, 0, 0, 0 }, 0x250, 2992, },
+  { 14, 4, 0, 0x0000008000000140ull, 0x000001ee000011c0ull, { 81, 0, 0, 0, 0 }, 0x30, 572, },
+  { 14, 4, 0, 0x0000008000000140ull, 0x000001ee000011c0ull, { 81, 0, 0, 0, 0 }, 0x70, 573, },
+  { 14, 4, 0, 0x0000008000000180ull, 0x000001ee000011c0ull, { 81, 0, 0, 0, 0 }, 0x230, 570, },
+  { 14, 4, 0, 0x0000008000000180ull, 0x000001ee000011c0ull, { 81, 0, 0, 0, 0 }, 0x270, 571, },
+  { 14, 4, 1, 0x000000a000000000ull, 0x000001ee00001000ull, { 15, 81, 0, 0, 0 }, 0x0, 566, },
+  { 14, 4, 1, 0x000000a000000000ull, 0x000001ee00001000ull, { 15, 81, 0, 0, 0 }, 0x40, 567, },
+  { 15, 4, 0, 0x0000000000000000ull, 0x000001e1f8000000ull, { 65, 0, 0, 0, 0 }, 0x0, 519, },
+  { 15, 5, 0, 0x0000000000000000ull, 0x000001e3f8000000ull, { 65, 0, 0, 0, 0 }, 0x0, 942, },
+  { 15, 2, 0, 0x0000000000000000ull, 0x000001eff8000000ull, { 65, 0, 0, 0, 0 }, 0x2, 1120, },
+  { 15, 3, 0, 0x0000000000000000ull, 0x000001eff8000000ull, { 65, 0, 0, 0, 0 }, 0x0, 1245, },
+  { 15, 6, 0, 0x0000000000000000ull, 0x000001eff8000000ull, { 69, 0, 0, 0, 0 }, 0x0, 2995, },
+  { 15, 7, 0, 0x0000000000000000ull, 0x0000000000000000ull, { 65, 0, 0, 0, 0 }, 0x0, 16, },
+  { 16, 6, 0, 0x0000018000000000ull, 0x000001ee000011ffull, { 82, 0, 0, 0, 0 }, 0x40, 1005, },
+  { 16, 6, 0, 0x0000018000000000ull, 0x000001ee000011c0ull, { 82, 0, 0, 0, 0 }, 0x0, 811, },
+  { 16, 6, 0, 0x0000018000000000ull, 0x000001ee000011c0ull, { 82, 0, 0, 0, 0 }, 0x40, 812, },
+  { 16, 6, 1, 0x000001a000000000ull, 0x000001ee00001000ull, { 15, 82, 0, 0, 0 }, 0x0, 568, },
+  { 16, 6, 1, 0x000001a000000000ull, 0x000001ee00001000ull, { 15, 82, 0, 0, 0 }, 0x40, 569, },
+  { 17, 4, 0, 0x0000004080000000ull, 0x000001e9f8000018ull, { 16, 77, 0, 0, 0 }, 0x20, 2818, },
+  { 17, 4, 0, 0x000000e000000000ull, 0x000001e800000018ull, { 81, 77, 0, 0, 0 }, 0x20, 2819, },
+  { 18, 4, 0, 0x0000000060000000ull, 0x000001e1f8000000ull, { 0, 0, 0, 0, 0 }, 0x2c, 222, },
+  { 22, 2, 0, 0x0000000200000000ull, 0x000001ee00000000ull, { 25, 80, 0, 0, 0 }, 0x0, 2205, },
+  { 22, 3, 0, 0x0000000800000000ull, 0x000001ee00000000ull, { 24, 81, 0, 0, 0 }, 0x0, 224, },
+  { 22, 3, 0, 0x0000000c00000000ull, 0x000001ee00000000ull, { 18, 81, 0, 0, 0 }, 0x0, 225, },
+  { 22, 3, 0, 0x0000002200000000ull, 0x000001ee00000000ull, { 25, 80, 0, 0, 0 }, 0x0, 2206, },
+  { 22, 3, 0, 0x0000002600000000ull, 0x000001ee00000000ull, { 19, 80, 0, 0, 0 }, 0x0, 2207, },
+  { 22, 7, 0, 0x0000000000000000ull, 0x0000000000000000ull, { 25, 80, 0, 0, 0 }, 0x0, 2208, },
+  { 25, 4, 0, 0x0000000020000000ull, 0x000001e1f8000000ull, { 0, 0, 0, 0, 0 }, 0x224, 18, },
+  { 26, 1, 2, 0x0000018000000000ull, 0x000001fe00001000ull, { 22, 23, 25, 26, 0 }, 0x0, 1204, },
+  { 26, 1, 1, 0x0000018000000000ull, 0x000001fe00001000ull, { 22, 25, 26, 0, 0 }, 0x40, 1205, },
+  { 26, 1, 2, 0x0000018000000000ull, 0x000001fe00001000ull, { 23, 22, 26, 25, 0 }, 0x0, 1163, },
+  { 26, 1, 1, 0x0000018000000000ull, 0x000001fe00001000ull, { 23, 26, 25, 0, 0 }, 0x40, 1164, },
+  { 26, 1, 2, 0x0000018000000000ull, 0x000001fe00001000ull, { 22, 23, 26, 25, 0 }, 0x0, 1072, },
+  { 26, 1, 1, 0x0000018000000000ull, 0x000001fe00001000ull, { 22, 26, 25, 0, 0 }, 0x40, 1073, },
+  { 26, 1, 2, 0x0000018000000000ull, 0x000001fe00001000ull, { 23, 22, 25, 26, 0 }, 0x0, 1034, },
+  { 26, 1, 1, 0x0000018000000000ull, 0x000001fe00001000ull, { 23, 25, 26, 0, 0 }, 0x40, 1035, },
+  { 26, 1, 2, 0x0000018200000000ull, 0x000001fe00001000ull, { 22, 23, 25, 26, 0 }, 0x40, 1358, },
+  { 26, 1, 2, 0x0000019000000000ull, 0x000001fe00001000ull, { 22, 23, 7, 26, 0 }, 0x0, 1074, },
+  { 26, 1, 1, 0x0000019000000000ull, 0x000001fe00001000ull, { 22, 7, 26, 0, 0 }, 0x40, 1075, },
+  { 26, 1, 2, 0x0000019000000000ull, 0x000001fe00001000ull, { 22, 23, 26, 7, 0 }, 0x40, 1208, },
+  { 26, 1, 1, 0x0000019000000000ull, 0x000001fe00001000ull, { 22, 26, 7, 0, 0 }, 0x40, 1209, },
+  { 26, 1, 2, 0x0000019000000000ull, 0x000001fe00001000ull, { 22, 23, 7, 26, 0 }, 0x40, 1169, },
+  { 26, 1, 2, 0x0000018800000000ull, 0x000001ee00001000ull, { 22, 23, 55, 26, 0 }, 0x0, 1211, },
+  { 26, 1, 1, 0x0000018800000000ull, 0x000001ee00001000ull, { 22, 55, 26, 0, 0 }, 0x40, 1212, },
+  { 26, 1, 2, 0x0000018800000000ull, 0x000001ee00001000ull, { 22, 23, 57, 26, 0 }, 0x0, 1170, },
+  { 26, 1, 1, 0x0000018800000000ull, 0x000001ee00001000ull, { 22, 57, 26, 0, 0 }, 0x40, 1171, },
+  { 26, 1, 2, 0x0000018800000000ull, 0x000001ee00001000ull, { 23, 22, 57, 26, 0 }, 0x0, 1079, },
+  { 26, 1, 1, 0x0000018800000000ull, 0x000001ee00001000ull, { 23, 57, 26, 0, 0 }, 0x40, 1080, },
+  { 26, 1, 2, 0x0000018800000000ull, 0x000001ee00001000ull, { 23, 22, 55, 26, 0 }, 0x0, 1041, },
+  { 26, 1, 1, 0x0000018800000000ull, 0x000001ee00001000ull, { 23, 55, 26, 0, 0 }, 0x40, 1042, },
+  { 26, 1, 2, 0x0000018a00000000ull, 0x000001ee00001000ull, { 22, 23, 55, 26, 0 }, 0x40, 1363, },
+  { 26, 1, 2, 0x000001a800000000ull, 0x000001ee00001000ull, { 22, 23, 59, 26, 0 }, 0x0, 1196, },
+  { 26, 1, 1, 0x000001a800000000ull, 0x000001ee00001000ull, { 22, 59, 26, 0, 0 }, 0x40, 1197, },
+  { 26, 1, 2, 0x000001a800000000ull, 0x000001ee00001000ull, { 23, 22, 59, 26, 0 }, 0x0, 1107, },
+  { 26, 1, 1, 0x000001a800000000ull, 0x000001ee00001000ull, { 23, 59, 26, 0, 0 }, 0x40, 1108, },
+  { 26, 1, 2, 0x000001c200000000ull, 0x000001fe00001000ull, { 23, 22, 25, 26, 0 }, 0x40, 1364, },
+  { 26, 1, 2, 0x000001d000000000ull, 0x000001fe00001000ull, { 23, 22, 7, 26, 0 }, 0x40, 1172, },
+  { 26, 1, 1, 0x000001d000000000ull, 0x000001fe00001000ull, { 23, 7, 26, 0, 0 }, 0x40, 1173, },
+  { 26, 1, 2, 0x000001d000000000ull, 0x000001fe00001000ull, { 23, 22, 26, 7, 0 }, 0x40, 1045, },
+  { 26, 1, 1, 0x000001d000000000ull, 0x000001fe00001000ull, { 23, 26, 7, 0, 0 }, 0x40, 1046, },
+  { 26, 1, 2, 0x000001ca00000000ull, 0x000001ee00001000ull, { 23, 22, 55, 26, 0 }, 0x40, 1365, },
+  { 27, 1, 2, 0x0000018400000000ull, 0x000001fe00001000ull, { 22, 23, 25, 26, 0 }, 0x0, 1217, },
+  { 27, 1, 1, 0x0000018400000000ull, 0x000001fe00001000ull, { 22, 25, 26, 0, 0 }, 0x40, 1218, },
+  { 27, 1, 2, 0x0000018400000000ull, 0x000001fe00001000ull, { 23, 22, 26, 25, 0 }, 0x0, 1176, },
+  { 27, 1, 1, 0x0000018400000000ull, 0x000001fe00001000ull, { 23, 26, 25, 0, 0 }, 0x40, 1177, },
+  { 27, 1, 2, 0x0000018400000000ull, 0x000001fe00001000ull, { 22, 23, 26, 25, 0 }, 0x0, 1085, },
+  { 27, 1, 1, 0x0000018400000000ull, 0x000001fe00001000ull, { 22, 26, 25, 0, 0 }, 0x40, 1086, },
+  { 27, 1, 2, 0x0000018400000000ull, 0x000001fe00001000ull, { 23, 22, 25, 26, 0 }, 0x0, 1047, },
+  { 27, 1, 1, 0x0000018400000000ull, 0x000001fe00001000ull, { 23, 25, 26, 0, 0 }, 0x40, 1048, },
+  { 27, 1, 2, 0x0000018600000000ull, 0x000001fe00001000ull, { 22, 23, 25, 26, 0 }, 0x40, 1370, },
+  { 27, 1, 2, 0x0000019400000000ull, 0x000001fe00001000ull, { 22, 23, 7, 26, 0 }, 0x0, 1087, },
+  { 27, 1, 1, 0x0000019400000000ull, 0x000001fe00001000ull, { 22, 7, 26, 0, 0 }, 0x40, 1088, },
+  { 27, 1, 2, 0x0000019400000000ull, 0x000001fe00001000ull, { 22, 23, 26, 7, 0 }, 0x40, 1221, },
+  { 27, 1, 1, 0x0000019400000000ull, 0x000001fe00001000ull, { 22, 26, 7, 0, 0 }, 0x40, 1222, },
+  { 27, 1, 2, 0x0000019400000000ull, 0x000001fe00001000ull, { 22, 23, 7, 26, 0 }, 0x40, 1182, },
+  { 27, 1, 2, 0x0000018c00000000ull, 0x000001ee00001000ull, { 22, 23, 55, 26, 0 }, 0x0, 1224, },
+  { 27, 1, 1, 0x0000018c00000000ull, 0x000001ee00001000ull, { 22, 55, 26, 0, 0 }, 0x40, 1225, },
+  { 27, 1, 2, 0x0000018c00000000ull, 0x000001ee00001000ull, { 22, 23, 57, 26, 0 }, 0x0, 1183, },
+  { 27, 1, 1, 0x0000018c00000000ull, 0x000001ee00001000ull, { 22, 57, 26, 0, 0 }, 0x40, 1184, },
+  { 27, 1, 2, 0x0000018c00000000ull, 0x000001ee00001000ull, { 23, 22, 57, 26, 0 }, 0x0, 1092, },
+  { 27, 1, 1, 0x0000018c00000000ull, 0x000001ee00001000ull, { 23, 57, 26, 0, 0 }, 0x40, 1093, },
+  { 27, 1, 2, 0x0000018c00000000ull, 0x000001ee00001000ull, { 23, 22, 55, 26, 0 }, 0x0, 1054, },
+  { 27, 1, 1, 0x0000018c00000000ull, 0x000001ee00001000ull, { 23, 55, 26, 0, 0 }, 0x40, 1055, },
+  { 27, 1, 2, 0x0000018e00000000ull, 0x000001ee00001000ull, { 22, 23, 55, 26, 0 }, 0x40, 1375, },
+  { 27, 1, 2, 0x000001ac00000000ull, 0x000001ee00001000ull, { 22, 23, 56, 26, 0 }, 0x0, 1241, },
+  { 27, 1, 1, 0x000001ac00000000ull, 0x000001ee00001000ull, { 22, 56, 26, 0, 0 }, 0x40, 1242, },
+  { 27, 1, 2, 0x000001ac00000000ull, 0x000001ee00001000ull, { 22, 23, 58, 26, 0 }, 0x0, 1200, },
+  { 27, 1, 1, 0x000001ac00000000ull, 0x000001ee00001000ull, { 22, 58, 26, 0, 0 }, 0x40, 1201, },
+  { 27, 1, 2, 0x000001ac00000000ull, 0x000001ee00001000ull, { 23, 22, 58, 26, 0 }, 0x0, 1111, },
+  { 27, 1, 1, 0x000001ac00000000ull, 0x000001ee00001000ull, { 23, 58, 26, 0, 0 }, 0x40, 1112, },
+  { 27, 1, 2, 0x000001ac00000000ull, 0x000001ee00001000ull, { 23, 22, 56, 26, 0 }, 0x0, 1070, },
+  { 27, 1, 1, 0x000001ac00000000ull, 0x000001ee00001000ull, { 23, 56, 26, 0, 0 }, 0x40, 1071, },
+  { 27, 1, 2, 0x000001c600000000ull, 0x000001fe00001000ull, { 23, 22, 25, 26, 0 }, 0x40, 1376, },
+  { 27, 1, 2, 0x000001d400000000ull, 0x000001fe00001000ull, { 23, 22, 7, 26, 0 }, 0x40, 1185, },
+  { 27, 1, 1, 0x000001d400000000ull, 0x000001fe00001000ull, { 23, 7, 26, 0, 0 }, 0x40, 1186, },
+  { 27, 1, 2, 0x000001d400000000ull, 0x000001fe00001000ull, { 23, 22, 26, 7, 0 }, 0x40, 1058, },
+  { 27, 1, 1, 0x000001d400000000ull, 0x000001fe00001000ull, { 23, 26, 7, 0, 0 }, 0x40, 1059, },
+  { 27, 1, 2, 0x000001ce00000000ull, 0x000001ee00001000ull, { 23, 22, 55, 26, 0 }, 0x40, 1377, },
+  { 28, 3, 1, 0x0000008808000000ull, 0x000001fff8000000ull, { 24, 33, 25, 1, 2 }, 0x0, 257, },
+  { 28, 3, 1, 0x0000008808000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x40, 258, },
+  { 29, 3, 1, 0x0000008008000000ull, 0x000001fff8000000ull, { 24, 33, 25, 2, 0 }, 0x0, 259, },
+  { 29, 3, 1, 0x0000008008000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x40, 260, },
+  { 30, 3, 1, 0x0000008048000000ull, 0x000001fff8000000ull, { 24, 33, 25, 2, 0 }, 0x0, 261, },
+  { 30, 3, 1, 0x0000008048000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x40, 262, },
+  { 31, 3, 1, 0x0000008088000000ull, 0x000001fff8000000ull, { 24, 33, 25, 2, 0 }, 0x0, 263, },
+  { 31, 3, 1, 0x0000008088000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x40, 264, },
+  { 32, 3, 1, 0x00000080c8000000ull, 0x000001fff8000000ull, { 24, 33, 25, 2, 0 }, 0x0, 265, },
+  { 32, 3, 1, 0x00000080c8000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x40, 266, },
+  { 34, 4, 0, 0x0000000010000000ull, 0x000001e1f8000000ull, { 0, 0, 0, 0, 0 }, 0x224, 19, },
+  { 36, 2, 1, 0x00000000c0000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x0, 1149, },
+  { 37, 2, 1, 0x00000000c8000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x0, 1150, },
+  { 39, 2, 1, 0x0000008000000000ull, 0x000001e000000000ull, { 24, 25, 26, 47, 72 }, 0x0, 20, },
+  { 39, 2, 1, 0x000000a600000000ull, 0x000001ee04000000ull, { 24, 25, 45, 73, 0 }, 0x0, 3000, },
+  { 39, 2, 1, 0x000000a604000000ull, 0x000001ee04000000ull, { 24, 55, 45, 73, 0 }, 0x0, 3001, },
+  { 39, 2, 1, 0x000000ae00000000ull, 0x000001ee00000000ull, { 24, 48, 26, 46, 73 }, 0x0, 21, },
+  { 43, 4, 0, 0x0000000080000000ull, 0x000001e1f8000000ull, { 0, 0, 0, 0, 0 }, 0x20, 22, },
+  { 48, 2, 1, 0x000000a400000000ull, 0x000001ee00002000ull, { 24, 26, 76, 73, 0 }, 0x0, 2836, },
+  { 50, 5, 1, 0x0000000080000000ull, 0x000001e3f80fe000ull, { 18, 20, 0, 0, 0 }, 0x40, 24, },
+  { 51, 5, 1, 0x0000010008000000ull, 0x000001fff8000000ull, { 18, 20, 19, 0, 0 }, 0x40, 2257, },
+  { 52, 5, 1, 0x00000000b8000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2258, },
+  { 52, 5, 1, 0x00000000b8000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x40, 26, },
+  { 53, 5, 1, 0x00000000b0000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2259, },
+  { 53, 5, 1, 0x00000000b0000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x40, 27, },
+  { 54, 5, 1, 0x0000000160000000ull, 0x000001e3f8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 28, },
+  { 55, 5, 1, 0x0000000168000000ull, 0x000001e3f8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 29, },
+  { 57, 3, 0, 0x0000002180000000ull, 0x000001fff8000000ull, { 26, 0, 0, 0, 0 }, 0x0, 30, },
+  { 58, 5, 0, 0x0000000040000000ull, 0x000001eff8000000ull, { 79, 0, 0, 0, 0 }, 0x0, 2260, },
+  { 58, 5, 0, 0x0000000040000000ull, 0x000001eff8000000ull, { 79, 0, 0, 0, 0 }, 0x40, 31, },
+  { 59, 5, 2, 0x000000a000000000ull, 0x000001e000001000ull, { 22, 23, 19, 60, 0 }, 0x0, 1247, },
+  { 59, 5, 1, 0x000000a000000000ull, 0x000001e000001000ull, { 22, 19, 60, 0, 0 }, 0x40, 1248, },
+  { 59, 5, 2, 0x000000a000000000ull, 0x000001e000001000ull, { 23, 22, 19, 60, 0 }, 0x40, 1402, },
+  { 59, 5, 1, 0x000000a000000000ull, 0x000001e000001000ull, { 23, 19, 60, 0, 0 }, 0x40, 1403, },
+  { 60, 5, 0, 0x0000000028000000ull, 0x000001eff8000000ull, { 0, 0, 0, 0, 0 }, 0x0, 2261, },
+  { 60, 5, 0, 0x0000000028000000ull, 0x000001eff8000000ull, { 0, 0, 0, 0, 0 }, 0x40, 32, },
+  { 61, 5, 2, 0x0000008000000000ull, 0x000001fe00001000ull, { 22, 23, 19, 20, 0 }, 0x0, 925, },
+  { 61, 5, 1, 0x0000008000000000ull, 0x000001fe00001000ull, { 22, 19, 20, 0, 0 }, 0x40, 926, },
+  { 61, 5, 2, 0x0000008000000000ull, 0x000001fe00001000ull, { 22, 23, 19, 20, 0 }, 0x40, 927, },
+  { 61, 5, 2, 0x0000009000000000ull, 0x000001fe00001000ull, { 22, 23, 20, 19, 0 }, 0x0, 1098, },
+  { 61, 5, 1, 0x0000009000000000ull, 0x000001fe00001000ull, { 22, 20, 19, 0, 0 }, 0x40, 1099, },
+  { 61, 5, 2, 0x0000009000000000ull, 0x000001fe00001000ull, { 22, 23, 20, 19, 0 }, 0x40, 1100, },
+  { 61, 5, 2, 0x0000008000000000ull, 0x000001fe00001000ull, { 23, 22, 19, 20, 0 }, 0x0, 1378, },
+  { 61, 5, 1, 0x0000008000000000ull, 0x000001fe00001000ull, { 23, 19, 20, 0, 0 }, 0x40, 1379, },
+  { 61, 5, 2, 0x0000008000000000ull, 0x000001fe00001000ull, { 23, 22, 19, 20, 0 }, 0x40, 1380, },
+  { 61, 5, 2, 0x0000009000000000ull, 0x000001fe00001000ull, { 23, 22, 20, 19, 0 }, 0x0, 1387, },
+  { 61, 5, 1, 0x0000009000000000ull, 0x000001fe00001000ull, { 23, 20, 19, 0, 0 }, 0x40, 1388, },
+  { 61, 5, 2, 0x0000009000000000ull, 0x000001fe00001000ull, { 23, 22, 20, 19, 0 }, 0x40, 1389, },
+  { 62, 5, 1, 0x00000000c0000000ull, 0x000001eff8000000ull, { 18, 19, 0, 0, 0 }, 0x0, 1024, },
+  { 62, 5, 1, 0x00000000c0000000ull, 0x000001eff8000000ull, { 18, 19, 0, 0, 0 }, 0x40, 1025, },
+  { 62, 5, 1, 0x00000000e0000000ull, 0x000001e3f8000000ull, { 18, 19, 0, 0, 0 }, 0x0, 2998, },
+  { 62, 5, 1, 0x0000010008000000ull, 0x000001fff80fe000ull, { 18, 20, 0, 0, 0 }, 0x40, 2999, },
+  { 63, 3, 1, 0x0000008488000000ull, 0x000001fff8000000ull, { 24, 33, 71, 0, 0 }, 0x0, 267, },
+  { 64, 3, 1, 0x00000084c8000000ull, 0x000001fff8000000ull, { 24, 33, 71, 0, 0 }, 0x0, 268, },
+  { 67, 3, 0, 0x0000000060000000ull, 0x000001eff8000000ull, { 0, 0, 0, 0, 0 }, 0x21, 33, },
+  { 68, 5, 1, 0x0000010000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x0, 2319, },
+  { 68, 5, 1, 0x0000010000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x40, 34, },
+  { 69, 5, 1, 0x00000000a8000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2320, },
+  { 69, 5, 1, 0x00000000a8000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x40, 35, },
+  { 70, 5, 1, 0x0000000080000000ull, 0x000001e3f8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2213, },
+  { 71, 5, 1, 0x00000000a0000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2321, },
+  { 71, 5, 1, 0x00000000a0000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x40, 36, },
+  { 72, 5, 1, 0x00000001c8000000ull, 0x000001e3f8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 1203, },
+  { 73, 5, 1, 0x0000010000000000ull, 0x000001fc000fe000ull, { 18, 20, 21, 0, 0 }, 0x40, 2324, },
+  { 74, 5, 1, 0x0000014000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x0, 2327, },
+  { 74, 5, 1, 0x0000014000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x40, 38, },
+  { 75, 5, 1, 0x0000000088000000ull, 0x000001e3f8000000ull, { 18, 20, 0, 0, 0 }, 0xc0, 39, },
+  { 76, 5, 1, 0x0000000088000000ull, 0x000001e3f80fe000ull, { 18, 20, 0, 0, 0 }, 0x40, 40, },
+  { 77, 5, 1, 0x0000018000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x0, 2330, },
+  { 77, 5, 1, 0x0000018000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x40, 41, },
+  { 78, 5, 1, 0x0000018000000000ull, 0x000001fc000fe000ull, { 18, 20, 21, 0, 0 }, 0x40, 2333, },
+  { 79, 5, 1, 0x0000010008000000ull, 0x000001fff80fe000ull, { 18, 20, 0, 0, 0 }, 0x40, 2336, },
+  { 80, 5, 1, 0x0000000170000000ull, 0x000001e3f8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 44, },
+  { 81, 5, 1, 0x0000002080000000ull, 0x000001e3f80fe000ull, { 18, 20, 0, 0, 0 }, 0x40, 45, },
+  { 82, 5, 1, 0x0000000140000000ull, 0x000001e3f8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 46, },
+  { 83, 5, 1, 0x00000020b8000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2337, },
+  { 83, 5, 1, 0x00000020b8000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x40, 47, },
+  { 84, 5, 1, 0x00000020b0000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2338, },
+  { 84, 5, 1, 0x00000020b0000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x40, 48, },
+  { 85, 5, 1, 0x0000002180000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 928, },
+  { 85, 5, 1, 0x0000002180000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x40, 929, },
+  { 85, 5, 1, 0x0000002188000000ull, 0x000001eff8000000ull, { 18, 20, 19, 0, 0 }, 0x40, 1101, },
+  { 86, 5, 1, 0x00000020c0000000ull, 0x000001eff8000000ull, { 18, 19, 0, 0, 0 }, 0x0, 1026, },
+  { 86, 5, 1, 0x00000020c0000000ull, 0x000001eff8000000ull, { 18, 19, 0, 0, 0 }, 0x40, 1027, },
+  { 87, 5, 1, 0x0000013000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x0, 2355, },
+  { 87, 5, 1, 0x0000013000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x40, 49, },
+  { 88, 5, 1, 0x00000020a8000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2356, },
+  { 88, 5, 1, 0x00000020a8000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x40, 50, },
+  { 89, 5, 1, 0x0000002080000000ull, 0x000001e3f8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2221, },
+  { 90, 5, 1, 0x00000020a0000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2357, },
+  { 90, 5, 1, 0x00000020a0000000ull, 0x000001eff8000000ull, { 18, 19, 20, 0, 0 }, 0x40, 51, },
+  { 91, 5, 1, 0x0000013000000000ull, 0x000001fc000fe000ull, { 18, 20, 21, 0, 0 }, 0x40, 2358, },
+  { 92, 5, 1, 0x0000017000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x0, 2359, },
+  { 92, 5, 1, 0x0000017000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x40, 53, },
+  { 93, 5, 1, 0x0000002088000000ull, 0x000001e3f8000000ull, { 18, 20, 0, 0, 0 }, 0xc0, 54, },
+  { 94, 5, 1, 0x0000002088000000ull, 0x000001e3f80fe000ull, { 18, 20, 0, 0, 0 }, 0x40, 55, },
+  { 95, 5, 1, 0x000001b000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x0, 2360, },
+  { 95, 5, 1, 0x000001b000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x40, 56, },
+  { 96, 5, 1, 0x000001b000000000ull, 0x000001fc000fe000ull, { 18, 20, 21, 0, 0 }, 0x40, 2361, },
+  { 97, 5, 2, 0x0000002200000000ull, 0x000001fe00000000ull, { 18, 23, 19, 20, 0 }, 0x0, 2362, },
+  { 97, 5, 2, 0x0000002200000000ull, 0x000001fe00000000ull, { 18, 23, 19, 20, 0 }, 0x40, 58, },
+  { 98, 5, 2, 0x0000003200000000ull, 0x000001fe00000000ull, { 18, 23, 20, 0, 0 }, 0x0, 2363, },
+  { 98, 5, 2, 0x0000003200000000ull, 0x000001fe00000000ull, { 18, 23, 20, 0, 0 }, 0x40, 59, },
+  { 99, 5, 2, 0x0000000200000000ull, 0x000001fe00000000ull, { 18, 23, 19, 20, 0 }, 0x0, 2364, },
+  { 99, 5, 2, 0x0000000200000000ull, 0x000001fe00000000ull, { 18, 23, 19, 20, 0 }, 0x40, 60, },
+  { 100, 5, 2, 0x0000001200000000ull, 0x000001fe00000000ull, { 18, 23, 20, 0, 0 }, 0x0, 2365, },
+  { 100, 5, 2, 0x0000001200000000ull, 0x000001fe00000000ull, { 18, 23, 20, 0, 0 }, 0x40, 61, },
+  { 101, 5, 1, 0x000001c000000000ull, 0x000001f000000000ull, { 18, 20, 21, 19, 0 }, 0x0, 62, },
+  { 102, 5, 0, 0x0000000020000000ull, 0x000001eff8000000ull, { 50, 51, 0, 0, 0 }, 0x0, 2366, },
+  { 102, 5, 0, 0x0000000020000000ull, 0x000001eff8000000ull, { 50, 51, 0, 0, 0 }, 0x40, 63, },
+  { 103, 5, 1, 0x0000014008000000ull, 0x000001fff8000000ull, { 18, 20, 19, 0, 0 }, 0x40, 2369, },
+  { 104, 5, 1, 0x00000001a0000000ull, 0x000001e3f8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 65, },
+  { 105, 5, 1, 0x00000001e0000000ull, 0x000001e3f8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 2168, },
+  { 106, 3, 0, 0x0000000100000000ull, 0x000001eff8000000ull, { 0, 0, 0, 0, 0 }, 0x0, 66, },
+  { 108, 5, 1, 0x0000000178000000ull, 0x000001e3f8000000ull, { 18, 19, 20, 0, 0 }, 0x0, 67, },
+  { 113, 3, 1, 0x0000008708000000ull, 0x000001ffc8000000ull, { 24, 19, 0, 0, 0 }, 0x0, 2747, },
+  { 118, 4, 0, 0x0000004008000000ull, 0x000001e1f8000000ull, { 65, 0, 0, 0, 0 }, 0x0, 520, },
+  { 118, 5, 0, 0x000000000c000000ull, 0x000001e3fc000000ull, { 65, 0, 0, 0, 0 }, 0x0, 943, },
+  { 118, 2, 0, 0x000000000c000000ull, 0x000001effc000000ull, { 65, 0, 0, 0, 0 }, 0x2, 1123, },
+  { 118, 3, 0, 0x000000000c000000ull, 0x000001effc000000ull, { 65, 0, 0, 0, 0 }, 0x0, 1249, },
+  { 118, 6, 0, 0x000000000c000000ull, 0x000001effc000000ull, { 69, 0, 0, 0, 0 }, 0x0, 2996, },
+  { 118, 7, 0, 0x0000000000000000ull, 0x0000000000000000ull, { 65, 0, 0, 0, 0 }, 0x0, 68, },
+  { 123, 3, 0, 0x0000000080000000ull, 0x000001eff8000000ull, { 0, 0, 0, 0, 0 }, 0x0, 69, },
+  { 123, 3, 0, 0x0000000090000000ull, 0x000001eff8000000ull, { 24, 0, 0, 0, 0 }, 0x0, 902, },
+  { 123, 3, 0, 0x0000000098000000ull, 0x000001eff8000000ull, { 18, 0, 0, 0, 0 }, 0x0, 903, },
+  { 124, 3, 0, 0x0000002170000000ull, 0x000001eff8000000ull, { 25, 0, 0, 0, 0 }, 0xc, 828, },
+  { 125, 3, 1, 0x0000002070000000ull, 0x000001eff8000000ull, { 30, 25, 0, 0, 0 }, 0x8, 829, },
+  { 125, 3, 1, 0x0000002078000000ull, 0x000001eff8000000ull, { 31, 25, 0, 0, 0 }, 0x8, 1125, },
+  { 127, 3, 1, 0x0000008000000000ull, 0x000001fff8000000ull, { 24, 33, 0, 0, 0 }, 0x0, 70, },
+  { 127, 3, 1, 0x0000009000000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x400, 71, },
+  { 127, 3, 1, 0x000000a000000000ull, 0x000001eff0000000ull, { 24, 33, 62, 0, 0 }, 0x400, 72, },
+  { 128, 3, 2, 0x0000008a08000000ull, 0x000001fff8000000ull, { 24, 1, 33, 0, 0 }, 0x0, 73, },
+  { 128, 3, 1, 0x0000008a08000000ull, 0x000001fff8000000ull, { 24, 33, 0, 0, 0 }, 0x40, 74, },
+  { 129, 3, 1, 0x0000008040000000ull, 0x000001fff8000000ull, { 24, 33, 0, 0, 0 }, 0x0, 75, },
+  { 129, 3, 1, 0x0000009040000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x400, 76, },
+  { 129, 3, 1, 0x000000a040000000ull, 0x000001eff0000000ull, { 24, 33, 62, 0, 0 }, 0x400, 77, },
+  { 130, 3, 1, 0x0000008080000000ull, 0x000001fff8000000ull, { 24, 33, 0, 0, 0 }, 0x0, 78, },
+  { 130, 3, 1, 0x0000009080000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x400, 79, },
+  { 130, 3, 1, 0x000000a080000000ull, 0x000001eff0000000ull, { 24, 33, 62, 0, 0 }, 0x400, 80, },
+  { 131, 3, 1, 0x00000080c0000000ull, 0x000001fff8000000ull, { 24, 33, 0, 0, 0 }, 0x0, 81, },
+  { 131, 3, 1, 0x00000080c0000000ull, 0x000001fff8000000ull, { 24, 33, 83, 0, 0 }, 0x0, 1321, },
+  { 131, 3, 1, 0x00000090c0000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x400, 82, },
+  { 131, 3, 1, 0x000000a0c0000000ull, 0x000001eff0000000ull, { 24, 33, 62, 0, 0 }, 0x400, 83, },
+  { 132, 3, 1, 0x000000c6c0000000ull, 0x000001fff8000000ull, { 18, 33, 0, 0, 0 }, 0x0, 1021, },
+  { 132, 3, 1, 0x000000d6c0000000ull, 0x000001fff8000000ull, { 18, 33, 25, 0, 0 }, 0x400, 1022, },
+  { 132, 3, 1, 0x000000e6c0000000ull, 0x000001eff0000000ull, { 18, 33, 62, 0, 0 }, 0x400, 1023, },
+  { 133, 3, 1, 0x000000c040000000ull, 0x000001fff8000000ull, { 18, 33, 0, 0, 0 }, 0x0, 84, },
+  { 133, 3, 1, 0x000000d040000000ull, 0x000001fff8000000ull, { 18, 33, 25, 0, 0 }, 0x400, 85, },
+  { 133, 3, 1, 0x000000e040000000ull, 0x000001eff0000000ull, { 18, 33, 62, 0, 0 }, 0x400, 86, },
+  { 134, 3, 1, 0x000000c0c0000000ull, 0x000001fff8000000ull, { 18, 33, 0, 0, 0 }, 0x0, 87, },
+  { 134, 3, 1, 0x000000d0c0000000ull, 0x000001fff8000000ull, { 18, 33, 25, 0, 0 }, 0x400, 88, },
+  { 134, 3, 1, 0x000000e0c0000000ull, 0x000001eff0000000ull, { 18, 33, 62, 0, 0 }, 0x400, 89, },
+  { 135, 3, 1, 0x000000c000000000ull, 0x000001fff8000000ull, { 18, 33, 0, 0, 0 }, 0x0, 90, },
+  { 135, 3, 1, 0x000000d000000000ull, 0x000001fff8000000ull, { 18, 33, 25, 0, 0 }, 0x400, 91, },
+  { 135, 3, 1, 0x000000e000000000ull, 0x000001eff0000000ull, { 18, 33, 62, 0, 0 }, 0x400, 92, },
+  { 136, 3, 2, 0x000000c048000000ull, 0x000001fff8000000ull, { 18, 19, 33, 0, 0 }, 0x0, 93, },
+  { 136, 3, 2, 0x000000d048000000ull, 0x000001fff8000000ull, { 18, 19, 33, 6, 0 }, 0x400, 94, },
+  { 137, 3, 2, 0x000000c0c8000000ull, 0x000001fff8000000ull, { 18, 19, 33, 0, 0 }, 0x0, 95, },
+  { 137, 3, 2, 0x000000d0c8000000ull, 0x000001fff8000000ull, { 18, 19, 33, 6, 0 }, 0x400, 96, },
+  { 138, 3, 2, 0x000000c088000000ull, 0x000001fff8000000ull, { 18, 19, 33, 0, 0 }, 0x0, 97, },
+  { 138, 3, 2, 0x000000d088000000ull, 0x000001fff8000000ull, { 18, 19, 33, 5, 0 }, 0x400, 98, },
+  { 139, 3, 1, 0x000000c080000000ull, 0x000001fff8000000ull, { 18, 33, 0, 0, 0 }, 0x0, 99, },
+  { 139, 3, 1, 0x000000d080000000ull, 0x000001fff8000000ull, { 18, 33, 25, 0, 0 }, 0x400, 100, },
+  { 139, 3, 1, 0x000000e080000000ull, 0x000001eff0000000ull, { 18, 33, 62, 0, 0 }, 0x400, 101, },
+  { 142, 3, 0, 0x000000cb00000000ull, 0x000001fff8000000ull, { 33, 0, 0, 0, 0 }, 0x0, 102, },
+  { 142, 3, 0, 0x000000db00000000ull, 0x000001fff8000000ull, { 33, 25, 0, 0, 0 }, 0x400, 103, },
+  { 142, 3, 0, 0x000000eb00000000ull, 0x000001eff0000000ull, { 33, 62, 0, 0, 0 }, 0x400, 104, },
+  { 143, 3, 0, 0x0000000050000000ull, 0x000001eff8000000ull, { 0, 0, 0, 0, 0 }, 0x21, 105, },
+  { 151, 3, 0, 0x0000000110000000ull, 0x000001eff8000000ull, { 0, 0, 0, 0, 0 }, 0x0, 106, },
+  { 152, 2, 1, 0x000000e880000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 2169, },
+  { 153, 2, 1, 0x000000ea80000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 2170, },
+  { 154, 2, 1, 0x000000f880000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 2171, },
+  { 155, 1, 1, 0x0000010800000000ull, 0x000001fff80fe000ull, { 24, 26, 0, 0, 0 }, 0x0, 107, },
+  { 155, 1, 1, 0x0000012000000000ull, 0x000001e000300000ull, { 24, 66, 0, 0, 0 }, 0x40, 108, },
+  { 155, 5, 1, 0x0000000080000000ull, 0x000001e3f8000000ull, { 18, 20, 0, 0, 0 }, 0xc0, 109, },
+  { 155, 2, 1, 0x0000000e00100000ull, 0x000001ee00f00000ull, { 15, 25, 0, 0, 0 }, 0x40, 110, },
+  { 155, 2, 1, 0x0000000e00000000ull, 0x000001ee00f00000ull, { 15, 25, 78, 0, 0 }, 0x0, 2821, },
+  { 155, 2, 1, 0x0000000188000000ull, 0x000001eff8000000ull, { 24, 16, 0, 0, 0 }, 0x0, 112, },
+  { 155, 2, 1, 0x0000000600000000ull, 0x000001ee00000000ull, { 9, 25, 64, 0, 0 }, 0x0, 113, },
+  { 155, 2, 1, 0x00000016ff001fc0ull, 0x000001feff001fc0ull, { 9, 25, 0, 0, 0 }, 0x40, 114, },
+  { 155, 2, 1, 0x0000000400000000ull, 0x000001ee00000000ull, { 10, 68, 0, 0, 0 }, 0x0, 115, },
+  { 155, 2, 1, 0x0000000180000000ull, 0x000001eff8000000ull, { 24, 8, 0, 0, 0 }, 0x0, 116, },
+  { 155, 2, 1, 0x0000000198000000ull, 0x000001eff8000000ull, { 24, 9, 0, 0, 0 }, 0x0, 117, },
+  { 155, 2, 1, 0x0000000150000000ull, 0x000001eff8000000ull, { 14, 25, 0, 0, 0 }, 0x0, 1126, },
+  { 155, 2, 1, 0x0000000050000000ull, 0x000001eff8000000ull, { 14, 55, 0, 0, 0 }, 0x0, 1127, },
+  { 155, 2, 1, 0x0000000190000000ull, 0x000001eff8000000ull, { 24, 14, 0, 0, 0 }, 0x0, 1128, },
+  { 155, 3, 1, 0x0000000140000000ull, 0x000001eff8000000ull, { 14, 55, 0, 0, 0 }, 0x0, 1250, },
+  { 155, 3, 1, 0x0000002150000000ull, 0x000001eff8000000ull, { 14, 25, 0, 0, 0 }, 0x0, 1251, },
+  { 155, 3, 1, 0x0000002110000000ull, 0x000001eff8000000ull, { 24, 14, 0, 0, 0 }, 0x0, 1252, },
+  { 155, 3, 1, 0x0000002160000000ull, 0x000001eff8000000ull, { 17, 25, 0, 0, 0 }, 0x8, 118, },
+  { 155, 3, 1, 0x0000002120000000ull, 0x000001eff8000000ull, { 24, 17, 0, 0, 0 }, 0x8, 119, },
+  { 155, 3, 1, 0x0000002168000000ull, 0x000001eff8000000ull, { 12, 25, 0, 0, 0 }, 0x8, 120, },
+  { 155, 3, 1, 0x0000002148000000ull, 0x000001eff8000000ull, { 13, 25, 0, 0, 0 }, 0x0, 121, },
+  { 155, 3, 1, 0x0000002128000000ull, 0x000001eff8000000ull, { 24, 11, 0, 0, 0 }, 0x8, 122, },
+  { 155, 3, 1, 0x0000002108000000ull, 0x000001eff8000000ull, { 24, 13, 0, 0, 0 }, 0x0, 123, },
+  { 155, 3, 1, 0x0000002000000000ull, 0x000001eff8000000ull, { 38, 25, 0, 0, 0 }, 0x8, 124, },
+  { 155, 3, 1, 0x0000002008000000ull, 0x000001eff8000000ull, { 29, 25, 0, 0, 0 }, 0x8, 125, },
+  { 155, 3, 1, 0x0000002010000000ull, 0x000001eff8000000ull, { 32, 25, 0, 0, 0 }, 0x8, 126, },
+  { 155, 3, 1, 0x0000002018000000ull, 0x000001eff8000000ull, { 35, 25, 0, 0, 0 }, 0x8, 127, },
+  { 155, 3, 1, 0x0000002020000000ull, 0x000001eff8000000ull, { 36, 25, 0, 0, 0 }, 0x8, 128, },
+  { 155, 3, 1, 0x0000002028000000ull, 0x000001eff8000000ull, { 37, 25, 0, 0, 0 }, 0x8, 129, },
+  { 155, 3, 1, 0x0000002030000000ull, 0x000001eff8000000ull, { 34, 25, 0, 0, 0 }, 0x8, 130, },
+  { 155, 3, 1, 0x0000002080000000ull, 0x000001eff8000000ull, { 24, 38, 0, 0, 0 }, 0x8, 131, },
+  { 155, 3, 1, 0x0000002088000000ull, 0x000001eff8000000ull, { 24, 29, 0, 0, 0 }, 0x8, 132, },
+  { 155, 3, 1, 0x0000002090000000ull, 0x000001eff8000000ull, { 24, 32, 0, 0, 0 }, 0x8, 133, },
+  { 155, 3, 1, 0x0000002098000000ull, 0x000001eff8000000ull, { 24, 35, 0, 0, 0 }, 0x8, 134, },
+  { 155, 3, 1, 0x00000020a0000000ull, 0x000001eff8000000ull, { 24, 36, 0, 0, 0 }, 0x8, 135, },
+  { 155, 3, 1, 0x00000020a8000000ull, 0x000001eff8000000ull, { 24, 37, 0, 0, 0 }, 0x0, 136, },
+  { 155, 3, 1, 0x00000020b0000000ull, 0x000001eff8000000ull, { 24, 34, 0, 0, 0 }, 0x8, 137, },
+  { 155, 3, 1, 0x00000020b8000000ull, 0x000001eff8000000ull, { 24, 28, 0, 0, 0 }, 0x0, 138, },
+  { 155, 7, 1, 0x0000000000000000ull, 0x0000000000000000ull, { 24, 14, 0, 0, 0 }, 0x0, 139, },
+  { 155, 7, 1, 0x0000000000000000ull, 0x0000000000000000ull, { 14, 55, 0, 0, 0 }, 0x0, 140, },
+  { 155, 7, 1, 0x0000000000000000ull, 0x0000000000000000ull, { 14, 25, 0, 0, 0 }, 0x0, 141, },
+  { 156, 6, 1, 0x000000c000000000ull, 0x000001e000100000ull, { 24, 70, 0, 0, 0 }, 0x0, 142, },
+  { 157, 2, 1, 0x000000eca0000000ull, 0x000001fff0000000ull, { 24, 25, 74, 0, 0 }, 0x0, 143, },
+  { 158, 2, 1, 0x000000eea0000000ull, 0x000001fff0000000ull, { 24, 25, 75, 0, 0 }, 0x0, 144, },
+  { 168, 4, 0, 0x0000004000000000ull, 0x000001e1f8000000ull, { 65, 0, 0, 0, 0 }, 0x0, 521, },
+  { 168, 5, 0, 0x0000000008000000ull, 0x000001e3fc000000ull, { 65, 0, 0, 0, 0 }, 0x0, 944, },
+  { 168, 2, 0, 0x0000000008000000ull, 0x000001effc000000ull, { 65, 0, 0, 0, 0 }, 0x2, 1129, },
+  { 168, 3, 0, 0x0000000008000000ull, 0x000001effc000000ull, { 65, 0, 0, 0, 0 }, 0x0, 1253, },
+  { 168, 6, 0, 0x0000000008000000ull, 0x000001effc000000ull, { 69, 0, 0, 0, 0 }, 0x0, 2997, },
+  { 168, 7, 0, 0x0000000000000000ull, 0x0000000000000000ull, { 65, 0, 0, 0, 0 }, 0x0, 145, },
+  { 175, 1, 1, 0x0000010070000000ull, 0x000001eff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 146, },
+  { 175, 1, 1, 0x0000010170000000ull, 0x000001eff8000000ull, { 24, 55, 26, 0, 0 }, 0x0, 147, },
+  { 178, 2, 1, 0x000000ea00000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 2979, },
+  { 179, 2, 1, 0x000000f820000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 2823, },
+  { 180, 1, 1, 0x0000010400000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 148, },
+  { 181, 1, 1, 0x0000010600000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 149, },
+  { 182, 1, 1, 0x0000011400000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 150, },
+  { 183, 1, 1, 0x0000010450000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 151, },
+  { 184, 1, 1, 0x0000010650000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 152, },
+  { 185, 1, 1, 0x0000010470000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 153, },
+  { 186, 1, 1, 0x0000010670000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 154, },
+  { 187, 1, 1, 0x0000010520000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 930, },
+  { 188, 1, 1, 0x0000010720000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 931, },
+  { 189, 1, 1, 0x0000011520000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 932, },
+  { 190, 2, 1, 0x000000e850000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 2837, },
+  { 191, 2, 1, 0x000000ea70000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 155, },
+  { 192, 2, 1, 0x000000e810000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 2838, },
+  { 193, 2, 1, 0x000000ea30000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 156, },
+  { 194, 2, 1, 0x000000ead0000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 2172, },
+  { 195, 2, 1, 0x000000e230000000ull, 0x000001ff30000000ull, { 24, 25, 26, 42, 0 }, 0x0, 157, },
+  { 196, 2, 1, 0x000000e690000000ull, 0x000001fff0000000ull, { 24, 26, 0, 0, 0 }, 0x0, 158, },
+  { 198, 3, 1, 0x00000021c0000000ull, 0x000001eff8000000ull, { 24, 26, 25, 0, 0 }, 0x0, 2173, },
+  { 198, 3, 1, 0x00000020c0000000ull, 0x000001eff8000000ull, { 24, 26, 49, 0, 0 }, 0x0, 2174, },
+  { 198, 3, 0, 0x0000002188000000ull, 0x000001eff8000000ull, { 26, 49, 0, 0, 0 }, 0x0, 2204, },
+  { 199, 2, 1, 0x000000e8b0000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 159, },
+  { 200, 2, 1, 0x000000e240000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 160, },
+  { 200, 2, 1, 0x000000ee50000000ull, 0x000001fff0000000ull, { 24, 25, 39, 0, 0 }, 0x0, 161, },
+  { 201, 2, 1, 0x000000f040000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 162, },
+  { 201, 2, 1, 0x000000fc50000000ull, 0x000001fff0000000ull, { 24, 25, 39, 0, 0 }, 0x0, 163, },
+  { 202, 1, 1, 0x0000010680000000ull, 0x000001ffe0000000ull, { 24, 25, 41, 26, 0 }, 0x0, 164, },
+  { 203, 2, 1, 0x000000e220000000ull, 0x000001fff0000000ull, { 24, 26, 25, 0, 0 }, 0x0, 165, },
+  { 203, 2, 1, 0x000000e630000000ull, 0x000001fff0000000ull, { 24, 26, 43, 0, 0 }, 0x0, 166, },
+  { 204, 2, 1, 0x000000f020000000ull, 0x000001fff0000000ull, { 24, 26, 25, 0, 0 }, 0x0, 167, },
+  { 204, 2, 1, 0x000000f430000000ull, 0x000001fff0000000ull, { 24, 26, 43, 0, 0 }, 0x0, 168, },
+  { 205, 1, 1, 0x00000106c0000000ull, 0x000001ffe0000000ull, { 24, 25, 41, 26, 0 }, 0x0, 169, },
+  { 206, 1, 1, 0x0000010420000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 170, },
+  { 207, 1, 1, 0x0000010620000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 171, },
+  { 208, 1, 1, 0x0000011420000000ull, 0x000001fff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 172, },
+  { 209, 3, 0, 0x0000002048000000ull, 0x000001eff8000000ull, { 26, 25, 0, 0, 0 }, 0x8, 1157, },
+  { 209, 3, 0, 0x0000002050000000ull, 0x000001eff8000000ull, { 26, 25, 0, 0, 0 }, 0xc, 1032, },
+  { 209, 3, 0, 0x00000021a0000000ull, 0x000001eff8000000ull, { 26, 0, 0, 0, 0 }, 0x8, 904, },
+  { 210, 3, 0, 0x0000002060000000ull, 0x000001eff8000000ull, { 26, 25, 0, 0, 0 }, 0x8, 830, },
+  { 215, 4, 0, 0x0000000040000000ull, 0x000001e1f8000000ull, { 0, 0, 0, 0, 0 }, 0x22c, 173, },
+  { 216, 3, 0, 0x0000000038000000ull, 0x000001ee78000000ull, { 67, 0, 0, 0, 0 }, 0x8, 174, },
+  { 217, 3, 0, 0x0000000028000000ull, 0x000001ee78000000ull, { 67, 0, 0, 0, 0 }, 0x0, 175, },
+  { 226, 3, 1, 0x000000c708000000ull, 0x000001ffc8000000ull, { 18, 25, 0, 0, 0 }, 0x0, 2748, },
+  { 227, 2, 1, 0x000000a600000000ull, 0x000001ee04000000ull, { 24, 25, 45, 0, 0 }, 0x140, 176, },
+  { 227, 2, 1, 0x000000f240000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 177, },
+  { 228, 1, 1, 0x0000010080000000ull, 0x000001efe0000000ull, { 24, 25, 40, 26, 0 }, 0x0, 178, },
+  { 229, 1, 1, 0x00000100c0000000ull, 0x000001efe0000000ull, { 24, 25, 40, 26, 0 }, 0x0, 179, },
+  { 230, 2, 1, 0x000000a400000000ull, 0x000001ee00002000ull, { 24, 26, 76, 0, 0 }, 0x140, 2844, },
+  { 230, 2, 1, 0x000000f220000000ull, 0x000001fff0000000ull, { 24, 26, 25, 0, 0 }, 0x0, 181, },
+  { 231, 2, 1, 0x000000ac00000000ull, 0x000001ee00000000ull, { 24, 25, 26, 44, 0 }, 0x0, 182, },
+  { 236, 3, 0, 0x0000000180000000ull, 0x000001eff8000000ull, { 0, 0, 0, 0, 0 }, 0x0, 832, },
+  { 237, 3, 0, 0x0000000030000000ull, 0x000001ee78000000ull, { 67, 0, 0, 0, 0 }, 0x8, 183, },
+  { 239, 3, 1, 0x0000008c00000000ull, 0x000001fff8000000ull, { 33, 25, 0, 0, 0 }, 0x0, 184, },
+  { 239, 3, 1, 0x000000ac00000000ull, 0x000001eff0000000ull, { 33, 25, 61, 0, 0 }, 0x400, 185, },
+  { 240, 3, 1, 0x0000008c08000000ull, 0x000001fff8000000ull, { 33, 25, 1, 0, 0 }, 0x0, 186, },
+  { 240, 3, 1, 0x0000008c08000000ull, 0x000001fff8000000ull, { 33, 25, 0, 0, 0 }, 0x40, 187, },
+  { 241, 3, 1, 0x0000008c40000000ull, 0x000001fff8000000ull, { 33, 25, 0, 0, 0 }, 0x0, 188, },
+  { 241, 3, 1, 0x000000ac40000000ull, 0x000001eff0000000ull, { 33, 25, 61, 0, 0 }, 0x400, 189, },
+  { 242, 3, 1, 0x0000008c80000000ull, 0x000001fff8000000ull, { 33, 25, 0, 0, 0 }, 0x0, 190, },
+  { 242, 3, 1, 0x000000ac80000000ull, 0x000001eff0000000ull, { 33, 25, 61, 0, 0 }, 0x400, 191, },
+  { 243, 3, 1, 0x0000008cc0000000ull, 0x000001fff8000000ull, { 33, 25, 0, 0, 0 }, 0x0, 192, },
+  { 243, 3, 1, 0x000000acc0000000ull, 0x000001eff0000000ull, { 33, 25, 61, 0, 0 }, 0x400, 193, },
+  { 244, 3, 1, 0x000000cec0000000ull, 0x000001fff8000000ull, { 33, 19, 0, 0, 0 }, 0x0, 2751, },
+  { 244, 3, 1, 0x000000eec0000000ull, 0x000001eff0000000ull, { 33, 19, 61, 0, 0 }, 0x400, 2752, },
+  { 245, 3, 1, 0x000000cc40000000ull, 0x000001fff8000000ull, { 33, 19, 0, 0, 0 }, 0x0, 194, },
+  { 245, 3, 1, 0x000000ec40000000ull, 0x000001eff0000000ull, { 33, 19, 61, 0, 0 }, 0x400, 195, },
+  { 246, 3, 1, 0x000000ccc0000000ull, 0x000001fff8000000ull, { 33, 19, 0, 0, 0 }, 0x0, 196, },
+  { 246, 3, 1, 0x000000ecc0000000ull, 0x000001eff0000000ull, { 33, 19, 61, 0, 0 }, 0x400, 197, },
+  { 247, 3, 1, 0x000000cc00000000ull, 0x000001fff8000000ull, { 33, 19, 0, 0, 0 }, 0x0, 198, },
+  { 247, 3, 1, 0x000000ec00000000ull, 0x000001eff0000000ull, { 33, 19, 61, 0, 0 }, 0x400, 199, },
+  { 248, 3, 1, 0x000000cc80000000ull, 0x000001fff8000000ull, { 33, 19, 0, 0, 0 }, 0x0, 200, },
+  { 248, 3, 1, 0x000000ec80000000ull, 0x000001eff0000000ull, { 33, 19, 61, 0, 0 }, 0x400, 201, },
+  { 249, 1, 1, 0x0000010028000000ull, 0x000001eff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 202, },
+  { 249, 1, 1, 0x0000010020000000ull, 0x000001eff8000000ull, { 24, 25, 26, 4, 0 }, 0x0, 203, },
+  { 249, 1, 1, 0x0000010128000000ull, 0x000001eff8000000ull, { 24, 55, 26, 0, 0 }, 0x0, 204, },
+  { 250, 3, 0, 0x0000000020000000ull, 0x000001ee78000000ull, { 67, 0, 0, 0, 0 }, 0x0, 205, },
+  { 251, 2, 1, 0x00000000a0000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x0, 206, },
+  { 252, 2, 1, 0x00000000a8000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x0, 207, },
+  { 253, 2, 1, 0x00000000b0000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x0, 208, },
+  { 254, 3, 0, 0x0000000198000000ull, 0x000001eff8000000ull, { 0, 0, 0, 0, 0 }, 0x0, 1132, },
+  { 255, 3, 1, 0x00000020f8000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x8, 209, },
+  { 256, 2, 2, 0x000000a000000000ull, 0x000001fe00003000ull, { 22, 23, 26, 76, 0 }, 0x0, 3002, },
+  { 256, 2, 1, 0x000000a000000000ull, 0x000001fe00003000ull, { 22, 26, 76, 0, 0 }, 0x40, 3003, },
+  { 256, 2, 2, 0x000000a000000000ull, 0x000001fe00003000ull, { 23, 22, 26, 76, 0 }, 0x40, 1985, },
+  { 256, 2, 1, 0x000000a000000000ull, 0x000001fe00003000ull, { 23, 26, 76, 0, 0 }, 0x40, 1986, },
+  { 257, 3, 1, 0x00000020d0000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x0, 210, },
+  { 258, 2, 2, 0x000000a000002000ull, 0x000001fe00003000ull, { 22, 23, 26, 0, 0 }, 0x0, 3006, },
+  { 258, 2, 1, 0x000000a000002000ull, 0x000001fe00003000ull, { 22, 26, 0, 0, 0 }, 0x40, 3007, },
+  { 258, 2, 2, 0x000000a000002000ull, 0x000001fe00003000ull, { 23, 22, 26, 0, 0 }, 0x40, 1989, },
+  { 258, 2, 1, 0x000000a000002000ull, 0x000001fe00003000ull, { 23, 26, 0, 0, 0 }, 0x40, 1990, },
+  { 259, 3, 1, 0x00000020f0000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x8, 211, },
+  { 261, 3, 1, 0x00000020d8000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x0, 212, },
+  { 265, 2, 1, 0x000000e840000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 1113, },
+  { 266, 2, 1, 0x000000ea40000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 1114, },
+  { 267, 2, 1, 0x000000f840000000ull, 0x000001fff0000000ull, { 24, 25, 26, 0, 0 }, 0x0, 1115, },
+  { 275, 3, 1, 0x0000008208000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x0, 213, },
+  { 276, 3, 1, 0x0000008248000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x0, 214, },
+  { 277, 3, 1, 0x0000008288000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x0, 215, },
+  { 278, 3, 1, 0x00000082c8000000ull, 0x000001fff8000000ull, { 24, 33, 25, 0, 0 }, 0x0, 216, },
+  { 280, 5, 1, 0x000001d000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x0, 1161, },
+  { 280, 5, 1, 0x000001d000000000ull, 0x000001fc00000000ull, { 18, 20, 21, 19, 0 }, 0x40, 1243, },
+  { 281, 5, 1, 0x000001d000000000ull, 0x000001fc000fe000ull, { 18, 20, 21, 0, 0 }, 0x40, 1162, },
+  { 282, 1, 1, 0x0000010078000000ull, 0x000001eff8000000ull, { 24, 25, 26, 0, 0 }, 0x0, 217, },
+  { 282, 1, 1, 0x0000010178000000ull, 0x000001eff8000000ull, { 24, 55, 26, 0, 0 }, 0x0, 218, },
+  { 285, 2, 1, 0x0000000080000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x0, 219, },
+  { 286, 2, 1, 0x0000000088000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x0, 220, },
+  { 287, 2, 1, 0x0000000090000000ull, 0x000001eff8000000ull, { 24, 26, 0, 0, 0 }, 0x0, 221, },
+};
+
+static const char dis_table[] = {
+0xa0, 0xc5, 0xe8, 0xa0, 0x2e, 0x98, 0xa0, 0x2c, 0x80, 0xa0, 0x1b, 0xc0,
+0x98, 0xb0, 0x02, 0x50, 0x90, 0x50, 0x90, 0x28, 0x24, 0x38, 0x28, 0x24,
+0x38, 0x20, 0x90, 0x28, 0x24, 0x38, 0x18, 0x24, 0x38, 0x10, 0x91, 0x60,
+0x90, 0x28, 0x24, 0x38, 0x00, 0x10, 0x10, 0x58, 0x41, 0x61, 0xbf, 0xc0,
+0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+0x10, 0x10, 0x52, 0xc0, 0xc0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+0x10, 0x10, 0x10, 0x24, 0x23, 0x70, 0x90, 0x28, 0x24, 0x37, 0xf0, 0x24,
+0x37, 0xe8, 0xa8, 0x0b, 0x48, 0x15, 0x20, 0x97, 0x20, 0x95, 0xc8, 0x9a,
+0xb8, 0x05, 0x38, 0x91, 0x18, 0x90, 0xa0, 0x90, 0x60, 0x80, 0x90, 0x20,
+0x34, 0x86, 0xa4, 0x24, 0x00, 0x34, 0x83, 0x80, 0xa4, 0x35, 0xa0, 0x36,
+0xb9, 0x90, 0x50, 0x90, 0x28, 0x80, 0x36, 0xaf, 0x80, 0x34, 0x66, 0x81,
+0x33, 0xe2, 0x90, 0xe0, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x23, 0x10, 0x34,
+0x63, 0xa4, 0x1f, 0x08, 0x34, 0x60, 0x90, 0x38, 0xa4, 0x37, 0xa0, 0x36,
+0xfa, 0xa4, 0x37, 0x48, 0x36, 0xee, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x36,
+0x20, 0x36, 0xcf, 0xa4, 0x35, 0xf8, 0x36, 0xca, 0x80, 0xa4, 0x22, 0xf0,
+0x34, 0x5f, 0x92, 0x18, 0x91, 0xc0, 0x80, 0x91, 0x80, 0x90, 0xf8, 0xdb,
+0x84, 0x60, 0xf9, 0x40, 0xc0, 0xc0, 0x80, 0xa4, 0x41, 0x58, 0x8c, 0x42,
+0xb8, 0x84, 0x38, 0x61, 0xc0, 0xc0, 0x80, 0xa4, 0x41, 0x48, 0x8c, 0x42,
+0x98, 0x84, 0x38, 0x5f, 0xd3, 0x82, 0x40, 0x50, 0xc0, 0xc0, 0x81, 0x38,
+0x13, 0x50, 0xc0, 0xc0, 0x81, 0x38, 0x11, 0xa4, 0x1f, 0x18, 0x33, 0xe4,
+0x80, 0x90, 0x28, 0x80, 0x33, 0xe0, 0x80, 0x34, 0x68, 0x81, 0x90, 0x38,
+0xa4, 0x23, 0x80, 0x34, 0x6b, 0xa4, 0x23, 0x48, 0x34, 0x65, 0xc0, 0x40,
+0x10, 0x10, 0x90, 0x38, 0xa4, 0x1e, 0xf0, 0x33, 0xdf, 0xa4, 0x1e, 0xe0,
+0x33, 0xdd, 0x18, 0x24, 0x23, 0xf8, 0x83, 0x90, 0xa8, 0xd3, 0x82, 0xc0,
+0xc0, 0xc0, 0x80, 0xa4, 0x41, 0x28, 0x38, 0x4b, 0xc0, 0xc0, 0x80, 0xa4,
+0x41, 0x18, 0x38, 0x47, 0xd3, 0x82, 0x40, 0x50, 0xc0, 0xc0, 0x81, 0x38,
+0x0d, 0x50, 0xc0, 0xc0, 0x81, 0x38, 0x0b, 0x92, 0xb8, 0x99, 0x84, 0x23,
+0x68, 0x90, 0x78, 0x90, 0x50, 0x10, 0x10, 0x80, 0xa4, 0x35, 0x98, 0x36,
+0xb8, 0x82, 0x36, 0xae, 0x90, 0x80, 0x10, 0x10, 0x90, 0x38, 0xa4, 0x37,
+0x98, 0x36, 0xf9, 0xa4, 0x37, 0x40, 0x36, 0xed, 0x80, 0x90, 0x38, 0xa4,
+0x36, 0x18, 0x36, 0xce, 0xa4, 0x35, 0xf0, 0x36, 0xc9, 0x83, 0x90, 0xa8,
+0xd3, 0x82, 0xc0, 0xc0, 0xc0, 0x80, 0xa4, 0x40, 0xf8, 0x38, 0x3f, 0xc0,
+0xc0, 0x80, 0xa4, 0x40, 0xe8, 0x38, 0x3b, 0xd3, 0x82, 0x40, 0x50, 0xc0,
+0xc0, 0x81, 0x38, 0x07, 0x50, 0xc0, 0xc0, 0x81, 0x38, 0x05, 0x18, 0x24,
+0x23, 0x78, 0x83, 0x90, 0xa8, 0xd3, 0x82, 0xc0, 0xc0, 0xc0, 0x80, 0xa4,
+0x40, 0xc8, 0x38, 0x33, 0xc0, 0xc0, 0x80, 0xa4, 0x40, 0xb8, 0x38, 0x2f,
+0xd3, 0x82, 0x40, 0x50, 0xc0, 0xc0, 0x81, 0x38, 0x01, 0x50, 0xc0, 0xc0,
+0x81, 0x37, 0xff, 0x94, 0x50, 0x92, 0xf8, 0x99, 0x84, 0x1f, 0x48, 0x90,
+0x78, 0x90, 0x50, 0x10, 0x10, 0x80, 0xa4, 0x35, 0x90, 0x36, 0xb7, 0x82,
+0x36, 0xad, 0x90, 0x80, 0x10, 0x10, 0x90, 0x38, 0xa4, 0x37, 0x90, 0x36,
+0xf8, 0xa4, 0x37, 0x38, 0x36, 0xec, 0x80, 0x90, 0x38, 0xa4, 0x36, 0x10,
+0x36, 0xcd, 0xa4, 0x35, 0xe8, 0x36, 0xc8, 0x83, 0x90, 0xe8, 0xd3, 0x83,
+0xc0, 0xc0, 0xc0, 0x80, 0xa4, 0x41, 0x68, 0x8c, 0x42, 0xd8, 0x84, 0x38,
+0x63, 0xc0, 0xc0, 0x80, 0xa4, 0x41, 0x50, 0x8c, 0x42, 0xa8, 0x84, 0x38,
+0x60, 0xd3, 0x82, 0x40, 0x50, 0xc0, 0xc0, 0x81, 0x38, 0x15, 0x50, 0xc0,
+0xc0, 0x81, 0x38, 0x12, 0x18, 0x24, 0x1f, 0x40, 0x83, 0x90, 0xa8, 0xd3,
+0x82, 0xc0, 0xc0, 0xc0, 0x80, 0xa4, 0x41, 0x38, 0x38, 0x4f, 0xc0, 0xc0,
+0x80, 0xa4, 0x41, 0x20, 0x38, 0x49, 0xd3, 0x82, 0x40, 0x50, 0xc0, 0xc0,
+0x81, 0x38, 0x0f, 0x50, 0xc0, 0xc0, 0x81, 0x38, 0x0c, 0x92, 0xb8, 0x99,
+0x84, 0x1f, 0x38, 0x90, 0x78, 0x90, 0x50, 0x10, 0x10, 0x80, 0xa4, 0x35,
+0x88, 0x36, 0xb6, 0x82, 0x36, 0xac, 0x90, 0x80, 0x10, 0x10, 0x90, 0x38,
+0xa4, 0x37, 0x88, 0x36, 0xf7, 0xa4, 0x37, 0x30, 0x36, 0xeb, 0x80, 0x90,
+0x38, 0xa4, 0x36, 0x08, 0x36, 0xcc, 0xa4, 0x35, 0xe0, 0x36, 0xc7, 0x83,
+0x90, 0xa8, 0xd3, 0x82, 0xc0, 0xc0, 0xc0, 0x80, 0xa4, 0x41, 0x08, 0x38,
+0x43, 0xc0, 0xc0, 0x80, 0xa4, 0x40, 0xf0, 0x38, 0x3d, 0xd3, 0x82, 0x40,
+0x50, 0xc0, 0xc0, 0x81, 0x38, 0x09, 0x50, 0xc0, 0xc0, 0x81, 0x38, 0x06,
+0x18, 0x20, 0x01, 0x48, 0x83, 0x90, 0xa8, 0xd3, 0x82, 0xc0, 0xc0, 0xc0,
+0x80, 0xa4, 0x40, 0xd8, 0x38, 0x37, 0xc0, 0xc0, 0x80, 0xa4, 0x40, 0xc0,
+0x38, 0x31, 0xd3, 0x82, 0x40, 0x50, 0xc0, 0xc0, 0x81, 0x38, 0x03, 0x50,
+0xc0, 0xc0, 0x81, 0x38, 0x00, 0xda, 0x06, 0xe0, 0xf9, 0x80, 0x90, 0x60,
+0x90, 0x38, 0xa4, 0x23, 0xe8, 0x34, 0x7b, 0x80, 0x34, 0x78, 0x90, 0x38,
+0xa4, 0x23, 0x90, 0x34, 0x76, 0x80, 0x34, 0x73, 0x90, 0x60, 0x90, 0x38,
+0xa4, 0x23, 0xd0, 0x34, 0x7c, 0x80, 0x34, 0x79, 0x90, 0x38, 0xa4, 0x23,
+0xa8, 0x34, 0x77, 0x80, 0x34, 0x74, 0xc8, 0x40, 0x19, 0x00, 0x91, 0x58,
+0x90, 0x60, 0x82, 0x90, 0x20, 0x36, 0xab, 0xa4, 0x35, 0x48, 0x36, 0xaa,
+0x90, 0xc0, 0x80, 0x90, 0x90, 0x90, 0x48, 0xc9, 0xe1, 0xb9, 0x00, 0x85,
+0x36, 0xe3, 0xc9, 0xe1, 0xb8, 0x40, 0x85, 0x36, 0xe0, 0x80, 0x36, 0xdf,
+0x10, 0x10, 0x81, 0x36, 0xbb, 0x90, 0xa8, 0x10, 0x10, 0x90, 0x28, 0x81,
+0x36, 0xd9, 0x90, 0x38, 0xa4, 0x36, 0xa0, 0x36, 0xd5, 0xa4, 0x36, 0x90,
+0x36, 0xd3, 0x90, 0x70, 0x10, 0x10, 0x90, 0x38, 0xa4, 0x36, 0xb8, 0x36,
+0xd8, 0x80, 0x36, 0xd6, 0x90, 0x60, 0x90, 0x28, 0x24, 0x36, 0xf0, 0xa4,
+0x36, 0xe0, 0x36, 0xdd, 0x80, 0xa4, 0x36, 0xd0, 0x36, 0xdb, 0x80, 0x90,
+0xf8, 0x90, 0x90, 0x90, 0x50, 0x90, 0x28, 0x80, 0x37, 0xf7, 0x80, 0x37,
+0xfe, 0x80, 0xa4, 0x3f, 0xe0, 0x37, 0xfd, 0x90, 0x28, 0x81, 0x37, 0xfb,
+0x80, 0xa4, 0x3f, 0xc8, 0x37, 0xfa, 0x83, 0x37, 0xf8, 0x98, 0xe8, 0x01,
+0xb0, 0x90, 0x88, 0x90, 0x60, 0xa4, 0x35, 0x38, 0x10, 0x10, 0x10, 0x10,
+0x83, 0x33, 0xb7, 0x24, 0x35, 0x30, 0x90, 0x28, 0x24, 0x35, 0x28, 0x24,
+0x35, 0x20, 0x90, 0x88, 0x90, 0x60, 0xa4, 0x35, 0x10, 0x10, 0x10, 0x10,
+0x10, 0x83, 0x33, 0xb6, 0x24, 0x35, 0x08, 0x90, 0x28, 0x24, 0x35, 0x00,
+0x24, 0x34, 0xf8, 0xa8, 0x09, 0x00, 0x0e, 0x20, 0x96, 0x48, 0x95, 0xe8,
+0x93, 0x38, 0x91, 0xa0, 0x90, 0xd0, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x1e,
+0x60, 0x33, 0xcd, 0xa4, 0x1e, 0x50, 0x33, 0xcb, 0x90, 0x38, 0xa4, 0x1e,
+0x40, 0x33, 0xc9, 0x80, 0x33, 0xc7, 0x90, 0x60, 0x90, 0x28, 0x24, 0x1e,
+0x00, 0xa4, 0x1d, 0xf0, 0x33, 0xbf, 0x90, 0x38, 0xa4, 0x1d, 0xe0, 0x33,
+0xbd, 0xa4, 0x1e, 0x28, 0x33, 0xc6, 0x90, 0xe0, 0x90, 0x70, 0x90, 0x38,
+0xa4, 0x1e, 0x18, 0x33, 0xc4, 0xa4, 0x1e, 0x08, 0x33, 0xc2, 0x90, 0x38,
+0xa4, 0x34, 0xb0, 0x36, 0x9c, 0xa4, 0x34, 0x50, 0x36, 0x90, 0x90, 0x70,
+0x90, 0x38, 0xa4, 0x31, 0x90, 0x36, 0x3e, 0xa4, 0x31, 0x60, 0x36, 0x38,
+0x10, 0x10, 0xa4, 0x1d, 0xd0, 0x33, 0xbb, 0x99, 0x60, 0x02, 0x70, 0x90,
+0x90, 0x90, 0x50, 0x90, 0x28, 0x24, 0x1e, 0x90, 0x80, 0x33, 0xda, 0x80,
+0xa4, 0x1e, 0x98, 0x33, 0xd8, 0x90, 0x50, 0x90, 0x28, 0x24, 0x1e, 0xa0,
+0x80, 0x33, 0xdb, 0x90, 0x38, 0xa4, 0x1e, 0xa8, 0x33, 0xd9, 0xa4, 0x1e,
+0x70, 0x33, 0xcf, 0x90, 0xe0, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x33, 0xe8,
+0x36, 0x85, 0xa4, 0x33, 0x48, 0x36, 0x72, 0x90, 0x38, 0xa4, 0x32, 0xe0,
+0x36, 0x63, 0xa4, 0x32, 0x50, 0x36, 0x52, 0x81, 0xa4, 0x1e, 0x80, 0x33,
+0xd1, 0xe4, 0xa1, 0xfc, 0x40, 0x37, 0xf3, 0x18, 0x24, 0x1d, 0xc8, 0xe4,
+0xe1, 0xfa, 0xc0, 0x37, 0xed, 0x92, 0x40, 0x91, 0x08, 0x10, 0x10, 0x90,
+0x80, 0x10, 0x10, 0x90, 0x38, 0xa4, 0x34, 0xa8, 0x36, 0x9b, 0xa4, 0x34,
+0x48, 0x36, 0x8f, 0x80, 0x90, 0x38, 0xa4, 0x31, 0x88, 0x36, 0x3d, 0xa4,
+0x31, 0x58, 0x36, 0x37, 0x18, 0x20, 0x00, 0xf8, 0x80, 0x90, 0x70, 0x90,
+0x38, 0xa4, 0x33, 0xd8, 0x36, 0x84, 0xa4, 0x33, 0x40, 0x36, 0x70, 0x90,
+0x38, 0xa4, 0x32, 0xd0, 0x36, 0x62, 0xa4, 0x32, 0x48, 0x36, 0x50, 0xe4,
+0xa1, 0xf9, 0x40, 0x37, 0xe7, 0x18, 0x24, 0x1d, 0xc0, 0xe4, 0xe1, 0xf7,
+0xc0, 0x37, 0xe1, 0x92, 0x90, 0x92, 0x40, 0x91, 0x08, 0x10, 0x10, 0x90,
+0x80, 0x10, 0x10, 0x90, 0x38, 0xa4, 0x34, 0xa0, 0x36, 0x9a, 0xa4, 0x34,
+0x40, 0x36, 0x8e, 0x80, 0x90, 0x38, 0xa4, 0x31, 0x80, 0x36, 0x3c, 0xa4,
+0x31, 0x50, 0x36, 0x36, 0x18, 0x20, 0x00, 0xf8, 0x80, 0x90, 0x70, 0x90,
+0x38, 0xa4, 0x33, 0xc8, 0x36, 0x83, 0xa4, 0x33, 0x38, 0x36, 0x6e, 0x90,
+0x38, 0xa4, 0x32, 0xc0, 0x36, 0x61, 0xa4, 0x32, 0x40, 0x36, 0x4e, 0xe4,
+0xa1, 0xfc, 0x80, 0x37, 0xf5, 0x10, 0x10, 0xe4, 0xe1, 0xfb, 0x00, 0x37,
+0xef, 0x92, 0x50, 0x99, 0x1c, 0x1e, 0xb0, 0x10, 0x10, 0x90, 0x80, 0x10,
+0x10, 0x90, 0x38, 0xa4, 0x34, 0x98, 0x36, 0x99, 0xa4, 0x34, 0x38, 0x36,
+0x8d, 0x80, 0x90, 0x38, 0xa4, 0x31, 0x78, 0x36, 0x3b, 0xa4, 0x31, 0x48,
+0x36, 0x35, 0x18, 0x20, 0x00, 0xf8, 0x80, 0x90, 0x70, 0x90, 0x38, 0xa4,
+0x33, 0xb8, 0x36, 0x82, 0xa4, 0x33, 0x30, 0x36, 0x6c, 0x90, 0x38, 0xa4,
+0x32, 0xb0, 0x36, 0x60, 0xa4, 0x32, 0x38, 0x36, 0x4c, 0xe4, 0xa1, 0xf9,
+0x80, 0x37, 0xe9, 0x10, 0x10, 0xe4, 0xe1, 0xf8, 0x00, 0x37, 0xe3, 0xc0,
+0x40, 0x80, 0x10, 0x10, 0x81, 0x90, 0x90, 0x90, 0x48, 0xc9, 0xe1, 0x90,
+0x80, 0x85, 0x36, 0x46, 0xc9, 0xe1, 0x91, 0x00, 0x85, 0x36, 0x43, 0x80,
+0x36, 0x41, 0x80, 0xd8, 0x47, 0x80, 0x0d, 0xc0, 0xc0, 0x80, 0x10, 0x10,
+0x82, 0x90, 0x58, 0xd5, 0x81, 0x80, 0x80, 0x37, 0xdd, 0x80, 0x37, 0xdb,
+0xd5, 0x81, 0x80, 0x80, 0x37, 0xd9, 0x80, 0x37, 0xd7, 0xc0, 0x80, 0x10,
+0x10, 0x82, 0x90, 0x58, 0xd5, 0x81, 0x80, 0x80, 0x37, 0xde, 0x80, 0x37,
+0xdc, 0xd5, 0x81, 0x80, 0x80, 0x37, 0xda, 0x80, 0x37, 0xd8, 0xc0, 0x80,
+0x83, 0xa4, 0x3e, 0xa8, 0x37, 0xd6, 0xa0, 0x57, 0xc0, 0xa0, 0x41, 0xe0,
+0xa8, 0x1e, 0xb0, 0x34, 0x88, 0xa0, 0x12, 0x38, 0xa0, 0x0b, 0x48, 0x96,
+0x00, 0x9a, 0xf0, 0x05, 0xc0, 0x91, 0x70, 0x90, 0xb8, 0x90, 0x70, 0x90,
+0x38, 0xa4, 0x15, 0x58, 0x33, 0xb5, 0xa4, 0x15, 0x78, 0x33, 0xb4, 0x10,
+0x10, 0xa4, 0x15, 0x68, 0x33, 0xb3, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x14,
+0xf8, 0x33, 0x9a, 0xa4, 0x15, 0x18, 0x33, 0x99, 0x10, 0x10, 0xa4, 0x15,
+0x08, 0x33, 0x98, 0x90, 0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x14, 0x98,
+0x33, 0x7f, 0xa4, 0x14, 0xb8, 0x33, 0x7e, 0x10, 0x10, 0xa4, 0x14, 0xa8,
+0x33, 0x7d, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x14, 0x38, 0x33, 0x63, 0xa4,
+0x14, 0x58, 0x33, 0x62, 0x10, 0x10, 0xa4, 0x14, 0x48, 0x33, 0x61, 0x91,
+0x70, 0x90, 0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x15, 0x28, 0x33, 0xb0,
+0xa4, 0x15, 0x48, 0x33, 0xb2, 0x10, 0x10, 0xa4, 0x15, 0x38, 0x33, 0xb1,
+0x90, 0x70, 0x90, 0x38, 0xa4, 0x14, 0xc8, 0x33, 0x95, 0xa4, 0x14, 0xe8,
+0x33, 0x97, 0x10, 0x10, 0xa4, 0x14, 0xd8, 0x33, 0x96, 0x90, 0xb8, 0x90,
+0x70, 0x90, 0x38, 0xa4, 0x14, 0x68, 0x33, 0x7a, 0xa4, 0x14, 0x88, 0x33,
+0x7c, 0x10, 0x10, 0xa4, 0x14, 0x78, 0x33, 0x7b, 0x90, 0x70, 0x90, 0x38,
+0xa4, 0x14, 0x08, 0x33, 0x5e, 0xa4, 0x14, 0x28, 0x33, 0x60, 0x10, 0x10,
+0xa4, 0x14, 0x18, 0x33, 0x5f, 0xe4, 0xe1, 0x83, 0x40, 0x36, 0x21, 0x9a,
+0xf0, 0x05, 0x00, 0x91, 0x70, 0x90, 0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4,
+0x13, 0xa0, 0x33, 0xad, 0xa4, 0x13, 0x98, 0x33, 0xaf, 0x10, 0x10, 0xa4,
+0x13, 0x90, 0x33, 0xae, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x13, 0x88, 0x33,
+0x92, 0xa4, 0x13, 0x80, 0x33, 0x94, 0x10, 0x10, 0xa4, 0x13, 0x78, 0x33,
+0x93, 0x90, 0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x13, 0x70, 0x33, 0x77,
+0xa4, 0x13, 0x68, 0x33, 0x79, 0x10, 0x10, 0xa4, 0x13, 0x60, 0x33, 0x78,
+0x90, 0x70, 0x90, 0x38, 0xa4, 0x13, 0x58, 0x33, 0x5b, 0xa4, 0x13, 0x50,
+0x33, 0x5d, 0x10, 0x10, 0xa4, 0x13, 0x48, 0x33, 0x5c, 0x91, 0x10, 0x90,
+0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0xaa, 0x80, 0x33, 0xac, 0x10,
+0x10, 0x80, 0x33, 0xab, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x8f, 0x80,
+0x33, 0x91, 0x10, 0x10, 0x80, 0x33, 0x90, 0x90, 0x88, 0x90, 0x50, 0x90,
+0x28, 0x80, 0x33, 0x74, 0x80, 0x33, 0x76, 0x10, 0x10, 0x80, 0x33, 0x75,
+0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x58, 0x80, 0x33, 0x5a, 0x10, 0x10,
+0x80, 0x33, 0x59, 0xe4, 0xe1, 0x5e, 0x40, 0x35, 0xa1, 0x95, 0x40, 0x9a,
+0x90, 0x05, 0x00, 0x91, 0x10, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80,
+0x33, 0xa7, 0x80, 0x33, 0xa9, 0x10, 0x10, 0x80, 0x33, 0xa8, 0x90, 0x50,
+0x90, 0x28, 0x80, 0x33, 0x8c, 0x80, 0x33, 0x8e, 0x10, 0x10, 0x80, 0x33,
+0x8d, 0x90, 0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x13, 0x30, 0x33, 0x71,
+0xa4, 0x13, 0x40, 0x33, 0x73, 0x10, 0x10, 0xa4, 0x13, 0x38, 0x33, 0x72,
+0x90, 0x70, 0x90, 0x38, 0xa4, 0x13, 0x00, 0x33, 0x55, 0xa4, 0x13, 0x10,
+0x33, 0x57, 0x10, 0x10, 0xa4, 0x13, 0x08, 0x33, 0x56, 0x91, 0x10, 0x90,
+0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0xa4, 0x80, 0x33, 0xa6, 0x10,
+0x10, 0x80, 0x33, 0xa5, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x89, 0x80,
+0x33, 0x8b, 0x10, 0x10, 0x80, 0x33, 0x8a, 0x90, 0xb8, 0x90, 0x70, 0x90,
+0x38, 0xa4, 0x13, 0x18, 0x33, 0x6e, 0xa4, 0x13, 0x28, 0x33, 0x70, 0x10,
+0x10, 0xa4, 0x13, 0x20, 0x33, 0x6f, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x12,
+0xe8, 0x33, 0x52, 0xa4, 0x12, 0xf8, 0x33, 0x54, 0x10, 0x10, 0xa4, 0x12,
+0xf0, 0x33, 0x53, 0xe4, 0xe1, 0x82, 0x40, 0x36, 0x1d, 0x98, 0xb8, 0x01,
+0x68, 0x10, 0x10, 0x10, 0x10, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x4f,
+0x80, 0x33, 0x51, 0x10, 0x10, 0x80, 0x33, 0x50, 0x90, 0x60, 0x90, 0x30,
+0x60, 0xa0, 0x97, 0x00, 0x60, 0xa0, 0x96, 0xc0, 0x90, 0x30, 0x60, 0xa0,
+0x96, 0x80, 0x60, 0xa0, 0x96, 0x40, 0xe4, 0xe1, 0x5c, 0x40, 0x35, 0x99,
+0xa0, 0x08, 0x08, 0x94, 0xe0, 0x9a, 0x60, 0x04, 0xa0, 0x91, 0x40, 0x90,
+0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x13, 0xd8, 0x33, 0x9e, 0xa4, 0x13,
+0xf8, 0x33, 0xa3, 0x10, 0x10, 0xa4, 0x13, 0xe8, 0x33, 0xa2, 0x90, 0x50,
+0x90, 0x28, 0x80, 0x33, 0x83, 0x80, 0x33, 0x88, 0x10, 0x10, 0x80, 0x33,
+0x87, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x68, 0x80, 0x33,
+0x6d, 0x10, 0x10, 0x80, 0x33, 0x6c, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33,
+0x49, 0x80, 0x33, 0x4e, 0x10, 0x10, 0x80, 0x33, 0x4d, 0x91, 0x40, 0x90,
+0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x13, 0xa8, 0x33, 0x9b, 0xa4, 0x13,
+0xc8, 0x33, 0x9d, 0x10, 0x10, 0xa4, 0x13, 0xb8, 0x33, 0x9c, 0x90, 0x50,
+0x90, 0x28, 0x80, 0x33, 0x80, 0x80, 0x33, 0x82, 0x10, 0x10, 0x80, 0x33,
+0x81, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x65, 0x80, 0x33,
+0x67, 0x10, 0x10, 0x80, 0x33, 0x66, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33,
+0x46, 0x80, 0x33, 0x48, 0x10, 0x10, 0x80, 0x33, 0x47, 0xe4, 0xe1, 0x81,
+0x40, 0x36, 0x19, 0x9a, 0x60, 0x02, 0xe0, 0x91, 0x40, 0x90, 0xb8, 0x90,
+0x70, 0x90, 0x38, 0xa4, 0x1a, 0x20, 0x33, 0x9f, 0xa4, 0x1a, 0x10, 0x33,
+0xa1, 0x10, 0x10, 0xa4, 0x1a, 0x00, 0x33, 0xa0, 0x90, 0x50, 0x90, 0x28,
+0x80, 0x33, 0x84, 0x80, 0x33, 0x86, 0x10, 0x10, 0x80, 0x33, 0x85, 0x90,
+0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x69, 0x80, 0x33, 0x6b, 0x10,
+0x10, 0x80, 0x33, 0x6a, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x4a, 0x80,
+0x33, 0x4c, 0x10, 0x10, 0x80, 0x33, 0x4b, 0x81, 0x90, 0x50, 0x90, 0x28,
+0x24, 0x19, 0xd0, 0x24, 0x19, 0xf0, 0x10, 0x10, 0x24, 0x19, 0xe0, 0xe4,
+0xe1, 0x5a, 0x40, 0x35, 0x91, 0x93, 0x90, 0x99, 0xb8, 0x03, 0x50, 0x90,
+0xe8, 0x90, 0x88, 0x90, 0x40, 0x80, 0xa4, 0x15, 0xb8, 0x32, 0xca, 0x10,
+0x10, 0xa4, 0x15, 0xa8, 0x32, 0xc9, 0x90, 0x28, 0x81, 0x32, 0xc6, 0x10,
+0x10, 0x80, 0x32, 0xc5, 0x90, 0x60, 0x90, 0x28, 0x81, 0x32, 0xc2, 0x10,
+0x10, 0x80, 0x32, 0xc1, 0x90, 0x28, 0x81, 0x32, 0xbe, 0x10, 0x10, 0x80,
+0x32, 0xbd, 0x90, 0xe8, 0x90, 0x88, 0x90, 0x40, 0x80, 0xa4, 0x15, 0x88,
+0x32, 0xc7, 0x10, 0x10, 0xa4, 0x15, 0x98, 0x32, 0xc8, 0x90, 0x28, 0x81,
+0x32, 0xc3, 0x10, 0x10, 0x80, 0x32, 0xc4, 0x90, 0x60, 0x90, 0x28, 0x81,
+0x32, 0xbf, 0x10, 0x10, 0x80, 0x32, 0xc0, 0x90, 0x28, 0x81, 0x32, 0xbb,
+0x10, 0x10, 0x80, 0x32, 0xbc, 0xe4, 0xe1, 0x80, 0x40, 0x36, 0x15, 0x88,
+0x00, 0x88, 0x10, 0x10, 0x10, 0x10, 0x90, 0x28, 0x81, 0x32, 0xb9, 0x10,
+0x10, 0x80, 0x32, 0xba, 0xe4, 0xe1, 0x58, 0x40, 0x35, 0x89, 0xa0, 0x0e,
+0x80, 0xa0, 0x09, 0x08, 0x94, 0x80, 0x9a, 0x30, 0x04, 0x40, 0x91, 0x10,
+0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x39, 0x80, 0x33, 0x38,
+0x10, 0x10, 0x80, 0x33, 0x37, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x1e,
+0x80, 0x33, 0x1d, 0x10, 0x10, 0x80, 0x33, 0x1c, 0x90, 0x88, 0x90, 0x50,
+0x90, 0x28, 0x80, 0x33, 0x03, 0x80, 0x33, 0x02, 0x10, 0x10, 0x80, 0x33,
+0x01, 0x90, 0x50, 0x90, 0x28, 0x80, 0x32, 0xe8, 0x80, 0x32, 0xe7, 0x10,
+0x10, 0x80, 0x32, 0xe6, 0x91, 0x10, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28,
+0x80, 0x33, 0x34, 0x80, 0x33, 0x36, 0x10, 0x10, 0x80, 0x33, 0x35, 0x90,
+0x50, 0x90, 0x28, 0x80, 0x33, 0x19, 0x80, 0x33, 0x1b, 0x10, 0x10, 0x80,
+0x33, 0x1a, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x32, 0xfe, 0x80,
+0x33, 0x00, 0x10, 0x10, 0x80, 0x32, 0xff, 0x90, 0x50, 0x90, 0x28, 0x80,
+0x32, 0xe3, 0x80, 0x32, 0xe5, 0x10, 0x10, 0x80, 0x32, 0xe4, 0xe4, 0xe1,
+0x72, 0x40, 0x35, 0xf1, 0x9a, 0x30, 0x04, 0x40, 0x91, 0x10, 0x90, 0x88,
+0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x31, 0x80, 0x33, 0x33, 0x10, 0x10,
+0x80, 0x33, 0x32, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x16, 0x80, 0x33,
+0x18, 0x10, 0x10, 0x80, 0x33, 0x17, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28,
+0x80, 0x32, 0xfb, 0x80, 0x32, 0xfd, 0x10, 0x10, 0x80, 0x32, 0xfc, 0x90,
+0x50, 0x90, 0x28, 0x80, 0x32, 0xe0, 0x80, 0x32, 0xe2, 0x10, 0x10, 0x80,
+0x32, 0xe1, 0x91, 0x10, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33,
+0x2e, 0x80, 0x33, 0x30, 0x10, 0x10, 0x80, 0x33, 0x2f, 0x90, 0x50, 0x90,
+0x28, 0x80, 0x33, 0x13, 0x80, 0x33, 0x15, 0x10, 0x10, 0x80, 0x33, 0x14,
+0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x32, 0xf8, 0x80, 0x32, 0xfa,
+0x10, 0x10, 0x80, 0x32, 0xf9, 0x90, 0x50, 0x90, 0x28, 0x80, 0x32, 0xdd,
+0x80, 0x32, 0xdf, 0x10, 0x10, 0x80, 0x32, 0xde, 0xe4, 0xe1, 0x51, 0x40,
+0x35, 0x59, 0x94, 0x80, 0x9a, 0x30, 0x04, 0x40, 0x91, 0x10, 0x90, 0x88,
+0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x2b, 0x80, 0x33, 0x2d, 0x10, 0x10,
+0x80, 0x33, 0x2c, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x10, 0x80, 0x33,
+0x12, 0x10, 0x10, 0x80, 0x33, 0x11, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28,
+0x80, 0x32, 0xf5, 0x80, 0x32, 0xf7, 0x10, 0x10, 0x80, 0x32, 0xf6, 0x90,
+0x50, 0x90, 0x28, 0x80, 0x32, 0xda, 0x80, 0x32, 0xdc, 0x10, 0x10, 0x80,
+0x32, 0xdb, 0x91, 0x10, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33,
+0x28, 0x80, 0x33, 0x2a, 0x10, 0x10, 0x80, 0x33, 0x29, 0x90, 0x50, 0x90,
+0x28, 0x80, 0x33, 0x0d, 0x80, 0x33, 0x0f, 0x10, 0x10, 0x80, 0x33, 0x0e,
+0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x32, 0xf2, 0x80, 0x32, 0xf4,
+0x10, 0x10, 0x80, 0x32, 0xf3, 0x90, 0x50, 0x90, 0x28, 0x80, 0x32, 0xd7,
+0x80, 0x32, 0xd9, 0x10, 0x10, 0x80, 0x32, 0xd8, 0xe4, 0xe1, 0x70, 0x40,
+0x35, 0xe9, 0x88, 0x00, 0xb0, 0x10, 0x10, 0x10, 0x10, 0x90, 0x50, 0x90,
+0x28, 0x80, 0x32, 0xd4, 0x80, 0x32, 0xd6, 0x10, 0x10, 0x80, 0x32, 0xd5,
+0xe4, 0xe1, 0x50, 0x40, 0x35, 0x55, 0x96, 0xe8, 0x94, 0x80, 0x9a, 0x30,
+0x04, 0x40, 0x91, 0x10, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33,
+0x22, 0x80, 0x33, 0x27, 0x10, 0x10, 0x80, 0x33, 0x26, 0x90, 0x50, 0x90,
+0x28, 0x80, 0x33, 0x07, 0x80, 0x33, 0x0c, 0x10, 0x10, 0x80, 0x33, 0x0b,
+0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x32, 0xec, 0x80, 0x32, 0xf1,
+0x10, 0x10, 0x80, 0x32, 0xf0, 0x90, 0x50, 0x90, 0x28, 0x80, 0x32, 0xce,
+0x80, 0x32, 0xd3, 0x10, 0x10, 0x80, 0x32, 0xd2, 0x91, 0x10, 0x90, 0x88,
+0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x1f, 0x80, 0x33, 0x21, 0x10, 0x10,
+0x80, 0x33, 0x20, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x04, 0x80, 0x33,
+0x06, 0x10, 0x10, 0x80, 0x33, 0x05, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28,
+0x80, 0x32, 0xe9, 0x80, 0x32, 0xeb, 0x10, 0x10, 0x80, 0x32, 0xea, 0x90,
+0x50, 0x90, 0x28, 0x80, 0x32, 0xcb, 0x80, 0x32, 0xcd, 0x10, 0x10, 0x80,
+0x32, 0xcc, 0xe4, 0xe1, 0x6e, 0x40, 0x35, 0xe1, 0x88, 0x02, 0x28, 0x91,
+0x10, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0x23, 0x80, 0x33,
+0x25, 0x10, 0x10, 0x80, 0x33, 0x24, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33,
+0x08, 0x80, 0x33, 0x0a, 0x10, 0x10, 0x80, 0x33, 0x09, 0x90, 0x88, 0x90,
+0x50, 0x90, 0x28, 0x80, 0x32, 0xed, 0x80, 0x32, 0xef, 0x10, 0x10, 0x80,
+0x32, 0xee, 0x90, 0x50, 0x90, 0x28, 0x80, 0x32, 0xcf, 0x80, 0x32, 0xd1,
+0x10, 0x10, 0x80, 0x32, 0xd0, 0xe4, 0xe1, 0x4f, 0x40, 0x35, 0x51, 0x90,
+0x40, 0xe5, 0x21, 0x6c, 0x40, 0x35, 0xd9, 0xe5, 0x21, 0x4e, 0x40, 0x35,
+0x4d, 0x9e, 0xb4, 0x22, 0xe8, 0x93, 0x70, 0x91, 0xd8, 0xd5, 0x07, 0x80,
+0xd0, 0xc4, 0x40, 0x90, 0x48, 0x80, 0x8c, 0x3e, 0x38, 0x84, 0x37, 0xd1,
+0xa4, 0x3c, 0x18, 0x37, 0x9b, 0x90, 0x28, 0x24, 0x3b, 0x58, 0xa4, 0x39,
+0xd8, 0x37, 0x53, 0xd0, 0xc4, 0x40, 0x90, 0x48, 0x80, 0x8c, 0x3e, 0x18,
+0x84, 0x37, 0xcf, 0xa4, 0x3c, 0x08, 0x37, 0x99, 0x90, 0x28, 0x24, 0x3b,
+0x48, 0xa4, 0x39, 0xc8, 0x37, 0x51, 0xd5, 0x06, 0x80, 0xd0, 0xc3, 0x40,
+0x90, 0x28, 0x80, 0x37, 0xbb, 0xa4, 0x3b, 0xe8, 0x37, 0x95, 0x90, 0x28,
+0x24, 0x3b, 0x28, 0xa4, 0x39, 0xa8, 0x37, 0x4d, 0xd0, 0xc3, 0x40, 0x90,
+0x28, 0x80, 0x37, 0xb7, 0xa4, 0x3b, 0xd8, 0x37, 0x93, 0x90, 0x28, 0x24,
+0x3b, 0x18, 0xa4, 0x39, 0x98, 0x37, 0x4b, 0x91, 0x98, 0xd5, 0x06, 0x80,
+0xd0, 0xc3, 0x40, 0x90, 0x28, 0x80, 0x37, 0xaf, 0xa4, 0x3b, 0xb8, 0x37,
+0x8f, 0x90, 0x28, 0x24, 0x3a, 0xf8, 0xa4, 0x39, 0x78, 0x37, 0x47, 0xd0,
+0xc3, 0x40, 0x90, 0x28, 0x80, 0x37, 0xab, 0xa4, 0x3b, 0xa8, 0x37, 0x8d,
+0x90, 0x28, 0x24, 0x3a, 0xe8, 0xa4, 0x39, 0x68, 0x37, 0x45, 0xd5, 0x06,
+0x80, 0xd0, 0xc3, 0x40, 0x90, 0x28, 0x80, 0x37, 0xa3, 0xa4, 0x3b, 0x88,
+0x37, 0x89, 0x90, 0x28, 0x24, 0x3a, 0xc8, 0xa4, 0x39, 0x48, 0x37, 0x41,
+0xd0, 0xc3, 0x40, 0x90, 0x28, 0x80, 0x37, 0x9f, 0xa4, 0x3b, 0x78, 0x37,
+0x87, 0x90, 0x28, 0x24, 0x3a, 0xb8, 0xa4, 0x39, 0x38, 0x37, 0x3f, 0x93,
+0x70, 0x91, 0xd8, 0xd5, 0x07, 0x80, 0xd0, 0xc4, 0x40, 0x90, 0x48, 0x80,
+0x8c, 0x3e, 0x58, 0x84, 0x37, 0xd3, 0xa4, 0x3c, 0x28, 0x37, 0x9d, 0x90,
+0x28, 0x24, 0x3b, 0x68, 0xa4, 0x39, 0xe8, 0x37, 0x55, 0xd0, 0xc4, 0x40,
+0x90, 0x48, 0x80, 0x8c, 0x3e, 0x28, 0x84, 0x37, 0xd0, 0xa4, 0x3c, 0x10,
+0x37, 0x9a, 0x90, 0x28, 0x24, 0x3b, 0x50, 0xa4, 0x39, 0xd0, 0x37, 0x52,
+0xd5, 0x06, 0x80, 0xd0, 0xc3, 0x40, 0x90, 0x28, 0x80, 0x37, 0xbf, 0xa4,
+0x3b, 0xf8, 0x37, 0x97, 0x90, 0x28, 0x24, 0x3b, 0x38, 0xa4, 0x39, 0xb8,
+0x37, 0x4f, 0xd0, 0xc3, 0x40, 0x90, 0x28, 0x80, 0x37, 0xb9, 0xa4, 0x3b,
+0xe0, 0x37, 0x94, 0x90, 0x28, 0x24, 0x3b, 0x20, 0xa4, 0x39, 0xa0, 0x37,
+0x4c, 0x91, 0x98, 0xd5, 0x06, 0x80, 0xd0, 0xc3, 0x40, 0x90, 0x28, 0x80,
+0x37, 0xb3, 0xa4, 0x3b, 0xc8, 0x37, 0x91, 0x90, 0x28, 0x24, 0x3b, 0x08,
+0xa4, 0x39, 0x88, 0x37, 0x49, 0xd0, 0xc3, 0x40, 0x90, 0x28, 0x80, 0x37,
+0xad, 0xa4, 0x3b, 0xb0, 0x37, 0x8e, 0x90, 0x28, 0x24, 0x3a, 0xf0, 0xa4,
+0x39, 0x70, 0x37, 0x46, 0xd5, 0x06, 0x80, 0xd0, 0xc3, 0x40, 0x90, 0x28,
+0x80, 0x37, 0xa7, 0xa4, 0x3b, 0x98, 0x37, 0x8b, 0x90, 0x28, 0x24, 0x3a,
+0xd8, 0xa4, 0x39, 0x58, 0x37, 0x43, 0xd0, 0xc3, 0x40, 0x90, 0x28, 0x80,
+0x37, 0xa1, 0xa4, 0x3b, 0x80, 0x37, 0x88, 0x90, 0x28, 0x24, 0x3a, 0xc0,
+0xa4, 0x39, 0x40, 0x37, 0x40, 0x99, 0x08, 0x01, 0xf0, 0x81, 0x90, 0x78,
+0xd4, 0xc2, 0x00, 0xa4, 0x22, 0x80, 0x34, 0x40, 0xa4, 0x21, 0x80, 0x34,
+0x20, 0xd4, 0xc2, 0x00, 0xa4, 0x21, 0xa0, 0x34, 0x44, 0xa4, 0x20, 0xa0,
+0x34, 0x24, 0x81, 0x90, 0x78, 0xd4, 0xc2, 0x00, 0xa4, 0x21, 0xe0, 0x34,
+0x4c, 0xa4, 0x20, 0xe0, 0x34, 0x2c, 0xd4, 0xc2, 0x00, 0xa4, 0x21, 0xc0,
+0x34, 0x48, 0xa4, 0x20, 0xc0, 0x34, 0x28, 0xa8, 0x0b, 0x18, 0x13, 0xa8,
+0x96, 0x80, 0x93, 0x40, 0x99, 0x90, 0x03, 0x00, 0x90, 0xc0, 0x90, 0x60,
+0x90, 0x38, 0xa4, 0x12, 0xb8, 0x32, 0x58, 0x24, 0x12, 0xb0, 0x90, 0x38,
+0xa4, 0x11, 0xe0, 0x32, 0x3d, 0x24, 0x11, 0xd8, 0x90, 0x60, 0x90, 0x38,
+0xa4, 0x11, 0x08, 0x32, 0x22, 0x24, 0x11, 0x00, 0x90, 0x38, 0xa4, 0x10,
+0x30, 0x32, 0x07, 0x24, 0x10, 0x28, 0x90, 0xc0, 0x90, 0x60, 0x90, 0x38,
+0xa4, 0x12, 0xa8, 0x32, 0x53, 0x24, 0x12, 0xa0, 0x90, 0x38, 0xa4, 0x11,
+0xd0, 0x32, 0x38, 0x24, 0x11, 0xc8, 0x90, 0x60, 0x90, 0x38, 0xa4, 0x10,
+0xf8, 0x32, 0x1d, 0x24, 0x10, 0xf0, 0x90, 0x38, 0xa4, 0x10, 0x20, 0x32,
+0x02, 0x24, 0x10, 0x18, 0xe4, 0xe1, 0xc8, 0x40, 0x37, 0x23, 0x99, 0x90,
+0x03, 0x00, 0x90, 0xc0, 0x90, 0x60, 0x90, 0x38, 0xa4, 0x12, 0x90, 0x32,
+0x50, 0x24, 0x12, 0x88, 0x90, 0x38, 0xa4, 0x11, 0xb8, 0x32, 0x35, 0x24,
+0x11, 0xb0, 0x90, 0x60, 0x90, 0x38, 0xa4, 0x10, 0xe0, 0x32, 0x1a, 0x24,
+0x10, 0xd8, 0x90, 0x38, 0xa4, 0x10, 0x08, 0x31, 0xff, 0x24, 0x10, 0x00,
+0x90, 0xc0, 0x90, 0x60, 0x90, 0x38, 0xa4, 0x12, 0x78, 0x32, 0x4d, 0x24,
+0x12, 0x70, 0x90, 0x38, 0xa4, 0x11, 0xa0, 0x32, 0x32, 0x24, 0x11, 0x98,
+0x90, 0x60, 0x90, 0x38, 0xa4, 0x10, 0xc8, 0x32, 0x17, 0x24, 0x10, 0xc0,
+0x90, 0x38, 0xa4, 0x0f, 0xf0, 0x31, 0xfc, 0x24, 0x0f, 0xe8, 0xe4, 0xe1,
+0xc6, 0xc0, 0x37, 0x1d, 0x93, 0x78, 0x99, 0x90, 0x03, 0x00, 0x90, 0xc0,
+0x90, 0x60, 0x90, 0x38, 0xa4, 0x12, 0x60, 0x32, 0x4a, 0x24, 0x12, 0x58,
+0x90, 0x38, 0xa4, 0x11, 0x88, 0x32, 0x2f, 0x24, 0x11, 0x80, 0x90, 0x60,
+0x90, 0x38, 0xa4, 0x10, 0xb0, 0x32, 0x14, 0x24, 0x10, 0xa8, 0x90, 0x38,
+0xa4, 0x0f, 0xd8, 0x31, 0xf9, 0x24, 0x0f, 0xd0, 0x90, 0xc0, 0x90, 0x60,
+0x90, 0x38, 0xa4, 0x12, 0x48, 0x32, 0x47, 0x24, 0x12, 0x40, 0x90, 0x38,
+0xa4, 0x11, 0x70, 0x32, 0x2c, 0x24, 0x11, 0x68, 0x90, 0x60, 0x90, 0x38,
+0xa4, 0x10, 0x98, 0x32, 0x11, 0x24, 0x10, 0x90, 0x90, 0x38, 0xa4, 0x0f,
+0xc0, 0x31, 0xf6, 0x24, 0x0f, 0xb8, 0xec, 0xa1, 0x16, 0x00, 0x02, 0x00,
+0x34, 0x5a, 0xa4, 0x38, 0xa8, 0x37, 0x17, 0x88, 0x00, 0x88, 0x10, 0x10,
+0x10, 0x10, 0x90, 0x38, 0xa4, 0x0f, 0xa8, 0x31, 0xf3, 0x24, 0x0f, 0xa0,
+0xe9, 0x61, 0x15, 0x40, 0x02, 0x00, 0x34, 0x56, 0xe3, 0x61, 0xc3, 0xc0,
+0x37, 0x11, 0x95, 0x08, 0x93, 0x40, 0x99, 0x90, 0x03, 0x00, 0x90, 0xc0,
+0x90, 0x60, 0x90, 0x38, 0xa4, 0x12, 0x30, 0x32, 0x41, 0x24, 0x12, 0x28,
+0x90, 0x38, 0xa4, 0x11, 0x58, 0x32, 0x26, 0x24, 0x11, 0x50, 0x90, 0x60,
+0x90, 0x38, 0xa4, 0x10, 0x80, 0x32, 0x0b, 0x24, 0x10, 0x78, 0x90, 0x38,
+0xa4, 0x0f, 0x90, 0x31, 0xed, 0x24, 0x0f, 0x88, 0x90, 0xc0, 0x90, 0x60,
+0x90, 0x38, 0xa4, 0x12, 0x00, 0x32, 0x3e, 0x24, 0x11, 0xf8, 0x90, 0x38,
+0xa4, 0x11, 0x28, 0x32, 0x23, 0x24, 0x11, 0x20, 0x90, 0x60, 0x90, 0x38,
+0xa4, 0x10, 0x50, 0x32, 0x08, 0x24, 0x10, 0x48, 0x90, 0x38, 0xa4, 0x0f,
+0x60, 0x31, 0xea, 0x24, 0x0f, 0x58, 0xe4, 0xe1, 0xc8, 0x80, 0x37, 0x25,
+0x88, 0x01, 0x88, 0x90, 0xc0, 0x90, 0x60, 0x90, 0x38, 0xa4, 0x12, 0x20,
+0x32, 0x42, 0x24, 0x12, 0x18, 0x90, 0x38, 0xa4, 0x11, 0x48, 0x32, 0x27,
+0x24, 0x11, 0x40, 0x90, 0x60, 0x90, 0x38, 0xa4, 0x10, 0x70, 0x32, 0x0c,
+0x24, 0x10, 0x68, 0x90, 0x38, 0xa4, 0x0f, 0x80, 0x31, 0xee, 0x24, 0x0f,
+0x78, 0xe4, 0xe1, 0xc7, 0x00, 0x37, 0x1f, 0x92, 0xd0, 0x99, 0x50, 0x02,
+0x80, 0x90, 0xa0, 0x90, 0x50, 0x90, 0x28, 0x80, 0x31, 0xe9, 0x24, 0x0f,
+0x40, 0x90, 0x28, 0x80, 0x31, 0xe5, 0x24, 0x0f, 0x20, 0x90, 0x50, 0x90,
+0x28, 0x80, 0x31, 0xe1, 0x24, 0x0f, 0x00, 0x90, 0x28, 0x80, 0x31, 0xdd,
+0x24, 0x0e, 0xe0, 0x90, 0xa0, 0x90, 0x50, 0x90, 0x28, 0x80, 0x31, 0xe6,
+0x24, 0x0f, 0x38, 0x90, 0x28, 0x80, 0x31, 0xe2, 0x24, 0x0f, 0x18, 0x90,
+0x50, 0x90, 0x28, 0x80, 0x31, 0xde, 0x24, 0x0e, 0xf8, 0x90, 0x28, 0x80,
+0x31, 0xda, 0x24, 0x0e, 0xd8, 0xec, 0xe1, 0xc5, 0xa1, 0x17, 0x00, 0x37,
+0x19, 0x88, 0x00, 0x78, 0x10, 0x10, 0x10, 0x10, 0x90, 0x28, 0x80, 0x31,
+0xd8, 0x24, 0x0e, 0xc8, 0xec, 0xe1, 0xc4, 0x21, 0x15, 0x00, 0x37, 0x13,
+0xe5, 0xa1, 0x4d, 0x40, 0x35, 0x31, 0xa0, 0x2a, 0x10, 0xa8, 0x16, 0x60,
+0x29, 0xd8, 0xa0, 0x0c, 0x48, 0xa0, 0x0a, 0xc8, 0x95, 0x60, 0x92, 0xb0,
+0x91, 0x40, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x31, 0xa1, 0x80,
+0x31, 0xa0, 0x10, 0x10, 0x80, 0x31, 0x9f, 0x90, 0x70, 0x90, 0x38, 0xa4,
+0x08, 0x98, 0x31, 0xb3, 0xa4, 0x08, 0x90, 0x31, 0xb2, 0x10, 0x10, 0xa4,
+0x08, 0x88, 0x31, 0xb1, 0x90, 0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x09,
+0xb8, 0x31, 0xd7, 0xa4, 0x09, 0xb0, 0x31, 0xd6, 0x10, 0x10, 0xa4, 0x09,
+0xa8, 0x31, 0xd5, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x09, 0x28, 0x31, 0xc5,
+0xa4, 0x09, 0x20, 0x31, 0xc4, 0x10, 0x10, 0xa4, 0x09, 0x18, 0x31, 0xc3,
+0x91, 0x40, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x31, 0x9c, 0x80,
+0x31, 0x9e, 0x10, 0x10, 0x80, 0x31, 0x9d, 0x90, 0x70, 0x90, 0x38, 0xa4,
+0x08, 0x70, 0x31, 0xae, 0xa4, 0x08, 0x80, 0x31, 0xb0, 0x10, 0x10, 0xa4,
+0x08, 0x78, 0x31, 0xaf, 0x90, 0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x09,
+0x90, 0x31, 0xd2, 0xa4, 0x09, 0xa0, 0x31, 0xd4, 0x10, 0x10, 0xa4, 0x09,
+0x98, 0x31, 0xd3, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x09, 0x00, 0x31, 0xc0,
+0xa4, 0x09, 0x10, 0x31, 0xc2, 0x10, 0x10, 0xa4, 0x09, 0x08, 0x31, 0xc1,
+0x92, 0xb0, 0x91, 0x40, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x31,
+0x99, 0x80, 0x31, 0x9b, 0x10, 0x10, 0x80, 0x31, 0x9a, 0x90, 0x70, 0x90,
+0x38, 0xa4, 0x08, 0x58, 0x31, 0xab, 0xa4, 0x08, 0x68, 0x31, 0xad, 0x10,
+0x10, 0xa4, 0x08, 0x60, 0x31, 0xac, 0x90, 0xb8, 0x90, 0x70, 0x90, 0x38,
+0xa4, 0x09, 0x78, 0x31, 0xcf, 0xa4, 0x09, 0x88, 0x31, 0xd1, 0x10, 0x10,
+0xa4, 0x09, 0x80, 0x31, 0xd0, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x08, 0xe8,
+0x31, 0xbd, 0xa4, 0x08, 0xf8, 0x31, 0xbf, 0x10, 0x10, 0xa4, 0x08, 0xf0,
+0x31, 0xbe, 0x91, 0x40, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80, 0x31,
+0x96, 0x80, 0x31, 0x98, 0x10, 0x10, 0x80, 0x31, 0x97, 0x90, 0x70, 0x90,
+0x38, 0xa4, 0x08, 0x40, 0x31, 0xa8, 0xa4, 0x08, 0x50, 0x31, 0xaa, 0x10,
+0x10, 0xa4, 0x08, 0x48, 0x31, 0xa9, 0x90, 0xb8, 0x90, 0x70, 0x90, 0x38,
+0xa4, 0x09, 0x60, 0x31, 0xcc, 0xa4, 0x09, 0x70, 0x31, 0xce, 0x10, 0x10,
+0xa4, 0x09, 0x68, 0x31, 0xcd, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x08, 0xd0,
+0x31, 0xba, 0xa4, 0x08, 0xe0, 0x31, 0xbc, 0x10, 0x10, 0xa4, 0x08, 0xd8,
+0x31, 0xbb, 0x10, 0x10, 0x90, 0xa8, 0x10, 0x10, 0x10, 0x10, 0x90, 0x50,
+0x90, 0x28, 0x80, 0x31, 0x8d, 0x80, 0x31, 0x8f, 0x10, 0x10, 0x80, 0x31,
+0x8e, 0x90, 0x60, 0x90, 0x30, 0x60, 0xa0, 0x2a, 0xc0, 0x60, 0xa0, 0x2a,
+0x80, 0x90, 0x30, 0x60, 0xa0, 0x2a, 0x40, 0x60, 0xa0, 0x2a, 0x00, 0x97,
+0xf0, 0x95, 0x60, 0x92, 0xb0, 0x91, 0x40, 0x90, 0x88, 0x90, 0x50, 0x90,
+0x28, 0x80, 0x31, 0x93, 0x80, 0x31, 0x95, 0x10, 0x10, 0x80, 0x31, 0x94,
+0x90, 0x70, 0x90, 0x38, 0xa4, 0x08, 0x28, 0x31, 0xa5, 0xa4, 0x08, 0x38,
+0x31, 0xa7, 0x10, 0x10, 0xa4, 0x08, 0x30, 0x31, 0xa6, 0x90, 0xb8, 0x90,
+0x70, 0x90, 0x38, 0xa4, 0x09, 0x48, 0x31, 0xc9, 0xa4, 0x09, 0x58, 0x31,
+0xcb, 0x10, 0x10, 0xa4, 0x09, 0x50, 0x31, 0xca, 0x90, 0x70, 0x90, 0x38,
+0xa4, 0x08, 0xb8, 0x31, 0xb7, 0xa4, 0x08, 0xc8, 0x31, 0xb9, 0x10, 0x10,
+0xa4, 0x08, 0xc0, 0x31, 0xb8, 0x91, 0x40, 0x90, 0x88, 0x90, 0x50, 0x90,
+0x28, 0x80, 0x31, 0x90, 0x80, 0x31, 0x92, 0x10, 0x10, 0x80, 0x31, 0x91,
+0x90, 0x70, 0x90, 0x38, 0xa4, 0x08, 0x10, 0x31, 0xa2, 0xa4, 0x08, 0x20,
+0x31, 0xa4, 0x10, 0x10, 0xa4, 0x08, 0x18, 0x31, 0xa3, 0x90, 0xb8, 0x90,
+0x70, 0x90, 0x38, 0xa4, 0x09, 0x30, 0x31, 0xc6, 0xa4, 0x09, 0x40, 0x31,
+0xc8, 0x10, 0x10, 0xa4, 0x09, 0x38, 0x31, 0xc7, 0x90, 0x70, 0x90, 0x38,
+0xa4, 0x08, 0xa0, 0x31, 0xb4, 0xa4, 0x08, 0xb0, 0x31, 0xb6, 0x10, 0x10,
+0xa4, 0x08, 0xa8, 0x31, 0xb5, 0x10, 0x10, 0x91, 0x40, 0x90, 0xa0, 0x90,
+0x50, 0x90, 0x28, 0x80, 0x30, 0xcb, 0x80, 0x30, 0xca, 0x90, 0x28, 0x80,
+0x30, 0xc9, 0x80, 0x30, 0xc8, 0x90, 0x50, 0x90, 0x28, 0x80, 0x30, 0xc4,
+0x80, 0x30, 0xc7, 0x90, 0x28, 0x80, 0x30, 0xc6, 0x80, 0x30, 0xc5, 0x90,
+0xa0, 0x90, 0x50, 0x90, 0x28, 0x80, 0x30, 0xbc, 0x80, 0x30, 0xc3, 0x90,
+0x28, 0x80, 0x30, 0xc2, 0x80, 0x30, 0xc1, 0x90, 0x50, 0x90, 0x28, 0x80,
+0x30, 0xbd, 0x80, 0x30, 0xc0, 0x90, 0x28, 0x80, 0x30, 0xbf, 0x80, 0x30,
+0xbe, 0x91, 0x88, 0x80, 0x90, 0xc0, 0x90, 0x60, 0x90, 0x28, 0x81, 0x31,
+0x3b, 0x10, 0x10, 0x80, 0x31, 0x3a, 0x90, 0x28, 0x81, 0x31, 0x3d, 0x10,
+0x10, 0x80, 0x31, 0x3c, 0x90, 0x60, 0x90, 0x28, 0x81, 0x31, 0x41, 0x10,
+0x10, 0x80, 0x31, 0x40, 0x90, 0x28, 0x81, 0x31, 0x3f, 0x10, 0x10, 0x80,
+0x31, 0x3e, 0x80, 0x10, 0x10, 0x10, 0x10, 0x90, 0x28, 0x81, 0x31, 0x38,
+0x10, 0x10, 0x80, 0x31, 0x39, 0xa0, 0x0b, 0x90, 0xa0, 0x0a, 0xc8, 0x95,
+0x60, 0x92, 0xb0, 0x91, 0x40, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80,
+0x31, 0x56, 0x80, 0x31, 0x55, 0x10, 0x10, 0x80, 0x31, 0x54, 0x90, 0x70,
+0x90, 0x38, 0xa4, 0x06, 0xe8, 0x31, 0x68, 0xa4, 0x06, 0xe0, 0x31, 0x67,
+0x10, 0x10, 0xa4, 0x06, 0xd8, 0x31, 0x66, 0x90, 0xb8, 0x90, 0x70, 0x90,
+0x38, 0xa4, 0x08, 0x08, 0x31, 0x8c, 0xa4, 0x08, 0x00, 0x31, 0x8b, 0x10,
+0x10, 0xa4, 0x07, 0xf8, 0x31, 0x8a, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x07,
+0x78, 0x31, 0x7a, 0xa4, 0x07, 0x70, 0x31, 0x79, 0x10, 0x10, 0xa4, 0x07,
+0x68, 0x31, 0x78, 0x91, 0x40, 0x90, 0x88, 0x90, 0x50, 0x90, 0x28, 0x80,
+0x31, 0x51, 0x80, 0x31, 0x53, 0x10, 0x10, 0x80, 0x31, 0x52, 0x90, 0x70,
+0x90, 0x38, 0xa4, 0x06, 0xc0, 0x31, 0x63, 0xa4, 0x06, 0xd0, 0x31, 0x65,
+0x10, 0x10, 0xa4, 0x06, 0xc8, 0x31, 0x64, 0x90, 0xb8, 0x90, 0x70, 0x90,
+0x38, 0xa4, 0x07, 0xe0, 0x31, 0x87, 0xa4, 0x07, 0xf0, 0x31, 0x89, 0x10,
+0x10, 0xa4, 0x07, 0xe8, 0x31, 0x88, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x07,
+0x50, 0x31, 0x75, 0xa4, 0x07, 0x60, 0x31, 0x77, 0x10, 0x10, 0xa4, 0x07,
+0x58, 0x31, 0x76, 0x92, 0xb0, 0x91, 0x40, 0x90, 0x88, 0x90, 0x50, 0x90,
+0x28, 0x80, 0x31, 0x4e, 0x80, 0x31, 0x50, 0x10, 0x10, 0x80, 0x31, 0x4f,
+0x90, 0x70, 0x90, 0x38, 0xa4, 0x06, 0xa8, 0x31, 0x60, 0xa4, 0x06, 0xb8,
+0x31, 0x62, 0x10, 0x10, 0xa4, 0x06, 0xb0, 0x31, 0x61, 0x90, 0xb8, 0x90,
+0x70, 0x90, 0x38, 0xa4, 0x07, 0xc8, 0x31, 0x84, 0xa4, 0x07, 0xd8, 0x31,
+0x86, 0x10, 0x10, 0xa4, 0x07, 0xd0, 0x31, 0x85, 0x90, 0x70, 0x90, 0x38,
+0xa4, 0x07, 0x38, 0x31, 0x72, 0xa4, 0x07, 0x48, 0x31, 0x74, 0x10, 0x10,
+0xa4, 0x07, 0x40, 0x31, 0x73, 0x91, 0x40, 0x90, 0x88, 0x90, 0x50, 0x90,
+0x28, 0x80, 0x31, 0x4b, 0x80, 0x31, 0x4d, 0x10, 0x10, 0x80, 0x31, 0x4c,
+0x90, 0x70, 0x90, 0x38, 0xa4, 0x06, 0x90, 0x31, 0x5d, 0xa4, 0x06, 0xa0,
+0x31, 0x5f, 0x10, 0x10, 0xa4, 0x06, 0x98, 0x31, 0x5e, 0x90, 0xb8, 0x90,
+0x70, 0x90, 0x38, 0xa4, 0x07, 0xb0, 0x31, 0x81, 0xa4, 0x07, 0xc0, 0x31,
+0x83, 0x10, 0x10, 0xa4, 0x07, 0xb8, 0x31, 0x82, 0x90, 0x70, 0x90, 0x38,
+0xa4, 0x07, 0x20, 0x31, 0x6f, 0xa4, 0x07, 0x30, 0x31, 0x71, 0x10, 0x10,
+0xa4, 0x07, 0x28, 0x31, 0x70, 0x10, 0x10, 0x80, 0x10, 0x10, 0x10, 0x10,
+0x90, 0x50, 0x90, 0x28, 0x80, 0x31, 0x42, 0x80, 0x31, 0x44, 0x10, 0x10,
+0x80, 0x31, 0x43, 0x80, 0x95, 0x60, 0x92, 0xb0, 0x91, 0x40, 0x90, 0x88,
+0x90, 0x50, 0x90, 0x28, 0x80, 0x31, 0x48, 0x80, 0x31, 0x4a, 0x10, 0x10,
+0x80, 0x31, 0x49, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x06, 0x78, 0x31, 0x5a,
+0xa4, 0x06, 0x88, 0x31, 0x5c, 0x10, 0x10, 0xa4, 0x06, 0x80, 0x31, 0x5b,
+0x90, 0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x07, 0x98, 0x31, 0x7e, 0xa4,
+0x07, 0xa8, 0x31, 0x80, 0x10, 0x10, 0xa4, 0x07, 0xa0, 0x31, 0x7f, 0x90,
+0x70, 0x90, 0x38, 0xa4, 0x07, 0x08, 0x31, 0x6c, 0xa4, 0x07, 0x18, 0x31,
+0x6e, 0x10, 0x10, 0xa4, 0x07, 0x10, 0x31, 0x6d, 0x91, 0x40, 0x90, 0x88,
+0x90, 0x50, 0x90, 0x28, 0x80, 0x31, 0x45, 0x80, 0x31, 0x47, 0x10, 0x10,
+0x80, 0x31, 0x46, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x06, 0x60, 0x31, 0x57,
+0xa4, 0x06, 0x70, 0x31, 0x59, 0x10, 0x10, 0xa4, 0x06, 0x68, 0x31, 0x58,
+0x90, 0xb8, 0x90, 0x70, 0x90, 0x38, 0xa4, 0x07, 0x80, 0x31, 0x7b, 0xa4,
+0x07, 0x90, 0x31, 0x7d, 0x10, 0x10, 0xa4, 0x07, 0x88, 0x31, 0x7c, 0x90,
+0x70, 0x90, 0x38, 0xa4, 0x06, 0xf0, 0x31, 0x69, 0xa4, 0x07, 0x00, 0x31,
+0x6b, 0x10, 0x10, 0xa4, 0x06, 0xf8, 0x31, 0x6a, 0x10, 0x10, 0x91, 0x40,
+0x90, 0xa0, 0x90, 0x50, 0x90, 0x28, 0x80, 0x30, 0xbb, 0x80, 0x30, 0xba,
+0x90, 0x28, 0x80, 0x30, 0xb9, 0x80, 0x30, 0xb8, 0x90, 0x50, 0x90, 0x28,
+0x80, 0x30, 0xb4, 0x80, 0x30, 0xb7, 0x90, 0x28, 0x80, 0x30, 0xb6, 0x80,
+0x30, 0xb5, 0x90, 0xa0, 0x90, 0x50, 0x90, 0x28, 0x80, 0x30, 0xac, 0x80,
+0x30, 0xb3, 0x90, 0x28, 0x80, 0x30, 0xb2, 0x80, 0x30, 0xb1, 0x90, 0x50,
+0x90, 0x28, 0x80, 0x30, 0xad, 0x80, 0x30, 0xb0, 0x90, 0x28, 0x80, 0x30,
+0xaf, 0x80, 0x30, 0xae, 0xc3, 0xc0, 0x30, 0x42, 0x9c, 0xe8, 0x07, 0x60,
+0x91, 0x90, 0x90, 0xf0, 0x10, 0x10, 0x80, 0x88, 0x00, 0x80, 0x90, 0x50,
+0x90, 0x28, 0x80, 0x33, 0xf8, 0x80, 0x33, 0xf9, 0x81, 0x33, 0xef, 0xd0,
+0x41, 0x80, 0x24, 0x20, 0x90, 0x24, 0x20, 0x98, 0x10, 0x10, 0x80, 0x90,
+0x58, 0x80, 0x90, 0x28, 0x24, 0x1f, 0x90, 0x24, 0x1f, 0x98, 0x81, 0x24,
+0x1f, 0x50, 0x92, 0x68, 0x91, 0x00, 0x80, 0x90, 0x90, 0x90, 0x30, 0x80,
+0x24, 0x20, 0x00, 0x90, 0x38, 0xa4, 0x1f, 0xf8, 0x34, 0x06, 0x80, 0x34,
+0x05, 0x80, 0x90, 0x28, 0x80, 0x34, 0x0f, 0xa4, 0x1f, 0xe0, 0x34, 0x0e,
+0x80, 0x90, 0xc0, 0x90, 0x60, 0x90, 0x28, 0x80, 0x34, 0x09, 0xa4, 0x1f,
+0xf0, 0x34, 0x08, 0x90, 0x28, 0x80, 0x34, 0x04, 0xa4, 0x1f, 0xe8, 0x34,
+0x03, 0x90, 0x50, 0x90, 0x28, 0x80, 0x34, 0x0d, 0x80, 0x34, 0x0c, 0x90,
+0x28, 0x24, 0x20, 0x88, 0x24, 0x20, 0x80, 0x90, 0x58, 0x80, 0x10, 0x10,
+0x80, 0x10, 0x10, 0x80, 0x33, 0xfb, 0x80, 0x90, 0x40, 0x10, 0x10, 0x80,
+0x24, 0x1f, 0x60, 0x80, 0x10, 0x10, 0x80, 0x33, 0xfa, 0x91, 0x58, 0x91,
+0x00, 0x90, 0x80, 0x81, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33, 0xf6, 0x80,
+0x33, 0xf7, 0x81, 0x33, 0xee, 0x81, 0x90, 0x50, 0x90, 0x28, 0x80, 0x33,
+0xf4, 0x80, 0x33, 0xf5, 0x81, 0x33, 0xed, 0x83, 0x90, 0x28, 0x24, 0x1f,
+0x80, 0x24, 0x1f, 0x88, 0x90, 0xe8, 0x81, 0x90, 0x88, 0x90, 0x38, 0x10,
+0x10, 0x80, 0x34, 0x07, 0x90, 0x28, 0x80, 0x34, 0x02, 0x80, 0x34, 0x01,
+0x80, 0x90, 0x28, 0x80, 0x34, 0x0b, 0x80, 0x34, 0x0a, 0x82, 0x10, 0x10,
+0x80, 0x24, 0x1f, 0x58, 0x97, 0x10, 0x9e, 0x10, 0x06, 0x98, 0x93, 0x00,
+0x91, 0x80, 0x90, 0xc0, 0x90, 0x60, 0x90, 0x38, 0xa4, 0x03, 0x80, 0x30,
+0x71, 0x24, 0x03, 0x78, 0x90, 0x38, 0xa4, 0x04, 0x10, 0x30, 0x83, 0x24,
+0x04, 0x08, 0x90, 0x60, 0x90, 0x38, 0xa4, 0x05, 0x30, 0x30, 0xa7, 0x24,
+0x05, 0x28, 0x90, 0x38, 0xa4, 0x04, 0xa0, 0x30, 0x95, 0x24, 0x04, 0x98,
+0x90, 0xc0, 0x90, 0x60, 0x90, 0x38, 0xa4, 0x03, 0x70, 0x30, 0x6c, 0x24,
+0x03, 0x68, 0x90, 0x38, 0xa4, 0x04, 0x00, 0x30, 0x7e, 0x24, 0x03, 0xf8,
+0x90, 0x60, 0x90, 0x38, 0xa4, 0x05, 0x20, 0x30, 0xa2, 0x24, 0x05, 0x18,
+0x90, 0x38, 0xa4, 0x04, 0x90, 0x30, 0x90, 0x24, 0x04, 0x88, 0x91, 0x80,
+0x90, 0xc0, 0x90, 0x60, 0x90, 0x38, 0xa4, 0x03, 0x58, 0x30, 0x69, 0x24,
+0x03, 0x50, 0x90, 0x38, 0xa4, 0x03, 0xe8, 0x30, 0x7b, 0x24, 0x03, 0xe0,
+0x90, 0x60, 0x90, 0x38, 0xa4, 0x05, 0x08, 0x30, 0x9f, 0x24, 0x05, 0x00,
+0x90, 0x38, 0xa4, 0x04, 0x78, 0x30, 0x8d, 0x24, 0x04, 0x70, 0x90, 0xc0,
+0x90, 0x60, 0x90, 0x38, 0xa4, 0x03, 0x40, 0x30, 0x66, 0x24, 0x03, 0x38,
+0x90, 0x38, 0xa4, 0x03, 0xd0, 0x30, 0x78, 0x24, 0x03, 0xc8, 0x90, 0x60,
+0x90, 0x38, 0xa4, 0x04, 0xf0, 0x30, 0x9c, 0x24, 0x04, 0xe8, 0x90, 0x38,
+0xa4, 0x04, 0x60, 0x30, 0x8a, 0x24, 0x04, 0x58, 0x10, 0x10, 0x80, 0x10,
+0x10, 0x10, 0x10, 0x90, 0x38, 0xa4, 0x02, 0xf8, 0x30, 0x5d, 0x24, 0x02,
+0xf0, 0xd7, 0x42, 0x00, 0xa4, 0x38, 0x58, 0x37, 0x0d, 0xa4, 0x38, 0x38,
+0x37, 0x09, 0x9c, 0xe0, 0x06, 0x90, 0x93, 0x00, 0x91, 0x80, 0x90, 0xc0,
+0x90, 0x60, 0x90, 0x38, 0xa4, 0x03, 0x28, 0x30, 0x63, 0x24, 0x03, 0x20,
+0x90, 0x38, 0xa4, 0x03, 0xb8, 0x30, 0x75, 0x24, 0x03, 0xb0, 0x90, 0x60,
+0x90, 0x38, 0xa4, 0x04, 0xd8, 0x30, 0x99, 0x24, 0x04, 0xd0, 0x90, 0x38,
+0xa4, 0x04, 0x48, 0x30, 0x87, 0x24, 0x04, 0x40, 0x90, 0xc0, 0x90, 0x60,
+0x90, 0x38, 0xa4, 0x03, 0x10, 0x30, 0x60, 0x24, 0x03, 0x08, 0x90, 0x38,
+0xa4, 0x03, 0xa0, 0x30, 0x72, 0x24, 0x03, 0x98, 0x90, 0x60, 0x90, 0x38,
+0xa4, 0x04, 0xc0, 0x30, 0x96, 0x24, 0x04, 0xb8, 0x90, 0x38, 0xa4, 0x04,
+0x30, 0x30, 0x84, 0x24, 0x04, 0x28, 0x10, 0x10, 0x90, 0xe0, 0x90, 0x70,
+0x90, 0x38, 0xa4, 0x02, 0x88, 0x30, 0x52, 0xa4, 0x02, 0x78, 0x30, 0x50,
+0x90, 0x38, 0xa4, 0x02, 0x70, 0x30, 0x4b, 0xa4, 0x02, 0x60, 0x30, 0x4d,
+0x90, 0x70, 0x90, 0x38, 0xa4, 0x02, 0x50, 0x30, 0x43, 0xa4, 0x02, 0x40,
+0x30, 0x49, 0x90, 0x38, 0xa4, 0x02, 0x38, 0x30, 0x44, 0xa4, 0x02, 0x28,
+0x30, 0x46, 0x91, 0x48, 0x80, 0x90, 0xa0, 0x90, 0x50, 0x90, 0x28, 0x80,
+0x30, 0x56, 0x24, 0x02, 0xa8, 0x90, 0x28, 0x80, 0x30, 0x58, 0x24, 0x02,
+0xb8, 0x90, 0x50, 0x90, 0x28, 0x80, 0x30, 0x5c, 0x24, 0x02, 0xd8, 0x90,
+0x28, 0x80, 0x30, 0x5a, 0x24, 0x02, 0xc8, 0x80, 0x10, 0x10, 0x10, 0x10,
+0x90, 0x28, 0x80, 0x30, 0x53, 0x24, 0x02, 0xa0, 0xd7, 0x42, 0x00, 0xa4,
+0x38, 0x60, 0x37, 0x0e, 0xa4, 0x38, 0x40, 0x37, 0x0a, 0xa0, 0x14, 0x68,
+0xa0, 0x10, 0x90, 0xa0, 0x0c, 0x60, 0x9e, 0x88, 0x09, 0xd0, 0x94, 0xf0,
+0x90, 0xb0, 0x88, 0x00, 0x68, 0x84, 0x10, 0x10, 0xc9, 0xe1, 0x44, 0x40,
+0x85, 0x35, 0x2d, 0xcb, 0x61, 0x3d, 0x00, 0x85, 0x35, 0x03, 0x9a, 0x00,
+0x03, 0xf8, 0x91, 0x98, 0x80, 0x91, 0x10, 0x90, 0xa0, 0x90, 0x68, 0x90,
+0x20, 0x3a, 0x53, 0xc9, 0xe2, 0x94, 0x40, 0x85, 0x35, 0x2b, 0xa4, 0x52,
+0x78, 0x3a, 0x50, 0x90, 0x38, 0xa4, 0x52, 0x40, 0x3a, 0x49, 0xa4, 0x52,
+0x30, 0x3a, 0x47, 0x90, 0x48, 0x10, 0x10, 0xa4, 0x51, 0xf8, 0x3a, 0x40,
+0x10, 0x10, 0x80, 0x3a, 0x3c, 0x81, 0x10, 0x10, 0x80, 0xa4, 0x51, 0xc8,
+0x3a, 0x3a, 0x91, 0xb0, 0x91, 0x60, 0x90, 0xe0, 0x90, 0x70, 0x90, 0x38,
+0xa4, 0x52, 0x68, 0x3a, 0x4e, 0xa4, 0x52, 0x58, 0x3a, 0x4c, 0x90, 0x38,
+0xa4, 0x52, 0x20, 0x3a, 0x45, 0xa4, 0x52, 0x10, 0x3a, 0x43, 0x90, 0x48,
+0x10, 0x10, 0xa4, 0x51, 0xe8, 0x3a, 0x3e, 0x10, 0x10, 0x80, 0x3a, 0x3b,
+0x90, 0x28, 0x80, 0x3a, 0x34, 0x80, 0x3a, 0x33, 0x81, 0x10, 0x10, 0x80,
+0xa4, 0x51, 0xb8, 0x3a, 0x38, 0xcb, 0x61, 0x3c, 0xc0, 0x85, 0x35, 0x02,
+0x90, 0xd8, 0x88, 0x00, 0x90, 0x84, 0x90, 0x38, 0xc1, 0xc0, 0x85, 0x3a,
+0x56, 0xc9, 0xe1, 0x44, 0x00, 0x85, 0x35, 0x29, 0xcb, 0x61, 0x3c, 0x80,
+0x85, 0x35, 0x01, 0x88, 0x00, 0x68, 0x84, 0x10, 0x10, 0xc9, 0xe1, 0x43,
+0xc0, 0x85, 0x35, 0x27, 0xcb, 0x61, 0x3c, 0x40, 0x85, 0x35, 0x00, 0x91,
+0xf8, 0x90, 0xb0, 0x88, 0x00, 0x68, 0x84, 0x10, 0x10, 0xc9, 0xe1, 0x43,
+0x40, 0x85, 0x35, 0x23, 0xcb, 0x61, 0x3b, 0xc0, 0x85, 0x34, 0xfe, 0x88,
+0x01, 0x00, 0x90, 0xa0, 0x81, 0x90, 0x70, 0x80, 0x90, 0x20, 0x3a, 0x4a,
+0xc9, 0xe1, 0x43, 0x00, 0x85, 0x35, 0x21, 0x81, 0x3a, 0x41, 0x81, 0x10,
+0x10, 0x80, 0xa4, 0x51, 0xa8, 0x3a, 0x36, 0xcb, 0x61, 0x3b, 0x80, 0x85,
+0x34, 0xfd, 0x90, 0xb0, 0x88, 0x00, 0x68, 0x84, 0x10, 0x10, 0xc9, 0xe1,
+0x42, 0xc0, 0x85, 0x35, 0x1f, 0xcb, 0x61, 0x3b, 0x40, 0x85, 0x34, 0xfc,
+0x88, 0x00, 0x68, 0x84, 0x10, 0x10, 0xc9, 0xe1, 0x42, 0x80, 0x85, 0x35,
+0x1d, 0xcb, 0x61, 0x3b, 0x00, 0x85, 0x34, 0xfb, 0x92, 0x38, 0x81, 0x91,
+0x68, 0x91, 0x18, 0x90, 0x80, 0x90, 0x40, 0x80, 0xa4, 0x53, 0x28, 0x3a,
+0x66, 0x80, 0xa4, 0x53, 0x20, 0x3a, 0x63, 0x90, 0x28, 0x81, 0x3a, 0x62,
+0x90, 0x38, 0xa4, 0x53, 0x00, 0x3a, 0x61, 0xa4, 0x52, 0xf0, 0x3a, 0x5f,
+0x90, 0x28, 0x80, 0x3a, 0x5d, 0x80, 0x3a, 0x5c, 0x80, 0x90, 0x40, 0x10,
+0x10, 0x80, 0x24, 0x52, 0xd8, 0x10, 0x10, 0x90, 0x38, 0xa4, 0x52, 0xc8,
+0x3a, 0x5a, 0xa4, 0x52, 0xb8, 0x3a, 0x58, 0x90, 0x28, 0x80, 0x3a, 0x55,
+0x80, 0x3a, 0x54, 0x9a, 0xd0, 0x03, 0xe0, 0x91, 0x60, 0x90, 0xb0, 0x88,
+0x00, 0x68, 0x84, 0x10, 0x10, 0xc9, 0xe1, 0x42, 0x00, 0x85, 0x35, 0x19,
+0xcb, 0x61, 0x3a, 0x80, 0x85, 0x34, 0xf9, 0x88, 0x00, 0x68, 0x84, 0x10,
+0x10, 0xc9, 0xe1, 0x41, 0xc0, 0x85, 0x35, 0x17, 0xcb, 0x61, 0x3a, 0x40,
+0x85, 0x34, 0xf8, 0x90, 0xb0, 0x88, 0x00, 0x68, 0x84, 0x10, 0x10, 0xc9,
+0xe1, 0x41, 0x80, 0x85, 0x35, 0x15, 0xcb, 0x61, 0x3a, 0x00, 0x85, 0x34,
+0xf7, 0x88, 0x00, 0x68, 0x84, 0x10, 0x10, 0xc9, 0xe1, 0x41, 0x40, 0x85,
+0x35, 0x13, 0xcb, 0x61, 0x39, 0xc0, 0x85, 0x34, 0xf6, 0x90, 0x90, 0x90,
+0x48, 0xcb, 0xa1, 0x38, 0x00, 0x85, 0x34, 0xe5, 0xcb, 0xa1, 0x37, 0xc0,
+0x85, 0x34, 0xe4, 0x90, 0x48, 0xcb, 0xa1, 0x37, 0x80, 0x85, 0x34, 0xe3,
+0xcb, 0xa1, 0x37, 0x40, 0x85, 0x34, 0xe2, 0xcb, 0xa2, 0x8c, 0x40, 0x80,
+0x3a, 0x32, 0x92, 0x40, 0x91, 0x20, 0x90, 0x90, 0x90, 0x48, 0x8c, 0x26,
+0x60, 0x84, 0x24, 0x26, 0xd8, 0x8c, 0x26, 0x58, 0x84, 0x24, 0x26, 0xd0,
+0x90, 0x48, 0x8c, 0x26, 0x50, 0x84, 0x24, 0x26, 0xc8, 0x8c, 0x26, 0x48,
+0x84, 0x24, 0x26, 0xc0, 0x90, 0x90, 0x90, 0x48, 0x8c, 0x26, 0x38, 0x84,
+0x24, 0x26, 0xb0, 0x8c, 0x26, 0x30, 0x84, 0x24, 0x26, 0xa8, 0x90, 0x48,
+0x8c, 0x26, 0x28, 0x84, 0x24, 0x26, 0xa0, 0x8c, 0x26, 0x20, 0x84, 0x24,
+0x26, 0x98, 0x91, 0x20, 0x90, 0x90, 0x90, 0x48, 0x8c, 0x26, 0x10, 0x84,
+0x24, 0x26, 0x88, 0x8c, 0x26, 0x08, 0x84, 0x24, 0x26, 0x80, 0x90, 0x48,
+0x8c, 0x26, 0x00, 0x84, 0x24, 0x26, 0x78, 0x8c, 0x25, 0xf8, 0x84, 0x24,
+0x26, 0x70, 0x90, 0x38, 0xa4, 0x25, 0xe0, 0x34, 0xbd, 0xa4, 0x25, 0xd0,
+0x34, 0xbb, 0xa0, 0x0f, 0x50, 0xa0, 0x09, 0x08, 0x9a, 0x30, 0x04, 0x40,
+0x91, 0x90, 0x90, 0xc8, 0x98, 0x50, 0x00, 0x80, 0xe5, 0x22, 0x8a, 0x40,
+0x3a, 0x21, 0xe5, 0x22, 0x82, 0x40, 0x3a, 0x1d, 0xcb, 0x61, 0x2a, 0x40,
+0x85, 0x34, 0xb8, 0x98, 0x50, 0x00, 0x80, 0xe5, 0x22, 0x7a, 0x40, 0x39,
+0xe1, 0xe5, 0x22, 0x72, 0x40, 0x39, 0xdd, 0xcb, 0x61, 0x2a, 0x00, 0x85,
+0x34, 0xb7, 0x90, 0x48, 0xcb, 0xa1, 0x29, 0xc0, 0x85, 0x34, 0xb6, 0xcb,
+0xa1, 0x29, 0x80, 0x85, 0x34, 0xb5, 0x91, 0x90, 0x90, 0xc8, 0x98, 0x50,
+0x00, 0x80, 0xe5, 0x22, 0x64, 0x40, 0x39, 0xa9, 0xe5, 0x22, 0x58, 0x40,
+0x39, 0x79, 0xcb, 0x61, 0x29, 0x00, 0x85, 0x34, 0xb3, 0x98, 0x50, 0x00,
+0x80, 0xe5, 0x22, 0x4c, 0x40, 0x39, 0x49, 0xe5, 0x22, 0x40, 0x40, 0x39,
+0x19, 0xcb, 0x61, 0x28, 0xc0, 0x85, 0x34, 0xb2, 0x90, 0x48, 0xcb, 0xa1,
+0x28, 0x80, 0x85, 0x34, 0xb1, 0xcb, 0xa1, 0x28, 0x40, 0x85, 0x34, 0xb0,
+0x92, 0x20, 0x91, 0x30, 0x90, 0xb8, 0xd5, 0x03, 0x00, 0xc0, 0xc0, 0x81,
+0x8c, 0x01, 0xa0, 0x84, 0x30, 0x3e, 0xc0, 0xc0, 0x81, 0x8c, 0x01, 0x80,
+0x84, 0x30, 0x3c, 0xd5, 0x02, 0x00, 0xc0, 0xc0, 0x81, 0x30, 0x28, 0xc0,
+0xc0, 0x81, 0x30, 0x24, 0x90, 0x78, 0xd5, 0x02, 0x00, 0xc0, 0xc0, 0x81,
+0x30, 0x1c, 0xc0, 0xc0, 0x81, 0x30, 0x18, 0xd5, 0x02, 0x00, 0xc0, 0xc0,
+0x81, 0x30, 0x10, 0xc0, 0xc0, 0x81, 0x30, 0x0c, 0x91, 0x70, 0x90, 0xd8,
+0xd5, 0x03, 0x80, 0xc8, 0xe2, 0x38, 0x40, 0x81, 0x8c, 0x01, 0xc0, 0x84,
+0x30, 0x40, 0xc8, 0xe2, 0x3a, 0x40, 0x81, 0x8c, 0x01, 0x90, 0x84, 0x30,
+0x3d, 0xd5, 0x02, 0x80, 0xc8, 0xe2, 0x37, 0x40, 0x81, 0x30, 0x2c, 0xc8,
+0xe2, 0x31, 0xc0, 0x81, 0x30, 0x26, 0x90, 0x98, 0xd5, 0x02, 0x80, 0xc8,
+0xe2, 0x26, 0xc0, 0x81, 0x30, 0x20, 0xc8, 0xe2, 0x28, 0xc0, 0x81, 0x30,
+0x1a, 0xd5, 0x02, 0x80, 0xc8, 0xe2, 0x25, 0xc0, 0x81, 0x30, 0x14, 0xc8,
+0xe2, 0x20, 0x40, 0x81, 0x30, 0x0e, 0x9a, 0x30, 0x04, 0x40, 0x91, 0x90,
+0x90, 0xc8, 0x98, 0x50, 0x00, 0x80, 0xe5, 0x22, 0x7e, 0x40, 0x39, 0xf1,
+0xe5, 0x22, 0x80, 0x40, 0x3a, 0x15, 0xcb, 0x61, 0x27, 0xc0, 0x85, 0x34,
+0xae, 0x98, 0x50, 0x00, 0x80, 0xe5, 0x22, 0x6e, 0x40, 0x39, 0xb1, 0xe5,
+0x22, 0x70, 0x40, 0x39, 0xd5, 0xcb, 0x61, 0x27, 0x80, 0x85, 0x34, 0xad,
+0x90, 0x48, 0xcb, 0xa1, 0x27, 0x40, 0x85, 0x34, 0xac, 0xcb, 0xa1, 0x27,
+0x00, 0x85, 0x34, 0xab, 0x91, 0x90, 0x90, 0xc8, 0x98, 0x50, 0x00, 0x80,
+0xe5, 0x22, 0x60, 0x40, 0x39, 0x99, 0xe5, 0x22, 0x54, 0x40, 0x39, 0x69,
+0xcb, 0x61, 0x25, 0x40, 0x85, 0x34, 0x9a, 0x98, 0x50, 0x00, 0x80, 0xe5,
+0x22, 0x48, 0x40, 0x39, 0x39, 0xe5, 0x22, 0x3c, 0x40, 0x39, 0x09, 0xcb,
+0x61, 0x25, 0x00, 0x85, 0x34, 0x99, 0x90, 0x48, 0xcb, 0xa1, 0x24, 0xc0,
+0x85, 0x34, 0x98, 0xcb, 0xa1, 0x24, 0x80, 0x85, 0x34, 0x97, 0x91, 0x00,
+0x90, 0x80, 0x90, 0x40, 0xe5, 0x20, 0x02, 0x40, 0x30, 0x0a, 0xe5, 0x20,
+0x01, 0x80, 0x30, 0x07, 0x90, 0x40, 0xe5, 0x20, 0x00, 0xc0, 0x30, 0x04,
+0xe5, 0x20, 0x00, 0x00, 0x30, 0x01, 0x90, 0x80, 0x90, 0x40, 0xe5, 0x22,
+0x2d, 0x40, 0x38, 0xab, 0xe5, 0x22, 0x2f, 0x80, 0x38, 0xd3, 0x90, 0x40,
+0xe5, 0x22, 0x1b, 0xc0, 0x38, 0x65, 0xe5, 0x22, 0x1e, 0x00, 0x38, 0x8d,
+0x80, 0x99, 0x28, 0x02, 0xf0, 0x8c, 0x24, 0x48, 0x90, 0x80, 0x90, 0x40,
+0xe5, 0x22, 0x84, 0x40, 0x3a, 0x0d, 0xe5, 0x22, 0x81, 0x40, 0x3a, 0x19,
+0x90, 0x40, 0xe5, 0x22, 0x74, 0x40, 0x39, 0xcd, 0xe5, 0x22, 0x71, 0x40,
+0x39, 0xd9, 0x91, 0x48, 0x90, 0xc8, 0x98, 0x50, 0x00, 0x80, 0xe5, 0x22,
+0x62, 0x40, 0x39, 0xa1, 0xe5, 0x22, 0x56, 0x40, 0x39, 0x71, 0xcb, 0x61,
+0x23, 0x00, 0x85, 0x34, 0x90, 0x90, 0x40, 0xe5, 0x22, 0x4a, 0x40, 0x39,
+0x41, 0xe5, 0x22, 0x3e, 0x40, 0x39, 0x11, 0x90, 0x48, 0xcb, 0xa1, 0x22,
+0x80, 0x85, 0x34, 0x8e, 0xcb, 0xa1, 0x22, 0xc0, 0x85, 0x34, 0x8f, 0x10,
+0x10, 0x90, 0x80, 0x90, 0x40, 0xe5, 0x22, 0x33, 0xc0, 0x38, 0xcb, 0xe5,
+0x22, 0x30, 0xc0, 0x38, 0xd9, 0x90, 0x40, 0xe5, 0x22, 0x22, 0x40, 0x38,
+0x85, 0xe5, 0x22, 0x1f, 0x40, 0x38, 0x93,
+};
+
+static const struct ia64_dis_names ia64_dis_names[] = {
+{ 0x51, 41, 0, 10 },
+{ 0x31, 41, 1, 20 },
+{ 0x11, 42, 0, 19 },
+{ 0x29, 41, 0, 12 },
+{ 0x19, 41, 1, 24 },
+{ 0x9, 42, 0, 23 },
+{ 0x15, 41, 0, 14 },
+{ 0xd, 41, 1, 28 },
+{ 0x5, 42, 0, 27 },
+{ 0xb, 41, 0, 16 },
+{ 0x7, 41, 1, 32 },
+{ 0x3, 42, 0, 31 },
+{ 0x51, 39, 1, 58 },
+{ 0x50, 39, 0, 34 },
+{ 0xd1, 39, 1, 57 },
+{ 0xd0, 39, 0, 33 },
+{ 0x31, 39, 1, 68 },
+{ 0x30, 39, 1, 44 },
+{ 0x11, 40, 1, 67 },
+{ 0x10, 40, 0, 43 },
+{ 0x71, 39, 1, 66 },
+{ 0x70, 39, 1, 42 },
+{ 0x31, 40, 1, 65 },
+{ 0x30, 40, 0, 41 },
+{ 0x29, 39, 1, 60 },
+{ 0x28, 39, 0, 36 },
+{ 0x69, 39, 1, 59 },
+{ 0x68, 39, 0, 35 },
+{ 0x19, 39, 1, 72 },
+{ 0x18, 39, 1, 48 },
+{ 0x9, 40, 1, 71 },
+{ 0x8, 40, 0, 47 },
+{ 0x39, 39, 1, 70 },
+{ 0x38, 39, 1, 46 },
+{ 0x19, 40, 1, 69 },
+{ 0x18, 40, 0, 45 },
+{ 0x15, 39, 1, 62 },
+{ 0x14, 39, 0, 38 },
+{ 0x35, 39, 1, 61 },
+{ 0x34, 39, 0, 37 },
+{ 0xd, 39, 1, 76 },
+{ 0xc, 39, 1, 52 },
+{ 0x5, 40, 1, 75 },
+{ 0x4, 40, 0, 51 },
+{ 0x1d, 39, 1, 74 },
+{ 0x1c, 39, 1, 50 },
+{ 0xd, 40, 1, 73 },
+{ 0xc, 40, 0, 49 },
+{ 0xb, 39, 1, 64 },
+{ 0xa, 39, 0, 40 },
+{ 0x1b, 39, 1, 63 },
+{ 0x1a, 39, 0, 39 },
+{ 0x7, 39, 1, 80 },
+{ 0x6, 39, 1, 56 },
+{ 0x3, 40, 1, 79 },
+{ 0x2, 40, 0, 55 },
+{ 0xf, 39, 1, 78 },
+{ 0xe, 39, 1, 54 },
+{ 0x7, 40, 1, 77 },
+{ 0x6, 40, 0, 53 },
+{ 0x8, 38, 0, 82 },
+{ 0x18, 38, 0, 81 },
+{ 0x1, 38, 1, 86 },
+{ 0x2, 38, 0, 85 },
+{ 0x3, 38, 1, 84 },
+{ 0x4, 38, 0, 83 },
+{ 0x1, 336, 0, 87 },
+{ 0x20, 289, 0, 98 },
+{ 0x220, 289, 0, 94 },
+{ 0x1220, 289, 0, 91 },
+{ 0xa20, 289, 0, 92 },
+{ 0x620, 289, 0, 93 },
+{ 0x120, 289, 0, 95 },
+{ 0xa0, 289, 0, 96 },
+{ 0x60, 289, 0, 97 },
+{ 0x10, 289, 0, 102 },
+{ 0x90, 289, 0, 99 },
+{ 0x50, 289, 0, 100 },
+{ 0x30, 289, 0, 101 },
+{ 0x8, 289, 0, 103 },
+{ 0x4, 289, 0, 104 },
+{ 0x2, 289, 0, 105 },
+{ 0x1, 289, 0, 106 },
+{ 0x1, 411, 0, 108 },
+{ 0x3, 411, 0, 107 },
+{ 0x2, 417, 0, 109 },
+{ 0x1, 417, 0, 110 },
+{ 0x2, 413, 0, 111 },
+{ 0x1, 413, 0, 112 },
+{ 0x2, 415, 0, 113 },
+{ 0x1, 415, 0, 114 },
+{ 0x2, 419, 0, 115 },
+{ 0x1, 419, 0, 116 },
+{ 0x1, 268, 0, 143 },
+{ 0x5, 268, 0, 141 },
+{ 0x3, 268, 0, 142 },
+{ 0x140, 277, 0, 119 },
+{ 0x540, 277, 0, 117 },
+{ 0x340, 277, 0, 118 },
+{ 0xc0, 277, 0, 131 },
+{ 0x2c0, 277, 0, 129 },
+{ 0x1c0, 277, 0, 130 },
+{ 0x20, 277, 0, 146 },
+{ 0xa0, 277, 0, 144 },
+{ 0x60, 277, 0, 145 },
+{ 0x10, 277, 0, 158 },
+{ 0x50, 277, 0, 156 },
+{ 0x30, 277, 0, 157 },
+{ 0x8, 277, 0, 170 },
+{ 0x28, 277, 0, 168 },
+{ 0x18, 277, 0, 169 },
+{ 0x4, 277, 0, 180 },
+{ 0x2, 277, 0, 181 },
+{ 0x1, 277, 0, 182 },
+{ 0x140, 271, 0, 122 },
+{ 0x540, 271, 0, 120 },
+{ 0x340, 271, 0, 121 },
+{ 0xc0, 271, 0, 134 },
+{ 0x2c0, 271, 0, 132 },
+{ 0x1c0, 271, 0, 133 },
+{ 0x20, 271, 0, 149 },
+{ 0xa0, 271, 0, 147 },
+{ 0x60, 271, 0, 148 },
+{ 0x10, 271, 0, 161 },
+{ 0x50, 271, 0, 159 },
+{ 0x30, 271, 0, 160 },
+{ 0x8, 271, 0, 173 },
+{ 0x28, 271, 0, 171 },
+{ 0x18, 271, 0, 172 },
+{ 0x4, 271, 0, 183 },
+{ 0x2, 271, 0, 184 },
+{ 0x1, 271, 0, 185 },
+{ 0x140, 274, 0, 125 },
+{ 0x540, 274, 0, 123 },
+{ 0x340, 274, 0, 124 },
+{ 0xc0, 274, 0, 137 },
+{ 0x2c0, 274, 0, 135 },
+{ 0x1c0, 274, 0, 136 },
+{ 0x20, 274, 0, 152 },
+{ 0xa0, 274, 0, 150 },
+{ 0x60, 274, 0, 151 },
+{ 0x10, 274, 0, 164 },
+{ 0x50, 274, 0, 162 },
+{ 0x30, 274, 0, 163 },
+{ 0x8, 274, 0, 176 },
+{ 0x28, 274, 0, 174 },
+{ 0x18, 274, 0, 175 },
+{ 0x4, 274, 0, 186 },
+{ 0x2, 274, 0, 187 },
+{ 0x1, 274, 0, 188 },
+{ 0x140, 286, 0, 128 },
+{ 0x540, 286, 0, 126 },
+{ 0x340, 286, 0, 127 },
+{ 0xc0, 286, 0, 140 },
+{ 0x2c0, 286, 0, 138 },
+{ 0x1c0, 286, 0, 139 },
+{ 0x20, 286, 0, 155 },
+{ 0xa0, 286, 0, 153 },
+{ 0x60, 286, 0, 154 },
+{ 0x10, 286, 0, 167 },
+{ 0x50, 286, 0, 165 },
+{ 0x30, 286, 0, 166 },
+{ 0x8, 286, 0, 179 },
+{ 0x28, 286, 0, 177 },
+{ 0x18, 286, 0, 178 },
+{ 0x4, 286, 0, 189 },
+{ 0x2, 286, 0, 190 },
+{ 0x1, 286, 0, 191 },
+{ 0x8, 390, 0, 192 },
+{ 0x4, 390, 0, 193 },
+{ 0x2, 390, 0, 194 },
+{ 0x1, 390, 0, 195 },
+{ 0x20, 288, 0, 203 },
+{ 0x220, 288, 0, 199 },
+{ 0x1220, 288, 0, 196 },
+{ 0xa20, 288, 0, 197 },
+{ 0x620, 288, 0, 198 },
+{ 0x120, 288, 0, 200 },
+{ 0xa0, 288, 0, 201 },
+{ 0x60, 288, 0, 202 },
+{ 0x10, 288, 0, 207 },
+{ 0x90, 288, 0, 204 },
+{ 0x50, 288, 0, 205 },
+{ 0x30, 288, 0, 206 },
+{ 0x8, 288, 0, 208 },
+{ 0x4, 288, 0, 209 },
+{ 0x2, 288, 0, 210 },
+{ 0x1, 288, 0, 211 },
+{ 0x20, 287, 0, 219 },
+{ 0x220, 287, 0, 215 },
+{ 0x1220, 287, 0, 212 },
+{ 0xa20, 287, 0, 213 },
+{ 0x620, 287, 0, 214 },
+{ 0x120, 287, 0, 216 },
+{ 0xa0, 287, 0, 217 },
+{ 0x60, 287, 0, 218 },
+{ 0x10, 287, 0, 223 },
+{ 0x90, 287, 0, 220 },
+{ 0x50, 287, 0, 221 },
+{ 0x30, 287, 0, 222 },
+{ 0x8, 287, 0, 224 },
+{ 0x4, 287, 0, 225 },
+{ 0x2, 287, 0, 226 },
+{ 0x1, 287, 0, 227 },
+{ 0x140, 279, 0, 230 },
+{ 0x540, 279, 0, 228 },
+{ 0x340, 279, 0, 229 },
+{ 0xc0, 279, 0, 239 },
+{ 0x2c0, 279, 0, 237 },
+{ 0x1c0, 279, 0, 238 },
+{ 0x20, 279, 0, 248 },
+{ 0xa0, 279, 0, 246 },
+{ 0x60, 279, 0, 247 },
+{ 0x10, 279, 0, 257 },
+{ 0x50, 279, 0, 255 },
+{ 0x30, 279, 0, 256 },
+{ 0x8, 279, 0, 266 },
+{ 0x28, 279, 0, 264 },
+{ 0x18, 279, 0, 265 },
+{ 0x4, 279, 0, 273 },
+{ 0x2, 279, 0, 274 },
+{ 0x1, 279, 0, 275 },
+{ 0x140, 281, 0, 233 },
+{ 0x540, 281, 0, 231 },
+{ 0x340, 281, 0, 232 },
+{ 0xc0, 281, 0, 242 },
+{ 0x2c0, 281, 0, 240 },
+{ 0x1c0, 281, 0, 241 },
+{ 0x20, 281, 0, 251 },
+{ 0xa0, 281, 0, 249 },
+{ 0x60, 281, 0, 250 },
+{ 0x10, 281, 0, 260 },
+{ 0x50, 281, 0, 258 },
+{ 0x30, 281, 0, 259 },
+{ 0x8, 281, 0, 269 },
+{ 0x28, 281, 0, 267 },
+{ 0x18, 281, 0, 268 },
+{ 0x4, 281, 0, 276 },
+{ 0x2, 281, 0, 277 },
+{ 0x1, 281, 0, 278 },
+{ 0x140, 283, 0, 236 },
+{ 0x540, 283, 0, 234 },
+{ 0x340, 283, 0, 235 },
+{ 0xc0, 283, 0, 245 },
+{ 0x2c0, 283, 0, 243 },
+{ 0x1c0, 283, 0, 244 },
+{ 0x20, 283, 0, 254 },
+{ 0xa0, 283, 0, 252 },
+{ 0x60, 283, 0, 253 },
+{ 0x10, 283, 0, 263 },
+{ 0x50, 283, 0, 261 },
+{ 0x30, 283, 0, 262 },
+{ 0x8, 283, 0, 272 },
+{ 0x28, 283, 0, 270 },
+{ 0x18, 283, 0, 271 },
+{ 0x4, 283, 0, 279 },
+{ 0x2, 283, 0, 280 },
+{ 0x1, 283, 0, 281 },
+{ 0x140, 278, 0, 284 },
+{ 0x540, 278, 0, 282 },
+{ 0x340, 278, 0, 283 },
+{ 0xc0, 278, 0, 293 },
+{ 0x2c0, 278, 0, 291 },
+{ 0x1c0, 278, 0, 292 },
+{ 0x20, 278, 0, 302 },
+{ 0xa0, 278, 0, 300 },
+{ 0x60, 278, 0, 301 },
+{ 0x10, 278, 0, 311 },
+{ 0x50, 278, 0, 309 },
+{ 0x30, 278, 0, 310 },
+{ 0x8, 278, 0, 320 },
+{ 0x28, 278, 0, 318 },
+{ 0x18, 278, 0, 319 },
+{ 0x4, 278, 0, 327 },
+{ 0x2, 278, 0, 328 },
+{ 0x1, 278, 0, 329 },
+{ 0x140, 280, 0, 287 },
+{ 0x540, 280, 0, 285 },
+{ 0x340, 280, 0, 286 },
+{ 0xc0, 280, 0, 296 },
+{ 0x2c0, 280, 0, 294 },
+{ 0x1c0, 280, 0, 295 },
+{ 0x20, 280, 0, 305 },
+{ 0xa0, 280, 0, 303 },
+{ 0x60, 280, 0, 304 },
+{ 0x10, 280, 0, 314 },
+{ 0x50, 280, 0, 312 },
+{ 0x30, 280, 0, 313 },
+{ 0x8, 280, 0, 323 },
+{ 0x28, 280, 0, 321 },
+{ 0x18, 280, 0, 322 },
+{ 0x4, 280, 0, 330 },
+{ 0x2, 280, 0, 331 },
+{ 0x1, 280, 0, 332 },
+{ 0x140, 282, 0, 290 },
+{ 0x540, 282, 0, 288 },
+{ 0x340, 282, 0, 289 },
+{ 0xc0, 282, 0, 299 },
+{ 0x2c0, 282, 0, 297 },
+{ 0x1c0, 282, 0, 298 },
+{ 0x20, 282, 0, 308 },
+{ 0xa0, 282, 0, 306 },
+{ 0x60, 282, 0, 307 },
+{ 0x10, 282, 0, 317 },
+{ 0x50, 282, 0, 315 },
+{ 0x30, 282, 0, 316 },
+{ 0x8, 282, 0, 326 },
+{ 0x28, 282, 0, 324 },
+{ 0x18, 282, 0, 325 },
+{ 0x4, 282, 0, 333 },
+{ 0x2, 282, 0, 334 },
+{ 0x1, 282, 0, 335 },
+{ 0x1, 410, 0, 337 },
+{ 0x3, 410, 0, 336 },
+{ 0x2, 416, 0, 338 },
+{ 0x1, 416, 0, 339 },
+{ 0x2, 412, 0, 340 },
+{ 0x1, 412, 0, 341 },
+{ 0x2, 414, 0, 342 },
+{ 0x1, 414, 0, 343 },
+{ 0x2, 418, 0, 344 },
+{ 0x1, 418, 0, 345 },
+{ 0x1, 267, 0, 372 },
+{ 0x5, 267, 0, 370 },
+{ 0x3, 267, 0, 371 },
+{ 0x140, 276, 0, 348 },
+{ 0x540, 276, 0, 346 },
+{ 0x340, 276, 0, 347 },
+{ 0xc0, 276, 0, 360 },
+{ 0x2c0, 276, 0, 358 },
+{ 0x1c0, 276, 0, 359 },
+{ 0x20, 276, 0, 375 },
+{ 0xa0, 276, 0, 373 },
+{ 0x60, 276, 0, 374 },
+{ 0x10, 276, 0, 387 },
+{ 0x50, 276, 0, 385 },
+{ 0x30, 276, 0, 386 },
+{ 0x8, 276, 0, 399 },
+{ 0x28, 276, 0, 397 },
+{ 0x18, 276, 0, 398 },
+{ 0x4, 276, 0, 409 },
+{ 0x2, 276, 0, 410 },
+{ 0x1, 276, 0, 411 },
+{ 0x140, 270, 0, 351 },
+{ 0x540, 270, 0, 349 },
+{ 0x340, 270, 0, 350 },
+{ 0xc0, 270, 0, 363 },
+{ 0x2c0, 270, 0, 361 },
+{ 0x1c0, 270, 0, 362 },
+{ 0x20, 270, 0, 378 },
+{ 0xa0, 270, 0, 376 },
+{ 0x60, 270, 0, 377 },
+{ 0x10, 270, 0, 390 },
+{ 0x50, 270, 0, 388 },
+{ 0x30, 270, 0, 389 },
+{ 0x8, 270, 0, 402 },
+{ 0x28, 270, 0, 400 },
+{ 0x18, 270, 0, 401 },
+{ 0x4, 270, 0, 412 },
+{ 0x2, 270, 0, 413 },
+{ 0x1, 270, 0, 414 },
+{ 0x140, 273, 0, 354 },
+{ 0x540, 273, 0, 352 },
+{ 0x340, 273, 0, 353 },
+{ 0xc0, 273, 0, 366 },
+{ 0x2c0, 273, 0, 364 },
+{ 0x1c0, 273, 0, 365 },
+{ 0x20, 273, 0, 381 },
+{ 0xa0, 273, 0, 379 },
+{ 0x60, 273, 0, 380 },
+{ 0x10, 273, 0, 393 },
+{ 0x50, 273, 0, 391 },
+{ 0x30, 273, 0, 392 },
+{ 0x8, 273, 0, 405 },
+{ 0x28, 273, 0, 403 },
+{ 0x18, 273, 0, 404 },
+{ 0x4, 273, 0, 415 },
+{ 0x2, 273, 0, 416 },
+{ 0x1, 273, 0, 417 },
+{ 0x140, 285, 0, 357 },
+{ 0x540, 285, 0, 355 },
+{ 0x340, 285, 0, 356 },
+{ 0xc0, 285, 0, 369 },
+{ 0x2c0, 285, 0, 367 },
+{ 0x1c0, 285, 0, 368 },
+{ 0x20, 285, 0, 384 },
+{ 0xa0, 285, 0, 382 },
+{ 0x60, 285, 0, 383 },
+{ 0x10, 285, 0, 396 },
+{ 0x50, 285, 0, 394 },
+{ 0x30, 285, 0, 395 },
+{ 0x8, 285, 0, 408 },
+{ 0x28, 285, 0, 406 },
+{ 0x18, 285, 0, 407 },
+{ 0x4, 285, 0, 418 },
+{ 0x2, 285, 0, 419 },
+{ 0x1, 285, 0, 420 },
+{ 0x1, 266, 0, 447 },
+{ 0x5, 266, 0, 445 },
+{ 0x3, 266, 0, 446 },
+{ 0x140, 275, 0, 423 },
+{ 0x540, 275, 0, 421 },
+{ 0x340, 275, 0, 422 },
+{ 0xc0, 275, 0, 435 },
+{ 0x2c0, 275, 0, 433 },
+{ 0x1c0, 275, 0, 434 },
+{ 0x20, 275, 0, 450 },
+{ 0xa0, 275, 0, 448 },
+{ 0x60, 275, 0, 449 },
+{ 0x10, 275, 0, 462 },
+{ 0x50, 275, 0, 460 },
+{ 0x30, 275, 0, 461 },
+{ 0x8, 275, 0, 474 },
+{ 0x28, 275, 0, 472 },
+{ 0x18, 275, 0, 473 },
+{ 0x4, 275, 0, 484 },
+{ 0x2, 275, 0, 485 },
+{ 0x1, 275, 0, 486 },
+{ 0x140, 269, 0, 426 },
+{ 0x540, 269, 0, 424 },
+{ 0x340, 269, 0, 425 },
+{ 0xc0, 269, 0, 438 },
+{ 0x2c0, 269, 0, 436 },
+{ 0x1c0, 269, 0, 437 },
+{ 0x20, 269, 0, 453 },
+{ 0xa0, 269, 0, 451 },
+{ 0x60, 269, 0, 452 },
+{ 0x10, 269, 0, 465 },
+{ 0x50, 269, 0, 463 },
+{ 0x30, 269, 0, 464 },
+{ 0x8, 269, 0, 477 },
+{ 0x28, 269, 0, 475 },
+{ 0x18, 269, 0, 476 },
+{ 0x4, 269, 0, 487 },
+{ 0x2, 269, 0, 488 },
+{ 0x1, 269, 0, 489 },
+{ 0x140, 272, 0, 429 },
+{ 0x540, 272, 0, 427 },
+{ 0x340, 272, 0, 428 },
+{ 0xc0, 272, 0, 441 },
+{ 0x2c0, 272, 0, 439 },
+{ 0x1c0, 272, 0, 440 },
+{ 0x20, 272, 0, 456 },
+{ 0xa0, 272, 0, 454 },
+{ 0x60, 272, 0, 455 },
+{ 0x10, 272, 0, 468 },
+{ 0x50, 272, 0, 466 },
+{ 0x30, 272, 0, 467 },
+{ 0x8, 272, 0, 480 },
+{ 0x28, 272, 0, 478 },
+{ 0x18, 272, 0, 479 },
+{ 0x4, 272, 0, 490 },
+{ 0x2, 272, 0, 491 },
+{ 0x1, 272, 0, 492 },
+{ 0x140, 284, 0, 432 },
+{ 0x540, 284, 0, 430 },
+{ 0x340, 284, 0, 431 },
+{ 0xc0, 284, 0, 444 },
+{ 0x2c0, 284, 0, 442 },
+{ 0x1c0, 284, 0, 443 },
+{ 0x20, 284, 0, 459 },
+{ 0xa0, 284, 0, 457 },
+{ 0x60, 284, 0, 458 },
+{ 0x10, 284, 0, 471 },
+{ 0x50, 284, 0, 469 },
+{ 0x30, 284, 0, 470 },
+{ 0x8, 284, 0, 483 },
+{ 0x28, 284, 0, 481 },
+{ 0x18, 284, 0, 482 },
+{ 0x4, 284, 0, 493 },
+{ 0x2, 284, 0, 494 },
+{ 0x1, 284, 0, 495 },
+{ 0x8, 409, 0, 497 },
+{ 0x18, 409, 0, 496 },
+{ 0x4, 409, 0, 499 },
+{ 0xc, 409, 0, 498 },
+{ 0x2, 409, 0, 506 },
+{ 0x1, 409, 0, 507 },
+{ 0x4, 407, 0, 501 },
+{ 0xc, 407, 0, 500 },
+{ 0x2, 407, 0, 508 },
+{ 0x1, 407, 0, 509 },
+{ 0x4, 405, 0, 503 },
+{ 0xc, 405, 0, 502 },
+{ 0x2, 405, 0, 510 },
+{ 0x1, 405, 0, 511 },
+{ 0x4, 401, 0, 505 },
+{ 0xc, 401, 0, 504 },
+{ 0x2, 401, 0, 512 },
+{ 0x1, 401, 0, 513 },
+{ 0xa00, 265, 0, 528 },
+{ 0x2a00, 265, 0, 526 },
+{ 0x1a00, 265, 0, 527 },
+{ 0x600, 265, 0, 540 },
+{ 0x2600, 265, 0, 516 },
+{ 0xa600, 265, 0, 514 },
+{ 0x6600, 265, 0, 515 },
+{ 0x1600, 265, 0, 538 },
+{ 0xe00, 265, 0, 539 },
+{ 0x100, 265, 0, 552 },
+{ 0x500, 265, 0, 550 },
+{ 0x300, 265, 0, 551 },
+{ 0x80, 265, 0, 555 },
+{ 0x280, 265, 0, 553 },
+{ 0x180, 265, 0, 554 },
+{ 0x40, 265, 0, 567 },
+{ 0x140, 265, 0, 565 },
+{ 0xc0, 265, 0, 566 },
+{ 0x20, 265, 0, 579 },
+{ 0xa0, 265, 0, 577 },
+{ 0x60, 265, 0, 578 },
+{ 0x10, 265, 0, 591 },
+{ 0x50, 265, 0, 589 },
+{ 0x30, 265, 0, 590 },
+{ 0x8, 265, 0, 603 },
+{ 0x28, 265, 0, 601 },
+{ 0x18, 265, 0, 602 },
+{ 0x4, 265, 0, 613 },
+{ 0x2, 265, 0, 614 },
+{ 0x1, 265, 0, 615 },
+{ 0x500, 261, 0, 531 },
+{ 0x1500, 261, 0, 529 },
+{ 0xd00, 261, 0, 530 },
+{ 0x300, 261, 0, 543 },
+{ 0x1300, 261, 0, 519 },
+{ 0x5300, 261, 0, 517 },
+{ 0x3300, 261, 0, 518 },
+{ 0xb00, 261, 0, 541 },
+{ 0x700, 261, 0, 542 },
+{ 0x80, 261, 0, 558 },
+{ 0x280, 261, 0, 556 },
+{ 0x180, 261, 0, 557 },
+{ 0x40, 261, 0, 570 },
+{ 0x140, 261, 0, 568 },
+{ 0xc0, 261, 0, 569 },
+{ 0x20, 261, 0, 582 },
+{ 0xa0, 261, 0, 580 },
+{ 0x60, 261, 0, 581 },
+{ 0x10, 261, 0, 594 },
+{ 0x50, 261, 0, 592 },
+{ 0x30, 261, 0, 593 },
+{ 0x8, 261, 0, 606 },
+{ 0x28, 261, 0, 604 },
+{ 0x18, 261, 0, 605 },
+{ 0x4, 261, 0, 616 },
+{ 0x2, 261, 0, 617 },
+{ 0x1, 261, 0, 618 },
+{ 0x500, 258, 0, 534 },
+{ 0x1500, 258, 0, 532 },
+{ 0xd00, 258, 0, 533 },
+{ 0x300, 258, 0, 546 },
+{ 0x1300, 258, 0, 522 },
+{ 0x5300, 258, 0, 520 },
+{ 0x3300, 258, 0, 521 },
+{ 0xb00, 258, 0, 544 },
+{ 0x700, 258, 0, 545 },
+{ 0x80, 258, 0, 561 },
+{ 0x280, 258, 0, 559 },
+{ 0x180, 258, 0, 560 },
+{ 0x40, 258, 0, 573 },
+{ 0x140, 258, 0, 571 },
+{ 0xc0, 258, 0, 572 },
+{ 0x20, 258, 0, 585 },
+{ 0xa0, 258, 0, 583 },
+{ 0x60, 258, 0, 584 },
+{ 0x10, 258, 0, 597 },
+{ 0x50, 258, 0, 595 },
+{ 0x30, 258, 0, 596 },
+{ 0x8, 258, 0, 609 },
+{ 0x28, 258, 0, 607 },
+{ 0x18, 258, 0, 608 },
+{ 0x4, 258, 0, 619 },
+{ 0x2, 258, 0, 620 },
+{ 0x1, 258, 0, 621 },
+{ 0x500, 253, 0, 537 },
+{ 0x1500, 253, 0, 535 },
+{ 0xd00, 253, 0, 536 },
+{ 0x300, 253, 0, 549 },
+{ 0x1300, 253, 0, 525 },
+{ 0x5300, 253, 0, 523 },
+{ 0x3300, 253, 0, 524 },
+{ 0xb00, 253, 0, 547 },
+{ 0x700, 253, 0, 548 },
+{ 0x80, 253, 0, 564 },
+{ 0x280, 253, 0, 562 },
+{ 0x180, 253, 0, 563 },
+{ 0x40, 253, 0, 576 },
+{ 0x140, 253, 0, 574 },
+{ 0xc0, 253, 0, 575 },
+{ 0x20, 253, 0, 588 },
+{ 0xa0, 253, 0, 586 },
+{ 0x60, 253, 0, 587 },
+{ 0x10, 253, 0, 600 },
+{ 0x50, 253, 0, 598 },
+{ 0x30, 253, 0, 599 },
+{ 0x8, 253, 0, 612 },
+{ 0x28, 253, 0, 610 },
+{ 0x18, 253, 0, 611 },
+{ 0x4, 253, 0, 622 },
+{ 0x2, 253, 0, 623 },
+{ 0x1, 253, 0, 624 },
+{ 0x8, 238, 0, 625 },
+{ 0x4, 238, 0, 626 },
+{ 0x2, 238, 0, 627 },
+{ 0x1, 238, 0, 628 },
+{ 0x2, 176, 0, 631 },
+{ 0xa, 176, 0, 629 },
+{ 0x6, 176, 0, 630 },
+{ 0x1, 176, 0, 637 },
+{ 0x5, 176, 0, 635 },
+{ 0x3, 176, 0, 636 },
+{ 0x2, 175, 0, 634 },
+{ 0xa, 175, 0, 632 },
+{ 0x6, 175, 0, 633 },
+{ 0x1, 175, 0, 640 },
+{ 0x5, 175, 0, 638 },
+{ 0x3, 175, 0, 639 },
+{ 0x4, 446, 0, 641 },
+{ 0x2, 446, 0, 642 },
+{ 0x1, 446, 0, 643 },
+{ 0x4, 445, 0, 644 },
+{ 0x2, 445, 0, 645 },
+{ 0x1, 445, 0, 646 },
+{ 0x4, 444, 0, 647 },
+{ 0x2, 444, 0, 648 },
+{ 0x1, 444, 0, 649 },
+{ 0x4, 443, 0, 650 },
+{ 0x2, 443, 0, 651 },
+{ 0x1, 443, 0, 652 },
+{ 0x2, 123, 1, 658 },
+{ 0x2, 124, 0, 657 },
+{ 0xa, 123, 1, 654 },
+{ 0xa, 124, 0, 653 },
+{ 0x6, 123, 1, 656 },
+{ 0x6, 124, 0, 655 },
+{ 0x1, 123, 1, 688 },
+{ 0x1, 124, 0, 687 },
+{ 0x5, 123, 1, 684 },
+{ 0x5, 124, 0, 683 },
+{ 0x3, 123, 1, 686 },
+{ 0x3, 124, 0, 685 },
+{ 0x2, 131, 1, 664 },
+{ 0x2, 132, 0, 663 },
+{ 0xa, 131, 1, 660 },
+{ 0xa, 132, 0, 659 },
+{ 0x6, 131, 1, 662 },
+{ 0x6, 132, 0, 661 },
+{ 0x1, 131, 1, 694 },
+{ 0x1, 132, 0, 693 },
+{ 0x5, 131, 1, 690 },
+{ 0x5, 132, 0, 689 },
+{ 0x3, 131, 1, 692 },
+{ 0x3, 132, 0, 691 },
+{ 0x2, 129, 1, 670 },
+{ 0x2, 130, 0, 669 },
+{ 0xa, 129, 1, 666 },
+{ 0xa, 130, 0, 665 },
+{ 0x6, 129, 1, 668 },
+{ 0x6, 130, 0, 667 },
+{ 0x1, 129, 1, 700 },
+{ 0x1, 130, 0, 699 },
+{ 0x5, 129, 1, 696 },
+{ 0x5, 130, 0, 695 },
+{ 0x3, 129, 1, 698 },
+{ 0x3, 130, 0, 697 },
+{ 0x2, 127, 1, 676 },
+{ 0x2, 128, 0, 675 },
+{ 0xa, 127, 1, 672 },
+{ 0xa, 128, 0, 671 },
+{ 0x6, 127, 1, 674 },
+{ 0x6, 128, 0, 673 },
+{ 0x1, 127, 1, 706 },
+{ 0x1, 128, 0, 705 },
+{ 0x5, 127, 1, 702 },
+{ 0x5, 128, 0, 701 },
+{ 0x3, 127, 1, 704 },
+{ 0x3, 128, 0, 703 },
+{ 0x2, 125, 1, 682 },
+{ 0x2, 126, 0, 681 },
+{ 0xa, 125, 1, 678 },
+{ 0xa, 126, 0, 677 },
+{ 0x6, 125, 1, 680 },
+{ 0x6, 126, 0, 679 },
+{ 0x1, 125, 1, 712 },
+{ 0x1, 126, 0, 711 },
+{ 0x5, 125, 1, 708 },
+{ 0x5, 126, 0, 707 },
+{ 0x3, 125, 1, 710 },
+{ 0x3, 126, 0, 709 },
+{ 0x4, 402, 1, 718 },
+{ 0x4, 403, 0, 717 },
+{ 0xc, 402, 1, 716 },
+{ 0xc, 403, 0, 715 },
+{ 0x2, 402, 1, 728 },
+{ 0x2, 403, 0, 727 },
+{ 0x1, 402, 1, 730 },
+{ 0x1, 403, 0, 729 },
+{ 0x8, 408, 0, 714 },
+{ 0x18, 408, 0, 713 },
+{ 0x4, 408, 0, 720 },
+{ 0xc, 408, 0, 719 },
+{ 0x2, 408, 0, 731 },
+{ 0x1, 408, 0, 732 },
+{ 0x4, 406, 0, 722 },
+{ 0xc, 406, 0, 721 },
+{ 0x2, 406, 0, 733 },
+{ 0x1, 406, 0, 734 },
+{ 0x4, 404, 0, 724 },
+{ 0xc, 404, 0, 723 },
+{ 0x2, 404, 0, 735 },
+{ 0x1, 404, 0, 736 },
+{ 0x4, 400, 0, 726 },
+{ 0xc, 400, 0, 725 },
+{ 0x2, 400, 0, 737 },
+{ 0x1, 400, 0, 738 },
+{ 0xa00, 264, 0, 753 },
+{ 0x2a00, 264, 0, 751 },
+{ 0x1a00, 264, 0, 752 },
+{ 0x600, 264, 0, 765 },
+{ 0x2600, 264, 0, 741 },
+{ 0xa600, 264, 0, 739 },
+{ 0x6600, 264, 0, 740 },
+{ 0x1600, 264, 0, 763 },
+{ 0xe00, 264, 0, 764 },
+{ 0x100, 264, 0, 777 },
+{ 0x500, 264, 0, 775 },
+{ 0x300, 264, 0, 776 },
+{ 0x80, 264, 0, 780 },
+{ 0x280, 264, 0, 778 },
+{ 0x180, 264, 0, 779 },
+{ 0x40, 264, 0, 792 },
+{ 0x140, 264, 0, 790 },
+{ 0xc0, 264, 0, 791 },
+{ 0x20, 264, 0, 804 },
+{ 0xa0, 264, 0, 802 },
+{ 0x60, 264, 0, 803 },
+{ 0x10, 264, 0, 816 },
+{ 0x50, 264, 0, 814 },
+{ 0x30, 264, 0, 815 },
+{ 0x8, 264, 0, 828 },
+{ 0x28, 264, 0, 826 },
+{ 0x18, 264, 0, 827 },
+{ 0x4, 264, 0, 838 },
+{ 0x2, 264, 0, 839 },
+{ 0x1, 264, 0, 840 },
+{ 0x500, 260, 0, 756 },
+{ 0x1500, 260, 0, 754 },
+{ 0xd00, 260, 0, 755 },
+{ 0x300, 260, 0, 768 },
+{ 0x1300, 260, 0, 744 },
+{ 0x5300, 260, 0, 742 },
+{ 0x3300, 260, 0, 743 },
+{ 0xb00, 260, 0, 766 },
+{ 0x700, 260, 0, 767 },
+{ 0x80, 260, 0, 783 },
+{ 0x280, 260, 0, 781 },
+{ 0x180, 260, 0, 782 },
+{ 0x40, 260, 0, 795 },
+{ 0x140, 260, 0, 793 },
+{ 0xc0, 260, 0, 794 },
+{ 0x20, 260, 0, 807 },
+{ 0xa0, 260, 0, 805 },
+{ 0x60, 260, 0, 806 },
+{ 0x10, 260, 0, 819 },
+{ 0x50, 260, 0, 817 },
+{ 0x30, 260, 0, 818 },
+{ 0x8, 260, 0, 831 },
+{ 0x28, 260, 0, 829 },
+{ 0x18, 260, 0, 830 },
+{ 0x4, 260, 0, 841 },
+{ 0x2, 260, 0, 842 },
+{ 0x1, 260, 0, 843 },
+{ 0x500, 257, 0, 759 },
+{ 0x1500, 257, 0, 757 },
+{ 0xd00, 257, 0, 758 },
+{ 0x300, 257, 0, 771 },
+{ 0x1300, 257, 0, 747 },
+{ 0x5300, 257, 0, 745 },
+{ 0x3300, 257, 0, 746 },
+{ 0xb00, 257, 0, 769 },
+{ 0x700, 257, 0, 770 },
+{ 0x80, 257, 0, 786 },
+{ 0x280, 257, 0, 784 },
+{ 0x180, 257, 0, 785 },
+{ 0x40, 257, 0, 798 },
+{ 0x140, 257, 0, 796 },
+{ 0xc0, 257, 0, 797 },
+{ 0x20, 257, 0, 810 },
+{ 0xa0, 257, 0, 808 },
+{ 0x60, 257, 0, 809 },
+{ 0x10, 257, 0, 822 },
+{ 0x50, 257, 0, 820 },
+{ 0x30, 257, 0, 821 },
+{ 0x8, 257, 0, 834 },
+{ 0x28, 257, 0, 832 },
+{ 0x18, 257, 0, 833 },
+{ 0x4, 257, 0, 844 },
+{ 0x2, 257, 0, 845 },
+{ 0x1, 257, 0, 846 },
+{ 0x500, 252, 0, 762 },
+{ 0x1500, 252, 0, 760 },
+{ 0xd00, 252, 0, 761 },
+{ 0x300, 252, 0, 774 },
+{ 0x1300, 252, 0, 750 },
+{ 0x5300, 252, 0, 748 },
+{ 0x3300, 252, 0, 749 },
+{ 0xb00, 252, 0, 772 },
+{ 0x700, 252, 0, 773 },
+{ 0x80, 252, 0, 789 },
+{ 0x280, 252, 0, 787 },
+{ 0x180, 252, 0, 788 },
+{ 0x40, 252, 0, 801 },
+{ 0x140, 252, 0, 799 },
+{ 0xc0, 252, 0, 800 },
+{ 0x20, 252, 0, 813 },
+{ 0xa0, 252, 0, 811 },
+{ 0x60, 252, 0, 812 },
+{ 0x10, 252, 0, 825 },
+{ 0x50, 252, 0, 823 },
+{ 0x30, 252, 0, 824 },
+{ 0x8, 252, 0, 837 },
+{ 0x28, 252, 0, 835 },
+{ 0x18, 252, 0, 836 },
+{ 0x4, 252, 0, 847 },
+{ 0x2, 252, 0, 848 },
+{ 0x1, 252, 0, 849 },
+{ 0x8, 254, 1, 895 },
+{ 0x8, 255, 0, 894 },
+{ 0x28, 254, 1, 891 },
+{ 0x28, 255, 0, 890 },
+{ 0x18, 254, 1, 893 },
+{ 0x18, 255, 0, 892 },
+{ 0x4, 254, 1, 957 },
+{ 0x4, 255, 0, 956 },
+{ 0x2, 254, 1, 959 },
+{ 0x2, 255, 0, 958 },
+{ 0x1, 254, 1, 961 },
+{ 0x1, 255, 0, 960 },
+{ 0xa00, 262, 0, 865 },
+{ 0x2a00, 262, 0, 863 },
+{ 0x1a00, 262, 0, 864 },
+{ 0x600, 262, 0, 877 },
+{ 0x2600, 262, 0, 853 },
+{ 0xa600, 262, 0, 851 },
+{ 0x6600, 262, 0, 852 },
+{ 0x1600, 262, 0, 875 },
+{ 0xe00, 262, 0, 876 },
+{ 0x100, 262, 0, 889 },
+{ 0x500, 262, 0, 887 },
+{ 0x300, 262, 0, 888 },
+{ 0x80, 262, 0, 898 },
+{ 0x280, 262, 0, 896 },
+{ 0x180, 262, 0, 897 },
+{ 0x40, 262, 0, 910 },
+{ 0x140, 262, 0, 908 },
+{ 0xc0, 262, 0, 909 },
+{ 0x20, 262, 0, 922 },
+{ 0xa0, 262, 0, 920 },
+{ 0x60, 262, 0, 921 },
+{ 0x10, 262, 0, 934 },
+{ 0x50, 262, 0, 932 },
+{ 0x30, 262, 0, 933 },
+{ 0x8, 262, 0, 946 },
+{ 0x28, 262, 0, 944 },
+{ 0x18, 262, 0, 945 },
+{ 0x4, 262, 0, 962 },
+{ 0x2, 262, 0, 963 },
+{ 0x1, 262, 1, 964 },
+{ 0x1, 263, 0, 850 },
+{ 0x500, 259, 0, 868 },
+{ 0x1500, 259, 0, 866 },
+{ 0xd00, 259, 0, 867 },
+{ 0x300, 259, 0, 880 },
+{ 0x1300, 259, 0, 856 },
+{ 0x5300, 259, 0, 854 },
+{ 0x3300, 259, 0, 855 },
+{ 0xb00, 259, 0, 878 },
+{ 0x700, 259, 0, 879 },
+{ 0x80, 259, 0, 901 },
+{ 0x280, 259, 0, 899 },
+{ 0x180, 259, 0, 900 },
+{ 0x40, 259, 0, 913 },
+{ 0x140, 259, 0, 911 },
+{ 0xc0, 259, 0, 912 },
+{ 0x20, 259, 0, 925 },
+{ 0xa0, 259, 0, 923 },
+{ 0x60, 259, 0, 924 },
+{ 0x10, 259, 0, 937 },
+{ 0x50, 259, 0, 935 },
+{ 0x30, 259, 0, 936 },
+{ 0x8, 259, 0, 949 },
+{ 0x28, 259, 0, 947 },
+{ 0x18, 259, 0, 948 },
+{ 0x4, 259, 0, 965 },
+{ 0x2, 259, 0, 966 },
+{ 0x1, 259, 0, 967 },
+{ 0x500, 256, 0, 871 },
+{ 0x1500, 256, 0, 869 },
+{ 0xd00, 256, 0, 870 },
+{ 0x300, 256, 0, 883 },
+{ 0x1300, 256, 0, 859 },
+{ 0x5300, 256, 0, 857 },
+{ 0x3300, 256, 0, 858 },
+{ 0xb00, 256, 0, 881 },
+{ 0x700, 256, 0, 882 },
+{ 0x80, 256, 0, 904 },
+{ 0x280, 256, 0, 902 },
+{ 0x180, 256, 0, 903 },
+{ 0x40, 256, 0, 916 },
+{ 0x140, 256, 0, 914 },
+{ 0xc0, 256, 0, 915 },
+{ 0x20, 256, 0, 928 },
+{ 0xa0, 256, 0, 926 },
+{ 0x60, 256, 0, 927 },
+{ 0x10, 256, 0, 940 },
+{ 0x50, 256, 0, 938 },
+{ 0x30, 256, 0, 939 },
+{ 0x8, 256, 0, 952 },
+{ 0x28, 256, 0, 950 },
+{ 0x18, 256, 0, 951 },
+{ 0x4, 256, 0, 968 },
+{ 0x2, 256, 0, 969 },
+{ 0x1, 256, 0, 970 },
+{ 0x500, 251, 0, 874 },
+{ 0x1500, 251, 0, 872 },
+{ 0xd00, 251, 0, 873 },
+{ 0x300, 251, 0, 886 },
+{ 0x1300, 251, 0, 862 },
+{ 0x5300, 251, 0, 860 },
+{ 0x3300, 251, 0, 861 },
+{ 0xb00, 251, 0, 884 },
+{ 0x700, 251, 0, 885 },
+{ 0x80, 251, 0, 907 },
+{ 0x280, 251, 0, 905 },
+{ 0x180, 251, 0, 906 },
+{ 0x40, 251, 0, 919 },
+{ 0x140, 251, 0, 917 },
+{ 0xc0, 251, 0, 918 },
+{ 0x20, 251, 0, 931 },
+{ 0xa0, 251, 0, 929 },
+{ 0x60, 251, 0, 930 },
+{ 0x10, 251, 0, 943 },
+{ 0x50, 251, 0, 941 },
+{ 0x30, 251, 0, 942 },
+{ 0x8, 251, 0, 955 },
+{ 0x28, 251, 0, 953 },
+{ 0x18, 251, 0, 954 },
+{ 0x4, 251, 0, 971 },
+{ 0x2, 251, 0, 972 },
+{ 0x1, 251, 0, 973 },
+{ 0x2, 150, 0, 975 },
+{ 0x1, 150, 0, 976 },
+{ 0x1, 50, 0, 977 },
+{ 0x3, 49, 0, 978 },
+{ 0x1, 428, 0, 979 },
+{ 0x1, 438, 0, 980 },
+{ 0x2, 386, 0, 983 },
+{ 0x1, 386, 0, 984 },
+{ 0x2, 384, 0, 985 },
+{ 0x1, 384, 0, 986 },
+{ 0x1, 383, 0, 987 },
+{ 0x1, 328, 0, 992 },
+{ 0x1, 327, 0, 993 },
+{ 0x1, 326, 0, 994 },
+{ 0x1, 325, 0, 995 },
+{ 0x1, 250, 0, 996 },
+{ 0x1, 249, 0, 997 },
+{ 0x1, 324, 0, 998 },
+{ 0x1, 323, 0, 999 },
+{ 0x1, 322, 0, 1000 },
+{ 0x1, 321, 0, 1001 },
+{ 0x1, 320, 0, 1002 },
+{ 0x1, 319, 0, 1003 },
+{ 0x1, 318, 0, 1004 },
+{ 0x2, 248, 0, 1005 },
+{ 0x1, 248, 0, 1006 },
+{ 0x2, 366, 0, 1012 },
+{ 0x1, 366, 0, 1013 },
+{ 0x1, 317, 0, 1014 },
+{ 0x1, 316, 0, 1015 },
+{ 0x1, 315, 0, 1016 },
+{ 0x1, 314, 0, 1017 },
+{ 0x1, 8, 1, 1019 },
+{ 0x1, 9, 0, 1018 },
+{ 0x1, 313, 0, 1020 },
+{ 0x1, 312, 0, 1021 },
+{ 0x1, 311, 0, 1022 },
+{ 0x1, 310, 0, 1023 },
+{ 0x1, 388, 0, 1024 },
+{ 0x1, 399, 0, 1025 },
+{ 0x1, 389, 0, 1026 },
+{ 0x1, 423, 0, 1027 },
+{ 0x1, 309, 0, 1031 },
+{ 0x1, 247, 0, 1032 },
+{ 0x1, 177, 0, 1035 },
+{ 0x2, 291, 0, 1039 },
+{ 0x1, 291, 0, 1040 },
+{ 0x1, 236, 0, 1041 },
+{ 0x5, 48, 0, 1043 },
+{ 0x3, 48, 0, 1044 },
+{ 0x5, 47, 0, 1045 },
+{ 0x3, 47, 0, 1046 },
+{ 0x1, 365, 0, 1047 },
+{ 0x1, 373, 0, 1048 },
+{ 0x1, 371, 0, 1049 },
+{ 0x1, 392, 0, 1050 },
+{ 0x1, 372, 0, 1051 },
+{ 0x1, 370, 0, 1052 },
+{ 0x2, 378, 0, 1053 },
+{ 0x1, 378, 0, 1055 },
+{ 0x2, 376, 0, 1054 },
+{ 0x1, 376, 0, 1056 },
+{ 0x2, 396, 0, 1057 },
+{ 0x1, 396, 0, 1060 },
+{ 0x2, 377, 0, 1058 },
+{ 0x1, 377, 0, 1061 },
+{ 0x2, 375, 0, 1059 },
+{ 0x1, 375, 0, 1062 },
+{ 0x1, 338, 0, 1063 },
+{ 0x1, 337, 0, 1064 },
+{ 0x1, 369, 0, 1065 },
+{ 0x1, 360, 0, 1066 },
+{ 0x1, 362, 0, 1067 },
+{ 0x1, 359, 0, 1068 },
+{ 0x1, 361, 0, 1069 },
+{ 0x2, 442, 0, 1070 },
+{ 0x1, 442, 0, 1073 },
+{ 0x2, 441, 0, 1071 },
+{ 0x1, 441, 0, 1074 },
+{ 0x2, 440, 0, 1072 },
+{ 0x1, 440, 0, 1075 },
+{ 0x1, 348, 0, 1076 },
+{ 0x2, 347, 0, 1077 },
+{ 0x1, 347, 0, 1078 },
+{ 0x2, 294, 0, 1079 },
+{ 0x1, 294, 0, 1082 },
+{ 0x2, 293, 0, 1080 },
+{ 0x1, 293, 0, 1083 },
+{ 0x2, 292, 0, 1081 },
+{ 0x1, 292, 0, 1084 },
+{ 0x2, 363, 0, 1085 },
+{ 0x1, 363, 0, 1086 },
+{ 0x2, 364, 0, 1087 },
+{ 0x1, 364, 0, 1088 },
+{ 0xa, 434, 1, 1100 },
+{ 0xa, 435, 1, 1099 },
+{ 0xa, 436, 1, 1098 },
+{ 0xa, 437, 0, 1097 },
+{ 0x1a, 434, 1, 1092 },
+{ 0x1a, 435, 1, 1091 },
+{ 0x32, 436, 1, 1090 },
+{ 0x32, 437, 0, 1089 },
+{ 0x6, 434, 1, 1108 },
+{ 0x6, 435, 1, 1107 },
+{ 0x6, 436, 1, 1106 },
+{ 0x6, 437, 0, 1105 },
+{ 0x1, 434, 1, 1120 },
+{ 0x1, 435, 1, 1119 },
+{ 0x1, 436, 1, 1118 },
+{ 0x1, 437, 0, 1117 },
+{ 0x9, 434, 1, 1104 },
+{ 0x9, 435, 1, 1103 },
+{ 0x9, 436, 1, 1102 },
+{ 0x9, 437, 0, 1101 },
+{ 0x19, 434, 1, 1096 },
+{ 0x19, 435, 1, 1095 },
+{ 0x31, 436, 1, 1094 },
+{ 0x31, 437, 0, 1093 },
+{ 0x5, 434, 1, 1112 },
+{ 0x5, 435, 1, 1111 },
+{ 0x5, 436, 1, 1110 },
+{ 0x5, 437, 0, 1109 },
+{ 0x3, 434, 1, 1116 },
+{ 0x3, 435, 1, 1115 },
+{ 0x3, 436, 1, 1114 },
+{ 0x3, 437, 0, 1113 },
+{ 0xa, 429, 1, 1132 },
+{ 0xa, 430, 1, 1131 },
+{ 0xa, 431, 1, 1130 },
+{ 0xa, 432, 0, 1129 },
+{ 0x1a, 429, 1, 1124 },
+{ 0x1a, 430, 1, 1123 },
+{ 0x32, 431, 1, 1122 },
+{ 0x32, 432, 0, 1121 },
+{ 0x6, 429, 1, 1140 },
+{ 0x6, 430, 1, 1139 },
+{ 0x6, 431, 1, 1138 },
+{ 0x6, 432, 0, 1137 },
+{ 0x1, 429, 1, 1152 },
+{ 0x1, 430, 1, 1151 },
+{ 0x1, 431, 1, 1150 },
+{ 0x1, 432, 0, 1149 },
+{ 0x9, 429, 1, 1136 },
+{ 0x9, 430, 1, 1135 },
+{ 0x9, 431, 1, 1134 },
+{ 0x9, 432, 0, 1133 },
+{ 0x19, 429, 1, 1128 },
+{ 0x19, 430, 1, 1127 },
+{ 0x31, 431, 1, 1126 },
+{ 0x31, 432, 0, 1125 },
+{ 0x5, 429, 1, 1144 },
+{ 0x5, 430, 1, 1143 },
+{ 0x5, 431, 1, 1142 },
+{ 0x5, 432, 0, 1141 },
+{ 0x3, 429, 1, 1148 },
+{ 0x3, 430, 1, 1147 },
+{ 0x3, 431, 1, 1146 },
+{ 0x3, 432, 0, 1145 },
+{ 0x1, 139, 0, 1153 },
+{ 0x1, 138, 0, 1154 },
+{ 0x1, 391, 1, 1156 },
+{ 0x1, 137, 0, 1155 },
+{ 0x2, 395, 1, 1158 },
+{ 0x2, 141, 0, 1157 },
+{ 0x1, 395, 1, 1160 },
+{ 0x1, 141, 0, 1159 },
+{ 0x1, 397, 0, 1161 },
+{ 0x1, 136, 0, 1162 },
+{ 0x2, 135, 0, 1163 },
+{ 0x2, 134, 0, 1164 },
+{ 0x1, 454, 1, 1170 },
+{ 0x1, 246, 0, 1033 },
+{ 0x1, 453, 0, 1171 },
+{ 0x1, 452, 1, 1172 },
+{ 0x1, 245, 0, 1042 },
+{ 0x1, 308, 0, 1173 },
+{ 0x1, 307, 1, 1174 },
+{ 0x1, 290, 0, 1034 },
+{ 0x1, 306, 0, 1175 },
+{ 0x1, 305, 1, 1176 },
+{ 0x1, 427, 0, 1036 },
+{ 0x1, 304, 1, 1177 },
+{ 0x1, 398, 0, 1038 },
+{ 0x1, 303, 0, 1178 },
+{ 0x1, 302, 0, 1179 },
+{ 0x1, 301, 0, 1180 },
+{ 0x1, 300, 1, 1181 },
+{ 0x2, 398, 0, 1037 },
+{ 0x10, 299, 0, 1185 },
+{ 0x90, 299, 0, 1183 },
+{ 0x190, 299, 0, 1182 },
+{ 0x50, 299, 0, 1184 },
+{ 0x30, 299, 0, 1187 },
+{ 0x70, 299, 0, 1186 },
+{ 0x8, 299, 0, 1189 },
+{ 0x18, 299, 0, 1188 },
+{ 0x4, 299, 0, 1190 },
+{ 0x1, 299, 0, 1193 },
+{ 0x3, 299, 0, 1192 },
+{ 0x1, 298, 1, 1194 },
+{ 0x2, 299, 0, 1191 },
+{ 0x3, 46, 0, 1195 },
+{ 0x1, 241, 1, 1196 },
+{ 0x1, 242, 1, 1028 },
+{ 0x1, 243, 0, 88 },
+{ 0x1, 341, 1, 1197 },
+{ 0x1, 342, 1, 1029 },
+{ 0x1, 343, 0, 89 },
+{ 0x1, 34, 1, 1198 },
+{ 0x1, 35, 1, 1030 },
+{ 0x1, 36, 0, 90 },
+{ 0x1, 230, 0, 1199 },
+{ 0x4, 447, 0, 1200 },
+{ 0x2, 447, 0, 1201 },
+{ 0x1, 447, 1, 1203 },
+{ 0x1, 448, 0, 1202 },
+{ 0x8, 449, 0, 1204 },
+{ 0x4, 449, 0, 1205 },
+{ 0x1, 449, 1, 1207 },
+{ 0x2, 449, 0, 1206 },
+{ 0x8, 219, 0, 1208 },
+{ 0x4, 219, 0, 1209 },
+{ 0x2, 219, 0, 1210 },
+{ 0x1, 219, 1, 1212 },
+{ 0x1, 220, 0, 1211 },
+{ 0x10, 221, 0, 1213 },
+{ 0x8, 221, 0, 1214 },
+{ 0x4, 221, 0, 1215 },
+{ 0x1, 221, 1, 1217 },
+{ 0x2, 221, 0, 1216 },
+{ 0x220, 191, 0, 1218 },
+{ 0x120, 191, 0, 1219 },
+{ 0xa0, 191, 0, 1220 },
+{ 0x60, 191, 1, 1222 },
+{ 0x4, 192, 0, 1221 },
+{ 0x110, 191, 0, 1228 },
+{ 0x90, 191, 0, 1229 },
+{ 0x50, 191, 0, 1230 },
+{ 0x30, 191, 1, 1232 },
+{ 0x2, 192, 0, 1231 },
+{ 0x8, 191, 0, 1233 },
+{ 0x4, 191, 0, 1234 },
+{ 0x2, 191, 0, 1235 },
+{ 0x1, 191, 1, 1237 },
+{ 0x1, 192, 0, 1236 },
+{ 0x440, 193, 0, 1223 },
+{ 0x240, 193, 0, 1224 },
+{ 0x140, 193, 0, 1225 },
+{ 0xc0, 193, 1, 1227 },
+{ 0x40, 193, 0, 1226 },
+{ 0x220, 193, 0, 1238 },
+{ 0x120, 193, 0, 1239 },
+{ 0xa0, 193, 0, 1240 },
+{ 0x60, 193, 1, 1242 },
+{ 0x20, 193, 0, 1241 },
+{ 0x10, 193, 0, 1243 },
+{ 0x8, 193, 0, 1244 },
+{ 0x4, 193, 0, 1245 },
+{ 0x1, 193, 1, 1247 },
+{ 0x2, 193, 0, 1246 },
+{ 0x8, 215, 0, 1248 },
+{ 0x4, 215, 0, 1249 },
+{ 0x2, 215, 0, 1250 },
+{ 0x1, 215, 1, 1252 },
+{ 0x1, 216, 0, 1251 },
+{ 0x220, 187, 0, 1253 },
+{ 0x120, 187, 0, 1254 },
+{ 0xa0, 187, 0, 1255 },
+{ 0x60, 187, 1, 1257 },
+{ 0x4, 188, 0, 1256 },
+{ 0x110, 187, 0, 1263 },
+{ 0x90, 187, 0, 1264 },
+{ 0x50, 187, 0, 1265 },
+{ 0x30, 187, 1, 1267 },
+{ 0x2, 188, 0, 1266 },
+{ 0x8, 187, 0, 1268 },
+{ 0x4, 187, 0, 1269 },
+{ 0x2, 187, 0, 1270 },
+{ 0x1, 187, 1, 1272 },
+{ 0x1, 188, 0, 1271 },
+{ 0x440, 233, 0, 1258 },
+{ 0x240, 233, 0, 1259 },
+{ 0x140, 233, 0, 1260 },
+{ 0xc0, 233, 1, 1262 },
+{ 0x40, 233, 0, 1261 },
+{ 0x220, 233, 0, 1273 },
+{ 0x120, 233, 0, 1274 },
+{ 0xa0, 233, 0, 1275 },
+{ 0x60, 233, 1, 1277 },
+{ 0x20, 233, 0, 1276 },
+{ 0x10, 233, 0, 1278 },
+{ 0x8, 233, 0, 1279 },
+{ 0x4, 233, 0, 1280 },
+{ 0x1, 233, 1, 1282 },
+{ 0x2, 233, 0, 1281 },
+{ 0x8, 207, 0, 1283 },
+{ 0x4, 207, 0, 1284 },
+{ 0x2, 207, 0, 1285 },
+{ 0x1, 207, 1, 1287 },
+{ 0x1, 208, 0, 1286 },
+{ 0x10, 214, 0, 1288 },
+{ 0x8, 214, 0, 1289 },
+{ 0x4, 214, 0, 1290 },
+{ 0x1, 214, 1, 1292 },
+{ 0x2, 214, 0, 1291 },
+{ 0x220, 178, 0, 1293 },
+{ 0x120, 178, 0, 1294 },
+{ 0xa0, 178, 0, 1295 },
+{ 0x60, 178, 1, 1297 },
+{ 0x4, 179, 0, 1296 },
+{ 0x110, 178, 0, 1318 },
+{ 0x90, 178, 0, 1319 },
+{ 0x50, 178, 0, 1320 },
+{ 0x30, 178, 1, 1322 },
+{ 0x2, 179, 0, 1321 },
+{ 0x8, 178, 0, 1323 },
+{ 0x4, 178, 0, 1324 },
+{ 0x2, 178, 0, 1325 },
+{ 0x1, 178, 1, 1327 },
+{ 0x1, 179, 0, 1326 },
+{ 0x440, 186, 0, 1298 },
+{ 0x240, 186, 0, 1299 },
+{ 0x140, 186, 0, 1300 },
+{ 0xc0, 186, 1, 1302 },
+{ 0x40, 186, 0, 1301 },
+{ 0x220, 186, 0, 1328 },
+{ 0x120, 186, 0, 1329 },
+{ 0xa0, 186, 0, 1330 },
+{ 0x60, 186, 1, 1332 },
+{ 0x20, 186, 0, 1331 },
+{ 0x10, 186, 0, 1333 },
+{ 0x8, 186, 0, 1334 },
+{ 0x4, 186, 0, 1335 },
+{ 0x1, 186, 1, 1337 },
+{ 0x2, 186, 0, 1336 },
+{ 0x440, 143, 0, 1303 },
+{ 0x240, 143, 0, 1304 },
+{ 0x140, 143, 0, 1305 },
+{ 0xc0, 143, 1, 1307 },
+{ 0x40, 143, 0, 1306 },
+{ 0x220, 143, 0, 1338 },
+{ 0x120, 143, 0, 1339 },
+{ 0xa0, 143, 0, 1340 },
+{ 0x60, 143, 1, 1342 },
+{ 0x20, 143, 0, 1341 },
+{ 0x10, 143, 0, 1343 },
+{ 0x8, 143, 0, 1344 },
+{ 0x1, 143, 1, 1347 },
+{ 0x2, 143, 0, 1346 },
+{ 0x440, 194, 1, 1313 },
+{ 0x441, 174, 0, 1308 },
+{ 0x240, 194, 1, 1314 },
+{ 0x241, 174, 0, 1309 },
+{ 0x140, 194, 1, 1315 },
+{ 0x141, 174, 0, 1310 },
+{ 0xc0, 194, 1, 1317 },
+{ 0x40, 194, 1, 1316 },
+{ 0xc1, 174, 1, 1312 },
+{ 0x41, 174, 0, 1311 },
+{ 0x220, 194, 1, 1358 },
+{ 0x221, 174, 0, 1348 },
+{ 0x120, 194, 1, 1359 },
+{ 0x121, 174, 0, 1349 },
+{ 0xa0, 194, 1, 1360 },
+{ 0xa1, 174, 0, 1350 },
+{ 0x60, 194, 1, 1362 },
+{ 0x20, 194, 1, 1361 },
+{ 0x61, 174, 1, 1352 },
+{ 0x21, 174, 0, 1351 },
+{ 0x10, 194, 1, 1363 },
+{ 0x11, 174, 0, 1353 },
+{ 0x8, 194, 1, 1364 },
+{ 0x9, 174, 0, 1354 },
+{ 0x4, 194, 1, 1365 },
+{ 0x5, 174, 0, 1355 },
+{ 0x1, 194, 1, 1367 },
+{ 0x2, 194, 1, 1366 },
+{ 0x3, 174, 1, 1357 },
+{ 0x1, 174, 0, 1356 },
+{ 0x1, 153, 1, 1375 },
+{ 0x1, 154, 1, 1374 },
+{ 0x1, 155, 1, 1373 },
+{ 0x1, 156, 0, 1372 },
+{ 0x3, 153, 1, 1371 },
+{ 0x3, 154, 1, 1370 },
+{ 0x3, 155, 1, 1369 },
+{ 0x3, 156, 0, 1368 },
+{ 0x1108, 159, 1, 1537 },
+{ 0x1108, 160, 1, 1536 },
+{ 0x1108, 165, 1, 1377 },
+{ 0x1108, 166, 0, 1376 },
+{ 0x908, 159, 1, 1539 },
+{ 0x908, 160, 1, 1538 },
+{ 0x908, 165, 1, 1379 },
+{ 0x908, 166, 0, 1378 },
+{ 0x508, 159, 1, 1541 },
+{ 0x508, 160, 1, 1540 },
+{ 0x508, 165, 1, 1381 },
+{ 0x508, 166, 0, 1380 },
+{ 0x308, 159, 1, 1545 },
+{ 0x308, 160, 1, 1544 },
+{ 0x108, 160, 1, 1542 },
+{ 0x18, 161, 1, 1543 },
+{ 0x308, 165, 1, 1385 },
+{ 0x308, 166, 1, 1384 },
+{ 0x108, 166, 1, 1382 },
+{ 0x18, 167, 0, 1383 },
+{ 0x88, 159, 1, 1577 },
+{ 0x88, 160, 1, 1576 },
+{ 0x88, 165, 1, 1457 },
+{ 0x88, 166, 0, 1456 },
+{ 0x48, 159, 1, 1579 },
+{ 0x48, 160, 1, 1578 },
+{ 0x48, 165, 1, 1459 },
+{ 0x48, 166, 0, 1458 },
+{ 0x28, 159, 1, 1581 },
+{ 0x28, 160, 1, 1580 },
+{ 0x28, 165, 1, 1461 },
+{ 0x28, 166, 0, 1460 },
+{ 0x18, 159, 1, 1585 },
+{ 0x18, 160, 1, 1584 },
+{ 0x8, 160, 1, 1582 },
+{ 0x8, 161, 1, 1583 },
+{ 0x18, 165, 1, 1465 },
+{ 0x18, 166, 1, 1464 },
+{ 0x8, 166, 1, 1462 },
+{ 0x8, 167, 0, 1463 },
+{ 0x884, 159, 1, 1547 },
+{ 0x884, 160, 1, 1546 },
+{ 0x442, 162, 1, 1437 },
+{ 0x442, 163, 1, 1436 },
+{ 0x884, 165, 1, 1407 },
+{ 0x884, 166, 1, 1406 },
+{ 0x442, 168, 1, 1387 },
+{ 0x442, 169, 0, 1386 },
+{ 0x484, 159, 1, 1549 },
+{ 0x484, 160, 1, 1548 },
+{ 0x242, 162, 1, 1439 },
+{ 0x242, 163, 1, 1438 },
+{ 0x484, 165, 1, 1409 },
+{ 0x484, 166, 1, 1408 },
+{ 0x242, 168, 1, 1389 },
+{ 0x242, 169, 0, 1388 },
+{ 0x284, 159, 1, 1551 },
+{ 0x284, 160, 1, 1550 },
+{ 0x142, 162, 1, 1441 },
+{ 0x142, 163, 1, 1440 },
+{ 0x284, 165, 1, 1411 },
+{ 0x284, 166, 1, 1410 },
+{ 0x142, 168, 1, 1391 },
+{ 0x142, 169, 0, 1390 },
+{ 0x184, 159, 1, 1555 },
+{ 0x184, 160, 1, 1554 },
+{ 0x84, 160, 1, 1552 },
+{ 0xc, 161, 1, 1553 },
+{ 0xc2, 162, 1, 1445 },
+{ 0xc2, 163, 1, 1444 },
+{ 0x42, 163, 1, 1442 },
+{ 0x6, 164, 1, 1443 },
+{ 0x184, 165, 1, 1415 },
+{ 0x184, 166, 1, 1414 },
+{ 0x84, 166, 1, 1412 },
+{ 0xc, 167, 1, 1413 },
+{ 0xc2, 168, 1, 1395 },
+{ 0xc2, 169, 1, 1394 },
+{ 0x42, 169, 1, 1392 },
+{ 0x6, 170, 0, 1393 },
+{ 0x44, 159, 1, 1587 },
+{ 0x44, 160, 1, 1586 },
+{ 0x22, 162, 1, 1517 },
+{ 0x22, 163, 1, 1516 },
+{ 0x44, 165, 1, 1487 },
+{ 0x44, 166, 1, 1486 },
+{ 0x22, 168, 1, 1467 },
+{ 0x22, 169, 0, 1466 },
+{ 0x24, 159, 1, 1589 },
+{ 0x24, 160, 1, 1588 },
+{ 0x12, 162, 1, 1519 },
+{ 0x12, 163, 1, 1518 },
+{ 0x24, 165, 1, 1489 },
+{ 0x24, 166, 1, 1488 },
+{ 0x12, 168, 1, 1469 },
+{ 0x12, 169, 0, 1468 },
+{ 0x14, 159, 1, 1591 },
+{ 0x14, 160, 1, 1590 },
+{ 0xa, 162, 1, 1521 },
+{ 0xa, 163, 1, 1520 },
+{ 0x14, 165, 1, 1491 },
+{ 0x14, 166, 1, 1490 },
+{ 0xa, 168, 1, 1471 },
+{ 0xa, 169, 0, 1470 },
+{ 0xc, 159, 1, 1595 },
+{ 0xc, 160, 1, 1594 },
+{ 0x4, 160, 1, 1592 },
+{ 0x4, 161, 1, 1593 },
+{ 0x6, 162, 1, 1525 },
+{ 0x6, 163, 1, 1524 },
+{ 0x2, 163, 1, 1522 },
+{ 0x2, 164, 1, 1523 },
+{ 0xc, 165, 1, 1495 },
+{ 0xc, 166, 1, 1494 },
+{ 0x4, 166, 1, 1492 },
+{ 0x4, 167, 1, 1493 },
+{ 0x6, 168, 1, 1475 },
+{ 0x6, 169, 1, 1474 },
+{ 0x2, 169, 1, 1472 },
+{ 0x2, 170, 0, 1473 },
+{ 0x442, 159, 1, 1557 },
+{ 0x442, 160, 1, 1556 },
+{ 0x221, 162, 1, 1447 },
+{ 0x221, 163, 1, 1446 },
+{ 0x442, 165, 1, 1417 },
+{ 0x442, 166, 1, 1416 },
+{ 0x221, 168, 1, 1397 },
+{ 0x221, 169, 0, 1396 },
+{ 0x242, 159, 1, 1559 },
+{ 0x242, 160, 1, 1558 },
+{ 0x121, 162, 1, 1449 },
+{ 0x121, 163, 1, 1448 },
+{ 0x242, 165, 1, 1419 },
+{ 0x242, 166, 1, 1418 },
+{ 0x121, 168, 1, 1399 },
+{ 0x121, 169, 0, 1398 },
+{ 0x142, 159, 1, 1561 },
+{ 0x142, 160, 1, 1560 },
+{ 0xa1, 162, 1, 1451 },
+{ 0xa1, 163, 1, 1450 },
+{ 0x142, 165, 1, 1421 },
+{ 0x142, 166, 1, 1420 },
+{ 0xa1, 168, 1, 1401 },
+{ 0xa1, 169, 0, 1400 },
+{ 0xc2, 159, 1, 1565 },
+{ 0xc2, 160, 1, 1564 },
+{ 0x42, 160, 1, 1562 },
+{ 0x6, 161, 1, 1563 },
+{ 0x61, 162, 1, 1455 },
+{ 0x61, 163, 1, 1454 },
+{ 0x21, 163, 1, 1452 },
+{ 0x3, 164, 1, 1453 },
+{ 0xc2, 165, 1, 1425 },
+{ 0xc2, 166, 1, 1424 },
+{ 0x42, 166, 1, 1422 },
+{ 0x6, 167, 1, 1423 },
+{ 0x61, 168, 1, 1405 },
+{ 0x61, 169, 1, 1404 },
+{ 0x21, 169, 1, 1402 },
+{ 0x3, 170, 0, 1403 },
+{ 0x22, 159, 1, 1597 },
+{ 0x22, 160, 1, 1596 },
+{ 0x11, 162, 1, 1527 },
+{ 0x11, 163, 1, 1526 },
+{ 0x22, 165, 1, 1497 },
+{ 0x22, 166, 1, 1496 },
+{ 0x11, 168, 1, 1477 },
+{ 0x11, 169, 0, 1476 },
+{ 0x12, 159, 1, 1599 },
+{ 0x12, 160, 1, 1598 },
+{ 0x9, 162, 1, 1529 },
+{ 0x9, 163, 1, 1528 },
+{ 0x12, 165, 1, 1499 },
+{ 0x12, 166, 1, 1498 },
+{ 0x9, 168, 1, 1479 },
+{ 0x9, 169, 0, 1478 },
+{ 0xa, 159, 1, 1601 },
+{ 0xa, 160, 1, 1600 },
+{ 0x5, 162, 1, 1531 },
+{ 0x5, 163, 1, 1530 },
+{ 0xa, 165, 1, 1501 },
+{ 0xa, 166, 1, 1500 },
+{ 0x5, 168, 1, 1481 },
+{ 0x5, 169, 0, 1480 },
+{ 0x6, 159, 1, 1605 },
+{ 0x6, 160, 1, 1604 },
+{ 0x2, 160, 1, 1602 },
+{ 0x2, 161, 1, 1603 },
+{ 0x3, 162, 1, 1535 },
+{ 0x3, 163, 1, 1534 },
+{ 0x1, 163, 1, 1532 },
+{ 0x1, 164, 1, 1533 },
+{ 0x6, 165, 1, 1505 },
+{ 0x6, 166, 1, 1504 },
+{ 0x2, 166, 1, 1502 },
+{ 0x2, 167, 1, 1503 },
+{ 0x3, 168, 1, 1485 },
+{ 0x3, 169, 1, 1484 },
+{ 0x1, 169, 1, 1482 },
+{ 0x1, 170, 0, 1483 },
+{ 0x221, 159, 1, 1567 },
+{ 0x221, 160, 1, 1566 },
+{ 0x221, 165, 1, 1427 },
+{ 0x221, 166, 0, 1426 },
+{ 0x121, 159, 1, 1569 },
+{ 0x121, 160, 1, 1568 },
+{ 0x121, 165, 1, 1429 },
+{ 0x121, 166, 0, 1428 },
+{ 0xa1, 159, 1, 1571 },
+{ 0xa1, 160, 1, 1570 },
+{ 0xa1, 165, 1, 1431 },
+{ 0xa1, 166, 0, 1430 },
+{ 0x61, 159, 1, 1575 },
+{ 0x61, 160, 1, 1574 },
+{ 0x21, 160, 1, 1572 },
+{ 0x3, 161, 1, 1573 },
+{ 0x61, 165, 1, 1435 },
+{ 0x61, 166, 1, 1434 },
+{ 0x21, 166, 1, 1432 },
+{ 0x3, 167, 0, 1433 },
+{ 0x11, 159, 1, 1607 },
+{ 0x11, 160, 1, 1606 },
+{ 0x11, 165, 1, 1507 },
+{ 0x11, 166, 0, 1506 },
+{ 0x9, 159, 1, 1609 },
+{ 0x9, 160, 1, 1608 },
+{ 0x9, 165, 1, 1509 },
+{ 0x9, 166, 0, 1508 },
+{ 0x5, 159, 1, 1611 },
+{ 0x5, 160, 1, 1610 },
+{ 0x5, 165, 1, 1511 },
+{ 0x5, 166, 0, 1510 },
+{ 0x3, 159, 1, 1615 },
+{ 0x3, 160, 1, 1614 },
+{ 0x1, 160, 1, 1612 },
+{ 0x1, 161, 1, 1613 },
+{ 0x3, 165, 1, 1515 },
+{ 0x3, 166, 1, 1514 },
+{ 0x1, 166, 1, 1512 },
+{ 0x1, 167, 0, 1513 },
+{ 0x442, 205, 0, 1616 },
+{ 0x242, 205, 0, 1617 },
+{ 0x142, 205, 0, 1618 },
+{ 0xc2, 205, 1, 1620 },
+{ 0x6, 206, 1, 1619 },
+{ 0x1, 439, 0, 981 },
+{ 0x22, 205, 0, 1626 },
+{ 0x12, 205, 0, 1627 },
+{ 0xa, 205, 0, 1628 },
+{ 0x6, 205, 1, 1630 },
+{ 0x2, 206, 1, 1629 },
+{ 0x2, 367, 0, 1010 },
+{ 0x221, 205, 0, 1621 },
+{ 0x121, 205, 0, 1622 },
+{ 0xa1, 205, 0, 1623 },
+{ 0x61, 205, 1, 1625 },
+{ 0x3, 206, 1, 1624 },
+{ 0x1, 433, 0, 982 },
+{ 0x11, 205, 0, 1631 },
+{ 0x9, 205, 0, 1632 },
+{ 0x5, 205, 0, 1633 },
+{ 0x3, 205, 1, 1635 },
+{ 0x1, 206, 1, 1634 },
+{ 0x1, 367, 0, 1011 },
+{ 0x4, 211, 0, 1636 },
+{ 0x1, 211, 0, 1638 },
+{ 0x1, 218, 0, 1639 },
+{ 0x1, 217, 1, 1640 },
+{ 0x2, 211, 0, 1637 },
+{ 0x1, 196, 0, 1641 },
+{ 0x880, 202, 0, 1642 },
+{ 0x480, 202, 0, 1643 },
+{ 0x280, 202, 0, 1644 },
+{ 0x180, 202, 1, 1646 },
+{ 0x80, 203, 0, 1645 },
+{ 0x440, 202, 1, 1657 },
+{ 0x88, 204, 0, 1647 },
+{ 0x240, 202, 1, 1658 },
+{ 0x48, 204, 0, 1648 },
+{ 0x140, 202, 1, 1659 },
+{ 0x28, 204, 0, 1649 },
+{ 0xc0, 202, 1, 1661 },
+{ 0x40, 203, 1, 1660 },
+{ 0x18, 204, 1, 1651 },
+{ 0x8, 204, 0, 1650 },
+{ 0x220, 202, 1, 1662 },
+{ 0x44, 204, 0, 1652 },
+{ 0x120, 202, 1, 1663 },
+{ 0x24, 204, 0, 1653 },
+{ 0xa0, 202, 1, 1664 },
+{ 0x14, 204, 0, 1654 },
+{ 0x60, 202, 1, 1666 },
+{ 0x20, 203, 1, 1665 },
+{ 0xc, 204, 1, 1656 },
+{ 0x4, 204, 0, 1655 },
+{ 0x110, 202, 0, 1667 },
+{ 0x90, 202, 0, 1668 },
+{ 0x50, 202, 0, 1669 },
+{ 0x30, 202, 1, 1671 },
+{ 0x10, 203, 1, 1670 },
+{ 0x1, 385, 0, 974 },
+{ 0x88, 202, 0, 1672 },
+{ 0x48, 202, 0, 1673 },
+{ 0x28, 202, 0, 1674 },
+{ 0x18, 202, 1, 1676 },
+{ 0x8, 203, 1, 1675 },
+{ 0xc, 368, 0, 1007 },
+{ 0x44, 202, 1, 1687 },
+{ 0x22, 204, 0, 1677 },
+{ 0x24, 202, 1, 1688 },
+{ 0x12, 204, 0, 1678 },
+{ 0x14, 202, 1, 1689 },
+{ 0xa, 204, 0, 1679 },
+{ 0xc, 202, 1, 1691 },
+{ 0x4, 203, 1, 1690 },
+{ 0x6, 204, 1, 1681 },
+{ 0x2, 204, 1, 1680 },
+{ 0x6, 368, 0, 1008 },
+{ 0x22, 202, 1, 1692 },
+{ 0x11, 204, 0, 1682 },
+{ 0x12, 202, 1, 1693 },
+{ 0x9, 204, 0, 1683 },
+{ 0xa, 202, 1, 1694 },
+{ 0x5, 204, 0, 1684 },
+{ 0x6, 202, 1, 1696 },
+{ 0x2, 203, 1, 1695 },
+{ 0x3, 204, 1, 1686 },
+{ 0x1, 204, 1, 1685 },
+{ 0x3, 368, 0, 1009 },
+{ 0x11, 202, 0, 1697 },
+{ 0x9, 202, 0, 1698 },
+{ 0x5, 202, 0, 1699 },
+{ 0x3, 202, 1, 1701 },
+{ 0x1, 203, 0, 1700 },
+{ 0x8, 198, 0, 1702 },
+{ 0x4, 198, 0, 1703 },
+{ 0x2, 198, 0, 1704 },
+{ 0x1, 198, 1, 1706 },
+{ 0x1, 199, 1, 1705 },
+{ 0x1, 332, 0, 988 },
+{ 0x8, 200, 0, 1707 },
+{ 0x4, 200, 0, 1708 },
+{ 0x2, 200, 0, 1709 },
+{ 0x1, 200, 1, 1711 },
+{ 0x1, 201, 1, 1710 },
+{ 0x1, 331, 0, 989 },
+{ 0x8, 209, 0, 1712 },
+{ 0x4, 209, 0, 1713 },
+{ 0x2, 209, 0, 1714 },
+{ 0x1, 209, 1, 1716 },
+{ 0x1, 210, 1, 1715 },
+{ 0x1, 330, 0, 990 },
+{ 0x8, 212, 0, 1717 },
+{ 0x4, 212, 0, 1718 },
+{ 0x2, 212, 0, 1719 },
+{ 0x1, 212, 1, 1721 },
+{ 0x1, 213, 1, 1720 },
+{ 0x1, 329, 0, 991 },
+{ 0x8, 224, 0, 1722 },
+{ 0x4, 224, 0, 1723 },
+{ 0x2, 224, 0, 1724 },
+{ 0x1, 224, 1, 1726 },
+{ 0x1, 225, 0, 1725 },
+{ 0x8, 222, 0, 1727 },
+{ 0x4, 222, 0, 1728 },
+{ 0x2, 222, 0, 1729 },
+{ 0x1, 222, 1, 1731 },
+{ 0x1, 223, 0, 1730 },
+{ 0x1, 240, 0, 1732 },
+{ 0x1, 340, 0, 1733 },
+{ 0x1, 33, 0, 1734 },
+{ 0x8, 151, 0, 1735 },
+{ 0x4, 151, 0, 1736 },
+{ 0x2, 151, 0, 1737 },
+{ 0x1, 151, 1, 1739 },
+{ 0x1, 152, 0, 1738 },
+{ 0x8, 157, 0, 1740 },
+{ 0x4, 157, 0, 1741 },
+{ 0x2, 157, 0, 1742 },
+{ 0x1, 157, 1, 1744 },
+{ 0x1, 158, 0, 1743 },
+{ 0x8, 231, 0, 1745 },
+{ 0x4, 231, 0, 1746 },
+{ 0x2, 231, 0, 1747 },
+{ 0x1, 231, 1, 1749 },
+{ 0x1, 232, 0, 1748 },
+{ 0x1, 173, 0, 1750 },
+{ 0x442, 171, 0, 1751 },
+{ 0x242, 171, 0, 1752 },
+{ 0x142, 171, 0, 1753 },
+{ 0xc2, 171, 1, 1755 },
+{ 0x6, 172, 0, 1754 },
+{ 0x22, 171, 0, 1761 },
+{ 0x12, 171, 0, 1762 },
+{ 0xa, 171, 0, 1763 },
+{ 0x6, 171, 1, 1765 },
+{ 0x2, 172, 1, 1764 },
+{ 0x1, 135, 0, 1165 },
+{ 0x221, 171, 0, 1756 },
+{ 0x121, 171, 0, 1757 },
+{ 0xa1, 171, 0, 1758 },
+{ 0x61, 171, 1, 1760 },
+{ 0x3, 172, 0, 1759 },
+{ 0x11, 171, 0, 1766 },
+{ 0x9, 171, 0, 1767 },
+{ 0x5, 171, 0, 1768 },
+{ 0x3, 171, 1, 1770 },
+{ 0x1, 172, 1, 1769 },
+{ 0x1, 134, 0, 1166 },
+{ 0x1, 237, 0, 1771 },
+{ 0x1, 195, 0, 1772 },
+{ 0x1, 149, 0, 1773 },
+{ 0x1, 148, 0, 1774 },
+{ 0x4, 234, 0, 1775 },
+{ 0x2, 234, 0, 1776 },
+{ 0x1, 234, 0, 1777 },
+{ 0x1, 197, 0, 1778 },
+{ 0x2, 235, 0, 1779 },
+{ 0x1, 235, 0, 1780 },
+{ 0x4, 185, 0, 1781 },
+{ 0x2, 185, 0, 1782 },
+{ 0x1, 185, 0, 1783 },
+{ 0x4, 182, 0, 1784 },
+{ 0x1, 190, 0, 1787 },
+{ 0x1, 189, 1, 1788 },
+{ 0x2, 182, 0, 1785 },
+{ 0x1, 142, 0, 1789 },
+{ 0x1, 297, 1, 1790 },
+{ 0x1, 182, 0, 1786 },
+{ 0x8, 144, 0, 1791 },
+{ 0x4, 144, 0, 1792 },
+{ 0x2, 144, 0, 1793 },
+{ 0x1, 144, 1, 1795 },
+{ 0x1, 145, 0, 1794 },
+{ 0x8, 146, 0, 1796 },
+{ 0x4, 146, 0, 1797 },
+{ 0x2, 146, 0, 1798 },
+{ 0x1, 146, 1, 1800 },
+{ 0x1, 147, 1, 1799 },
+{ 0x1, 426, 0, 1167 },
+{ 0x8, 180, 0, 1801 },
+{ 0x4, 180, 0, 1802 },
+{ 0x2, 180, 0, 1803 },
+{ 0x1, 180, 1, 1805 },
+{ 0x1, 181, 1, 1804 },
+{ 0x1, 425, 0, 1168 },
+{ 0x8, 183, 0, 1806 },
+{ 0x4, 183, 0, 1807 },
+{ 0x2, 183, 0, 1808 },
+{ 0x1, 183, 1, 1810 },
+{ 0x1, 184, 1, 1809 },
+{ 0x1, 424, 0, 1169 },
+{ 0x8, 228, 0, 1811 },
+{ 0x4, 228, 0, 1812 },
+{ 0x2, 228, 0, 1813 },
+{ 0x1, 228, 1, 1815 },
+{ 0x1, 229, 0, 1814 },
+{ 0x8, 226, 0, 1816 },
+{ 0x4, 226, 0, 1817 },
+{ 0x2, 226, 0, 1818 },
+{ 0x1, 226, 1, 1820 },
+{ 0x1, 227, 0, 1819 },
+{ 0x8, 44, 0, 1825 },
+{ 0x18, 44, 0, 1821 },
+{ 0x4, 44, 0, 1826 },
+{ 0xc, 44, 0, 1822 },
+{ 0x2, 44, 0, 1827 },
+{ 0x6, 44, 0, 1823 },
+{ 0x1, 44, 0, 1828 },
+{ 0x3, 44, 0, 1824 },
+{ 0x51, 30, 0, 1830 },
+{ 0xd1, 30, 0, 1829 },
+{ 0x31, 30, 1, 1840 },
+{ 0x11, 31, 0, 1839 },
+{ 0x71, 30, 1, 1838 },
+{ 0x31, 31, 0, 1837 },
+{ 0x29, 30, 0, 1832 },
+{ 0x69, 30, 0, 1831 },
+{ 0x19, 30, 1, 1844 },
+{ 0x9, 31, 0, 1843 },
+{ 0x39, 30, 1, 1842 },
+{ 0x19, 31, 0, 1841 },
+{ 0x15, 30, 0, 1834 },
+{ 0x35, 30, 0, 1833 },
+{ 0xd, 30, 1, 1848 },
+{ 0x5, 31, 0, 1847 },
+{ 0x1d, 30, 1, 1846 },
+{ 0xd, 31, 0, 1845 },
+{ 0xb, 30, 0, 1836 },
+{ 0x1b, 30, 0, 1835 },
+{ 0x7, 30, 1, 1852 },
+{ 0x3, 31, 0, 1851 },
+{ 0xf, 30, 1, 1850 },
+{ 0x7, 31, 0, 1849 },
+{ 0xa2, 28, 0, 1854 },
+{ 0x1a2, 28, 0, 1853 },
+{ 0x62, 28, 1, 1864 },
+{ 0x22, 29, 0, 1863 },
+{ 0xe2, 28, 1, 1862 },
+{ 0x62, 29, 0, 1861 },
+{ 0x52, 28, 0, 1856 },
+{ 0xd2, 28, 0, 1855 },
+{ 0x32, 28, 1, 1868 },
+{ 0x12, 29, 0, 1867 },
+{ 0x72, 28, 1, 1866 },
+{ 0x32, 29, 0, 1865 },
+{ 0x2a, 28, 0, 1858 },
+{ 0x6a, 28, 0, 1857 },
+{ 0x1a, 28, 1, 1872 },
+{ 0xa, 29, 0, 1871 },
+{ 0x3a, 28, 1, 1870 },
+{ 0x1a, 29, 0, 1869 },
+{ 0x16, 28, 0, 1860 },
+{ 0x36, 28, 0, 1859 },
+{ 0xe, 28, 1, 1876 },
+{ 0x6, 29, 0, 1875 },
+{ 0x1e, 28, 1, 1874 },
+{ 0xe, 29, 0, 1873 },
+{ 0x51, 28, 0, 1878 },
+{ 0xd1, 28, 0, 1877 },
+{ 0x31, 28, 1, 1888 },
+{ 0x11, 29, 0, 1887 },
+{ 0x71, 28, 1, 1886 },
+{ 0x31, 29, 0, 1885 },
+{ 0x29, 28, 0, 1880 },
+{ 0x69, 28, 0, 1879 },
+{ 0x19, 28, 1, 1892 },
+{ 0x9, 29, 0, 1891 },
+{ 0x39, 28, 1, 1890 },
+{ 0x19, 29, 0, 1889 },
+{ 0x15, 28, 0, 1882 },
+{ 0x35, 28, 0, 1881 },
+{ 0xd, 28, 1, 1896 },
+{ 0x5, 29, 0, 1895 },
+{ 0x1d, 28, 1, 1894 },
+{ 0xd, 29, 0, 1893 },
+{ 0xb, 28, 0, 1884 },
+{ 0x1b, 28, 0, 1883 },
+{ 0x7, 28, 1, 1900 },
+{ 0x3, 29, 0, 1899 },
+{ 0xf, 28, 1, 1898 },
+{ 0x7, 29, 0, 1897 },
+{ 0x51, 26, 0, 1902 },
+{ 0xd1, 26, 0, 1901 },
+{ 0x31, 26, 1, 1912 },
+{ 0x11, 27, 0, 1911 },
+{ 0x71, 26, 1, 1910 },
+{ 0x31, 27, 0, 1909 },
+{ 0x29, 26, 0, 1904 },
+{ 0x69, 26, 0, 1903 },
+{ 0x19, 26, 1, 1916 },
+{ 0x9, 27, 0, 1915 },
+{ 0x39, 26, 1, 1914 },
+{ 0x19, 27, 0, 1913 },
+{ 0x15, 26, 0, 1906 },
+{ 0x35, 26, 0, 1905 },
+{ 0xd, 26, 1, 1920 },
+{ 0x5, 27, 0, 1919 },
+{ 0x1d, 26, 1, 1918 },
+{ 0xd, 27, 0, 1917 },
+{ 0xb, 26, 0, 1908 },
+{ 0x1b, 26, 0, 1907 },
+{ 0x7, 26, 1, 1924 },
+{ 0x3, 27, 0, 1923 },
+{ 0xf, 26, 1, 1922 },
+{ 0x7, 27, 0, 1921 },
+{ 0xa2, 24, 0, 1926 },
+{ 0x1a2, 24, 0, 1925 },
+{ 0x62, 24, 1, 1936 },
+{ 0x22, 25, 0, 1935 },
+{ 0xe2, 24, 1, 1934 },
+{ 0x62, 25, 0, 1933 },
+{ 0x52, 24, 0, 1928 },
+{ 0xd2, 24, 0, 1927 },
+{ 0x32, 24, 1, 1940 },
+{ 0x12, 25, 0, 1939 },
+{ 0x72, 24, 1, 1938 },
+{ 0x32, 25, 0, 1937 },
+{ 0x2a, 24, 0, 1930 },
+{ 0x6a, 24, 0, 1929 },
+{ 0x1a, 24, 1, 1944 },
+{ 0xa, 25, 0, 1943 },
+{ 0x3a, 24, 1, 1942 },
+{ 0x1a, 25, 0, 1941 },
+{ 0x16, 24, 0, 1932 },
+{ 0x36, 24, 0, 1931 },
+{ 0xe, 24, 1, 1948 },
+{ 0x6, 25, 0, 1947 },
+{ 0x1e, 24, 1, 1946 },
+{ 0xe, 25, 0, 1945 },
+{ 0x51, 24, 0, 1950 },
+{ 0xd1, 24, 0, 1949 },
+{ 0x31, 24, 1, 1960 },
+{ 0x11, 25, 0, 1959 },
+{ 0x71, 24, 1, 1958 },
+{ 0x31, 25, 0, 1957 },
+{ 0x29, 24, 0, 1952 },
+{ 0x69, 24, 0, 1951 },
+{ 0x19, 24, 1, 1964 },
+{ 0x9, 25, 0, 1963 },
+{ 0x39, 24, 1, 1962 },
+{ 0x19, 25, 0, 1961 },
+{ 0x15, 24, 0, 1954 },
+{ 0x35, 24, 0, 1953 },
+{ 0xd, 24, 1, 1968 },
+{ 0x5, 25, 0, 1967 },
+{ 0x1d, 24, 1, 1966 },
+{ 0xd, 25, 0, 1965 },
+{ 0xb, 24, 0, 1956 },
+{ 0x1b, 24, 0, 1955 },
+{ 0x7, 24, 1, 1972 },
+{ 0x3, 25, 0, 1971 },
+{ 0xf, 24, 1, 1970 },
+{ 0x7, 25, 0, 1969 },
+{ 0x51, 22, 1, 1998 },
+{ 0x50, 22, 0, 1974 },
+{ 0xd1, 22, 1, 1997 },
+{ 0xd0, 22, 0, 1973 },
+{ 0x31, 22, 1, 2008 },
+{ 0x30, 22, 1, 1984 },
+{ 0x11, 23, 1, 2007 },
+{ 0x10, 23, 0, 1983 },
+{ 0x71, 22, 1, 2006 },
+{ 0x70, 22, 1, 1982 },
+{ 0x31, 23, 1, 2005 },
+{ 0x30, 23, 0, 1981 },
+{ 0x29, 22, 1, 2000 },
+{ 0x28, 22, 0, 1976 },
+{ 0x69, 22, 1, 1999 },
+{ 0x68, 22, 0, 1975 },
+{ 0x19, 22, 1, 2012 },
+{ 0x18, 22, 1, 1988 },
+{ 0x9, 23, 1, 2011 },
+{ 0x8, 23, 0, 1987 },
+{ 0x39, 22, 1, 2010 },
+{ 0x38, 22, 1, 1986 },
+{ 0x19, 23, 1, 2009 },
+{ 0x18, 23, 0, 1985 },
+{ 0x15, 22, 1, 2002 },
+{ 0x14, 22, 0, 1978 },
+{ 0x35, 22, 1, 2001 },
+{ 0x34, 22, 0, 1977 },
+{ 0xd, 22, 1, 2016 },
+{ 0xc, 22, 1, 1992 },
+{ 0x5, 23, 1, 2015 },
+{ 0x4, 23, 0, 1991 },
+{ 0x1d, 22, 1, 2014 },
+{ 0x1c, 22, 1, 1990 },
+{ 0xd, 23, 1, 2013 },
+{ 0xc, 23, 0, 1989 },
+{ 0xb, 22, 1, 2004 },
+{ 0xa, 22, 0, 1980 },
+{ 0x1b, 22, 1, 2003 },
+{ 0x1a, 22, 0, 1979 },
+{ 0x7, 22, 1, 2020 },
+{ 0x6, 22, 1, 1996 },
+{ 0x3, 23, 1, 2019 },
+{ 0x2, 23, 0, 1995 },
+{ 0xf, 22, 1, 2018 },
+{ 0xe, 22, 1, 1994 },
+{ 0x7, 23, 1, 2017 },
+{ 0x6, 23, 0, 1993 },
+{ 0x8, 21, 0, 2022 },
+{ 0x18, 21, 0, 2021 },
+{ 0x1, 21, 1, 2026 },
+{ 0x2, 21, 0, 2025 },
+{ 0x3, 21, 1, 2024 },
+{ 0x4, 21, 0, 2023 },
+{ 0x1, 239, 0, 2027 },
+{ 0x1, 339, 0, 2028 },
+{ 0x14, 43, 0, 2031 },
+{ 0x34, 43, 0, 2029 },
+{ 0xc, 43, 0, 2032 },
+{ 0x1c, 43, 0, 2030 },
+{ 0x2, 43, 0, 2035 },
+{ 0x6, 43, 0, 2033 },
+{ 0x1, 43, 0, 2036 },
+{ 0x3, 43, 0, 2034 },
+{ 0x51, 19, 0, 2038 },
+{ 0xd1, 19, 0, 2037 },
+{ 0x31, 19, 1, 2048 },
+{ 0x11, 20, 0, 2047 },
+{ 0x71, 19, 1, 2046 },
+{ 0x31, 20, 0, 2045 },
+{ 0x29, 19, 0, 2040 },
+{ 0x69, 19, 0, 2039 },
+{ 0x19, 19, 1, 2052 },
+{ 0x9, 20, 0, 2051 },
+{ 0x39, 19, 1, 2050 },
+{ 0x19, 20, 0, 2049 },
+{ 0x15, 19, 0, 2042 },
+{ 0x35, 19, 0, 2041 },
+{ 0xd, 19, 1, 2056 },
+{ 0x5, 20, 0, 2055 },
+{ 0x1d, 19, 1, 2054 },
+{ 0xd, 20, 0, 2053 },
+{ 0xb, 19, 0, 2044 },
+{ 0x1b, 19, 0, 2043 },
+{ 0x7, 19, 1, 2060 },
+{ 0x3, 20, 0, 2059 },
+{ 0xf, 19, 1, 2058 },
+{ 0x7, 20, 0, 2057 },
+{ 0x1, 32, 0, 2061 },
+{ 0x1, 140, 0, 2062 },
+{ 0x2, 45, 0, 2063 },
+{ 0x1, 45, 0, 2064 },
+{ 0x1, 387, 0, 2065 },
+{ 0x2, 52, 0, 2066 },
+{ 0x1, 52, 0, 2067 },
+{ 0x1, 133, 0, 2068 },
+{ 0x51, 17, 0, 2070 },
+{ 0xd1, 17, 0, 2069 },
+{ 0x31, 17, 1, 2080 },
+{ 0x11, 18, 0, 2079 },
+{ 0x71, 17, 1, 2078 },
+{ 0x31, 18, 0, 2077 },
+{ 0x29, 17, 0, 2072 },
+{ 0x69, 17, 0, 2071 },
+{ 0x19, 17, 1, 2084 },
+{ 0x9, 18, 0, 2083 },
+{ 0x39, 17, 1, 2082 },
+{ 0x19, 18, 0, 2081 },
+{ 0x15, 17, 0, 2074 },
+{ 0x35, 17, 0, 2073 },
+{ 0xd, 17, 1, 2088 },
+{ 0x5, 18, 0, 2087 },
+{ 0x1d, 17, 1, 2086 },
+{ 0xd, 18, 0, 2085 },
+{ 0xb, 17, 0, 2076 },
+{ 0x1b, 17, 0, 2075 },
+{ 0x7, 17, 1, 2092 },
+{ 0x3, 18, 0, 2091 },
+{ 0xf, 17, 1, 2090 },
+{ 0x7, 18, 0, 2089 },
+{ 0xa20, 15, 0, 2094 },
+{ 0x1a20, 15, 0, 2093 },
+{ 0x620, 15, 1, 2104 },
+{ 0x220, 16, 0, 2103 },
+{ 0xe20, 15, 1, 2102 },
+{ 0x620, 16, 0, 2101 },
+{ 0x520, 15, 0, 2096 },
+{ 0xd20, 15, 0, 2095 },
+{ 0x320, 15, 1, 2108 },
+{ 0x120, 16, 0, 2107 },
+{ 0x720, 15, 1, 2106 },
+{ 0x320, 16, 0, 2105 },
+{ 0x2a0, 15, 0, 2098 },
+{ 0x6a0, 15, 0, 2097 },
+{ 0x1a0, 15, 1, 2112 },
+{ 0xa0, 16, 0, 2111 },
+{ 0x3a0, 15, 1, 2110 },
+{ 0x1a0, 16, 0, 2109 },
+{ 0x160, 15, 0, 2100 },
+{ 0x360, 15, 0, 2099 },
+{ 0xe0, 15, 1, 2116 },
+{ 0x60, 16, 0, 2115 },
+{ 0x1e0, 15, 1, 2114 },
+{ 0xe0, 16, 0, 2113 },
+{ 0x51, 15, 1, 2142 },
+{ 0x50, 15, 0, 2118 },
+{ 0xd1, 15, 1, 2141 },
+{ 0xd0, 15, 0, 2117 },
+{ 0x31, 15, 1, 2152 },
+{ 0x30, 15, 1, 2128 },
+{ 0x11, 16, 1, 2151 },
+{ 0x10, 16, 0, 2127 },
+{ 0x71, 15, 1, 2150 },
+{ 0x70, 15, 1, 2126 },
+{ 0x31, 16, 1, 2149 },
+{ 0x30, 16, 0, 2125 },
+{ 0x29, 15, 1, 2144 },
+{ 0x28, 15, 0, 2120 },
+{ 0x69, 15, 1, 2143 },
+{ 0x68, 15, 0, 2119 },
+{ 0x19, 15, 1, 2156 },
+{ 0x18, 15, 1, 2132 },
+{ 0x9, 16, 1, 2155 },
+{ 0x8, 16, 0, 2131 },
+{ 0x39, 15, 1, 2154 },
+{ 0x38, 15, 1, 2130 },
+{ 0x19, 16, 1, 2153 },
+{ 0x18, 16, 0, 2129 },
+{ 0x15, 15, 1, 2146 },
+{ 0x14, 15, 0, 2122 },
+{ 0x35, 15, 1, 2145 },
+{ 0x34, 15, 0, 2121 },
+{ 0xd, 15, 1, 2160 },
+{ 0xc, 15, 1, 2136 },
+{ 0x5, 16, 1, 2159 },
+{ 0x4, 16, 0, 2135 },
+{ 0x1d, 15, 1, 2158 },
+{ 0x1c, 15, 1, 2134 },
+{ 0xd, 16, 1, 2157 },
+{ 0xc, 16, 0, 2133 },
+{ 0xb, 15, 1, 2148 },
+{ 0xa, 15, 0, 2124 },
+{ 0x1b, 15, 1, 2147 },
+{ 0x1a, 15, 0, 2123 },
+{ 0x7, 15, 1, 2164 },
+{ 0x6, 15, 1, 2140 },
+{ 0x3, 16, 1, 2163 },
+{ 0x2, 16, 0, 2139 },
+{ 0xf, 15, 1, 2162 },
+{ 0xe, 15, 1, 2138 },
+{ 0x7, 16, 1, 2161 },
+{ 0x6, 16, 0, 2137 },
+{ 0x8, 14, 0, 2166 },
+{ 0x18, 14, 0, 2165 },
+{ 0x1, 14, 1, 2170 },
+{ 0x2, 14, 0, 2169 },
+{ 0x3, 14, 1, 2168 },
+{ 0x4, 14, 0, 2167 },
+{ 0x1, 109, 1, 2322 },
+{ 0x1, 110, 1, 2321 },
+{ 0x1, 111, 1, 2320 },
+{ 0x1, 112, 1, 2319 },
+{ 0x1, 113, 1, 2318 },
+{ 0x1, 114, 1, 2317 },
+{ 0x1, 115, 1, 2316 },
+{ 0x1, 116, 1, 2315 },
+{ 0x39, 41, 1, 22 },
+{ 0x19, 42, 0, 21 },
+{ 0x3, 109, 1, 2314 },
+{ 0x3, 110, 1, 2313 },
+{ 0x3, 111, 1, 2312 },
+{ 0x3, 112, 1, 2311 },
+{ 0x3, 113, 1, 2310 },
+{ 0x3, 114, 1, 2309 },
+{ 0x3, 115, 1, 2308 },
+{ 0x3, 116, 1, 2307 },
+{ 0x69, 41, 0, 11 },
+{ 0x14, 100, 1, 2302 },
+{ 0x22, 101, 1, 2299 },
+{ 0x44, 101, 1, 2301 },
+{ 0xa, 108, 1, 2300 },
+{ 0xd1, 41, 0, 9 },
+{ 0x34, 100, 1, 2174 },
+{ 0xc4, 101, 1, 2173 },
+{ 0x1c, 107, 1, 2171 },
+{ 0xe, 122, 0, 2172 },
+{ 0xc, 100, 1, 2462 },
+{ 0xa, 101, 1, 2459 },
+{ 0x14, 101, 1, 2461 },
+{ 0x6, 108, 0, 2460 },
+{ 0x2, 100, 1, 2186 },
+{ 0x2, 101, 1, 2185 },
+{ 0x2, 106, 1, 2184 },
+{ 0x2, 107, 0, 2183 },
+{ 0x12, 100, 1, 2182 },
+{ 0x42, 101, 1, 2181 },
+{ 0x6, 106, 1, 2180 },
+{ 0x6, 107, 0, 2179 },
+{ 0xa, 100, 1, 2306 },
+{ 0x12, 101, 1, 2305 },
+{ 0x24, 101, 1, 2303 },
+{ 0x5, 108, 1, 2304 },
+{ 0x71, 41, 1, 18 },
+{ 0x31, 42, 0, 17 },
+{ 0x1a, 100, 1, 2178 },
+{ 0x32, 101, 1, 2177 },
+{ 0x1a, 107, 1, 2175 },
+{ 0x7, 122, 0, 2176 },
+{ 0x6, 100, 1, 2466 },
+{ 0x6, 101, 1, 2465 },
+{ 0xc, 101, 1, 2463 },
+{ 0x3, 108, 0, 2464 },
+{ 0x1, 100, 1, 2482 },
+{ 0x1, 101, 1, 2481 },
+{ 0x1, 102, 1, 2480 },
+{ 0x1, 103, 1, 2479 },
+{ 0x1, 104, 1, 2478 },
+{ 0x1, 105, 1, 2477 },
+{ 0x1, 106, 1, 2476 },
+{ 0x1, 107, 0, 2475 },
+{ 0x3, 100, 1, 2474 },
+{ 0x3, 101, 1, 2473 },
+{ 0x3, 102, 1, 2472 },
+{ 0x3, 103, 1, 2471 },
+{ 0x3, 104, 1, 2470 },
+{ 0x3, 105, 1, 2469 },
+{ 0x3, 106, 1, 2468 },
+{ 0x3, 107, 0, 2467 },
+{ 0x8, 67, 1, 2346 },
+{ 0x8, 68, 1, 2345 },
+{ 0x2, 73, 1, 2340 },
+{ 0x2, 74, 1, 2339 },
+{ 0x1, 76, 1, 2344 },
+{ 0x1, 77, 1, 2343 },
+{ 0x1, 78, 1, 2342 },
+{ 0x1, 79, 1, 2341 },
+{ 0xf, 41, 1, 30 },
+{ 0x7, 42, 0, 29 },
+{ 0x18, 67, 1, 2338 },
+{ 0x18, 68, 1, 2337 },
+{ 0x6, 73, 1, 2332 },
+{ 0x6, 74, 1, 2331 },
+{ 0x3, 76, 1, 2336 },
+{ 0x3, 77, 1, 2335 },
+{ 0x3, 78, 1, 2334 },
+{ 0x3, 79, 1, 2333 },
+{ 0x1b, 41, 0, 15 },
+{ 0x14, 67, 1, 2326 },
+{ 0x22, 68, 1, 2323 },
+{ 0x44, 68, 1, 2325 },
+{ 0xa, 75, 1, 2324 },
+{ 0x35, 41, 0, 13 },
+{ 0x34, 67, 1, 2190 },
+{ 0xc4, 68, 1, 2189 },
+{ 0x38, 74, 1, 2187 },
+{ 0xe, 85, 0, 2188 },
+{ 0xc, 67, 1, 2486 },
+{ 0xa, 68, 1, 2483 },
+{ 0x14, 68, 1, 2485 },
+{ 0x6, 75, 0, 2484 },
+{ 0x2, 67, 1, 2202 },
+{ 0x2, 68, 1, 2201 },
+{ 0x4, 73, 1, 2200 },
+{ 0x4, 74, 0, 2199 },
+{ 0x12, 67, 1, 2198 },
+{ 0x42, 68, 1, 2197 },
+{ 0xc, 73, 1, 2196 },
+{ 0xc, 74, 0, 2195 },
+{ 0xa, 67, 1, 2330 },
+{ 0x12, 68, 1, 2329 },
+{ 0x24, 68, 1, 2327 },
+{ 0x5, 75, 1, 2328 },
+{ 0x1d, 41, 1, 26 },
+{ 0xd, 42, 0, 25 },
+{ 0x1a, 67, 1, 2194 },
+{ 0x32, 68, 1, 2193 },
+{ 0x34, 74, 1, 2191 },
+{ 0x7, 85, 0, 2192 },
+{ 0x6, 67, 1, 2490 },
+{ 0x6, 68, 1, 2489 },
+{ 0xc, 68, 1, 2487 },
+{ 0x3, 75, 0, 2488 },
+{ 0x1, 67, 1, 2506 },
+{ 0x1, 68, 1, 2505 },
+{ 0x1, 69, 1, 2504 },
+{ 0x1, 70, 1, 2503 },
+{ 0x1, 71, 1, 2502 },
+{ 0x1, 72, 1, 2501 },
+{ 0x1, 73, 1, 2500 },
+{ 0x1, 74, 0, 2499 },
+{ 0x3, 67, 1, 2498 },
+{ 0x3, 68, 1, 2497 },
+{ 0x3, 69, 1, 2496 },
+{ 0x3, 70, 1, 2495 },
+{ 0x3, 71, 1, 2494 },
+{ 0x3, 72, 1, 2493 },
+{ 0x3, 73, 1, 2492 },
+{ 0x3, 74, 0, 2491 },
+{ 0x28, 95, 1, 2354 },
+{ 0x44, 96, 1, 2349 },
+{ 0x88, 96, 1, 2353 },
+{ 0x44, 97, 1, 2348 },
+{ 0x88, 97, 1, 2352 },
+{ 0x44, 98, 1, 2347 },
+{ 0x88, 98, 1, 2351 },
+{ 0x28, 99, 0, 2350 },
+{ 0x68, 95, 1, 2210 },
+{ 0x188, 96, 1, 2209 },
+{ 0x188, 97, 1, 2208 },
+{ 0x188, 98, 1, 2207 },
+{ 0x38, 118, 1, 2206 },
+{ 0x38, 119, 1, 2205 },
+{ 0x38, 120, 1, 2204 },
+{ 0x38, 121, 0, 2203 },
+{ 0x18, 95, 1, 2514 },
+{ 0x14, 96, 1, 2509 },
+{ 0x28, 96, 1, 2513 },
+{ 0x14, 97, 1, 2508 },
+{ 0x28, 97, 1, 2512 },
+{ 0x14, 98, 1, 2507 },
+{ 0x28, 98, 1, 2511 },
+{ 0x18, 99, 0, 2510 },
+{ 0x14, 95, 1, 2362 },
+{ 0x24, 96, 1, 2361 },
+{ 0x48, 96, 1, 2357 },
+{ 0x24, 97, 1, 2360 },
+{ 0x48, 97, 1, 2356 },
+{ 0x24, 98, 1, 2359 },
+{ 0x48, 98, 1, 2355 },
+{ 0x14, 99, 0, 2358 },
+{ 0x34, 95, 1, 2218 },
+{ 0x64, 96, 1, 2217 },
+{ 0x64, 97, 1, 2216 },
+{ 0x64, 98, 1, 2215 },
+{ 0x1c, 118, 1, 2214 },
+{ 0x1c, 119, 1, 2213 },
+{ 0x1c, 120, 1, 2212 },
+{ 0x1c, 121, 0, 2211 },
+{ 0xc, 95, 1, 2522 },
+{ 0xc, 96, 1, 2521 },
+{ 0x18, 96, 1, 2517 },
+{ 0xc, 97, 1, 2520 },
+{ 0x18, 97, 1, 2516 },
+{ 0xc, 98, 1, 2519 },
+{ 0x18, 98, 1, 2515 },
+{ 0xc, 99, 0, 2518 },
+{ 0xa, 95, 1, 2370 },
+{ 0x11, 96, 1, 2365 },
+{ 0x22, 96, 1, 2369 },
+{ 0x11, 97, 1, 2364 },
+{ 0x22, 97, 1, 2368 },
+{ 0x11, 98, 1, 2363 },
+{ 0x22, 98, 1, 2367 },
+{ 0xa, 99, 0, 2366 },
+{ 0x1a, 95, 1, 2226 },
+{ 0x62, 96, 1, 2225 },
+{ 0x62, 97, 1, 2224 },
+{ 0x62, 98, 1, 2223 },
+{ 0xe, 118, 1, 2222 },
+{ 0xe, 119, 1, 2221 },
+{ 0xe, 120, 1, 2220 },
+{ 0xe, 121, 0, 2219 },
+{ 0x6, 95, 1, 2530 },
+{ 0x5, 96, 1, 2525 },
+{ 0xa, 96, 1, 2529 },
+{ 0x5, 97, 1, 2524 },
+{ 0xa, 97, 1, 2528 },
+{ 0x5, 98, 1, 2523 },
+{ 0xa, 98, 1, 2527 },
+{ 0x6, 99, 0, 2526 },
+{ 0x5, 95, 1, 2378 },
+{ 0x9, 96, 1, 2377 },
+{ 0x12, 96, 1, 2373 },
+{ 0x9, 97, 1, 2376 },
+{ 0x12, 97, 1, 2372 },
+{ 0x9, 98, 1, 2375 },
+{ 0x12, 98, 1, 2371 },
+{ 0x5, 99, 0, 2374 },
+{ 0xd, 95, 1, 2234 },
+{ 0x19, 96, 1, 2233 },
+{ 0x19, 97, 1, 2232 },
+{ 0x19, 98, 1, 2231 },
+{ 0x7, 118, 1, 2230 },
+{ 0x7, 119, 1, 2229 },
+{ 0x7, 120, 1, 2228 },
+{ 0x7, 121, 0, 2227 },
+{ 0x3, 95, 1, 2538 },
+{ 0x3, 96, 1, 2537 },
+{ 0x6, 96, 1, 2533 },
+{ 0x3, 97, 1, 2536 },
+{ 0x6, 97, 1, 2532 },
+{ 0x3, 98, 1, 2535 },
+{ 0x6, 98, 1, 2531 },
+{ 0x3, 99, 0, 2534 },
+{ 0x28, 62, 1, 2386 },
+{ 0x44, 63, 1, 2381 },
+{ 0x88, 63, 1, 2385 },
+{ 0x44, 64, 1, 2380 },
+{ 0x88, 64, 1, 2384 },
+{ 0x44, 65, 1, 2379 },
+{ 0x88, 65, 1, 2383 },
+{ 0x28, 66, 0, 2382 },
+{ 0x68, 62, 1, 2242 },
+{ 0x188, 63, 1, 2241 },
+{ 0x188, 64, 1, 2240 },
+{ 0x188, 65, 1, 2239 },
+{ 0x38, 81, 1, 2238 },
+{ 0x38, 82, 1, 2237 },
+{ 0x38, 83, 1, 2236 },
+{ 0x38, 84, 0, 2235 },
+{ 0x18, 62, 1, 2546 },
+{ 0x14, 63, 1, 2541 },
+{ 0x28, 63, 1, 2545 },
+{ 0x14, 64, 1, 2540 },
+{ 0x28, 64, 1, 2544 },
+{ 0x14, 65, 1, 2539 },
+{ 0x28, 65, 1, 2543 },
+{ 0x18, 66, 0, 2542 },
+{ 0x14, 62, 1, 2394 },
+{ 0x24, 63, 1, 2393 },
+{ 0x48, 63, 1, 2389 },
+{ 0x24, 64, 1, 2392 },
+{ 0x48, 64, 1, 2388 },
+{ 0x24, 65, 1, 2391 },
+{ 0x48, 65, 1, 2387 },
+{ 0x14, 66, 0, 2390 },
+{ 0x34, 62, 1, 2250 },
+{ 0x64, 63, 1, 2249 },
+{ 0x64, 64, 1, 2248 },
+{ 0x64, 65, 1, 2247 },
+{ 0x1c, 81, 1, 2246 },
+{ 0x1c, 82, 1, 2245 },
+{ 0x1c, 83, 1, 2244 },
+{ 0x1c, 84, 0, 2243 },
+{ 0xc, 62, 1, 2554 },
+{ 0xc, 63, 1, 2553 },
+{ 0x18, 63, 1, 2549 },
+{ 0xc, 64, 1, 2552 },
+{ 0x18, 64, 1, 2548 },
+{ 0xc, 65, 1, 2551 },
+{ 0x18, 65, 1, 2547 },
+{ 0xc, 66, 0, 2550 },
+{ 0xa, 62, 1, 2402 },
+{ 0x11, 63, 1, 2397 },
+{ 0x22, 63, 1, 2401 },
+{ 0x11, 64, 1, 2396 },
+{ 0x22, 64, 1, 2400 },
+{ 0x11, 65, 1, 2395 },
+{ 0x22, 65, 1, 2399 },
+{ 0xa, 66, 0, 2398 },
+{ 0x1a, 62, 1, 2258 },
+{ 0x62, 63, 1, 2257 },
+{ 0x62, 64, 1, 2256 },
+{ 0x62, 65, 1, 2255 },
+{ 0xe, 81, 1, 2254 },
+{ 0xe, 82, 1, 2253 },
+{ 0xe, 83, 1, 2252 },
+{ 0xe, 84, 0, 2251 },
+{ 0x6, 62, 1, 2562 },
+{ 0x5, 63, 1, 2557 },
+{ 0xa, 63, 1, 2561 },
+{ 0x5, 64, 1, 2556 },
+{ 0xa, 64, 1, 2560 },
+{ 0x5, 65, 1, 2555 },
+{ 0xa, 65, 1, 2559 },
+{ 0x6, 66, 0, 2558 },
+{ 0x5, 62, 1, 2410 },
+{ 0x9, 63, 1, 2409 },
+{ 0x12, 63, 1, 2405 },
+{ 0x9, 64, 1, 2408 },
+{ 0x12, 64, 1, 2404 },
+{ 0x9, 65, 1, 2407 },
+{ 0x12, 65, 1, 2403 },
+{ 0x5, 66, 0, 2406 },
+{ 0xd, 62, 1, 2266 },
+{ 0x19, 63, 1, 2265 },
+{ 0x19, 64, 1, 2264 },
+{ 0x19, 65, 1, 2263 },
+{ 0x7, 81, 1, 2262 },
+{ 0x7, 82, 1, 2261 },
+{ 0x7, 83, 1, 2260 },
+{ 0x7, 84, 0, 2259 },
+{ 0x3, 62, 1, 2570 },
+{ 0x3, 63, 1, 2569 },
+{ 0x6, 63, 1, 2565 },
+{ 0x3, 64, 1, 2568 },
+{ 0x6, 64, 1, 2564 },
+{ 0x3, 65, 1, 2567 },
+{ 0x6, 65, 1, 2563 },
+{ 0x3, 66, 0, 2566 },
+{ 0x8, 86, 1, 2434 },
+{ 0x8, 87, 1, 2433 },
+{ 0x2, 88, 1, 2432 },
+{ 0x2, 89, 1, 2431 },
+{ 0x2, 90, 1, 2430 },
+{ 0x2, 91, 1, 2429 },
+{ 0x2, 92, 1, 2428 },
+{ 0x2, 93, 0, 2427 },
+{ 0x18, 86, 1, 2426 },
+{ 0x18, 87, 1, 2425 },
+{ 0x6, 88, 1, 2424 },
+{ 0x6, 89, 1, 2423 },
+{ 0x6, 90, 1, 2422 },
+{ 0x6, 91, 1, 2421 },
+{ 0x6, 92, 1, 2420 },
+{ 0x6, 93, 0, 2419 },
+{ 0x14, 86, 1, 2414 },
+{ 0x22, 87, 1, 2411 },
+{ 0x44, 87, 1, 2413 },
+{ 0xa, 94, 0, 2412 },
+{ 0x34, 86, 1, 2270 },
+{ 0xc4, 87, 1, 2269 },
+{ 0x38, 93, 1, 2267 },
+{ 0xe, 117, 0, 2268 },
+{ 0xc, 86, 1, 2574 },
+{ 0xa, 87, 1, 2571 },
+{ 0x14, 87, 1, 2573 },
+{ 0x6, 94, 0, 2572 },
+{ 0x2, 86, 1, 2282 },
+{ 0x2, 87, 1, 2281 },
+{ 0x4, 92, 1, 2280 },
+{ 0x4, 93, 0, 2279 },
+{ 0x12, 86, 1, 2278 },
+{ 0x42, 87, 1, 2277 },
+{ 0xc, 92, 1, 2276 },
+{ 0xc, 93, 0, 2275 },
+{ 0xa, 86, 1, 2418 },
+{ 0x12, 87, 1, 2417 },
+{ 0x24, 87, 1, 2415 },
+{ 0x5, 94, 0, 2416 },
+{ 0x1a, 86, 1, 2274 },
+{ 0x32, 87, 1, 2273 },
+{ 0x34, 93, 1, 2271 },
+{ 0x7, 117, 0, 2272 },
+{ 0x6, 86, 1, 2578 },
+{ 0x6, 87, 1, 2577 },
+{ 0xc, 87, 1, 2575 },
+{ 0x3, 94, 0, 2576 },
+{ 0x1, 86, 1, 2594 },
+{ 0x1, 87, 1, 2593 },
+{ 0x1, 88, 1, 2592 },
+{ 0x1, 89, 1, 2591 },
+{ 0x1, 90, 1, 2590 },
+{ 0x1, 91, 1, 2589 },
+{ 0x1, 92, 1, 2588 },
+{ 0x1, 93, 0, 2587 },
+{ 0x3, 86, 1, 2586 },
+{ 0x3, 87, 1, 2585 },
+{ 0x3, 88, 1, 2584 },
+{ 0x3, 89, 1, 2583 },
+{ 0x3, 90, 1, 2582 },
+{ 0x3, 91, 1, 2581 },
+{ 0x3, 92, 1, 2580 },
+{ 0x3, 93, 0, 2579 },
+{ 0x8, 53, 1, 2458 },
+{ 0x8, 54, 1, 2457 },
+{ 0x2, 55, 1, 2456 },
+{ 0x2, 56, 1, 2455 },
+{ 0x2, 57, 1, 2454 },
+{ 0x2, 58, 1, 2453 },
+{ 0x2, 59, 1, 2452 },
+{ 0x2, 60, 0, 2451 },
+{ 0x18, 53, 1, 2450 },
+{ 0x18, 54, 1, 2449 },
+{ 0x6, 55, 1, 2448 },
+{ 0x6, 56, 1, 2447 },
+{ 0x6, 57, 1, 2446 },
+{ 0x6, 58, 1, 2445 },
+{ 0x6, 59, 1, 2444 },
+{ 0x6, 60, 0, 2443 },
+{ 0x14, 53, 1, 2438 },
+{ 0x22, 54, 1, 2435 },
+{ 0x44, 54, 1, 2437 },
+{ 0xa, 61, 0, 2436 },
+{ 0x34, 53, 1, 2286 },
+{ 0xc4, 54, 1, 2285 },
+{ 0x38, 60, 1, 2283 },
+{ 0xe, 80, 0, 2284 },
+{ 0xc, 53, 1, 2598 },
+{ 0xa, 54, 1, 2595 },
+{ 0x14, 54, 1, 2597 },
+{ 0x6, 61, 0, 2596 },
+{ 0x2, 53, 1, 2298 },
+{ 0x2, 54, 1, 2297 },
+{ 0x4, 59, 1, 2296 },
+{ 0x4, 60, 0, 2295 },
+{ 0x12, 53, 1, 2294 },
+{ 0x42, 54, 1, 2293 },
+{ 0xc, 59, 1, 2292 },
+{ 0xc, 60, 0, 2291 },
+{ 0xa, 53, 1, 2442 },
+{ 0x12, 54, 1, 2441 },
+{ 0x24, 54, 1, 2439 },
+{ 0x5, 61, 0, 2440 },
+{ 0x1a, 53, 1, 2290 },
+{ 0x32, 54, 1, 2289 },
+{ 0x34, 60, 1, 2287 },
+{ 0x7, 80, 0, 2288 },
+{ 0x6, 53, 1, 2602 },
+{ 0x6, 54, 1, 2601 },
+{ 0xc, 54, 1, 2599 },
+{ 0x3, 61, 0, 2600 },
+{ 0x1, 53, 1, 2618 },
+{ 0x1, 54, 1, 2617 },
+{ 0x1, 55, 1, 2616 },
+{ 0x1, 56, 1, 2615 },
+{ 0x1, 57, 1, 2614 },
+{ 0x1, 58, 1, 2613 },
+{ 0x1, 59, 1, 2612 },
+{ 0x1, 60, 0, 2611 },
+{ 0x3, 53, 1, 2610 },
+{ 0x3, 54, 1, 2609 },
+{ 0x3, 55, 1, 2608 },
+{ 0x3, 56, 1, 2607 },
+{ 0x3, 57, 1, 2606 },
+{ 0x3, 58, 1, 2605 },
+{ 0x3, 59, 1, 2604 },
+{ 0x3, 60, 0, 2603 },
+{ 0x1, 4, 0, 2619 },
+{ 0x1, 296, 0, 2620 },
+{ 0x1, 379, 0, 2621 },
+{ 0x1, 374, 0, 2622 },
+{ 0x2, 358, 0, 2623 },
+{ 0x1, 358, 0, 2626 },
+{ 0x2, 357, 0, 2624 },
+{ 0x1, 357, 0, 2627 },
+{ 0x2, 356, 0, 2625 },
+{ 0x1, 356, 0, 2628 },
+{ 0x1, 355, 0, 2629 },
+{ 0x1, 354, 0, 2630 },
+{ 0x2, 353, 0, 2631 },
+{ 0x1, 353, 0, 2633 },
+{ 0x2, 352, 0, 2632 },
+{ 0x1, 352, 0, 2634 },
+{ 0x1, 382, 0, 2641 },
+{ 0x8, 381, 0, 2635 },
+{ 0x4, 381, 0, 2637 },
+{ 0x2, 381, 0, 2639 },
+{ 0x1, 381, 0, 2642 },
+{ 0x8, 380, 0, 2636 },
+{ 0x4, 380, 0, 2638 },
+{ 0x2, 380, 0, 2640 },
+{ 0x1, 380, 0, 2643 },
+{ 0x1, 351, 0, 2650 },
+{ 0x8, 350, 0, 2644 },
+{ 0x4, 350, 0, 2646 },
+{ 0x2, 350, 0, 2648 },
+{ 0x1, 350, 0, 2651 },
+{ 0x8, 349, 0, 2645 },
+{ 0x4, 349, 0, 2647 },
+{ 0x2, 349, 1, 2649 },
+{ 0x4, 143, 0, 1345 },
+{ 0x1, 349, 0, 2652 },
+{ 0x1, 6, 0, 2653 },
+{ 0x1, 7, 0, 2654 },
+{ 0x1, 295, 0, 2655 },
+{ 0x1, 451, 0, 2656 },
+{ 0x1, 346, 0, 2657 },
+{ 0x1, 13, 0, 2658 },
+{ 0x1, 11, 0, 2659 },
+{ 0x1, 422, 0, 2660 },
+{ 0x1, 394, 0, 2661 },
+{ 0x1, 393, 0, 2662 },
+{ 0x1, 450, 0, 2663 },
+{ 0x1, 345, 0, 2664 },
+{ 0x1, 12, 0, 2665 },
+{ 0x1, 10, 0, 2666 },
+{ 0x1, 5, 0, 2667 },
+{ 0x1, 421, 0, 2668 },
+{ 0x1, 420, 0, 2669 },
+{ 0x1, 1, 0, 2670 },
+{ 0x1, 0, 0, 2671 },
+};
+
diff --git a/arch/ia64/kdb/ia64-asmtab.h b/arch/ia64/kdb/ia64-asmtab.h
new file mode 100644 (file)
index 0000000..9bcd23b
--- /dev/null
@@ -0,0 +1,158 @@
+/* ia64-asmtab.h -- Header for compacted IA-64 opcode tables.
+   Copyright 1999, 2000 Free Software Foundation, Inc.
+   Contributed by Bob Manson of Cygnus Support <manson@cygnus.com>
+
+   This file is part of GDB, GAS, and the GNU binutils.
+
+   GDB, GAS, and the GNU binutils are free software; you can redistribute
+   them and/or modify them under the terms of the GNU General Public
+   License as published by the Free Software Foundation; either version
+   2, or (at your option) any later version.
+
+   GDB, GAS, and the GNU binutils are distributed in the hope that they
+   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 file; see the file COPYING.  If not, write to the
+   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+#ifndef IA64_ASMTAB_H
+#define IA64_ASMTAB_H
+
+#ifdef __KERNEL__
+#include "ia64.h"
+#else  /* __KERNEL__ */
+#include "opcode/ia64.h"
+#endif /* __KERNEL__ */
+
+/* The primary opcode table is made up of the following: */
+struct ia64_main_table
+{
+  /* The entry in the string table that corresponds to the name of this
+     opcode. */
+  unsigned short name_index;
+
+  /* The type of opcode; corresponds to the TYPE field in
+     struct ia64_opcode. */
+  unsigned char opcode_type;
+
+  /* The number of outputs for this opcode. */
+  unsigned char num_outputs;
+
+  /* The base insn value for this opcode.  It may be modified by completers. */
+  ia64_insn opcode;
+
+  /* The mask of valid bits in OPCODE. Zeros indicate operand fields. */
+  ia64_insn mask;
+
+  /* The operands of this instruction.  Corresponds to the OPERANDS field
+     in struct ia64_opcode. */
+  unsigned char operands[5];
+
+  /* The flags for this instruction.  Corresponds to the FLAGS field in
+     struct ia64_opcode. */
+  short flags;
+
+  /* The tree of completers for this instruction; this is an offset into
+     completer_table. */
+  short completers;
+};
+
+/* Each instruction has a set of possible "completers", or additional
+   suffixes that can alter the instruction's behavior, and which has
+   potentially different dependencies.
+
+   The completer entries modify certain bits in the instruction opcode.
+   Which bits are to be modified are marked by the BITS, MASK and
+   OFFSET fields.  The completer entry may also note dependencies for the
+   opcode.
+
+   These completers are arranged in a DAG; the pointers are indexes
+   into the completer_table array.  The completer DAG is searched by
+   find_completer () and ia64_find_matching_opcode ().
+
+   Note that each completer needs to be applied in turn, so that if we
+   have the instruction
+       cmp.lt.unc
+   the completer entries for both "lt" and "unc" would need to be applied
+   to the opcode's value.
+
+   Some instructions do not require any completers; these contain an
+   empty completer entry.  Instructions that require a completer do
+   not contain an empty entry.
+
+   Terminal completers (those completers that validly complete an
+   instruction) are marked by having the TERMINAL_COMPLETER flag set.
+
+   Only dependencies listed in the terminal completer for an opcode are
+   considered to apply to that opcode instance. */
+
+struct ia64_completer_table
+{
+  /* The bit value that this completer sets. */
+  unsigned int bits;
+
+  /* And its mask. 1s are bits that are to be modified in the
+     instruction. */
+  unsigned int mask;
+
+  /* The entry in the string table that corresponds to the name of this
+     completer. */
+  unsigned short name_index;
+
+  /* An alternative completer, or -1 if this is the end of the chain. */
+  short alternative;
+
+  /* A pointer to the DAG of completers that can potentially follow
+     this one, or -1. */
+  short subentries;
+
+  /* The bit offset in the instruction where BITS and MASK should be
+     applied. */
+  unsigned char offset : 7;
+
+  unsigned char terminal_completer : 1;
+
+  /* Index into the dependency list table */
+  short dependencies;
+};
+
+/* This contains sufficient information for the disassembler to resolve
+   the complete name of the original instruction.  */
+struct ia64_dis_names
+{
+  /* COMPLETER_INDEX represents the tree of completers that make up
+     the instruction.  The LSB represents the top of the tree for the
+     specified instruction.
+
+     A 0 bit indicates to go to the next alternate completer via the
+     alternative field; a 1 bit indicates that the current completer
+     is part of the instruction, and to go down the subentries index.
+     We know we've reached the final completer when we run out of 1
+     bits.
+
+     There is always at least one 1 bit. */
+  unsigned int completer_index : 20;
+
+  /* The index in the main_table[] array for the instruction. */
+  unsigned short insn_index : 11;
+
+  /* If set, the next entry in this table is an alternate possibility
+     for this instruction encoding.  Which one to use is determined by
+     the instruction type and other factors (see opcode_verify ()).  */
+  unsigned int next_flag : 1;
+
+  /* The disassembly priority of this entry among instructions. */
+  unsigned short priority;
+};
+
+#endif
diff --git a/arch/ia64/kdb/ia64-dis.c b/arch/ia64/kdb/ia64-dis.c
new file mode 100644 (file)
index 0000000..6067eb6
--- /dev/null
@@ -0,0 +1,312 @@
+/* ia64-dis.c -- Disassemble ia64 instructions
+   Copyright 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   This file is part of GDB, GAS, and the GNU binutils.
+
+   GDB, GAS, and the GNU binutils are free software; you can redistribute
+   them and/or modify them under the terms of the GNU General Public
+   License as published by the Free Software Foundation; either version
+   2, or (at your option) any later version.
+
+   GDB, GAS, and the GNU binutils are distributed in the hope that they
+   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 file; see the file COPYING.  If not, write to the
+   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/dis-asm.h>
+#include "ia64.h"
+
+/* imported from bfd/libbfd.c for kernel */
+bfd_uint64_t
+bfd_getl64 (const void *p ATTRIBUTE_UNUSED)
+{
+#ifdef BFD_HOST_64_BIT
+  const bfd_byte *addr = p;
+  bfd_uint64_t v;
+
+  v  = addr[7]; v <<= 8;
+  v |= addr[6]; v <<= 8;
+  v |= addr[5]; v <<= 8;
+  v |= addr[4]; v <<= 8;
+  v |= addr[3]; v <<= 8;
+  v |= addr[2]; v <<= 8;
+  v |= addr[1]; v <<= 8;
+  v |= addr[0];
+
+  return v;
+#else
+  BFD_FAIL();
+  return 0;
+#endif
+
+}
+
+#else  /* __KERNEL__ */
+#include <assert.h>
+#include <string.h>
+
+#include "dis-asm.h"
+#include "opcode/ia64.h"
+#endif /* __KERNEL__ */
+
+#define NELEMS(a)      ((int) (sizeof (a) / sizeof (a[0])))
+
+/* Disassemble ia64 instruction.  */
+
+/* Return the instruction type for OPCODE found in unit UNIT. */
+
+static enum ia64_insn_type
+unit_to_type (ia64_insn opcode, enum ia64_unit unit)
+{
+  enum ia64_insn_type type;
+  int op;
+
+  op = IA64_OP (opcode);
+
+  if (op >= 8 && (unit == IA64_UNIT_I || unit == IA64_UNIT_M))
+    {
+      type = IA64_TYPE_A;
+    }
+  else
+    {
+      switch (unit)
+       {
+       case IA64_UNIT_I:
+         type = IA64_TYPE_I; break;
+       case IA64_UNIT_M:
+         type = IA64_TYPE_M; break;
+       case IA64_UNIT_B:
+         type = IA64_TYPE_B; break;
+       case IA64_UNIT_F:
+         type = IA64_TYPE_F; break;
+        case IA64_UNIT_L:
+       case IA64_UNIT_X:
+         type = IA64_TYPE_X; break;
+       default:
+         type = -1;
+       }
+    }
+  return type;
+}
+
+int
+print_insn_ia64 (bfd_vma memaddr, struct disassemble_info *info)
+{
+  ia64_insn t0, t1, slot[3], template, s_bit, insn;
+  int slotnum, j, status, need_comma, retval, slot_multiplier;
+  const struct ia64_operand *odesc;
+  const struct ia64_opcode *idesc;
+  const char *err, *str, *tname;
+  BFD_HOST_U_64_BIT value;
+  bfd_byte bundle[16];
+  enum ia64_unit unit;
+  char regname[16];
+
+  if (info->bytes_per_line == 0)
+    info->bytes_per_line = 6;
+  info->display_endian = info->endian;
+
+  slot_multiplier = info->bytes_per_line;
+  retval = slot_multiplier;
+
+  slotnum = (((long) memaddr) & 0xf) / slot_multiplier;
+  if (slotnum > 2)
+    return -1;
+
+  memaddr -= (memaddr & 0xf);
+  status = (*info->read_memory_func) (memaddr, bundle, sizeof (bundle), info);
+  if (status != 0)
+    {
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
+    }
+  /* bundles are always in little-endian byte order */
+  t0 = bfd_getl64 (bundle);
+  t1 = bfd_getl64 (bundle + 8);
+  s_bit = t0 & 1;
+  template = (t0 >> 1) & 0xf;
+  slot[0] = (t0 >>  5) & 0x1ffffffffffLL;
+  slot[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18);
+  slot[2] = (t1 >> 23) & 0x1ffffffffffLL;
+
+  tname = ia64_templ_desc[template].name;
+  if (slotnum == 0)
+    (*info->fprintf_func) (info->stream, "[%s] ", tname);
+  else
+    (*info->fprintf_func) (info->stream, "      ");
+
+  unit = ia64_templ_desc[template].exec_unit[slotnum];
+
+  if (template == 2 && slotnum == 1)
+    {
+      /* skip L slot in MLI template: */
+      slotnum = 2;
+      retval += slot_multiplier;
+    }
+
+  insn = slot[slotnum];
+
+  if (unit == IA64_UNIT_NIL)
+    goto decoding_failed;
+
+  idesc = ia64_dis_opcode (insn, unit_to_type (insn, unit));
+  if (idesc == NULL)
+    goto decoding_failed;
+
+  /* print predicate, if any: */
+
+  if ((idesc->flags & IA64_OPCODE_NO_PRED)
+      || (insn & 0x3f) == 0)
+    (*info->fprintf_func) (info->stream, "      ");
+  else
+    (*info->fprintf_func) (info->stream, "(p%02d) ", (int)(insn & 0x3f));
+
+  /* now the actual instruction: */
+
+  (*info->fprintf_func) (info->stream, "%s", idesc->name);
+  if (idesc->operands[0])
+    (*info->fprintf_func) (info->stream, " ");
+
+  need_comma = 0;
+  for (j = 0; j < NELEMS (idesc->operands) && idesc->operands[j]; ++j)
+    {
+      odesc = elf64_ia64_operands + idesc->operands[j];
+
+      if (need_comma)
+       (*info->fprintf_func) (info->stream, ",");
+
+      if (odesc - elf64_ia64_operands == IA64_OPND_IMMU64)
+       {
+         /* special case of 64 bit immediate load: */
+         value = ((insn >> 13) & 0x7f) | (((insn >> 27) & 0x1ff) << 7)
+           | (((insn >> 22) & 0x1f) << 16) | (((insn >> 21) & 0x1) << 21)
+           | (slot[1] << 22) | (((insn >> 36) & 0x1) << 63);
+       }
+      else if (odesc - elf64_ia64_operands == IA64_OPND_IMMU62)
+        {
+          /* 62-bit immediate for nop.x/break.x */
+          value = ((slot[1] & 0x1ffffffffffLL) << 21)
+            | (((insn >> 36) & 0x1) << 20)
+            | ((insn >> 6) & 0xfffff);
+        }
+      else if (odesc - elf64_ia64_operands == IA64_OPND_TGT64)
+       {
+         /* 60-bit immediate for long branches. */
+         value = (((insn >> 13) & 0xfffff)
+                  | (((insn >> 36) & 1) << 59)
+                  | (((slot[1] >> 2) & 0x7fffffffffLL) << 20)) << 4;
+       }
+      else
+       {
+         err = (*odesc->extract) (odesc, insn, &value);
+         if (err)
+           {
+             (*info->fprintf_func) (info->stream, "%s", err);
+             goto done;
+           }
+       }
+
+       switch (odesc->class)
+         {
+         case IA64_OPND_CLASS_CST:
+           (*info->fprintf_func) (info->stream, "%s", odesc->str);
+           break;
+
+         case IA64_OPND_CLASS_REG:
+           if (odesc->str[0] == 'a' && odesc->str[1] == 'r')
+             {
+               switch (value)
+                 {
+                 case 0: case 1: case 2: case 3:
+                 case 4: case 5: case 6: case 7:
+                   sprintf (regname, "ar.k%u", (unsigned int) value);
+                   break;
+                 case 16:      strcpy (regname, "ar.rsc"); break;
+                 case 17:      strcpy (regname, "ar.bsp"); break;
+                 case 18:      strcpy (regname, "ar.bspstore"); break;
+                 case 19:      strcpy (regname, "ar.rnat"); break;
+                 case 32:      strcpy (regname, "ar.ccv"); break;
+                 case 36:      strcpy (regname, "ar.unat"); break;
+                 case 40:      strcpy (regname, "ar.fpsr"); break;
+                 case 44:      strcpy (regname, "ar.itc"); break;
+                 case 64:      strcpy (regname, "ar.pfs"); break;
+                 case 65:      strcpy (regname, "ar.lc"); break;
+                 case 66:      strcpy (regname, "ar.ec"); break;
+                 default:
+                   sprintf (regname, "ar%u", (unsigned int) value);
+                   break;
+                 }
+               (*info->fprintf_func) (info->stream, "%s", regname);
+             }
+           else
+             (*info->fprintf_func) (info->stream, "%s%d", odesc->str, (int)value);
+           break;
+
+         case IA64_OPND_CLASS_IND:
+           (*info->fprintf_func) (info->stream, "%s[r%d]", odesc->str, (int)value);
+           break;
+
+         case IA64_OPND_CLASS_ABS:
+           str = 0;
+           if (odesc - elf64_ia64_operands == IA64_OPND_MBTYPE4)
+             switch (value)
+               {
+               case 0x0: str = "@brcst"; break;
+               case 0x8: str = "@mix"; break;
+               case 0x9: str = "@shuf"; break;
+               case 0xa: str = "@alt"; break;
+               case 0xb: str = "@rev"; break;
+               }
+
+           if (str)
+             (*info->fprintf_func) (info->stream, "%s", str);
+           else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_SIGNED)
+             (*info->fprintf_func) (info->stream, "%lld", (long long) value);
+           else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_UNSIGNED)
+             (*info->fprintf_func) (info->stream, "%llu", (long long) value);
+           else
+             (*info->fprintf_func) (info->stream, "0x%llx", (long long) value);
+           break;
+
+         case IA64_OPND_CLASS_REL:
+           (*info->print_address_func) (memaddr + value, info);
+           break;
+         }
+
+      need_comma = 1;
+      if (j + 1 == idesc->num_outputs)
+       {
+         (*info->fprintf_func) (info->stream, "=");
+         need_comma = 0;
+       }
+    }
+  if (slotnum + 1 == ia64_templ_desc[template].group_boundary
+      || ((slotnum == 2) && s_bit))
+    (*info->fprintf_func) (info->stream, ";;");
+
+ done:
+  ia64_free_opcode ((struct ia64_opcode *)idesc);
+ failed:
+  if (slotnum == 2)
+    retval += 16 - 3*slot_multiplier;
+  return retval;
+
+ decoding_failed:
+  (*info->fprintf_func) (info->stream, "      data8 %#011llx", (long long) insn);
+  goto failed;
+}
diff --git a/arch/ia64/kdb/ia64-opc.c b/arch/ia64/kdb/ia64-opc.c
new file mode 100644 (file)
index 0000000..ec6328d
--- /dev/null
@@ -0,0 +1,749 @@
+/* ia64-opc.c -- Functions to access the compacted opcode table
+   Copyright 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+   Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com>
+
+   This file is part of GDB, GAS, and the GNU binutils.
+
+   GDB, GAS, and the GNU binutils are free software; you can redistribute
+   them and/or modify them under the terms of the GNU General Public
+   License as published by the Free Software Foundation; either version
+   2, or (at your option) any later version.
+
+   GDB, GAS, and the GNU binutils are distributed in the hope that they
+   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 file; see the file COPYING.  If not, write to the
+   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <asm/ansidecl.h>
+
+#define xstrdup(string) ({ char *res = kdb_strdup(string, GFP_ATOMIC); if (!res) BUG(); res; })
+#define xmalloc(size) ({ void *res = debug_kmalloc(size, GFP_ATOMIC); if (!res) BUG(); res; })
+#define free(address) debug_kfree(address)
+#define abort() BUG()
+
+#else  /* __KERNEL__ */
+#include "ansidecl.h"
+#include "sysdep.h"
+#include "libiberty.h"
+#endif /* __KERNEL__ */
+#include "ia64-asmtab.h"
+#include "ia64-asmtab.c"
+
+static void get_opc_prefix (const char **, char *);
+static short int find_string_ent (const char *);
+static short int find_main_ent (short int);
+static short int find_completer (short int, short int, const char *);
+static ia64_insn apply_completer (ia64_insn, int);
+static int extract_op_bits (int, int, int);
+static int extract_op (int, int *, unsigned int *);
+static int opcode_verify (ia64_insn, int, enum ia64_insn_type);
+static int locate_opcode_ent (ia64_insn, enum ia64_insn_type);
+static struct ia64_opcode *make_ia64_opcode
+  (ia64_insn, const char *, int, int);
+static struct ia64_opcode *ia64_find_matching_opcode
+  (const char *, short int);
+
+const struct ia64_templ_desc ia64_templ_desc[16] =
+  {
+    { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },   /* 0 */
+    { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },
+    { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" },
+    { 0, { 0, },                                   "-3-" },
+    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },   /* 4 */
+    { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },
+    { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" },
+    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" },
+    { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" },   /* 8 */
+    { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" },
+    { 0, { 0, },                                   "-a-" },
+    { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" },
+    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" },   /* c */
+    { 0, { 0, },                                   "-d-" },
+    { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" },
+    { 0, { 0, },                                   "-f-" },
+  };
+
+
+/* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST.
+   PTR will be adjusted to point to the start of the next portion
+   of the opcode, or at the NUL character. */
+
+static void
+get_opc_prefix (const char **ptr, char *dest)
+{
+  char *c = strchr (*ptr, '.');
+  if (c != NULL)
+    {
+      memcpy (dest, *ptr, c - *ptr);
+      dest[c - *ptr] = '\0';
+      *ptr = c + 1;
+    }
+  else
+    {
+      int l = strlen (*ptr);
+      memcpy (dest, *ptr, l);
+      dest[l] = '\0';
+      *ptr += l;
+    }
+}
+\f
+/* Find the index of the entry in the string table corresponding to
+   STR; return -1 if one does not exist. */
+
+static short
+find_string_ent (const char *str)
+{
+  short start = 0;
+  short end = sizeof (ia64_strings) / sizeof (const char *);
+  short i = (start + end) / 2;
+
+  if (strcmp (str, ia64_strings[end - 1]) > 0)
+    {
+      return -1;
+    }
+  while (start <= end)
+    {
+      int c = strcmp (str, ia64_strings[i]);
+      if (c < 0)
+       {
+         end = i - 1;
+       }
+      else if (c == 0)
+       {
+         return i;
+       }
+      else
+       {
+         start = i + 1;
+       }
+      i = (start + end) / 2;
+    }
+  return -1;
+}
+\f
+/* Find the opcode in the main opcode table whose name is STRINGINDEX, or
+   return -1 if one does not exist. */
+
+static short
+find_main_ent (short nameindex)
+{
+  short start = 0;
+  short end = sizeof (main_table) / sizeof (struct ia64_main_table);
+  short i = (start + end) / 2;
+
+  if (nameindex < main_table[0].name_index
+      || nameindex > main_table[end - 1].name_index)
+    {
+      return -1;
+    }
+  while (start <= end)
+    {
+      if (nameindex < main_table[i].name_index)
+       {
+         end = i - 1;
+       }
+      else if (nameindex == main_table[i].name_index)
+       {
+         while (i > 0 && main_table[i - 1].name_index == nameindex)
+           {
+             i--;
+           }
+         return i;
+       }
+      else
+       {
+         start = i + 1;
+       }
+      i = (start + end) / 2;
+    }
+  return -1;
+}
+\f
+/* Find the index of the entry in the completer table that is part of
+   MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or
+   return -1 if one does not exist. */
+
+static short
+find_completer (short main_ent, short prev_completer, const char *name)
+{
+  short name_index = find_string_ent (name);
+
+  if (name_index < 0)
+    {
+      return -1;
+    }
+
+  if (prev_completer == -1)
+    {
+      prev_completer = main_table[main_ent].completers;
+    }
+  else
+    {
+      prev_completer = completer_table[prev_completer].subentries;
+    }
+
+  while (prev_completer != -1)
+    {
+      if (completer_table[prev_completer].name_index == name_index)
+       {
+         return prev_completer;
+       }
+      prev_completer = completer_table[prev_completer].alternative;
+    }
+  return -1;
+}
+\f
+/* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
+   return the result. */
+
+static ia64_insn
+apply_completer (ia64_insn opcode, int completer_index)
+{
+  ia64_insn mask = completer_table[completer_index].mask;
+  ia64_insn bits = completer_table[completer_index].bits;
+  int shiftamt = (completer_table[completer_index].offset & 63);
+
+  mask = mask << shiftamt;
+  bits = bits << shiftamt;
+  opcode = (opcode & ~mask) | bits;
+  return opcode;
+}
+\f
+/* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in
+   the dis_table array, and return its value.  (BITOFFSET is numbered
+   starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the
+   first byte in OP_POINTER.) */
+
+static int
+extract_op_bits (int op_pointer, int bitoffset, int bits)
+{
+  int res = 0;
+
+  op_pointer += (bitoffset / 8);
+
+  if (bitoffset % 8)
+    {
+      unsigned int op = dis_table[op_pointer++];
+      int numb = 8 - (bitoffset % 8);
+      int mask = (1 << numb) - 1;
+      int bata = (bits < numb) ? bits : numb;
+      int delta = numb - bata;
+
+      res = (res << bata) | ((op & mask) >> delta);
+      bitoffset += bata;
+      bits -= bata;
+    }
+  while (bits >= 8)
+    {
+      res = (res << 8) | (dis_table[op_pointer++] & 255);
+      bits -= 8;
+    }
+  if (bits > 0)
+    {
+      unsigned int op = (dis_table[op_pointer++] & 255);
+      res = (res << bits) | (op >> (8 - bits));
+    }
+  return res;
+}
+\f
+/* Examine the state machine entry at OP_POINTER in the dis_table
+   array, and extract its values into OPVAL and OP.  The length of the
+   state entry in bits is returned. */
+
+static int
+extract_op (int op_pointer, int *opval, unsigned int *op)
+{
+  int oplen = 5;
+
+  *op = dis_table[op_pointer];
+
+  if ((*op) & 0x40)
+    {
+      opval[0] = extract_op_bits (op_pointer, oplen, 5);
+      oplen += 5;
+    }
+  switch ((*op) & 0x30)
+    {
+    case 0x10:
+      {
+       opval[1] = extract_op_bits (op_pointer, oplen, 8);
+       oplen += 8;
+       opval[1] += op_pointer;
+       break;
+      }
+    case 0x20:
+      {
+       opval[1] = extract_op_bits (op_pointer, oplen, 16);
+       if (! (opval[1] & 32768))
+         {
+           opval[1] += op_pointer;
+         }
+       oplen += 16;
+       break;
+      }
+    case 0x30:
+      {
+       oplen--;
+       opval[2] = extract_op_bits (op_pointer, oplen, 12);
+       oplen += 12;
+       opval[2] |= 32768;
+       break;
+      }
+    }
+  if (((*op) & 0x08) && (((*op) & 0x30) != 0x30))
+    {
+      opval[2] = extract_op_bits (op_pointer, oplen, 16);
+      oplen += 16;
+      if (! (opval[2] & 32768))
+       {
+         opval[2] += op_pointer;
+       }
+    }
+  return oplen;
+}
+\f
+/* Returns a non-zero value if the opcode in the main_table list at
+   PLACE matches OPCODE and is of type TYPE. */
+
+static int
+opcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type)
+{
+  if (main_table[place].opcode_type != type)
+    {
+      return 0;
+    }
+  if (main_table[place].flags
+      & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT))
+    {
+      const struct ia64_operand *o1, *o2;
+      ia64_insn f2, f3;
+
+      if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3)
+       {
+         o1 = elf64_ia64_operands + IA64_OPND_F2;
+         o2 = elf64_ia64_operands + IA64_OPND_F3;
+         (*o1->extract) (o1, opcode, &f2);
+         (*o2->extract) (o2, opcode, &f3);
+         if (f2 != f3)
+           return 0;
+       }
+      else
+       {
+         ia64_insn len, count;
+
+         /* length must equal 64-count: */
+         o1 = elf64_ia64_operands + IA64_OPND_LEN6;
+         o2 = elf64_ia64_operands + main_table[place].operands[2];
+         (*o1->extract) (o1, opcode, &len);
+         (*o2->extract) (o2, opcode, &count);
+         if (len != 64 - count)
+           return 0;
+       }
+    }
+  return 1;
+}
+\f
+/* Find an instruction entry in the ia64_dis_names array that matches
+   opcode OPCODE and is of type TYPE.  Returns either a positive index
+   into the array, or a negative value if an entry for OPCODE could
+   not be found.  Checks all matches and returns the one with the highest
+   priority. */
+
+static int
+locate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type)
+{
+  int currtest[41];
+  int bitpos[41];
+  int op_ptr[41];
+  int currstatenum = 0;
+  short found_disent = -1;
+  short found_priority = -1;
+
+  currtest[currstatenum] = 0;
+  op_ptr[currstatenum] = 0;
+  bitpos[currstatenum] = 40;
+
+  while (1)
+    {
+      int op_pointer = op_ptr[currstatenum];
+      unsigned int op;
+      int currbitnum = bitpos[currstatenum];
+      int oplen;
+      int opval[3] = {0};
+      int next_op;
+      int currbit;
+
+      oplen = extract_op (op_pointer, opval, &op);
+
+      bitpos[currstatenum] = currbitnum;
+
+      /* Skip opval[0] bits in the instruction. */
+      if (op & 0x40)
+       {
+         currbitnum -= opval[0];
+       }
+
+      /* The value of the current bit being tested. */
+      currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0;
+      next_op = -1;
+
+      /* We always perform the tests specified in the current state in
+        a particular order, falling through to the next test if the
+        previous one failed. */
+      switch (currtest[currstatenum])
+       {
+       case 0:
+         currtest[currstatenum]++;
+         if (currbit == 0 && (op & 0x80))
+           {
+             /* Check for a zero bit.  If this test solely checks for
+                a zero bit, we can check for up to 8 consecutive zero
+                bits (the number to check is specified by the lower 3
+                bits in the state code.)
+
+                If the state instruction matches, we go to the very
+                next state instruction; otherwise, try the next test. */
+
+             if ((op & 0xf8) == 0x80)
+               {
+                 int count = op & 0x7;
+                 int x;
+
+                 for (x = 0; x <= count; x++)
+                   {
+                     int i =
+                       opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0;
+                     if (i)
+                       {
+                         break;
+                       }
+                   }
+                 if (x > count)
+                   {
+                     next_op = op_pointer + ((oplen + 7) / 8);
+                     currbitnum -= count;
+                     break;
+                   }
+               }
+             else if (! currbit)
+               {
+                 next_op = op_pointer + ((oplen + 7) / 8);
+                 break;
+               }
+           }
+         /* FALLTHROUGH */
+       case 1:
+         /* If the bit in the instruction is one, go to the state
+            instruction specified by opval[1]. */
+         currtest[currstatenum]++;
+         if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30))
+           {
+             next_op = opval[1];
+             break;
+           }
+         /* FALLTHROUGH */
+       case 2:
+         /* Don't care.  Skip the current bit and go to the state
+            instruction specified by opval[2].
+
+            An encoding of 0x30 is special; this means that a 12-bit
+            offset into the ia64_dis_names[] array is specified.  */
+         currtest[currstatenum]++;
+         if ((op & 0x08) || ((op & 0x30) == 0x30))
+           {
+             next_op = opval[2];
+             break;
+           }
+       }
+
+      /* If bit 15 is set in the address of the next state, an offset
+        in the ia64_dis_names array was specified instead.  We then
+        check to see if an entry in the list of opcodes matches the
+        opcode we were given; if so, we have succeeded.  */
+
+      if ((next_op >= 0) && (next_op & 32768))
+       {
+         short disent = next_op & 32767;
+          short priority = -1;
+
+         if (next_op > 65535)
+           {
+             abort ();
+           }
+
+         /* Run through the list of opcodes to check, trying to find
+            one that matches.  */
+         while (disent >= 0)
+           {
+             int place = ia64_dis_names[disent].insn_index;
+
+              priority = ia64_dis_names[disent].priority;
+
+             if (opcode_verify (opcode, place, type)
+                  && priority > found_priority)
+               {
+                 break;
+               }
+             if (ia64_dis_names[disent].next_flag)
+               {
+                 disent++;
+               }
+             else
+               {
+                 disent = -1;
+               }
+           }
+
+         if (disent >= 0)
+           {
+              found_disent = disent;
+              found_priority = priority;
+           }
+          /* Try the next test in this state, regardless of whether a match
+             was found. */
+          next_op = -2;
+       }
+
+      /* next_op == -1 is "back up to the previous state".
+        next_op == -2 is "stay in this state and try the next test".
+        Otherwise, transition to the state indicated by next_op. */
+
+      if (next_op == -1)
+       {
+         currstatenum--;
+         if (currstatenum < 0)
+           {
+              return found_disent;
+           }
+       }
+      else if (next_op >= 0)
+       {
+         currstatenum++;
+         bitpos[currstatenum] = currbitnum - 1;
+         op_ptr[currstatenum] = next_op;
+         currtest[currstatenum] = 0;
+       }
+    }
+}
+\f
+/* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
+
+static struct ia64_opcode *
+make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind)
+{
+  struct ia64_opcode *res =
+    (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode));
+  res->name = xstrdup (name);
+  res->type = main_table[place].opcode_type;
+  res->num_outputs = main_table[place].num_outputs;
+  res->opcode = opcode;
+  res->mask = main_table[place].mask;
+  res->operands[0] = main_table[place].operands[0];
+  res->operands[1] = main_table[place].operands[1];
+  res->operands[2] = main_table[place].operands[2];
+  res->operands[3] = main_table[place].operands[3];
+  res->operands[4] = main_table[place].operands[4];
+  res->flags = main_table[place].flags;
+  res->ent_index = place;
+  res->dependencies = &op_dependencies[depind];
+  return res;
+}
+\f
+/* Determine the ia64_opcode entry for the opcode specified by INSN
+   and TYPE.  If a valid entry is not found, return NULL. */
+struct ia64_opcode *
+ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type)
+{
+  int disent = locate_opcode_ent (insn, type);
+
+  if (disent < 0)
+    {
+      return NULL;
+    }
+  else
+    {
+      unsigned int cb = ia64_dis_names[disent].completer_index;
+      static char name[128];
+      int place = ia64_dis_names[disent].insn_index;
+      int ci = main_table[place].completers;
+      ia64_insn tinsn = main_table[place].opcode;
+
+      strcpy (name, ia64_strings [main_table[place].name_index]);
+
+      while (cb)
+       {
+         if (cb & 1)
+           {
+             int cname = completer_table[ci].name_index;
+
+             tinsn = apply_completer (tinsn, ci);
+
+             if (ia64_strings[cname][0] != '\0')
+               {
+                 strcat (name, ".");
+                 strcat (name, ia64_strings[cname]);
+               }
+             if (cb != 1)
+               {
+                 ci = completer_table[ci].subentries;
+               }
+           }
+         else
+           {
+             ci = completer_table[ci].alternative;
+           }
+         if (ci < 0)
+           {
+             abort ();
+           }
+         cb = cb >> 1;
+       }
+      if (tinsn != (insn & main_table[place].mask))
+       {
+         abort ();
+       }
+      return make_ia64_opcode (insn, name, place,
+                               completer_table[ci].dependencies);
+    }
+}
+\f
+/* Search the main_opcode table starting from PLACE for an opcode that
+   matches NAME.  Return NULL if one is not found. */
+
+static struct ia64_opcode *
+ia64_find_matching_opcode (const char *name, short place)
+{
+  char op[129];
+  const char *suffix;
+  short name_index;
+
+  if (strlen (name) > 128)
+    {
+      return NULL;
+    }
+  suffix = name;
+  get_opc_prefix (&suffix, op);
+  name_index = find_string_ent (op);
+  if (name_index < 0)
+    {
+      return NULL;
+    }
+
+  while (main_table[place].name_index == name_index)
+    {
+      const char *curr_suffix = suffix;
+      ia64_insn curr_insn = main_table[place].opcode;
+      short completer = -1;
+
+      do {
+       if (suffix[0] == '\0')
+         {
+           completer = find_completer (place, completer, suffix);
+         }
+       else
+         {
+           get_opc_prefix (&curr_suffix, op);
+           completer = find_completer (place, completer, op);
+         }
+       if (completer != -1)
+         {
+           curr_insn = apply_completer (curr_insn, completer);
+         }
+      } while (completer != -1 && curr_suffix[0] != '\0');
+
+      if (completer != -1 && curr_suffix[0] == '\0'
+         && completer_table[completer].terminal_completer)
+       {
+          int depind = completer_table[completer].dependencies;
+         return make_ia64_opcode (curr_insn, name, place, depind);
+       }
+      else
+       {
+         place++;
+       }
+    }
+  return NULL;
+}
+\f
+/* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
+   if one does not exist.
+
+   It is the caller's responsibility to invoke ia64_free_opcode () to
+   release any resources used by the returned entry. */
+
+struct ia64_opcode *
+ia64_find_next_opcode (struct ia64_opcode *prev_ent)
+{
+  return ia64_find_matching_opcode (prev_ent->name,
+                                   prev_ent->ent_index + 1);
+}
+
+/* Find the first opcode that matches NAME, or return NULL if it does
+   not exist.
+
+   It is the caller's responsibility to invoke ia64_free_opcode () to
+   release any resources used by the returned entry. */
+
+struct ia64_opcode *
+ia64_find_opcode (const char *name)
+{
+  char op[129];
+  const char *suffix;
+  short place;
+  short name_index;
+
+  if (strlen (name) > 128)
+    {
+      return NULL;
+    }
+  suffix = name;
+  get_opc_prefix (&suffix, op);
+  name_index = find_string_ent (op);
+  if (name_index < 0)
+    {
+      return NULL;
+    }
+
+  place = find_main_ent (name_index);
+
+  if (place < 0)
+    {
+      return NULL;
+    }
+  return ia64_find_matching_opcode (name, place);
+}
+
+/* Free any resources used by ENT. */
+void
+ia64_free_opcode (struct ia64_opcode *ent)
+{
+  free ((void *)ent->name);
+  free (ent);
+}
+
+const struct ia64_dependency *
+ia64_find_dependency (int index)
+{
+  index = DEP(index);
+
+  if (index < 0
+      || index >= (int)(sizeof(dependencies) / sizeof(dependencies[0])))
+    return NULL;
+
+  return &dependencies[index];
+}
diff --git a/arch/ia64/kdb/ia64-opc.h b/arch/ia64/kdb/ia64-opc.h
new file mode 100644 (file)
index 0000000..cee0b9a
--- /dev/null
@@ -0,0 +1,141 @@
+/* ia64-opc.h -- IA-64 opcode table.
+   Copyright 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+   This file is part of GDB, GAS, and the GNU binutils.
+
+   GDB, GAS, and the GNU binutils are free software; you can redistribute
+   them and/or modify them under the terms of the GNU General Public
+   License as published by the Free Software Foundation; either version
+   2, or (at your option) any later version.
+
+   GDB, GAS, and the GNU binutils are distributed in the hope that they
+   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 file; see the file COPYING.  If not, write to the
+   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+#ifndef IA64_OPC_H
+#define IA64_OPC_H
+
+#ifdef __KERNEL__
+#include "ia64.h"
+#else  /* __KERNEL__ */
+#include "opcode/ia64.h"
+#endif /* __KERNEL__ */
+
+/* define a couple of abbreviations: */
+
+#define bOp(x) (((ia64_insn) ((x) & 0xf)) << 37)
+#define mOp    bOp (-1)
+#define Op(x)  bOp (x), mOp
+
+#define FIRST          IA64_OPCODE_FIRST
+#define X_IN_MLX       IA64_OPCODE_X_IN_MLX
+#define LAST           IA64_OPCODE_LAST
+#define PRIV           IA64_OPCODE_PRIV
+#define NO_PRED                IA64_OPCODE_NO_PRED
+#define SLOT2          IA64_OPCODE_SLOT2
+#define PSEUDO         IA64_OPCODE_PSEUDO
+#define F2_EQ_F3       IA64_OPCODE_F2_EQ_F3
+#define LEN_EQ_64MCNT  IA64_OPCODE_LEN_EQ_64MCNT
+#define MOD_RRBS        IA64_OPCODE_MOD_RRBS
+#define POSTINC                IA64_OPCODE_POSTINC
+
+#define AR_CCV IA64_OPND_AR_CCV
+#define AR_PFS IA64_OPND_AR_PFS
+#define AR_CSD IA64_OPND_AR_CSD
+#define C1     IA64_OPND_C1
+#define C8     IA64_OPND_C8
+#define C16    IA64_OPND_C16
+#define GR0    IA64_OPND_GR0
+#define IP     IA64_OPND_IP
+#define PR     IA64_OPND_PR
+#define PR_ROT IA64_OPND_PR_ROT
+#define PSR    IA64_OPND_PSR
+#define PSR_L  IA64_OPND_PSR_L
+#define PSR_UM IA64_OPND_PSR_UM
+
+#define AR3    IA64_OPND_AR3
+#define B1     IA64_OPND_B1
+#define B2     IA64_OPND_B2
+#define CR3    IA64_OPND_CR3
+#define F1     IA64_OPND_F1
+#define F2     IA64_OPND_F2
+#define F3     IA64_OPND_F3
+#define F4     IA64_OPND_F4
+#define P1     IA64_OPND_P1
+#define P2     IA64_OPND_P2
+#define R1     IA64_OPND_R1
+#define R2     IA64_OPND_R2
+#define R3     IA64_OPND_R3
+#define R3_2   IA64_OPND_R3_2
+
+#define CPUID_R3 IA64_OPND_CPUID_R3
+#define DBR_R3 IA64_OPND_DBR_R3
+#define DTR_R3 IA64_OPND_DTR_R3
+#define ITR_R3 IA64_OPND_ITR_R3
+#define IBR_R3 IA64_OPND_IBR_R3
+#define MR3    IA64_OPND_MR3
+#define MSR_R3 IA64_OPND_MSR_R3
+#define PKR_R3 IA64_OPND_PKR_R3
+#define PMC_R3 IA64_OPND_PMC_R3
+#define PMD_R3 IA64_OPND_PMD_R3
+#define RR_R3  IA64_OPND_RR_R3
+
+#define CCNT5  IA64_OPND_CCNT5
+#define CNT2a  IA64_OPND_CNT2a
+#define CNT2b  IA64_OPND_CNT2b
+#define CNT2c  IA64_OPND_CNT2c
+#define CNT5   IA64_OPND_CNT5
+#define CNT6   IA64_OPND_CNT6
+#define CPOS6a IA64_OPND_CPOS6a
+#define CPOS6b IA64_OPND_CPOS6b
+#define CPOS6c IA64_OPND_CPOS6c
+#define IMM1   IA64_OPND_IMM1
+#define IMM14  IA64_OPND_IMM14
+#define IMM17  IA64_OPND_IMM17
+#define IMM22  IA64_OPND_IMM22
+#define IMM44  IA64_OPND_IMM44
+#define SOF    IA64_OPND_SOF
+#define SOL    IA64_OPND_SOL
+#define SOR    IA64_OPND_SOR
+#define IMM8   IA64_OPND_IMM8
+#define IMM8U4 IA64_OPND_IMM8U4
+#define IMM8M1 IA64_OPND_IMM8M1
+#define IMM8M1U4 IA64_OPND_IMM8M1U4
+#define IMM8M1U8 IA64_OPND_IMM8M1U8
+#define IMM9a  IA64_OPND_IMM9a
+#define IMM9b  IA64_OPND_IMM9b
+#define IMMU2  IA64_OPND_IMMU2
+#define IMMU21 IA64_OPND_IMMU21
+#define IMMU24 IA64_OPND_IMMU24
+#define IMMU62 IA64_OPND_IMMU62
+#define IMMU64 IA64_OPND_IMMU64
+#define IMMU7a IA64_OPND_IMMU7a
+#define IMMU7b IA64_OPND_IMMU7b
+#define IMMU9  IA64_OPND_IMMU9
+#define INC3   IA64_OPND_INC3
+#define LEN4   IA64_OPND_LEN4
+#define LEN6   IA64_OPND_LEN6
+#define MBTYPE4        IA64_OPND_MBTYPE4
+#define MHTYPE8        IA64_OPND_MHTYPE8
+#define POS6   IA64_OPND_POS6
+#define TAG13  IA64_OPND_TAG13
+#define TAG13b IA64_OPND_TAG13b
+#define TGT25  IA64_OPND_TGT25
+#define TGT25b IA64_OPND_TGT25b
+#define TGT25c IA64_OPND_TGT25c
+#define TGT64   IA64_OPND_TGT64
+
+#endif
diff --git a/arch/ia64/kdb/ia64.h b/arch/ia64/kdb/ia64.h
new file mode 100644 (file)
index 0000000..72e3716
--- /dev/null
@@ -0,0 +1,402 @@
+/* ia64.h -- Header file for ia64 opcode table
+   Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+       Contributed by David Mosberger-Tang <davidm@hpl.hp.com> */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+#ifndef opcode_ia64_h
+#define opcode_ia64_h
+
+#ifdef __KERNEL__
+#include <asm/bfd.h>
+#else  /* __KERNEL__ */
+#include <sys/types.h>
+
+#include "bfd.h"
+#endif /* __KERNEL__ */
+
+
+typedef BFD_HOST_U_64_BIT ia64_insn;
+
+enum ia64_insn_type
+  {
+    IA64_TYPE_NIL = 0, /* illegal type */
+    IA64_TYPE_A,       /* integer alu (I- or M-unit) */
+    IA64_TYPE_I,       /* non-alu integer (I-unit) */
+    IA64_TYPE_M,       /* memory (M-unit) */
+    IA64_TYPE_B,       /* branch (B-unit) */
+    IA64_TYPE_F,       /* floating-point (F-unit) */
+    IA64_TYPE_X,       /* long encoding (X-unit) */
+    IA64_TYPE_DYN,     /* Dynamic opcode */
+    IA64_NUM_TYPES
+  };
+
+enum ia64_unit
+  {
+    IA64_UNIT_NIL = 0, /* illegal unit */
+    IA64_UNIT_I,       /* integer unit */
+    IA64_UNIT_M,       /* memory unit */
+    IA64_UNIT_B,       /* branching unit */
+    IA64_UNIT_F,       /* floating-point unit */
+    IA64_UNIT_L,       /* long "unit" */
+    IA64_UNIT_X,       /* may be integer or branch unit */
+    IA64_NUM_UNITS
+  };
+
+/* Changes to this enumeration must be propagated to the operand table in
+   bfd/cpu-ia64-opc.c
+ */
+enum ia64_opnd
+  {
+    IA64_OPND_NIL,     /* no operand---MUST BE FIRST!*/
+
+    /* constants */
+    IA64_OPND_AR_CSD,  /* application register csd (ar.csd) */
+    IA64_OPND_AR_CCV,  /* application register ccv (ar.ccv) */
+    IA64_OPND_AR_PFS,  /* application register pfs (ar.pfs) */
+    IA64_OPND_C1,      /* the constant 1 */
+    IA64_OPND_C8,      /* the constant 8 */
+    IA64_OPND_C16,     /* the constant 16 */
+    IA64_OPND_GR0,     /* gr0 */
+    IA64_OPND_IP,      /* instruction pointer (ip) */
+    IA64_OPND_PR,      /* predicate register (pr) */
+    IA64_OPND_PR_ROT,  /* rotating predicate register (pr.rot) */
+    IA64_OPND_PSR,     /* processor status register (psr) */
+    IA64_OPND_PSR_L,   /* processor status register L (psr.l) */
+    IA64_OPND_PSR_UM,  /* processor status register UM (psr.um) */
+
+    /* register operands: */
+    IA64_OPND_AR3,     /* third application register # (bits 20-26) */
+    IA64_OPND_B1,      /* branch register # (bits 6-8) */
+    IA64_OPND_B2,      /* branch register # (bits 13-15) */
+    IA64_OPND_CR3,     /* third control register # (bits 20-26) */
+    IA64_OPND_F1,      /* first floating-point register # */
+    IA64_OPND_F2,      /* second floating-point register # */
+    IA64_OPND_F3,      /* third floating-point register # */
+    IA64_OPND_F4,      /* fourth floating-point register # */
+    IA64_OPND_P1,      /* first predicate # */
+    IA64_OPND_P2,      /* second predicate # */
+    IA64_OPND_R1,      /* first register # */
+    IA64_OPND_R2,      /* second register # */
+    IA64_OPND_R3,      /* third register # */
+    IA64_OPND_R3_2,    /* third register # (limited to gr0-gr3) */
+
+    /* indirect operands: */
+    IA64_OPND_CPUID_R3,        /* cpuid[reg] */
+    IA64_OPND_DBR_R3,  /* dbr[reg] */
+    IA64_OPND_DTR_R3,  /* dtr[reg] */
+    IA64_OPND_ITR_R3,  /* itr[reg] */
+    IA64_OPND_IBR_R3,  /* ibr[reg] */
+    IA64_OPND_MR3,     /* memory at addr of third register # */
+    IA64_OPND_MSR_R3,  /* msr[reg] */
+    IA64_OPND_PKR_R3,  /* pkr[reg] */
+    IA64_OPND_PMC_R3,  /* pmc[reg] */
+    IA64_OPND_PMD_R3,  /* pmd[reg] */
+    IA64_OPND_RR_R3,   /* rr[reg] */
+
+    /* immediate operands: */
+    IA64_OPND_CCNT5,   /* 5-bit count (31 - bits 20-24) */
+    IA64_OPND_CNT2a,   /* 2-bit count (1 + bits 27-28) */
+    IA64_OPND_CNT2b,   /* 2-bit count (bits 27-28): 1, 2, 3 */
+    IA64_OPND_CNT2c,   /* 2-bit count (bits 30-31): 0, 7, 15, or 16 */
+    IA64_OPND_CNT5,    /* 5-bit count (bits 14-18) */
+    IA64_OPND_CNT6,    /* 6-bit count (bits 27-32) */
+    IA64_OPND_CPOS6a,  /* 6-bit count (63 - bits 20-25) */
+    IA64_OPND_CPOS6b,  /* 6-bit count (63 - bits 14-19) */
+    IA64_OPND_CPOS6c,  /* 6-bit count (63 - bits 31-36) */
+    IA64_OPND_IMM1,    /* signed 1-bit immediate (bit 36) */
+    IA64_OPND_IMMU2,   /* unsigned 2-bit immediate (bits 13-14) */
+    IA64_OPND_IMMU7a,  /* unsigned 7-bit immediate (bits 13-19) */
+    IA64_OPND_IMMU7b,  /* unsigned 7-bit immediate (bits 20-26) */
+    IA64_OPND_SOF,     /* 8-bit stack frame size */
+    IA64_OPND_SOL,     /* 8-bit size of locals */
+    IA64_OPND_SOR,     /* 6-bit number of rotating registers (scaled by 8) */
+    IA64_OPND_IMM8,    /* signed 8-bit immediate (bits 13-19 & 36) */
+    IA64_OPND_IMM8U4,  /* cmp4*u signed 8-bit immediate (bits 13-19 & 36) */
+    IA64_OPND_IMM8M1,  /* signed 8-bit immediate -1 (bits 13-19 & 36) */
+    IA64_OPND_IMM8M1U4,        /* cmp4*u signed 8-bit immediate -1 (bits 13-19 & 36)*/
+    IA64_OPND_IMM8M1U8,        /* cmp*u signed 8-bit immediate -1 (bits 13-19 & 36) */
+    IA64_OPND_IMMU9,   /* unsigned 9-bit immediate (bits 33-34, 20-26) */
+    IA64_OPND_IMM9a,   /* signed 9-bit immediate (bits 6-12, 27, 36) */
+    IA64_OPND_IMM9b,   /* signed 9-bit immediate (bits 13-19, 27, 36) */
+    IA64_OPND_IMM14,   /* signed 14-bit immediate (bits 13-19, 27-32, 36) */
+    IA64_OPND_IMM17,   /* signed 17-bit immediate (2*bits 6-12, 24-31, 36) */
+    IA64_OPND_IMMU21,  /* unsigned 21-bit immediate (bits 6-25, 36) */
+    IA64_OPND_IMM22,   /* signed 22-bit immediate (bits 13-19, 22-36) */
+    IA64_OPND_IMMU24,  /* unsigned 24-bit immediate (bits 6-26, 31-32, 36) */
+    IA64_OPND_IMM44,   /* signed 44-bit immediate (2^16*bits 6-32, 36) */
+    IA64_OPND_IMMU62,  /* unsigned 62-bit immediate */
+    IA64_OPND_IMMU64,  /* unsigned 64-bit immediate (lotsa bits...) */
+    IA64_OPND_INC3,    /* signed 3-bit (bits 13-15): +/-1, 4, 8, 16 */
+    IA64_OPND_LEN4,    /* 4-bit count (bits 27-30 + 1) */
+    IA64_OPND_LEN6,    /* 6-bit count (bits 27-32 + 1) */
+    IA64_OPND_MBTYPE4, /* 4-bit mux type (bits 20-23) */
+    IA64_OPND_MHTYPE8, /* 8-bit mux type (bits 20-27) */
+    IA64_OPND_POS6,    /* 6-bit count (bits 14-19) */
+    IA64_OPND_TAG13,   /* signed 13-bit tag (ip + 16*bits 6-12, 33-34) */
+    IA64_OPND_TAG13b,  /* signed 13-bit tag (ip + 16*bits 24-32) */
+    IA64_OPND_TGT25,   /* signed 25-bit (ip + 16*bits 6-25, 36) */
+    IA64_OPND_TGT25b,  /* signed 25-bit (ip + 16*bits 6-12, 20-32, 36) */
+    IA64_OPND_TGT25c,  /* signed 25-bit (ip + 16*bits 13-32, 36) */
+    IA64_OPND_TGT64,    /* 64-bit (ip + 16*bits 13-32, 36, 2-40(L)) */
+    IA64_OPND_LDXMOV,  /* any symbol, generates R_IA64_LDXMOV.  */
+
+    IA64_OPND_COUNT    /* # of operand types (MUST BE LAST!) */
+  };
+
+enum ia64_dependency_mode
+{
+  IA64_DV_RAW,
+  IA64_DV_WAW,
+  IA64_DV_WAR,
+};
+
+enum ia64_dependency_semantics
+{
+  IA64_DVS_NONE,
+  IA64_DVS_IMPLIED,
+  IA64_DVS_IMPLIEDF,
+  IA64_DVS_DATA,
+  IA64_DVS_INSTR,
+  IA64_DVS_SPECIFIC,
+  IA64_DVS_STOP,
+  IA64_DVS_OTHER,
+};
+
+enum ia64_resource_specifier
+{
+  IA64_RS_ANY,
+  IA64_RS_AR_K,
+  IA64_RS_AR_UNAT,
+  IA64_RS_AR, /* 8-15, 20, 22-23, 31, 33-35, 37-39, 41-43, 45-47, 67-111 */
+  IA64_RS_ARb, /* 48-63, 112-127 */
+  IA64_RS_BR,
+  IA64_RS_CFM,
+  IA64_RS_CPUID,
+  IA64_RS_CR_IRR,
+  IA64_RS_CR_LRR,
+  IA64_RS_CR, /* 3-7,10-15,18,26-63,75-79,82-127 */
+  IA64_RS_DBR,
+  IA64_RS_FR,
+  IA64_RS_FRb,
+  IA64_RS_GR0,
+  IA64_RS_GR,
+  IA64_RS_IBR,
+  IA64_RS_INSERVICE, /* CR[EOI] or CR[IVR] */
+  IA64_RS_MSR,
+  IA64_RS_PKR,
+  IA64_RS_PMC,
+  IA64_RS_PMD,
+  IA64_RS_PR,  /* non-rotating, 1-15 */
+  IA64_RS_PRr, /* rotating, 16-62 */
+  IA64_RS_PR63,
+  IA64_RS_RR,
+
+  IA64_RS_ARX, /* ARs not in RS_AR or RS_ARb */
+  IA64_RS_CRX, /* CRs not in RS_CR */
+  IA64_RS_PSR, /* PSR bits */
+  IA64_RS_RSE, /* implementation-specific RSE resources */
+  IA64_RS_AR_FPSR,
+};
+
+enum ia64_rse_resource
+{
+  IA64_RSE_N_STACKED_PHYS,
+  IA64_RSE_BOF,
+  IA64_RSE_STORE_REG,
+  IA64_RSE_LOAD_REG,
+  IA64_RSE_BSPLOAD,
+  IA64_RSE_RNATBITINDEX,
+  IA64_RSE_CFLE,
+  IA64_RSE_NDIRTY,
+};
+
+/* Information about a given resource dependency */
+struct ia64_dependency
+{
+  /* Name of the resource */
+  const char *name;
+  /* Does this dependency need further specification? */
+  enum ia64_resource_specifier specifier;
+  /* Mode of dependency */
+  enum ia64_dependency_mode mode;
+  /* Dependency semantics */
+  enum ia64_dependency_semantics semantics;
+  /* Register index, if applicable (distinguishes AR, CR, and PSR deps) */
+#define REG_NONE (-1)
+  int regindex;
+  /* Special info on semantics */
+  const char *info;
+};
+
+/* Two arrays of indexes into the ia64_dependency table.
+   chks are dependencies to check for conflicts when an opcode is
+   encountered; regs are dependencies to register (mark as used) when an
+   opcode is used.  chks correspond to readers (RAW) or writers (WAW or
+   WAR) of a resource, while regs correspond to writers (RAW or WAW) and
+   readers (WAR) of a resource.  */
+struct ia64_opcode_dependency
+{
+  int nchks;
+  const unsigned short *chks;
+  int nregs;
+  const unsigned short *regs;
+};
+
+/* encode/extract the note/index for a dependency */
+#define RDEP(N,X) (((N)<<11)|(X))
+#define NOTE(X) (((X)>>11)&0x1F)
+#define DEP(X) ((X)&0x7FF)
+
+/* A template descriptor describes the execution units that are active
+   for each of the three slots.  It also specifies the location of
+   instruction group boundaries that may be present between two slots.  */
+struct ia64_templ_desc
+  {
+    int group_boundary;        /* 0=no boundary, 1=between slot 0 & 1, etc. */
+    enum ia64_unit exec_unit[3];
+    const char *name;
+  };
+
+/* The opcode table is an array of struct ia64_opcode.  */
+
+struct ia64_opcode
+  {
+    /* The opcode name.  */
+    const char *name;
+
+    /* The type of the instruction: */
+    enum ia64_insn_type type;
+
+    /* Number of output operands: */
+    int num_outputs;
+
+    /* The opcode itself.  Those bits which will be filled in with
+       operands are zeroes.  */
+    ia64_insn opcode;
+
+    /* The opcode mask.  This is used by the disassembler.  This is a
+       mask containing ones indicating those bits which must match the
+       opcode field, and zeroes indicating those bits which need not
+       match (and are presumably filled in by operands).  */
+    ia64_insn mask;
+
+    /* An array of operand codes.  Each code is an index into the
+       operand table.  They appear in the order which the operands must
+       appear in assembly code, and are terminated by a zero.  */
+    enum ia64_opnd operands[5];
+
+    /* One bit flags for the opcode.  These are primarily used to
+       indicate specific processors and environments support the
+       instructions.  The defined values are listed below. */
+    unsigned int flags;
+
+    /* Used by ia64_find_next_opcode (). */
+    short ent_index;
+
+    /* Opcode dependencies. */
+    const struct ia64_opcode_dependency *dependencies;
+  };
+
+/* Values defined for the flags field of a struct ia64_opcode.  */
+
+#define IA64_OPCODE_FIRST      (1<<0)  /* must be first in an insn group */
+#define IA64_OPCODE_X_IN_MLX   (1<<1)  /* insn is allowed in X slot of MLX */
+#define IA64_OPCODE_LAST       (1<<2)  /* must be last in an insn group */
+#define IA64_OPCODE_PRIV       (1<<3)  /* privileged instruct */
+#define IA64_OPCODE_SLOT2      (1<<4)  /* insn allowed in slot 2 only */
+#define IA64_OPCODE_NO_PRED    (1<<5)  /* insn cannot be predicated */
+#define IA64_OPCODE_PSEUDO     (1<<6)  /* insn is a pseudo-op */
+#define IA64_OPCODE_F2_EQ_F3   (1<<7)  /* constraint: F2 == F3 */
+#define IA64_OPCODE_LEN_EQ_64MCNT      (1<<8)  /* constraint: LEN == 64-CNT */
+#define IA64_OPCODE_MOD_RRBS    (1<<9) /* modifies all rrbs in CFM */
+#define IA64_OPCODE_POSTINC    (1<<10) /* postincrement MR3 operand */
+
+/* A macro to extract the major opcode from an instruction.  */
+#define IA64_OP(i)     (((i) >> 37) & 0xf)
+
+enum ia64_operand_class
+  {
+    IA64_OPND_CLASS_CST,       /* constant */
+    IA64_OPND_CLASS_REG,       /* register */
+    IA64_OPND_CLASS_IND,       /* indirect register */
+    IA64_OPND_CLASS_ABS,       /* absolute value */
+    IA64_OPND_CLASS_REL,       /* IP-relative value */
+  };
+
+/* The operands table is an array of struct ia64_operand.  */
+
+struct ia64_operand
+{
+  enum ia64_operand_class class;
+
+  /* Set VALUE as the operand bits for the operand of type SELF in the
+     instruction pointed to by CODE.  If an error occurs, *CODE is not
+     modified and the returned string describes the cause of the
+     error.  If no error occurs, NULL is returned.  */
+  const char *(*insert) (const struct ia64_operand *self, ia64_insn value,
+                        ia64_insn *code);
+
+  /* Extract the operand bits for an operand of type SELF from
+     instruction CODE store them in *VALUE.  If an error occurs, the
+     cause of the error is described by the string returned.  If no
+     error occurs, NULL is returned.  */
+  const char *(*extract) (const struct ia64_operand *self, ia64_insn code,
+                         ia64_insn *value);
+
+  /* A string whose meaning depends on the operand class.  */
+
+  const char *str;
+
+  struct bit_field
+    {
+      /* The number of bits in the operand.  */
+      int bits;
+
+      /* How far the operand is left shifted in the instruction.  */
+      int shift;
+    }
+  field[4];            /* no operand has more than this many bit-fields */
+
+  unsigned int flags;
+
+  const char *desc;    /* brief description */
+};
+
+/* Values defined for the flags field of a struct ia64_operand.  */
+
+/* Disassemble as signed decimal (instead of hex): */
+#define IA64_OPND_FLAG_DECIMAL_SIGNED  (1<<0)
+/* Disassemble as unsigned decimal (instead of hex): */
+#define IA64_OPND_FLAG_DECIMAL_UNSIGNED        (1<<1)
+
+extern const struct ia64_templ_desc ia64_templ_desc[16];
+
+/* The tables are sorted by major opcode number and are otherwise in
+   the order in which the disassembler should consider instructions.  */
+extern struct ia64_opcode ia64_opcodes_a[];
+extern struct ia64_opcode ia64_opcodes_i[];
+extern struct ia64_opcode ia64_opcodes_m[];
+extern struct ia64_opcode ia64_opcodes_b[];
+extern struct ia64_opcode ia64_opcodes_f[];
+extern struct ia64_opcode ia64_opcodes_d[];
+
+
+extern struct ia64_opcode *ia64_find_opcode (const char *name);
+extern struct ia64_opcode *ia64_find_next_opcode (struct ia64_opcode *ent);
+
+extern struct ia64_opcode *ia64_dis_opcode (ia64_insn insn,
+                                           enum ia64_insn_type type);
+
+extern void ia64_free_opcode (struct ia64_opcode *ent);
+extern const struct ia64_dependency *ia64_find_dependency (int index);
+
+/* To avoid circular library dependencies, this array is implemented
+   in bfd/cpu-ia64-opc.c: */
+extern const struct ia64_operand elf64_ia64_operands[IA64_OPND_COUNT];
+
+#endif /* opcode_ia64_h */
diff --git a/arch/ia64/kdb/kdb_cmds b/arch/ia64/kdb/kdb_cmds
new file mode 100644 (file)
index 0000000..9ce7d2c
--- /dev/null
@@ -0,0 +1,17 @@
+# Standard architecture specific commands for kdb.
+# These commands are appended to those in kdb/kdb_cmds, see that file for
+# restrictions.
+
+# Standard debugging information for first level support, invoked from archkdb*
+# commands that are defined in kdb/kdb_cmds.
+
+defcmd archkdbcommon "" "Common arch debugging"
+  set LINES 2000000
+  set BTAPROMPT 0
+  -summary
+  -id %ip-0x40
+  -cpu
+  -ps
+  -dmesg 600
+  -bt
+endefcmd
diff --git a/arch/ia64/kdb/kdba_bp.c b/arch/ia64/kdb/kdba_bp.c
new file mode 100644 (file)
index 0000000..0d71baf
--- /dev/null
@@ -0,0 +1,841 @@
+/*
+ * Kernel Debugger Architecture Dependent Breakpoint Handling
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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>
+#include <asm/pgalloc.h>
+
+
+static char *kdba_rwtypes[] = { "Instruction(Register)", "Data Write",
+                       "I/O", "Data Access"};
+
+/*
+ * Table describing processor architecture hardware
+ * breakpoint registers.
+ */
+
+static kdbhard_bp_t kdb_hardbreaks[KDB_MAXHARDBPT];
+
+#ifdef CONFIG_KDB_HARDWARE_BREAKPOINTS
+/*
+ * Counters for number of debug registers used on each CPU.
+ * Used to detect when to enable and disable debug traps.
+ */
+static unsigned char kdb_dbrs_used[NR_CPUS];
+#endif /* CONFIG_KDB_HARDWARE_BREAKPOINTS */
+
+/*
+ * 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)
+{
+       int i;
+       kdb_dbtrap_t rv = KDB_DB_BPT;
+       kdb_bp_t *bp;
+
+       if (KDB_NULL_REGS(regs))
+               return KDB_DB_NOBPT;
+
+       if (KDB_DEBUG(BP))
+               kdb_printf("kdba_db_trap: error %d\n", error);
+
+       if (error == 36) {
+               /* Single step */
+               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)) {
+                                               kdba_clearsinglestep(regs);
+                                               return(KDB_DB_SSBPT);
+                                       }
+                                       break;
+                               }
+                       }
+                       if (i == KDB_MAXBPT) {
+                               kdb_printf("kdb: Unable to find delayed breakpoint\n");
+                       }
+                       if (!KDB_STATE(DOING_SS)) {
+                               kdba_clearsinglestep(regs);
+                               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))
+                       return(KDB_DB_NOBPT);
+
+               /* single step */
+               rv = KDB_DB_SS;         /* Indicate single step */
+               if (KDB_STATE(DOING_SSB))               /* No ia64 ssb support yet */
+                       KDB_STATE_CLEAR(DOING_SSB);     /* No ia64 ssb support yet */
+               if (KDB_STATE(DOING_SSB)) {
+                       /* No IA64 ssb support yet */
+               } else {
+                       /*
+                        * Print current insn
+                        */
+                       kdb_machreg_t pc = regs->cr_iip + ia64_psr(regs)->ri * 6;
+                       kdb_printf("SS trap at ");
+                       kdb_symbol_print(pc, NULL, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+                       kdb_id1(pc);
+                       KDB_STATE_CLEAR(DOING_SS);
+               }
+
+               if (rv != KDB_DB_SSB)
+                       kdba_clearsinglestep(regs);
+       }
+
+       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 ip.  It should be called
+ *              once per breakpoint and the result cached.
+ */
+
+kdb_dbtrap_t
+kdba_bp_trap(struct pt_regs *regs, int error)
+{
+       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: ip=0x%lx "
+                          "regs=0x%p sp=0x%lx\n",
+                          regs->cr_iip, regs, regs->r12);
+
+       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 (bp->bp_addr == regs->cr_iip) {
+                       /* Hit this breakpoint.  */
+                       kdb_printf("Instruction(i) breakpoint #%d at 0x%lx\n",
+                                 i, regs->cr_iip);
+                       kdb_id1(regs->cr_iip);
+                       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(s)
+ *     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->cr_iip = 0x%lx\n", regs->cr_iip);
+
+       /*
+        * 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:
+ */
+
+static 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) {
+               /* Note that bp->bp_hard[NR_CPU] is for x86.
+                * The ia64 uses bp->bp_hard[0] only.
+                */
+               kdba_printbpreg(bp->bp_hard[0]);
+               if (bp->bp_hard[0]->bph_mode != 0) {
+                       kdb_printf(" for %d bytes",
+                                  bp->bp_hard[0]->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 IA64 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;
+               }
+
+               if (bph->bph_mode == 0)
+                       kdba_check_pc(&bp->bp_addr);
+
+               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 = 0;      /* software, break is fault, not trap */
+               }
+       }
+
+       if (bph->bph_mode == 0 && 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;
+#ifndef CONFIG_KDB_HARDWARE_BREAKPOINTS
+       if (!bph->bph_free) {
+               kdb_printf("kdba_parsebp hardware breakpoints are not supported yet\n");
+               return KDB_NOTIMP;
+       }
+#endif /* CONFIG_KDB_HARDWARE_BREAKPOINTS */
+       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:
+ */
+
+static 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_alloc_hwbp
+ *
+ *     Associate a hardware registers with a breakpoint.
+ *     If hw bp is global hw registers descriptor will be allocated
+ *     on every CPU.
+ *
+ * Parameters:
+ *     bp - hardware bp
+ *     diagp - pointer to variable that will store error when
+ *     function complete
+ * Outputs:
+ *     None.
+ * Returns:
+ *     None
+ * Locking:
+ *     None.
+ * Remarks:
+ *     Should be called with correct bp->bp_template.
+ */
+
+void
+kdba_alloc_hwbp(kdb_bp_t *bp, int *diagp)
+{
+       /* Note that bp->bp_hard[NR_CPU] is for x86.
+        * The ia64 uses bp->bp_hard[0] only.
+        */
+       bp->bp_hard[0] = kdba_allocbp(&bp->bp_template, diagp);
+       bp->bp_hardtype = 1;
+}
+
+
+
+/*
+ * kdba_freebp
+ *
+ *     Deallocate a hardware breakpoint
+ *
+ * Parameters:
+ *     None.
+ * Outputs:
+ *     None.
+ * Returns:
+ *     Zero for success, a kdb diagnostic for failure
+ * Locking:
+ *     None.
+ * Remarks:
+ */
+
+static void
+kdba_freebp(kdbhard_bp_t *bph)
+{
+       bph->bph_free = 1;
+}
+
+/*
+ * kdba_free_hwbp
+ *
+ *     Frees allocated hw registers descriptors for bp.
+ *     If hw bp is global, hw registers descriptors will be freed
+ *     on every CPU.
+ *
+ * Parameters:
+ *     bp - hardware bp
+ * Outputs:
+ *     None.
+ * Returns:
+ *     None
+ * Locking:
+ *     None.
+ * Remarks:
+ *     Should be called with correct bp->bp_template
+ */
+
+void
+kdba_free_hwbp(kdb_bp_t *bp)
+{
+       /* When kernel enters KDB, first, all local bps
+        * are removed, so here we don't need to clear
+        * debug registers.
+        */
+
+       kdba_freebp(bp->bp_hard[0]);
+       bp->bp_hard[0] = NULL;
+       bp->bp_hardtype = 0;
+}
+
+
+/*
+ * 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 ia64 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;
+       }
+}
+
+#ifdef CONFIG_KDB_HARDWARE_BREAKPOINTS
+/*
+ * Enable Instruction Debug & Data Debug faults on this CPU now.
+ */
+static inline void kdba_enable_debug_faults(void)
+{
+       unsigned long tmp;
+
+       tmp = ia64_getreg(_IA64_REG_PSR);
+       ia64_stop();
+       tmp |= IA64_PSR_DB;
+       ia64_stop();
+       ia64_setreg(_IA64_REG_PSR_L, tmp);
+       ia64_srlz_i();
+       if (KDB_DEBUG(BP))
+               kdb_printf("enabling debug faults: [%d]PSR.L=%08x\n",
+                          smp_processor_id(), (unsigned int)tmp);
+}
+
+/*
+ * Disable Instruction Debug & Data Debug faults on this CPU now.
+ */
+static inline void kdba_disable_debug_faults(void)
+{
+       unsigned long tmp;
+
+       tmp = ia64_getreg(_IA64_REG_PSR);
+       ia64_stop();
+       tmp &= ~IA64_PSR_DB;
+       ia64_stop();
+       ia64_setreg(_IA64_REG_PSR_L, tmp);
+       ia64_srlz_i();
+       if (KDB_DEBUG(BP))
+               kdb_printf("disabling debug faults: [%d]PSR.L=%08x\n",
+                          smp_processor_id(), (unsigned int)tmp);
+}
+#endif /* CONFIG_KDB_HARDWARE_BREAKPOINTS */
+
+/*
+ * kdba_installbp
+ *
+ *     Install a breakpoint
+ *
+ * Parameters:
+ *     regs    Exception frame
+ *     bp      Breakpoint structure for the breakpoint to be installed
+ * Outputs:
+ *     None.
+ * Returns:
+ *     0 if breakpoint set, otherwise error.
+ * 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_hardtype) {
+#ifdef CONFIG_KDB_HARDWARE_BREAKPOINTS
+               /*
+                * Hardware breakpoints are always local for the
+                * purposes of installation (i.e. they use per-cpu
+                * registers), so we don't need to check bp_installed
+                */
+               kdba_installdbreg(bp);
+               if (++kdb_dbrs_used[smp_processor_id()] == 1)
+                       kdba_enable_debug_faults();
+               bp->bp_installed = 1;
+               if (KDB_DEBUG(BP)) {
+                       kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt0 "\n",
+                                  bp->bp_hard[0]->bph_reg, bp->bp_addr);
+               }
+#endif /* CONFIG_KDB_HARDWARE_BREAKPOINTS */
+
+       } else if (bp->bp_delay) {
+               if (!bp->bp_installed) {
+                       if (KDB_DEBUG(BP))
+                               kdb_printf("kdba_installbp delayed bp\n");
+                       kdba_handle_bp(regs, bp);
+               }
+       } else {
+               if (!bp->bp_installed) {
+                       /* Software breakpoints always use slot 0 in the 128 bit
+                        * bundle.  The template type does not matter, slot 0
+                        * can only be M or B and the encodings for break.m and
+                        * break.b are the same.
+                        */
+                       unsigned long break_inst;
+                       if (kdb_getarea_size(bp->bp_inst.inst, bp->bp_addr, sizeof(bp->bp_inst.inst))) {
+                               kdb_printf("kdba_installbp failed to read software breakpoint at 0x%lx\n", bp->bp_addr);
+                               return(1);
+                       }
+                       break_inst = (bp->bp_inst.inst[0] & ~INST_SLOT0_MASK) | BREAK_INSTR;
+                       if (kdb_putarea_size(bp->bp_addr, &break_inst, sizeof(break_inst))) {
+                               kdb_printf("kdba_installbp failed to set software breakpoint at 0x%lx\n", bp->bp_addr);
+                               return(1);
+                       }
+                       if (KDB_DEBUG(BP))
+                               kdb_printf("kdba_installbp instruction 0x%lx at " kdb_bfd_vma_fmt0 "\n",
+                                          BREAK_INSTR, bp->bp_addr);
+                       bp->bp_installed = 1;
+                       flush_icache_range(bp->bp_addr, bp->bp_addr+16);
+               }
+       }
+       return(0);
+}
+
+/*
+ * kdba_removebp
+ *
+ *     Make a breakpoint ineffective.
+ *
+ * Parameters:
+ *     None.
+ * Outputs:
+ *     None.
+ * Returns:
+ *     0 if breakpoint removed, otherwise error.
+ * 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_hardtype) {
+#ifdef CONFIG_KDB_HARDWARE_BREAKPOINTS
+               if (KDB_DEBUG(BP)) {
+                       kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt0 "\n",
+                                  bp->bp_hard[0]->bph_reg, bp->bp_addr);
+               }
+               if (--kdb_dbrs_used[smp_processor_id()] == 0)
+                       kdba_disable_debug_faults();
+               kdba_removedbreg(bp);
+#endif /* CONFIG_KDB_HARDWARE_BREAKPOINTS */
+       } else {
+               if (bp->bp_installed) {
+                       if (KDB_DEBUG(BP))
+                               kdb_printf("kdb: restoring instruction 0x%016lx%016lx at " kdb_bfd_vma_fmt0 "\n",
+                                          bp->bp_inst.inst[0], bp->bp_inst.inst[1], bp->bp_addr);
+                       if (kdba_putarea_size(bp->bp_addr, bp->bp_inst.inst, sizeof(bp->bp_inst.inst)))
+                               return(1);
+               }
+               bp->bp_installed = 0;
+               flush_icache_range(bp->bp_addr, bp->bp_addr+16);
+       }
+       return(0);
+}
diff --git a/arch/ia64/kdb/kdba_bt.c b/arch/ia64/kdb/kdba_bt.c
new file mode 100644 (file)
index 0000000..fc59674
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Kernel Debugger Architecture Dependent Stack Traceback
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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>
+#include <asm/sections.h>
+
+/*
+ * bt_print_one
+ *
+ *     Print one back trace entry.
+ *
+ * Inputs:
+ *     ip      Current program counter.
+ *     symtab  Information about symbol that ip 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 ip,
+            const kdb_symtab_t *symtab, int argcount,
+            struct unw_frame_info *info)
+{
+       int btsymarg = 0;               /* Convert arguments to symbols */
+       int btsp = 0;                   /* Print stack and backing store pointers */
+       int nosect = 0;                 /* Suppress section data */
+       int args;
+       kdb_machreg_t sp, bsp, cfm;
+
+       kdbgetintenv("BTSYMARG", &btsymarg);
+       kdbgetintenv("BTSP", &btsp);
+       kdbgetintenv("NOSECT", &nosect);
+
+       unw_get_sp(info, &sp);
+       unw_get_bsp(info, &bsp);
+       unw_get_cfm(info, &cfm);
+       kdb_symbol_print(ip, symtab, KDB_SP_VALUE|KDB_SP_NEWLINE);
+       args = (cfm >> 7) & 0x7f;       /* sol */
+       if (!args)
+               args = cfm & 0x7f;      /* no in/local, use sof instead */
+       if (argcount && args) {
+               int i, argc = args;
+
+               kdb_printf("        args (");
+               if (argc > argcount)
+                       argc = argcount;
+
+               for(i = 0; i < argc; i++){
+                       kdb_machreg_t arg;
+                       char nat;
+                       if (unw_access_gr(info, i+32, &arg, &nat, 0))
+                               arg = 0;
+
+                       if (i)
+                               kdb_printf(", ");
+                       kdb_printf("0x%lx", arg);
+               }
+               kdb_printf(")\n");
+               if (btsymarg) {
+                       kdb_symtab_t    arg_symtab;
+                       kdb_machreg_t   arg;
+                       for(i = 0; i < argc; i++){
+                               char nat;
+                               if (unw_access_gr(info, i+32, &arg, &nat, 0))
+                                       arg = 0;
+                               if (kdbnearsym(arg, &arg_symtab)) {
+                                       kdb_printf("        arg %d ", i);
+                                       kdb_symbol_print(arg, &arg_symtab, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+                               }
+                       }
+               }
+       }
+       if (symtab->sym_name) {
+               if (!nosect) {
+                       kdb_printf("        %s", symtab->mod_name);
+                       if (symtab->sec_name)
+                               kdb_printf(" %s 0x%lx", symtab->sec_name, symtab->sec_start);
+                       kdb_printf(" 0x%lx", symtab->sym_start);
+                       if (symtab->sym_end)
+                               kdb_printf(" 0x%lx", symtab->sym_end);
+                       kdb_printf("\n");
+               }
+               if (strncmp(symtab->sym_name, "ia64_spinlock_contention", 24) == 0) {
+                       kdb_machreg_t r31;
+                       char nat;
+                       kdb_printf("        r31 (spinlock address) ");
+                       if (unw_access_gr(info, 31, &r31, &nat, 0))
+                               r31 = 0;
+                       kdb_symbol_print(r31, NULL, KDB_SP_VALUE|KDB_SP_NEWLINE);
+               }
+       }
+       if (btsp)
+               kdb_printf("        sp 0x%016lx bsp 0x%016lx cfm 0x%016lx info->pfs_loc 0x%016lx 0x%016lx\n",
+                               sp, bsp, cfm, (u64) info->pfs_loc, info->pfs_loc ? *(info->pfs_loc) : 0);
+}
+
+/*
+ * kdba_bt_stack
+ *
+ *     Unwind the ia64 backtrace for a specified process.
+ *
+ * Inputs:
+ *     argcount
+ *     p       Pointer to task structure to unwind.
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     none.
+ */
+
+static int
+kdba_bt_stack(int argcount, const struct task_struct *p)
+{
+       kdb_symtab_t symtab;
+       struct unw_frame_info info;
+       struct switch_stack *sw;
+       struct pt_regs *regs = NULL;
+       int count = 0;
+       int btsp = 0;                   /* Backtrace the kdb code as well */
+       u64 *prev_pfs_loc = NULL;
+       extern char __attribute__ ((weak)) ia64_spinlock_contention_pre3_4[];
+       extern char __attribute__ ((weak)) ia64_spinlock_contention_pre3_4_end[];
+
+       /*
+        * Upon entering kdb_main_loop, the stack frame looks like this:
+        *
+        *      +---------------------+
+        *      |   struct pt_regs    |
+        *      +---------------------+
+        *      |                     |
+        *      |   kernel stack      |
+        *      |                     |
+        *      +=====================+ <--- top of stack upon entering kdb
+        *      |   struct pt_regs    |
+        *      +---------------------+
+        *      |                     |
+        *      |   kdb stack         |
+        *      |                     |
+        *      +---------------------+
+        *      | struct switch_stack |
+        *      +=====================+ <--- kdb_running_process[cpu].arch.sw from do_kdba_main_loop
+        *
+        * When looking at another process, we do not have the address of the
+        * current pt_regs, it is NULL.  If the process has saved its state, use
+        * that pt_regs instead.
+        */
+
+       kdbgetintenv("BTSP", &btsp);
+
+       if (kdb_task_has_cpu(p)) {
+               struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+               if (krp->seqno) {
+                       sw = krp->arch.sw;
+                       regs = krp->regs;
+               }
+               else
+                       sw = NULL;
+       }
+       else {
+               /* Not running, assume blocked */
+               sw = (struct switch_stack *) (p->thread.ksp + 16);
+       }
+       if (!sw) {
+               kdb_printf("Process does not have a switch_stack, cannot backtrace\n");
+               kdb_ps1(p);
+               return 0;
+       }
+
+       unw_init_frame_info(&info, (struct task_struct *)p, sw);
+
+       /* If we have the address of pt_regs, suppress backtrace on the frames below
+        * pt_regs.  No point in displaying kdb itself, unless the user is debugging
+        * the unwinder using set BTSP=1.
+        */
+       if (regs && !btsp) {
+               kdb_machreg_t sp;
+               if (user_mode(regs)) {
+                       kdb_printf("Process was interrupted in user mode, no backtrace available\n");
+                       return 0;
+               }
+               do {
+                       unw_get_sp(&info, &sp);
+                       if (sp >= (kdb_machreg_t)regs)
+                               break;
+               } while (unw_unwind(&info) >= 0 && count++ < 200);
+       }
+
+       do {
+               kdb_machreg_t ip;
+
+               /* Avoid unsightly console message from unw_unwind() when attempting
+                * to unwind through the Interrupt Vector Table which has no unwind
+                * information.  dispatch_illegal_op_fault() is an exception, it sits
+                * in the 0x3c00 slot.
+                */
+               if (info.ip >= (u64)__start_ivt_text && info.ip < (u64)__end_ivt_text) {
+                       if (info.ip < (u64)__start_ivt_text + 0x3c00 ||
+                           info.ip >= (u64)__start_ivt_text + 0x4000)
+                               return 0;
+               }
+
+               /* WAR for spinlock contention from leaf functions.  ia64_spinlock_contention_pre3_4
+                * has ar.pfs == r0.  Leaf functions do not modify ar.pfs so ar.pfs remains
+                * as 0, stopping the backtrace.  Record the previous ar.pfs when the current
+                * IP is in ia64_spinlock_contention_pre3_4 then unwind, if pfs_loc has not changed
+                * after unwind then use pt_regs.ar_pfs which is where the real ar.pfs is for
+                * leaf functions.
+                */
+               if (prev_pfs_loc && regs && info.pfs_loc == prev_pfs_loc)
+                       info.pfs_loc = &regs->ar_pfs;
+               prev_pfs_loc = (info.ip >= (u64)ia64_spinlock_contention_pre3_4 &&
+                               info.ip < (u64)ia64_spinlock_contention_pre3_4_end) ?
+                              info.pfs_loc : NULL;
+
+               unw_get_ip(&info, &ip);
+               if (ip == 0)
+                       break;
+
+               kdbnearsym(ip, &symtab);
+               if (!symtab.sym_name) {
+                       kdb_printf("0x%0*lx - No name.  May be an area that has no unwind data\n",
+                               (int)(2*sizeof(ip)), ip);
+                       return 0;
+               }
+               bt_print_one(ip, &symtab, argcount, &info);
+       } while (unw_unwind(&info) >= 0 && count++ < 200);
+       if (count >= 200)
+               kdb_printf("bt truncated, count limit reached\n");
+
+       return 0;
+}
+
+int
+kdba_bt_address(kdb_machreg_t addr, int argcount)
+{
+       kdb_printf("Backtrace from a stack address is not supported on ia64\n");
+       return KDB_NOTIMP;
+}
+
+/*
+ * 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(const struct task_struct *p, int argcount)
+{
+       return kdba_bt_stack(argcount, p);
+}
diff --git a/arch/ia64/kdb/kdba_fru.c b/arch/ia64/kdb/kdba_fru.c
new file mode 100644 (file)
index 0000000..4ba1eec
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Kernel Debugger Architecture Dependent FRU functions.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/module.h>
+#include <asm/sal.h>
+#include <asm/sn/sn_sal.h>
+
+MODULE_AUTHOR("Jesse Barnes");
+MODULE_DESCRIPTION("Capture FRU data");
+MODULE_LICENSE("GPL");
+
+/**
+ * kdba_fru - capture FRU data
+ * @argc: arg count
+ * @argv: arg values
+ *
+ * Tell the system contollers to capture FRU data
+ */
+static int
+kdba_fru(int argc, const char **argv)
+{
+       u64 ret;
+
+       kdb_printf("Capturing FRU data...");
+       ret = ia64_sn_fru_capture();
+       kdb_printf("done.\n");
+       return ret;
+}
+
+/**
+ * kdba_fru_init - register 'fru' command with kdb
+ *
+ * Register the 'fru' command with kdb at load time.
+ */
+static int __init
+kdba_fru_init(void)
+{
+       kdb_register("fru", kdba_fru, 0, "Capture FRU data", 0);
+
+       return 0;
+}
+
+/**
+ * kdba_fru_exit - unregister the 'fru' command
+ *
+ * Tell kdb that the 'fru' command is no longer available.
+ */
+static void __exit
+kdba_fru_exit(void)
+{
+       kdb_unregister("fru");
+}
+
+module_init(kdba_fru_init)
+module_exit(kdba_fru_exit)
diff --git a/arch/ia64/kdb/kdba_id.c b/arch/ia64/kdb/kdba_id.c
new file mode 100644 (file)
index 0000000..fbba06d
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * Kernel Debugger Architecture Dependent Instruction Disassembly
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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>
+#include <asm/patch.h>
+
+#define KDBA_PRINTBUF_LEN      64      /* buffer len to print a single instr */
+#define KDBA_READBUFFER_LEN    256     /* buffer for BFD disassembler */
+
+#define BUNDLE_MULTIPLIER      3       /* how many instr/bundle */
+#define BUNDLE_SIZE            16      /* how many bytes/bundle */
+#define KDBA_DEFAULT_IDLEN     3       /* default number of bundles to disassemble */
+
+/*
+ * 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 */
+static void
+kdba_printaddress(kdb_machreg_t addr, disassemble_info *dip, int flag)
+{
+       kdb_symtab_t symtab;
+       int spaces = 5;
+       unsigned int offset;
+       int slot;
+
+       /* Some code prints slot number, some prints "byte" offset
+        * from start of bundle.  Standardise on "byte" offset.
+        */
+       slot = addr & 0x0f;
+       if (slot < 3)
+               slot *= 6;
+       addr = (addr & ~0x0f) + slot;
+
+       /*
+        * Print a symbol name or address as necessary.
+        */
+       dip->fprintf_func(dip->stream, "0x%0*lx ", (int)(2*sizeof(addr)), addr);
+       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, "%s", 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);
+               }
+       }
+
+       if (flag) {
+               if (spaces < 1) {
+                       spaces = 1;
+               }
+               dip->fprintf_func(dip->stream, ":%*s", spaces, " ");
+       }
+}
+
+/* Calls outside the current kernel module use a PLT */
+
+static int addr_maybe_plt;
+
+/* The templates below were extracted from arch/ia64/kernel/module.c.  The
+ * masks were generated by this quick and dirty program:
+ */
+
+#if 0  /* mask program */
+#include <stdio.h>
+
+#define u64 unsigned long
+
+/* routines copied from arch/ia64/kernel/patch.c */
+
+static void
+ia64_patch (u64 insn_addr, u64 mask, u64 val)
+{
+       u64 m0, m1, v0, v1, b0, b1, *b = (u64 *) (insn_addr & -16);
+#      define insn_mask ((1UL << 41) - 1)
+       unsigned long shift;
+
+       b0 = b[0]; b1 = b[1];
+       shift = 5 + 41 * (insn_addr % 16); /* 5 bits of template, then 3 x 41-bit instructions */
+       if (shift >= 64) {
+               m1 = mask << (shift - 64);
+               v1 = val << (shift - 64);
+       } else {
+               m0 = mask << shift; m1 = mask >> (64 - shift);
+               v0 = val  << shift; v1 = val >> (64 - shift);
+               b[0] = (b0 & ~m0) | (v0 & m0);
+       }
+       b[1] = (b1 & ~m1) | (v1 & m1);
+}
+
+static void
+ia64_patch_imm64 (u64 insn_addr, u64 val)
+{
+       /* The assembler may generate offset pointing to either slot 1
+          or slot 2 for a long (2-slot) instruction, occupying slots 1
+          and 2.  */
+       insn_addr &= -16UL;
+       ia64_patch(insn_addr + 2,
+                  0x01fffefe000UL, (  ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
+                                    | ((val & 0x0000000000200000UL) <<  0) /* bit 21 -> 21 */
+                                    | ((val & 0x00000000001f0000UL) <<  6) /* bit 16 -> 22 */
+                                    | ((val & 0x000000000000ff80UL) << 20) /* bit  7 -> 27 */
+                                    | ((val & 0x000000000000007fUL) << 13) /* bit  0 -> 13 */));
+       ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
+}
+
+static void
+ia64_patch_imm60 (u64 insn_addr, u64 val)
+{
+       /* The assembler may generate offset pointing to either slot 1
+          or slot 2 for a long (2-slot) instruction, occupying slots 1
+          and 2.  */
+       insn_addr &= -16UL;
+       ia64_patch(insn_addr + 2,
+                  0x011ffffe000UL, (  ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
+                                    | ((val & 0x00000000000fffffUL) << 13) /* bit  0 -> 13 */));
+       ia64_patch(insn_addr + 1, 0x1fffffffffcUL, val >> 18);
+}
+
+struct plt_entry {
+       unsigned char bundle[3][16];
+};
+static struct plt_entry ia64_plt_mask;
+
+int main(void)
+{
+       int i, j;
+       printf("2 bundle\n");
+       for (i = 0; i < 2; ++i)
+               for (j = 0; j < 16; ++j)
+                       ia64_plt_mask.bundle[i][j] = 0xff;
+       ia64_patch_imm64((u64) (ia64_plt_mask.bundle + 0), 0);
+       ia64_patch_imm60((u64) (ia64_plt_mask.bundle + 1), 0);
+       for (i = 0; i < 2; ++i) {
+               for (j = 0; j < 16; ++j) {
+                       printf("0x%02x", ia64_plt_mask.bundle[i][j]);
+                       if (j != 15)
+                               printf(", ");
+                       if (j % 6 == 5 || j == 15)
+                               printf("\n");
+               }
+       }
+       printf("\n3 bundle\n");
+       for (i = 0; i < 3; ++i)
+               for (j = 0; j < 16; ++j)
+                       ia64_plt_mask.bundle[i][j] = 0xff;
+       ia64_patch_imm64((u64) (ia64_plt_mask.bundle + 0), 0);
+       ia64_patch_imm64((u64) (ia64_plt_mask.bundle + 1), 0);
+       for (i = 0; i < 3; ++i) {
+               for (j = 0; j < 16; ++j) {
+                       printf("0x%02x", ia64_plt_mask.bundle[i][j]);
+                       if (j != 15)
+                               printf(", ");
+                       if (j % 6 == 5 || j == 15)
+                               printf("\n");
+               }
+       }
+       return 0;
+}
+#endif /* mask program */
+
+#ifdef CONFIG_IA64_BRL_EMU
+#define PLT_BUNDLES 3
+struct plt_entry {
+       unsigned char bundle[PLT_BUNDLES][16];
+};
+static const struct plt_entry ia64_plt_template = {
+       {
+               {
+                       0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*       movl r16=TARGET_IP */
+                       0x02, 0x00, 0x00, 0x60
+               },
+               {
+                       0x04, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x20, /*       movl gp=TARGET_GP */
+                       0x00, 0x00, 0x00, 0x60
+               },
+               {
+                       0x11, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MIB] nop.m 0 */
+                       0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /*       mov b6=r16 */
+                       0x60, 0x00, 0x80, 0x00              /*       br.few b6 */
+               }
+       }
+};
+static const struct plt_entry ia64_plt_mask = {
+       {
+               {
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, /* [MLX] nop.m 0 */
+                       0x00, 0x00, 0x00, 0x00, 0x80, 0xff, /*       movl r16=TARGET_IP */
+                       0x0f, 0x08, 0x00, 0xf0
+               },
+               {
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, /* [MLX] nop.m 0 */
+                       0x00, 0x00, 0x00, 0x00, 0x80, 0xff, /*       movl gp=TARGET_GP */
+                       0x0f, 0x08, 0x00, 0xf0
+               },
+               {
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* [MIB] nop.m 0 */
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*       mov b6=r16 */
+                       0xff, 0xff, 0xff, 0xff              /*       br.few b6 */
+               }
+};
+
+#else /* !CONFIG_IA64_BRL_EMU */
+
+#define PLT_BUNDLES 2
+struct plt_entry {
+       unsigned char bundle[PLT_BUNDLES][16];
+};
+static const struct plt_entry ia64_plt_template = {
+       {
+               {
+                       0x04, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x20, /*       movl gp=TARGET_GP */
+                       0x00, 0x00, 0x00, 0x60
+               },
+               {
+                       0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*       brl.many TARGET_IP */
+                       0x08, 0x00, 0x00, 0xc0
+               }
+       }
+};
+static const struct plt_entry ia64_plt_mask = {
+       {
+               {
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, /* [MLX] nop.m 0 */
+                       0x00, 0x00, 0x00, 0x00, 0x80, 0xff, /*       movl gp=TARGET_GP */
+                       0x0f, 0x08, 0x00, 0xf0
+               },
+               {
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* [MLX] nop.m 0 */
+                       0x00, 0x00, 0x00, 0x00, 0x80, 0xff, /*       brl.many TARGET_IP */
+                       0x0f, 0x00, 0x00, 0xf7
+               }
+       }
+};
+#endif /* CONFIG_IA64_BRL_EMU */
+
+static inline u64
+get_slot(u64 bundle, int slot)
+{
+       switch (slot) {
+       case 0:
+               return (((u64 *)bundle)[0] >> 5) & 0x1ffffffffffLL;
+       case 1:
+               return ((((u64 *)bundle)[0] >> 46) & 0x3ffff) |
+                      ((((u64 *)bundle)[1] & 0x7fffff) << 18);
+       default:
+               return (((u64 *)bundle)[1] >> 23) & 0x1ffffffffffLL;
+       }
+}
+
+static inline u64
+get_movl (u64 addr)
+{
+       /* X2 format */
+       u64 slot1 = get_slot(addr, 1), slot2 = get_slot(addr, 2);
+       u64 i, imm9d, imm5c, ic, imm7b, imm41;
+       i = (slot2 >> 36) & 0x1UL;
+       imm9d = (slot2 >> 27) & 0xfffUL;
+       imm5c = (slot2 >> 22) & 0x1fUL;
+       ic = (slot2 >> 21) & 0x1UL;
+       imm7b = (slot2 >> 13) & 0x7fUL;
+       imm41 = slot1;
+       return (i << 63) | (imm41 << 22) | (ic << 21) | (imm5c << 16) |
+              (imm9d << 7) | imm7b;
+}
+
+static inline u64
+get_brl (u64 addr)
+{
+       /* X3 format */
+       u64 slot1 = get_slot(addr, 1), slot2 = get_slot(addr, 2);
+       u64 i, imm20b, imm39;
+       i = (slot2 >> 36) & 0x1UL;
+       imm20b = (slot2 >> 13) & 0xfffffUL;
+       imm39 = slot1 >> 2;
+       return ((i << 59) | (imm39 << 20) | imm20b) << 4;
+}
+
+static bfd_vma
+is_plt(bfd_vma addr) {
+       int i, j;
+       u64 target;
+       struct plt_entry plt;
+       if (kdb_getarea_size(&plt, addr, sizeof(plt)))
+               return 0;
+       for (i = 0; i < PLT_BUNDLES; ++i) {
+               for (j = 0; j < 16; ++j) {
+                       if ((plt.bundle[i][j] & ia64_plt_mask.bundle[i][j]) !=
+                           ia64_plt_template.bundle[i][j])
+                               return 0;
+               }
+       }
+       if (PLT_BUNDLES == 2) {
+               /* brl is IP relative, in second bundle */
+               target = get_brl(addr + 16) + addr + 16;
+       } else {
+               /* movl is absolute, in first bundle */
+               target = get_movl(addr);
+       }
+       return target;
+}
+
+/*
+ * 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.  If the address may be a PLT entry then try to decode
+ *     the PLT information.
+ */
+
+static void
+kdba_dis_printaddr(bfd_vma addr, disassemble_info *dip)
+{
+       bfd_vma target;
+       kdba_printaddress(addr, dip, 0);
+       if (!addr_maybe_plt)
+               return;
+       if (!(target = is_plt(addr)))
+               return;
+       kdb_printf(" PLT --> ");
+       kdba_printaddress(target, 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
+ * 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:
+ *     No mode supported yet.
+ */
+
+int
+kdba_id_parsemode(const char *mode, disassemble_info *dip)
+{
+       if (mode && strcmp(mode, "ia64"))
+               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)
+{
+       (*pc) &= ~0xf;  /* pc must be 16 byte aligned */
+}
+
+/*
+ * kdba_id_printinsn
+ *
+ *     Format and print a single bundle at 'pc'. Return the
+ *     length of the bundle.
+ *
+ * Parameters:
+ *     pc      Program Counter Value.
+ *     dip     Disassemble_info structure pointer
+ * Returns:
+ *     Length of instruction, -1 for error.
+ * Locking:
+ *     None.
+ * Remarks:
+ *     None.
+ */
+
+int
+kdba_id_printinsn(kdb_machreg_t pc, disassemble_info *dip)
+{
+       int ret;
+       int byte = 0;
+
+       kdba_check_pc(&pc);
+       while (byte < 16) {
+               kdba_dis_printaddr(pc+byte, dip);
+               addr_maybe_plt = 1;
+               ret = print_insn_ia64((kdb_machreg_t)(pc+byte), dip);
+               addr_maybe_plt = 0;
+               dip->fprintf_func(dip->stream, "\n");
+               if (ret < 0)
+                       break;
+               byte += ret;
+       }
+       return(byte);
+}
+
+/*
+ * 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
+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_ia64;
+       dip->endian                 = BFD_ENDIAN_LITTLE;
+
+       dip->display_endian         = BFD_ENDIAN_LITTLE;
+}
diff --git a/arch/ia64/kdb/kdba_io.c b/arch/ia64/kdb/kdba_io.c
new file mode 100644 (file)
index 0000000..561bc05
--- /dev/null
@@ -0,0 +1,661 @@
+/*
+ * Kernel Debugger Architecture Dependent Console I/O handler
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2006 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <linux/delay.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>
+
+#if defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_SGI_L1_CONSOLE)
+#define HAVE_KDBA_SERIAL_CONSOLE
+#endif
+
+/* from include/linux/pc_keyb.h on 2.4 */
+#define KBD_STATUS_REG         0x64    /* Status register (R) */
+#define KBD_DATA_REG           0x60    /* Keyboard data register (R/W) */
+#define KBD_CMD_SET_LEDS       0xED    /* Set keyboard leds */
+#define KBD_STAT_OBF           0x01    /* Keyboard output buffer full */
+#define KBD_STAT_IBF           0x02    /* Keyboard input buffer full */
+#define KBD_STAT_MOUSE_OBF     0x20    /* Mouse output buffer full */
+
+#ifdef CONFIG_VT_CONSOLE
+#define KDB_BLINK_LED 1
+#else
+#undef KDB_BLINK_LED
+#endif
+
+#ifdef CONFIG_KDB_USB
+
+/* support up to 8 USB keyboards (probably excessive, but...) */
+#define KDB_USB_NUM_KEYBOARDS  8
+struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS];
+
+extern int kdb_no_usb;
+
+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
+};
+
+/*
+ * kdb_usb_keyboard_attach()
+ * Attach a USB keyboard to kdb.
+ */
+int
+kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func)
+{
+       int     i;
+       int     rc = -1;
+
+       if (kdb_no_usb)
+               return 0;
+
+       /*
+        * Search through the array of KDB USB keyboards (kdb_usb_kbds)
+        * looking for a free index. If found, assign the keyboard to
+        * the array index.
+        */
+
+       for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) {
+               if (kdb_usb_kbds[i].urb) /* index is already assigned */
+                       continue;
+
+               /* found a free array index */
+               kdb_usb_kbds[i].urb = urb;
+               kdb_usb_kbds[i].buffer = buffer;
+               kdb_usb_kbds[i].poll_func = poll_func;
+
+               rc = 0; /* success */
+
+               break;
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach);
+
+/*
+ * kdb_usb_keyboard_detach()
+ * Detach a USB keyboard from kdb.
+ */
+int
+kdb_usb_keyboard_detach(struct urb *urb)
+{
+       int     i;
+       int     rc = -1;
+
+       if (kdb_no_usb)
+               return 0;
+
+       /*
+        * Search through the array of KDB USB keyboards (kdb_usb_kbds)
+        * looking for the index with the matching URB. If found,
+        * clear the array index.
+        */
+
+       for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) {
+               if (kdb_usb_kbds[i].urb != urb)
+                       continue;
+
+               /* found it, clear the index */
+               kdb_usb_kbds[i].urb = NULL;
+               kdb_usb_kbds[i].buffer = NULL;
+               kdb_usb_kbds[i].poll_func = NULL;
+               kdb_usb_kbds[i].caps_lock = 0;
+
+               rc = 0; /* success */
+
+               break;
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach);
+
+/*
+ * get_usb_char
+ * This function drives the USB attached keyboards.
+ * Fetch the USB scancode and decode it.
+ */
+static int
+get_usb_char(void)
+{
+       int     i;
+       int     ret;
+       unsigned char keycode, spec;
+       extern u_short plain_map[], shift_map[], ctrl_map[];
+
+       if (kdb_no_usb)
+               return -1;
+
+       /*
+        * Loop through all the USB keyboard(s) and return
+        * the first character obtained from them.
+        */
+
+       for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) {
+               /* skip uninitialized keyboard array entries */
+               if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer ||
+                   !kdb_usb_kbds[i].poll_func)
+                       continue;
+
+               /* Transfer char */
+               ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb);
+
+               if (ret == -EBUSY && kdb_usb_kbds[i].poll_ret != -EBUSY)
+                       kdb_printf("NOTICE: USB HC driver BUSY. "
+                           "USB keyboard has been disabled.\n");
+
+               kdb_usb_kbds[i].poll_ret = ret;
+
+               if (ret < 0) /* error or no characters, try the next kbd */
+                       continue;
+
+               spec = kdb_usb_kbds[i].buffer[0];
+               keycode = kdb_usb_kbds[i].buffer[2];
+               kdb_usb_kbds[i].buffer[0] = (char)0;
+               kdb_usb_kbds[i].buffer[2] = (char)0;
+
+               if(kdb_usb_kbds[i].buffer[3]) {
+                       kdb_usb_kbds[i].buffer[3] = (char)0;
+                       continue;
+               }
+
+               /* 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 */
+                               kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock);
+                               break;
+                       case 0x0E: /* Backspace */
+                               return 8;
+                       case 0x0F: /* TAB */
+                               return 9;
+                       case 0x77: /* Pause */
+                               break ;
+                       default:
+                               if(!kdb_usb_kbds[i].caps_lock) {
+                                       return plain_map[keycode];
+                               }
+                               else {
+                                       return shift_map[keycode];
+                               }
+                       }
+               }
+       }
+
+       /* no chars were returned from any of the USB keyboards */
+
+       return -1;
+}
+#endif /* CONFIG_KDB_USB */
+
+/*
+ * 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)
+{
+       int timeout;
+       for (timeout = 200 * 1000; timeout && (inb(KBD_STATUS_REG) & KBD_STAT_IBF); timeout--);
+       outb(byte, KBD_DATA_REG);
+       udelay(40);
+       for (timeout = 200 * 1000; timeout && (~inb(KBD_STATUS_REG) & KBD_STAT_OBF); timeout--);
+       inb(KBD_DATA_REG);
+       udelay(40);
+}
+
+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 */
+
+#ifdef HAVE_KDBA_SERIAL_CONSOLE
+
+struct kdb_serial kdb_serial;
+enum kdba_serial_console kdba_serial_console;
+static int get_serial_char(void);
+
+/* There must be a serial_inp_xxx() and get_serial_char_xxx() for each type
+ * of console.  See enum kdba_serial_console in include/asm-$(ARCH)/kdbprivate.h.
+ */
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+
+static unsigned int
+serial_inp_standard(const struct kdb_serial *kdb_serial, int offset)
+{
+       offset <<= kdb_serial->ioreg_shift;
+
+       switch (kdb_serial->io_type) {
+       case SERIAL_IO_MEM:
+               return readb((void __iomem *)(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_standard(void)
+{
+       unsigned char ch;
+       static unsigned long fifon;
+       if (fifon == 0) {
+               /* try to set the FIFO */
+               fifon = kdb_serial.iobase +
+                       (UART_FCR << kdb_serial.ioreg_shift);
+               switch (kdb_serial.io_type) {
+               case SERIAL_IO_MEM:
+                       writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
+                               UART_FCR_CLEAR_XMIT), (void __iomem *)fifon);
+                       break;
+               default:
+                       outb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
+                               UART_FCR_CLEAR_XMIT), fifon);
+                       break;
+               }
+       }
+
+       if (kdb_serial.iobase == 0)
+               return -1;
+
+       if (serial_inp_standard(&kdb_serial, UART_LSR) & UART_LSR_DR) {
+               ch = serial_inp_standard(&kdb_serial, UART_RX);
+               if (ch == 0x7f)
+                       ch = 8;
+               return ch;
+       }
+       return -1;
+}
+
+#else  /* !CONFIG_SERIAL_8250_CONSOLE */
+
+#define get_serial_char_standard() -1
+
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
+
+#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
+
+extern u64 master_node_bedrock_address;
+
+/* UART registers on the Bedrock start at 0x80 */
+
+extern int l1_serial_in_polled(void);
+extern int l1_control_in_polled(int);
+
+/* Read a byte from the L1 port.  kdb_serial is ignored */
+static unsigned int
+serial_inp_sgi_l1(const struct kdb_serial *kdb_serial, int offset)
+{
+       if (offset & 0x80) {
+               int counter = 10000;
+               unsigned int value;
+               while ( counter-- ) {
+                       value = l1_serial_in_polled();
+                       /* Gobble up the 0's */
+                       if ( value )
+                               return(value);
+               }
+               return(0);
+       }
+       else {
+               return l1_control_in_polled(offset);
+       }
+}
+
+/* Check if there is a byte ready at the L1 port. */
+static int
+get_serial_char_sgi_l1(void)
+{
+       unsigned char ch;
+       int status;
+
+       if ((status = serial_inp_sgi_l1(&kdb_serial, UART_LSR)) & UART_LSR_DR) {
+               ch = serial_inp_sgi_l1(&kdb_serial, UART_RX | 0x80);    /* bedrock offset */
+               if (ch == 0x7f)
+                       ch = 8;
+               return ch;
+       }
+       return -1;
+}
+
+#else  /* !CONFIG_SERIAL_SGI_L1_CONSOLE */
+
+#define get_serial_char_sgi_l1() -1
+
+#endif /* CONFIG_SERIAL_SGI_L1_CONSOLE */
+
+/* Select the serial console input at run time, to handle generic kernels */
+
+static int
+get_serial_char(void)
+{
+       switch (kdba_serial_console) {
+       case KDBA_SC_NONE:
+               return -1;
+       case KDBA_SC_STANDARD:
+               return get_serial_char_standard();
+       case KDBA_SC_SGI_L1:
+               return get_serial_char_sgi_l1();
+       }
+       /* gcc is not smart enough to realize that all paths return before here :( */
+       return -1;
+}
+
+#endif /* HAVE_KDBA_SERIAL_CONSOLE */
+
+#ifdef CONFIG_VT_CONSOLE
+
+static int kbd_exists;
+
+/*
+ * 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 (KDB_FLAG(NO_I8042) || KDB_FLAG(NO_VT_CONSOLE) ||
+           (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;
+       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.
+ */
+static int kdba_blink_mask = 0x1 | 0x4;
+
+#ifdef CONFIG_SMP
+#define BOGOMIPS (local_cpu_data->loops_per_jiffy/(500000/HZ))
+#else
+#define BOGOMIPS (loops_per_jiffy/(500000/HZ))
+#endif
+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
+#ifdef HAVE_KDBA_SERIAL_CONSOLE
+       get_serial_char,
+#endif
+#ifdef KDB_BLINK_LED
+       blink_led,
+#endif
+#ifdef CONFIG_KDB_USB
+       get_usb_char,
+#endif
+       NULL
+};
+
+/* Dummy versions of kdba_local_arch_setup, kdba_local_arch_cleanup.
+ * FIXME: ia64 with legacy keyboard might need the same code as i386.
+ */
+
+void kdba_local_arch_setup(void) {}
+void kdba_local_arch_cleanup(void) {}
diff --git a/arch/ia64/kdb/kdba_jmp.S b/arch/ia64/kdb/kdba_jmp.S
new file mode 100644 (file)
index 0000000..f3552d4
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Kernel Debugger Architecture Dependent Longjump Support.
+ */
+
+/* setjmp() and longjmp() assembler support for kdb on ia64.
+
+   This code was copied from glibc CVS as of 2001-06-27 and modified where
+   necessary to fit the kernel.  No glibc lines were changed or deleted, all
+   adjustments are wrapped in #ifdef __KERNEL__, except for the added
+   .mem.offset lines, they work in or out of the kenrel.  The original code is
+   in sysdeps/unix/sysv/linux/ia64/{setjmp.S,__longjmp.S}.
+
+   glibc has setjmp (save signals) and _setjmp (do not save signals).  Kernel
+   code does not have signals, only kdba_setjmp_asm() is used.
+
+   Keith Owens <kaos@melbourne.sgi.com> 2001-06-27
+ */
+
+/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   The layout of the jmp_buf is as follows.  This is subject to change
+   and user-code should never depend on the particular layout of
+   jmp_buf!
+
+
+       offset: description:
+       ------- ------------
+       0x000   stack pointer (r12)     ; unchangeable (see _JMPBUF_UNWINDS)
+       0x008   r1 (gp)
+       0x010   caller's unat
+       0x018   fpsr
+       0x020   r4
+       0x028   r5
+       0x030   r6
+       0x038   r7
+       0x040   rp (b0)
+       0x048   b1
+       0x050   b2
+       0x058   b3
+       0x060   b4
+       0x068   b5
+       0x070   ar.pfs
+       0x078   ar.lc
+       0x080   pr
+       0x088   ar.bsp                  ; unchangeable (see __longjmp.S)
+       0x090   ar.unat
+       0x098   &__jmp_buf      ; address of the jmpbuf (needed to locate NaT bits in unat)
+       0x0a0    f2
+       0x0b0    f3
+       0x0c0    f4
+       0x0d0    f5
+       0x0e0   f16
+       0x0f0   f17
+       0x100   f18
+       0x110   f19
+       0x120   f20
+       0x130   f21
+       0x130   f22
+       0x140   f23
+       0x150   f24
+       0x160   f25
+       0x170   f26
+       0x180   f27
+       0x190   f28
+       0x1a0   f29
+       0x1b0   f30
+       0x1c0   f31 */
+
+#ifndef __KERNEL__
+
+#include <sysdep.h>
+#include <features.h>
+
+       /* The following two entry points are the traditional entry points: */
+
+LEAF(setjmp)
+       alloc r8=ar.pfs,2,0,0,0
+       mov in1=1
+       br.cond.sptk.many __sigsetjmp
+END(setjmp)
+
+LEAF(_setjmp)
+       alloc r8=ar.pfs,2,0,0,0
+       mov in1=0
+       br.cond.sptk.many __sigsetjmp
+END(_setjmp)
+
+       /* __sigsetjmp(__jmp_buf buf, int savemask) */
+
+ENTRY(__sigsetjmp)
+
+#else  /* __KERNEL __ */
+#include <asm/asmmacro.h>
+#define ret br.ret.sptk.few rp
+GLOBAL_ENTRY(kdba_setjmp)
+#endif /* !__KERNEL__ */
+
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+       alloc loc1=ar.pfs,2,2,2,0
+       mov r16=ar.unat
+       ;;
+       mov r17=ar.fpsr
+       mov r2=in0
+       add r3=8,in0
+       ;;
+.mem.offset 0,0;
+       st8.spill.nta [r2]=sp,16        // r12 (sp)
+.mem.offset 8,0;
+       st8.spill.nta [r3]=gp,16        // r1 (gp)
+       ;;
+       st8.nta [r2]=r16,16             // save caller's unat
+       st8.nta [r3]=r17,16             // save fpsr
+       add r8=0xa0,in0
+       ;;
+.mem.offset 160,0;
+       st8.spill.nta [r2]=r4,16        // r4
+.mem.offset 168,0;
+       st8.spill.nta [r3]=r5,16        // r5
+       add r9=0xb0,in0
+       ;;
+       stf.spill.nta [r8]=f2,32
+       stf.spill.nta [r9]=f3,32
+       mov loc0=rp
+       .body
+       ;;
+       stf.spill.nta [r8]=f4,32
+       stf.spill.nta [r9]=f5,32
+       mov r17=b1
+       ;;
+       stf.spill.nta [r8]=f16,32
+       stf.spill.nta [r9]=f17,32
+       mov r18=b2
+       ;;
+       stf.spill.nta [r8]=f18,32
+       stf.spill.nta [r9]=f19,32
+       mov r19=b3
+       ;;
+       stf.spill.nta [r8]=f20,32
+       stf.spill.nta [r9]=f21,32
+       mov r20=b4
+       ;;
+       stf.spill.nta [r8]=f22,32
+       stf.spill.nta [r9]=f23,32
+       mov r21=b5
+       ;;
+       stf.spill.nta [r8]=f24,32
+       stf.spill.nta [r9]=f25,32
+       mov r22=ar.lc
+       ;;
+       stf.spill.nta [r8]=f26,32
+       stf.spill.nta [r9]=f27,32
+       mov r24=pr
+       ;;
+       stf.spill.nta [r8]=f28,32
+       stf.spill.nta [r9]=f29,32
+       ;;
+       stf.spill.nta [r8]=f30
+       stf.spill.nta [r9]=f31
+
+.mem.offset 0,0;
+       st8.spill.nta [r2]=r6,16        // r6
+.mem.offset 8,0;
+       st8.spill.nta [r3]=r7,16        // r7
+       ;;
+       mov r23=ar.bsp
+       mov r25=ar.unat
+#ifndef __KERNEL__
+       mov out0=in0
+#endif /* !__KERNEL__ */
+
+       st8.nta [r2]=loc0,16            // b0
+       st8.nta [r3]=r17,16             // b1
+#ifndef __KERNEL__
+       mov out1=in1
+#endif /* !__KERNEL__ */
+       ;;
+       st8.nta [r2]=r18,16             // b2
+       st8.nta [r3]=r19,16             // b3
+       ;;
+       st8.nta [r2]=r20,16             // b4
+       st8.nta [r3]=r21,16             // b5
+       ;;
+       st8.nta [r2]=loc1,16            // ar.pfs
+       st8.nta [r3]=r22,16             // ar.lc
+       ;;
+       st8.nta [r2]=r24,16             // pr
+       st8.nta [r3]=r23,16             // ar.bsp
+       ;;
+       st8.nta [r2]=r25                // ar.unat
+       st8.nta [r3]=in0                // &__jmp_buf
+#ifndef __KERNEL__
+       br.call.dpnt.few rp=__sigjmp_save
+.ret0:                                 // force a new bundle ::q
+#endif /* !_KERNEL__ */
+       mov r8=0
+       mov rp=loc0
+       mov ar.pfs=loc1
+       ret
+#ifndef __KERNEL__
+END(__sigsetjmp)
+
+weak_extern(_setjmp)
+weak_extern(setjmp)
+
+#else  /* __KERNEL__ */
+END(kdba_setjmp)
+#endif /* !_KERNEL__ */
+
+/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Note that __sigsetjmp() did NOT flush the register stack.  Instead,
+   we do it here since __longjmp() is usually much less frequently
+   invoked than __sigsetjmp(). The only difficulty is that __sigsetjmp()
+   didn't (and wouldn't be able to) save ar.rnat either.  This is a problem
+   because if we're not careful, we could end up loading random NaT bits.
+   There are two cases:
+
+       (i)  ar.bsp < ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+               ar.rnat contains the desired bits---preserve ar.rnat
+               across loadrs and write to ar.bspstore
+
+       (ii) ar.bsp >= ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+               The desired ar.rnat is stored in
+               ia64_rse_rnat_addr(jmpbuf.ar_bsp).  Load those
+               bits into ar.rnat after setting ar.bspstore. */
+
+#ifndef __KERNEL__
+#include <sysdep.h>
+#include <features.h>
+#endif /* !__KERNEL__ */
+
+#      define  pPos    p6      /* is rotate count positive? */
+#      define  pNeg    p7      /* is rotate count negative? */
+
+
+       /* __longjmp(__jmp_buf buf, int val) */
+
+#ifndef __KERNEL__
+LEAF(__longjmp)
+#else  /* __KERNEL__ */
+GLOBAL_ENTRY(kdba_longjmp)
+#endif /* !__KERNEL__ */
+       alloc r8=ar.pfs,2,1,0,0
+       mov r27=ar.rsc
+       add r2=0x98,in0         // r2 <- &jmpbuf.orig_jmp_buf_addr
+       ;;
+       ld8 r8=[r2],-16         // r8 <- orig_jmp_buf_addr
+       mov r10=ar.bsp
+       and r11=~0x3,r27        // clear ar.rsc.mode
+       ;;
+       flushrs                 // flush dirty regs to backing store (must be first in insn grp)
+       ld8 r23=[r2],8          // r23 <- jmpbuf.ar_bsp
+       sub r8=r8,in0           // r8 <- &orig_jmpbuf - &jmpbuf
+       ;;
+       ld8 r25=[r2]            // r25 <- jmpbuf.ar_unat
+       extr.u r8=r8,3,6        // r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f
+       ;;
+       cmp.lt pNeg,pPos=r8,r0
+       mov r2=in0
+       ;;
+(pPos) mov r16=r8
+(pNeg) add r16=64,r8
+(pPos) sub r17=64,r8
+(pNeg) sub r17=r0,r8
+       ;;
+       mov ar.rsc=r11          // put RSE in enforced lazy mode
+       shr.u r8=r25,r16
+       add r3=8,in0            // r3 <- &jmpbuf.r1
+       shl r9=r25,r17
+       ;;
+       or r25=r8,r9
+       ;;
+       mov r26=ar.rnat
+       mov ar.unat=r25         // setup ar.unat (NaT bits for r1, r4-r7, and r12)
+       ;;
+       ld8.fill.nta sp=[r2],16 // r12 (sp)
+       ld8.fill.nta gp=[r3],16         // r1 (gp)
+       dep r11=-1,r23,3,6      // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+       ;;
+       ld8.nta r16=[r2],16             // caller's unat
+       ld8.nta r17=[r3],16             // fpsr
+       ;;
+       ld8.fill.nta r4=[r2],16 // r4
+       ld8.fill.nta r5=[r3],16         // r5 (gp)
+       cmp.geu p8,p0=r10,r11   // p8 <- (ar.bsp >= jmpbuf.ar_bsp)
+       ;;
+       ld8.fill.nta r6=[r2],16 // r6
+       ld8.fill.nta r7=[r3],16         // r7
+       ;;
+       mov ar.unat=r16                 // restore caller's unat
+       mov ar.fpsr=r17                 // restore fpsr
+       ;;
+       ld8.nta r16=[r2],16             // b0
+       ld8.nta r17=[r3],16             // b1
+       ;;
+(p8)   ld8 r26=[r11]           // r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+       mov ar.bspstore=r23     // restore ar.bspstore
+       ;;
+       ld8.nta r18=[r2],16             // b2
+       ld8.nta r19=[r3],16             // b3
+       ;;
+       ld8.nta r20=[r2],16             // b4
+       ld8.nta r21=[r3],16             // b5
+       ;;
+       ld8.nta r11=[r2],16             // ar.pfs
+       ld8.nta r22=[r3],56             // ar.lc
+       ;;
+       ld8.nta r24=[r2],32             // pr
+       mov b0=r16
+       ;;
+       ldf.fill.nta f2=[r2],32
+       ldf.fill.nta f3=[r3],32
+       mov b1=r17
+       ;;
+       ldf.fill.nta f4=[r2],32
+       ldf.fill.nta f5=[r3],32
+       mov b2=r18
+       ;;
+       ldf.fill.nta f16=[r2],32
+       ldf.fill.nta f17=[r3],32
+       mov b3=r19
+       ;;
+       ldf.fill.nta f18=[r2],32
+       ldf.fill.nta f19=[r3],32
+       mov b4=r20
+       ;;
+       ldf.fill.nta f20=[r2],32
+       ldf.fill.nta f21=[r3],32
+       mov b5=r21
+       ;;
+       ldf.fill.nta f22=[r2],32
+       ldf.fill.nta f23=[r3],32
+       mov ar.lc=r22
+       ;;
+       ldf.fill.nta f24=[r2],32
+       ldf.fill.nta f25=[r3],32
+       cmp.eq p8,p9=0,in1
+       ;;
+       ldf.fill.nta f26=[r2],32
+       ldf.fill.nta f27=[r3],32
+       mov ar.pfs=r11
+       ;;
+       ldf.fill.nta f28=[r2],32
+       ldf.fill.nta f29=[r3],32
+       ;;
+       ldf.fill.nta f30=[r2]
+       ldf.fill.nta f31=[r3]
+(p8)   mov r8=1
+
+       mov ar.rnat=r26         // restore ar.rnat
+       ;;
+       mov ar.rsc=r27          // restore ar.rsc
+(p9)   mov r8=in1
+
+       invala                  // virt. -> phys. regnum mapping may change
+       mov pr=r24,-1
+       ret
+#ifndef __KERNEL__
+END(__longjmp)
+#else  /* __KERNEL__ */
+END(kdba_longjmp)
+#endif /* !_KERNEL__ */
diff --git a/arch/ia64/kdb/kdba_pod.c b/arch/ia64/kdb/kdba_pod.c
new file mode 100644 (file)
index 0000000..f1bca7a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Kernel Debugger Architecture Dependent POD functions.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2006 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/module.h>
+#include <asm/sal.h>
+#include <asm/sn/sn_sal.h>
+
+MODULE_AUTHOR("Jesse Barnes");
+MODULE_DESCRIPTION("Enter POD through KDB");
+MODULE_LICENSE("GPL");
+
+/**
+ * kdba_pod - enter POD mode from kdb
+ * @argc: arg count
+ * @argv: arg values
+ *
+ * Enter POD mode from kdb using SGI SN specific SAL function call.
+ */
+static int
+kdba_pod(int argc, const char **argv)
+{
+       kdb_printf("WARNING: pod commands are dangerous unless you know exactly\n"
+                  "what you are doing.  If in doubt, type exit immediately.\n");
+       return ia64_sn_pod_mode();
+}
+
+/**
+ * kdba_pod_init - register 'pod' command with kdb
+ *
+ * Register the 'pod' command with kdb at load time.
+ */
+static int __init
+kdba_pod_init(void)
+{
+       if (ia64_platform_is("sn2"))
+               kdb_register("pod", kdba_pod, NULL, "Enter POD", 0);
+
+       return 0;
+}
+
+/**
+ * kdba_pod_exit - unregister the 'pod' command
+ *
+ * Tell kdb that the 'pod' command is no longer available.
+ */
+static void __exit
+kdba_pod_exit(void)
+{
+       if (ia64_platform_is("sn2"))
+               kdb_unregister("pod");
+}
+
+module_init(kdba_pod_init)
+module_exit(kdba_pod_exit)
diff --git a/arch/ia64/kdb/kdba_support.c b/arch/ia64/kdb/kdba_support.c
new file mode 100644 (file)
index 0000000..0a7e86e
--- /dev/null
@@ -0,0 +1,1726 @@
+/*
+ * Kernel Debugger Architecture Independent Support Functions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2006 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/string.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/module.h>
+#ifdef CONFIG_KDB_KDUMP
+#include <linux/kexec.h>
+#endif
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/rse.h>
+#include <asm/delay.h>
+#ifdef CONFIG_SMP
+#include <asm/hw_irq.h>
+#endif
+#include <asm/mca.h>
+
+struct kdb_running_process *kdb_running_process_save; /* [NR_CPUS] */
+static int kdba_show_handlers = 0;
+
+static int
+kdba_itm (int argc, const char **argv)
+{
+       int diag;
+       unsigned long val;
+
+       diag = kdbgetularg(argv[1], &val);
+       if (diag)
+               return diag;
+       kdb_printf("new itm=" kdb_machreg_fmt "\n", val);
+
+       ia64_set_itm(val);
+       return 0;
+}
+
+static void
+kdba_show_intregs(void)
+{
+       u64 lid, tpr, lrr0, lrr1, itv, pmv, cmcv;
+
+       asm ("mov %0=cr.lid" : "=r"(lid));
+       asm ("mov %0=cr.tpr" : "=r"(tpr));
+       asm ("mov %0=cr.lrr0" : "=r"(lrr0));
+       asm ("mov %0=cr.lrr1" : "=r"(lrr1));
+       kdb_printf("lid=" kdb_machreg_fmt ", tpr=" kdb_machreg_fmt ", lrr0=" kdb_machreg_fmt ", llr1=" kdb_machreg_fmt "\n", lid, tpr, lrr0, lrr1);
+
+       asm ("mov %0=cr.itv" : "=r"(itv));
+       asm ("mov %0=cr.pmv" : "=r"(pmv));
+       asm ("mov %0=cr.cmcv" : "=r"(cmcv));
+       kdb_printf("itv=" kdb_machreg_fmt ", pmv=" kdb_machreg_fmt ", cmcv=" kdb_machreg_fmt "\n", itv, pmv, cmcv);
+
+       kdb_printf("irr=0x%016lx,0x%016lx,0x%016lx,0x%016lx\n",
+               ia64_getreg(_IA64_REG_CR_IRR0), ia64_getreg(_IA64_REG_CR_IRR1), ia64_getreg(_IA64_REG_CR_IRR2), ia64_getreg(_IA64_REG_CR_IRR3));
+
+       kdb_printf("itc=0x%016lx, itm=0x%016lx\n", ia64_get_itc(), ia64_get_itm());
+}
+
+static int
+kdba_sir (int argc, const char **argv)
+{
+       kdba_show_intregs();
+
+       return 0;
+}
+
+/*
+ * kdba_pt_regs
+ *
+ *     Format a struct pt_regs
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     If no address is supplied, it uses the current irq pt_regs.
+ */
+
+static int
+kdba_pt_regs(int argc, const char **argv)
+{
+       int diag;
+       kdb_machreg_t addr;
+       long offset = 0;
+       int nextarg;
+       struct pt_regs *p;
+
+       if (argc == 0) {
+               addr = (kdb_machreg_t) get_irq_regs();
+       } else if (argc == 1) {
+               nextarg = 1;
+               diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
+               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("b6", p->b6);
+       kdb_print_nameval("b7", p->b7);
+       kdb_printf("  ar_csd      0x%lx\n", p->ar_csd);
+       kdb_printf("  ar_ssd      0x%lx\n", p->ar_ssd);
+       kdb_print_nameval("r8", p->r8);
+       kdb_print_nameval("r9", p->r9);
+       kdb_print_nameval("r10", p->r10);
+       kdb_print_nameval("r11", p->r11);
+       kdb_printf("  cr_ipsr     0x%lx\n", p->cr_ipsr);
+       kdb_print_nameval("cr_iip", p->cr_iip);
+       kdb_printf("  cr_ifs      0x%lx\n", p->cr_ifs);
+       kdb_printf("  ar_unat     0x%lx\n", p->ar_unat);
+       kdb_printf("  ar_pfs      0x%lx\n", p->ar_pfs);
+       kdb_printf("  ar_rsc      0x%lx\n", p->ar_rsc);
+       kdb_printf("  ar_rnat     0x%lx\n", p->ar_rnat);
+       kdb_printf("  ar_bspstore 0x%lx\n", p->ar_bspstore);
+       kdb_printf("  pr          0x%lx\n", p->pr);
+       kdb_print_nameval("b0", p->b0);
+       kdb_printf("  loadrs      0x%lx\n", p->loadrs);
+       kdb_print_nameval("r1", p->r1);
+       kdb_print_nameval("r12", p->r12);
+       kdb_print_nameval("r13", p->r13);
+       kdb_printf("  ar_fpsr     0x%lx\n", p->ar_fpsr);
+       kdb_print_nameval("r15", p->r15);
+       kdb_print_nameval("r14", p->r14);
+       kdb_print_nameval("r2", p->r2);
+       kdb_print_nameval("r3", p->r3);
+       kdb_print_nameval("r16", p->r16);
+       kdb_print_nameval("r17", p->r17);
+       kdb_print_nameval("r18", p->r18);
+       kdb_print_nameval("r19", p->r19);
+       kdb_print_nameval("r20", p->r20);
+       kdb_print_nameval("r21", p->r21);
+       kdb_print_nameval("r22", p->r22);
+       kdb_print_nameval("r23", p->r23);
+       kdb_print_nameval("r24", p->r24);
+       kdb_print_nameval("r25", p->r25);
+       kdb_print_nameval("r26", p->r26);
+       kdb_print_nameval("r27", p->r27);
+       kdb_print_nameval("r28", p->r28);
+       kdb_print_nameval("r29", p->r29);
+       kdb_print_nameval("r30", p->r30);
+       kdb_print_nameval("r31", p->r31);
+       kdb_printf("  ar_ccv      0x%lx\n", p->ar_ccv);
+       kdb_printf("  f6          0x%lx 0x%lx\n", p->f6.u.bits[0], p->f6.u.bits[1]);
+       kdb_printf("  f7          0x%lx 0x%lx\n", p->f7.u.bits[0], p->f7.u.bits[1]);
+       kdb_printf("  f8          0x%lx 0x%lx\n", p->f8.u.bits[0], p->f8.u.bits[1]);
+       kdb_printf("  f9          0x%lx 0x%lx\n", p->f9.u.bits[0], p->f9.u.bits[1]);
+       kdb_printf("  f10         0x%lx 0x%lx\n", p->f10.u.bits[0], p->f10.u.bits[1]);
+       kdb_printf("  f11         0x%lx 0x%lx\n", p->f11.u.bits[0], p->f11.u.bits[1]);
+
+       return 0;
+}
+
+/*
+ * kdba_stackdepth
+ *
+ *     Print processes that are using more than a specific percentage of their
+ *     stack.
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     If no percentage is supplied, it uses 60.
+ */
+
+static int
+kdba_stackdepth(int argc, const char **argv)
+{
+       int diag, threshold, used;
+       unsigned long percentage;
+       unsigned long esp;
+       long offset = 0;
+       int nextarg;
+       struct task_struct *p, *g;
+       struct switch_stack *sw;
+
+       if (argc == 0) {
+               percentage = 60;
+       } else if (argc == 1) {
+               nextarg = 1;
+               diag = kdbgetaddrarg(argc, argv, &nextarg, &percentage, &offset, NULL);
+               if (diag)
+                       return diag;
+       } else {
+               return KDB_ARGCOUNT;
+       }
+       percentage = max_t(int, percentage, 1);
+       percentage = min_t(int, percentage, 100);
+       threshold = ((2 * THREAD_SIZE * percentage) / 100 + 1) >> 1;
+       kdb_printf("stackdepth: processes using more than %ld%% (%d bytes) of stack\n",
+               percentage, threshold);
+       kdb_do_each_thread(g, p) {
+               if (kdb_task_has_cpu(p)) {
+                       struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+                       if (krp->seqno)
+                               sw = krp->arch.sw;
+                       else
+                               sw = NULL;
+               } else
+                       sw = (struct switch_stack *) (p->thread.ksp + 16);
+               if (!sw)
+                       continue;
+               esp = (unsigned long) sw;
+               used = THREAD_SIZE - (esp - sw->ar_bspstore);
+               if (used >= threshold) {
+                       kdb_ps1(p);
+                       kdb_printf("  esp %lx bsp %lx used %d\n", esp, sw->ar_bspstore, used);
+               }
+       } kdb_while_each_thread(g, p);
+
+       return 0;
+}
+
+/*
+ * kdb_switch_stack
+ *
+ *     Format a struct switch_stack
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     If no address is supplied, it uses kdb_running_process[smp_processor_id()].arch.sw.
+ */
+
+static int
+kdba_switch_stack(int argc, const char **argv)
+{
+       int diag;
+       kdb_machreg_t addr;
+       long offset = 0;
+       int nextarg;
+       struct switch_stack *p;
+
+       if (argc == 0) {
+               addr = (kdb_machreg_t) kdb_running_process[smp_processor_id()].arch.sw;
+       } else if (argc == 1) {
+               nextarg = 1;
+               diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
+               if (diag)
+                       return diag;
+       } else {
+               return KDB_ARGCOUNT;
+       }
+
+       p = (struct switch_stack *) addr;
+       kdb_printf("struct switch_stack %p-%p\n", p, (unsigned char *)p + sizeof(*p) - 1);
+       kdb_printf("  caller_unat 0x%lx\n", p->caller_unat);
+       kdb_printf("  ar_fpsr     0x%lx\n", p->ar_fpsr);
+       kdb_printf("  f2          0x%lx 0x%lx\n", p->f2.u.bits[0], p->f2.u.bits[1]);
+       kdb_printf("  f3          0x%lx 0x%lx\n", p->f3.u.bits[0], p->f3.u.bits[1]);
+       kdb_printf("  f4          0x%lx 0x%lx\n", p->f4.u.bits[0], p->f4.u.bits[1]);
+       kdb_printf("  f5          0x%lx 0x%lx\n", p->f5.u.bits[0], p->f5.u.bits[1]);
+       kdb_printf("  f12         0x%lx 0x%lx\n", p->f12.u.bits[0], p->f12.u.bits[1]);
+       kdb_printf("  f13         0x%lx 0x%lx\n", p->f13.u.bits[0], p->f13.u.bits[1]);
+       kdb_printf("  f14         0x%lx 0x%lx\n", p->f14.u.bits[0], p->f14.u.bits[1]);
+       kdb_printf("  f15         0x%lx 0x%lx\n", p->f15.u.bits[0], p->f15.u.bits[1]);
+       kdb_printf("  f16         0x%lx 0x%lx\n", p->f16.u.bits[0], p->f16.u.bits[1]);
+       kdb_printf("  f17         0x%lx 0x%lx\n", p->f17.u.bits[0], p->f17.u.bits[1]);
+       kdb_printf("  f18         0x%lx 0x%lx\n", p->f18.u.bits[0], p->f18.u.bits[1]);
+       kdb_printf("  f19         0x%lx 0x%lx\n", p->f19.u.bits[0], p->f19.u.bits[1]);
+       kdb_printf("  f20         0x%lx 0x%lx\n", p->f20.u.bits[0], p->f20.u.bits[1]);
+       kdb_printf("  f21         0x%lx 0x%lx\n", p->f21.u.bits[0], p->f21.u.bits[1]);
+       kdb_printf("  f22         0x%lx 0x%lx\n", p->f22.u.bits[0], p->f22.u.bits[1]);
+       kdb_printf("  f23         0x%lx 0x%lx\n", p->f23.u.bits[0], p->f23.u.bits[1]);
+       kdb_printf("  f24         0x%lx 0x%lx\n", p->f24.u.bits[0], p->f24.u.bits[1]);
+       kdb_printf("  f25         0x%lx 0x%lx\n", p->f25.u.bits[0], p->f25.u.bits[1]);
+       kdb_printf("  f26         0x%lx 0x%lx\n", p->f26.u.bits[0], p->f26.u.bits[1]);
+       kdb_printf("  f27         0x%lx 0x%lx\n", p->f27.u.bits[0], p->f27.u.bits[1]);
+       kdb_printf("  f28         0x%lx 0x%lx\n", p->f28.u.bits[0], p->f28.u.bits[1]);
+       kdb_printf("  f29         0x%lx 0x%lx\n", p->f29.u.bits[0], p->f29.u.bits[1]);
+       kdb_printf("  f30         0x%lx 0x%lx\n", p->f30.u.bits[0], p->f30.u.bits[1]);
+       kdb_printf("  f31         0x%lx 0x%lx\n", p->f31.u.bits[0], p->f31.u.bits[1]);
+       kdb_print_nameval("r4", p->r4);
+       kdb_print_nameval("r5", p->r5);
+       kdb_print_nameval("r6", p->r6);
+       kdb_print_nameval("r7", p->r7);
+       kdb_print_nameval("b0", p->b0);
+       kdb_print_nameval("b1", p->b1);
+       kdb_print_nameval("b2", p->b2);
+       kdb_print_nameval("b3", p->b3);
+       kdb_print_nameval("b4", p->b4);
+       kdb_print_nameval("b5", p->b5);
+       kdb_printf("  ar_pfs      0x%lx\n", p->ar_pfs);
+       kdb_printf("  ar_lc       0x%lx\n", p->ar_lc);
+       kdb_printf("  ar_unat     0x%lx\n", p->ar_unat);
+       kdb_printf("  ar_rnat     0x%lx\n", p->ar_rnat);
+       kdb_printf("  ar_bspstore 0x%lx\n", p->ar_bspstore);
+       kdb_printf("  pr          0x%lx\n", p->pr);
+
+       return 0;
+}
+
+/*
+ * kdb_minstate
+ *
+ *     Format the PAL minstate area.
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     None.
+ */
+
+static int
+kdba_minstate(int argc, const char **argv)
+{
+       int diag;
+       kdb_machreg_t addr;
+       long offset = 0;
+       int nextarg;
+       pal_min_state_area_t *p;
+
+       if (argc == 1) {
+               nextarg = 1;
+               diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
+               if (diag)
+                       return diag;
+       } else {
+               return KDB_ARGCOUNT;
+       }
+
+       p = (pal_min_state_area_t *) addr;
+       kdb_printf("PAL minstate %p-%p\n", p, (unsigned char *)p + sizeof(*p) - 1);
+       kdb_printf("  pmsa_nat_bits 0x%lx\n", p->pmsa_nat_bits);
+       kdb_print_nameval("r1", p->pmsa_gr[1-1]);
+       kdb_print_nameval("r2", p->pmsa_gr[2-1]);
+       kdb_print_nameval("r3", p->pmsa_gr[3-1]);
+       kdb_print_nameval("r4", p->pmsa_gr[4-1]);
+       kdb_print_nameval("r5", p->pmsa_gr[5-1]);
+       kdb_print_nameval("r6", p->pmsa_gr[6-1]);
+       kdb_print_nameval("r7", p->pmsa_gr[7-1]);
+       kdb_print_nameval("r8", p->pmsa_gr[8-1]);
+       kdb_print_nameval("r9", p->pmsa_gr[9-1]);
+       kdb_print_nameval("r10", p->pmsa_gr[10-1]);
+       kdb_print_nameval("r11", p->pmsa_gr[11-1]);
+       kdb_print_nameval("r12", p->pmsa_gr[12-1]);
+       kdb_print_nameval("r13", p->pmsa_gr[13-1]);
+       kdb_print_nameval("r14", p->pmsa_gr[14-1]);
+       kdb_print_nameval("r15", p->pmsa_gr[15-1]);
+       kdb_printf("  Bank 0\n");
+       kdb_print_nameval("r16", p->pmsa_bank0_gr[16-16]);
+       kdb_print_nameval("r17", p->pmsa_bank0_gr[17-16]);
+       kdb_print_nameval("r18", p->pmsa_bank0_gr[18-16]);
+       kdb_print_nameval("r19", p->pmsa_bank0_gr[19-16]);
+       kdb_print_nameval("r20", p->pmsa_bank0_gr[20-16]);
+       kdb_print_nameval("r21", p->pmsa_bank0_gr[21-16]);
+       kdb_print_nameval("r22", p->pmsa_bank0_gr[22-16]);
+       kdb_print_nameval("r23", p->pmsa_bank0_gr[23-16]);
+       kdb_print_nameval("r24", p->pmsa_bank0_gr[24-16]);
+       kdb_print_nameval("r25", p->pmsa_bank0_gr[25-16]);
+       kdb_print_nameval("r26", p->pmsa_bank0_gr[26-16]);
+       kdb_print_nameval("r27", p->pmsa_bank0_gr[27-16]);
+       kdb_print_nameval("r28", p->pmsa_bank0_gr[28-16]);
+       kdb_print_nameval("r29", p->pmsa_bank0_gr[29-16]);
+       kdb_print_nameval("r30", p->pmsa_bank0_gr[30-16]);
+       kdb_print_nameval("r31", p->pmsa_bank0_gr[31-16]);
+       kdb_printf("  Bank 1\n");
+       kdb_print_nameval("r16", p->pmsa_bank1_gr[16-16]);
+       kdb_print_nameval("r17", p->pmsa_bank1_gr[17-16]);
+       kdb_print_nameval("r18", p->pmsa_bank1_gr[18-16]);
+       kdb_print_nameval("r19", p->pmsa_bank1_gr[19-16]);
+       kdb_print_nameval("r20", p->pmsa_bank1_gr[20-16]);
+       kdb_print_nameval("r21", p->pmsa_bank1_gr[21-16]);
+       kdb_print_nameval("r22", p->pmsa_bank1_gr[22-16]);
+       kdb_print_nameval("r23", p->pmsa_bank1_gr[23-16]);
+       kdb_print_nameval("r24", p->pmsa_bank1_gr[24-16]);
+       kdb_print_nameval("r25", p->pmsa_bank1_gr[25-16]);
+       kdb_print_nameval("r26", p->pmsa_bank1_gr[26-16]);
+       kdb_print_nameval("r27", p->pmsa_bank1_gr[27-16]);
+       kdb_print_nameval("r28", p->pmsa_bank1_gr[28-16]);
+       kdb_print_nameval("r29", p->pmsa_bank1_gr[29-16]);
+       kdb_print_nameval("r30", p->pmsa_bank1_gr[30-16]);
+       kdb_print_nameval("r31", p->pmsa_bank1_gr[31-16]);
+       kdb_printf("  pr          0x%lx\n", p->pmsa_pr);
+       kdb_print_nameval("b0", p->pmsa_br0);
+       kdb_printf("  ar.rsc      0x%lx\n", p->pmsa_rsc);
+       kdb_print_nameval("cr.iip", p->pmsa_iip);
+       kdb_printf("  cr.ipsr     0x%lx\n", p->pmsa_ipsr);
+       kdb_printf("  cr.ifs      0x%lx\n", p->pmsa_ifs);
+       kdb_print_nameval("cr.xip", p->pmsa_xip);
+       kdb_printf("  cr.xpsr     0x%lx\n", p->pmsa_xpsr);
+       kdb_printf("  cr.xfs      0x%lx\n", p->pmsa_xfs);
+       kdb_print_nameval("b1", p->pmsa_br1);
+
+       return 0;
+}
+
+/*
+ * kdba_cpuinfo
+ *
+ *     Format struct cpuinfo_ia64.
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     If no cpu is supplied, it prints cpuinfo for all online cpus.
+ */
+
+static int
+kdba_cpuinfo(int argc, const char **argv)
+{
+       int diag;
+       unsigned long cpunum = -1;
+       long offset = 0;
+       int nextarg, c, i;
+       struct cpuinfo_ia64 *cpuinfo;
+
+       if (argc == 1) {
+               nextarg = 1;
+               diag = kdbgetaddrarg(argc, argv, &nextarg, &cpunum, &offset, NULL);
+               if (diag)
+                       return diag;
+               if (cpunum >= NR_CPUS || !cpu_online(cpunum))
+                       return KDB_BADCPUNUM;
+       } else if (argc > 1) {
+               return KDB_ARGCOUNT;
+       }
+
+       for (c = (cpunum == -1 ? 0 : cpunum);
+            c < (cpunum == -1 ? NR_CPUS : cpunum+1);
+            ++c) {
+               if (!cpu_online(c))
+                       continue;
+               cpuinfo = cpu_data(c);
+               kdb_printf("struct cpuinfo_ia64 for cpu %d is at 0x%p\n", c, cpuinfo);
+               kdb_printf("  softirq_pending  0x%x\n",   cpuinfo->softirq_pending);
+               kdb_printf("  itm_delta        %ld\n",    cpuinfo->itm_delta);
+               kdb_printf("  itm_next         %ld\n",    cpuinfo->itm_next);
+               kdb_printf("  nsec_per_cyc     %ld\n",    cpuinfo->nsec_per_cyc);
+               kdb_printf("  unimpl_va_mask   0x%lx\n",  cpuinfo->unimpl_va_mask);
+               kdb_printf("  unimpl_pa_mask   0x%lx\n",  cpuinfo->unimpl_pa_mask);
+               kdb_printf("  itc_freq         %ld\n",    cpuinfo->itc_freq);
+               kdb_printf("  proc_freq        %ld\n",    cpuinfo->proc_freq);
+               kdb_printf("  cyc_per_usec     %ld\n",    cpuinfo->cyc_per_usec);
+               kdb_printf("  cyc_per_usec     %ld\n",    cpuinfo->cyc_per_usec);
+#if 0  /* RJA per-cpu MCA */
+               kdb_printf("  percpu_paddr     0x%lx\n",  cpuinfo->percpu_paddr);
+#endif
+               kdb_printf("  ptce_base        0x%lx\n",  cpuinfo->ptce_base);
+               kdb_printf("  ptce_count       %d %d\n",  cpuinfo->ptce_count[0], cpuinfo->ptce_count[1]);
+               kdb_printf("  ptce_stride      %d %d\n",  cpuinfo->ptce_stride[0], cpuinfo->ptce_stride[1]);
+#if 0  /* RJA per-cpu MCA */
+               kdb_printf("  pal_paddr        0x%lx\n",  cpuinfo->pal_paddr);
+               kdb_printf("  pal_base         0x%lx\n",  cpuinfo->pal_base);
+#endif
+               kdb_printf("  ksoftirqd        0x%p\n",   cpuinfo->ksoftirqd);
+#ifdef CONFIG_SMP
+               kdb_printf("  loops_per_jiffy  %ld\n",    cpuinfo->loops_per_jiffy);
+               kdb_printf("  cpu              %d\n",     cpuinfo->cpu);
+               kdb_printf("  socket_id        %d\n",     cpuinfo->socket_id);
+               kdb_printf("  core_id          %d\n",     cpuinfo->core_id);
+               kdb_printf("  thread_id        %d\n",     cpuinfo->thread_id);
+               kdb_printf("  num_log          %d\n",     cpuinfo->num_log);
+               kdb_printf("  cores_per_socket %d\n",     cpuinfo->cores_per_socket);
+               kdb_printf("  threads_per_core %d\n",     cpuinfo->threads_per_core);
+#endif
+               kdb_printf("  ppn              0x%lx\n",  cpuinfo->ppn);
+               kdb_printf("  features         0x%lx\n",  cpuinfo->features);
+               kdb_printf("  number           %d\n",     cpuinfo->number);
+               kdb_printf("  revision         %d\n",     cpuinfo->revision);
+               kdb_printf("  model            %d\n",     cpuinfo->model);
+               kdb_printf("  family           %d\n",     cpuinfo->family);
+               kdb_printf("  archrev          %d\n",     cpuinfo->archrev);
+               kdb_printf("  vendor          ");
+               for (i = 0; i < sizeof(cpuinfo->vendor); ++i)
+                       kdb_printf(" 0x%02x", cpuinfo->vendor[i]);
+               kdb_printf("\n");
+#ifdef CONFIG_NUMA
+               kdb_printf("  node_data        0x%p\n",   cpuinfo->node_data);
+#endif
+#if 0  /* RJA per-cpu MCA */
+               kdb_printf("  ia64_pa_mca_data 0x%p\n",   cpuinfo->ia64_pa_mca_data);
+#endif
+       }
+       return 0;
+}
+
+#ifdef CONFIG_KDB_HARDWARE_BREAKPOINTS
+void
+kdba_installdbreg(kdb_bp_t *bp)
+{
+       unsigned long mask;
+       unsigned int regbase;
+       static unsigned long masks[] = {
+           0x00FFFFFFFFFFFFFFUL,   // 1 byte long
+           0x00FFFFFFFFFFFFFEUL,   // 2 bytes long
+           0x0000000000000000UL,   // invalid
+           0x00FFFFFFFFFFFFFCUL    // 4 bytes long
+       };
+       static unsigned char modes[] = {
+           0x81,                   // instruction => x, plm=priv level 0 only
+           0x41,                   // write => w, plm=priv level 0 only
+           0x00,                   // io
+           0x81                    // read => r, plm=priv level 0 only
+       };
+
+       /* Note that bp->bp_hard[NR_CPU] is for x86.
+        * The ia64 uses bp->bp_hard[0] only.
+        */
+       if (KDB_DEBUG(BP))
+               kdb_printf("kdba_installdbreg:\n");
+       mask = masks[bp->bp_hard[0]->bph_length] |
+              (((unsigned long)(modes[bp->bp_hard[0]->bph_mode])) << 56);
+       regbase = 2*bp->bp_hard[0]->bph_reg;
+
+       switch (bp->bp_hard[0]->bph_mode)
+       {
+       case 1:
+       case 3:
+               if (KDB_DEBUG(BP)) {
+                       kdb_printf("kdba_installdbreg: dbr[%u]=%016lx\n",
+                                       regbase, bp->bp_addr);
+                       kdb_printf("kdba_installdbreg: dbr[%u]=%016lx\n",
+                                       regbase+1, mask);
+               }
+
+               ia64_set_dbr(regbase, bp->bp_addr);
+               ia64_set_dbr(regbase+1, mask);
+               ia64_srlz_d();
+               break;
+
+       case 0: /* instruction */
+#if 0
+               ia64_set_ibr(regbase, bp->bp_addr);
+               ia64_set_ibr(regbase+1, mask);
+               ia64_srlz_d();
+#else
+               kdb_printf("\"instr\" mode not implemented\n");
+#endif
+               break;
+
+       case 2: /* io */
+               kdb_printf("\"io\" mode not implemented\n");
+               break;
+       }
+}
+
+void
+kdba_removedbreg(kdb_bp_t *bp)
+{
+       unsigned int regbase = 2*bp->bp_hard[0]->bph_reg;
+
+       /* Note that bp->bp_hard[NR_CPU] is for x86.
+        * The ia64 uses bp->bp_hard[0] only.
+        */
+       switch (bp->bp_hard[0]->bph_mode)
+       {
+       case 1:
+       case 3:
+               ia64_set_dbr(regbase, 0);
+               ia64_set_dbr(regbase+1, 0);
+               ia64_srlz_d();
+               break;
+
+       case 0: /* instruction */
+#if 0
+               ia64_set_ibr(regbase, 0);
+               ia64_set_ibr(regbase+1, 0);
+               ia64_srlz_d();
+#else
+               kdb_printf("\"instr\" mode not implemented\n");
+#endif
+               break;
+
+       case 2: /* io */
+               kdb_printf("\"io\" mode not implemented\n");
+               break;
+       }
+}
+#endif /* CONFIG_KDB_HARDWARE_BREAKPOINTS */
+
+
+static kdb_machreg_t
+kdba_getdr(int regnum)
+{
+       kdb_machreg_t contents = 0;
+       unsigned long reg = (unsigned long)regnum;
+
+       __asm__ ("mov %0=ibr[%1]"::"r"(contents),"r"(reg));
+//        __asm__ ("mov ibr[%0]=%1"::"r"(dbreg_cond),"r"(value));
+
+       return contents;
+}
+
+
+static void
+get_fault_regs(fault_regs_t *fr)
+{
+       fr->ifa = 0 ;
+       fr->isr = 0 ;
+
+       __asm__ ("rsm psr.ic;;") ;
+       ia64_srlz_d();
+       __asm__ ("mov %0=cr.ifa" : "=r"(fr->ifa));
+       __asm__ ("mov %0=cr.isr" : "=r"(fr->isr));
+       __asm__ ("ssm psr.ic;;") ;
+       ia64_srlz_d();
+}
+
+static void
+show_kernel_regs (void)
+{
+       unsigned long kr[8];
+       int i;
+
+       asm ("mov %0=ar.k0" : "=r"(kr[0])); asm ("mov %0=ar.k1" : "=r"(kr[1]));
+       asm ("mov %0=ar.k2" : "=r"(kr[2])); asm ("mov %0=ar.k3" : "=r"(kr[3]));
+       asm ("mov %0=ar.k4" : "=r"(kr[4])); asm ("mov %0=ar.k5" : "=r"(kr[5]));
+       asm ("mov %0=ar.k6" : "=r"(kr[6])); asm ("mov %0=ar.k7" : "=r"(kr[7]));
+
+       for (i = 0; i < 4; ++i)
+               kdb_printf(" kr%d: %016lx  kr%d: %016lx\n", 2*i, kr[2*i], 2*i+1, kr[2*i+1]);
+       kdb_printf("\n");
+}
+
+static int
+change_cur_stack_frame(int regno, unsigned long *contents)
+{
+       unsigned long sof, i, cfm, sp, *bsp, __user *ubsp;
+       struct unw_frame_info info;
+       mm_segment_t old_fs;
+       int cpu = kdb_process_cpu(kdb_current_task);
+       struct kdb_running_process *krp = kdb_running_process + cpu;
+
+       if (kdb_current_task != krp->p) {
+               kdb_printf("Stacked registers are not available for tasks that are not running.\n");
+               kdb_printf("Use bt with a large BTARGS value instead\n");
+               return 0;
+       }
+       unw_init_frame_info(&info, krp->p, krp->arch.sw);
+       do {
+               if (unw_unwind(&info) < 0) {
+                       kdb_printf("Failed to unwind\n");
+                       return 0;
+               }
+               unw_get_sp(&info, &sp);
+       } while (sp <= (unsigned long) kdb_current_regs);
+       unw_get_bsp(&info, (unsigned long *) &bsp);
+       unw_get_cfm(&info, &cfm);
+
+       if (!bsp) {
+               kdb_printf("Unable to get Current Stack Frame\n");
+               return 0;
+       }
+
+       sof = (cfm & 0x7f);
+
+       if(((unsigned long)regno - 32) >= (sof - 2)) return 1;
+
+       old_fs = set_fs(KERNEL_DS);
+       for (i = 0; i < (regno - 32); ++i)
+               bsp = ia64_rse_skip_regs(bsp, 1);
+       ubsp = (unsigned long __user *) bsp;
+       put_user(*contents, ubsp);
+       set_fs(old_fs);
+
+       return 0 ;
+}
+
+static int
+show_cur_stack_frame(int regno, unsigned long *contents)
+{
+       unsigned long sof, i, cfm, val, sp, *bsp, __user *ubsp;
+       struct unw_frame_info info;
+       mm_segment_t old_fs;
+       int cpu = kdb_process_cpu(kdb_current_task);
+       struct kdb_running_process *krp = kdb_running_process + cpu;
+
+       if (kdb_current_task != krp->p) {
+               kdb_printf("Stacked registers are not available for tasks that are not running.\n");
+               kdb_printf("Use bt with a large BTARGS value instead\n");
+               return 0;
+       }
+       unw_init_frame_info(&info, krp->p, krp->arch.sw);
+       do {
+               if (unw_unwind(&info) < 0) {
+                       kdb_printf("Failed to unwind\n");
+                       return 0;
+               }
+               unw_get_sp(&info, &sp);
+       } while (sp <= (unsigned long) kdb_current_regs);
+       unw_get_bsp(&info, (unsigned long *) &bsp);
+       unw_get_cfm(&info, &cfm);
+
+       if (!bsp) {
+               kdb_printf("Unable to display Current Stack Frame\n");
+               return 0;
+       }
+
+       sof = (cfm & 0x7f);
+
+       if (regno) {
+               if ((unsigned) regno - 32 >= sof)
+                       return 0;
+               bsp = ia64_rse_skip_regs(bsp, regno - 32);
+               old_fs = set_fs(KERNEL_DS);
+               ubsp = (unsigned long __user *) bsp;
+               get_user(val, ubsp);
+               set_fs(old_fs);
+               *contents = val;
+               return 1;
+       }
+
+       old_fs = set_fs(KERNEL_DS);
+       for (i = 0; i < sof; ++i) {
+               ubsp = (unsigned long __user *) bsp;
+               get_user(val, ubsp);
+               kdb_printf(" r%lu: %016lx ", 32 + i, val);
+               if (!((i + 1) % 3))
+                       kdb_printf("\n");
+               bsp = ia64_rse_skip_regs(bsp, 1);
+       }
+       kdb_printf("\n");
+       set_fs(old_fs);
+
+       return 0 ;
+}
+
+/*
+ * 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
+ *        sstk          - Prints switch stack for ia64
+ *        %<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:
+ *
+ *     Note that this function is really machine independent.   The kdb
+ *     register list is not, however.
+ */
+
+static struct kdbregs {
+       char   *reg_name;
+       size_t  reg_offset;
+} kdbreglist[] = {
+       { "psr",        offsetof(struct pt_regs, cr_ipsr) },
+       { "ifs",        offsetof(struct pt_regs, cr_ifs) },
+       { "ip", offsetof(struct pt_regs, cr_iip) },
+
+       { "unat",       offsetof(struct pt_regs, ar_unat) },
+       { "pfs",        offsetof(struct pt_regs, ar_pfs) },
+       { "rsc",        offsetof(struct pt_regs, ar_rsc) },
+
+       { "rnat",       offsetof(struct pt_regs, ar_rnat) },
+       { "bsps",       offsetof(struct pt_regs, ar_bspstore) },
+       { "pr", offsetof(struct pt_regs, pr) },
+
+       { "ldrs",       offsetof(struct pt_regs, loadrs) },
+       { "ccv",        offsetof(struct pt_regs, ar_ccv) },
+       { "fpsr",       offsetof(struct pt_regs, ar_fpsr) },
+
+       { "b0", offsetof(struct pt_regs, b0) },
+       { "b6", offsetof(struct pt_regs, b6) },
+       { "b7", offsetof(struct pt_regs, b7) },
+
+       { "r1",offsetof(struct pt_regs, r1) },
+       { "r2",offsetof(struct pt_regs, r2) },
+       { "r3",offsetof(struct pt_regs, r3) },
+
+       { "r8",offsetof(struct pt_regs, r8) },
+       { "r9",offsetof(struct pt_regs, r9) },
+       { "r10",offsetof(struct pt_regs, r10) },
+
+       { "r11",offsetof(struct pt_regs, r11) },
+       { "r12",offsetof(struct pt_regs, r12) },
+       { "r13",offsetof(struct pt_regs, r13) },
+
+       { "r14",offsetof(struct pt_regs, r14) },
+       { "r15",offsetof(struct pt_regs, r15) },
+       { "r16",offsetof(struct pt_regs, r16) },
+
+       { "r17",offsetof(struct pt_regs, r17) },
+       { "r18",offsetof(struct pt_regs, r18) },
+       { "r19",offsetof(struct pt_regs, r19) },
+
+       { "r20",offsetof(struct pt_regs, r20) },
+       { "r21",offsetof(struct pt_regs, r21) },
+       { "r22",offsetof(struct pt_regs, r22) },
+
+       { "r23",offsetof(struct pt_regs, r23) },
+       { "r24",offsetof(struct pt_regs, r24) },
+       { "r25",offsetof(struct pt_regs, r25) },
+
+       { "r26",offsetof(struct pt_regs, r26) },
+       { "r27",offsetof(struct pt_regs, r27) },
+       { "r28",offsetof(struct pt_regs, r28) },
+
+       { "r29",offsetof(struct pt_regs, r29) },
+       { "r30",offsetof(struct pt_regs, r30) },
+       { "r31",offsetof(struct pt_regs, r31) },
+
+};
+
+static const int nkdbreglist = sizeof(kdbreglist) / sizeof(struct kdbregs);
+
+int
+kdba_getregcontents(const char *regname, struct pt_regs *regs, unsigned long *contents)
+{
+       int i;
+
+       if (strcmp(regname, "isr") == 0) {
+               fault_regs_t fr ;
+               get_fault_regs(&fr) ;
+               *contents = fr.isr ;
+               return 0 ;
+       }
+
+       if (!regs) {
+               kdb_printf("%s: pt_regs not available, use bt* or pid to select a different task\n", __FUNCTION__);
+               return KDB_BADREG;
+       }
+
+       if (strcmp(regname, "&regs") == 0) {
+               *contents = (unsigned long)regs;
+               return 0;
+       }
+
+       if (strcmp(regname, "sstk") == 0) {
+               *contents = (unsigned long)getprsregs(regs) ;
+               return 0;
+       }
+
+       if (strcmp(regname, "ksp") == 0) {
+               *contents = (unsigned long) (regs + 1);
+               return 0;
+       }
+
+       for (i=0; i<nkdbreglist; i++) {
+               if (strstr(kdbreglist[i].reg_name, regname))
+                       break;
+       }
+
+       if (i == nkdbreglist) {
+               /* Lets check the rse maybe */
+               if (regname[0] == 'r')
+                       if (show_cur_stack_frame(simple_strtoul(regname+1, NULL, 0), contents))
+                               return 0 ;
+               return KDB_BADREG;
+       }
+
+       *contents = *(unsigned long *)((unsigned long)regs +
+                       kdbreglist[i].reg_offset);
+
+       return 0;
+}
+
+/*
+ * 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, ret = 0, fixed = 0;
+       char *endp;
+       unsigned long regno;
+
+       if (regname[0] == '%') {
+               regname++;
+               regs = (struct pt_regs *)
+                       (kdb_current_task->thread.ksp - sizeof(struct pt_regs));
+       }
+
+       if (!regs) {
+               kdb_printf("%s: pt_regs not available, use bt* or pid to select a different task\n", __FUNCTION__);
+               return KDB_BADREG;
+       }
+
+       /* fixed registers */
+       for (i=0; i<nkdbreglist; i++) {
+               if (strnicmp(kdbreglist[i].reg_name,
+                            regname,
+                            strlen(regname)) == 0) {
+                       fixed = 1;
+                       break;
+               }
+       }
+
+       /* stacked registers */
+       if (!fixed) {
+               regno = (simple_strtoul(&regname[1], &endp, 10));
+               if ((regname[0] == 'r') && regno > (unsigned long)31) {
+                       ret = change_cur_stack_frame(regno, &contents);
+                       if(!ret) return 0;
+               }
+       }
+
+       if ((i == nkdbreglist)
+           || (strlen(kdbreglist[i].reg_name) != strlen(regname))
+           || ret) {
+               return KDB_BADREG;
+       }
+
+       /* just in case of "standard" register */
+       *(unsigned long *)((unsigned long)regs + kdbreglist[i].reg_offset) =
+               contents;
+
+       return 0;
+}
+
+/*
+ * 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
+ *     i               Interrupt registers -- same as "irr" command
+ * Following not yet implemented:
+ *     m               Model Specific Registers (extra defines register #)
+ *     r               Memory Type Range Registers (extra defines register)
+ *
+ *     For now, all registers are covered as follows:
+ *
+ *     rd              - dumps all regs
+ *     rd      %isr    - current interrupt status reg, read freshly
+ *     rd      s       - valid stacked regs
+ *     rd      %sstk   - gets switch stack addr. dump memory and search
+ *     rd      d       - debug regs, may not be too useful
+ *     rd      k       - dump kernel regs
+ *
+ *     ARs             TB Done
+ *     OTHERS          TB Decided ??
+ *
+ *     Intel wish list
+ *     These will be implemented later - Srinivasa
+ *
+ *      type        action
+ *      ----        ------
+ *      g           dump all General static registers
+ *      s           dump all general Stacked registers
+ *      f           dump all Floating Point registers
+ *      p           dump all Predicate registers
+ *      b           dump all Branch registers
+ *      a           dump all Application registers
+ *      c           dump all Control registers
+ *
+ */
+
+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.ksp - sizeof(struct pt_regs));
+       }
+
+       if (type == NULL) {
+               if (!regs) {
+                       kdb_printf("%s: pt_regs not available, use bt* or pid to select a different task\n", __FUNCTION__);
+                       return KDB_BADREG;
+               }
+               for (i=0; i<nkdbreglist; i++) {
+                       kdb_printf("%4s: 0x%16.16lx  ",
+                                  kdbreglist[i].reg_name,
+                                  *(unsigned long *)((unsigned long)regs +
+                                                 kdbreglist[i].reg_offset));
+
+                       if ((++count % 3) == 0)
+                               kdb_printf("\n");
+               }
+
+               kdb_printf("&regs = %p\n", (void *)regs);
+
+               return 0;
+       }
+
+       switch (type[0]) {
+       case 'd':
+       {
+               for(i=0; i<8; i+=2) {
+                       kdb_printf("idr%d: 0x%16.16lx  idr%d: 0x%16.16lx\n", i,
+                                       kdba_getdr(i), i+1, kdba_getdr(i+1));
+
+               }
+               return 0;
+       }
+       case 'i':
+               kdba_show_intregs();
+               break;
+       case 'k':
+               show_kernel_regs();
+               break;
+       case 'm':
+               break;
+       case 'r':
+               break;
+
+       case 's':
+       {
+               if (!regs) {
+                       kdb_printf("%s: pt_regs not available, use bt* or pid to select a different task\n", __FUNCTION__);
+                       return KDB_BADREG;
+               }
+               show_cur_stack_frame(0, NULL) ;
+
+               return 0 ;
+       }
+
+       case '%':
+       {
+               unsigned long contents ;
+
+               if (!kdba_getregcontents(type+1, regs, &contents))
+                       kdb_printf("%s = 0x%16.16lx\n", type+1, contents) ;
+               else
+                       kdb_printf("diag: Invalid register %s\n", type+1) ;
+
+               return 0 ;
+       }
+
+       default:
+               return KDB_BADREG;
+       }
+
+       /* NOTREACHED */
+       return 0;
+}
+EXPORT_SYMBOL(kdba_dumpregs);
+
+kdb_machreg_t
+kdba_getpc(struct pt_regs *regs)
+{
+       return regs ? regs->cr_iip + ia64_psr(regs)->ri : 0;
+}
+
+int
+kdba_setpc(struct pt_regs *regs, kdb_machreg_t newpc)
+{
+       if (KDB_NULL_REGS(regs))
+               return KDB_BADREG;
+       regs->cr_iip = newpc & ~0xf;
+       ia64_psr(regs)->ri = newpc & 0x3;
+       KDB_STATE_SET(IP_ADJUSTED);
+       return 0;
+}
+
+struct kdba_main_loop_data {
+       kdb_reason_t reason;
+       kdb_reason_t reason2;
+       int error;
+       kdb_dbtrap_t db_result;
+       struct pt_regs *regs;
+       int ret;
+};
+
+/*
+ * do_kdba_main_loop
+ *
+ *     Invoked from kdba_main_loop via unw_init_running() after that routine
+ *     has pushed a struct switch_stack.
+ *
+ * Inputs:
+ *     info    Unwind information.
+ *     data    kdb data passed as void * to unw_init_running.
+ * Returns:
+ *     none (unw_init_running requires void).  vdata->ret is set to
+ *     0       KDB was invoked for an event which it wasn't responsible
+ *     1       KDB handled the event for which it was invoked.
+ * Outputs:
+ *     none
+ * Locking:
+ *     None.
+ * Remarks:
+ *     unw_init_running() creates struct switch_stack then struct
+ *     unw_frame_info.  We get the address of the info so step over
+ *     that to get switch_stack.  Just hope that unw_init_running
+ *     does not change its stack usage.  unw_init_running adds padding
+ *     to put switch_stack on a 16 byte boundary.
+ */
+
+static void
+do_kdba_main_loop(struct unw_frame_info *info, void *vdata)
+{
+       struct kdba_main_loop_data *data = vdata;
+       struct switch_stack *sw, *prev_sw;
+       struct pt_regs *prev_regs;
+       struct kdb_running_process *krp =
+               kdb_running_process + smp_processor_id();
+       KDB_DEBUG_STATE(__FUNCTION__, data->reason);
+       prev_sw = krp->arch.sw;
+       sw = (struct switch_stack *)(info+1);
+       /* padding from unw_init_running */
+       sw = (struct switch_stack *)(((unsigned long)sw + 15) & ~15);
+       krp->arch.sw = sw;
+       prev_regs = krp->regs;
+       data->ret = kdb_save_running(data->regs, data->reason, data->reason2,
+                       data->error, data->db_result);
+       kdb_unsave_running(data->regs);
+       krp->regs = prev_regs;
+       krp->arch.sw = prev_sw;
+}
+
+/*
+ * 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 processes 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 SILENT or CPU_UP 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:
+ *     Builds a switch_stack structure before calling the main loop.
+ * 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)
+{
+       struct kdba_main_loop_data data;
+       KDB_DEBUG_STATE("kdba_main_loop", reason);
+       data.reason = reason;
+       data.reason2 = reason2;
+       data.error = error;
+       data.db_result = db_result;
+       data.regs = regs;
+       unw_init_running(do_kdba_main_loop, &data);
+       return(data.ret);
+}
+
+void
+kdba_disableint(kdb_intstate_t *state)
+{
+       unsigned long *fp = (unsigned long *)state;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       *fp = flags;
+}
+
+void
+kdba_restoreint(kdb_intstate_t *state)
+{
+       unsigned long flags = *(unsigned long *)state;
+       local_irq_restore(flags);
+}
+
+void
+kdba_setsinglestep(struct pt_regs *regs)
+{
+       if (KDB_NULL_REGS(regs))
+               return;
+       ia64_psr(regs)->ss = 1;
+}
+
+void
+kdba_clearsinglestep(struct pt_regs *regs)
+{
+       if (KDB_NULL_REGS(regs))
+               return;
+       ia64_psr(regs)->ss = 0;
+}
+
+/*
+ * kdb_tpa
+ *
+ *     Virtual to Physical address translation command.
+ *
+ *     tpa  <addr>
+ *
+ * Parameters:
+ *     argc    Count of arguments in argv
+ *     argv    Space delimited command line arguments
+ * Outputs:
+ *     None.
+ * Returns:
+ *     Zero for success, a kdb diagnostic if failure.
+ * Locking:
+ *     None.
+ * Remarks:
+ */
+#define __xtpa(x)              ({ia64_va _v; asm("tpa %0=%1" : "=r"(_v.l) : "r"(x)); _v.l;})
+static int
+kdba_tpa(int argc, const char **argv)
+{
+       kdb_machreg_t addr;
+       int diag;
+       long offset = 0;
+       int nextarg;
+       char c;
+
+       nextarg = 1;
+       if (argc != 1)
+               return KDB_ARGCOUNT;
+       diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
+       if (diag)
+               return diag;
+       if (kdb_getarea(c, addr))
+               return(0);
+       kdb_printf("vaddr: 0x%lx , paddr: 0x%lx\n", addr, __xtpa(addr));
+       return(0);
+}
+#if defined(CONFIG_NUMA)
+static int
+kdba_tpav(int argc, const char **argv)
+{
+       kdb_machreg_t addr, end, paddr;
+       int diag;
+       long offset = 0;
+       int nextarg, nid, nid_old;
+       char c;
+
+       nextarg = 1;
+       if (argc != 2)
+               return KDB_ARGCOUNT;
+       diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
+       if (diag)
+               return diag;
+       diag = kdbgetaddrarg(argc, argv, &nextarg, &end, &offset, NULL);
+       if (diag)
+               return diag;
+       if (kdb_getarea(c, addr))
+               return(0);
+       if (kdb_getarea(c, end))
+               return(0);
+       paddr=__xtpa(addr);
+       nid = paddr_to_nid(paddr);
+       kdb_printf("begin: 0x%lx , paddr: 0x%lx , nid: %d\n", addr, __xtpa(addr), nid);
+       for(;addr<end; addr += PAGE_SIZE) {
+               nid_old=nid;
+               paddr =__xtpa(addr);
+               nid = paddr_to_nid(paddr);
+               if (nid != nid_old)
+                       kdb_printf("NOT on same NODE: addr: 0x%lx , paddr: 0x%lx , nid: %d\n", addr, paddr, nid);
+       }
+       paddr=__xtpa(end);
+       nid=paddr_to_nid(end);
+       kdb_printf("end: 0x%lx , paddr: 0x%lx , nid: %d\n", end, paddr, nid);
+       return(0);
+}
+#endif
+
+#if defined(CONFIG_SMP)
+/*
+ * kdba_sendinit
+ *
+ *      This function implements the 'init' command.
+ *
+ *      init    [<cpunum>]
+ *
+ * Inputs:
+ *      argc    argument count
+ *      argv    argument vector
+ * Outputs:
+ *      None.
+ * Returns:
+ *      zero for success, a kdb diagnostic if error
+ * Locking:
+ *      none.
+ * Remarks:
+ */
+
+static int
+kdba_sendinit(int argc, const char **argv)
+{
+       unsigned long cpunum;
+       int diag;
+
+       if (argc != 1)
+               return KDB_ARGCOUNT;
+
+       diag = kdbgetularg(argv[1], &cpunum);
+       if (diag)
+               return diag;
+
+       if (cpunum >= NR_CPUS || !cpu_online(cpunum))
+               return KDB_BADCPUNUM;
+
+       platform_send_ipi(cpunum, 0, IA64_IPI_DM_INIT, 0);
+       return 0;
+}
+
+/* Invoked once from kdb_wait_for_cpus when waiting for cpus.  For those cpus
+ * that have not responded to the normal KDB interrupt yet, hit them with an
+ * INIT event.
+ */
+void
+kdba_wait_for_cpus(void)
+{
+       int c;
+       if (KDB_FLAG(CATASTROPHIC))
+               return;
+       kdb_printf("  Sending INIT to cpus that have not responded yet\n");
+       for_each_online_cpu(c)
+               if (kdb_running_process[c].seqno < kdb_seqno - 1)
+                       platform_send_ipi(c, 0, IA64_IPI_DM_INIT, 0);
+}
+
+#endif /* CONFIG_SMP */
+
+/* This code is sensitive to the layout of the MCA/INIT stack (see mca_asm.h)
+ * and to the stack layout that ia64_mca_modify_original_stack() creates when
+ * it makes the original task look blocked.
+ */
+static void
+kdba_handlers_modify(struct task_struct *task, int cpu)
+{
+       struct kdb_running_process *work, *save;
+       work = kdb_running_process + cpu;
+       save = kdb_running_process_save + cpu;
+       *work = *save;
+       if (!kdba_show_handlers && REGION_NUMBER(task) >= RGN_GATE &&
+           (task_thread_info(task)->flags & _TIF_MCA_INIT)) {
+               struct ia64_sal_os_state *sos = (struct ia64_sal_os_state *)
+                       ((unsigned long)save->p + MCA_SOS_OFFSET);
+               char *p;
+               if (!sos->prev_task)
+                       return;
+               work->p = sos->prev_task;
+               p = (char *)sos->prev_task->thread.ksp;
+               p += 16;
+               work->arch.sw = (struct switch_stack *)p;
+               p += sizeof(struct switch_stack);
+               work->regs = (struct pt_regs *)p;
+               work->irq_depth = 2;    /* any value >1 will do */
+       }
+}
+
+/* Turn the display of the MCA/INIT handlers on or off, or display the status
+ * of the MCA/INIT handlers.
+ */
+static int
+kdba_handlers(int argc, const char **argv)
+{
+       int cpu;
+       struct kdb_running_process *krp;
+       if (argc != 1)
+               return KDB_ARGCOUNT;
+       if (strcmp(argv[1], "show") == 0)
+               kdba_show_handlers = 1;
+       else if (strcmp(argv[1], "hide") == 0)
+               kdba_show_handlers = 0;
+       else if (strcmp(argv[1], "status") != 0) {
+               kdb_printf("handlers <show|hide|status>\n");
+               return 0;
+       }
+       for (cpu = 0, krp = kdb_running_process_save; cpu < NR_CPUS; ++cpu, ++krp) {
+               if (krp->p)
+                       kdba_handlers_modify(krp->p, cpu);
+       }
+       if (strcmp(argv[1], "status") != 0)
+               return 0;
+       kdb_printf("handlers status is %s\n", kdba_show_handlers ? "'show'" : "'hide'");
+       kdb_printf(" cpu handler task       command            original task      command\n");
+       for (cpu = 0, krp = kdb_running_process_save; cpu < NR_CPUS; ++cpu, ++krp) {
+               struct task_struct *p = krp->p;
+               if (!p)
+                       continue;
+               kdb_printf("%4d", cpu);
+               if (task_thread_info(p)->flags & _TIF_MCA_INIT) {
+                       struct ia64_sal_os_state *sos;
+                       kdb_printf(" " kdb_machreg_fmt0 " %-*s  ",
+                                  (unsigned long)p, (int)sizeof(p->comm), p->comm);
+                       sos = (struct ia64_sal_os_state *)((unsigned long)p + MCA_SOS_OFFSET);
+                       p = sos->prev_task;
+               } else
+                       kdb_printf("%*s", (int)(1+2+16+1+sizeof(p->comm)+2), " ");
+               if (p)
+                       kdb_printf(" " kdb_machreg_fmt0 " %-*s",
+                                  (unsigned long)p, (int)sizeof(p->comm), p->comm);
+               kdb_printf("\n");
+       }
+       return 0;
+}
+
+/* Executed once on each cpu at startup. */
+void
+kdba_cpu_up(void)
+{
+}
+
+/*
+ * kdba_init
+ *
+ *     Architecture specific initialization.
+ *
+ * Parameters:
+ *     None.
+ * Returns:
+ *     None.
+ * Locking:
+ *     None.
+ * Remarks:
+ *     None.
+ */
+
+void
+kdba_init(void)
+{
+       kdb_running_process_save = kzalloc(
+               sizeof(*kdb_running_process_save) * NR_CPUS, GFP_KERNEL);
+       BUG_ON(!kdb_running_process_save);
+       kdb_register("irr", kdba_sir, "", "Show interrupt registers", 0);
+       kdb_register("itm", kdba_itm, "", "Set new ITM value", 0);
+#if defined(CONFIG_SMP)
+       kdb_register("init", kdba_sendinit, "", "Send INIT to cpu", 0);
+#endif
+       kdb_register("pt_regs", kdba_pt_regs, "address", "Format struct pt_regs", 0);
+       kdb_register("switch_stack", kdba_switch_stack, "address", "Format struct switch_stack", 0);
+       kdb_register("minstate", kdba_minstate, "address", "Format PAL minstate", 0);
+       kdb_register("tpa", kdba_tpa, "<vaddr>", "Translate virtual to physical address", 0);
+#if defined(CONFIG_NUMA)
+       kdb_register("tpav", kdba_tpav, "<begin addr> <end addr>", "Verify that physical addresses corresponding to virtual addresses from <begin addr> to <end addr> are in same node", 0);
+#endif
+       kdb_register("stackdepth", kdba_stackdepth, "[percentage]", "Print processes using >= stack percentage", 0);
+       kdb_register("cpuinfo", kdba_cpuinfo, "[cpu]", "Print struct cpuinfo_ia64", 0);
+       kdb_register("handlers", kdba_handlers, "<show|hide|status>", "Control the display of MCA/INIT handlers", 0);
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       kdba_serial_console = KDBA_SC_STANDARD;
+#endif
+#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
+       if (ia64_platform_is("sn2"))
+               kdba_serial_console = KDBA_SC_SGI_L1;
+#endif
+       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 SILENT or CPU_UP then regs is NULL, otherwise it should
+ *                     always be valid.
+ * Returns:
+ *     None.
+ * Locking:
+ *     None.
+ * Remarks:
+ *     On IA64, KDB_ENTER() and KDB_ENTER_SLAVE() use break which is a fault,
+ *     not a trap.  The instruction pointer must be stepped before leaving
+ *     kdb, otherwise we get a loop.
+ */
+
+void
+kdba_adjust_ip(kdb_reason_t reason, int error, struct pt_regs *regs)
+{
+       if ((reason == KDB_REASON_ENTER || reason == KDB_REASON_ENTER_SLAVE) &&
+           !KDB_STATE(IP_ADJUSTED)) {
+               if (KDB_NULL_REGS(regs))
+                       return;
+               if (ia64_psr(regs)->ri < 2)
+                       kdba_setpc(regs, regs->cr_iip + ia64_psr(regs)->ri + 1);
+               else
+                       kdba_setpc(regs, regs->cr_iip + 16);
+       }
+}
+
+void
+kdba_save_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+       struct kdb_running_process *work, *save;
+       int cpu = smp_processor_id();
+       work = kdb_running_process + cpu;
+       save = kdb_running_process_save + cpu;
+       *save = *work;
+       if (!regs)
+               return;
+       kdba_handlers_modify((struct task_struct *)regs->r13, cpu);
+}
+
+void
+kdba_unsave_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+       memset(kdb_running_process_save + smp_processor_id(), 0,
+                       sizeof(*kdb_running_process_save));
+}
+
+void
+kdba_set_current_task(const struct task_struct *p)
+{
+       int cpu = kdb_process_cpu(p);
+       struct kdb_running_process *work, *save;
+       work = kdb_running_process + cpu;
+       save = kdb_running_process_save + cpu;
+       kdb_current_task = p;
+       if (kdb_task_has_cpu(p)) {
+               kdb_current_regs = work->regs;
+               return;
+       }
+       kdb_current_regs = NULL;
+       /* For most blocked tasks we cannot get the pt_regs without doing an
+        * unwind, which is not worth doing.  For tasks interrupted by
+        * MCA/INIT, when the user is not working on the handlers, we must use
+        * the registers at the time of interrupt.
+        */
+       if (work->p == save->p || work->p != p)
+               return;
+       kdb_current_regs = (struct pt_regs *)(work->p->thread.ksp + 16 +
+               sizeof(struct switch_stack));
+}
+
+/*
+ * asm-ia64 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,
+ */
+
+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 >> 61 <= 4) {
+               return kdb_putuserarea_size(to_xxx, from, size);
+       }
+
+       set_fs(KERNEL_DS);
+       r = __copy_to_user_inatomic((void __user *)to_xxx, from, size);
+       set_fs(oldfs);
+       return r;
+}
+
+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 >> 61 <= 4)
+               return kdb_getuserarea_size(to, from_xxx, size);
+
+       set_fs(KERNEL_DS);
+       switch (size) {
+       case 1:
+               r = __copy_to_user_inatomic((void __user *)to, (void *)from_xxx, 1);
+               break;
+       case 2:
+               r = __copy_to_user_inatomic((void __user *)to, (void *)from_xxx, 2);
+               break;
+       case 4:
+               r = __copy_to_user_inatomic((void __user *)to, (void *)from_xxx, 4);
+               break;
+       case 8:
+               r = __copy_to_user_inatomic((void __user *)to, (void *)from_xxx, 8);
+               break;
+       default:
+               r = __copy_to_user_inatomic((void __user *)to, (void *)from_xxx, size);
+               break;
+       }
+       set_fs(oldfs);
+       return r;
+}
+
+int
+kdba_verify_rw(unsigned long addr, size_t size)
+{
+       unsigned char data[(__force size_t) size];
+       return(kdba_getarea_size(data, addr, size) || kdba_putarea_size(addr, data, size));
+}
+
+#ifdef CONFIG_KDB_KDUMP
+void
+kdba_kdump_prepare(struct pt_regs *fixed_regs)
+{
+       int i;
+
+       /* Set on KEXEC bit on all onlinr cpus */
+       for (i = 1; i < NR_CPUS; ++i) {
+               if (!cpu_online(i))
+                       continue;
+
+               KDB_STATE_SET_CPU(KEXEC, i);
+       }
+
+       /* delaying for 5 seconds ... */
+       udelay(5*1000000);
+       machine_crash_shutdown(fixed_regs);
+}
+
+void kdba_kdump_shutdown_slave(struct pt_regs *regs)
+{
+       /* When we entered via KDB_REASON_OOPS, we are not handled by
+        * kdump_init_notifier.
+        */
+       if (kdb_kdump_state != KDB_KDUMP_RESET &&
+           kdb_kdump_reason == KDB_REASON_OOPS) {
+               unw_init_running(kdump_cpu_freeze, NULL);
+       }
+}
+#endif
index 8bdea8e..e30de98 100644 (file)
@@ -259,8 +259,13 @@ start_ap:
        /*
         * Switch into virtual mode:
         */
+#ifdef CONFIG_KDB_HARDWARE_BREAKPOINTS
+#define IA64_PSR_KDB_FLAGS IA64_PSR_DB
+#else
+#define IA64_PSR_KDB_FLAGS 0
+#endif
        movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \
-                 |IA64_PSR_DI)
+                 |IA64_PSR_DI|IA64_PSR_KDB_FLAGS)
        ;;
        mov cr.ipsr=r16
        movl r17=1f
index 7dd96c1..a628738 100644 (file)
 #include <linux/cpumask.h>
 #include <linux/kdebug.h>
 #include <linux/cpu.h>
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>  /* for switch state wrappers */
+#endif /* CONFIG_KDB */
 
 #include <asm/delay.h>
 #include <asm/machvec.h>
@@ -789,6 +793,14 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg)
         */
        ia64_sal_mc_rendez();
 
+#ifdef CONFIG_KDB
+       /* We get here when the MCA monarch has entered and has woken up the
+        * slaves.  Do a KDB rendezvous to meet the monarch cpu.
+        */
+       if (monarch_cpu != -1)
+               KDB_ENTER_SLAVE();
+#endif
+
        NOTIFY_MCA(DIE_MCA_RENDZVOUS_PROCESS, get_irq_regs(), (long)&nd, 1);
 
        /* Wait for the monarch cpu to exit. */
@@ -1326,6 +1338,19 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
                mca_insert_tr(0x2); /*Reload dynamic itrs*/
        }
 
+#ifdef CONFIG_KDB
+       kdb_save_flags();
+       KDB_FLAG_CLEAR(CATASTROPHIC);
+       KDB_FLAG_CLEAR(RECOVERY);
+       if (recover)
+               KDB_FLAG_SET(RECOVERY);
+       else
+               KDB_FLAG_SET(CATASTROPHIC);
+       KDB_FLAG_SET(NOIPI);            /* do not send IPI for MCA/INIT events */
+       KDB_ENTER();
+       kdb_restore_flags();
+#endif /* CONFIG_KDB */
+
        NOTIFY_MCA(DIE_MCA_MONARCH_LEAVE, regs, (long)&nd, 1);
 
        if (atomic_dec_return(&mca_count) > 0) {
@@ -1338,6 +1363,12 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
                        if (cpu_isset(i, mca_cpu)) {
                                monarch_cpu = i;
                                cpu_clear(i, mca_cpu);  /* wake next cpu */
+#ifdef CONFIG_KDB
+                               /*
+                                * No longer a monarch, report in as a slave.
+                                */
+                               KDB_ENTER_SLAVE();
+#endif
                                while (monarch_cpu != -1)
                                        cpu_relax();    /* spin until last cpu leaves */
                                set_curr_task(cpu, previous_current);
@@ -1347,6 +1378,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
                        }
                }
        }
+
        set_curr_task(cpu, previous_current);
        ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
        monarch_cpu = -1;       /* This frees the slaves and previous monarchs */
@@ -1607,6 +1639,11 @@ default_monarch_init_process(struct notifier_block *self, unsigned long val, voi
                }
        }
        printk("\n\n");
+#ifdef CONFIG_KDB
+       KDB_FLAG_SET(NOIPI);            /* do not send IPI for MCA/INIT events */
+       KDB_ENTER();
+       KDB_FLAG_CLEAR(NOIPI);
+#else  /* !CONFIG_KDB */
        if (read_trylock(&tasklist_lock)) {
                do_each_thread (g, t) {
                        printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);
@@ -1614,6 +1651,7 @@ default_monarch_init_process(struct notifier_block *self, unsigned long val, voi
                } while_each_thread (g, t);
                read_unlock(&tasklist_lock);
        }
+#endif /* CONFIG_KDB */
        /* FIXME: This will not restore zapped printk locks. */
        RESTORE_LOGLEVEL(console_loglevel);
        return NOTIFY_DONE;
@@ -1646,6 +1684,20 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
        int cpu = smp_processor_id();
        struct ia64_mca_notify_die nd =
                { .sos = sos, .monarch_cpu = &monarch_cpu };
+#ifdef CONFIG_KDB
+       int kdba_recalcitrant = 0;
+       /* kdba_wait_for_cpus() sends INIT to recalcitrant cpus which ends up
+        * calling this routine.  If KDB is waiting for the IPI to be processed
+        * then treat all INIT events as slaves, kdb_initial_cpu is the
+        * monarch.
+        */
+       if (KDB_STATE(WAIT_IPI)) {
+               monarch_cpu = kdb_initial_cpu;
+               sos->monarch = 0;
+               KDB_STATE_CLEAR(WAIT_IPI);
+               kdba_recalcitrant = 1;
+       }
+#endif /* CONFIG_KDB */
 
        NOTIFY_INIT(DIE_INIT_ENTER, regs, (long)&nd, 0);
 
@@ -1684,6 +1736,11 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
                ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;
                while (monarch_cpu == -1)
                       cpu_relax();     /* spin until monarch enters */
+#ifdef CONFIG_KDB
+               KDB_ENTER_SLAVE();
+               if (kdba_recalcitrant)
+                       monarch_cpu = -1;
+#endif /* CONFIG_KDB */
 
                NOTIFY_INIT(DIE_INIT_SLAVE_ENTER, regs, (long)&nd, 1);
                NOTIFY_INIT(DIE_INIT_SLAVE_PROCESS, regs, (long)&nd, 1);
@@ -1712,6 +1769,14 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
        mprintk("Delaying for 5 seconds...\n");
        udelay(5*1000000);
        ia64_wait_for_slaves(cpu, "INIT");
+
+#ifdef CONFIG_KDB
+       kdb_save_flags();
+       KDB_FLAG_SET(NOIPI);            /* do not send IPI for MCA/INIT events */
+       KDB_ENTER();
+       kdb_restore_flags();
+#endif /* CONFIG_KDB */
+
        /* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through
         * to default_monarch_init_process() above and just print all the
         * tasks.
@@ -1950,6 +2015,13 @@ ia64_mca_init(void)
                        printk(KERN_INFO "Increasing MCA rendezvous timeout from "
                                "%ld to %ld milliseconds\n", timeout, isrv.v0);
                        timeout = isrv.v0;
+#ifdef CONFIG_KDB
+                       /* kdb must wait long enough for the MCA timeout to trip
+                        * and process.  The MCA timeout is in milliseconds.
+                        */
+                       kdb_wait_for_cpus_secs = max(kdb_wait_for_cpus_secs,
+                                               (int)(timeout/1000) + 10);
+#endif /* CONFIG_KDB */
                        NOTIFY_MCA(DIE_MCA_NEW_TIMEOUT, NULL, timeout, 0);
                        continue;
                }
index 3676468..ac71a9a 100644 (file)
 #include <asm/current.h>
 #include <asm/delay.h>
 #include <asm/machvec.h>
+
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
+
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/page.h>
@@ -64,6 +69,9 @@ static DEFINE_PER_CPU(unsigned int, shadow_flush_counts[NR_CPUS]) ____cacheline_
 #define IPI_CPU_STOP           1
 #define IPI_CALL_FUNC_SINGLE   2
 #define IPI_KDUMP_CPU_STOP     3
+#ifdef CONFIG_KDB
+#define IPI_KDB_INTERRUPT      4
+#endif /* CONFIG_KDB */
 
 /* This needs to be cacheline aligned because it is written to by *other* CPUs.  */
 static DEFINE_PER_CPU_SHARED_ALIGNED(u64, ipi_operation);
@@ -124,6 +132,12 @@ handle_IPI (int irq, void *dev_id)
                                unw_init_running(kdump_cpu_freeze, NULL);
                                break;
 #endif
+#ifdef CONFIG_KDB
+                       case IPI_KDB_INTERRUPT:
+                               if (!kdb_ipi(get_irq_regs(), NULL))
+                                       printk(KERN_ERR "kdb_ipi() rejected IPI_KDB_INTERRUPT\n");
+                               break;
+#endif
                        default:
                                printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n",
                                                this_cpu, which);
@@ -335,3 +349,12 @@ setup_profiling_timer (unsigned int multiplier)
 {
        return -EINVAL;
 }
+
+#if defined(CONFIG_KDB)
+void
+smp_kdb_stop(void)
+{
+       if (!KDB_FLAG(NOIPI))
+               send_IPI_allbutself(IPI_KDB_INTERRUPT);
+}
+#endif /* CONFIG_KDB */
index f0cda76..5d13d93 100644 (file)
@@ -13,6 +13,9 @@
 #include <linux/tty.h>
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 #include <linux/module.h>       /* for EXPORT_SYMBOL */
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
 #include <linux/delay.h>               /* for ssleep() */
@@ -78,6 +81,10 @@ die (const char *str, struct pt_regs *regs, long err)
        if (!regs)
                return 1;
 
+#ifdef CONFIG_KDB
+       (void)kdb(KDB_REASON_OOPS, err, regs);
+#endif /* CONFIG_KDB */
+
        if (panic_on_oops)
                panic("Fatal exception");
 
@@ -171,6 +178,17 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
                if (break_num < 0x80000) {
                        sig = SIGILL; code = __ILL_BREAK;
                } else {
+#ifdef CONFIG_KDB
+                       if (break_num == KDB_BREAK_ENTER &&
+                           kdb(KDB_REASON_ENTER, break_num, regs))
+                               return;         /* kdb handled it */
+                       if (break_num == KDB_BREAK_ENTER_SLAVE &&
+                           kdb(KDB_REASON_ENTER_SLAVE, break_num, regs))
+                               return;         /* kdb handled it */
+                       if (break_num == KDB_BREAK_BREAK &&
+                           kdb(KDB_REASON_BREAK, break_num, regs))
+                               return;         /* kdb handled it */
+#endif /* CONFIG_KDB */
                        if (notify_die(DIE_BREAK, "bad break", regs, break_num, TRAP_BRKPT, SIGTRAP)
                                        == NOTIFY_STOP)
                                return;
@@ -565,6 +583,10 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
                if (notify_die(DIE_FAULT, "ia64_fault", &regs, vector, siginfo.si_code, SIGTRAP)
                                == NOTIFY_STOP)
                        return;
+#ifdef CONFIG_KDB
+               if (!user_mode(&regs) && kdb(KDB_REASON_DEBUG, vector, &regs))
+                       return; /* kdb handled this */
+#endif /* CONFIG_KDB */
                siginfo.si_signo = SIGTRAP;
                siginfo.si_errno = 0;
                siginfo.si_addr  = (void __user *) ifa;
index 67810b7..dd61886 100644 (file)
 
 #ifdef UNW_DEBUG
   static unsigned int unw_debug_level = UNW_DEBUG;
-#  define UNW_DEBUG_ON(n)      unw_debug_level >= n
-   /* Do not code a printk level, not all debug lines end in newline */
-#  define UNW_DPRINT(n, ...)  if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
+#  ifdef CONFIG_KDB
+#    include <linux/kdb.h>
+#    include <linux/kdbprivate.h>
+#    define UNW_KMALLOC(s, f)  debug_kmalloc(s, f)
+#    define UNW_KFREE(p)       debug_kfree(p)
+#    define UNW_DEBUG_ON(n)    (unw_debug_level >= n && !KDB_IS_RUNNING())
+#    define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__)
+#  else        /* !CONFIG_KDB */
+#    define UNW_DEBUG_ON(n)    unw_debug_level >= n
+     /* Do not code a printk level, not all debug lines end in newline */
+#    define UNW_DPRINT(n, ...)  if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
+#    define UNW_KMALLOC(s, f)  kmalloc(s, f)
+#    define UNW_KFREE(p)       kfree(p)
+#  endif /* CONFIG_KDB */
 #  undef inline
 #  define inline
 #else /* !UNW_DEBUG */
 #  define UNW_DEBUG_ON(n)  0
 #  define UNW_DPRINT(n, ...)
+#  define UNW_KMALLOC(s, f)    kmalloc(s, f)
+#  define UNW_KFREE(p)         kfree(p)
 #endif /* UNW_DEBUG */
 
 #if UNW_STATS
 # define STAT(x...)
 #endif
 
-#define alloc_reg_state()      kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC)
-#define free_reg_state(usr)    kfree(usr)
-#define alloc_labeled_state()  kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC)
-#define free_labeled_state(usr)        kfree(usr)
+#define alloc_reg_state()      UNW_KMALLOC(sizeof(struct unw_reg_state), GFP_ATOMIC)
+#define free_reg_state(usr)    UNW_KFREE(usr)
+#define alloc_labeled_state()  UNW_KMALLOC(sizeof(struct unw_labeled_state), GFP_ATOMIC)
+#define free_labeled_state(usr)        UNW_KFREE(usr)
 
 typedef unsigned long unw_word;
 typedef unsigned char unw_hash_index_t;
@@ -2092,7 +2105,7 @@ unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned lon
                return NULL;
        }
 
-       table = kmalloc(sizeof(*table), GFP_USER);
+       table = UNW_KMALLOC(sizeof(*table), GFP_USER);
        if (!table)
                return NULL;
 
@@ -2165,7 +2178,7 @@ unw_remove_unwind_table (void *handle)
                write_unlock(&tmp->lock);
        }
 
-       kfree(table);
+       UNW_KFREE(table);
 }
 
 static int __init
@@ -2199,7 +2212,7 @@ create_gate_table (void)
                size += 3*8 + 8 + 8*UNW_LENGTH(*(u64 *) (segbase + entry->info_offset));
        size += 8;      /* reserve space for "end of table" marker */
 
-       unw.gate_table = kmalloc(size, GFP_KERNEL);
+       unw.gate_table = UNW_KMALLOC(size, GFP_KERNEL);
        if (!unw.gate_table) {
                unw.gate_table_size = 0;
                printk(KERN_ERR "%s: unable to create unwind data for gate page!\n", __func__);
index 092f019..7dba4a8 100644 (file)
@@ -301,5 +301,91 @@ config OPTIMIZE_INLINING
 
          If unsure, say N.
 
-endmenu
+config KDB
+       bool "Built-in Kernel Debugger support"
+       depends on DEBUG_KERNEL
+       select KALLSYMS
+       select KALLSYMS_ALL
+       help
+         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 key sequence <escape>KDB on the serial port will cause the
+         kernel debugger to be entered with input from the serial port and
+         output to the serial console.  If unsure, say N.
+
+config KDB_MODULES
+       tristate "KDB modules"
+       depends on KDB
+       help
+         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.
+
+config KDB_OFF
+       bool "KDB off by default"
+       depends on KDB
+       help
+         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.
+
+config KDB_CONTINUE_CATASTROPHIC
+       int "KDB continues after catastrophic errors"
+       depends on KDB
+       default "0"
+       help
+         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_LKCD_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.
+
+config KDB_USB
+       bool "Support for USB Keyboard in KDB (OHCI and/or EHCI only)"
+       depends on KDB && (USB_OHCI_HCD || USB_EHCI_HCD)
+       help
+         If you want to use kdb from USB keyboards then say Y here.  If you
+         say N then kdb can only be used from a PC (AT) keyboard or a serial
+         console.
+
+config KDB_KDUMP
+       bool "Support for Kdump in KDB"
+       depends on KDB
+       select KEXEC
+       default N
+       help
+         If you want to take Kdump kernel vmcore from KDB then say Y here.
+         Of imsire. say N.
 
+endmenu
index f5631da..9b6e3fa 100644 (file)
@@ -171,6 +171,9 @@ ifeq ($(CONFIG_X86_32),y)
 drivers-$(CONFIG_FB) += arch/x86/video/
 endif
 
+# KDB support
+drivers-$(CONFIG_KDB) += arch/x86/kdb/
+
 ####
 # boot loader support. Several targets are kept for legacy purposes
 
diff --git a/arch/x86/kdb/ChangeLog b/arch/x86/kdb/ChangeLog
new file mode 100644 (file)
index 0000000..e8132d3
--- /dev/null
@@ -0,0 +1,214 @@
+2008-08-14 Jay Lan  <jlan@sgi.com>
+
+       * Support 'kdump' command to take a kdump vmcore from KDB,
+           Dan Aloni (da-x@monatomic.org),
+           Jason Xiao (jidong.xiao@gmail.com),
+           Jay Lan (jlan@sgi.com)
+       * kdb-v4.4-2.6.27-rc2-x86-2.
+
+2008-08-06 Jay Lan  <jlan@sgi.com>
+
+       * Fix up the NULL pointer deference issue in ohci_kdb_poll_char,
+         Jason Xiao <jidong.xiao@gmail.com>
+       * Backtrace on x86_64 and i386 were incomplete since 2.6.27-rc2.
+       * kdb-v4.4-2.6.27-rc2-x86-1.
+
+2008-07-18 Jay Lan  <jlan@sgi.com>
+
+       * support Hardware Breakpoint (bph/bpha) commands
+         IA64: Greg Banks <gnb@sgi.com>
+         X86:  Konstantin Baydarov <kbaidarov@ru.mvista.com>
+       * kdb-v4.4-2.6.26-x86-2.
+
+2008-07-14 Jay Lan  <jlan@sgi.com>
+
+        * kdb-v4.4-2.6.26-x86-1.
+
+2008-07-11 Jay Lan  <jlan@sgi.com>
+
+        * New commands and some fixups and enhancements,
+          Joe Korty <joe.korty@ccur.com>
+          John Blackwood <john.blackwood@ccur.com>
+          Jim Houston <jim.houston@ccur.com>
+          - Use the non-sleeping copy_from_user_atomic.
+          - Enhance kdb_cmderror diagnostic output.
+          - Expand the KDB 'duplicate command' error message.
+          - Touch NMI watchdog in various KDB busy-loops.
+          - Support IMB HS20 Blade 8843 platform.
+          - Display exactly which cpus needed an NMI to get them into kdb.
+          - Better document that kdb's 'ps A' command can be used to show
+            _all_ processes and threads
+          - Suppress KDB boottime INFO messages if quiet boot.
+          - Add a KDB breakpoint to the OOPs path.
+          - Add CONFIG_DISCONTIGMEM support to kdbm_memmap.
+          - Extend the KDB task command to handle CONFIG_NUMA fields.
+          - Extend the KDB vm command to support NUMA stuff.
+          - Create the KDB mempolicy command.
+          - Create a pgdat command for KDB.
+          - Fix a hang on boot on some i386 systems.
+        * kdb-v4.4-2.6.26-rc9-x86-1.
+
+2008-06-30 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc8-x86-1.
+
+2008-06-25 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc7-x86-1.
+
+2008-06-06 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc5-x86-1.
+
+2008-05-30 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc4-x86-1.
+
+2008-05-20 Jay Lan  <jlan@sgi.com>
+
+       * Merged <asm-x86/kdb_32.h> and <asm-x86/kdb_64.h> to <asm-x86/kdb.h>.
+       * Merged <asm-x86/kdbprivate_32.h> and <asm-x86/kdbprivate_64.h> to
+         <asm-x86/kdbprivate.h>.
+       * kdb-v4.4-2.6.26-rc3-x86-1.
+
+2008-05-15 Jay Lan  <jlan@sgi.com>
+
+       * Fixed the i386 backtrace problem where KDB failed to find stacks
+         in the kernel space.
+       * kdb-v4.4-2.6.26-rc1-x86-3.
+
+2008-05-14 Jay Lan  <jlan@sgi.com>
+
+       * Fixed a bug that bb_all scans only odd number entries of kallsyms.
+       * kdb-v4.4-2.6.26-rc1-x86-2.
+
+2008-05-13 Jay Lan  <jlan@sgi.com>
+
+       * Known problem: backtrace for i386 is broken since 2.6.25-rc1.
+       * kdb-v4.4-2.6.26-rc1-x86-1.
+
+2008-05-13 Jay Lan  <jlan@sgi.com>
+
+       * Known problem: backtrace for i386 is broken since 2.6.25-rc1.
+       * Fixed a couple of x86_64 problems:
+         - "iret_label" are replaced by "irq_return".
+         - bb1 failure on ia32_sysenter_target() & ia32_cstar_target()
+       * kdb-v4.4-2.6.25-x86-2.
+
+2008-04-17 Jay Lan  <jlan@sgi.com>
+
+       * Known problem: backtrace for i386 is broken since 2.6.25-rc1.
+       * kdb-v4.4-2.6.25-x86-1.
+
+2008-03-19 Jay Lan  <jlan@sgi.com>
+
+       * i386: systenter_entry was replaced with ia32_sysenter_target since
+         2.6.25-rc1, Jay Lan <jlan@sgi.com>
+       * Known problem: backtrace for i386 is broken since 2.6.25-rc1.
+       * kdb-v4.4-2.6.25-rc6-x86-2.
+
+2008-03-16 Jay Lan  <jlan@sgi.com>
+
+       * Known problem: backtrace for i386 is broken since 2.6.25-rc1.
+       * kdb-v4.4-2.6.25-rc6-x86-1.
+
+2008-03-03 Jay Lan  <jlan@sgi.com>
+
+       * Known problem: backtrace for i386 is broken since 2.6.25-rc1.
+       * kdb-v4.4-2.6.25-rc3-x86-1.
+
+2008-02-26 Jay Lan  <jlan@sgi.com>
+
+       * remove 'fastcall' from kdb code.
+       * Known problem: backtrace for i386 is broken since 2.6.25-rc1.
+       * kdb-v4.4-2.6.25-rc2-x86-1.
+
+2008-02-19 Jay Lan  <jlan@sgi.com>
+
+       * Known problem: backtrace for i386 is broken.
+       * kdb-v4.4-2.6.25-rc1-x86-1.
+
+2008-02-01 Jay Lan  <jlan@sgi.com>
+
+       * Backed out USB UHCI support since it caused dropped characters and
+          broke OHCI.
+       * Restored "archkdbcommon" commands for x86. It was lost at the x86
+         merge.
+       * Detecting if the HC was "busy", Aaron Young <ayoung@sgi.com>
+       * kdb-v4.4-2.6.24-x86-2.
+
+2008-01-29 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.24-x86-1.
+
+2008-01-22 Jay Lan  <jlan@sgi.com>
+
+       * USB UHCI kdb support, Konstantin Baydarov <kbaidarov@ru.mvista.com>
+       * kdb-v4.4-2.6.24-rc8-x86-3.
+
+2008-01-18 Jay Lan  <jlan@sgi.com>
+
+       * USB EHCI kdb support,  Aaron Young <ayoung@sgi.com>
+       * kdb-v4.4-2.6.24-rc8-x86-2.
+
+2008-01-18 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.24-rc8-x86-1.
+
+2008-01-09 Jay Lan  <jlan@sgi.com>
+
+       * Merge arch/x86/kdb/kdba_io_64.c and arch/x86/kdb/kdba_io_32.c to
+         arch/x86/kdb/kdba_io.c
+       * Merge arch/x86/kdb/kdba_id_64.c and arch/x86/kdb/kdba_id_32.c to
+         arch/x86/kdb/kdba_id.c
+       * Merge arch/x86/kdb/pc_keyb_64.h and arch/x86/kdb/pc_keyb_32.h to
+         arch/x86/kdb/pc_keyb.h
+       * kdb-v4.4-2.6.24-rc7-x86-2.
+
+2008-01-07 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.24-rc7-x86-1.
+
+2007-12-21 Jay Lan  <jlan@sgi.com>
+
+       * Renamed kdb/kdba_bt_x86.c to arch/x86/kdba_bt.c.
+       * Find gcc options 'no-optimize-sibling-calls' & 'regparm' from
+         $(KBUILD_CFLAGS) in arch/x86/kdb/Makefile_{32,64}. We used to
+         get them from $(CFLAGS).
+       * Default regparm to 3 on x86_32 if not defined.
+       * kdb v4.4-2.6.24-rc6-x86-1.
+
+2007-12-12 Jay Lan  <jlan@sgi.com>
+
+       * Fixed a Makefile_32 error.
+       * kdb v4.4-2.6.24-rc5-x86-1.
+
+2007-12-05 Jay Lan  <jlan@sgi.com>
+
+       * Fixed a 'sysctl table check failed' problem.
+       * kdb v4.4-2.6.24-rc4-x86-1.
+
+2007-11-26 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.24-rc3-x86-1.
+
+2007-11-13 Jay Lan  <jlan@sgi.com>
+
+       * Back ported "New KDB USB interface" from Aaron Young in
+         v4.4-2.6.23-{i386,x86_64}-2 to 2.6.24 kdb patchset.
+       * Fixed a make problem at arch/x86/Makefile_{32,64}.
+       * kdb v4.4-2.6.24-rc2-x86-2.
+
+2007-11-12 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.24-rc2-x86-1.
+
+2007-11-09 Jay Lan  <jlan@sgi.com>
+
+       * Rebase to 2.6.24-rc1 kernel
+       *   - merged kdb-v4.4-2.6.23-i386-1 and kdb-v4.4-2.6.23-x86_64-1
+       *     into kdb-v4.4-2.6.24-rc1-x86-1
+       *   - Fields "done", "sglist_len", and "pid" are removed from
+       *     struct scsi_cmnd. Thus, these fields are no longer displayed
+       *     on "sc" command.
+       * kdb v4.4-2.6.24-rc1-x86-1.
diff --git a/arch/x86/kdb/ChangeLog_32 b/arch/x86/kdb/ChangeLog_32
new file mode 100644 (file)
index 0000000..f193e81
--- /dev/null
@@ -0,0 +1,865 @@
+2007-11-08 Jay Lan  <jlan@sgi.com>
+
+       * New KDB USB interface,  Aaron Young <ayoung@sgi.com>
+       *  1. This patch allows KDB to work with any Host Contoller driver
+       *     and call the correct HC driver poll routine (as long as the
+       *     HC driver provides a .kdb_poll_char routine via it's
+       *     associated hc_driver struct).
+       *  2. Hotplugged keyboards are now recognized by KDB.
+       *  3. Currently KDB can only make use of 1 USB type keyboard.
+       *     New code can handle up to 8 attached keyboards - input is
+       *     multiplexed from all of them while in kdb.
+       * kdb v4.4-2.6.23-common-2.
+
+2007-10-24 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-i386-1.
+
+2007-09-26 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc8-i386-1.
+
+2007-09-21 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc7-i386-1.
+
+2007-09-12 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc6-i386-1.
+
+2007-09-06 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc5-i386-1.
+
+2007-08-30 Keith Owens  <kaos@sgi.com>
+
+       * New i386/x86_64 backtrace requires that kdb_save_running() does not
+         exit until after kdb_main_loop() has completed.
+       * kdb v4.4-2.6.23-rc4-i386-2.
+
+2007-08-30 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc4-i386-1.
+
+2007-08-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.23-rc3-i386-1.
+
+2007-08-07 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc2-i386-1.
+
+2007-07-31 Keith Owens  <kaos@sgi.com>
+
+       * Delete obsolete kdba_bt.c.
+       * kdb v4.4-2.6.23-rc1-i386-2.
+
+2007-07-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.23-rc1-i386-1.
+
+2007-07-26 Keith Owens  <kaos@sgi.com>
+
+       * New x86 backtrace code.
+       * kdb v4.4-2.6.22-i386-2.
+
+2007-07-09 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-i386-1.
+
+2007-07-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc7-i386-1.
+
+2007-06-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc5-i386-1.
+
+2007-06-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc4-i386-1.
+
+2007-05-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc3-i386-1.
+
+2007-05-22 Keith Owens  <kaos@sgi.com>
+
+       * Register KDBENTER_VECTOR early on the boot cpu.
+       * kdb v4.4-2.6.22-rc2-i386-2.
+
+2007-05-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc2-i386-1.
+
+2007-05-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc1-i386-1.
+
+2007-05-17 Keith Owens  <kaos@sgi.com>
+
+       * Update dumpregs comments for rdmsr and wrmsr commands.
+         Bernardo Innocenti.
+       * kdb v4.4-2.6.21-i386-3.
+
+2007-05-15 Keith Owens  <kaos@sgi.com>
+
+       * Change kdba_late_init to kdba_arch_init so KDB_ENTER() can be used
+         earlier.
+       * kdb v4.4-2.6.21-i386-2.
+
+2007-04-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-i386-1.
+
+2007-04-16 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc7-i386-1.
+
+2007-04-10 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc6-i386-1.
+
+2007-04-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc5-i386-1.
+
+2007-03-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc4-i386-1.
+
+2007-03-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc3-i386-1.
+
+2007-03-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc2-i386-1.
+
+2007-03-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc1-i386-1.
+
+2007-03-01 Keith Owens  <kaos@sgi.com>
+
+       * Remove sparse warnings.
+       * kdb v4.4-2.6.20-i386-3.
+
+2007-02-16 Keith Owens  <kaos@sgi.com>
+
+       * Initialise variable bits of struct disassemble_info each time.
+       * kdb v4.4-2.6.20-i386-2.
+
+2007-02-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-i386-1.
+
+2007-02-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc7-i386-1.
+
+2007-01-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc4-i386-1.
+
+2007-01-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc3-i386-1.
+
+2006-12-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc1-i386-1.
+
+2006-11-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-i386-1.
+
+2006-11-27 Keith Owens  <kaos@sgi.com>
+
+       * Only use VT keyboard if the command line allows it and ACPI indicates
+         that there is an i8042.
+       * kdb v4.4-2.6.19-rc6-i386-2.
+
+2006-11-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc6-i386-1.
+
+2006-11-09 Keith Owens  <kaos@sgi.com>
+
+       * Change kdb() to fastcall.
+       * Add unwind info to kdb_call().  Steve Lord.
+       * Only use VT console if the command line allows it.
+       * kdb v4.4-2.6.19-rc5-i386-2.
+
+2006-11-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc5-i386-1.
+
+2006-11-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc4-i386-1.
+
+2006-10-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc3-i386-1.
+
+2006-10-24 Keith Owens  <kaos@sgi.com>
+
+       * Remove redundant regs and envp parameters.
+       * kdb v4.4-2.6.19-rc2-i386-2.
+
+2006-10-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc2-i386-1.
+
+2006-10-11 Keith Owens  <kaos@sgi.com>
+
+       * Move kdbm_x86.c from the i386 to the common KDB patch.
+       * Make the KDBENTER_VECTOR an interrupt gate instead of a trap gate, it
+         simplifies the code and disables interrupts on KDBENTER().
+       * Exclude the KDBENTER_VECTOR from irq assignment.
+       * kdb v4.4-2.6.19-rc1-i386-2.
+
+2006-10-09 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc1-i386-1.
+
+2006-10-06 Keith Owens  <kaos@sgi.com>
+
+       * Remove #include <linux/config.h>
+       * kdb v4.4-2.6.18-i386-2.
+
+2006-09-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-i386-1.
+
+2006-09-15 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc7-i386-1.
+
+2006-08-30 Keith Owens  <kaos@sgi.com>
+
+       * Add warning for problems when following alternate stacks.
+       * kdb v4.4-2.6.18-rc5-i386-3.
+
+2006-08-29 Keith Owens  <kaos@sgi.com>
+
+       * Rewrite all backtrace code.
+       * kdb v4.4-2.6.18-rc5-i386-2.
+
+2006-08-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc5-i386-1.
+
+2006-08-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc4-i386-1.
+
+2006-08-04 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc3-i386-1.
+
+2006-07-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc2-i386-1.
+
+2006-07-12 Keith Owens  <kaos@sgi.com>
+
+       * Remove dead KDB_REASON codes.
+       * sparse cleanups.
+       * kdb v4.4-2.6.18-rc1-i386-2.
+
+2006-07-07 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc1-i386-1.
+
+2006-07-04 Keith Owens  <kaos@sgi.com>
+
+       * Make KDB rendezvous on i386 a two stage approach.
+       * Clean up generation of KDB interrupt code.
+       * Move smp_kdb_stop() and smp_kdb_interrupt() to kdbasupport.c.
+       * Move setting of interrupt traps to kdbasupport.c.
+       * Remove KDB hooks from arch/i386/kernel smp.c, smpboot.c, i8259.c,
+         io_apic.c.
+       * Add KDB_REASON_CPU_UP support.
+       * Move per cpu setup to kdba_cpu_up().
+       * Rework support for 4K stacks to make backtrace more accurate.
+       * Add BTSP option to get the full backtrace, including kdb routines.
+       * Delete kdba_enable_mce, architectures now do their own setup.
+       * Delete kdba_enable_lbr, kdba_disable_lbr, kdba_print_lbr,
+         page_fault_mca.  Only ever implemented on x86, difficult to maintain
+         and rarely used in the field.
+       * Replace #ifdef KDB_HAVE_LONGJMP with #ifdef kdba_setjmp.
+       * kdb v4.4-2.6.17-i386-2.
+
+2006-06-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-i386-1.
+
+2006-05-25 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc5-i386-1.
+
+2006-05-15 Keith Owens  <kaos@sgi.com>
+
+       * Refresh bfd related files from binutils 2.16.91.0.2.
+       * kdb v4.4-2.6.17-rc4-i386-2.
+
+2006-05-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc4-i386-1.
+
+2006-04-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc3-i386-1.
+
+2006-04-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc2-i386-1.
+
+2006-04-11 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc1-i386-1.
+
+2006-03-30 Keith Owens  <kaos@sgi.com>
+
+       * Change CONFIG_LKCD to CONFIG_LKCD_DUMP.
+       * kdb v4.4-2.6.16-i386-3.
+
+2006-03-24 Keith Owens  <kaos@sgi.com>
+
+       * Define a dummy kdba_wait_for_cpus().
+       * kdb v4.4-2.6.16-i386-2.
+
+2006-03-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.16-i386-1.
+
+2006-03-14 Nathan Scott  <nathans@sgi.com>
+
+       * kdb v4.4-2.6.16-rc6-i386-1.
+
+2006-02-28 Nathan Scott  <nathans@sgi.com>
+
+       * kdb v4.4-2.6.16-rc5-i386-1.
+
+2006-02-20 Nathan Scott  <nathans@sgi.com>
+
+       * kdb v4.4-2.6.16-rc4-i386-1.
+
+2006-02-06 Keith Owens  <kaos@sgi.com>
+
+       * Change CONFIG_CRASH_DUMP to CONFIG_LKCD.
+       * kdb v4.4-2.6.16-rc2-i386-2.
+
+2006-02-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.16-rc2-i386-1.
+
+2006-01-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.16-rc1-i386-1.
+
+2006-01-08 Keith Owens  <kaos@sgi.com>
+
+       * Add DIE_KDEBUG_ENTER and DIE_KDEBUG_LEAVE to notify_die.
+       * kdb v4.4-2.6.15-i386-2.
+
+2006-01-04 Keith Owens  <kaos@sgi.com>
+
+       * Remove some inlines and the last vestige of CONFIG_NUMA_REPLICATE.
+       * Read the keyboard acknowledgment after sending a character.  SuSE
+         Bugzilla 60240.
+       * kdb v4.4-2.6.15-i386-1.
+
+2005-12-25 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc7-i386-1.
+
+2005-12-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc6-i386-1.
+
+2005-12-05 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc5-i386-1.
+
+2005-12-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc4-i386-1.
+
+2005-11-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc3-i386-1.
+
+2005-11-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc2-i386-1.
+
+2005-11-15 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc1-i386-1.
+
+2005-10-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.14-i386-1.
+
+2005-10-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.14-rc5-i386-1.
+
+2005-10-11 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.14-rc4-i386-1.
+
+2005-10-04 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.14-rc3-i386-1.
+
+2005-09-21 Keith Owens  <kaos@sgi.com>
+
+       * Support kdb_current_task in register display and modify commands.
+       * kdb v4.4-2.6.14-rc2-i386-1.
+
+2005-09-20 Keith Owens  <kaos@sgi.com>
+
+       * Remove use of __STDC_VERSION__ in ansidecl.h.
+       * kdb v4.4-2.6.14-rc1-i386-1.
+
+2005-08-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-i386-1.
+
+2005-08-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc7-i386-1.
+
+2005-08-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc6-i386-1.
+
+2005-08-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc5-i386-1.
+
+2005-07-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc4-i386-1.
+
+2005-07-22 Keith Owens  <kaos@sgi.com>
+
+       * Compile fix for kprobes.
+       * kdb v4.4-2.6.13-rc3-i386-2.
+
+2005-07-19 Keith Owens  <kaos@sgi.com>
+
+       * Add support for USB keyboard (OHCI only).  Aaron Young, SGI.
+       * kdb v4.4-2.6.13-rc3-i386-1.
+
+2005-07-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc2-i386-1.
+
+2005-07-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc1-i386-1.
+
+2005-06-19 Keith Owens  <kaos@sgi.com>
+
+       * gcc 4 compile fix, remove extern kdb_hardbreaks.  Steve Lord.
+       * kdb v4.4-2.6.12-i386-2.
+
+2005-06-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-i386-1.
+
+2005-06-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc6-i386-1.
+
+2005-05-25 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc5-i386-1.
+
+2005-05-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc4-i386-1.
+
+2005-04-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc3-i386-1.
+
+2005-04-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc2-i386-1.
+
+2005-03-29 Keith Owens  <kaos@sgi.com>
+
+       * Replace __copy_to_user with __copy_to_user_inatomic.
+       * kdb v4.4-2.6.12-rc1-i386-1.
+
+2005-03-08 Keith Owens  <kaos@sgi.com>
+
+       * Coexistence patches for lkcd.
+       * kdb v4.4-2.6.11-i386-2.
+
+2005-03-03 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.11-i386-1.
+
+2005-02-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.11-rc4-i386-1.
+
+2005-02-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.11-rc3-bk4-i386-1.
+
+2005-02-03 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.11-rc3-i386-1.
+
+2005-01-27 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.11-rc2-i386-1.
+
+2005-01-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.11-rc1-i386-1.
+
+2004-12-25 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.10-i386-1.
+
+2004-12-07 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.10-rc3-i386-1.
+
+2004-11-23 Keith Owens  <kaos@sgi.com>
+
+       * Coexist with asmlinkage/fastcall changes.
+       * kdb v4.4-2.6.10-rc2-i386-1.
+
+2004-10-29 Keith Owens  <kaos@sgi.com>
+
+       * Handle change defintions for hard and soft irq context.
+       * Make stack switch in kdb backtrace look more like the oops output.
+       * kdb v4.4-2.6.10-rc1-i386-1.
+
+2004-10-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.9-i386-1.
+
+2004-10-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.9-rc4-i386-1.
+
+2004-10-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.9-rc3-i386-1.
+
+2004-09-30 Keith Owens  <kaos@sgi.com>
+
+       * Add stackdepth command.
+       * Handle backtrace with separate soft and hard irq stacks
+         (CONFIG_4KSTACKS).
+       * Work around RESTORE_ALL macro, which can only be used once.
+       * Export kdba_dumpregs.  Bryan Cardillo, UPenn.
+       * kdb v4.4-2.6.9-rc2-i386-2.
+
+2004-09-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.9-rc2-i386-1.
+
+2004-08-27 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.9-rc1-i386-1.
+
+2004-08-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.8-i386-1.
+
+2004-08-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.8-rc4-i386-1.
+
+2004-08-04 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.8-rc3-i386-1.
+
+2004-07-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.8-rc2-i386-1.
+
+2004-07-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.8-rc1-i386-1.
+
+2004-06-16 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.7-i386-1.
+
+2004-06-10 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.7-rc3-i386-1.
+
+2004-06-09 Keith Owens  <kaos@sgi.com>
+
+       * Namespace clean up.  Mark code/variables as static when it is only
+         used in one file, delete dead code/variables.
+       * kdb v4.4-2.6.7-rc2-i386-3.
+
+2004-06-08 Keith Owens  <kaos@sgi.com>
+
+       * Whitespace clean up, no code changes.
+       * kdb v4.4-2.6.7-rc2-i386-2.
+
+2004-06-07 Keith Owens  <kaos@sgi.com>
+
+       * Force KALLSYMS and KALLSYMS_ALL for CONFIG_KDB.
+       * kdb v4.4-2.6.7-rc2-i386-1.
+
+2004-06-06 Keith Owens  <kaos@sgi.com>
+
+       * Correct Kconfig help text.
+       * Coexist with CONFIG_REGPARM.
+       * Add standard archkdb commands.
+       * Move kdb_{get,put}userarea_size definitions to linux/kdb.h.
+       * kdb v4.4-2.6.6-i386-2.
+
+2004-05-23 Keith Owens  <kaos@sgi.com>
+
+       * Move bfd.h and ansidecl.h from arch/$(ARCH)/kdb to include/asm-$(ARCH).
+       * Update copyright notices.
+       * kdb v4.4-2.6.6-i386-1.
+
+2004-05-10 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.6-i386-1.
+
+2004-05-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.6-rc3-i386-1.
+
+2004-05-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.6-rc2-i386-1.
+
+2004-04-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.6-rc1-i386-1.
+
+2004-04-05 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6-5-i386-1.
+
+2004-02-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6-4-rc1-i386-1.
+
+2004-02-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6-3-i386-1.
+
+2004-02-17 Keith Owens  <kaos@sgi.com>
+
+       * Pick up changes from Jim Houston for 2.6.
+       * Sync with kdb v4.3-2.4.25-rc1-i386-1.
+       * Adjust for LDT changes in i386 mainline.
+       * Convert longjmp buffers from static to dynamic allocation, for large
+         cpu counts.
+       * Do not use USB keyboard if it has not been probed.
+       * Do not print section data, 2.6 kallsyms does not support sections :(.
+       * kdb v4.3-2.6-3-rc3-i386-1.
+
+2003-08-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.4.22-i386-1.
+
+2003-08-05 Keith Owens  <kaos@sgi.com>
+
+       * Remove duplicate setting of trap for machine_check.
+       * Only reset keyboard when CONFIG_VT_CONSOLE is defined.
+
+2003-07-27 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.4.22-pre8-i386-5.
+
+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 --git a/arch/x86/kdb/ChangeLog_64 b/arch/x86/kdb/ChangeLog_64
new file mode 100644 (file)
index 0000000..49fd438
--- /dev/null
@@ -0,0 +1,447 @@
+2007-11-08 Jay Lan  <jlan@sgi.com>
+
+       * New KDB USB interface,  Aaron Young <ayoung@sgi.com>
+       *  1. This patch allows KDB to work with any Host Contoller driver
+       *     and call the correct HC driver poll routine (as long as the
+       *     HC driver provides a .kdb_poll_char routine via it's
+       *     associated hc_driver struct).
+       *  2. Hotplugged keyboards are now recognized by KDB.
+       *  3. Currently KDB can only make use of 1 USB type keyboard.
+       *     New code can handle up to 8 attached keyboards - input is
+       *     multiplexed from all of them while in kdb.
+       * kdb v4.4-2.6.23-common-2.
+
+2007-10-24 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-x86_64-1.
+
+2007-09-26 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc8-x86_64-1.
+
+2007-09-21 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc7-x86_64-1.
+
+2007-09-12 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc6-x86_64-1.
+
+2007-09-06 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc5-x86_64-1.
+
+2007-08-30 Keith Owens  <kaos@sgi.com>
+
+       * New i386/x86_64 backtrace requires that kdb_save_running() does not
+         exit until after kdb_main_loop() has completed.
+       * kdb v4.4-2.6.23-rc4-x86_64-2.
+
+2007-08-30 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc4-x86_64-1.
+
+2007-08-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.23-rc3-x86_64-1.
+
+2007-08-07 Jay Lan  <jlan@sgi.com>
+
+       * v4.4-2.6.23-rc2-x86_64-1.
+
+2007-07-31 Keith Owens  <kaos@sgi.com>
+
+       * Delete obsolete kdba_bt.c.
+       * kdb v4.4-2.6.23-rc1-x86_64-2.
+
+2007-07-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.23-rc1-x86_64-1.
+
+2007-07-26 Keith Owens  <kaos@sgi.com>
+
+       * New x86 backtrace code.
+       * kdb v4.4-2.6.22-x86_64-2.
+
+2007-07-09 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-x86_64-1.
+
+2007-07-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc7-x86_64-1.
+
+2007-06-25 Keith Owens  <kaos@sgi.com>
+
+       * Hook into DIE_NMIWATCHDOG.
+       * kdb v4.4-2.6.22-rc5-x86_64-2.
+
+2007-06-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc5-x86_64-1.
+
+2007-06-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc4-x86_64-1.
+
+2007-05-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc3-x86_64-1.
+
+2007-05-22 Keith Owens  <kaos@sgi.com>
+
+       * Register KDBENTER_VECTOR early on the boot cpu.
+       * kdb v4.4-2.6.22-rc2-x86_64-2.
+
+2007-05-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc2-x86_64-1.
+
+2007-05-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc1-x86_64-1.
+
+2007-05-17 Keith Owens  <kaos@sgi.com>
+
+       * Update dumpregs comments for rdmsr and wrmsr commands.
+         Bernardo Innocenti.
+       * kdb v4.4-2.6.21-x86_64-3.
+
+2007-05-15 Keith Owens  <kaos@sgi.com>
+
+       * Change kdba_late_init to kdba_arch_init so KDB_ENTER() can be used
+         earlier.
+       * kdb v4.4-2.6.21-x86_64-2.
+
+2007-04-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-x86_64-1.
+
+2007-04-16 Keith Owens  <kaos@sgi.com>
+
+       * Select KALLSYMS and KALLSYMS_ALL when KDB is selected.
+       * kdb v4.4-2.6.21-rc7-x86_64-2.
+
+2007-04-16 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc7-x86_64-1.
+
+2007-04-10 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc6-x86_64-1.
+
+2007-04-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc5-x86_64-1.
+
+2007-03-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc4-x86_64-1.
+
+2007-03-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc3-x86_64-1.
+
+2007-03-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc2-x86_64-1.
+
+2007-03-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc1-x86_64-1.
+
+2007-03-01 Keith Owens  <kaos@sgi.com>
+
+       * Remove sparse warnings.
+       * kdb v4.4-2.6.20-x86_64-3.
+
+2007-02-16 Keith Owens  <kaos@sgi.com>
+
+       * Initialise variable bits of struct disassemble_info each time.
+       * kdb v4.4-2.6.20-x86_64-2.
+
+2007-02-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-x86_64-1.
+
+2007-02-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc7-x86_64-1.
+
+2007-01-10 Keith Owens  <kaos@sgi.com>
+
+       * Correct setjmp for the FRAME_POINTER=y case.
+       * Remove duplicate longjmp code for FRAME_POINTER=n/y.
+       * kdb v4.4-2.6.20-rc4-x86_64-2.
+
+2007-01-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc4-x86_64-1.
+
+2007-01-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc3-x86_64-1.
+
+2006-12-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc1-x86_64-1.
+
+2006-12-07 Keith Owens  <kaos@sgi.com>
+
+       * Export kdba_dumpregs.
+       * kdb v4.4-2.6.19-x86_64-2.
+
+2006-11-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-x86_64-1.
+
+2006-11-27 Keith Owens  <kaos@sgi.com>
+
+       * Only use VT keyboard if the command line allows it and ACPI indicates
+         that there is an i8042.
+       * kdb v4.4-2.6.19-rc6-x86_64-2.
+
+2006-11-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc6-x86_64-1.
+
+2006-11-09 Keith Owens  <kaos@sgi.com>
+
+       * Only use VT console if the command line allows it.
+       * kdb v4.4-2.6.19-rc5-x86_64-2.
+
+2006-11-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc5-x86_64-1.
+
+2006-11-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc4-x86_64-1.
+
+2006-10-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc3-x86_64-1.
+
+2006-10-24 Keith Owens  <kaos@sgi.com>
+
+       * Remove redundant regs and envp parameters.
+       * kdb v4.4-2.6.19-rc2-x86_64-2.
+
+2006-10-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc2-x86_64-1.
+
+2006-10-11 Keith Owens  <kaos@sgi.com>
+
+       * Make the KDBENTER_VECTOR an interrupt gate instead of a trap gate, it
+         simplifies the code and disables interrupts on KDB_ENTER().
+       * Exclude the KDBENTER_VECTOR from irq assignment.
+       * Enable KDB_ENTER() again.
+       * kdb v4.4-2.6.19-rc1-x86_64-2.
+
+2006-10-09 Keith Owens  <kaos@sgi.com>
+
+       * KDB_ENTER() is getting spurious activations on some x86_64 hardware.
+         Deactivate KDB_ENTER() until it is fixed.
+       * kdb v4.4-2.6.19-rc1-x86_64-1.
+
+2006-10-06 Keith Owens  <kaos@sgi.com>
+
+       * Remove #include <linux/config.h>
+       * kdb v4.4-2.6.18-x86_64-2.
+
+2006-09-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-x86_64-1.
+
+2006-09-15 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc7-x86_64-1.
+
+2006-08-30 Keith Owens  <kaos@sgi.com>
+
+       * Do not print debugstackptr in cpu_pda, it will be deleted soon.
+       * Add KDB_ENTER().
+       * Add warning for problems when following alternate stacks.
+       * kdb v4.4-2.6.18-rc5-x86_64-3.
+
+2006-08-29 Keith Owens  <kaos@sgi.com>
+
+       * Rewrite all backtrace code.
+       * Add pt_regs and cpu_pda commands.
+       * Include patch to define orig_ist, to be removed once that patch is in
+         the community tree.
+       * kdb v4.4-2.6.18-rc5-x86_64-2.
+
+2006-08-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc5-x86_64-1.
+
+2006-08-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc4-x86_64-1.
+
+2006-08-04 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc3-x86_64-1.
+
+2006-07-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc2-x86_64-1.
+
+2006-07-12 Keith Owens  <kaos@sgi.com>
+
+       * sparse cleanups
+       * kdb v4.4-2.6.18-rc1-x86_64-2.
+
+2006-07-07 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc1-x86_64-1.
+
+2006-07-04 Keith Owens  <kaos@sgi.com>
+
+       * Make KDB rendezvous on x86_64 a two stage approach.
+       * Move smp_kdb_stop() and smp_kdb_interrupt() to kdbasupport.c.
+       * Move setting of interrupt traps to kdbasupport.c.
+       * Add KDB_REASON_CPU_UP support.
+       * Move per cpu setup to kdba_cpu_up().
+       * Delete kdba_enable_mce, architectures now do their own setup.
+       * Delete kdba_enable_lbr, kdba_disable_lbr, kdba_print_lbr,
+         page_fault_mca.  Only ever implemented on x86, difficult to maintain
+         and rarely used in the field.
+       * Replace #ifdef KDB_HAVE_LONGJMP with #ifdef kdba_setjmp.
+       * kdb v4.4-2.6.17-x86_64-2.
+
+2006-06-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-x86_64-1.
+
+2006-05-31 Keith Owens  <kaos@sgi.com>
+
+       * Define arch/x86_64/kdb/kdb_cmds.
+       * kdb v4.4-2.6.17-rc5-x86_64-2.
+
+2006-05-25 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc5-x86_64-1.
+
+2006-05-15 Keith Owens  <kaos@sgi.com>
+
+       * Refresh bfd related files from binutils 2.16.91.0.2.
+       * kdb v4.4-2.6.17-rc4-x86_64-2.
+
+2006-05-12 Keith Owens <kaos@sgi.com>
+
+       * kdb v4.4-2.6-17-rc4-x86_64-1.
+
+2006-04-22 Keith Owens <kaos@sgi.com>
+
+       * kdb v4.4-2.6-17-rc2-x86_64-1.
+
+2006-04-13 Keith Owens <kaos@sgi.com>
+
+       * Remove trailing white space.
+       * kdb v4.4-2.6-17-rc1-x86_64-1.
+
+2006-03-25 Jack F. Vogel <jfv@bluesong.net>
+       * Sync with Keith's changes for 2.6.16
+       * code from Andi Kleen to support above
+
+2005-09-30 Jack F. Vogel <jfv@bluesong.net>
+       * Port to 2.6.14-rc2
+       * sync with a couple changes from Keith
+       * Add backtrace code from Jim Houston
+         (thanks Jim)
+
+2005-08-31 Jack F. Vogel <jfv@bluesong.net>
+       * Change to linker script for kexec
+         thanks to Steven Dake <sdake@mvista.com>
+
+2005-08-30 Jack F. Vogel <jfv@bluesong.net>
+       * Notify struct should not be devinit
+         thanks IWAMOTO Toshihiro <iwamoto@valinux.co.jp>
+
+2005-08-25 Jack F. Vogel <jfv@bluesong.net>
+       * Update to 2.6.11
+       * Fix to synchronize with the notify changes
+         thanks to Jim Houston.
+
+2004-09-30 Keith Owens <kaos@sgi.com>
+       * Port to 2.6.9-rc2
+       * Fix line editting characters.  Jim Houston, Comcast.
+       * kdb v4.4-2.6.9-rc2-x86-64-1.
+
+2004-08-15 Jack F. Vogel <jfv@bluesong.net>
+       * Port to 2.6.8
+       * tighten up the code, using the built-in
+         die_chain notify interface, thanks to
+         Andi Kleen for pointing this out.
+
+2004-05-15 Jack F. Vogel <jfv@bluesong.net>
+       * port to 2.6.6 for x86_64
+
+2003-12-15 Cliff Neighbors <cliff@fabric7.com>
+       * initial port from i386 to x86_64
+
+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.
+
diff --git a/arch/x86/kdb/Makefile b/arch/x86/kdb/Makefile
new file mode 100644 (file)
index 0000000..3817a0b
--- /dev/null
@@ -0,0 +1,5 @@
+ifeq ($(CONFIG_X86_32),y)
+include ${srctree}/arch/x86/kdb/Makefile_32
+else
+include ${srctree}/arch/x86/kdb/Makefile_64
+endif
diff --git a/arch/x86/kdb/Makefile_32 b/arch/x86/kdb/Makefile_32
new file mode 100644 (file)
index 0000000..e1ca8f6
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+#
+
+obj-$(CONFIG_KDB)      := kdba_bp_32.o kdbasupport_32.o i386-dis.o
+
+# The i386 and x86_64 backtrace commands are handled by common code.
+obj-y          += kdba_bt.o kdba_io.o kdba_id.o kdba_support.o
+ifneq (,$(findstring -fno-optimize-sibling-calls,$(KBUILD_CFLAGS)))
+  CFLAGS_kdba_bt.o += -DNO_SIBLINGS
+endif
+REGPARM := $(subst -mregparm=,,$(filter -mregparm=%,$(KBUILD_CFLAGS)))
+ifeq (,$(REGPARM))
+  REGPARM := 3
+endif
+
+CFLAGS_kdba_bt.o += -DREGPARM=$(REGPARM) -DCCVERSION="$(CCVERSION)"
+
+override CFLAGS := $(CFLAGS:%-pg=% )
+
+CFLAGS_kdba_io.o += -I $(TOPDIR)/arch/$(SRCARCH)/kdb
diff --git a/arch/x86/kdb/Makefile_64 b/arch/x86/kdb/Makefile_64
new file mode 100644 (file)
index 0000000..248cbf4
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+#
+
+obj-$(CONFIG_KDB)      := kdba_bp_64.o kdbasupport_64.o x86_64-dis.o
+
+# The i386 and x86_64 backtrace commands are handled by common code.
+obj-y          += kdba_bt.o kdba_io.o kdba_id.o kdba_support.o
+ifneq (,$(findstring -fno-optimize-sibling-calls,$(KBUILD_CFLAGS)))
+  CFLAGS_kdba_bt.o += -DNO_SIBLINGS
+endif
+REGPARM := $(subst -mregparm=,,$(filter -mregparm=%,$(KBUILD_CFLAGS)))
+ifeq (,$(REGPARM))
+  REGPARM := 6
+endif
+
+CFLAGS_kdba_bt.o += -DREGPARM=$(REGPARM) -DCCVERSION="$(CCVERSION)"
+
+override CFLAGS := $(CFLAGS:%-pg=% )
+
+CFLAGS_kdba_io.o += -I $(TOPDIR)/arch/$(SRCARCH)/kdb
diff --git a/arch/x86/kdb/i386-dis.c b/arch/x86/kdb/i386-dis.c
new file mode 100644 (file)
index 0000000..78ba637
--- /dev/null
@@ -0,0 +1,4686 @@
+/* Print i386 instructions for GDB, the GNU debugger.
+   Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+/* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+   July 1988
+    modified by John Hassey (hassey@dg-rtp.dg.com)
+    x86-64 support added by Jan Hubicka (jh@suse.cz)
+    VIA PadLock support by Michal Ludvig (mludvig@suse.cz).  */
+
+/* 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>
+#define abort() BUG()
+#else  /* __KERNEL__ */
+#include "dis-asm.h"
+#include "sysdep.h"
+#include "opintl.h"
+#endif /* __KERNEL__ */
+
+#define MAXLEN 20
+
+#ifndef __KERNEL__
+#include <setjmp.h>
+#endif /* __KERNEL__ */
+
+#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 (struct disassemble_info *, bfd_byte *);
+static void ckprefix (void);
+static const char *prefix_name (int, int);
+static int print_insn (bfd_vma, disassemble_info *);
+static void dofloat (int);
+static void OP_ST (int, int);
+static void OP_STi (int, int);
+static int putop (const char *, int);
+static void oappend (const char *);
+static void append_seg (void);
+static void OP_indirE (int, int);
+static void print_operand_value (char *, int, bfd_vma);
+static void OP_E (int, int);
+static void OP_G (int, int);
+static bfd_vma get64 (void);
+static bfd_signed_vma get32 (void);
+static bfd_signed_vma get32s (void);
+static int get16 (void);
+static void set_op (bfd_vma, int);
+static void OP_REG (int, int);
+static void OP_IMREG (int, int);
+static void OP_I (int, int);
+static void OP_I64 (int, int);
+static void OP_sI (int, int);
+static void OP_J (int, int);
+static void OP_SEG (int, int);
+static void OP_DIR (int, int);
+static void OP_OFF (int, int);
+static void OP_OFF64 (int, int);
+static void ptr_reg (int, int);
+static void OP_ESreg (int, int);
+static void OP_DSreg (int, int);
+static void OP_C (int, int);
+static void OP_D (int, int);
+static void OP_T (int, int);
+static void OP_Rd (int, int);
+static void OP_MMX (int, int);
+static void OP_XMM (int, int);
+static void OP_EM (int, int);
+static void OP_EX (int, int);
+static void OP_MS (int, int);
+static void OP_XS (int, int);
+static void OP_M (int, int);
+static void OP_VMX (int, int);
+static void OP_0fae (int, int);
+static void OP_0f07 (int, int);
+static void NOP_Fixup (int, int);
+static void OP_3DNowSuffix (int, int);
+static void OP_SIMD_Suffix (int, int);
+static void SIMD_Fixup (int, int);
+static void PNI_Fixup (int, int);
+static void SVME_Fixup (int, int);
+static void INVLPG_Fixup (int, int);
+static void BadOp (void);
+static void SEG_Fixup (int, int);
+static void VMX_Fixup (int, int);
+
+struct dis_private {
+  /* Points to first byte not fetched.  */
+  bfd_byte *max_fetched;
+  bfd_byte the_buffer[MAXLEN];
+  bfd_vma insn_start;
+  int orig_sizeflag;
+#ifndef __KERNEL__
+  jmp_buf bailout;
+#endif /* __KERNEL__ */
+};
+
+/* The opcode for the fwait instruction, which we treat as a prefix
+   when we can.  */
+#define FWAIT_OPCODE (0x9b)
+
+/* Set to 1 for 64bit mode disassembly.  */
+static int mode_64bit;
+
+/* Flags for the prefixes for the current instruction.  See below.  */
+static int prefixes;
+
+/* REX prefix the current instruction.  See below.  */
+static int rex;
+/* Bits of REX we've already used.  */
+static int rex_used;
+#define REX_MODE64     8
+#define REX_EXTX       4
+#define REX_EXTY       2
+#define REX_EXTZ       1
+/* Mark parts used in the REX prefix.  When we are testing for
+   empty prefix (for 8bit register REX extension), just mask it
+   out.  Otherwise test for REX bit is excuse for existence of REX
+   only in case value is nonzero.  */
+#define USED_REX(value)                                        \
+  {                                                    \
+    if (value)                                         \
+      rex_used |= (rex & value) ? (value) | 0x40 : 0;  \
+    else                                               \
+      rex_used |= 0x40;                                        \
+  }
+
+/* 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 (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  /* __KERNEL__ */
+       /* XXX - what to do? */
+       kdb_printf("Hmm. longjmp.\n");
+#endif /* __KERNEL__ */
+    }
+  else
+    priv->max_fetched = addr;
+  return 1;
+}
+
+#define XX NULL, 0
+
+#define Eb OP_E, b_mode
+#define Ev OP_E, v_mode
+#define Ed OP_E, d_mode
+#define Eq OP_E, q_mode
+#define Edq OP_E, dq_mode
+#define Edqw OP_E, dqw_mode
+#define indirEv OP_indirE, branch_v_mode
+#define indirEp OP_indirE, f_mode
+#define Em OP_E, m_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_M, 0              /* lea, lgdt, etc. */
+#define Mp OP_M, f_mode                /* 32 or 48 bit memory operand for LDS, LES etc */
+#define Gb OP_G, b_mode
+#define Gv OP_G, v_mode
+#define Gd OP_G, d_mode
+#define Gdq OP_G, dq_mode
+#define Gm OP_G, m_mode
+#define Gw OP_G, w_mode
+#define Rd OP_Rd, d_mode
+#define Rm OP_Rd, m_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode      /* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iq OP_I, q_mode
+#define Iv64 OP_I64, v_mode
+#define Iw OP_I, w_mode
+#define I1 OP_I, const_1_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#define Cm OP_C, m_mode
+#define Dm OP_D, m_mode
+#define Td OP_T, d_mode
+#define Sv SEG_Fixup, v_mode
+
+#define RMeAX OP_REG, eAX_reg
+#define RMeBX OP_REG, eBX_reg
+#define RMeCX OP_REG, eCX_reg
+#define RMeDX OP_REG, eDX_reg
+#define RMeSP OP_REG, eSP_reg
+#define RMeBP OP_REG, eBP_reg
+#define RMeSI OP_REG, eSI_reg
+#define RMeDI OP_REG, eDI_reg
+#define RMrAX OP_REG, rAX_reg
+#define RMrBX OP_REG, rBX_reg
+#define RMrCX OP_REG, rCX_reg
+#define RMrDX OP_REG, rDX_reg
+#define RMrSP OP_REG, rSP_reg
+#define RMrBP OP_REG, rBP_reg
+#define RMrSI OP_REG, rSI_reg
+#define RMrDI OP_REG, rDI_reg
+#define RMAL OP_REG, al_reg
+#define RMAL OP_REG, al_reg
+#define RMCL OP_REG, cl_reg
+#define RMDL OP_REG, dl_reg
+#define RMBL OP_REG, bl_reg
+#define RMAH OP_REG, ah_reg
+#define RMCH OP_REG, ch_reg
+#define RMDH OP_REG, dh_reg
+#define RMBH OP_REG, bh_reg
+#define RMAX OP_REG, ax_reg
+#define RMDX OP_REG, dx_reg
+
+#define eAX OP_IMREG, eAX_reg
+#define eBX OP_IMREG, eBX_reg
+#define eCX OP_IMREG, eCX_reg
+#define eDX OP_IMREG, eDX_reg
+#define eSP OP_IMREG, eSP_reg
+#define eBP OP_IMREG, eBP_reg
+#define eSI OP_IMREG, eSI_reg
+#define eDI OP_IMREG, eDI_reg
+#define AL OP_IMREG, al_reg
+#define AL OP_IMREG, al_reg
+#define CL OP_IMREG, cl_reg
+#define DL OP_IMREG, dl_reg
+#define BL OP_IMREG, bl_reg
+#define AH OP_IMREG, ah_reg
+#define CH OP_IMREG, ch_reg
+#define DH OP_IMREG, dh_reg
+#define BH OP_IMREG, bh_reg
+#define AX OP_IMREG, ax_reg
+#define DX OP_IMREG, dx_reg
+#define indirDX OP_IMREG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, 0
+#define Ob OP_OFF, b_mode
+#define Ob64 OP_OFF64, b_mode
+#define Ov OP_OFF, v_mode
+#define Ov64 OP_OFF64, 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 XS OP_XS, v_mode
+#define VM OP_VMX, q_mode
+#define OPSUF OP_3DNowSuffix, 0
+#define OPSIMD OP_SIMD_Suffix, 0
+
+#define cond_jump_flag NULL, cond_jump_mode
+#define loop_jcxz_flag NULL, loop_jcxz_mode
+
+/* bits in sizeflag */
+#define SUFFIX_ALWAYS 4
+#define AFLAG 2
+#define DFLAG 1
+
+#define b_mode 1  /* byte operand */
+#define v_mode 2  /* operand size depends on prefixes */
+#define w_mode 3  /* word operand */
+#define d_mode 4  /* double word operand  */
+#define q_mode 5  /* quad word operand */
+#define t_mode 6  /* ten-byte operand */
+#define x_mode 7  /* 16-byte XMM operand */
+#define m_mode 8  /* d_mode in 32bit, q_mode in 64bit mode.  */
+#define cond_jump_mode 9
+#define loop_jcxz_mode 10
+#define dq_mode 11 /* operand size depends on REX prefixes.  */
+#define dqw_mode 12 /* registers like dq_mode, memory like w_mode.  */
+#define f_mode 13 /* 4- or 6-byte pointer operand */
+#define const_1_mode 14
+#define branch_v_mode 15 /* v_mode for branch.  */
+
+#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 rAX_reg 132
+#define rCX_reg 133
+#define rDX_reg 134
+#define rBX_reg 135
+#define rSP_reg 136
+#define rBP_reg 137
+#define rSI_reg 138
+#define rDI_reg 139
+
+#define indir_dx_reg 150
+
+#define FLOATCODE 1
+#define USE_GROUPS 2
+#define USE_PREFIX_USER_TABLE 3
+#define X86_64_SPECIAL 4
+
+#define FLOAT    NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
+
+#define GRP1b    NULL, NULL, USE_GROUPS, NULL,  0, NULL, 0
+#define GRP1S    NULL, NULL, USE_GROUPS, NULL,  1, NULL, 0
+#define GRP1Ss   NULL, NULL, USE_GROUPS, NULL,  2, NULL, 0
+#define GRP2b    NULL, NULL, USE_GROUPS, NULL,  3, NULL, 0
+#define GRP2S    NULL, NULL, USE_GROUPS, NULL,  4, NULL, 0
+#define GRP2b_one NULL, NULL, USE_GROUPS, NULL,  5, NULL, 0
+#define GRP2S_one NULL, NULL, USE_GROUPS, NULL,  6, NULL, 0
+#define GRP2b_cl  NULL, NULL, USE_GROUPS, NULL,  7, NULL, 0
+#define GRP2S_cl  NULL, NULL, USE_GROUPS, NULL,  8, NULL, 0
+#define GRP3b    NULL, NULL, USE_GROUPS, NULL,  9, NULL, 0
+#define GRP3S    NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0
+#define GRP4     NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0
+#define GRP5     NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0
+#define GRP6     NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0
+#define GRP7     NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0
+#define GRP8     NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0
+#define GRP9     NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0
+#define GRP10    NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0
+#define GRP11    NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0
+#define GRP12    NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0
+#define GRP13    NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0
+#define GRP14    NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0
+#define GRPAMD   NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0
+#define GRPPADLCK1 NULL, NULL, USE_GROUPS, NULL, 23, NULL, 0
+#define GRPPADLCK2 NULL, NULL, USE_GROUPS, NULL, 24, NULL, 0
+
+#define PREGRP0   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  0, NULL, 0
+#define PREGRP1   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  1, NULL, 0
+#define PREGRP2   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  2, NULL, 0
+#define PREGRP3   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  3, NULL, 0
+#define PREGRP4   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  4, NULL, 0
+#define PREGRP5   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  5, NULL, 0
+#define PREGRP6   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  6, NULL, 0
+#define PREGRP7   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  7, NULL, 0
+#define PREGRP8   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  8, NULL, 0
+#define PREGRP9   NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  9, NULL, 0
+#define PREGRP10  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0
+#define PREGRP11  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0
+#define PREGRP12  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0
+#define PREGRP13  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0
+#define PREGRP14  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0
+#define PREGRP15  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0
+#define PREGRP16  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0
+#define PREGRP17  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0
+#define PREGRP18  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0
+#define PREGRP19  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0
+#define PREGRP20  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0
+#define PREGRP21  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0
+#define PREGRP22  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0
+#define PREGRP23  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0
+#define PREGRP24  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0
+#define PREGRP25  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0
+#define PREGRP26  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0
+#define PREGRP27  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 27, NULL, 0
+#define PREGRP28  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 28, NULL, 0
+#define PREGRP29  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 29, NULL, 0
+#define PREGRP30  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 30, NULL, 0
+#define PREGRP31  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 31, NULL, 0
+#define PREGRP32  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 32, NULL, 0
+
+#define X86_64_0  NULL, NULL, X86_64_SPECIAL, NULL,  0, NULL, 0
+
+typedef void (*op_rtn) (int bytemode, int sizeflag);
+
+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
+   'C' => print 's' or 'l' ('w' or 'd' in Intel mode) depending on operand
+   .      size prefix
+   'E' => print 'e' if 32-bit form of jcxz
+   'F' => print 'w' or 'l' depending on address size prefix (loop insns)
+   'H' => print ",pt" or ",pn" branch hint
+   'I' => honor following macro letter even in Intel mode (implemented only
+   .      for some of the macro letters)
+   'J' => print 'l'
+   'L' => print 'l' if suffix_always is true
+   'N' => print 'n' if instruction has no wait "prefix"
+   'O' => print 'd', or 'o'
+   'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
+   .      or suffix_always is true.  print 'q' if rex prefix is present.
+   'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
+   .      is true
+   'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode)
+   'S' => print 'w', 'l' or 'q' if suffix_always is true
+   'T' => print 'q' in 64bit mode and behave as 'P' otherwise
+   'U' => print 'q' in 64bit mode and behave as 'Q' otherwise
+   'W' => print 'b' or 'w' ("w" or "de" in intel mode)
+   'X' => print 's', 'd' depending on data16 prefix (for XMM)
+   'Y' => 'q' if instruction has an REX 64bit overwrite prefix
+
+   Many of the above letters print nothing in Intel mode.  See "putop"
+   for the details.
+
+   Braces '{' and '}', and vertical bars '|', indicate alternative
+   mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel
+   modes.  In cases where there are only two alternatives, the X86_64
+   instruction is reserved, and "(bad)" is printed.
+*/
+
+static const struct dis386 dis386[] = {
+  /* 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 },
+  { "push{T|}",                es, XX, XX },
+  { "pop{T|}",         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 },
+  { "push{T|}",                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 },
+  { "push{T|}",                ss, XX, XX },
+  { "popT|}",          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 },
+  { "push{T|}",                ds, XX, XX },
+  { "pop{T|}",         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 */
+  { "inc{S|}",         RMeAX, XX, XX },
+  { "inc{S|}",         RMeCX, XX, XX },
+  { "inc{S|}",         RMeDX, XX, XX },
+  { "inc{S|}",         RMeBX, XX, XX },
+  { "inc{S|}",         RMeSP, XX, XX },
+  { "inc{S|}",         RMeBP, XX, XX },
+  { "inc{S|}",         RMeSI, XX, XX },
+  { "inc{S|}",         RMeDI, XX, XX },
+  /* 48 */
+  { "dec{S|}",         RMeAX, XX, XX },
+  { "dec{S|}",         RMeCX, XX, XX },
+  { "dec{S|}",         RMeDX, XX, XX },
+  { "dec{S|}",         RMeBX, XX, XX },
+  { "dec{S|}",         RMeSP, XX, XX },
+  { "dec{S|}",         RMeBP, XX, XX },
+  { "dec{S|}",         RMeSI, XX, XX },
+  { "dec{S|}",         RMeDI, XX, XX },
+  /* 50 */
+  { "pushS",           RMrAX, XX, XX },
+  { "pushS",           RMrCX, XX, XX },
+  { "pushS",           RMrDX, XX, XX },
+  { "pushS",           RMrBX, XX, XX },
+  { "pushS",           RMrSP, XX, XX },
+  { "pushS",           RMrBP, XX, XX },
+  { "pushS",           RMrSI, XX, XX },
+  { "pushS",           RMrDI, XX, XX },
+  /* 58 */
+  { "popS",            RMrAX, XX, XX },
+  { "popS",            RMrCX, XX, XX },
+  { "popS",            RMrDX, XX, XX },
+  { "popS",            RMrBX, XX, XX },
+  { "popS",            RMrSP, XX, XX },
+  { "popS",            RMrBP, XX, XX },
+  { "popS",            RMrSI, XX, XX },
+  { "popS",            RMrDI, XX, XX },
+  /* 60 */
+  { "pusha{P|}",       XX, XX, XX },
+  { "popa{P|}",                XX, XX, XX },
+  { "bound{S|}",       Gv, Ma, XX },
+  { X86_64_0 },
+  { "(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 */
+  { "pushT",           Iq, XX, XX },
+  { "imulS",           Gv, Ev, Iv },
+  { "pushT",           sIb, XX, XX },
+  { "imulS",           Gv, Ev, sIb },
+  { "ins{b||b|}",      Yb, indirDX, XX },
+  { "ins{R||R|}",      Yv, indirDX, XX },
+  { "outs{b||b|}",     indirDX, Xb, XX },
+  { "outs{R||R|}",     indirDX, Xv, XX },
+  /* 70 */
+  { "joH",             Jb, XX, cond_jump_flag },
+  { "jnoH",            Jb, XX, cond_jump_flag },
+  { "jbH",             Jb, XX, cond_jump_flag },
+  { "jaeH",            Jb, XX, cond_jump_flag },
+  { "jeH",             Jb, XX, cond_jump_flag },
+  { "jneH",            Jb, XX, cond_jump_flag },
+  { "jbeH",            Jb, XX, cond_jump_flag },
+  { "jaH",             Jb, XX, cond_jump_flag },
+  /* 78 */
+  { "jsH",             Jb, XX, cond_jump_flag },
+  { "jnsH",            Jb, XX, cond_jump_flag },
+  { "jpH",             Jb, XX, cond_jump_flag },
+  { "jnpH",            Jb, XX, cond_jump_flag },
+  { "jlH",             Jb, XX, cond_jump_flag },
+  { "jgeH",            Jb, XX, cond_jump_flag },
+  { "jleH",            Jb, XX, cond_jump_flag },
+  { "jgH",             Jb, XX, cond_jump_flag },
+  /* 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",            Sv, Sw, XX },
+  { "leaS",            Gv, M, XX },
+  { "movQ",            Sw, Sv, XX },
+  { "popU",            Ev, XX, XX },
+  /* 90 */
+  { "nop",             NOP_Fixup, 0, XX, XX },
+  { "xchgS",           RMeCX, eAX, XX },
+  { "xchgS",           RMeDX, eAX, XX },
+  { "xchgS",           RMeBX, eAX, XX },
+  { "xchgS",           RMeSP, eAX, XX },
+  { "xchgS",           RMeBP, eAX, XX },
+  { "xchgS",           RMeSI, eAX, XX },
+  { "xchgS",           RMeDI, eAX, XX },
+  /* 98 */
+  { "cW{tR||tR|}",     XX, XX, XX },
+  { "cR{tO||tO|}",     XX, XX, XX },
+  { "Jcall{T|}",       Ap, XX, XX },
+  { "(bad)",           XX, XX, XX },   /* fwait */
+  { "pushfT",          XX, XX, XX },
+  { "popfT",           XX, XX, XX },
+  { "sahf{|}",         XX, XX, XX },
+  { "lahf{|}",         XX, XX, XX },
+  /* a0 */
+  { "movB",            AL, Ob64, XX },
+  { "movS",            eAX, Ov64, XX },
+  { "movB",            Ob64, AL, XX },
+  { "movS",            Ov64, eAX, XX },
+  { "movs{b||b|}",     Yb, Xb, XX },
+  { "movs{R||R|}",     Yv, Xv, XX },
+  { "cmps{b||b|}",     Xb, Yb, XX },
+  { "cmps{R||R|}",     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",            RMAL, Ib, XX },
+  { "movB",            RMCL, Ib, XX },
+  { "movB",            RMDL, Ib, XX },
+  { "movB",            RMBL, Ib, XX },
+  { "movB",            RMAH, Ib, XX },
+  { "movB",            RMCH, Ib, XX },
+  { "movB",            RMDH, Ib, XX },
+  { "movB",            RMBH, Ib, XX },
+  /* b8 */
+  { "movS",            RMeAX, Iv64, XX },
+  { "movS",            RMeCX, Iv64, XX },
+  { "movS",            RMeDX, Iv64, XX },
+  { "movS",            RMeBX, Iv64, XX },
+  { "movS",            RMeSP, Iv64, XX },
+  { "movS",            RMeBP, Iv64, XX },
+  { "movS",            RMeSI, Iv64, XX },
+  { "movS",            RMeDI, Iv64, XX },
+  /* c0 */
+  { GRP2b },
+  { GRP2S },
+  { "retT",            Iw, XX, XX },
+  { "retT",            XX, XX, XX },
+  { "les{S|}",         Gv, Mp, XX },
+  { "ldsS",            Gv, Mp, XX },
+  { "movA",            Eb, Ib, XX },
+  { "movQ",            Ev, Iv, XX },
+  /* c8 */
+  { "enterT",          Iw, Ib, XX },
+  { "leaveT",          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 */
+  { "loopneFH",                Jb, XX, loop_jcxz_flag },
+  { "loopeFH",         Jb, XX, loop_jcxz_flag },
+  { "loopFH",          Jb, XX, loop_jcxz_flag },
+  { "jEcxzH",          Jb, XX, loop_jcxz_flag },
+  { "inB",             AL, Ib, XX },
+  { "inS",             eAX, Ib, XX },
+  { "outB",            Ib, AL, XX },
+  { "outS",            Ib, eAX, XX },
+  /* e8 */
+  { "callT",           Jv, XX, XX },
+  { "jmpT",            Jv, XX, XX },
+  { "Jjmp{T|}",                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 */
+  { "icebp",           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[] = {
+  /* 00 */
+  { GRP6 },
+  { GRP7 },
+  { "larS",            Gv, Ew, XX },
+  { "lslS",            Gv, Ew, XX },
+  { "(bad)",           XX, XX, XX },
+  { "syscall",         XX, XX, XX },
+  { "clts",            XX, XX, XX },
+  { "sysretP",         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 },
+  { PREGRP30 },
+  { "movlpX",          EX, XM, SIMD_Fixup, 'h' },
+  { "unpcklpX",                XM, EX, XX },
+  { "unpckhpX",                XM, EX, XX },
+  { PREGRP31 },
+  { "movhpX",          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 */
+  { "movL",            Rm, Cm, XX },
+  { "movL",            Rm, Dm, XX },
+  { "movL",            Cm, Rm, XX },
+  { "movL",            Dm, Rm, XX },
+  { "movL",            Rd, Td, XX },
+  { "(bad)",           XX, XX, XX },
+  { "movL",            Td, Rd, XX },
+  { "(bad)",           XX, XX, XX },
+  /* 28 */
+  { "movapX",          XM, EX, XX },
+  { "movapX",          EX, XM, XX },
+  { PREGRP2 },
+  { "movntpX",         Ev, XM, XX },
+  { PREGRP4 },
+  { PREGRP3 },
+  { "ucomisX",         XM,EX, XX },
+  { "comisX",          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 */
+  { "movmskpX",                Gdq, XS, XX },
+  { PREGRP13 },
+  { PREGRP12 },
+  { PREGRP11 },
+  { "andpX",           XM, EX, XX },
+  { "andnpX",          XM, EX, XX },
+  { "orpX",            XM, EX, XX },
+  { "xorpX",           XM, EX, XX },
+  /* 58 */
+  { PREGRP0 },
+  { PREGRP10 },
+  { PREGRP17 },
+  { PREGRP16 },
+  { 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 },
+  { PREGRP26 },
+  { PREGRP24 },
+  { "movd",            MX, Edq, XX },
+  { PREGRP19 },
+  /* 70 */
+  { PREGRP22 },
+  { GRP10 },
+  { GRP11 },
+  { GRP12 },
+  { "pcmpeqb",         MX, EM, XX },
+  { "pcmpeqw",         MX, EM, XX },
+  { "pcmpeqd",         MX, EM, XX },
+  { "emms",            XX, XX, XX },
+  /* 78 */
+  { "vmread",          Em, Gm, XX },
+  { "vmwrite",         Gm, Em, XX },
+  { "(bad)",           XX, XX, XX },
+  { "(bad)",           XX, XX, XX },
+  { PREGRP28 },
+  { PREGRP29 },
+  { PREGRP23 },
+  { PREGRP20 },
+  /* 80 */
+  { "joH",             Jv, XX, cond_jump_flag },
+  { "jnoH",            Jv, XX, cond_jump_flag },
+  { "jbH",             Jv, XX, cond_jump_flag },
+  { "jaeH",            Jv, XX, cond_jump_flag },
+  { "jeH",             Jv, XX, cond_jump_flag },
+  { "jneH",            Jv, XX, cond_jump_flag },
+  { "jbeH",            Jv, XX, cond_jump_flag },
+  { "jaH",             Jv, XX, cond_jump_flag },
+  /* 88 */
+  { "jsH",             Jv, XX, cond_jump_flag },
+  { "jnsH",            Jv, XX, cond_jump_flag },
+  { "jpH",             Jv, XX, cond_jump_flag },
+  { "jnpH",            Jv, XX, cond_jump_flag },
+  { "jlH",             Jv, XX, cond_jump_flag },
+  { "jgeH",            Jv, XX, cond_jump_flag },
+  { "jleH",            Jv, XX, cond_jump_flag },
+  { "jgH",             Jv, XX, cond_jump_flag },
+  /* 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 */
+  { "pushT",           fs, XX, XX },
+  { "popT",            fs, XX, XX },
+  { "cpuid",           XX, XX, XX },
+  { "btS",             Ev, Gv, XX },
+  { "shldS",           Ev, Gv, Ib },
+  { "shldS",           Ev, Gv, CL },
+  { GRPPADLCK2 },
+  { GRPPADLCK1 },
+  /* a8 */
+  { "pushT",           gs, XX, XX },
+  { "popT",            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 },
+  { "movz{bR|x|bR|x}", Gv, Eb, XX },
+  { "movz{wR|x|wR|x}", 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 },
+  { "movs{bR|x|bR|x}", Gv, Eb, XX },
+  { "movs{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movsww ! */
+  /* c0 */
+  { "xaddB",           Eb, Gb, XX },
+  { "xaddS",           Ev, Gv, XX },
+  { PREGRP1 },
+  { "movntiS",         Ev, Gv, XX },
+  { "pinsrw",          MX, Edqw, Ib },
+  { "pextrw",          Gdq, MS, Ib },
+  { "shufpX",          XM, EX, Ib },
+  { GRP9 },
+  /* c8 */
+  { "bswap",           RMeAX, XX, XX },
+  { "bswap",           RMeCX, XX, XX },
+  { "bswap",           RMeDX, XX, XX },
+  { "bswap",           RMeBX, XX, XX },
+  { "bswap",           RMeSP, XX, XX },
+  { "bswap",           RMeBP, XX, XX },
+  { "bswap",           RMeSI, XX, XX },
+  { "bswap",           RMeDI, XX, XX },
+  /* d0 */
+  { PREGRP27 },
+  { "psrlw",           MX, EM, XX },
+  { "psrld",           MX, EM, XX },
+  { "psrlq",           MX, EM, XX },
+  { "paddq",           MX, EM, XX },
+  { "pmullw",          MX, EM, XX },
+  { PREGRP21 },
+  { "pmovmskb",                Gdq, MS, 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 },
+  { PREGRP15 },
+  { PREGRP25 },
+  /* 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 */
+  { PREGRP32 },
+  { "psllw",           MX, EM, XX },
+  { "pslld",           MX, EM, XX },
+  { "psllq",           MX, EM, XX },
+  { "pmuludq",         MX, EM, XX },
+  { "pmaddwd",         MX, EM, XX },
+  { "psadbw",          MX, EM, XX },
+  { PREGRP18 },
+  /* f8 */
+  { "psubb",           MX, EM, XX },
+  { "psubw",           MX, EM, XX },
+  { "psubd",           MX, EM, XX },
+  { "psubq",           MX, EM, 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,0,1,0,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,1,1,1,1,1,1, /* 5f */
+  /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
+  /* 70 */ 1,1,1,1,1,1,1,0,1,1,0,0,1,1,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 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
+  /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
+  /* f0 */ 1,1,1,1,1,1,1,1,1,1,1,1,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_SSE_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,1,0,0,0,1,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,1,1,1,1,1,1, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */
+  /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, /* 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 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 1,0,0,0,0,0,0,1,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 unsigned char need_modrm;
+
+/* If we are accessing mod/rm/reg without need_modrm set, then the
+   values are stale.  Hitting this abort likely indicates that you
+   need to update onebyte_has_modrm or twobyte_has_modrm.  */
+#define MODRM_CHECK  if (!need_modrm) abort ()
+
+static const char **names64;
+static const char **names32;
+static const char **names16;
+static const char **names8;
+static const char **names8rex;
+static const char **names_seg;
+static const char **index16;
+
+static const char *intel_names64[] = {
+  "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+};
+static const char *intel_names32[] = {
+  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
+  "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
+};
+static const char *intel_names16[] = {
+  "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
+  "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
+};
+static const char *intel_names8[] = {
+  "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
+};
+static const char *intel_names8rex[] = {
+  "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
+  "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
+};
+static const char *intel_names_seg[] = {
+  "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
+};
+static const char *intel_index16[] = {
+  "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
+};
+
+static const char *att_names64[] = {
+  "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
+  "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+};
+static const char *att_names32[] = {
+  "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
+  "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
+};
+static const char *att_names16[] = {
+  "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
+  "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
+};
+static const char *att_names8[] = {
+  "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
+};
+static const char *att_names8rex[] = {
+  "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
+  "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
+};
+static const char *att_names_seg[] = {
+  "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?",
+};
+static const char *att_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, I1, XX },
+    { "rorA",  Eb, I1, XX },
+    { "rclA",  Eb, I1, XX },
+    { "rcrA",  Eb, I1, XX },
+    { "shlA",  Eb, I1, XX },
+    { "shrA",  Eb, I1, XX },
+    { "(bad)", XX, XX, XX },
+    { "sarA",  Eb, I1, XX },
+  },
+  /* GRP2S_one */
+  {
+    { "rolQ",  Ev, I1, XX },
+    { "rorQ",  Ev, I1, XX },
+    { "rclQ",  Ev, I1, XX },
+    { "rcrQ",  Ev, I1, XX },
+    { "shlQ",  Ev, I1, XX },
+    { "shrQ",  Ev, I1, XX },
+    { "(bad)", XX, XX, XX},
+    { "sarQ",  Ev, I1, 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 },
+    { "mulA",  Eb, XX, XX },   /* Don't print the implicit %al register,  */
+    { "imulA", Eb, XX, XX },   /* to distinguish these opcodes from other */
+    { "divA",  Eb, XX, XX },   /* mul/imul opcodes.  Do the same for div  */
+    { "idivA", Eb, XX, XX }    /* and idiv for consistency.               */
+  },
+  /* GRP3S */
+  {
+    { "testQ", Ev, Iv, XX },
+    { "(bad)", XX, XX, XX },
+    { "notQ",  Ev, XX, XX },
+    { "negQ",  Ev, XX, XX },
+    { "mulQ",  Ev, XX, XX },   /* Don't print the implicit register.  */
+    { "imulQ", Ev, XX, XX },
+    { "divQ",  Ev, XX, XX },
+    { "idivQ", Ev, XX, 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 },
+    { "callT", indirEv, XX, XX },
+    { "JcallT",        indirEp, XX, XX },
+    { "jmpT",  indirEv, XX, XX },
+    { "JjmpT", indirEp, XX, XX },
+    { "pushU", Ev, XX, XX },
+    { "(bad)", XX, XX, XX },
+  },
+  /* GRP6 */
+  {
+    { "sldtQ", Ev, XX, XX },
+    { "strQ",  Ev, 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 */
+  {
+    { "sgdtIQ", VMX_Fixup, 0, XX, XX },
+    { "sidtIQ", PNI_Fixup, 0, XX, XX },
+    { "lgdt{Q|Q||}",    M, XX, XX },
+    { "lidt{Q|Q||}",    SVME_Fixup, 0, XX, XX },
+    { "smswQ", Ev, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "lmsw",  Ew, XX, XX },
+    { "invlpg",        INVLPG_Fixup, w_mode, 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", Eq, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "",      VM, XX, XX },           /* See OP_VMX.  */
+    { "vmptrst", Eq, 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 },
+    { "psrldq",        MS, Ib, XX },
+    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "psllq", MS, Ib, XX },
+    { "pslldq",        MS, Ib, XX },
+  },
+  /* GRP13 */
+  {
+    { "fxsave", Ev, XX, XX },
+    { "fxrstor", Ev, XX, XX },
+    { "ldmxcsr", Ev, XX, XX },
+    { "stmxcsr", Ev, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "lfence", OP_0fae, 0, XX, XX },
+    { "mfence", OP_0fae, 0, XX, XX },
+    { "clflush", OP_0fae, 0, 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 },
+  },
+  /* GRPPADLCK1 */
+  {
+    { "xstore-rng", OP_0f07, 0, XX, XX },
+    { "xcrypt-ecb", OP_0f07, 0, XX, XX },
+    { "xcrypt-cbc", OP_0f07, 0, XX, XX },
+    { "xcrypt-ctr", OP_0f07, 0, XX, XX },
+    { "xcrypt-cfb", OP_0f07, 0, XX, XX },
+    { "xcrypt-ofb", OP_0f07, 0, XX, XX },
+    { "(bad)", OP_0f07, 0, XX, XX },
+    { "(bad)", OP_0f07, 0, XX, XX },
+  },
+  /* GRPPADLCK2 */
+  {
+    { "montmul", OP_0f07, 0, XX, XX },
+    { "xsha1",   OP_0f07, 0, XX, XX },
+    { "xsha256", OP_0f07, 0, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX },
+    { "(bad)",   OP_0f07, 0, XX, XX },
+    { "(bad)",   OP_0f07, 0, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX },
+  }
+};
+
+static const struct dis386 prefix_user_table[][4] = {
+  /* PREGRP0 */
+  {
+    { "addps", XM, EX, XX },
+    { "addss", XM, EX, XX },
+    { "addpd", XM, EX, XX },
+    { "addsd", XM, EX, XX },
+  },
+  /* PREGRP1 */
+  {
+    { "", XM, EX, OPSIMD },    /* See OP_SIMD_SUFFIX.  */
+    { "", XM, EX, OPSIMD },
+    { "", XM, EX, OPSIMD },
+    { "", XM, EX, OPSIMD },
+  },
+  /* PREGRP2 */
+  {
+    { "cvtpi2ps", XM, EM, XX },
+    { "cvtsi2ssY", XM, Ev, XX },
+    { "cvtpi2pd", XM, EM, XX },
+    { "cvtsi2sdY", XM, Ev, XX },
+  },
+  /* PREGRP3 */
+  {
+    { "cvtps2pi", MX, EX, XX },
+    { "cvtss2siY", Gv, EX, XX },
+    { "cvtpd2pi", MX, EX, XX },
+    { "cvtsd2siY", Gv, EX, XX },
+  },
+  /* PREGRP4 */
+  {
+    { "cvttps2pi", MX, EX, XX },
+    { "cvttss2siY", Gv, EX, XX },
+    { "cvttpd2pi", MX, EX, XX },
+    { "cvttsd2siY", Gv, EX, XX },
+  },
+  /* PREGRP5 */
+  {
+    { "divps", XM, EX, XX },
+    { "divss", XM, EX, XX },
+    { "divpd", XM, EX, XX },
+    { "divsd", XM, EX, XX },
+  },
+  /* PREGRP6 */
+  {
+    { "maxps", XM, EX, XX },
+    { "maxss", XM, EX, XX },
+    { "maxpd", XM, EX, XX },
+    { "maxsd", XM, EX, XX },
+  },
+  /* PREGRP7 */
+  {
+    { "minps", XM, EX, XX },
+    { "minss", XM, EX, XX },
+    { "minpd", XM, EX, XX },
+    { "minsd", XM, EX, XX },
+  },
+  /* PREGRP8 */
+  {
+    { "movups", XM, EX, XX },
+    { "movss", XM, EX, XX },
+    { "movupd", XM, EX, XX },
+    { "movsd", XM, EX, XX },
+  },
+  /* PREGRP9 */
+  {
+    { "movups", EX, XM, XX },
+    { "movss", EX, XM, XX },
+    { "movupd", EX, XM, XX },
+    { "movsd", EX, XM, XX },
+  },
+  /* PREGRP10 */
+  {
+    { "mulps", XM, EX, XX },
+    { "mulss", XM, EX, XX },
+    { "mulpd", XM, EX, XX },
+    { "mulsd", XM, EX, XX },
+  },
+  /* PREGRP11 */
+  {
+    { "rcpps", XM, EX, XX },
+    { "rcpss", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP12 */
+  {
+    { "rsqrtps", XM, EX, XX },
+    { "rsqrtss", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP13 */
+  {
+    { "sqrtps", XM, EX, XX },
+    { "sqrtss", XM, EX, XX },
+    { "sqrtpd", XM, EX, XX },
+    { "sqrtsd", XM, EX, XX },
+  },
+  /* PREGRP14 */
+  {
+    { "subps", XM, EX, XX },
+    { "subss", XM, EX, XX },
+    { "subpd", XM, EX, XX },
+    { "subsd", XM, EX, XX },
+  },
+  /* PREGRP15 */
+  {
+    { "(bad)", XM, EX, XX },
+    { "cvtdq2pd", XM, EX, XX },
+    { "cvttpd2dq", XM, EX, XX },
+    { "cvtpd2dq", XM, EX, XX },
+  },
+  /* PREGRP16 */
+  {
+    { "cvtdq2ps", XM, EX, XX },
+    { "cvttps2dq",XM, EX, XX },
+    { "cvtps2dq",XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP17 */
+  {
+    { "cvtps2pd", XM, EX, XX },
+    { "cvtss2sd", XM, EX, XX },
+    { "cvtpd2ps", XM, EX, XX },
+    { "cvtsd2ss", XM, EX, XX },
+  },
+  /* PREGRP18 */
+  {
+    { "maskmovq", MX, MS, XX },
+    { "(bad)", XM, EX, XX },
+    { "maskmovdqu", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP19 */
+  {
+    { "movq", MX, EM, XX },
+    { "movdqu", XM, EX, XX },
+    { "movdqa", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP20 */
+  {
+    { "movq", EM, MX, XX },
+    { "movdqu", EX, XM, XX },
+    { "movdqa", EX, XM, XX },
+    { "(bad)", EX, XM, XX },
+  },
+  /* PREGRP21 */
+  {
+    { "(bad)", EX, XM, XX },
+    { "movq2dq", XM, MS, XX },
+    { "movq", EX, XM, XX },
+    { "movdq2q", MX, XS, XX },
+  },
+  /* PREGRP22 */
+  {
+    { "pshufw", MX, EM, Ib },
+    { "pshufhw", XM, EX, Ib },
+    { "pshufd", XM, EX, Ib },
+    { "pshuflw", XM, EX, Ib },
+  },
+  /* PREGRP23 */
+  {
+    { "movd", Edq, MX, XX },
+    { "movq", XM, EX, XX },
+    { "movd", Edq, XM, XX },
+    { "(bad)", Ed, XM, XX },
+  },
+  /* PREGRP24 */
+  {
+    { "(bad)", MX, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "punpckhqdq", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP25 */
+  {
+    { "movntq", EM, MX, XX },
+    { "(bad)", EM, XM, XX },
+    { "movntdq", EM, XM, XX },
+    { "(bad)", EM, XM, XX },
+  },
+  /* PREGRP26 */
+  {
+    { "(bad)", MX, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "punpcklqdq", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP27 */
+  {
+    { "(bad)", MX, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "addsubpd", XM, EX, XX },
+    { "addsubps", XM, EX, XX },
+  },
+  /* PREGRP28 */
+  {
+    { "(bad)", MX, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "haddpd", XM, EX, XX },
+    { "haddps", XM, EX, XX },
+  },
+  /* PREGRP29 */
+  {
+    { "(bad)", MX, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "hsubpd", XM, EX, XX },
+    { "hsubps", XM, EX, XX },
+  },
+  /* PREGRP30 */
+  {
+    { "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */
+    { "movsldup", XM, EX, XX },
+    { "movlpd", XM, EX, XX },
+    { "movddup", XM, EX, XX },
+  },
+  /* PREGRP31 */
+  {
+    { "movhpX", XM, EX, SIMD_Fixup, 'l' },
+    { "movshdup", XM, EX, XX },
+    { "movhpd", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP32 */
+  {
+    { "(bad)", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "lddqu", XM, M, XX },
+  },
+};
+
+static const struct dis386 x86_64_table[][2] = {
+  {
+    { "arpl", Ew, Gw, XX },
+    { "movs{||lq|xd}", Gv, Ed, XX },
+  },
+};
+
+#ifdef __KERNEL__
+#define INTERNAL_DISASSEMBLER_ERROR "<internal disassembler error>"
+#else  /* __KERNEL__ */
+#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
+#endif /* __KERNEL__ */
+
+static void
+ckprefix (void)
+{
+  int newrex;
+  rex = 0;
+  prefixes = 0;
+  used_prefixes = 0;
+  rex_used = 0;
+  while (1)
+    {
+      FETCH_DATA (the_info, codep + 1);
+      newrex = 0;
+      switch (*codep)
+       {
+       /* REX prefixes family.  */
+       case 0x40:
+       case 0x41:
+       case 0x42:
+       case 0x43:
+       case 0x44:
+       case 0x45:
+       case 0x46:
+       case 0x47:
+       case 0x48:
+       case 0x49:
+       case 0x4a:
+       case 0x4b:
+       case 0x4c:
+       case 0x4d:
+       case 0x4e:
+       case 0x4f:
+           if (mode_64bit)
+             newrex = *codep;
+           else
+             return;
+         break;
+       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;
+       }
+      /* Rex is ignored when followed by another prefix.  */
+      if (rex)
+       {
+         oappend (prefix_name (rex, 0));
+         oappend (" ");
+       }
+      rex = newrex;
+      codep++;
+    }
+}
+
+/* Return the name of the prefix byte PREF, or NULL if PREF is not a
+   prefix byte.  */
+
+static const char *
+prefix_name (int pref, int sizeflag)
+{
+  switch (pref)
+    {
+    /* REX prefixes family.  */
+    case 0x40:
+      return "rex";
+    case 0x41:
+      return "rexZ";
+    case 0x42:
+      return "rexY";
+    case 0x43:
+      return "rexYZ";
+    case 0x44:
+      return "rexX";
+    case 0x45:
+      return "rexXZ";
+    case 0x46:
+      return "rexXY";
+    case 0x47:
+      return "rexXYZ";
+    case 0x48:
+      return "rex64";
+    case 0x49:
+      return "rex64Z";
+    case 0x4a:
+      return "rex64Y";
+    case 0x4b:
+      return "rex64YZ";
+    case 0x4c:
+      return "rex64X";
+    case 0x4d:
+      return "rex64XZ";
+    case 0x4e:
+      return "rex64XY";
+    case 0x4f:
+      return "rex64XYZ";
+    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:
+      if (mode_64bit)
+       return (sizeflag & AFLAG) ? "addr32" : "addr64";
+      else
+       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 int two_source_ops;
+static bfd_vma op_address[3];
+static bfd_vma op_riprel[3];
+static bfd_vma start_pc;
+\f
+/*
+ *   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 char intel_syntax;
+static char open_char;
+static char close_char;
+static char separator_char;
+static char scale_char;
+
+/* Here for backwards compatibility.  When gdb stops using
+   print_insn_i386_att and print_insn_i386_intel these functions can
+   disappear, and print_insn_i386 be merged into print_insn.  */
+int
+print_insn_i386_att (bfd_vma pc, disassemble_info *info)
+{
+  intel_syntax = 0;
+
+  return print_insn (pc, info);
+}
+
+int
+print_insn_i386_intel (bfd_vma pc, disassemble_info *info)
+{
+  intel_syntax = 1;
+
+  return print_insn (pc, info);
+}
+
+int
+print_insn_i386 (bfd_vma pc, disassemble_info *info)
+{
+  intel_syntax = -1;
+
+  return print_insn (pc, info);
+}
+
+static int
+print_insn (bfd_vma pc, disassemble_info *info)
+{
+  const struct dis386 *dp;
+  int i;
+  char *first, *second, *third;
+  int needcomma;
+  unsigned char uses_SSE_prefix, uses_LOCK_prefix;
+  int sizeflag;
+  const char *p;
+  struct dis_private priv;
+
+  mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
+               || info->mach == bfd_mach_x86_64);
+
+  if (intel_syntax == (char) -1)
+    intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
+                   || info->mach == bfd_mach_x86_64_intel_syntax);
+
+  if (info->mach == bfd_mach_i386_i386
+      || info->mach == bfd_mach_x86_64
+      || info->mach == bfd_mach_i386_i386_intel_syntax
+      || info->mach == bfd_mach_x86_64_intel_syntax)
+    priv.orig_sizeflag = AFLAG | DFLAG;
+  else if (info->mach == bfd_mach_i386_i8086)
+    priv.orig_sizeflag = 0;
+  else
+    abort ();
+
+  for (p = info->disassembler_options; p != NULL; )
+    {
+      if (strncmp (p, "x86-64", 6) == 0)
+       {
+         mode_64bit = 1;
+         priv.orig_sizeflag = AFLAG | DFLAG;
+       }
+      else if (strncmp (p, "i386", 4) == 0)
+       {
+         mode_64bit = 0;
+         priv.orig_sizeflag = AFLAG | DFLAG;
+       }
+      else if (strncmp (p, "i8086", 5) == 0)
+       {
+         mode_64bit = 0;
+         priv.orig_sizeflag = 0;
+       }
+      else if (strncmp (p, "intel", 5) == 0)
+       {
+         intel_syntax = 1;
+       }
+      else if (strncmp (p, "att", 3) == 0)
+       {
+         intel_syntax = 0;
+       }
+      else if (strncmp (p, "addr", 4) == 0)
+       {
+         if (p[4] == '1' && p[5] == '6')
+           priv.orig_sizeflag &= ~AFLAG;
+         else if (p[4] == '3' && p[5] == '2')
+           priv.orig_sizeflag |= AFLAG;
+       }
+      else if (strncmp (p, "data", 4) == 0)
+       {
+         if (p[4] == '1' && p[5] == '6')
+           priv.orig_sizeflag &= ~DFLAG;
+         else if (p[4] == '3' && p[5] == '2')
+           priv.orig_sizeflag |= DFLAG;
+       }
+      else if (strncmp (p, "suffix", 6) == 0)
+       priv.orig_sizeflag |= SUFFIX_ALWAYS;
+
+      p = strchr (p, ',');
+      if (p != NULL)
+       p++;
+    }
+
+  if (intel_syntax)
+    {
+      names64 = intel_names64;
+      names32 = intel_names32;
+      names16 = intel_names16;
+      names8 = intel_names8;
+      names8rex = intel_names8rex;
+      names_seg = intel_names_seg;
+      index16 = intel_index16;
+      open_char = '[';
+      close_char = ']';
+      separator_char = '+';
+      scale_char = '*';
+    }
+  else
+    {
+      names64 = att_names64;
+      names32 = att_names32;
+      names16 = att_names16;
+      names8 = att_names8;
+      names8rex = att_names8rex;
+      names_seg = att_names_seg;
+      index16 = att_index16;
+      open_char = '(';
+      close_char =  ')';
+      separator_char = ',';
+      scale_char = ',';
+    }
+
+  /* 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 = &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 = priv.the_buffer;
+  codep = priv.the_buffer;
+
+#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 > priv.the_buffer)
+       {
+         name = prefix_name (priv.the_buffer[0], priv.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) priv.the_buffer[0]);
+           }
+
+         return 1;
+       }
+
+      return -1;
+    }
+#endif /* __KERNEL__ */
+
+  obufp = obuf;
+  ckprefix ();
+
+  insn_codep = codep;
+  sizeflag = priv.orig_sizeflag;
+
+  FETCH_DATA (info, codep + 1);
+  two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
+
+  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 (priv.the_buffer[0], priv.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);
+      dp = &dis386_twobyte[*++codep];
+      need_modrm = twobyte_has_modrm[*codep];
+      uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep];
+      uses_LOCK_prefix = (*codep & ~0x02) == 0x20;
+    }
+  else
+    {
+      dp = &dis386[*codep];
+      need_modrm = onebyte_has_modrm[*codep];
+      uses_SSE_prefix = 0;
+      uses_LOCK_prefix = 0;
+    }
+  codep++;
+
+  if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ))
+    {
+      oappend ("repz ");
+      used_prefixes |= PREFIX_REPZ;
+    }
+  if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ))
+    {
+      oappend ("repnz ");
+      used_prefixes |= PREFIX_REPNZ;
+    }
+  if (!uses_LOCK_prefix && (prefixes & PREFIX_LOCK))
+    {
+      oappend ("lock ");
+      used_prefixes |= PREFIX_LOCK;
+    }
+
+  if (prefixes & PREFIX_ADDR)
+    {
+      sizeflag ^= AFLAG;
+      if (dp->bytemode3 != loop_jcxz_mode || intel_syntax)
+       {
+         if ((sizeflag & AFLAG) || mode_64bit)
+           oappend ("addr32 ");
+         else
+           oappend ("addr16 ");
+         used_prefixes |= PREFIX_ADDR;
+       }
+    }
+
+  if (!uses_SSE_prefix && (prefixes & PREFIX_DATA))
+    {
+      sizeflag ^= DFLAG;
+      if (dp->bytemode3 == cond_jump_mode
+         && dp->bytemode1 == v_mode
+         && !intel_syntax)
+       {
+         if (sizeflag & DFLAG)
+           oappend ("data32 ");
+         else
+           oappend ("data16 ");
+         used_prefixes |= PREFIX_DATA;
+       }
+    }
+
+  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
+    {
+      int index;
+      if (dp->name == NULL)
+       {
+         switch (dp->bytemode1)
+           {
+           case USE_GROUPS:
+             dp = &grps[dp->bytemode2][reg];
+             break;
+
+           case USE_PREFIX_USER_TABLE:
+             index = 0;
+             used_prefixes |= (prefixes & PREFIX_REPZ);
+             if (prefixes & PREFIX_REPZ)
+               index = 1;
+             else
+               {
+                 used_prefixes |= (prefixes & PREFIX_DATA);
+                 if (prefixes & PREFIX_DATA)
+                   index = 2;
+                 else
+                   {
+                     used_prefixes |= (prefixes & PREFIX_REPNZ);
+                     if (prefixes & PREFIX_REPNZ)
+                       index = 3;
+                   }
+               }
+             dp = &prefix_user_table[dp->bytemode2][index];
+             break;
+
+           case X86_64_SPECIAL:
+             dp = &x86_64_table[dp->bytemode2][mode_64bit];
+             break;
+
+           default:
+             oappend (INTERNAL_DISASSEMBLER_ERROR);
+             break;
+           }
+       }
+
+      if (putop (dp->name, sizeflag) == 0)
+       {
+         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 (priv.the_buffer[0], priv.orig_sizeflag);
+      if (name == NULL)
+       name = INTERNAL_DISASSEMBLER_ERROR;
+      (*info->fprintf_func) (info->stream, "%s", name);
+      return 1;
+    }
+  if (rex & ~rex_used)
+    {
+      const char *name;
+      name = prefix_name (rex | 0x40, priv.orig_sizeflag);
+      if (name == NULL)
+       name = INTERNAL_DISASSEMBLER_ERROR;
+      (*info->fprintf_func) (info->stream, "%s ", name);
+    }
+
+  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 && !op_riprel[0])
+       (*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 && !op_riprel[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 && !op_riprel[2])
+       (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
+      else
+       (*info->fprintf_func) (info->stream, "%s", third);
+    }
+  for (i = 0; i < 3; i++)
+    if (op_index[i] != -1 && op_riprel[i])
+      {
+       (*info->fprintf_func) (info->stream, "        # ");
+       (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep
+                                               + op_address[op_index[i]]), info);
+      }
+  return codep - priv.the_buffer;
+}
+
+static const char *float_mem[] = {
+  /* d8 */
+  "fadd{s||s|}",
+  "fmul{s||s|}",
+  "fcom{s||s|}",
+  "fcomp{s||s|}",
+  "fsub{s||s|}",
+  "fsubr{s||s|}",
+  "fdiv{s||s|}",
+  "fdivr{s||s|}",
+  /* d9 */
+  "fld{s||s|}",
+  "(bad)",
+  "fst{s||s|}",
+  "fstp{s||s|}",
+  "fldenvIC",
+  "fldcw",
+  "fNstenvIC",
+  "fNstcw",
+  /* da */
+  "fiadd{l||l|}",
+  "fimul{l||l|}",
+  "ficom{l||l|}",
+  "ficomp{l||l|}",
+  "fisub{l||l|}",
+  "fisubr{l||l|}",
+  "fidiv{l||l|}",
+  "fidivr{l||l|}",
+  /* db */
+  "fild{l||l|}",
+  "fisttp{l||l|}",
+  "fist{l||l|}",
+  "fistp{l||l|}",
+  "(bad)",
+  "fld{t||t|}",
+  "(bad)",
+  "fstp{t||t|}",
+  /* dc */
+  "fadd{l||l|}",
+  "fmul{l||l|}",
+  "fcom{l||l|}",
+  "fcomp{l||l|}",
+  "fsub{l||l|}",
+  "fsubr{l||l|}",
+  "fdiv{l||l|}",
+  "fdivr{l||l|}",
+  /* dd */
+  "fld{l||l|}",
+  "fisttp{ll||ll|}",
+  "fst{l||l|}",
+  "fstp{l||l|}",
+  "frstorIC",
+  "(bad)",
+  "fNsaveIC",
+  "fNstsw",
+  /* de */
+  "fiadd",
+  "fimul",
+  "ficom",
+  "ficomp",
+  "fisub",
+  "fisubr",
+  "fidiv",
+  "fidivr",
+  /* df */
+  "fild",
+  "fisttp",
+  "fist",
+  "fistp",
+  "fbld",
+  "fild{ll||ll|}",
+  "fbstp",
+  "fistp{ll||ll|}",
+};
+
+static const unsigned char float_mem_mode[] = {
+  /* d8 */
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  /* d9 */
+  d_mode,
+  0,
+  d_mode,
+  d_mode,
+  0,
+  w_mode,
+  0,
+  w_mode,
+  /* da */
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  /* db */
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  0,
+  t_mode,
+  0,
+  t_mode,
+  /* dc */
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  /* dd */
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  0,
+  0,
+  0,
+  w_mode,
+  /* de */
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  /* df */
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  t_mode,
+  q_mode,
+  t_mode,
+  q_mode
+};
+
+#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 */
+  {
+    { "ffreep",        STi, 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 (int sizeflag)
+{
+  const struct dis386 *dp;
+  unsigned char floatop;
+
+  floatop = codep[-1];
+
+  if (mod != 3)
+    {
+      int fp_indx = (floatop - 0xd8) * 8 + reg;
+
+      putop (float_mem[fp_indx], sizeflag);
+      obufp = op1out;
+      OP_E (float_mem_mode[fp_indx], sizeflag);
+      return;
+    }
+  /* Skip mod/rm byte.  */
+  MODRM_CHECK;
+  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);
+    }
+}
+
+static void
+OP_ST (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  oappend ("%st");
+}
+
+static void
+OP_STi (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  sprintf (scratchbuf, "%%st(%d)", rm);
+  oappend (scratchbuf + intel_syntax);
+}
+
+/* Capital letters in template are macros.  */
+static int
+putop (const char *template, int sizeflag)
+{
+  const char *p;
+  int alt = 0;
+
+  for (p = template; *p; p++)
+    {
+      switch (*p)
+       {
+       default:
+         *obufp++ = *p;
+         break;
+       case '{':
+         alt = 0;
+         if (intel_syntax)
+           alt += 1;
+         if (mode_64bit)
+           alt += 2;
+         while (alt != 0)
+           {
+             while (*++p != '|')
+               {
+                 if (*p == '}')
+                   {
+                     /* Alternative not valid.  */
+                     strcpy (obuf, "(bad)");
+                     obufp = obuf + 5;
+                     return 1;
+                   }
+                 else if (*p == '\0')
+                   abort ();
+               }
+             alt--;
+           }
+         /* Fall through.  */
+       case 'I':
+         alt = 1;
+         continue;
+       case '|':
+         while (*++p != '}')
+           {
+             if (*p == '\0')
+               abort ();
+           }
+         break;
+       case '}':
+         break;
+       case 'A':
+         if (intel_syntax)
+           break;
+         if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
+           *obufp++ = 'b';
+         break;
+       case 'B':
+         if (intel_syntax)
+           break;
+         if (sizeflag & SUFFIX_ALWAYS)
+           *obufp++ = 'b';
+         break;
+       case 'C':
+         if (intel_syntax && !alt)
+           break;
+         if ((prefixes & PREFIX_DATA) || (sizeflag & SUFFIX_ALWAYS))
+           {
+             if (sizeflag & DFLAG)
+               *obufp++ = intel_syntax ? 'd' : 'l';
+             else
+               *obufp++ = intel_syntax ? 'w' : 's';
+             used_prefixes |= (prefixes & PREFIX_DATA);
+           }
+         break;
+       case 'E':               /* For jcxz/jecxz */
+         if (mode_64bit)
+           {
+             if (sizeflag & AFLAG)
+               *obufp++ = 'r';
+             else
+               *obufp++ = 'e';
+           }
+         else
+           if (sizeflag & AFLAG)
+             *obufp++ = 'e';
+         used_prefixes |= (prefixes & PREFIX_ADDR);
+         break;
+       case 'F':
+         if (intel_syntax)
+           break;
+         if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
+           {
+             if (sizeflag & AFLAG)
+               *obufp++ = mode_64bit ? 'q' : 'l';
+             else
+               *obufp++ = mode_64bit ? 'l' : 'w';
+             used_prefixes |= (prefixes & PREFIX_ADDR);
+           }
+         break;
+       case 'H':
+         if (intel_syntax)
+           break;
+         if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_CS
+             || (prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_DS)
+           {
+             used_prefixes |= prefixes & (PREFIX_CS | PREFIX_DS);
+             *obufp++ = ',';
+             *obufp++ = 'p';
+             if (prefixes & PREFIX_DS)
+               *obufp++ = 't';
+             else
+               *obufp++ = 'n';
+           }
+         break;
+       case 'J':
+         if (intel_syntax)
+           break;
+         *obufp++ = 'l';
+         break;
+       case 'L':
+         if (intel_syntax)
+           break;
+         if (sizeflag & SUFFIX_ALWAYS)
+           *obufp++ = 'l';
+         break;
+       case 'N':
+         if ((prefixes & PREFIX_FWAIT) == 0)
+           *obufp++ = 'n';
+         else
+           used_prefixes |= PREFIX_FWAIT;
+         break;
+       case 'O':
+         USED_REX (REX_MODE64);
+         if (rex & REX_MODE64)
+           *obufp++ = 'o';
+         else
+           *obufp++ = 'd';
+         break;
+       case 'T':
+         if (intel_syntax)
+           break;
+         if (mode_64bit)
+           {
+             *obufp++ = 'q';
+             break;
+           }
+         /* Fall through.  */
+       case 'P':
+         if (intel_syntax)
+           break;
+         if ((prefixes & PREFIX_DATA)
+             || (rex & REX_MODE64)
+             || (sizeflag & SUFFIX_ALWAYS))
+           {
+             USED_REX (REX_MODE64);
+             if (rex & REX_MODE64)
+               *obufp++ = 'q';
+             else
+               {
+                  if (sizeflag & DFLAG)
+                     *obufp++ = 'l';
+                  else
+                    *obufp++ = 'w';
+                  used_prefixes |= (prefixes & PREFIX_DATA);
+               }
+           }
+         break;
+       case 'U':
+         if (intel_syntax)
+           break;
+         if (mode_64bit)
+           {
+             *obufp++ = 'q';
+             break;
+           }
+         /* Fall through.  */
+       case 'Q':
+         if (intel_syntax && !alt)
+           break;
+         USED_REX (REX_MODE64);
+         if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
+           {
+             if (rex & REX_MODE64)
+               *obufp++ = 'q';
+             else
+               {
+                 if (sizeflag & DFLAG)
+                   *obufp++ = intel_syntax ? 'd' : 'l';
+                 else
+                   *obufp++ = 'w';
+                 used_prefixes |= (prefixes & PREFIX_DATA);
+               }
+           }
+         break;
+       case 'R':
+         USED_REX (REX_MODE64);
+         if (intel_syntax)
+           {
+             if (rex & REX_MODE64)
+               {
+                 *obufp++ = 'q';
+                 *obufp++ = 't';
+               }
+             else if (sizeflag & DFLAG)
+               {
+                 *obufp++ = 'd';
+                 *obufp++ = 'q';
+               }
+             else
+               {
+                 *obufp++ = 'w';
+                 *obufp++ = 'd';
+               }
+           }
+         else
+           {
+             if (rex & REX_MODE64)
+               *obufp++ = 'q';
+             else if (sizeflag & DFLAG)
+               *obufp++ = 'l';
+             else
+               *obufp++ = 'w';
+           }
+         if (!(rex & REX_MODE64))
+           used_prefixes |= (prefixes & PREFIX_DATA);
+         break;
+       case 'S':
+         if (intel_syntax)
+           break;
+         if (sizeflag & SUFFIX_ALWAYS)
+           {
+             if (rex & REX_MODE64)
+               *obufp++ = 'q';
+             else
+               {
+                 if (sizeflag & DFLAG)
+                   *obufp++ = 'l';
+                 else
+                   *obufp++ = 'w';
+                 used_prefixes |= (prefixes & PREFIX_DATA);
+               }
+           }
+         break;
+       case 'X':
+         if (prefixes & PREFIX_DATA)
+           *obufp++ = 'd';
+         else
+           *obufp++ = 's';
+         used_prefixes |= (prefixes & PREFIX_DATA);
+         break;
+       case 'Y':
+         if (intel_syntax)
+           break;
+         if (rex & REX_MODE64)
+           {
+             USED_REX (REX_MODE64);
+             *obufp++ = 'q';
+           }
+         break;
+         /* implicit operand size 'l' for i386 or 'q' for x86-64 */
+       case 'W':
+         /* operand size flag for cwtl, cbtw */
+         USED_REX (0);
+         if (rex)
+           *obufp++ = 'l';
+         else if (sizeflag & DFLAG)
+           *obufp++ = 'w';
+         else
+           *obufp++ = 'b';
+         if (intel_syntax)
+           {
+             if (rex)
+               {
+                 *obufp++ = 'q';
+                 *obufp++ = 'e';
+               }
+             if (sizeflag & DFLAG)
+               {
+                 *obufp++ = 'd';
+                 *obufp++ = 'e';
+               }
+             else
+               {
+                 *obufp++ = 'w';
+               }
+           }
+         if (!rex)
+           used_prefixes |= (prefixes & PREFIX_DATA);
+         break;
+       }
+      alt = 0;
+    }
+  *obufp = 0;
+  return 0;
+}
+
+static void
+oappend (const char *s)
+{
+  strcpy (obufp, s);
+  obufp += strlen (s);
+}
+
+static void
+append_seg (void)
+{
+  if (prefixes & PREFIX_CS)
+    {
+      used_prefixes |= PREFIX_CS;
+      oappend ("%cs:" + intel_syntax);
+    }
+  if (prefixes & PREFIX_DS)
+    {
+      used_prefixes |= PREFIX_DS;
+      oappend ("%ds:" + intel_syntax);
+    }
+  if (prefixes & PREFIX_SS)
+    {
+      used_prefixes |= PREFIX_SS;
+      oappend ("%ss:" + intel_syntax);
+    }
+  if (prefixes & PREFIX_ES)
+    {
+      used_prefixes |= PREFIX_ES;
+      oappend ("%es:" + intel_syntax);
+    }
+  if (prefixes & PREFIX_FS)
+    {
+      used_prefixes |= PREFIX_FS;
+      oappend ("%fs:" + intel_syntax);
+    }
+  if (prefixes & PREFIX_GS)
+    {
+      used_prefixes |= PREFIX_GS;
+      oappend ("%gs:" + intel_syntax);
+    }
+}
+
+static void
+OP_indirE (int bytemode, int sizeflag)
+{
+  if (!intel_syntax)
+    oappend ("*");
+  OP_E (bytemode, sizeflag);
+}
+
+static void
+print_operand_value (char *buf, int hex, bfd_vma disp)
+{
+  if (mode_64bit)
+    {
+      if (hex)
+       {
+         char tmp[30];
+         int i;
+         buf[0] = '0';
+         buf[1] = 'x';
+         sprintf_vma (tmp, disp);
+         for (i = 0; tmp[i] == '0' && tmp[i + 1]; i++);
+         strcpy (buf + 2, tmp + i);
+       }
+      else
+       {
+         bfd_signed_vma v = disp;
+         char tmp[30];
+         int i;
+         if (v < 0)
+           {
+             *(buf++) = '-';
+             v = -disp;
+             /* Check for possible overflow on 0x8000000000000000.  */
+             if (v < 0)
+               {
+                 strcpy (buf, "9223372036854775808");
+                 return;
+               }
+           }
+         if (!v)
+           {
+             strcpy (buf, "0");
+             return;
+           }
+
+         i = 0;
+         tmp[29] = 0;
+         while (v)
+           {
+             tmp[28 - i] = (v % 10) + '0';
+             v /= 10;
+             i++;
+           }
+         strcpy (buf, tmp + 29 - i);
+       }
+    }
+  else
+    {
+      if (hex)
+       sprintf (buf, "0x%x", (unsigned int) disp);
+      else
+       sprintf (buf, "%d", (int) disp);
+    }
+}
+
+static void
+OP_E (int bytemode, int sizeflag)
+{
+  bfd_vma disp;
+  int add = 0;
+  int riprel = 0;
+  USED_REX (REX_EXTZ);
+  if (rex & REX_EXTZ)
+    add += 8;
+
+  /* Skip mod/rm byte.  */
+  MODRM_CHECK;
+  codep++;
+
+  if (mod == 3)
+    {
+      switch (bytemode)
+       {
+       case b_mode:
+         USED_REX (0);
+         if (rex)
+           oappend (names8rex[rm + add]);
+         else
+           oappend (names8[rm + add]);
+         break;
+       case w_mode:
+         oappend (names16[rm + add]);
+         break;
+       case d_mode:
+         oappend (names32[rm + add]);
+         break;
+       case q_mode:
+         oappend (names64[rm + add]);
+         break;
+       case m_mode:
+         if (mode_64bit)
+           oappend (names64[rm + add]);
+         else
+           oappend (names32[rm + add]);
+         break;
+       case branch_v_mode:
+         if (mode_64bit)
+           oappend (names64[rm + add]);
+         else
+           {
+             if ((sizeflag & DFLAG) || bytemode != branch_v_mode)
+               oappend (names32[rm + add]);
+             else
+               oappend (names16[rm + add]);
+             used_prefixes |= (prefixes & PREFIX_DATA);
+           }
+         break;
+       case v_mode:
+       case dq_mode:
+       case dqw_mode:
+         USED_REX (REX_MODE64);
+         if (rex & REX_MODE64)
+           oappend (names64[rm + add]);
+         else if ((sizeflag & DFLAG) || bytemode != v_mode)
+           oappend (names32[rm + add]);
+         else
+           oappend (names16[rm + add]);
+         used_prefixes |= (prefixes & PREFIX_DATA);
+         break;
+       case 0:
+         break;
+       default:
+         oappend (INTERNAL_DISASSEMBLER_ERROR);
+         break;
+       }
+      return;
+    }
+
+  disp = 0;
+  append_seg ();
+
+  if ((sizeflag & AFLAG) || mode_64bit) /* 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);
+         index = (*codep >> 3) & 7;
+         if (mode_64bit || index != 0x4)
+           /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored.  */
+           scale = (*codep >> 6) & 3;
+         base = *codep & 7;
+         USED_REX (REX_EXTY);
+         if (rex & REX_EXTY)
+           index += 8;
+         codep++;
+       }
+      base += add;
+
+      switch (mod)
+       {
+       case 0:
+         if ((base & 7) == 5)
+           {
+             havebase = 0;
+             if (mode_64bit && !havesib)
+               riprel = 1;
+             disp = get32s ();
+           }
+         break;
+       case 1:
+         FETCH_DATA (the_info, codep + 1);
+         disp = *codep++;
+         if ((disp & 0x80) != 0)
+           disp -= 0x100;
+         break;
+       case 2:
+         disp = get32s ();
+         break;
+       }
+
+      if (!intel_syntax)
+       if (mod != 0 || (base & 7) == 5)
+         {
+           print_operand_value (scratchbuf, !riprel, disp);
+           oappend (scratchbuf);
+           if (riprel)
+             {
+               set_op (disp, 1);
+               oappend ("(%rip)");
+             }
+         }
+
+      if (havebase || (havesib && (index != 4 || scale != 0)))
+       {
+         if (intel_syntax)
+           {
+             switch (bytemode)
+               {
+               case b_mode:
+                 oappend ("BYTE PTR ");
+                 break;
+               case w_mode:
+               case dqw_mode:
+                 oappend ("WORD PTR ");
+                 break;
+               case branch_v_mode:
+               case v_mode:
+               case dq_mode:
+                 USED_REX (REX_MODE64);
+                 if (rex & REX_MODE64)
+                   oappend ("QWORD PTR ");
+                 else if ((sizeflag & DFLAG) || bytemode == dq_mode)
+                   oappend ("DWORD PTR ");
+                 else
+                   oappend ("WORD PTR ");
+                 used_prefixes |= (prefixes & PREFIX_DATA);
+                 break;
+               case d_mode:
+                 oappend ("DWORD PTR ");
+                 break;
+               case q_mode:
+                 oappend ("QWORD PTR ");
+                 break;
+               case m_mode:
+                 if (mode_64bit)
+                   oappend ("QWORD PTR ");
+                 else
+                   oappend ("DWORD PTR ");
+                 break;
+               case f_mode:
+                 if (sizeflag & DFLAG)
+                   {
+                     used_prefixes |= (prefixes & PREFIX_DATA);
+                     oappend ("FWORD PTR ");
+                   }
+                 else
+                   oappend ("DWORD PTR ");
+                 break;
+               case t_mode:
+                 oappend ("TBYTE PTR ");
+                 break;
+               case x_mode:
+                 oappend ("XMMWORD PTR ");
+                 break;
+               default:
+                 break;
+               }
+           }
+         *obufp++ = open_char;
+         if (intel_syntax && riprel)
+           oappend ("rip + ");
+         *obufp = '\0';
+         if (havebase)
+           oappend (mode_64bit && (sizeflag & AFLAG)
+                    ? names64[base] : names32[base]);
+         if (havesib)
+           {
+             if (index != 4)
+               {
+                 if (!intel_syntax || havebase)
+                   {
+                     *obufp++ = separator_char;
+                     *obufp = '\0';
+                   }
+                 oappend (mode_64bit && (sizeflag & AFLAG)
+                          ? names64[index] : names32[index]);
+               }
+             if (scale != 0 || (!intel_syntax && index != 4))
+               {
+                 *obufp++ = scale_char;
+                 *obufp = '\0';
+                 sprintf (scratchbuf, "%d", 1 << scale);
+                 oappend (scratchbuf);
+               }
+           }
+         if (intel_syntax && disp)
+           {
+             if ((bfd_signed_vma) disp > 0)
+               {
+                 *obufp++ = '+';
+                 *obufp = '\0';
+               }
+             else if (mod != 1)
+               {
+                 *obufp++ = '-';
+                 *obufp = '\0';
+                 disp = - (bfd_signed_vma) disp;
+               }
+
+             print_operand_value (scratchbuf, mod != 1, disp);
+             oappend (scratchbuf);
+           }
+
+         *obufp++ = close_char;
+         *obufp = '\0';
+       }
+      else if (intel_syntax)
+       {
+         if (mod != 0 || (base & 7) == 5)
+           {
+             if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+                             | PREFIX_ES | PREFIX_FS | PREFIX_GS))
+               ;
+             else
+               {
+                 oappend (names_seg[ds_reg - es_reg]);
+                 oappend (":");
+               }
+             print_operand_value (scratchbuf, 1, 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)
+         {
+           print_operand_value (scratchbuf, 0, disp);
+           oappend (scratchbuf);
+         }
+
+      if (mod != 0 || rm != 6)
+       {
+         *obufp++ = open_char;
+         *obufp = '\0';
+         oappend (index16[rm]);
+         if (intel_syntax && disp)
+           {
+             if ((bfd_signed_vma) disp > 0)
+               {
+                 *obufp++ = '+';
+                 *obufp = '\0';
+               }
+             else if (mod != 1)
+               {
+                 *obufp++ = '-';
+                 *obufp = '\0';
+                 disp = - (bfd_signed_vma) disp;
+               }
+
+             print_operand_value (scratchbuf, mod != 1, disp);
+             oappend (scratchbuf);
+           }
+
+         *obufp++ = close_char;
+         *obufp = '\0';
+       }
+      else if (intel_syntax)
+       {
+         if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+                         | PREFIX_ES | PREFIX_FS | PREFIX_GS))
+           ;
+         else
+           {
+             oappend (names_seg[ds_reg - es_reg]);
+             oappend (":");
+           }
+         print_operand_value (scratchbuf, 1, disp & 0xffff);
+         oappend (scratchbuf);
+       }
+    }
+}
+
+static void
+OP_G (int bytemode, int sizeflag)
+{
+  int add = 0;
+  USED_REX (REX_EXTX);
+  if (rex & REX_EXTX)
+    add += 8;
+  switch (bytemode)
+    {
+    case b_mode:
+      USED_REX (0);
+      if (rex)
+       oappend (names8rex[reg + add]);
+      else
+       oappend (names8[reg + add]);
+      break;
+    case w_mode:
+      oappend (names16[reg + add]);
+      break;
+    case d_mode:
+      oappend (names32[reg + add]);
+      break;
+    case q_mode:
+      oappend (names64[reg + add]);
+      break;
+    case v_mode:
+    case dq_mode:
+    case dqw_mode:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       oappend (names64[reg + add]);
+      else if ((sizeflag & DFLAG) || bytemode != v_mode)
+       oappend (names32[reg + add]);
+      else
+       oappend (names16[reg + add]);
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    case m_mode:
+      if (mode_64bit)
+       oappend (names64[reg + add]);
+      else
+       oappend (names32[reg + add]);
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      break;
+    }
+}
+
+static bfd_vma
+get64 (void)
+{
+  bfd_vma x;
+#ifdef BFD64
+  unsigned int a;
+  unsigned int b;
+
+  FETCH_DATA (the_info, codep + 8);
+  a = *codep++ & 0xff;
+  a |= (*codep++ & 0xff) << 8;
+  a |= (*codep++ & 0xff) << 16;
+  a |= (*codep++ & 0xff) << 24;
+  b = *codep++ & 0xff;
+  b |= (*codep++ & 0xff) << 8;
+  b |= (*codep++ & 0xff) << 16;
+  b |= (*codep++ & 0xff) << 24;
+  x = a + ((bfd_vma) b << 32);
+#else
+  abort ();
+  x = 0;
+#endif
+  return x;
+}
+
+static bfd_signed_vma
+get32 (void)
+{
+  bfd_signed_vma x = 0;
+
+  FETCH_DATA (the_info, codep + 4);
+  x = *codep++ & (bfd_signed_vma) 0xff;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
+  return x;
+}
+
+static bfd_signed_vma
+get32s (void)
+{
+  bfd_signed_vma x = 0;
+
+  FETCH_DATA (the_info, codep + 4);
+  x = *codep++ & (bfd_signed_vma) 0xff;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
+
+  x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31);
+
+  return x;
+}
+
+static int
+get16 (void)
+{
+  int x = 0;
+
+  FETCH_DATA (the_info, codep + 2);
+  x = *codep++ & 0xff;
+  x |= (*codep++ & 0xff) << 8;
+  return x;
+}
+
+static void
+set_op (bfd_vma op, int riprel)
+{
+  op_index[op_ad] = op_ad;
+  if (mode_64bit)
+    {
+      op_address[op_ad] = op;
+      op_riprel[op_ad] = riprel;
+    }
+  else
+    {
+      /* Mask to get a 32-bit address.  */
+      op_address[op_ad] = op & 0xffffffff;
+      op_riprel[op_ad] = riprel & 0xffffffff;
+    }
+}
+
+static void
+OP_REG (int code, int sizeflag)
+{
+  const char *s;
+  int add = 0;
+  USED_REX (REX_EXTZ);
+  if (rex & REX_EXTZ)
+    add = 8;
+
+  switch (code)
+    {
+    case indir_dx_reg:
+      if (intel_syntax)
+       s = "[dx]";
+      else
+       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 + add];
+      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 + add];
+      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:
+      USED_REX (0);
+      if (rex)
+       s = names8rex[code - al_reg + add];
+      else
+       s = names8[code - al_reg];
+      break;
+    case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
+    case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
+      if (mode_64bit)
+       {
+         s = names64[code - rAX_reg + add];
+         break;
+       }
+      code += eAX_reg - rAX_reg;
+      /* Fall through.  */
+    case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+    case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       s = names64[code - eAX_reg + add];
+      else if (sizeflag & DFLAG)
+       s = names32[code - eAX_reg + add];
+      else
+       s = names16[code - eAX_reg + add];
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    default:
+      s = INTERNAL_DISASSEMBLER_ERROR;
+      break;
+    }
+  oappend (s);
+}
+
+static void
+OP_IMREG (int code, int sizeflag)
+{
+  const char *s;
+
+  switch (code)
+    {
+    case indir_dx_reg:
+      if (intel_syntax)
+       s = "[dx]";
+      else
+       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:
+      USED_REX (0);
+      if (rex)
+       s = names8rex[code - al_reg];
+      else
+       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:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       s = names64[code - eAX_reg];
+      else 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 (int bytemode, int sizeflag)
+{
+  bfd_signed_vma op;
+  bfd_signed_vma mask = -1;
+
+  switch (bytemode)
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++;
+      mask = 0xff;
+      break;
+    case q_mode:
+      if (mode_64bit)
+       {
+         op = get32s ();
+         break;
+       }
+      /* Fall through.  */
+    case v_mode:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       op = get32s ();
+      else if (sizeflag & DFLAG)
+       {
+         op = get32 ();
+         mask = 0xffffffff;
+       }
+      else
+       {
+         op = get16 ();
+         mask = 0xfffff;
+       }
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    case w_mode:
+      mask = 0xfffff;
+      op = get16 ();
+      break;
+    case const_1_mode:
+      if (intel_syntax)
+        oappend ("1");
+      return;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+
+  op &= mask;
+  scratchbuf[0] = '$';
+  print_operand_value (scratchbuf + 1, 1, op);
+  oappend (scratchbuf + intel_syntax);
+  scratchbuf[0] = '\0';
+}
+
+static void
+OP_I64 (int bytemode, int sizeflag)
+{
+  bfd_signed_vma op;
+  bfd_signed_vma mask = -1;
+
+  if (!mode_64bit)
+    {
+      OP_I (bytemode, sizeflag);
+      return;
+    }
+
+  switch (bytemode)
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++;
+      mask = 0xff;
+      break;
+    case v_mode:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       op = get64 ();
+      else if (sizeflag & DFLAG)
+       {
+         op = get32 ();
+         mask = 0xffffffff;
+       }
+      else
+       {
+         op = get16 ();
+         mask = 0xfffff;
+       }
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    case w_mode:
+      mask = 0xfffff;
+      op = get16 ();
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+
+  op &= mask;
+  scratchbuf[0] = '$';
+  print_operand_value (scratchbuf + 1, 1, op);
+  oappend (scratchbuf + intel_syntax);
+  scratchbuf[0] = '\0';
+}
+
+static void
+OP_sI (int bytemode, int sizeflag)
+{
+  bfd_signed_vma op;
+  bfd_signed_vma mask = -1;
+
+  switch (bytemode)
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++;
+      if ((op & 0x80) != 0)
+       op -= 0x100;
+      mask = 0xffffffff;
+      break;
+    case v_mode:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       op = get32s ();
+      else if (sizeflag & DFLAG)
+       {
+         op = get32s ();
+         mask = 0xffffffff;
+       }
+      else
+       {
+         mask = 0xffffffff;
+         op = get16 ();
+         if ((op & 0x8000) != 0)
+           op -= 0x10000;
+       }
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    case w_mode:
+      op = get16 ();
+      mask = 0xffffffff;
+      if ((op & 0x8000) != 0)
+       op -= 0x10000;
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+
+  scratchbuf[0] = '$';
+  print_operand_value (scratchbuf + 1, 1, op);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_J (int bytemode, int sizeflag)
+{
+  bfd_vma disp;
+  bfd_vma 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 = get32s ();
+      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;
+       }
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+  disp = (start_pc + codep - start_codep + disp) & mask;
+  set_op (disp, 0);
+  print_operand_value (scratchbuf, 1, disp);
+  oappend (scratchbuf);
+}
+
+static void
+OP_SEG (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  oappend (names_seg[reg]);
+}
+
+static void
+OP_DIR (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);
+  if (intel_syntax)
+    sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
+  else
+    sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
+  oappend (scratchbuf);
+}
+
+static void
+OP_OFF (int bytemode ATTRIBUTE_UNUSED, int sizeflag)
+{
+  bfd_vma off;
+
+  append_seg ();
+
+  if ((sizeflag & AFLAG) || mode_64bit)
+    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[ds_reg - es_reg]);
+         oappend (":");
+       }
+    }
+  print_operand_value (scratchbuf, 1, off);
+  oappend (scratchbuf);
+}
+
+static void
+OP_OFF64 (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  bfd_vma off;
+
+  if (!mode_64bit)
+    {
+      OP_OFF (bytemode, sizeflag);
+      return;
+    }
+
+  append_seg ();
+
+  off = get64 ();
+
+  if (intel_syntax)
+    {
+      if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+                       | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+       {
+         oappend (names_seg[ds_reg - es_reg]);
+         oappend (":");
+       }
+    }
+  print_operand_value (scratchbuf, 1, off);
+  oappend (scratchbuf);
+}
+
+static void
+ptr_reg (int code, int sizeflag)
+{
+  const char *s;
+
+  *obufp++ = open_char;
+  used_prefixes |= (prefixes & PREFIX_ADDR);
+  if (mode_64bit)
+    {
+      if (!(sizeflag & AFLAG))
+       s = names32[code - eAX_reg];
+      else
+       s = names64[code - eAX_reg];
+    }
+  else if (sizeflag & AFLAG)
+    s = names32[code - eAX_reg];
+  else
+    s = names16[code - eAX_reg];
+  oappend (s);
+  *obufp++ = close_char;
+  *obufp = 0;
+}
+
+static void
+OP_ESreg (int code, int sizeflag)
+{
+  if (intel_syntax)
+    {
+      if (codep[-1] & 1)
+       {
+         USED_REX (REX_MODE64);
+         used_prefixes |= (prefixes & PREFIX_DATA);
+         if (rex & REX_MODE64)
+           oappend ("QWORD PTR ");
+         else if ((sizeflag & DFLAG))
+           oappend ("DWORD PTR ");
+         else
+           oappend ("WORD PTR ");
+       }
+      else
+       oappend ("BYTE PTR ");
+    }
+
+  oappend ("%es:" + intel_syntax);
+  ptr_reg (code, sizeflag);
+}
+
+static void
+OP_DSreg (int code, int sizeflag)
+{
+  if (intel_syntax)
+    {
+      if (codep[-1] != 0xd7 && (codep[-1] & 1))
+       {
+         USED_REX (REX_MODE64);
+         used_prefixes |= (prefixes & PREFIX_DATA);
+         if (rex & REX_MODE64)
+           oappend ("QWORD PTR ");
+         else if ((sizeflag & DFLAG))
+           oappend ("DWORD PTR ");
+         else
+           oappend ("WORD PTR ");
+       }
+      else
+       oappend ("BYTE PTR ");
+    }
+
+  if ((prefixes
+       & (PREFIX_CS
+         | PREFIX_DS
+         | PREFIX_SS
+         | PREFIX_ES
+         | PREFIX_FS
+         | PREFIX_GS)) == 0)
+    prefixes |= PREFIX_DS;
+  append_seg ();
+  ptr_reg (code, sizeflag);
+}
+
+static void
+OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  int add = 0;
+  if (rex & REX_EXTX)
+    {
+      USED_REX (REX_EXTX);
+      add = 8;
+    }
+  else if (!mode_64bit && (prefixes & PREFIX_LOCK))
+    {
+      used_prefixes |= PREFIX_LOCK;
+      add = 8;
+    }
+  sprintf (scratchbuf, "%%cr%d", reg + add);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_D (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  int add = 0;
+  USED_REX (REX_EXTX);
+  if (rex & REX_EXTX)
+    add = 8;
+  if (intel_syntax)
+    sprintf (scratchbuf, "db%d", reg + add);
+  else
+    sprintf (scratchbuf, "%%db%d", reg + add);
+  oappend (scratchbuf);
+}
+
+static void
+OP_T (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  sprintf (scratchbuf, "%%tr%d", reg);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_Rd (int bytemode, int sizeflag)
+{
+  if (mod == 3)
+    OP_E (bytemode, sizeflag);
+  else
+    BadOp ();
+}
+
+static void
+OP_MMX (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  used_prefixes |= (prefixes & PREFIX_DATA);
+  if (prefixes & PREFIX_DATA)
+    {
+      int add = 0;
+      USED_REX (REX_EXTX);
+      if (rex & REX_EXTX)
+       add = 8;
+      sprintf (scratchbuf, "%%xmm%d", reg + add);
+    }
+  else
+    sprintf (scratchbuf, "%%mm%d", reg);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_XMM (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  int add = 0;
+  USED_REX (REX_EXTX);
+  if (rex & REX_EXTX)
+    add = 8;
+  sprintf (scratchbuf, "%%xmm%d", reg + add);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_EM (int bytemode, int sizeflag)
+{
+  if (mod != 3)
+    {
+      if (intel_syntax && bytemode == v_mode)
+       {
+         bytemode = (prefixes & PREFIX_DATA) ? x_mode : q_mode;
+         used_prefixes |= (prefixes & PREFIX_DATA);
+       }
+      OP_E (bytemode, sizeflag);
+      return;
+    }
+
+  /* Skip mod/rm byte.  */
+  MODRM_CHECK;
+  codep++;
+  used_prefixes |= (prefixes & PREFIX_DATA);
+  if (prefixes & PREFIX_DATA)
+    {
+      int add = 0;
+
+      USED_REX (REX_EXTZ);
+      if (rex & REX_EXTZ)
+       add = 8;
+      sprintf (scratchbuf, "%%xmm%d", rm + add);
+    }
+  else
+    sprintf (scratchbuf, "%%mm%d", rm);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_EX (int bytemode, int sizeflag)
+{
+  int add = 0;
+  if (mod != 3)
+    {
+      if (intel_syntax && bytemode == v_mode)
+       {
+         switch (prefixes & (PREFIX_DATA|PREFIX_REPZ|PREFIX_REPNZ))
+           {
+           case 0:            bytemode = x_mode; break;
+           case PREFIX_REPZ:  bytemode = d_mode; used_prefixes |= PREFIX_REPZ;  break;
+           case PREFIX_DATA:  bytemode = x_mode; used_prefixes |= PREFIX_DATA;  break;
+           case PREFIX_REPNZ: bytemode = q_mode; used_prefixes |= PREFIX_REPNZ; break;
+           default:           bytemode = 0; break;
+           }
+       }
+      OP_E (bytemode, sizeflag);
+      return;
+    }
+  USED_REX (REX_EXTZ);
+  if (rex & REX_EXTZ)
+    add = 8;
+
+  /* Skip mod/rm byte.  */
+  MODRM_CHECK;
+  codep++;
+  sprintf (scratchbuf, "%%xmm%d", rm + add);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_MS (int bytemode, int sizeflag)
+{
+  if (mod == 3)
+    OP_EM (bytemode, sizeflag);
+  else
+    BadOp ();
+}
+
+static void
+OP_XS (int bytemode, int sizeflag)
+{
+  if (mod == 3)
+    OP_EX (bytemode, sizeflag);
+  else
+    BadOp ();
+}
+
+static void
+OP_M (int bytemode, int sizeflag)
+{
+  if (mod == 3)
+    BadOp ();  /* bad lea,lds,les,lfs,lgs,lss modrm */
+  else
+    OP_E (bytemode, sizeflag);
+}
+
+static void
+OP_0f07 (int bytemode, int sizeflag)
+{
+  if (mod != 3 || rm != 0)
+    BadOp ();
+  else
+    OP_E (bytemode, sizeflag);
+}
+
+static void
+OP_0fae (int bytemode, int sizeflag)
+{
+  if (mod == 3)
+    {
+      if (reg == 7)
+       strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence");
+
+      if (reg < 5 || rm != 0)
+       {
+         BadOp ();     /* bad sfence, mfence, or lfence */
+         return;
+       }
+    }
+  else if (reg != 7)
+    {
+      BadOp ();                /* bad clflush */
+      return;
+    }
+
+  OP_E (bytemode, sizeflag);
+}
+
+static void
+NOP_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  /* NOP with REPZ prefix is called PAUSE.  */
+  if (prefixes == PREFIX_REPZ)
+    strcpy (obuf, "pause");
+}
+
+static const char *const 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 (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 (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)
+    {
+      char suffix1 = 'p', suffix2 = 's';
+      used_prefixes |= (prefixes & PREFIX_REPZ);
+      if (prefixes & PREFIX_REPZ)
+       suffix1 = 's';
+      else
+       {
+         used_prefixes |= (prefixes & PREFIX_DATA);
+         if (prefixes & PREFIX_DATA)
+           suffix2 = 'd';
+         else
+           {
+             used_prefixes |= (prefixes & PREFIX_REPNZ);
+             if (prefixes & PREFIX_REPNZ)
+               suffix1 = 's', suffix2 = 'd';
+           }
+       }
+      sprintf (scratchbuf, "cmp%s%c%c",
+              simd_cmp_op[cmp_type], suffix1, suffix2);
+      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 (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
+PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
+{
+  if (mod == 3 && reg == 1 && rm <= 1)
+    {
+      /* Override "sidt".  */
+      char *p = obuf + strlen (obuf) - 4;
+
+      /* We might have a suffix when disassembling with -Msuffix.  */
+      if (*p == 'i')
+       --p;
+
+      if (rm)
+       {
+         /* mwait %eax,%ecx  */
+         strcpy (p, "mwait");
+         if (!intel_syntax)
+           strcpy (op1out, names32[0]);
+       }
+      else
+       {
+         /* monitor %eax,%ecx,%edx"  */
+         strcpy (p, "monitor");
+         if (!intel_syntax)
+           {
+             if (!mode_64bit)
+               strcpy (op1out, names32[0]);
+             else if (!(prefixes & PREFIX_ADDR))
+               strcpy (op1out, names64[0]);
+             else
+               {
+                 strcpy (op1out, names32[0]);
+                 used_prefixes |= PREFIX_ADDR;
+               }
+             strcpy (op3out, names32[2]);
+           }
+       }
+      if (!intel_syntax)
+       {
+         strcpy (op2out, names32[1]);
+         two_source_ops = 1;
+       }
+
+      codep++;
+    }
+  else
+    OP_M (0, sizeflag);
+}
+
+static void
+SVME_Fixup (int bytemode, int sizeflag)
+{
+  const char *alt;
+  char *p;
+
+  switch (*codep)
+    {
+    case 0xd8:
+      alt = "vmrun";
+      break;
+    case 0xd9:
+      alt = "vmmcall";
+      break;
+    case 0xda:
+      alt = "vmload";
+      break;
+    case 0xdb:
+      alt = "vmsave";
+      break;
+    case 0xdc:
+      alt = "stgi";
+      break;
+    case 0xdd:
+      alt = "clgi";
+      break;
+    case 0xde:
+      alt = "skinit";
+      break;
+    case 0xdf:
+      alt = "invlpga";
+      break;
+    default:
+      OP_M (bytemode, sizeflag);
+      return;
+    }
+  /* Override "lidt".  */
+  p = obuf + strlen (obuf) - 4;
+  /* We might have a suffix.  */
+  if (*p == 'i')
+    --p;
+  strcpy (p, alt);
+  if (!(prefixes & PREFIX_ADDR))
+    {
+      ++codep;
+      return;
+    }
+  used_prefixes |= PREFIX_ADDR;
+  switch (*codep++)
+    {
+    case 0xdf:
+      strcpy (op2out, names32[1]);
+      two_source_ops = 1;
+         /* Fall through.  */
+    case 0xd8:
+    case 0xda:
+    case 0xdb:
+      *obufp++ = open_char;
+      if (mode_64bit || (sizeflag & AFLAG))
+        alt = names32[0];
+      else
+        alt = names16[0];
+      strcpy (obufp, alt);
+      obufp += strlen (alt);
+      *obufp++ = close_char;
+      *obufp = '\0';
+      break;
+    }
+}
+
+static void
+INVLPG_Fixup (int bytemode, int sizeflag)
+{
+  const char *alt;
+
+  switch (*codep)
+    {
+    case 0xf8:
+      alt = "swapgs";
+      break;
+    case 0xf9:
+      alt = "rdtscp";
+      break;
+    default:
+      OP_M (bytemode, sizeflag);
+      return;
+    }
+  /* Override "invlpg".  */
+  strcpy (obuf + strlen (obuf) - 6, alt);
+  codep++;
+}
+
+static void
+BadOp (void)
+{
+  /* Throw away prefixes and 1st. opcode byte.  */
+  codep = insn_codep + 1;
+  oappend ("(bad)");
+}
+
+static void
+SEG_Fixup (int extrachar, int sizeflag)
+{
+  if (mod == 3)
+    {
+      /* We need to add a proper suffix with
+
+               movw %ds,%ax
+               movl %ds,%eax
+               movq %ds,%rax
+               movw %ax,%ds
+               movl %eax,%ds
+               movq %rax,%ds
+       */
+      const char *suffix;
+
+      if (prefixes & PREFIX_DATA)
+       suffix = "w";
+      else
+       {
+         USED_REX (REX_MODE64);
+         if (rex & REX_MODE64)
+           suffix = "q";
+         else
+           suffix = "l";
+       }
+      strcat (obuf, suffix);
+    }
+  else
+    {
+      /* We need to fix the suffix for
+
+               movw %ds,(%eax)
+               movw %ds,(%rax)
+               movw (%eax),%ds
+               movw (%rax),%ds
+
+        Override "mov[l|q]".  */
+      char *p = obuf + strlen (obuf) - 1;
+
+      /* We might not have a suffix.  */
+      if (*p == 'v')
+       ++p;
+      *p = 'w';
+    }
+
+  OP_E (extrachar, sizeflag);
+}
+
+static void
+VMX_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
+{
+  if (mod == 3 && reg == 0 && rm >=1 && rm <= 4)
+    {
+      /* Override "sgdt".  */
+      char *p = obuf + strlen (obuf) - 4;
+
+      /* We might have a suffix when disassembling with -Msuffix.  */
+      if (*p == 'g')
+       --p;
+
+      switch (rm)
+       {
+       case 1:
+         strcpy (p, "vmcall");
+         break;
+       case 2:
+         strcpy (p, "vmlaunch");
+         break;
+       case 3:
+         strcpy (p, "vmresume");
+         break;
+       case 4:
+         strcpy (p, "vmxoff");
+         break;
+       }
+
+      codep++;
+    }
+  else
+    OP_E (0, sizeflag);
+}
+
+static void
+OP_VMX (int bytemode, int sizeflag)
+{
+  used_prefixes |= (prefixes & (PREFIX_DATA | PREFIX_REPZ));
+  if (prefixes & PREFIX_DATA)
+    strcpy (obuf, "vmclear");
+  else if (prefixes & PREFIX_REPZ)
+    strcpy (obuf, "vmxon");
+  else
+    strcpy (obuf, "vmptrld");
+  OP_E (bytemode, sizeflag);
+}
diff --git a/arch/x86/kdb/kdb_cmds_32 b/arch/x86/kdb/kdb_cmds_32
new file mode 100644 (file)
index 0000000..9e71a62
--- /dev/null
@@ -0,0 +1,17 @@
+# Standard architecture specific commands for kdb.
+# These commands are appended to those in kdb/kdb_cmds, see that file for
+# restrictions.
+
+# Standard debugging information for first level support, invoked from archkdb*
+# commands that are defined in kdb/kdb_cmds.
+
+defcmd archkdbcommon "" "Common arch debugging"
+  set LINES 2000000
+  set BTAPROMPT 0
+  -summary
+  -id %eip-24
+  -cpu
+  -ps
+  -dmesg 600
+  -bt
+endefcmd
diff --git a/arch/x86/kdb/kdb_cmds_64 b/arch/x86/kdb/kdb_cmds_64
new file mode 100644 (file)
index 0000000..ea9bdef
--- /dev/null
@@ -0,0 +1,18 @@
+# Standard architecture specific commands for kdb.
+# These commands are appended to those in kdb/kdb_cmds, see that file for
+# restrictions.
+
+# Standard debugging information for first level support, invoked from archkdb*
+# commands that are defined in kdb/kdb_cmds.
+
+defcmd archkdbcommon "" "Common arch debugging"
+  set LINES 2000000
+  set BTAPROMPT 0
+  -summary
+  -id %rip-24
+  -cpu
+  -ps
+  -dmesg 600
+  -bt
+  -cpu_pda *
+endefcmd
diff --git a/arch/x86/kdb/kdba_bp_32.c b/arch/x86/kdb/kdba_bp_32.c
new file mode 100644 (file)
index 0000000..2c14b6f
--- /dev/null
@@ -0,0 +1,914 @@
+/*
+ * Kernel Debugger Architecture Dependent Breakpoint Handling
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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 for every CPU.
+ */
+
+static kdbhard_bp_t kdb_hardbreaks[NR_CPUS][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;
+       int cpu = smp_processor_id();
+
+       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)){
+                                               /* Can't be hw breakpoint */
+                                               if (bp->bp_hardtype)
+                                                       kdb_printf("kdb: Error - hw bp delayed\n");
+                                               kdb_printf("kdba_installbp\n");
+                                       }
+                                       kdba_installbp(regs, bp);
+                                       if (!KDB_STATE(DOING_SS)) {
+                                               regs->flags &= ~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->flags &= ~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->ip);
+                       if (kdb_getarea(instruction, regs->ip) ||
+                           (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->ip, NULL, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+                       kdb_id1(regs->ip);
+                       KDB_STATE_CLEAR(DOING_SS);
+               }
+
+               if (rv != KDB_DB_SSB)
+                       regs->flags &= ~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->flags |= 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[cpu])
+                && (bp->bp_hard[cpu]->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->ip);
+                       }
+
+                       goto handled;
+               }
+       }
+
+unknown:
+       regs->flags |= 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 ip.  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: ip=0x%lx (not adjusted) "
+                          "flags=0x%lx regs=0x%p sp=0x%lx\n",
+                          regs->ip, regs->flags, regs, regs->sp);
+
+       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->ip - bp->bp_adjust)) {
+                       /* Hit this breakpoint.  */
+                       regs->ip -= bp->bp_adjust;
+                       kdb_printf("Instruction(i) breakpoint #%d at 0x%lx (adjusted)\n",
+                                 i, regs->ip);
+                       kdb_id1(regs->ip);
+                       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->ip = 0x%lx\n", regs->ip);
+
+       /*
+        * 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:
+ */
+
+static 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)
+{
+       int cpu;
+
+       kdb_printf("\n    is enabled");
+       if (bp->bp_hardtype) {
+               if (bp->bp_global)
+                       cpu = smp_processor_id();
+               else
+                       cpu = bp->bp_cpu;
+               kdba_printbpreg(bp->bp_hard[cpu]);
+               if (bp->bp_hard[cpu]->bph_mode != 0) {
+                       kdb_printf(" for %d bytes",
+                                  bp->bp_hard[cpu]->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
+ *
+ *     Allocate hw register for bp on specific CPU
+ *
+ * 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:
+ */
+
+static kdbhard_bp_t *
+kdba_allocbp(kdbhard_bp_t *bph, int *diagp, unsigned int cpu)
+{
+       int i;
+       kdbhard_bp_t *newbph;
+
+       for(i=0; i < KDB_MAXHARDBPT; i++) {
+               newbph=&(kdb_hardbreaks[cpu][i]);
+               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_alloc_hwbp
+ *
+ *     Associate a hardware registers with a breakpoint.
+ *     If hw bp is global hw registers descriptor will be allocated
+ *     on every CPU.
+ *
+ * Parameters:
+ *     bp - hardware bp
+ *     diagp - pointer to variable that will store error when
+ *     function complete
+ * Outputs:
+ *     None.
+ * Returns:
+ *     None
+ * Locking:
+ *     None.
+ * Remarks:
+ *     Should be called with correct bp->bp_template
+ */
+
+void
+kdba_alloc_hwbp(kdb_bp_t *bp, int *diagp)
+{
+       int i;
+
+       if (bp->bp_global){
+               for (i = 0; i < NR_CPUS; ++i) {
+                       if (!cpu_online(i))
+                               continue;
+                       bp->bp_hard[i] = kdba_allocbp(&bp->bp_template, diagp, i);
+                       if (*diagp)
+                               break;
+               }
+       } else {
+               bp->bp_hard[bp->bp_cpu] = kdba_allocbp(&bp->bp_template, diagp, bp->bp_cpu);
+       }
+       bp->bp_hardtype = 1;
+}
+
+/*
+ * kdba_freebp
+ *
+ *     Deallocate hw registers descriptor for bp on specific CPU
+ *
+ * Parameters:
+ *     None.
+ * Outputs:
+ *     None.
+ * Returns:
+ *     Zero for success, a kdb diagnostic for failure
+ * Locking:
+ *     None.
+ * Remarks:
+ */
+
+static void
+kdba_freebp(kdbhard_bp_t *bph)
+{
+       bph->bph_free = 1;
+}
+
+/*
+ * kdba_free_hwbp
+ *
+ *     Frees allocated hw registers descriptors for bp.
+ *     If hw bp is global, hw registers descriptors will be freed
+ *     on every CPU.
+ *
+ * Parameters:
+ *     bp - hardware bp
+ * Outputs:
+ *     None.
+ * Returns:
+ *     None
+ * Locking:
+ *     None.
+ * Remarks:
+ *     Should be called with correct bp->bp_template
+ */
+
+void
+kdba_free_hwbp(kdb_bp_t *bp)
+{
+       int i;
+
+       /* When kernel enters KDB, first, all local bps
+        * are removed, so here we don't need to clear
+        * debug registers.
+        */
+
+       if (bp->bp_global){
+               for (i = 0; i < NR_CPUS; ++i) {
+                       if (!cpu_online(i))
+                               continue;
+                       if (bp->bp_hard[i])
+                               kdba_freebp(bp->bp_hard[i]);
+                       bp->bp_hard[i] = 0;
+               }
+       } else {
+               kdba_freebp(bp->bp_hard[bp->bp_cpu]);
+               bp->bp_hard[bp->bp_cpu] = NULL;
+       }
+       bp->bp_hardtype = 0;
+}
+
+/*
+ * 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,j;
+       kdbhard_bp_t *bph;
+
+       /*
+        * Clear the hardware breakpoint table
+        */
+
+       memset(kdb_hardbreaks, '\0', sizeof(kdb_hardbreaks));
+
+       for (i = 0; i < NR_CPUS; ++i) {
+               /* Called early so we don't know actual
+                * ammount of CPUs
+                */
+               for(j=0; j < KDB_MAXHARDBPT; j++) {
+                       bph=&(kdb_hardbreaks[i][j]);
+                       bph->bph_reg = j;
+                       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)
+{
+       int cpu = smp_processor_id();
+
+       /*
+        * 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_hardtype) {
+               if (KDB_DEBUG(BP) && !bp->bp_global && cpu != bp->bp_cpu){
+                       kdb_printf("kdba_installbp: cpu != bp->bp_cpu for local hw bp\n");
+               }
+
+               if (KDB_DEBUG(BP) && !bp->bp_hard[cpu]){
+                       kdb_printf("kdba_installbp: Error - bp_hard[smp_processor_id()] is emply\n");
+                       return 1;
+               }
+
+               if (!bp->bp_hard[cpu]->bph_installed){
+                       kdba_installdbreg(bp);
+                       bp->bp_hard[cpu]->bph_installed = 1;
+                       if (KDB_DEBUG(BP)) {
+                               kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+                                  bp->bp_hard[cpu]->bph_reg, bp->bp_addr);
+                       }
+               }
+       } else if (!bp->bp_installed) {
+               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)
+{
+       int cpu = smp_processor_id();
+
+       /*
+        * 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_hardtype) {
+               if (KDB_DEBUG(BP) && !bp->bp_global && cpu != bp->bp_cpu){
+                       kdb_printf("kdba_removebp: cpu != bp->bp_cpu for local hw bp\n");
+               }
+
+               if (KDB_DEBUG(BP) && !bp->bp_hard[cpu]){
+                       kdb_printf("kdba_removebp: Error - bp_hard[smp_processor_id()] is emply\n");
+                       return 1;
+               }
+
+               if (KDB_DEBUG(BP)) {
+                       kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+                                  bp->bp_hard[cpu]->bph_reg, bp->bp_addr);
+               }
+
+               if (bp->bp_hard[cpu]->bph_installed){
+                       if (KDB_DEBUG(BP)) {
+                               kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+                                  bp->bp_hard[cpu]->bph_reg, bp->bp_addr);
+                       }
+                       kdba_removedbreg(bp);
+                       bp->bp_hard[cpu]->bph_installed = 0;
+               }
+       } else if (bp->bp_installed) {
+               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 --git a/arch/x86/kdb/kdba_bp_64.c b/arch/x86/kdb/kdba_bp_64.c
new file mode 100644 (file)
index 0000000..bceedec
--- /dev/null
@@ -0,0 +1,912 @@
+/*
+ * Kernel Debugger Architecture Dependent Breakpoint Handling
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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 for every CPU.
+ */
+
+static kdbhard_bp_t kdb_hardbreaks[NR_CPUS][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;
+       int cpu = smp_processor_id();
+
+       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)){
+                                               /* Can't be hw breakpoint */
+                                               if (bp->bp_hardtype)
+                                                       kdb_printf("kdb: Error - hw bp delayed\n");
+                                               kdb_printf("kdba_installbp\n");
+                                       }
+                                       kdba_installbp(regs, bp);
+                                       if (!KDB_STATE(DOING_SS)) {
+                                               regs->flags &= ~X86_EFLAGS_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->flags &= ~X86_EFLAGS_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->ip);
+                       if (kdb_getarea(instruction, regs->ip) ||
+                           (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->ip, NULL, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+                       kdb_id1(regs->ip);
+                       KDB_STATE_CLEAR(DOING_SS);
+               }
+
+               if (rv != KDB_DB_SSB)
+                       regs->flags &= ~X86_EFLAGS_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->flags |= X86_EFLAGS_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[cpu])
+                && (bp->bp_hard[cpu]->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->ip);
+                       }
+
+                       goto handled;
+               }
+       }
+
+unknown:
+       regs->flags |= X86_EFLAGS_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 ip.  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: ip=0x%lx (not adjusted) "
+                          "flags=0x%lx ef=0x%p sp=0x%lx\n",
+                          regs->ip, regs->flags, regs, regs->sp);
+
+       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->ip - bp->bp_adjust)) {
+                       /* Hit this breakpoint.  */
+                       regs->ip -= bp->bp_adjust;
+                       kdb_printf("Instruction(i) breakpoint #%d at 0x%lx (adjusted)\n",
+                                 i, regs->ip);
+                       kdb_id1(regs->ip);
+                       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->ip = 0x%lx\n", regs->ip);
+
+       /*
+        * 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:
+ */
+
+static 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)
+{
+       int cpu;
+
+       kdb_printf("\n    is enabled");
+       if (bp->bp_hardtype) {
+               if (bp->bp_global)
+                       cpu = smp_processor_id();
+               else
+                       cpu = bp->bp_cpu;
+               kdba_printbpreg(bp->bp_hard[cpu]);
+               if (bp->bp_hard[cpu]->bph_mode != 0) {
+                       kdb_printf(" for %d bytes",
+                                  bp->bp_hard[cpu]->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
+ *
+ *     Allocate hw register for bp on specific CPU
+ *
+ * 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:
+ */
+
+static kdbhard_bp_t *
+kdba_allocbp(kdbhard_bp_t *bph, int *diagp, unsigned int cpu)
+{
+       int i;
+       kdbhard_bp_t *newbph;
+
+       for(i=0; i < KDB_MAXHARDBPT; i++) {
+               newbph=&(kdb_hardbreaks[cpu][i]);
+               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_alloc_hwbp
+ *
+ *     Associate a hardware registers with a breakpoint.
+ *     If hw bp is global hw registers descriptor will be allocated
+ *     on every CPU.
+ *
+ * Parameters:
+ *     bp - hardware bp
+ *     diagp - pointer to variable that will store error when
+ *     function complete
+ * Outputs:
+ *     None.
+ * Returns:
+ *     None
+ * Locking:
+ *     None.
+ * Remarks:
+ *     Should be called with correct bp->bp_template
+ */
+
+void
+kdba_alloc_hwbp(kdb_bp_t *bp, int *diagp)
+{
+       int i;
+
+       if (bp->bp_global){
+               for (i = 0; i < NR_CPUS; ++i) {
+                       if (!cpu_online(i))
+                               continue;
+                       bp->bp_hard[i] = kdba_allocbp(&bp->bp_template, diagp, i);
+                       if (*diagp)
+                               break;
+               }
+       } else {
+               bp->bp_hard[bp->bp_cpu] = kdba_allocbp(&bp->bp_template, diagp, bp->bp_cpu);
+       }
+       bp->bp_hardtype = 1;
+}
+
+/*
+ * kdba_freebp
+ *
+ *     Deallocate hw registers descriptor for bp on specific CPU
+ *
+ * Parameters:
+ *     None.
+ * Outputs:
+ *     None.
+ * Returns:
+ *     Zero for success, a kdb diagnostic for failure
+ * Locking:
+ *     None.
+ * Remarks:
+ */
+
+static void
+kdba_freebp(kdbhard_bp_t *bph)
+{
+       bph->bph_free = 1;
+}
+
+/*
+ * kdba_free_hwbp
+ *
+ *     Frees allocated hw registers descriptors for bp.
+ *     If hw bp is global, hw registers descriptors will be freed
+ *     on every CPU.
+ *
+ * Parameters:
+ *     bp - hardware bp
+ * Outputs:
+ *     None.
+ * Returns:
+ *     None
+ * Locking:
+ *     None.
+ * Remarks:
+ *     Should be called with correct bp->bp_template
+ */
+
+void
+kdba_free_hwbp(kdb_bp_t *bp)
+{
+       int i;
+
+       /* When kernel enters KDB, first, all local bps
+        * are removed, so here we don't need to clear
+        * debug registers.
+        */
+
+       if (bp->bp_global){
+               for (i = 0; i < NR_CPUS; ++i) {
+                       if (!cpu_online(i))
+                               continue;
+                       if (bp->bp_hard[i])
+                               kdba_freebp(bp->bp_hard[i]);
+                       bp->bp_hard[i] = 0;
+               }
+       } else {
+               kdba_freebp(bp->bp_hard[bp->bp_cpu]);
+               bp->bp_hard[bp->bp_cpu] = NULL;
+       }
+       bp->bp_hardtype = 0;
+}
+
+/*
+ * 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,j;
+       kdbhard_bp_t *bph;
+
+       /*
+        * Clear the hardware breakpoint table
+        */
+
+       memset(kdb_hardbreaks, '\0', sizeof(kdb_hardbreaks));
+
+       for (i = 0; i < NR_CPUS; ++i) {
+               /* Called early so we don't know actual
+                * ammount of CPUs
+                */
+               for(j=0; j < KDB_MAXHARDBPT; j++) {
+                       bph=&(kdb_hardbreaks[i][j]);
+                       bph->bph_reg = j;
+                       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.
+ */
+
+int
+kdba_installbp(struct pt_regs *regs, kdb_bp_t *bp)
+{
+       int cpu = smp_processor_id();
+
+       /*
+        * 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_hardtype) {
+               if (KDB_DEBUG(BP) && !bp->bp_global && cpu != bp->bp_cpu){
+                       kdb_printf("kdba_removebp: cpu != bp->bp_cpu for local hw bp\n");
+               }
+
+               if (KDB_DEBUG(BP) && !bp->bp_hard[cpu]){
+                       kdb_printf("kdba_removebp: Error - bp_hard[smp_processor_id()] is emply\n");
+                       return 1;
+               }
+
+               if (!bp->bp_hard[cpu]->bph_installed){
+                       kdba_installdbreg(bp);
+                       bp->bp_hard[cpu]->bph_installed = 1;
+                       if (KDB_DEBUG(BP)) {
+                               kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+                                  bp->bp_hard[cpu]->bph_reg, bp->bp_addr);
+                       }
+               }
+       } else if (!bp->bp_installed) {
+               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 " kdb_bfd_vma_fmt "\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)
+{
+       int cpu = smp_processor_id();
+
+       /*
+        * 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_hardtype) {
+               if (KDB_DEBUG(BP) && !bp->bp_global && cpu != bp->bp_cpu){
+                       kdb_printf("kdba_removebp: cpu != bp->bp_cpu for local hw bp\n");
+               }
+
+               if (KDB_DEBUG(BP) && !bp->bp_hard[cpu]){
+                       kdb_printf("kdba_removebp: Error - bp_hard[smp_processor_id()] is emply\n");
+                       return 1;
+               }
+
+               if (KDB_DEBUG(BP)) {
+                       kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+                                  bp->bp_hard[cpu]->bph_reg, bp->bp_addr);
+               }
+
+               if (bp->bp_hard[cpu]->bph_installed){
+                       if (KDB_DEBUG(BP)) {
+                               kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+                                  bp->bp_hard[cpu]->bph_reg, bp->bp_addr);
+                       }
+                       kdba_removedbreg(bp);
+                       bp->bp_hard[cpu]->bph_installed = 0;
+               }
+       } else if (bp->bp_installed) {
+               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 --git a/arch/x86/kdb/kdba_bt.c b/arch/x86/kdb/kdba_bt.c
new file mode 100644 (file)
index 0000000..62a8444
--- /dev/null
@@ -0,0 +1,5597 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2006, 2007-2008 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * Common code for doing accurate backtraces on i386 and x86_64, including
+ * printing the values of arguments.
+ */
+
+#include <linux/init.h>
+#include <linux/kallsyms.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/stringify.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/nmi.h>
+#include <asm/asm-offsets.h>
+#include <asm/system.h>
+
+#define KDB_DEBUG_BB(fmt, ...)                                                 \
+       {if (KDB_DEBUG(BB)) kdb_printf(fmt, ## __VA_ARGS__);}
+#define KDB_DEBUG_BB_OFFSET_PRINTF(offset, prefix, suffix)                     \
+       kdb_printf(prefix "%c0x%x" suffix,                                      \
+                  offset >= 0 ? '+' : '-',                                     \
+                  offset >= 0 ? offset : -offset)
+#define KDB_DEBUG_BB_OFFSET(offset, prefix, suffix)                            \
+       {if (KDB_DEBUG(BB)) KDB_DEBUG_BB_OFFSET_PRINTF(offset, prefix, suffix);}
+
+#define        BB_CHECK(expr, val, ret)                                                \
+({                                                                             \
+       if (unlikely(expr)) {                                                   \
+               kdb_printf("%s, line %d: BB_CHECK(" #expr ") failed "           \
+                       #val "=%lx\n",                                          \
+                       __FUNCTION__, __LINE__, (long)val);                     \
+               bb_giveup = 1;                                                  \
+               return ret;                                                     \
+       }                                                                       \
+})
+
+static int bb_giveup;
+
+/* Use BBRG_Rxx for both i386 and x86_64.  RAX through R15 must be at the end,
+ * starting with RAX.  Some of these codes do not reflect actual registers,
+ * such codes are special cases when parsing the record of register changes.
+ * When updating BBRG_ entries, update bbrg_name as well.
+ */
+
+enum bb_reg_code
+{
+       BBRG_UNDEFINED = 0,     /* Register contents are undefined */
+       BBRG_OSP,               /* original stack pointer on entry to function */
+       BBRG_RAX,
+       BBRG_RBX,
+       BBRG_RCX,
+       BBRG_RDX,
+       BBRG_RDI,
+       BBRG_RSI,
+       BBRG_RBP,
+       BBRG_RSP,
+       BBRG_R8,
+       BBRG_R9,
+       BBRG_R10,
+       BBRG_R11,
+       BBRG_R12,
+       BBRG_R13,
+       BBRG_R14,
+       BBRG_R15,
+};
+
+const static char *bbrg_name[] = {
+       [BBRG_UNDEFINED]   = "undefined",
+       [BBRG_OSP]         = "osp",
+       [BBRG_RAX]         = "rax",
+       [BBRG_RBX]         = "rbx",
+       [BBRG_RCX]         = "rcx",
+       [BBRG_RDX]         = "rdx",
+       [BBRG_RDI]         = "rdi",
+       [BBRG_RSI]         = "rsi",
+       [BBRG_RBP]         = "rbp",
+       [BBRG_RSP]         = "rsp",
+       [BBRG_R8]          = "r8",
+       [BBRG_R9]          = "r9",
+       [BBRG_R10]         = "r10",
+       [BBRG_R11]         = "r11",
+       [BBRG_R12]         = "r12",
+       [BBRG_R13]         = "r13",
+       [BBRG_R14]         = "r14",
+       [BBRG_R15]         = "r15",
+};
+
+/* Map a register name to its register code.  This includes the sub-register
+ * addressable fields, e.g. parts of rax can be addressed as ax, al, ah, eax.
+ * The list is sorted so it can be binary chopped, sort command is:
+ *   LANG=C sort -t '"' -k2
+ */
+
+struct bb_reg_code_map {
+       enum bb_reg_code reg;
+       const char *name;
+};
+
+const static struct bb_reg_code_map
+bb_reg_code_map[] = {
+       { BBRG_RAX, "ah" },
+       { BBRG_RAX, "al" },
+       { BBRG_RAX, "ax" },
+       { BBRG_RBX, "bh" },
+       { BBRG_RBX, "bl" },
+       { BBRG_RBP, "bp" },
+       { BBRG_RBP, "bpl" },
+       { BBRG_RBX, "bx" },
+       { BBRG_RCX, "ch" },
+       { BBRG_RCX, "cl" },
+       { BBRG_RCX, "cx" },
+       { BBRG_RDX, "dh" },
+       { BBRG_RDI, "di" },
+       { BBRG_RDI, "dil" },
+       { BBRG_RDX, "dl" },
+       { BBRG_RDX, "dx" },
+       { BBRG_RAX, "eax" },
+       { BBRG_RBP, "ebp" },
+       { BBRG_RBX, "ebx" },
+       { BBRG_RCX, "ecx" },
+       { BBRG_RDI, "edi" },
+       { BBRG_RDX, "edx" },
+       { BBRG_RSI, "esi" },
+       { BBRG_RSP, "esp" },
+       { BBRG_R10, "r10" },
+       { BBRG_R10, "r10d" },
+       { BBRG_R10, "r10l" },
+       { BBRG_R10, "r10w" },
+       { BBRG_R11, "r11" },
+       { BBRG_R11, "r11d" },
+       { BBRG_R11, "r11l" },
+       { BBRG_R11, "r11w" },
+       { BBRG_R12, "r12" },
+       { BBRG_R12, "r12d" },
+       { BBRG_R12, "r12l" },
+       { BBRG_R12, "r12w" },
+       { BBRG_R13, "r13" },
+       { BBRG_R13, "r13d" },
+       { BBRG_R13, "r13l" },
+       { BBRG_R13, "r13w" },
+       { BBRG_R14, "r14" },
+       { BBRG_R14, "r14d" },
+       { BBRG_R14, "r14l" },
+       { BBRG_R14, "r14w" },
+       { BBRG_R15, "r15" },
+       { BBRG_R15, "r15d" },
+       { BBRG_R15, "r15l" },
+       { BBRG_R15, "r15w" },
+       { BBRG_R8,  "r8" },
+       { BBRG_R8,  "r8d" },
+       { BBRG_R8,  "r8l" },
+       { BBRG_R8,  "r8w" },
+       { BBRG_R9,  "r9" },
+       { BBRG_R9,  "r9d" },
+       { BBRG_R9,  "r9l" },
+       { BBRG_R9,  "r9w" },
+       { BBRG_RAX, "rax" },
+       { BBRG_RBP, "rbp" },
+       { BBRG_RBX, "rbx" },
+       { BBRG_RCX, "rcx" },
+       { BBRG_RDI, "rdi" },
+       { BBRG_RDX, "rdx" },
+       { BBRG_RSI, "rsi" },
+       { BBRG_RSP, "rsp" },
+       { BBRG_RSI, "si" },
+       { BBRG_RSI, "sil" },
+       { BBRG_RSP, "sp" },
+       { BBRG_RSP, "spl" },
+};
+
+/* Record register contents in terms of the values that were passed to this
+ * function, IOW track which registers contain an input value.  A register's
+ * contents can be undefined, it can contain an input register value or it can
+ * contain an offset from the original stack pointer.
+ *
+ * This structure is used to represent the current contents of the integer
+ * registers, it is held in an array that is indexed by BBRG_xxx.  The element
+ * for BBRG_xxx indicates what input value is currently in BBRG_xxx.  When
+ * 'value' is BBRG_OSP then register BBRG_xxx contains a stack pointer,
+ * pointing at 'offset' from the original stack pointer on entry to the
+ * function.  When 'value' is not BBRG_OSP then element BBRG_xxx contains the
+ * original contents of an input register and offset is ignored.
+ *
+ * An input register 'value' can be stored in more than one register and/or in
+ * more than one memory location.
+ */
+
+struct bb_reg_contains
+{
+       enum bb_reg_code value: 8;
+       short offset;
+};
+
+/* Note: the offsets in struct bb_mem_contains in this code are _NOT_ offsets
+ * from OSP, they are offsets from current RSP.  It fits better with the way
+ * that struct pt_regs is built, some code pushes extra data before pt_regs so
+ * working with OSP relative offsets gets messy.  struct bb_mem_contains
+ * entries must be in descending order of RSP offset.
+ */
+
+typedef struct { DECLARE_BITMAP(bits, BBRG_R15+1); } bbrgmask_t;
+#define BB_SKIP(reg) (1 << (BBRG_ ## reg))
+struct bb_mem_contains {
+       short offset_address;
+       enum bb_reg_code value: 8;
+};
+
+/* Transfer of control to a label outside the current function.  If the
+ * transfer is to a known common restore path that expects known registers
+ * and/or a known memory state (e.g. struct pt_regs) then do a sanity check on
+ * the state at this point.
+ */
+
+struct bb_name_state {
+       const char *name;                       /* target function */
+       bfd_vma address;                        /* Address of target function */
+       const char *fname;                      /* optional from function name */
+       const struct bb_mem_contains *mem;      /* expected memory state */
+       const struct bb_reg_contains *regs;     /* expected register state */
+       const unsigned short mem_size;          /* ARRAY_SIZE(mem) */
+       const unsigned short regs_size;         /* ARRAY_SIZE(regs) */
+       const short osp_offset;                 /* RSP in regs == OSP+osp_offset */
+       const bbrgmask_t skip_mem;              /* Some slots in mem may be undefined */
+       const bbrgmask_t skip_regs;             /* Some slots in regs may be undefined */
+};
+
+/* NS (NAME_STATE) macros define the register and memory state when we transfer
+ * control to or start decoding a special case name.  Use NS when the target
+ * label always has the same state.  Use NS_FROM and specify the source label
+ * if the target state is slightly different depending on where it is branched
+ * from.  This gives better state checking, by isolating the special cases.
+ *
+ * Note: for the same target label, NS_FROM entries must be followed by a
+ * single NS entry.
+ */
+
+#define        NS_FROM(iname, ifname, imem, iregs, iskip_mem, iskip_regs, iosp_offset) \
+       { \
+               .name = iname, \
+               .fname = ifname, \
+               .mem = imem, \
+               .regs = iregs, \
+               .mem_size = ARRAY_SIZE(imem), \
+               .regs_size = ARRAY_SIZE(iregs), \
+               .skip_mem.bits[0] = iskip_mem, \
+               .skip_regs.bits[0] = iskip_regs, \
+               .osp_offset = iosp_offset, \
+                       .address = 0 \
+       }
+
+/* Shorter forms for the common cases */
+#define        NS(iname, imem, iregs, iskip_mem, iskip_regs, iosp_offset) \
+         NS_FROM(iname, NULL, imem, iregs, iskip_mem, iskip_regs, iosp_offset)
+#define        NS_MEM(iname, imem, iskip_mem) \
+         NS_FROM(iname, NULL, imem, no_regs, iskip_mem, 0, 0)
+#define        NS_MEM_FROM(iname, ifname, imem, iskip_mem) \
+         NS_FROM(iname, ifname, imem, no_regs, iskip_mem, 0, 0)
+#define        NS_REG(iname, iregs, iskip_regs) \
+         NS_FROM(iname, NULL, no_memory, iregs, 0, iskip_regs, 0)
+#define        NS_REG_FROM(iname, ifname, iregs, iskip_regs) \
+         NS_FROM(iname, ifname, no_memory, iregs, 0, iskip_regs, 0)
+
+static void
+bb_reg_code_set_value(enum bb_reg_code dst, enum bb_reg_code src);
+
+static const char *bb_mod_name, *bb_func_name;
+
+static int
+bb_noret(const char *name)
+{
+       if (strcmp(name, "panic") == 0 ||
+           strcmp(name, "do_exit") == 0 ||
+           strcmp(name, "do_group_exit") == 0 ||
+           strcmp(name, "complete_and_exit") == 0)
+               return 1;
+       return 0;
+}
+
+/*============================================================================*/
+/*                                                                            */
+/* Most of the basic block code and data is common to x86_64 and i386.  This  */
+/* large ifdef  contains almost all of the differences between the two        */
+/* architectures.                                                             */
+/*                                                                            */
+/* Make sure you update the correct section of this ifdef.                    */
+/*                                                                            */
+/*============================================================================*/
+
+#ifdef CONFIG_X86_64
+
+/* Registers that can be used to pass parameters, in the order that parameters
+ * are passed.
+ */
+
+const static enum bb_reg_code
+bb_param_reg[] = {
+       BBRG_RDI,
+       BBRG_RSI,
+       BBRG_RDX,
+       BBRG_RCX,
+       BBRG_R8,
+       BBRG_R9,
+};
+
+const static enum bb_reg_code
+bb_preserved_reg[] = {
+       BBRG_RBX,
+       BBRG_RBP,
+       BBRG_RSP,
+       BBRG_R12,
+       BBRG_R13,
+       BBRG_R14,
+       BBRG_R15,
+};
+
+static const struct bb_mem_contains full_pt_regs[] = {
+       { 0x70, BBRG_RDI },
+       { 0x68, BBRG_RSI },
+       { 0x60, BBRG_RDX },
+       { 0x58, BBRG_RCX },
+       { 0x50, BBRG_RAX },
+       { 0x48, BBRG_R8  },
+       { 0x40, BBRG_R9  },
+       { 0x38, BBRG_R10 },
+       { 0x30, BBRG_R11 },
+       { 0x28, BBRG_RBX },
+       { 0x20, BBRG_RBP },
+       { 0x18, BBRG_R12 },
+       { 0x10, BBRG_R13 },
+       { 0x08, BBRG_R14 },
+       { 0x00, BBRG_R15 },
+};
+static const struct bb_mem_contains partial_pt_regs[] = {
+       { 0x40, BBRG_RDI },
+       { 0x38, BBRG_RSI },
+       { 0x30, BBRG_RDX },
+       { 0x28, BBRG_RCX },
+       { 0x20, BBRG_RAX },
+       { 0x18, BBRG_R8  },
+       { 0x10, BBRG_R9  },
+       { 0x08, BBRG_R10 },
+       { 0x00, BBRG_R11 },
+};
+static const struct bb_mem_contains partial_pt_regs_plus_1[] = {
+       { 0x48, BBRG_RDI },
+       { 0x40, BBRG_RSI },
+       { 0x38, BBRG_RDX },
+       { 0x30, BBRG_RCX },
+       { 0x28, BBRG_RAX },
+       { 0x20, BBRG_R8  },
+       { 0x18, BBRG_R9  },
+       { 0x10, BBRG_R10 },
+       { 0x08, BBRG_R11 },
+};
+static const struct bb_mem_contains partial_pt_regs_plus_2[] = {
+       { 0x50, BBRG_RDI },
+       { 0x48, BBRG_RSI },
+       { 0x40, BBRG_RDX },
+       { 0x38, BBRG_RCX },
+       { 0x30, BBRG_RAX },
+       { 0x28, BBRG_R8  },
+       { 0x20, BBRG_R9  },
+       { 0x18, BBRG_R10 },
+       { 0x10, BBRG_R11 },
+};
+static const struct bb_mem_contains no_memory[] = {
+};
+/* Hardware has already pushed an error_code on the stack.  Use undefined just
+ * to set the initial stack offset.
+ */
+static const struct bb_mem_contains error_code[] = {
+       { 0x0, BBRG_UNDEFINED },
+};
+/* error_code plus original rax */
+static const struct bb_mem_contains error_code_rax[] = {
+       { 0x8, BBRG_UNDEFINED },
+       { 0x0, BBRG_RAX },
+};
+
+static const struct bb_reg_contains all_regs[] = {
+       [BBRG_RAX] = { BBRG_RAX, 0 },
+       [BBRG_RBX] = { BBRG_RBX, 0 },
+       [BBRG_RCX] = { BBRG_RCX, 0 },
+       [BBRG_RDX] = { BBRG_RDX, 0 },
+       [BBRG_RDI] = { BBRG_RDI, 0 },
+       [BBRG_RSI] = { BBRG_RSI, 0 },
+       [BBRG_RBP] = { BBRG_RBP, 0 },
+       [BBRG_RSP] = { BBRG_OSP, 0 },
+       [BBRG_R8 ] = { BBRG_R8,  0 },
+       [BBRG_R9 ] = { BBRG_R9,  0 },
+       [BBRG_R10] = { BBRG_R10, 0 },
+       [BBRG_R11] = { BBRG_R11, 0 },
+       [BBRG_R12] = { BBRG_R12, 0 },
+       [BBRG_R13] = { BBRG_R13, 0 },
+       [BBRG_R14] = { BBRG_R14, 0 },
+       [BBRG_R15] = { BBRG_R15, 0 },
+};
+static const struct bb_reg_contains no_regs[] = {
+};
+
+static struct bb_name_state bb_special_cases[] = {
+
+       /* First the cases that pass data only in memory.  We do not check any
+        * register state for these cases.
+        */
+
+       /* Simple cases, no exceptions */
+       NS_MEM("ia32_ptregs_common", partial_pt_regs_plus_1, 0),
+       NS_MEM("ia32_sysret", partial_pt_regs, 0),
+       NS_MEM("int_careful", partial_pt_regs, 0),
+       NS_MEM("int_restore_rest", full_pt_regs, 0),
+       NS_MEM("int_signal", full_pt_regs, 0),
+       NS_MEM("int_very_careful", partial_pt_regs, 0),
+       NS_MEM("int_with_check", partial_pt_regs, 0),
+#ifdef CONFIG_TRACE_IRQFLAGS
+       NS_MEM("paranoid_exit0", full_pt_regs, 0),
+#endif /* CONFIG_TRACE_IRQFLAGS */
+       NS_MEM("paranoid_exit1", full_pt_regs, 0),
+       NS_MEM("ptregscall_common", partial_pt_regs_plus_1, 0),
+       NS_MEM("restore_norax", partial_pt_regs, 0),
+       NS_MEM("restore", partial_pt_regs, 0),
+       NS_MEM("ret_from_intr", partial_pt_regs_plus_2, 0),
+       NS_MEM("stub32_clone", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub32_execve", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub32_fork", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub32_iopl", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub32_rt_sigreturn", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub32_rt_sigsuspend", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub32_sigaltstack", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub32_sigreturn", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub32_sigsuspend", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub32_vfork", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub_clone", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub_execve", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub_fork", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub_iopl", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub_rt_sigreturn", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub_rt_sigsuspend", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub_sigaltstack", partial_pt_regs_plus_1, 0),
+       NS_MEM("stub_vfork", partial_pt_regs_plus_1, 0),
+
+       NS_MEM_FROM("ia32_badsys", "ia32_sysenter_target",
+               partial_pt_regs,
+               /* ia32_sysenter_target uses CLEAR_RREGS to clear R8-R11 on
+                * some paths.  It also stomps on RAX.
+                */
+               BB_SKIP(R8) | BB_SKIP(R9) | BB_SKIP(R10) | BB_SKIP(R11) |
+               BB_SKIP(RAX)),
+       NS_MEM_FROM("ia32_badsys", "ia32_cstar_target",
+               partial_pt_regs,
+               /* ia32_cstar_target uses CLEAR_RREGS to clear R8-R11 on some
+                * paths.  It also stomps on RAX.  Even more confusing, instead
+                * of storing RCX it stores RBP.  WTF?
+                */
+               BB_SKIP(R8) | BB_SKIP(R9) | BB_SKIP(R10) | BB_SKIP(R11) |
+               BB_SKIP(RAX) | BB_SKIP(RCX)),
+       NS_MEM("ia32_badsys", partial_pt_regs, 0),
+
+       /* Various bits of code branch to int_ret_from_sys_call, with slightly
+        * different missing values in pt_regs.
+        */
+       NS_MEM_FROM("int_ret_from_sys_call", "ret_from_fork",
+               partial_pt_regs,
+               BB_SKIP(R11)),
+       NS_MEM_FROM("int_ret_from_sys_call", "stub_execve",
+               partial_pt_regs,
+               BB_SKIP(RAX) | BB_SKIP(RCX)),
+       NS_MEM_FROM("int_ret_from_sys_call", "stub_rt_sigreturn",
+               partial_pt_regs,
+               BB_SKIP(RAX) | BB_SKIP(RCX)),
+       NS_MEM_FROM("int_ret_from_sys_call", "kernel_execve",
+               partial_pt_regs,
+               BB_SKIP(RAX)),
+       NS_MEM_FROM("int_ret_from_sys_call", "ia32_syscall",
+               partial_pt_regs,
+               /* ia32_syscall only saves RDI through RCX. */
+               BB_SKIP(R8) | BB_SKIP(R9) | BB_SKIP(R10) | BB_SKIP(R11) |
+               BB_SKIP(RAX)),
+       NS_MEM_FROM("int_ret_from_sys_call", "ia32_sysenter_target",
+               partial_pt_regs,
+               /* ia32_sysenter_target uses CLEAR_RREGS to clear R8-R11 on
+               * some paths.  It also stomps on RAX.
+               */
+               BB_SKIP(R8) | BB_SKIP(R9) | BB_SKIP(R10) | BB_SKIP(R11) |
+               BB_SKIP(RAX)),
+       NS_MEM_FROM("int_ret_from_sys_call", "ia32_cstar_target",
+               partial_pt_regs,
+               /* ia32_cstar_target uses CLEAR_RREGS to clear R8-R11 on some
+                * paths.  It also stomps on RAX.  Even more confusing, instead
+                * of storing RCX it stores RBP.  WTF?
+                */
+               BB_SKIP(R8) | BB_SKIP(R9) | BB_SKIP(R10) | BB_SKIP(R11) |
+               BB_SKIP(RAX) | BB_SKIP(RCX)),
+       NS_MEM("int_ret_from_sys_call", partial_pt_regs, 0),
+
+#ifdef CONFIG_PREEMPT
+       NS_MEM("retint_kernel", partial_pt_regs, BB_SKIP(RAX)),
+#endif /* CONFIG_PREEMPT */
+
+       NS_MEM("retint_careful", partial_pt_regs, BB_SKIP(RAX)),
+
+       /* Horrible hack: For a brand new x86_64 task, switch_to() branches to
+        * ret_from_fork with a totally different stack state from all the
+        * other tasks that come out of switch_to().  This non-standard state
+        * cannot be represented so just ignore the branch from switch_to() to
+        * ret_from_fork.  Due to inlining and linker labels, switch_to() can
+        * appear as several different function labels, including schedule,
+        * context_switch and __sched_text_start.
+        */
+       NS_MEM_FROM("ret_from_fork", "schedule", no_memory, 0),
+       NS_MEM_FROM("ret_from_fork", "__sched_text_start", no_memory, 0),
+       NS_MEM_FROM("ret_from_fork", "context_switch", no_memory, 0),
+       NS_MEM("ret_from_fork", full_pt_regs, 0),
+
+
+       NS_MEM_FROM("ret_from_sys_call", "ret_from_fork",
+               partial_pt_regs,
+               BB_SKIP(R11)),
+       NS_MEM("ret_from_sys_call", partial_pt_regs, 0),
+
+       NS_MEM("retint_restore_args",
+               partial_pt_regs,
+               BB_SKIP(RAX) | BB_SKIP(RCX)),
+
+       NS_MEM("retint_swapgs",
+               partial_pt_regs,
+               BB_SKIP(RAX) | BB_SKIP(RCX)),
+
+       /* Now the cases that pass data in registers.  We do not check any
+        * memory state for these cases.
+        */
+
+       NS_REG("bad_put_user",
+               all_regs,
+               BB_SKIP(RAX) | BB_SKIP(RCX) | BB_SKIP(R8)),
+
+       NS_REG("bad_get_user",
+               all_regs,
+               BB_SKIP(RAX) | BB_SKIP(RCX) | BB_SKIP(R8)),
+
+       NS_REG("bad_to_user",
+               all_regs,
+               BB_SKIP(RAX) | BB_SKIP(RCX)),
+
+       NS_REG("ia32_ptregs_common",
+               all_regs,
+               0),
+
+       NS_REG("copy_user_generic_unrolled",
+               all_regs,
+               BB_SKIP(RAX) | BB_SKIP(RCX)),
+
+       NS_REG("copy_user_generic_string",
+               all_regs,
+               BB_SKIP(RAX) | BB_SKIP(RCX)),
+
+       NS_REG("irq_return",
+               all_regs,
+               0),
+
+       /* Finally the cases that pass data in both registers and memory.
+        */
+
+       NS("invalid_TSS", error_code, all_regs, 0, 0, 0),
+       NS("segment_not_present", error_code, all_regs, 0, 0, 0),
+       NS("alignment_check", error_code, all_regs, 0, 0, 0),
+       NS("page_fault", error_code, all_regs, 0, 0, 0),
+       NS("general_protection", error_code, all_regs, 0, 0, 0),
+       NS("error_entry", error_code_rax, all_regs, 0, BB_SKIP(RAX), -0x10),
+       NS("common_interrupt", error_code, all_regs, 0, 0, -0x8),
+};
+
+static const char *bb_spurious[] = {
+                               /* schedule */
+       "thread_return",
+                               /* ret_from_fork */
+       "rff_action",
+       "rff_trace",
+                               /* system_call */
+       "ret_from_sys_call",
+       "sysret_check",
+       "sysret_careful",
+       "sysret_signal",
+       "badsys",
+       "tracesys",
+       "int_ret_from_sys_call",
+       "int_with_check",
+       "int_careful",
+       "int_very_careful",
+       "int_signal",
+       "int_restore_rest",
+                               /* common_interrupt */
+       "ret_from_intr",
+       "exit_intr",
+       "retint_with_reschedule",
+       "retint_check",
+       "retint_swapgs",
+       "retint_restore_args",
+       "restore_args",
+       "irq_return",
+       "bad_iret",
+       "retint_careful",
+       "retint_signal",
+#ifdef CONFIG_PREEMPT
+       "retint_kernel",
+#endif /* CONFIG_PREEMPT */
+                               /* .macro paranoidexit */
+#ifdef CONFIG_TRACE_IRQFLAGS
+       "paranoid_exit0",
+       "paranoid_userspace0",
+       "paranoid_restore0",
+       "paranoid_swapgs0",
+       "paranoid_schedule0",
+#endif /* CONFIG_TRACE_IRQFLAGS */
+       "paranoid_exit1",
+       "paranoid_swapgs1",
+       "paranoid_restore1",
+       "paranoid_userspace1",
+       "paranoid_schedule1",
+                               /* error_entry */
+       "error_swapgs",
+       "error_sti",
+       "error_exit",
+       "error_kernelspace",
+                               /* load_gs_index */
+       "gs_change",
+       "bad_gs",
+                               /* ia32_sysenter_target */
+       "sysenter_do_call",
+       "sysenter_tracesys",
+                               /* ia32_cstar_target */
+       "cstar_do_call",
+       "cstar_tracesys",
+       "ia32_badarg",
+                               /* ia32_syscall */
+       "ia32_do_syscall",
+       "ia32_sysret",
+       "ia32_tracesys",
+       "ia32_badsys",
+#ifdef CONFIG_HIBERNATION
+                               /* restore_image */
+       "loop",
+       "done",
+#endif /* CONFIG_HIBERNATION */
+#ifdef CONFIG_KPROBES
+                               /* jprobe_return */
+       "jprobe_return_end",
+                               /* kretprobe_trampoline_holder */
+       "kretprobe_trampoline",
+#endif /* CONFIG_KPROBES */
+#ifdef CONFIG_KEXEC
+                               /* relocate_kernel */
+       "relocate_new_kernel",
+#endif /* CONFIG_KEXEC */
+#ifdef CONFIG_XEN
+                               /* arch/i386/xen/xen-asm.S */
+       "xen_irq_enable_direct_end",
+       "xen_irq_disable_direct_end",
+       "xen_save_fl_direct_end",
+       "xen_restore_fl_direct_end",
+       "xen_iret_start_crit",
+       "iret_restore_end",
+       "xen_iret_end_crit",
+       "hyper_iret",
+#endif /* CONFIG_XEN */
+};
+
+static const char *bb_hardware_handlers[] = {
+       "system_call",
+       "common_interrupt",
+       "error_entry",
+       "debug",
+       "nmi",
+       "int3",
+       "double_fault",
+       "stack_segment",
+       "machine_check",
+       "kdb_call",
+};
+
+static int
+bb_hardware_pushed_arch(kdb_machreg_t rsp,
+                       const struct kdb_activation_record *ar)
+{
+       /* x86_64 interrupt stacks are 16 byte aligned and you must get the
+        * next rsp from stack, it cannot be statically calculated.  Do not
+        * include the word at rsp, it is pushed by hardware but is treated as
+        * a normal software return value.
+        *
+        * When an IST switch occurs (e.g. NMI) then the saved rsp points to
+        * another stack entirely.  Assume that the IST stack is 16 byte
+        * aligned and just return the size of the hardware data on this stack.
+        * The stack unwind code will take care of the stack switch.
+        */
+       kdb_machreg_t saved_rsp = *((kdb_machreg_t *)rsp + 3);
+       int hardware_pushed = saved_rsp - rsp - KDB_WORD_SIZE;
+       if (hardware_pushed < 4 * KDB_WORD_SIZE ||
+           saved_rsp < ar->stack.logical_start ||
+           saved_rsp >= ar->stack.logical_end)
+               return 4 * KDB_WORD_SIZE;
+       else
+               return hardware_pushed;
+}
+
+static void
+bb_start_block0(void)
+{
+       bb_reg_code_set_value(BBRG_RAX, BBRG_RAX);
+       bb_reg_code_set_value(BBRG_RBX, BBRG_RBX);
+       bb_reg_code_set_value(BBRG_RCX, BBRG_RCX);
+       bb_reg_code_set_value(BBRG_RDX, BBRG_RDX);
+       bb_reg_code_set_value(BBRG_RDI, BBRG_RDI);
+       bb_reg_code_set_value(BBRG_RSI, BBRG_RSI);
+       bb_reg_code_set_value(BBRG_RBP, BBRG_RBP);
+       bb_reg_code_set_value(BBRG_RSP, BBRG_OSP);
+       bb_reg_code_set_value(BBRG_R8, BBRG_R8);
+       bb_reg_code_set_value(BBRG_R9, BBRG_R9);
+       bb_reg_code_set_value(BBRG_R10, BBRG_R10);
+       bb_reg_code_set_value(BBRG_R11, BBRG_R11);
+       bb_reg_code_set_value(BBRG_R12, BBRG_R12);
+       bb_reg_code_set_value(BBRG_R13, BBRG_R13);
+       bb_reg_code_set_value(BBRG_R14, BBRG_R14);
+       bb_reg_code_set_value(BBRG_R15, BBRG_R15);
+}
+
+/* x86_64 does not have a special case for __switch_to */
+
+static void
+bb_fixup_switch_to(char *p)
+{
+}
+
+static int
+bb_asmlinkage_arch(void)
+{
+       return strncmp(bb_func_name, "__down", 6) == 0 ||
+              strncmp(bb_func_name, "__up", 4) == 0 ||
+              strncmp(bb_func_name, "stub_", 5) == 0 ||
+              strcmp(bb_func_name, "ret_from_fork") == 0 ||
+              strcmp(bb_func_name, "ptregscall_common") == 0;
+}
+
+#else  /* !CONFIG_X86_64 */
+
+/* Registers that can be used to pass parameters, in the order that parameters
+ * are passed.
+ */
+
+const static enum bb_reg_code
+bb_param_reg[] = {
+       BBRG_RAX,
+       BBRG_RDX,
+       BBRG_RCX,
+};
+
+const static enum bb_reg_code
+bb_preserved_reg[] = {
+       BBRG_RBX,
+       BBRG_RBP,
+       BBRG_RSP,
+       BBRG_RSI,
+       BBRG_RDI,
+};
+
+static const struct bb_mem_contains full_pt_regs[] = {
+       { 0x18, BBRG_RAX },
+       { 0x14, BBRG_RBP },
+       { 0x10, BBRG_RDI },
+       { 0x0c, BBRG_RSI },
+       { 0x08, BBRG_RDX },
+       { 0x04, BBRG_RCX },
+       { 0x00, BBRG_RBX },
+};
+static const struct bb_mem_contains no_memory[] = {
+};
+/* Hardware has already pushed an error_code on the stack.  Use undefined just
+ * to set the initial stack offset.
+ */
+static const struct bb_mem_contains error_code[] = {
+       { 0x0, BBRG_UNDEFINED },
+};
+/* rbx already pushed */
+static const struct bb_mem_contains rbx_pushed[] = {
+       { 0x0, BBRG_RBX },
+};
+#ifdef CONFIG_MATH_EMULATION
+static const struct bb_mem_contains mem_fpu_reg_round[] = {
+       { 0xc, BBRG_RBP },
+       { 0x8, BBRG_RSI },
+       { 0x4, BBRG_RDI },
+       { 0x0, BBRG_RBX },
+};
+#endif /* CONFIG_MATH_EMULATION */
+
+static const struct bb_reg_contains all_regs[] = {
+       [BBRG_RAX] = { BBRG_RAX, 0 },
+       [BBRG_RBX] = { BBRG_RBX, 0 },
+       [BBRG_RCX] = { BBRG_RCX, 0 },
+       [BBRG_RDX] = { BBRG_RDX, 0 },
+       [BBRG_RDI] = { BBRG_RDI, 0 },
+       [BBRG_RSI] = { BBRG_RSI, 0 },
+       [BBRG_RBP] = { BBRG_RBP, 0 },
+       [BBRG_RSP] = { BBRG_OSP, 0 },
+};
+static const struct bb_reg_contains no_regs[] = {
+};
+#ifdef CONFIG_MATH_EMULATION
+static const struct bb_reg_contains reg_fpu_reg_round[] = {
+       [BBRG_RBP] = { BBRG_OSP, -0x4 },
+       [BBRG_RSP] = { BBRG_OSP, -0x10 },
+};
+#endif /* CONFIG_MATH_EMULATION */
+
+static struct bb_name_state bb_special_cases[] = {
+
+       /* First the cases that pass data only in memory.  We do not check any
+        * register state for these cases.
+        */
+
+       /* Simple cases, no exceptions */
+       NS_MEM("check_userspace", full_pt_regs, 0),
+       NS_MEM("device_not_available_emulate", full_pt_regs, 0),
+       NS_MEM("ldt_ss", full_pt_regs, 0),
+       NS_MEM("no_singlestep", full_pt_regs, 0),
+       NS_MEM("restore_all", full_pt_regs, 0),
+       NS_MEM("restore_nocheck", full_pt_regs, 0),
+       NS_MEM("restore_nocheck_notrace", full_pt_regs, 0),
+       NS_MEM("ret_from_exception", full_pt_regs, 0),
+       NS_MEM("ret_from_fork", full_pt_regs, 0),
+       NS_MEM("ret_from_intr", full_pt_regs, 0),
+       NS_MEM("work_notifysig", full_pt_regs, 0),
+       NS_MEM("work_pending", full_pt_regs, 0),
+
+#ifdef CONFIG_PREEMPT
+       NS_MEM("resume_kernel", full_pt_regs, 0),
+#endif /* CONFIG_PREEMPT */
+
+       NS_MEM("common_interrupt", error_code, 0),
+       NS_MEM("error_code", error_code, 0),
+
+       NS_MEM("bad_put_user", rbx_pushed, 0),
+
+       NS_MEM_FROM("resume_userspace", "syscall_badsys",
+               full_pt_regs, BB_SKIP(RAX)),
+       NS_MEM_FROM("resume_userspace", "syscall_fault",
+               full_pt_regs, BB_SKIP(RAX)),
+       NS_MEM_FROM("resume_userspace", "syscall_trace_entry",
+               full_pt_regs, BB_SKIP(RAX)),
+       /* Too difficult to trace through the various vm86 functions for now.
+        * They are C functions that start off with some memory state, fiddle
+        * the registers then jmp directly to resume_userspace.  For the
+        * moment, just assume that they are valid and do no checks.
+        */
+       NS_FROM("resume_userspace", "do_int",
+               no_memory, no_regs, 0, 0, 0),
+       NS_FROM("resume_userspace", "do_sys_vm86",
+               no_memory, no_regs, 0, 0, 0),
+       NS_FROM("resume_userspace", "handle_vm86_fault",
+               no_memory, no_regs, 0, 0, 0),
+       NS_FROM("resume_userspace", "handle_vm86_trap",
+               no_memory, no_regs, 0, 0, 0),
+       NS_MEM("resume_userspace", full_pt_regs, 0),
+
+       NS_MEM_FROM("syscall_badsys", "ia32_sysenter_target",
+               full_pt_regs, BB_SKIP(RBP)),
+       NS_MEM("syscall_badsys", full_pt_regs, 0),
+
+       NS_MEM_FROM("syscall_call", "syscall_trace_entry",
+               full_pt_regs, BB_SKIP(RAX)),
+       NS_MEM("syscall_call", full_pt_regs, 0),
+
+       NS_MEM_FROM("syscall_exit", "syscall_trace_entry",
+               full_pt_regs, BB_SKIP(RAX)),
+       NS_MEM("syscall_exit", full_pt_regs, 0),
+
+       NS_MEM_FROM("syscall_exit_work", "ia32_sysenter_target",
+               full_pt_regs, BB_SKIP(RAX) | BB_SKIP(RBP)),
+       NS_MEM_FROM("syscall_exit_work", "system_call",
+               full_pt_regs, BB_SKIP(RAX)),
+       NS_MEM("syscall_exit_work", full_pt_regs, 0),
+
+       NS_MEM_FROM("syscall_trace_entry", "ia32_sysenter_target",
+               full_pt_regs, BB_SKIP(RBP)),
+       NS_MEM_FROM("syscall_trace_entry", "system_call",
+               full_pt_regs, BB_SKIP(RAX)),
+       NS_MEM("syscall_trace_entry", full_pt_regs, 0),
+
+       /* Now the cases that pass data in registers.  We do not check any
+        * memory state for these cases.
+        */
+
+       NS_REG("syscall_fault", all_regs, 0),
+
+       NS_REG("bad_get_user", all_regs,
+               BB_SKIP(RAX) | BB_SKIP(RDX)),
+
+       /* Finally the cases that pass data in both registers and memory.
+       */
+
+       /* This entry is redundant now because bb_fixup_switch_to() hides the
+        * jmp __switch_to case, however the entry is left here as
+        * documentation.
+        *
+        * NS("__switch_to", no_memory, no_regs, 0, 0, 0),
+        */
+
+       NS("iret_exc", no_memory, all_regs, 0, 0, 0x20),
+
+#ifdef CONFIG_MATH_EMULATION
+       NS("fpu_reg_round", mem_fpu_reg_round, reg_fpu_reg_round, 0, 0, 0),
+#endif /* CONFIG_MATH_EMULATION */
+};
+
+static const char *bb_spurious[] = {
+                               /* ret_from_exception */
+       "ret_from_intr",
+       "check_userspace",
+       "resume_userspace",
+                               /* resume_kernel */
+#ifdef CONFIG_PREEMPT
+       "need_resched",
+#endif /* CONFIG_PREEMPT */
+                               /* ia32_sysenter_target */
+       "sysenter_past_esp",
+                               /* system_call */
+       "no_singlestep",
+       "syscall_call",
+       "syscall_exit",
+       "restore_all",
+       "restore_nocheck",
+       "restore_nocheck_notrace",
+       "ldt_ss",
+       /* do not include iret_exc, it is in a .fixup section */
+                               /* work_pending */
+       "work_resched",
+       "work_notifysig",
+#ifdef CONFIG_VM86
+       "work_notifysig_v86",
+#endif /* CONFIG_VM86 */
+                               /* page_fault */
+       "error_code",
+                               /* device_not_available */
+       "device_not_available_emulate",
+                               /* debug */
+       "debug_esp_fix_insn",
+       "debug_stack_correct",
+                               /* nmi */
+       "nmi_stack_correct",
+       "nmi_stack_fixup",
+       "nmi_debug_stack_check",
+       "nmi_espfix_stack",
+#ifdef CONFIG_HIBERNATION
+                               /* restore_image */
+       "copy_loop",
+       "done",
+#endif /* CONFIG_HIBERNATION */
+#ifdef CONFIG_KPROBES
+                               /* jprobe_return */
+       "jprobe_return_end",
+#endif /* CONFIG_KPROBES */
+#ifdef CONFIG_KEXEC
+                               /* relocate_kernel */
+       "relocate_new_kernel",
+#endif /* CONFIG_KEXEC */
+#ifdef CONFIG_MATH_EMULATION
+                               /* assorted *.S files in arch/i386/math_emu */
+       "Denorm_done",
+       "Denorm_shift_more_than_32",
+       "Denorm_shift_more_than_63",
+       "Denorm_shift_more_than_64",
+       "Do_unmasked_underflow",
+       "Exp_not_underflow",
+       "fpu_Arith_exit",
+       "fpu_reg_round",
+       "fpu_reg_round_signed_special_exit",
+       "fpu_reg_round_special_exit",
+       "L_accum_done",
+       "L_accum_loaded",
+       "L_accum_loop",
+       "L_arg1_larger",
+       "L_bugged",
+       "L_bugged_1",
+       "L_bugged_2",
+       "L_bugged_3",
+       "L_bugged_4",
+       "L_bugged_denorm_486",
+       "L_bugged_round24",
+       "L_bugged_round53",
+       "L_bugged_round64",
+       "LCheck_24_round_up",
+       "LCheck_53_round_up",
+       "LCheck_Round_Overflow",
+       "LCheck_truncate_24",
+       "LCheck_truncate_53",
+       "LCheck_truncate_64",
+       "LDenormal_adj_exponent",
+       "L_deNormalised",
+       "LDo_24_round_up",
+       "LDo_2nd_32_bits",
+       "LDo_2nd_div",
+       "LDo_3rd_32_bits",
+       "LDo_3rd_div",
+       "LDo_53_round_up",
+       "LDo_64_round_up",
+       "L_done",
+       "LDo_truncate_24",
+       "LDown_24",
+       "LDown_53",
+       "LDown_64",
+       "L_entry_bugged",
+       "L_error_exit",
+       "L_exactly_32",
+       "L_exception_exit",
+       "L_exit",
+       "L_exit_nuo_valid",
+       "L_exit_nuo_zero",
+       "L_exit_valid",
+       "L_extent_zero",
+       "LFirst_div_done",
+       "LFirst_div_not_1",
+       "L_Full_Division",
+       "LGreater_Half_24",
+       "LGreater_Half_53",
+       "LGreater_than_1",
+       "LLess_than_1",
+       "L_Make_denorm",
+       "L_more_31_no_low",
+       "L_more_63_no_low",
+       "L_more_than_31",
+       "L_more_than_63",
+       "L_more_than_64",
+       "L_more_than_65",
+       "L_more_than_95",
+       "L_must_be_zero",
+       "L_n_exit",
+       "L_no_adjust",
+       "L_no_bit_lost",
+       "L_no_overflow",
+       "L_no_precision_loss",
+       "L_Normalised",
+       "L_norm_bugged",
+       "L_n_shift_1",
+       "L_nuo_shift_1",
+       "L_overflow",
+       "L_precision_lost_down",
+       "L_precision_lost_up",
+       "LPrevent_2nd_overflow",
+       "LPrevent_3rd_overflow",
+       "LPseudoDenormal",
+       "L_Re_normalise",
+       "LResult_Normalised",
+       "L_round",
+       "LRound_large",
+       "LRound_nearest_24",
+       "LRound_nearest_53",
+       "LRound_nearest_64",
+       "LRound_not_small",
+       "LRound_ovfl",
+       "LRound_precision",
+       "LRound_prep",
+       "L_round_the_result",
+       "LRound_To_24",
+       "LRound_To_53",
+       "LRound_To_64",
+       "LSecond_div_done",
+       "LSecond_div_not_1",
+       "L_shift_1",
+       "L_shift_32",
+       "L_shift_65_nc",
+       "L_shift_done",
+       "Ls_less_than_32",
+       "Ls_more_than_63",
+       "Ls_more_than_95",
+       "L_Store_significand",
+       "L_subtr",
+       "LTest_over",
+       "LTruncate_53",
+       "LTruncate_64",
+       "L_underflow",
+       "L_underflow_to_zero",
+       "LUp_24",
+       "LUp_53",
+       "LUp_64",
+       "L_zero",
+       "Normalise_result",
+       "Signal_underflow",
+       "sqrt_arg_ge_2",
+       "sqrt_get_more_precision",
+       "sqrt_more_prec_large",
+       "sqrt_more_prec_ok",
+       "sqrt_more_prec_small",
+       "sqrt_near_exact",
+       "sqrt_near_exact_large",
+       "sqrt_near_exact_ok",
+       "sqrt_near_exact_small",
+       "sqrt_near_exact_x",
+       "sqrt_prelim_no_adjust",
+       "sqrt_round_result",
+       "sqrt_stage_2_done",
+       "sqrt_stage_2_error",
+       "sqrt_stage_2_finish",
+       "sqrt_stage_2_positive",
+       "sqrt_stage_3_error",
+       "sqrt_stage_3_finished",
+       "sqrt_stage_3_no_error",
+       "sqrt_stage_3_positive",
+       "Unmasked_underflow",
+       "xExp_not_underflow",
+#endif /* CONFIG_MATH_EMULATION */
+};
+
+static const char *bb_hardware_handlers[] = {
+       "ret_from_exception",
+       "system_call",
+       "work_pending",
+       "syscall_fault",
+       "page_fault",
+       "coprocessor_error",
+       "simd_coprocessor_error",
+       "device_not_available",
+       "debug",
+       "nmi",
+       "int3",
+       "overflow",
+       "bounds",
+       "invalid_op",
+       "coprocessor_segment_overrun",
+       "invalid_TSS",
+       "segment_not_present",
+       "stack_segment",
+       "general_protection",
+       "alignment_check",
+       "kdb_call",
+       "divide_error",
+       "machine_check",
+       "spurious_interrupt_bug",
+};
+
+static int
+bb_hardware_pushed_arch(kdb_machreg_t rsp,
+                       const struct kdb_activation_record *ar)
+{
+       return (2 * KDB_WORD_SIZE);
+}
+
+static void
+bb_start_block0(void)
+{
+       bb_reg_code_set_value(BBRG_RAX, BBRG_RAX);
+       bb_reg_code_set_value(BBRG_RBX, BBRG_RBX);
+       bb_reg_code_set_value(BBRG_RCX, BBRG_RCX);
+       bb_reg_code_set_value(BBRG_RDX, BBRG_RDX);
+       bb_reg_code_set_value(BBRG_RDI, BBRG_RDI);
+       bb_reg_code_set_value(BBRG_RSI, BBRG_RSI);
+       bb_reg_code_set_value(BBRG_RBP, BBRG_RBP);
+       bb_reg_code_set_value(BBRG_RSP, BBRG_OSP);
+}
+
+/* The i386 code that switches stack in a context switch is an extremely
+ * special case.  It saves the rip pointing to a label that is not otherwise
+ * referenced, saves the current rsp then pushes a word.  The magic code that
+ * resumes the new task picks up the saved rip and rsp, effectively referencing
+ * a label that otherwise is not used and ignoring the pushed word.
+ *
+ * The simplest way to handle this very strange case is to recognise jmp
+ * address <__switch_to> and treat it as a popfl instruction.  This avoids
+ * terminating the block on this jmp and removes one word from the stack state,
+ * which is the end effect of all the magic code.
+ *
+ * Called with the instruction line, starting after the first ':'.
+ */
+
+static void
+bb_fixup_switch_to(char *p)
+{
+       char *p1 = p;
+       p += strspn(p, " \t");          /* start of instruction */
+       if (strncmp(p, "jmp", 3))
+               return;
+       p += strcspn(p, " \t");         /* end of instruction */
+       p += strspn(p, " \t");          /* start of address */
+       p += strcspn(p, " \t");         /* end of address */
+       p += strspn(p, " \t");          /* start of comment */
+       if (strcmp(p, "<__switch_to>") == 0)
+               strcpy(p1, "popfl");
+}
+
+static int
+bb_asmlinkage_arch(void)
+{
+       return strcmp(bb_func_name, "ret_from_exception") == 0 ||
+              strcmp(bb_func_name, "syscall_trace_entry") == 0;
+}
+
+#endif /* CONFIG_X86_64 */
+
+
+/*============================================================================*/
+/*                                                                            */
+/* Common code and data.                                                      */
+/*                                                                            */
+/*============================================================================*/
+
+
+/* Tracking registers by decoding the instructions is quite a bit harder than
+ * doing the same tracking using compiler generated information.  Register
+ * contents can remain in the same register, they can be copied to other
+ * registers, they can be stored on stack or they can be modified/overwritten.
+ * At any one time, there are 0 or more copies of the original value that was
+ * supplied in each register on input to the current function.  If a register
+ * exists in multiple places, one copy of that register is the master version,
+ * the others are temporary copies which may or may not be destroyed before the
+ * end of the function.
+ *
+ * The compiler knows which copy of a register is the master and which are
+ * temporary copies, which makes it relatively easy to track register contents
+ * as they are saved and restored.  Without that compiler based knowledge, this
+ * code has to track _every_ possible copy of each register, simply because we
+ * do not know which is the master copy and which are temporary copies which
+ * may be destroyed later.
+ *
+ * It gets worse: registers that contain parameters can be copied to other
+ * registers which are then saved on stack in a lower level function.  Also the
+ * stack pointer may be held in multiple registers (typically RSP and RBP)
+ * which contain different offsets from the base of the stack on entry to this
+ * function.  All of which means that we have to track _all_ register
+ * movements, or at least as much as possible.
+ *
+ * Start with the basic block that contains the start of the function, by
+ * definition all registers contain their initial value.  Track each
+ * instruction's effect on register contents, this includes reading from a
+ * parameter register before any write to that register, IOW the register
+ * really does contain a parameter.  The register state is represented by a
+ * dynamically sized array with each entry containing :-
+ *
+ *   Register name
+ *   Location it is copied to (another register or stack + offset)
+ *
+ * Besides the register tracking array, we track which parameter registers are
+ * read before being written, to determine how many parameters are passed in
+ * registers.  We also track which registers contain stack pointers, including
+ * their offset from the original stack pointer on entry to the function.
+ *
+ * At each exit from the current basic block (via JMP instruction or drop
+ * through), the register state is cloned to form the state on input to the
+ * target basic block and the target is marked for processing using this state.
+ * When there are multiple ways to enter a basic block (e.g. several JMP
+ * instructions referencing the same target) then there will be multiple sets
+ * of register state to form the "input" for that basic block, there is no
+ * guarantee that all paths to that block will have the same register state.
+ *
+ * As each target block is processed, all the known sets of register state are
+ * merged to form a suitable subset of the state which agrees with all the
+ * inputs.  The most common case is where one path to this block copies a
+ * register to another register but another path does not, therefore the copy
+ * is only a temporary and should not be propogated into this block.
+ *
+ * If the target block already has an input state from the current transfer
+ * point and the new input state is identical to the previous input state then
+ * we have reached a steady state for the arc from the current location to the
+ * target block.  Therefore there is no need to process the target block again.
+ *
+ * The steps of "process a block, create state for target block(s), pick a new
+ * target block, merge state for target block, process target block" will
+ * continue until all the state changes have propogated all the way down the
+ * basic block tree, including round any cycles in the tree.  The merge step
+ * only deletes tracking entries from the input state(s), it never adds a
+ * tracking entry.  Therefore the overall algorithm is guaranteed to converge
+ * to a steady state, the worst possible case is that every tracking entry into
+ * a block is deleted, which will result in an empty output state.
+ *
+ * As each instruction is decoded, it is checked to see if this is the point at
+ * which execution left this function.  This can be a call to another function
+ * (actually the return address to this function) or is the instruction which
+ * was about to be executed when an interrupt occurred (including an oops).
+ * Save the register state at this point.
+ *
+ * We always know what the registers contain when execution left this function.
+ * For an interrupt, the registers are in struct pt_regs.  For a call to
+ * another function, we have already deduced the register state on entry to the
+ * other function by unwinding to the start of that function.  Given the
+ * register state on exit from this function plus the known register contents
+ * on entry to the next function, we can determine the stack pointer value on
+ * input to this function.  That in turn lets us calculate the address of input
+ * registers that have been stored on stack, giving us the input parameters.
+ * Finally the stack pointer gives us the return address which is the exit
+ * point from the calling function, repeat the unwind process on that function.
+ *
+ * The data that tracks which registers contain input parameters is function
+ * global, not local to any basic block.  To determine which input registers
+ * contain parameters, we have to decode the entire function.  Otherwise an
+ * exit early in the function might not have read any parameters yet.
+ */
+
+/* Record memory contents in terms of the values that were passed to this
+ * function, IOW track which memory locations contain an input value.  A memory
+ * location's contents can be undefined, it can contain an input register value
+ * or it can contain an offset from the original stack pointer.
+ *
+ * This structure is used to record register contents that have been stored in
+ * memory.  Location (BBRG_OSP + 'offset_address') contains the input value
+ * from register 'value'.  When 'value' is BBRG_OSP then offset_value contains
+ * the offset from the original stack pointer that was stored in this memory
+ * location.  When 'value' is not BBRG_OSP then the memory location contains
+ * the original contents of an input register and offset_value is ignored.
+ *
+ * An input register 'value' can be stored in more than one register and/or in
+ * more than one memory location.
+ */
+
+struct bb_memory_contains
+{
+       short offset_address;
+       enum bb_reg_code value: 8;
+       short offset_value;
+};
+
+/* Track the register state in each basic block. */
+
+struct bb_reg_state
+{
+       /* Indexed by register value 'reg - BBRG_RAX' */
+       struct bb_reg_contains contains[KDB_INT_REGISTERS];
+       int ref_count;
+       int mem_count;
+       /* dynamic size for memory locations, see mem_count */
+       struct bb_memory_contains memory[0];
+};
+
+static struct bb_reg_state *bb_reg_state, *bb_exit_state;
+static int bb_reg_state_max, bb_reg_params, bb_memory_params;
+
+struct bb_actual
+{
+       bfd_vma value;
+       int valid;
+};
+
+/* Contains the actual hex value of a register, plus a valid bit.  Indexed by
+ * register value 'reg - BBRG_RAX'
+ */
+static struct bb_actual bb_actual[KDB_INT_REGISTERS];
+
+static bfd_vma bb_func_start, bb_func_end;
+static bfd_vma bb_common_interrupt, bb_error_entry, bb_ret_from_intr,
+              bb_thread_return, bb_sync_regs, bb_save_v86_state,
+              bb__sched_text_start, bb__sched_text_end;
+
+/* Record jmp instructions, both conditional and unconditional.  These form the
+ * arcs between the basic blocks.  This is also used to record the state when
+ * one block drops through into the next.
+ *
+ * A bb can have multiple associated bb_jmp entries, one for each jcc
+ * instruction plus at most one bb_jmp for the drop through case.  If a bb
+ * drops through to the next bb then the drop through bb_jmp entry will be the
+ * last entry in the set of bb_jmp's that are associated with the bb.  This is
+ * enforced by the fact that jcc entries are added during the disassembly phase
+ * of pass 1, the drop through entries are added near the end of pass 1.
+ *
+ * At address 'from' in this block, we have a jump to address 'to'.  The
+ * register state at 'from' is copied to the target block.
+ */
+
+struct bb_jmp
+{
+       bfd_vma from;
+       bfd_vma to;
+       struct bb_reg_state *state;
+       unsigned int drop_through: 1;
+};
+
+struct bb
+{
+       bfd_vma start;
+       /* The end address of a basic block is sloppy.  It can be the first
+        * byte of the last instruction in the block or it can be the last byte
+        * of the block.
+        */
+       bfd_vma end;
+       unsigned int changed: 1;
+       unsigned int drop_through: 1;
+};
+
+static struct bb **bb_list, *bb_curr;
+static int bb_max, bb_count;
+
+static struct bb_jmp *bb_jmp_list;
+static int bb_jmp_max, bb_jmp_count;
+
+/* Add a new bb entry to the list.  This does an insert sort. */
+
+static struct bb *
+bb_new(bfd_vma order)
+{
+       int i, j;
+       struct bb *bb, *p;
+       if (bb_giveup)
+               return NULL;
+       if (bb_count == bb_max) {
+               struct bb **bb_list_new;
+               bb_max += 10;
+               bb_list_new = debug_kmalloc(bb_max*sizeof(*bb_list_new),
+                                           GFP_ATOMIC);
+               if (!bb_list_new) {
+                       kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
+                       bb_giveup = 1;
+                       return NULL;
+               }
+               memcpy(bb_list_new, bb_list, bb_count*sizeof(*bb_list));
+               debug_kfree(bb_list);
+               bb_list = bb_list_new;
+       }
+       bb = debug_kmalloc(sizeof(*bb), GFP_ATOMIC);
+       if (!bb) {
+               kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
+               bb_giveup = 1;
+               return NULL;
+       }
+       memset(bb, 0, sizeof(*bb));
+       for (i = 0; i < bb_count; ++i) {
+               p = bb_list[i];
+               if ((p->start && p->start > order) ||
+                   (p->end && p->end > order))
+                       break;
+       }
+       for (j = bb_count-1; j >= i; --j)
+               bb_list[j+1] = bb_list[j];
+       bb_list[i] = bb;
+       ++bb_count;
+       return bb;
+}
+
+/* Add a new bb_jmp entry to the list.  This list is not sorted. */
+
+static struct bb_jmp *
+bb_jmp_new(bfd_vma from, bfd_vma to, unsigned int drop_through)
+{
+       struct bb_jmp *bb_jmp;
+       if (bb_giveup)
+               return NULL;
+       if (bb_jmp_count == bb_jmp_max) {
+               struct bb_jmp *bb_jmp_list_new;
+               bb_jmp_max += 10;
+               bb_jmp_list_new =
+                       debug_kmalloc(bb_jmp_max*sizeof(*bb_jmp_list_new),
+                                     GFP_ATOMIC);
+               if (!bb_jmp_list_new) {
+                       kdb_printf("\n\n%s: out of debug_kmalloc\n",
+                                  __FUNCTION__);
+                       bb_giveup = 1;
+                       return NULL;
+               }
+               memcpy(bb_jmp_list_new, bb_jmp_list,
+                      bb_jmp_count*sizeof(*bb_jmp_list));
+               debug_kfree(bb_jmp_list);
+               bb_jmp_list = bb_jmp_list_new;
+       }
+       bb_jmp = bb_jmp_list + bb_jmp_count++;
+       bb_jmp->from = from;
+       bb_jmp->to = to;
+       bb_jmp->drop_through = drop_through;
+       bb_jmp->state = NULL;
+       return bb_jmp;
+}
+
+static void
+bb_delete(int i)
+{
+       struct bb *bb = bb_list[i];
+       memcpy(bb_list+i, bb_list+i+1, (bb_count-i-1)*sizeof(*bb_list));
+       bb_list[--bb_count] = NULL;
+       debug_kfree(bb);
+}
+
+static struct bb *
+bb_add(bfd_vma start, bfd_vma end)
+{
+       int i;
+       struct bb *bb;
+       /* Ignore basic blocks whose start address is outside the current
+        * function.  These occur for call instructions and for tail recursion.
+        */
+       if (start &&
+           (start < bb_func_start || start >= bb_func_end))
+                      return NULL;
+       for (i = 0; i < bb_count; ++i) {
+               bb = bb_list[i];
+               if ((start && bb->start == start) ||
+                   (end && bb->end == end))
+                       return bb;
+       }
+       bb = bb_new(start ? start : end);
+       if (bb) {
+               bb->start = start;
+               bb->end = end;
+       }
+       return bb;
+}
+
+static struct bb_jmp *
+bb_jmp_add(bfd_vma from, bfd_vma to, unsigned int drop_through)
+{
+       int i;
+       struct bb_jmp *bb_jmp;
+       for (i = 0, bb_jmp = bb_jmp_list; i < bb_jmp_count; ++i, ++bb_jmp) {
+               if (bb_jmp->from == from &&
+                   bb_jmp->to == to &&
+                   bb_jmp->drop_through == drop_through)
+                       return bb_jmp;
+       }
+       bb_jmp = bb_jmp_new(from, to, drop_through);
+       return bb_jmp;
+}
+
+static unsigned long bb_curr_addr, bb_exit_addr;
+static char bb_buffer[256];    /* A bit too big to go on stack */
+
+/* Computed jmp uses 'jmp *addr(,%reg,[48])' where 'addr' is the start of a
+ * table of addresses that point into the current function.  Run the table and
+ * generate bb starts for each target address plus a bb_jmp from this address
+ * to the target address.
+ *
+ * Only called for 'jmp' instructions, with the pointer starting at 'jmp'.
+ */
+
+static void
+bb_pass1_computed_jmp(char *p)
+{
+       unsigned long table, scale;
+       kdb_machreg_t addr;
+       struct bb* bb;
+       p += strcspn(p, " \t");         /* end of instruction */
+       p += strspn(p, " \t");          /* start of address */
+       if (*p++ != '*')
+               return;
+       table = simple_strtoul(p, &p, 0);
+       if (strncmp(p, "(,%", 3) != 0)
+               return;
+       p += 3;
+       p += strcspn(p, ",");           /* end of reg */
+       if (*p++ != ',')
+               return;
+       scale = simple_strtoul(p, &p, 0);
+       if (scale != KDB_WORD_SIZE || strcmp(p, ")"))
+               return;
+       while (!bb_giveup) {
+               if (kdb_getword(&addr, table, sizeof(addr)))
+                       return;
+               if (addr < bb_func_start || addr >= bb_func_end)
+                       return;
+               bb = bb_add(addr, 0);
+               if (bb)
+                       bb_jmp_add(bb_curr_addr, addr, 0);
+               table += KDB_WORD_SIZE;
+       }
+}
+
+/* Pass 1, identify the start and end of each basic block */
+
+static int
+bb_dis_pass1(PTR file, const char *fmt, ...)
+{
+       int l = strlen(bb_buffer);
+       char *p;
+       va_list ap;
+       va_start(ap, fmt);
+       vsnprintf(bb_buffer + l, sizeof(bb_buffer) - l, fmt, ap);
+       va_end(ap);
+       if ((p = strchr(bb_buffer, '\n'))) {
+               *p = '\0';
+               /* ret[q], iret[q], sysexit, sysret, ud2a or jmp[q] end a
+                * block.  As does a call to a function marked noret.
+                */
+               p = bb_buffer;
+               p += strcspn(p, ":");
+               if (*p++ == ':') {
+                       bb_fixup_switch_to(p);
+                       p += strspn(p, " \t");  /* start of instruction */
+                       if (strncmp(p, "ret", 3) == 0 ||
+                           strncmp(p, "iret", 4) == 0 ||
+                           strncmp(p, "sysexit", 7) == 0 ||
+                           strncmp(p, "sysret", 6) == 0 ||
+                           strncmp(p, "ud2a", 4) == 0 ||
+                           strncmp(p, "jmp", 3) == 0) {
+                               if (strncmp(p, "jmp", 3) == 0)
+                                       bb_pass1_computed_jmp(p);
+                               bb_add(0, bb_curr_addr);
+                       };
+                       if (strncmp(p, "call", 4) == 0) {
+                               strsep(&p, " \t");      /* end of opcode */
+                               if (p)
+                                       p += strspn(p, " \t");  /* operand(s) */
+                               if (p && strchr(p, '<')) {
+                                       p = strchr(p, '<') + 1;
+                                       *strchr(p, '>') = '\0';
+                                       if (bb_noret(p))
+                                               bb_add(0, bb_curr_addr);
+                               }
+                       };
+               }
+               bb_buffer[0] = '\0';
+       }
+       return 0;
+}
+
+static void
+bb_printaddr_pass1(bfd_vma addr, disassemble_info *dip)
+{
+       kdb_symtab_t symtab;
+       unsigned int offset;
+       struct bb* bb;
+       /* disasm only calls the printaddr routine for the target of jmp, loop
+        * or call instructions, i.e. the start of a basic block.  call is
+        * ignored by bb_add because the target address is outside the current
+        * function.
+        */
+       dip->fprintf_func(dip->stream, "0x%lx", addr);
+       kdbnearsym(addr, &symtab);
+       if (symtab.sym_name) {
+               dip->fprintf_func(dip->stream, " <%s", symtab.sym_name);
+               if ((offset = addr - symtab.sym_start))
+                       dip->fprintf_func(dip->stream, "+0x%x", offset);
+               dip->fprintf_func(dip->stream, ">");
+       }
+       bb = bb_add(addr, 0);
+       if (bb)
+               bb_jmp_add(bb_curr_addr, addr, 0);
+}
+
+static void
+bb_pass1(void)
+{
+       int i;
+       unsigned long addr;
+       struct bb *bb;
+       struct bb_jmp *bb_jmp;
+
+       if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
+               kdb_printf("%s: func_name %s func_start " kdb_bfd_vma_fmt0
+                          " func_end " kdb_bfd_vma_fmt0 "\n",
+                          __FUNCTION__,
+                          bb_func_name,
+                          bb_func_start,
+                          bb_func_end);
+       kdb_di.fprintf_func = bb_dis_pass1;
+       kdb_di.print_address_func = bb_printaddr_pass1;
+
+       bb_add(bb_func_start, 0);
+       for (bb_curr_addr = bb_func_start;
+            bb_curr_addr < bb_func_end;
+            ++bb_curr_addr) {
+               unsigned char c;
+               if (kdb_getarea(c, bb_curr_addr)) {
+                       kdb_printf("%s: unreadable function code at ",
+                                  __FUNCTION__);
+                       kdb_symbol_print(bb_curr_addr, NULL, KDB_SP_DEFAULT);
+                       kdb_printf(", giving up\n");
+                       bb_giveup = 1;
+                       return;
+               }
+       }
+       for (addr = bb_func_start; addr < bb_func_end; ) {
+               bb_curr_addr = addr;
+               addr += kdba_id_printinsn(addr, &kdb_di);
+               kdb_di.fprintf_func(NULL, "\n");
+       }
+       if (bb_giveup)
+               goto out;
+
+       /* Special case: a block consisting of a single instruction which is
+        * both the target of a jmp and is also an ending instruction, so we
+        * add two blocks using the same address, one as a start and one as an
+        * end, in no guaranteed order.  The end must be ordered after the
+        * start.
+        */
+       for (i = 0; i < bb_count-1; ++i) {
+               struct bb *bb1 = bb_list[i], *bb2 = bb_list[i+1];
+               if (bb1->end && bb1->end == bb2->start) {
+                       bb = bb_list[i+1];
+                       bb_list[i+1] = bb_list[i];
+                       bb_list[i] = bb;
+               }
+       }
+
+       /* Some bb have a start address, some have an end address.  Collapse
+        * them into entries that have both start and end addresses.  The first
+        * entry is guaranteed to have a start address.
+        */
+       for (i = 0; i < bb_count-1; ++i) {
+               struct bb *bb1 = bb_list[i], *bb2 = bb_list[i+1];
+               if (bb1->end)
+                       continue;
+               if (bb2->start) {
+                       bb1->end = bb2->start - 1;
+                       bb1->drop_through = 1;
+                       bb_jmp_add(bb1->end, bb2->start, 1);
+               } else {
+                       bb1->end = bb2->end;
+                       bb_delete(i+1);
+               }
+       }
+       bb = bb_list[bb_count-1];
+       if (!bb->end)
+               bb->end = bb_func_end - 1;
+
+       /* It would be nice to check that all bb have a valid start and end
+        * address but there is just too much garbage code in the kernel to do
+        * that check.  Aligned functions in assembler code mean that there is
+        * space between the end of one function and the start of the next and
+        * that space contains previous code from the assembler's buffers.  It
+        * looks like dead code with nothing that branches to it, so no start
+        * address.  do_sys_vm86() ends with 'jmp resume_userspace' which the C
+        * compiler does not know about so gcc appends the normal exit code,
+        * again nothing branches to this dangling code.
+        *
+        * The best we can do is delete bb entries with no start address.
+        */
+       for (i = 0; i < bb_count; ++i) {
+               struct bb *bb = bb_list[i];
+               if (!bb->start)
+                       bb_delete(i--);
+       }
+       for (i = 0; i < bb_count; ++i) {
+               struct bb *bb = bb_list[i];
+               if (!bb->end) {
+                       kdb_printf("%s: incomplete bb state\n", __FUNCTION__);
+                       bb_giveup = 1;
+                       goto debug;
+               }
+       }
+
+out:
+       if (!KDB_DEBUG(BB))
+               return;
+debug:
+       kdb_printf("%s: end\n", __FUNCTION__);
+       for (i = 0; i < bb_count; ++i) {
+               bb = bb_list[i];
+               kdb_printf("  bb[%d] start "
+                          kdb_bfd_vma_fmt0
+                          " end " kdb_bfd_vma_fmt0
+                          " drop_through %d",
+                          i, bb->start, bb->end, bb->drop_through);
+               kdb_printf("\n");
+       }
+       for (i = 0; i < bb_jmp_count; ++i) {
+               bb_jmp = bb_jmp_list + i;
+               kdb_printf("  bb_jmp[%d] from "
+                          kdb_bfd_vma_fmt0
+                          " to " kdb_bfd_vma_fmt0
+                          " drop_through %d\n",
+                          i, bb_jmp->from, bb_jmp->to, bb_jmp->drop_through);
+       }
+}
+
+/* Pass 2, record register changes in each basic block */
+
+/* For each opcode that we care about, indicate how it uses its operands.  Most
+ * opcodes can be handled generically because they completely specify their
+ * operands in the instruction, however many opcodes have side effects such as
+ * reading or writing rax or updating rsp.  Instructions that change registers
+ * that are not listed in the operands must be handled as special cases.  In
+ * addition, instructions that copy registers while preserving their contents
+ * (push, pop, mov) or change the contents in a well defined way (add with an
+ * immediate, lea) must be handled as special cases in order to track the
+ * register contents.
+ *
+ * The tables below only list opcodes that are actually used in the Linux
+ * kernel, so they omit most of the floating point and all of the SSE type
+ * instructions.  The operand usage entries only cater for accesses to memory
+ * and to the integer registers, accesses to floating point registers and flags
+ * are not relevant for kernel backtraces.
+ */
+
+enum bb_operand_usage {
+       BBOU_UNKNOWN = 0,
+               /* generic entries.  because xchg can do any combinations of
+                * read src, write src, read dst and  write dst we need to
+                * define all 16 possibilities.  These are ordered by rs = 1,
+                * rd = 2, ws = 4, wd = 8, bb_usage_x*() functions rely on this
+                * order.
+                */
+       BBOU_RS = 1,    /* read src */          /*  1 */
+       BBOU_RD,        /* read dst */          /*  2 */
+       BBOU_RSRD,                              /*  3 */
+       BBOU_WS,        /* write src */         /*  4 */
+       BBOU_RSWS,                              /*  5 */
+       BBOU_RDWS,                              /*  6 */
+       BBOU_RSRDWS,                            /*  7 */
+       BBOU_WD,        /* write dst */         /*  8 */
+       BBOU_RSWD,                              /*  9 */
+       BBOU_RDWD,                              /* 10 */
+       BBOU_RSRDWD,                            /* 11 */
+       BBOU_WSWD,                              /* 12 */
+       BBOU_RSWSWD,                            /* 13 */
+       BBOU_RDWSWD,                            /* 14 */
+       BBOU_RSRDWSWD,                          /* 15 */
+               /* opcode specific entries */
+       BBOU_ADD,
+       BBOU_CALL,
+       BBOU_CBW,
+       BBOU_CMOV,
+       BBOU_CMPXCHG,
+       BBOU_CMPXCHGD,
+       BBOU_CPUID,
+       BBOU_CWD,
+       BBOU_DIV,
+       BBOU_IDIV,
+       BBOU_IMUL,
+       BBOU_IRET,
+       BBOU_JMP,
+       BBOU_LAHF,
+       BBOU_LEA,
+       BBOU_LEAVE,
+       BBOU_LODS,
+       BBOU_LOOP,
+       BBOU_LSS,
+       BBOU_MONITOR,
+       BBOU_MOV,
+       BBOU_MOVS,
+       BBOU_MUL,
+       BBOU_MWAIT,
+       BBOU_NOP,
+       BBOU_OUTS,
+       BBOU_POP,
+       BBOU_POPF,
+       BBOU_PUSH,
+       BBOU_PUSHF,
+       BBOU_RDMSR,
+       BBOU_RDTSC,
+       BBOU_RET,
+       BBOU_SAHF,
+       BBOU_SCAS,
+       BBOU_SUB,
+       BBOU_SYSEXIT,
+       BBOU_SYSRET,
+       BBOU_WRMSR,
+       BBOU_XADD,
+       BBOU_XCHG,
+       BBOU_XOR,
+};
+
+struct bb_opcode_usage {
+       int length;
+       enum bb_operand_usage usage;
+       const char *opcode;
+};
+
+/* This table is sorted in alphabetical order of opcode, except that the
+ * trailing '"' is treated as a high value.  For example, 'in' sorts after
+ * 'inc', 'bt' after 'btc'.  This modified sort order ensures that shorter
+ * opcodes come after long ones.  A normal sort would put 'in' first, so 'in'
+ * would match both 'inc' and 'in'.  When adding any new entries to this table,
+ * be careful to put shorter entries last in their group.
+ *
+ * To automatically sort the table (in vi)
+ *   Mark the first and last opcode line with 'a and 'b
+ *   'a
+ *   !'bsed -e 's/"}/}}/' | LANG=C sort -t '"' -k2 | sed -e 's/}}/"}/'
+ *
+ * If a new instruction has to be added, first consider if it affects registers
+ * other than those listed in the operands.  Also consider if you want to track
+ * the results of issuing the instruction, IOW can you extract useful
+ * information by looking in detail at the modified registers or memory.  If
+ * either test is true then you need a special case to handle the instruction.
+ *
+ * The generic entries at the start of enum bb_operand_usage all have one thing
+ * in common, if a register or memory location is updated then that location
+ * becomes undefined, i.e. we lose track of anything that was previously saved
+ * in that location.  So only use a generic BBOU_* value when the result of the
+ * instruction cannot be calculated exactly _and_ when all the affected
+ * registers are listed in the operands.
+ *
+ * Examples:
+ *
+ * 'call' does not generate a known result, but as a side effect of call,
+ * several scratch registers become undefined, so it needs a special BBOU_CALL
+ * entry.
+ *
+ * 'adc' generates a variable result, it depends on the carry flag, so 'adc'
+ * gets a generic entry.  'add' can generate an exact result (add with
+ * immediate on a register that points to the stack) or it can generate an
+ * unknown result (add a variable, or add immediate to a register that does not
+ * contain a stack pointer) so 'add' has its own BBOU_ADD entry.
+ */
+
+static const struct bb_opcode_usage
+bb_opcode_usage_all[] = {
+       {3, BBOU_RSRDWD,  "adc"},
+       {3, BBOU_ADD,     "add"},
+       {3, BBOU_RSRDWD,  "and"},
+       {3, BBOU_RSWD,    "bsf"},
+       {3, BBOU_RSWD,    "bsr"},
+       {5, BBOU_RSWS,    "bswap"},
+       {3, BBOU_RSRDWD,  "btc"},
+       {3, BBOU_RSRDWD,  "btr"},
+       {3, BBOU_RSRDWD,  "bts"},
+       {2, BBOU_RSRD,    "bt"},
+       {4, BBOU_CALL,    "call"},
+       {4, BBOU_CBW,     "cbtw"},      /* Intel cbw */
+       {3, BBOU_NOP,     "clc"},
+       {3, BBOU_NOP,     "cld"},
+       {7, BBOU_RS,      "clflush"},
+       {4, BBOU_NOP,     "clgi"},
+       {3, BBOU_NOP,     "cli"},
+       {4, BBOU_CWD,     "cltd"},      /* Intel cdq */
+       {4, BBOU_CBW,     "cltq"},      /* Intel cdqe */
+       {4, BBOU_NOP,     "clts"},
+       {4, BBOU_CMOV,    "cmov"},
+       {9, BBOU_CMPXCHGD,"cmpxchg16"},
+       {8, BBOU_CMPXCHGD,"cmpxchg8"},
+       {7, BBOU_CMPXCHG, "cmpxchg"},
+       {3, BBOU_RSRD,    "cmp"},
+       {5, BBOU_CPUID,   "cpuid"},
+       {4, BBOU_CWD,     "cqto"},      /* Intel cdo */
+       {4, BBOU_CWD,     "cwtd"},      /* Intel cwd */
+       {4, BBOU_CBW,     "cwtl"},      /* Intel cwde */
+       {4, BBOU_NOP,     "data"},      /* alternative ASM_NOP<n> generates data16 on x86_64 */
+       {3, BBOU_RSWS,    "dec"},
+       {3, BBOU_DIV,     "div"},
+       {5, BBOU_RS,      "fdivl"},
+       {5, BBOU_NOP,     "finit"},
+       {6, BBOU_RS,      "fistpl"},
+       {4, BBOU_RS,      "fldl"},
+       {4, BBOU_RS,      "fmul"},
+       {6, BBOU_NOP,     "fnclex"},
+       {6, BBOU_NOP,     "fninit"},
+       {6, BBOU_RS,      "fnsave"},
+       {7, BBOU_NOP,     "fnsetpm"},
+       {6, BBOU_RS,      "frstor"},
+       {5, BBOU_WS,      "fstsw"},
+       {5, BBOU_RS,      "fsubp"},
+       {5, BBOU_NOP,     "fwait"},
+       {7, BBOU_RS,      "fxrstor"},
+       {6, BBOU_RS,      "fxsave"},
+       {3, BBOU_NOP,     "hlt"},
+       {4, BBOU_IDIV,    "idiv"},
+       {4, BBOU_IMUL,    "imul"},
+       {3, BBOU_RSWS,    "inc"},
+       {3, BBOU_NOP,     "int"},
+       {7, BBOU_RSRD,    "invlpga"},
+       {6, BBOU_RS,      "invlpg"},
+       {2, BBOU_RSWD,    "in"},
+       {4, BBOU_IRET,    "iret"},
+       {1, BBOU_JMP,     "j"},
+       {4, BBOU_LAHF,    "lahf"},
+       {3, BBOU_RSWD,    "lar"},
+       {5, BBOU_RS,      "lcall"},
+       {5, BBOU_LEAVE,   "leave"},
+       {3, BBOU_LEA,     "lea"},
+       {6, BBOU_NOP,     "lfence"},
+       {4, BBOU_RS,      "lgdt"},
+       {4, BBOU_RS,      "lidt"},
+       {4, BBOU_RS,      "ljmp"},
+       {4, BBOU_RS,      "lldt"},
+       {4, BBOU_RS,      "lmsw"},
+       {4, BBOU_LODS,    "lods"},
+       {4, BBOU_LOOP,    "loop"},
+       {4, BBOU_NOP,     "lret"},
+       {3, BBOU_RSWD,    "lsl"},
+       {3, BBOU_LSS,     "lss"},
+       {3, BBOU_RS,      "ltr"},
+       {6, BBOU_NOP,     "mfence"},
+       {7, BBOU_MONITOR, "monitor"},
+       {4, BBOU_MOVS,    "movs"},
+       {3, BBOU_MOV,     "mov"},
+       {3, BBOU_MUL,     "mul"},
+       {5, BBOU_MWAIT,   "mwait"},
+       {3, BBOU_RSWS,    "neg"},
+       {3, BBOU_NOP,     "nop"},
+       {3, BBOU_RSWS,    "not"},
+       {2, BBOU_RSRDWD,  "or"},
+       {4, BBOU_OUTS,    "outs"},
+       {3, BBOU_RSRD,    "out"},
+       {5, BBOU_NOP,     "pause"},
+       {4, BBOU_POPF,    "popf"},
+       {3, BBOU_POP,     "pop"},
+       {8, BBOU_RS,      "prefetch"},
+       {5, BBOU_PUSHF,   "pushf"},
+       {4, BBOU_PUSH,    "push"},
+       {3, BBOU_RSRDWD,  "rcl"},
+       {3, BBOU_RSRDWD,  "rcr"},
+       {5, BBOU_RDMSR,   "rdmsr"},
+       {5, BBOU_RDMSR,   "rdpmc"},     /* same side effects as rdmsr */
+       {5, BBOU_RDTSC,   "rdtsc"},
+       {3, BBOU_RET,     "ret"},
+       {3, BBOU_RSRDWD,  "rol"},
+       {3, BBOU_RSRDWD,  "ror"},
+       {4, BBOU_SAHF,    "sahf"},
+       {3, BBOU_RSRDWD,  "sar"},
+       {3, BBOU_RSRDWD,  "sbb"},
+       {4, BBOU_SCAS,    "scas"},
+       {3, BBOU_WS,      "set"},
+       {6, BBOU_NOP,     "sfence"},
+       {4, BBOU_WS,      "sgdt"},
+       {3, BBOU_RSRDWD,  "shl"},
+       {3, BBOU_RSRDWD,  "shr"},
+       {4, BBOU_WS,      "sidt"},
+       {4, BBOU_WS,      "sldt"},
+       {3, BBOU_NOP,     "stc"},
+       {3, BBOU_NOP,     "std"},
+       {4, BBOU_NOP,     "stgi"},
+       {3, BBOU_NOP,     "sti"},
+       {4, BBOU_SCAS,    "stos"},
+       {4, BBOU_WS,      "strl"},
+       {3, BBOU_WS,      "str"},
+       {3, BBOU_SUB,     "sub"},
+       {6, BBOU_NOP,     "swapgs"},
+       {7, BBOU_SYSEXIT, "sysexit"},
+       {6, BBOU_SYSRET,  "sysret"},
+       {4, BBOU_NOP,     "test"},
+       {4, BBOU_NOP,     "ud2a"},
+       {7, BBOU_RS,      "vmclear"},
+       {8, BBOU_NOP,     "vmlaunch"},
+       {6, BBOU_RS,      "vmload"},
+       {7, BBOU_RS,      "vmptrld"},
+       {6, BBOU_WD,      "vmread"},    /* vmread src is an encoding, not a register */
+       {8, BBOU_NOP,     "vmresume"},
+       {5, BBOU_RS,      "vmrun"},
+       {6, BBOU_RS,      "vmsave"},
+       {7, BBOU_WD,      "vmwrite"},   /* vmwrite src is an encoding, not a register */
+       {6, BBOU_NOP,     "wbinvd"},
+       {5, BBOU_WRMSR,   "wrmsr"},
+       {4, BBOU_XADD,    "xadd"},
+       {4, BBOU_XCHG,    "xchg"},
+       {3, BBOU_XOR,     "xor"},
+       {10, BBOU_WS,      "xstore-rng"},
+};
+
+/* To speed up searching, index bb_opcode_usage_all by the first letter of each
+ * opcode.
+ */
+static struct {
+       const struct bb_opcode_usage *opcode;
+       int size;
+} bb_opcode_usage[26];
+
+struct bb_operand {
+       char *base;
+       char *index;
+       char *segment;
+       long disp;
+       unsigned int scale;
+       enum bb_reg_code base_rc;               /* UNDEFINED or RAX through R15 */
+       enum bb_reg_code index_rc;              /* UNDEFINED or RAX through R15 */
+       unsigned int present            :1;
+       unsigned int disp_present       :1;
+       unsigned int indirect           :1;     /* must be combined with reg or memory */
+       unsigned int immediate          :1;     /* exactly one of these 3 must be set */
+       unsigned int reg                :1;
+       unsigned int memory             :1;
+};
+
+struct bb_decode {
+       char *prefix;
+       char *opcode;
+       const struct bb_opcode_usage *match;
+       struct bb_operand src;
+       struct bb_operand dst;
+       struct bb_operand dst2;
+};
+
+static struct bb_decode bb_decode;
+
+static enum bb_reg_code
+bb_reg_map(const char *reg)
+{
+       int lo, hi, c;
+       const struct bb_reg_code_map *p;
+       lo = 0;
+       hi = ARRAY_SIZE(bb_reg_code_map) - 1;
+       while (lo <= hi) {
+               int mid = (hi + lo) / 2;
+               p = bb_reg_code_map + mid;
+               c = strcmp(p->name, reg+1);
+               if (c == 0)
+                       return p->reg;
+               else if (c > 0)
+                       hi = mid - 1;
+               else
+                       lo = mid + 1;
+       }
+       return BBRG_UNDEFINED;
+}
+
+static void
+bb_parse_operand(char *str, struct bb_operand *operand)
+{
+       char *p = str;
+       int sign = 1;
+       operand->present = 1;
+       /* extract any segment prefix */
+       if (p[0] == '%' && p[1] && p[2] == 's' && p[3] == ':') {
+               operand->memory = 1;
+               operand->segment = p;
+               p[3] = '\0';
+               p += 4;
+       }
+       /* extract displacement, base, index, scale */
+       if (*p == '*') {
+               /* jmp/call *disp(%reg), *%reg or *0xnnn */
+               operand->indirect = 1;
+               ++p;
+       }
+       if (*p == '-') {
+               sign = -1;
+               ++p;
+       }
+       if (*p == '$') {
+               operand->immediate = 1;
+               operand->disp_present = 1;
+               operand->disp = simple_strtoul(p+1, &p, 0);
+       } else if (isdigit(*p)) {
+               operand->memory = 1;
+               operand->disp_present = 1;
+               operand->disp = simple_strtoul(p, &p, 0) * sign;
+       }
+       if (*p == '%') {
+               operand->reg = 1;
+               operand->base = p;
+       } else if (*p == '(') {
+               operand->memory = 1;
+               operand->base = ++p;
+               p += strcspn(p, ",)");
+               if (p == operand->base)
+                       operand->base = NULL;
+               if (*p == ',') {
+                       *p = '\0';
+                       operand->index = ++p;
+                       p += strcspn(p, ",)");
+                       if (p == operand->index)
+                               operand->index = NULL;
+               }
+               if (*p == ',') {
+                       *p = '\0';
+                       operand->scale = simple_strtoul(p+1, &p, 0);
+               }
+               *p = '\0';
+       } else if (*p) {
+               kdb_printf("%s: unexpected token '%c' after disp '%s'\n",
+                          __FUNCTION__, *p, str);
+               bb_giveup = 1;
+       }
+       if ((operand->immediate + operand->reg + operand->memory != 1) ||
+           (operand->indirect && operand->immediate)) {
+               kdb_printf("%s: incorrect decode '%s' N %d I %d R %d M %d\n",
+                          __FUNCTION__, str,
+                          operand->indirect, operand->immediate, operand->reg,
+                          operand->memory);
+               bb_giveup = 1;
+       }
+       if (operand->base)
+               operand->base_rc = bb_reg_map(operand->base);
+       if (operand->index)
+               operand->index_rc = bb_reg_map(operand->index);
+}
+
+static void
+bb_print_operand(const char *type, const struct bb_operand *operand)
+{
+       if (!operand->present)
+               return;
+       kdb_printf("  %s %c%c: ",
+                  type,
+                  operand->indirect ? 'N' : ' ',
+                  operand->immediate ? 'I' :
+                    operand->reg ? 'R' :
+                    operand->memory ? 'M' :
+                    '?'
+                  );
+       if (operand->segment)
+               kdb_printf("%s:", operand->segment);
+       if (operand->immediate) {
+               kdb_printf("$0x%lx", operand->disp);
+       } else if (operand->reg) {
+               if (operand->indirect)
+                       kdb_printf("*");
+               kdb_printf("%s", operand->base);
+       } else if (operand->memory) {
+               if (operand->indirect && (operand->base || operand->index))
+                       kdb_printf("*");
+               if (operand->disp_present) {
+                       kdb_printf("0x%lx", operand->disp);
+               }
+               if (operand->base || operand->index || operand->scale) {
+                       kdb_printf("(");
+                       if (operand->base)
+                               kdb_printf("%s", operand->base);
+                       if (operand->index || operand->scale)
+                               kdb_printf(",");
+                       if (operand->index)
+                               kdb_printf("%s", operand->index);
+                       if (operand->scale)
+                               kdb_printf(",%d", operand->scale);
+                       kdb_printf(")");
+               }
+       }
+       if (operand->base_rc)
+               kdb_printf(" base_rc %d (%s)",
+                          operand->base_rc, bbrg_name[operand->base_rc]);
+       if (operand->index_rc)
+               kdb_printf(" index_rc %d (%s)",
+                          operand->index_rc,
+                          bbrg_name[operand->index_rc]);
+       kdb_printf("\n");
+}
+
+static void
+bb_print_opcode(void)
+{
+       const struct bb_opcode_usage *o = bb_decode.match;
+       kdb_printf("  ");
+       if (bb_decode.prefix)
+               kdb_printf("%s ", bb_decode.prefix);
+       kdb_printf("opcode '%s' matched by '%s', usage %d\n",
+                  bb_decode.opcode, o->opcode, o->usage);
+}
+
+static int
+bb_parse_opcode(void)
+{
+       int c, i;
+       const struct bb_opcode_usage *o;
+       static int bb_parse_opcode_error_limit = 5;
+       c = bb_decode.opcode[0] - 'a';
+       if (c < 0 || c >= ARRAY_SIZE(bb_opcode_usage))
+               goto nomatch;
+       o = bb_opcode_usage[c].opcode;
+       if (!o)
+               goto nomatch;
+       for (i = 0; i < bb_opcode_usage[c].size; ++i, ++o) {
+               if (strncmp(bb_decode.opcode, o->opcode, o->length) == 0) {
+                       bb_decode.match = o;
+                       if (KDB_DEBUG(BB))
+                               bb_print_opcode();
+                       return 0;
+               }
+       }
+nomatch:
+       if (!bb_parse_opcode_error_limit)
+               return 1;
+       --bb_parse_opcode_error_limit;
+       kdb_printf("%s: no match at [%s]%s " kdb_bfd_vma_fmt0 " - '%s'\n",
+                  __FUNCTION__,
+                  bb_mod_name, bb_func_name, bb_curr_addr,
+                  bb_decode.opcode);
+       return 1;
+}
+
+static bool
+bb_is_int_reg(enum bb_reg_code reg)
+{
+       return reg >= BBRG_RAX && reg < (BBRG_RAX + KDB_INT_REGISTERS);
+}
+
+static bool
+bb_is_simple_memory(const struct bb_operand *operand)
+{
+       return operand->memory &&
+              bb_is_int_reg(operand->base_rc) &&
+              !operand->index_rc &&
+              operand->scale == 0 &&
+              !operand->segment;
+}
+
+static bool
+bb_is_static_disp(const struct bb_operand *operand)
+{
+       return operand->memory &&
+              !operand->base_rc &&
+              !operand->index_rc &&
+              operand->scale == 0 &&
+              !operand->segment &&
+              !operand->indirect;
+}
+
+static enum bb_reg_code
+bb_reg_code_value(enum bb_reg_code reg)
+{
+       BB_CHECK(!bb_is_int_reg(reg), reg, 0);
+       return bb_reg_state->contains[reg - BBRG_RAX].value;
+}
+
+static short
+bb_reg_code_offset(enum bb_reg_code reg)
+{
+       BB_CHECK(!bb_is_int_reg(reg), reg, 0);
+       return bb_reg_state->contains[reg - BBRG_RAX].offset;
+}
+
+static void
+bb_reg_code_set_value(enum bb_reg_code dst, enum bb_reg_code src)
+{
+       BB_CHECK(!bb_is_int_reg(dst), dst, );
+       bb_reg_state->contains[dst - BBRG_RAX].value = src;
+}
+
+static void
+bb_reg_code_set_offset(enum bb_reg_code dst, short offset)
+{
+       BB_CHECK(!bb_is_int_reg(dst), dst, );
+       bb_reg_state->contains[dst - BBRG_RAX].offset = offset;
+}
+
+static bool
+bb_is_osp_defined(enum bb_reg_code reg)
+{
+       if (bb_is_int_reg(reg))
+               return bb_reg_code_value(reg) == BBRG_OSP;
+       else
+               return 0;
+}
+
+static bfd_vma
+bb_actual_value(enum bb_reg_code reg)
+{
+       BB_CHECK(!bb_is_int_reg(reg), reg, 0);
+       return bb_actual[reg - BBRG_RAX].value;
+}
+
+static int
+bb_actual_valid(enum bb_reg_code reg)
+{
+       BB_CHECK(!bb_is_int_reg(reg), reg, 0);
+       return bb_actual[reg - BBRG_RAX].valid;
+}
+
+static void
+bb_actual_set_value(enum bb_reg_code reg, bfd_vma value)
+{
+       BB_CHECK(!bb_is_int_reg(reg), reg, );
+       bb_actual[reg - BBRG_RAX].value = value;
+}
+
+static void
+bb_actual_set_valid(enum bb_reg_code reg, int valid)
+{
+       BB_CHECK(!bb_is_int_reg(reg), reg, );
+       bb_actual[reg - BBRG_RAX].valid = valid;
+}
+
+/* The scheduler code switches RSP then does PUSH, it is not an error for RSP
+ * to be undefined in this area of the code.
+ */
+static bool
+bb_is_scheduler_address(void)
+{
+       return bb_curr_addr >= bb__sched_text_start &&
+              bb_curr_addr < bb__sched_text_end;
+}
+
+static void
+bb_reg_read(enum bb_reg_code reg)
+{
+       int i, r = 0;
+       if (!bb_is_int_reg(reg) ||
+           bb_reg_code_value(reg) != reg)
+               return;
+       for (i = 0;
+            i < min_t(unsigned int, REGPARM, ARRAY_SIZE(bb_param_reg));
+            ++i) {
+               if (reg == bb_param_reg[i]) {
+                       r = i + 1;
+                       break;
+               }
+       }
+       bb_reg_params = max(bb_reg_params, r);
+}
+
+static void
+bb_do_reg_state_print(const struct bb_reg_state *s)
+{
+       int i, offset_address, offset_value;
+       const struct bb_memory_contains *c;
+       enum bb_reg_code value;
+       kdb_printf("  bb_reg_state %p\n", s);
+       for (i = 0; i < ARRAY_SIZE(s->contains); ++i) {
+               value = s->contains[i].value;
+               offset_value = s->contains[i].offset;
+               kdb_printf("    %s = %s",
+                          bbrg_name[i + BBRG_RAX], bbrg_name[value]);
+               if (value == BBRG_OSP)
+                       KDB_DEBUG_BB_OFFSET_PRINTF(offset_value, "", "");
+               kdb_printf("\n");
+       }
+       for (i = 0, c = s->memory; i < s->mem_count; ++i, ++c) {
+               offset_address = c->offset_address;
+               value = c->value;
+               offset_value = c->offset_value;
+               kdb_printf("    slot %d offset_address %c0x%x %s",
+                          i,
+                          offset_address >= 0 ? '+' : '-',
+                          offset_address >= 0 ? offset_address : -offset_address,
+                          bbrg_name[value]);
+               if (value == BBRG_OSP)
+                       KDB_DEBUG_BB_OFFSET_PRINTF(offset_value, "", "");
+               kdb_printf("\n");
+       }
+}
+
+static void
+bb_reg_state_print(const struct bb_reg_state *s)
+{
+       if (KDB_DEBUG(BB))
+               bb_do_reg_state_print(s);
+}
+
+/* Set register 'dst' to contain the value from 'src'.  This includes reading
+ * from 'src' and writing to 'dst'.  The offset value is copied iff 'src'
+ * contains a stack pointer.
+ *
+ * Be very careful about the context here.  'dst' and 'src' reflect integer
+ * registers by name, _not_ by the value of their contents.  "mov %rax,%rsi"
+ * will call this function as bb_reg_set_reg(BBRG_RSI, BBRG_RAX), which
+ * reflects what the assembler code is doing.  However we need to track the
+ * _values_ in the registers, not their names.  IOW, we really care about "what
+ * value does rax contain when it is copied into rsi?", so we can record the
+ * fact that we now have two copies of that value, one in rax and one in rsi.
+ */
+
+static void
+bb_reg_set_reg(enum bb_reg_code dst, enum bb_reg_code src)
+{
+       enum bb_reg_code src_value = BBRG_UNDEFINED;
+       short offset_value = 0;
+       KDB_DEBUG_BB("  %s = %s", bbrg_name[dst], bbrg_name[src]);
+       if (bb_is_int_reg(src)) {
+               bb_reg_read(src);
+               src_value = bb_reg_code_value(src);
+               KDB_DEBUG_BB(" (%s", bbrg_name[src_value]);
+               if (bb_is_osp_defined(src)) {
+                       offset_value = bb_reg_code_offset(src);
+                       KDB_DEBUG_BB_OFFSET(offset_value, "", "");
+               }
+               KDB_DEBUG_BB(")");
+       }
+       if (bb_is_int_reg(dst)) {
+               bb_reg_code_set_value(dst, src_value);
+               bb_reg_code_set_offset(dst, offset_value);
+       }
+       KDB_DEBUG_BB("\n");
+}
+
+static void
+bb_reg_set_undef(enum bb_reg_code dst)
+{
+       bb_reg_set_reg(dst, BBRG_UNDEFINED);
+}
+
+/* Delete any record of a stored register held in osp + 'offset' */
+
+static void
+bb_delete_memory(short offset)
+{
+       int i;
+       struct bb_memory_contains *c;
+       for (i = 0, c = bb_reg_state->memory;
+            i < bb_reg_state->mem_count;
+            ++i, ++c) {
+               if (c->offset_address == offset &&
+                   c->value != BBRG_UNDEFINED) {
+                       KDB_DEBUG_BB("  delete %s from ",
+                                    bbrg_name[c->value]);
+                       KDB_DEBUG_BB_OFFSET(offset, "osp", "");
+                       KDB_DEBUG_BB(" slot %d\n",
+                                    (int)(c - bb_reg_state->memory));
+                       memset(c, BBRG_UNDEFINED, sizeof(*c));
+                       if (i == bb_reg_state->mem_count - 1)
+                               --bb_reg_state->mem_count;
+               }
+       }
+}
+
+/* Set memory location *('dst' + 'offset_address') to contain the supplied
+ * value and offset.  'dst' is assumed to be a register that contains a stack
+ * pointer.
+ */
+
+static void
+bb_memory_set_reg_value(enum bb_reg_code dst, short offset_address,
+                       enum bb_reg_code value, short offset_value)
+{
+       int i;
+       struct bb_memory_contains *c, *free = NULL;
+       BB_CHECK(!bb_is_osp_defined(dst), dst, );
+       KDB_DEBUG_BB("  *(%s", bbrg_name[dst]);
+       KDB_DEBUG_BB_OFFSET(offset_address, "", "");
+       offset_address += bb_reg_code_offset(dst);
+       KDB_DEBUG_BB_OFFSET(offset_address, " osp", ") = ");
+       KDB_DEBUG_BB("%s", bbrg_name[value]);
+       if (value == BBRG_OSP)
+               KDB_DEBUG_BB_OFFSET(offset_value, "", "");
+       for (i = 0, c = bb_reg_state->memory;
+            i < bb_reg_state_max;
+            ++i, ++c) {
+               if (c->offset_address == offset_address)
+                       free = c;
+               else if (c->value == BBRG_UNDEFINED && !free)
+                       free = c;
+       }
+       if (!free) {
+               struct bb_reg_state *new, *old = bb_reg_state;
+               size_t old_size, new_size;
+               int slot;
+               old_size = sizeof(*old) + bb_reg_state_max *
+                                 sizeof(old->memory[0]);
+               slot = bb_reg_state_max;
+               bb_reg_state_max += 5;
+               new_size = sizeof(*new) + bb_reg_state_max *
+                                 sizeof(new->memory[0]);
+               new = debug_kmalloc(new_size, GFP_ATOMIC);
+               if (!new) {
+                       kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
+                       bb_giveup = 1;
+               } else {
+                       memcpy(new, old, old_size);
+                       memset((char *)new + old_size, BBRG_UNDEFINED,
+                              new_size - old_size);
+                       bb_reg_state = new;
+                       debug_kfree(old);
+                       free = bb_reg_state->memory + slot;
+               }
+       }
+       if (free) {
+               int slot = free - bb_reg_state->memory;
+               free->offset_address = offset_address;
+               free->value = value;
+               free->offset_value = offset_value;
+               KDB_DEBUG_BB(" slot %d", slot);
+               bb_reg_state->mem_count = max(bb_reg_state->mem_count, slot+1);
+       }
+       KDB_DEBUG_BB("\n");
+}
+
+/* Set memory location *('dst' + 'offset') to contain the value from register
+ * 'src'.  'dst' is assumed to be a register that contains a stack pointer.
+ * This differs from bb_memory_set_reg_value because it takes a src register
+ * which contains a value and possibly an offset, bb_memory_set_reg_value is
+ * passed the value and offset directly.
+ */
+
+static void
+bb_memory_set_reg(enum bb_reg_code dst, enum bb_reg_code src,
+                 short offset_address)
+{
+       int offset_value;
+       enum bb_reg_code value;
+       BB_CHECK(!bb_is_osp_defined(dst), dst, );
+       if (!bb_is_int_reg(src))
+               return;
+       value = bb_reg_code_value(src);
+       if (value == BBRG_UNDEFINED) {
+               bb_delete_memory(offset_address + bb_reg_code_offset(dst));
+               return;
+       }
+       offset_value = bb_reg_code_offset(src);
+       bb_reg_read(src);
+       bb_memory_set_reg_value(dst, offset_address, value, offset_value);
+}
+
+/* Set register 'dst' to contain the value from memory *('src' + offset_address).
+ * 'src' is assumed to be a register that contains a stack pointer.
+ */
+
+static void
+bb_reg_set_memory(enum bb_reg_code dst, enum bb_reg_code src, short offset_address)
+{
+       int i, defined = 0;
+       struct bb_memory_contains *s;
+       BB_CHECK(!bb_is_osp_defined(src), src, );
+       KDB_DEBUG_BB("  %s = *(%s",
+                    bbrg_name[dst], bbrg_name[src]);
+       KDB_DEBUG_BB_OFFSET(offset_address, "", ")");
+       offset_address += bb_reg_code_offset(src);
+       KDB_DEBUG_BB_OFFSET(offset_address, " (osp", ")");
+       for (i = 0, s = bb_reg_state->memory;
+            i < bb_reg_state->mem_count;
+            ++i, ++s) {
+               if (s->offset_address == offset_address && bb_is_int_reg(dst)) {
+                       bb_reg_code_set_value(dst, s->value);
+                       KDB_DEBUG_BB(" value %s", bbrg_name[s->value]);
+                       if (s->value == BBRG_OSP) {
+                               bb_reg_code_set_offset(dst, s->offset_value);
+                               KDB_DEBUG_BB_OFFSET(s->offset_value, "", "");
+                       } else {
+                               bb_reg_code_set_offset(dst, 0);
+                       }
+                       defined = 1;
+               }
+       }
+       if (!defined)
+               bb_reg_set_reg(dst, BBRG_UNDEFINED);
+       else
+               KDB_DEBUG_BB("\n");
+}
+
+/* A generic read from an operand. */
+
+static void
+bb_read_operand(const struct bb_operand *operand)
+{
+       int m = 0;
+       if (operand->base_rc)
+               bb_reg_read(operand->base_rc);
+       if (operand->index_rc)
+               bb_reg_read(operand->index_rc);
+       if (bb_is_simple_memory(operand) &&
+           bb_is_osp_defined(operand->base_rc) &&
+           bb_decode.match->usage != BBOU_LEA) {
+               m = (bb_reg_code_offset(operand->base_rc) + operand->disp +
+                    KDB_WORD_SIZE - 1) / KDB_WORD_SIZE;
+               bb_memory_params = max(bb_memory_params, m);
+       }
+}
+
+/* A generic write to an operand, resulting in an undefined value in that
+ * location.  All well defined operands are handled separately, this function
+ * only handles the opcodes where the result is undefined.
+ */
+
+static void
+bb_write_operand(const struct bb_operand *operand)
+{
+       enum bb_reg_code base_rc = operand->base_rc;
+       if (operand->memory) {
+               if (base_rc)
+                       bb_reg_read(base_rc);
+               if (operand->index_rc)
+                       bb_reg_read(operand->index_rc);
+       } else if (operand->reg && base_rc) {
+               bb_reg_set_undef(base_rc);
+       }
+       if (bb_is_simple_memory(operand) && bb_is_osp_defined(base_rc)) {
+               int offset;
+               offset = bb_reg_code_offset(base_rc) + operand->disp;
+               offset = ALIGN(offset - KDB_WORD_SIZE + 1, KDB_WORD_SIZE);
+               bb_delete_memory(offset);
+       }
+}
+
+/* Adjust a register that contains a stack pointer */
+
+static void
+bb_adjust_osp(enum bb_reg_code reg, int adjust)
+{
+       int offset = bb_reg_code_offset(reg), old_offset = offset;
+       KDB_DEBUG_BB("  %s osp offset ", bbrg_name[reg]);
+       KDB_DEBUG_BB_OFFSET(bb_reg_code_offset(reg), "", " -> ");
+       offset += adjust;
+       bb_reg_code_set_offset(reg, offset);
+       KDB_DEBUG_BB_OFFSET(bb_reg_code_offset(reg), "", "\n");
+       /* When RSP is adjusted upwards, it invalidates any memory
+        * stored between the old and current stack offsets.
+        */
+       if (reg == BBRG_RSP) {
+               while (old_offset < bb_reg_code_offset(reg)) {
+                       bb_delete_memory(old_offset);
+                       old_offset += KDB_WORD_SIZE;
+               }
+       }
+}
+
+/* The current instruction adjusts a register that contains a stack pointer.
+ * Direction is 1 or -1, depending on whether the instruction is add/lea or
+ * sub.
+ */
+
+static void
+bb_adjust_osp_instruction(int direction)
+{
+       enum bb_reg_code dst_reg = bb_decode.dst.base_rc;
+       if (bb_decode.src.immediate ||
+           bb_decode.match->usage == BBOU_LEA /* lea has its own checks */) {
+               int adjust = direction * bb_decode.src.disp;
+               bb_adjust_osp(dst_reg, adjust);
+       } else {
+               /* variable stack adjustment, osp offset is not well defined */
+               KDB_DEBUG_BB("  %s osp offset ", bbrg_name[dst_reg]);
+               KDB_DEBUG_BB_OFFSET(bb_reg_code_offset(dst_reg), "", " -> undefined\n");
+               bb_reg_code_set_value(dst_reg, BBRG_UNDEFINED);
+               bb_reg_code_set_offset(dst_reg, 0);
+       }
+}
+
+/* Some instructions using memory have an explicit length suffix (b, w, l, q).
+ * The equivalent instructions using a register imply the length from the
+ * register name.  Deduce the operand length.
+ */
+
+static int
+bb_operand_length(const struct bb_operand *operand, char opcode_suffix)
+{
+       int l = 0;
+       switch (opcode_suffix) {
+       case 'b':
+               l = 8;
+               break;
+       case 'w':
+               l = 16;
+               break;
+       case 'l':
+               l = 32;
+               break;
+       case 'q':
+               l = 64;
+               break;
+       }
+       if (l == 0 && operand->reg) {
+               switch (strlen(operand->base)) {
+               case 3:
+                       switch (operand->base[2]) {
+                       case 'h':
+                       case 'l':
+                               l = 8;
+                               break;
+                       default:
+                               l = 16;
+                               break;
+                       }
+               case 4:
+                       if (operand->base[1] == 'r')
+                               l = 64;
+                       else
+                               l = 32;
+                       break;
+               }
+       }
+       return l;
+}
+
+static int
+bb_reg_state_size(const struct bb_reg_state *state)
+{
+       return sizeof(*state) +
+              state->mem_count * sizeof(state->memory[0]);
+}
+
+/* Canonicalize the current bb_reg_state so it can be compared against
+ * previously created states.  Sort the memory entries in descending order of
+ * offset_address (stack grows down).  Empty slots are moved to the end of the
+ * list and trimmed.
+ */
+
+static void
+bb_reg_state_canonicalize(void)
+{
+       int i, order, changed;
+       struct bb_memory_contains *p1, *p2, temp;
+       do {
+               changed = 0;
+               for (i = 0, p1 = bb_reg_state->memory;
+                    i < bb_reg_state->mem_count-1;
+                    ++i, ++p1) {
+                       p2 = p1 + 1;
+                       if (p2->value == BBRG_UNDEFINED) {
+                               order = 0;
+                       } else if (p1->value == BBRG_UNDEFINED) {
+                               order = 1;
+                       } else if (p1->offset_address < p2->offset_address) {
+                               order = 1;
+                       } else if (p1->offset_address > p2->offset_address) {
+                               order = -1;
+                       } else {
+                               order = 0;
+                       }
+                       if (order > 0) {
+                               temp = *p2;
+                               *p2 = *p1;
+                               *p1 = temp;
+                               changed = 1;
+                       }
+               }
+       } while(changed);
+       for (i = 0, p1 = bb_reg_state->memory;
+            i < bb_reg_state_max;
+            ++i, ++p1) {
+               if (p1->value != BBRG_UNDEFINED)
+                       bb_reg_state->mem_count = i + 1;
+       }
+       bb_reg_state_print(bb_reg_state);
+}
+
+static int
+bb_special_case(bfd_vma to)
+{
+       int i, j, rsp_offset, expect_offset, offset, errors = 0, max_errors = 40;
+       enum bb_reg_code reg, expect_value, value;
+       struct bb_name_state *r;
+
+       for (i = 0, r = bb_special_cases;
+            i < ARRAY_SIZE(bb_special_cases);
+            ++i, ++r) {
+               if (to == r->address &&
+                   (r->fname == NULL || strcmp(bb_func_name, r->fname) == 0))
+                       goto match;
+       }
+       /* Some inline assembler code has jumps to .fixup sections which result
+        * in out of line transfers with undefined state, ignore them.
+        */
+       if (strcmp(bb_func_name, "strnlen_user") == 0 ||
+           strcmp(bb_func_name, "copy_from_user") == 0)
+               return 1;
+       return 0;
+
+match:
+       /* Check the running registers match */
+       for (reg = BBRG_RAX; reg < r->regs_size; ++reg) {
+               expect_value = r->regs[reg].value;
+               if (test_bit(expect_value, r->skip_regs.bits)) {
+                       /* this regs entry is not defined for this label */
+                       continue;
+               }
+               if (expect_value == BBRG_UNDEFINED)
+                       continue;
+               expect_offset = r->regs[reg].offset;
+               value = bb_reg_code_value(reg);
+               offset = bb_reg_code_offset(reg);
+               if (expect_value == value &&
+                   (value != BBRG_OSP || r->osp_offset == offset))
+                       continue;
+               kdb_printf("%s: Expected %s to contain %s",
+                          __FUNCTION__,
+                          bbrg_name[reg],
+                          bbrg_name[expect_value]);
+               if (r->osp_offset)
+                       KDB_DEBUG_BB_OFFSET_PRINTF(r->osp_offset, "", "");
+               kdb_printf(".  It actually contains %s", bbrg_name[value]);
+               if (offset)
+                       KDB_DEBUG_BB_OFFSET_PRINTF(offset, "", "");
+               kdb_printf("\n");
+               ++errors;
+               if (max_errors-- == 0)
+                       goto fail;
+       }
+       /* Check that any memory data on stack matches */
+       i = j = 0;
+       while (i < bb_reg_state->mem_count &&
+              j < r->mem_size) {
+               expect_value = r->mem[j].value;
+               if (test_bit(expect_value, r->skip_mem.bits) ||
+                   expect_value == BBRG_UNDEFINED) {
+                       /* this memory slot is not defined for this label */
+                       ++j;
+                       continue;
+               }
+               rsp_offset = bb_reg_state->memory[i].offset_address -
+                       bb_reg_code_offset(BBRG_RSP);
+               if (rsp_offset >
+                   r->mem[j].offset_address) {
+                       /* extra slots in memory are OK */
+                       ++i;
+               } else if (rsp_offset <
+                          r->mem[j].offset_address) {
+                       /* Required memory slot is missing */
+                       kdb_printf("%s: Invalid bb_reg_state.memory, "
+                                  "missing memory entry[%d] %s\n",
+                          __FUNCTION__, j, bbrg_name[expect_value]);
+                       ++errors;
+                       if (max_errors-- == 0)
+                               goto fail;
+                       ++j;
+               } else {
+                       if (bb_reg_state->memory[i].offset_value ||
+                           bb_reg_state->memory[i].value != expect_value) {
+                               /* memory slot is present but contains wrong
+                                * value.
+                                */
+                               kdb_printf("%s: Invalid bb_reg_state.memory, "
+                                           "wrong value in slot %d, "
+                                           "should be %s, it is %s\n",
+                                  __FUNCTION__, i,
+                                  bbrg_name[expect_value],
+                                  bbrg_name[bb_reg_state->memory[i].value]);
+                               ++errors;
+                               if (max_errors-- == 0)
+                                       goto fail;
+                       }
+                       ++i;
+                       ++j;
+               }
+       }
+       while (j < r->mem_size) {
+               expect_value = r->mem[j].value;
+               if (test_bit(expect_value, r->skip_mem.bits) ||
+                   expect_value == BBRG_UNDEFINED)
+                       ++j;
+               else
+                       break;
+       }
+       if (j != r->mem_size) {
+               /* Hit end of memory before testing all the pt_reg slots */
+               kdb_printf("%s: Invalid bb_reg_state.memory, "
+                           "missing trailing entries\n",
+                  __FUNCTION__);
+               ++errors;
+               if (max_errors-- == 0)
+                       goto fail;
+       }
+       if (errors)
+               goto fail;
+       return 1;
+fail:
+       kdb_printf("%s: on transfer to %s\n", __FUNCTION__, r->name);
+       bb_giveup = 1;
+       return 1;
+}
+
+/* Transfer of control to a label outside the current function.  If the
+ * transfer is to a known common code path then do a sanity check on the state
+ * at this point.
+ */
+
+static void
+bb_sanity_check(int type)
+{
+       enum bb_reg_code expect, actual;
+       int i, offset, error = 0;
+
+       for (i = 0; i < ARRAY_SIZE(bb_preserved_reg); ++i) {
+               expect = bb_preserved_reg[i];
+               actual = bb_reg_code_value(expect);
+               offset = bb_reg_code_offset(expect);
+               if (expect == actual)
+                       continue;
+               /* type == 1 is sysret/sysexit, ignore RSP */
+               if (type && expect == BBRG_RSP)
+                       continue;
+               /* type == 1 is sysret/sysexit, ignore RBP for i386 */
+               /* We used to have "#ifndef CONFIG_X86_64" for the type=1 RBP
+                * test; however, x86_64 can run ia32 compatible mode and
+                * hit this problem. Perform the following test anyway!
+                */
+               if (type && expect == BBRG_RBP)
+                       continue;
+               /* RSP should contain OSP+0.  Except for ptregscall_common and
+                * ia32_ptregs_common, they get a partial pt_regs, fudge the
+                * stack to make it a full pt_regs then reverse the effect on
+                * exit, so the offset is -0x50 on exit.
+                */
+               if (expect == BBRG_RSP &&
+                   bb_is_osp_defined(expect) &&
+                   (offset == 0 ||
+                    (offset == -0x50 &&
+                     (strcmp(bb_func_name, "ptregscall_common") == 0 ||
+                      strcmp(bb_func_name, "ia32_ptregs_common") == 0))))
+                       continue;
+               kdb_printf("%s: Expected %s, got %s",
+                          __FUNCTION__,
+                          bbrg_name[expect], bbrg_name[actual]);
+               if (offset)
+                       KDB_DEBUG_BB_OFFSET_PRINTF(offset, "", "");
+               kdb_printf("\n");
+               error = 1;
+       }
+       BB_CHECK(error, error, );
+}
+
+/* Transfer of control.  Follow the arc and save the current state as input to
+ * another basic block.
+ */
+
+static void
+bb_transfer(bfd_vma from, bfd_vma to, unsigned int drop_through)
+{
+       int i, found;
+       size_t size;
+       struct bb* bb = NULL;   /*stupid gcc */
+       struct bb_jmp *bb_jmp;
+       struct bb_reg_state *state;
+       bb_reg_state_canonicalize();
+       found = 0;
+       for (i = 0; i < bb_jmp_count; ++i) {
+               bb_jmp = bb_jmp_list + i;
+               if (bb_jmp->from == from &&
+                   bb_jmp->to == to &&
+                   bb_jmp->drop_through == drop_through) {
+                       found = 1;
+                       break;
+               }
+       }
+       if (!found) {
+               /* Transfer outside the current function.  Check the special
+                * cases (mainly in entry.S) first.  If it is not a known
+                * special case then check if the target address is the start
+                * of a function or not.  If it is the start of a function then
+                * assume tail recursion and require that the state be the same
+                * as on entry.  Otherwise assume out of line code (e.g.
+                * spinlock contention path) and ignore it, the state can be
+                * anything.
+                */
+               kdb_symtab_t symtab;
+               if (bb_special_case(to))
+                       return;
+               kdbnearsym(to, &symtab);
+               if (symtab.sym_start != to)
+                       return;
+               bb_sanity_check(0);
+               if (bb_giveup)
+                       return;
+#ifdef NO_SIBLINGS
+               /* Only print this message when the kernel is compiled with
+                * -fno-optimize-sibling-calls.  Otherwise it would print a
+                * message for every tail recursion call.  If you see the
+                * message below then you probably have an assembler label that
+                * is not listed in the special cases.
+                */
+               kdb_printf("  not matched: from "
+                          kdb_bfd_vma_fmt0
+                          " to " kdb_bfd_vma_fmt0
+                          " drop_through %d bb_jmp[%d]\n",
+                          from, to, drop_through, i);
+#endif /* NO_SIBLINGS */
+               return;
+       }
+       KDB_DEBUG_BB("  matched: from " kdb_bfd_vma_fmt0
+                    " to " kdb_bfd_vma_fmt0
+                    " drop_through %d bb_jmp[%d]\n",
+                    from, to, drop_through, i);
+       found = 0;
+       for (i = 0; i < bb_count; ++i) {
+               bb = bb_list[i];
+               if (bb->start == to) {
+                       found = 1;
+                       break;
+               }
+       }
+       BB_CHECK(!found, to, );
+       /* If the register state for this arc has already been set (we are
+        * rescanning the block that originates the arc) and the state is the
+        * same as the previous state for this arc then this input to the
+        * target block is the same as last time, so there is no need to rescan
+        * the target block.
+        */
+       state = bb_jmp->state;
+       size = bb_reg_state_size(bb_reg_state);
+       if (state) {
+               bb_reg_state->ref_count = state->ref_count;
+               if (memcmp(state, bb_reg_state, size) == 0) {
+                       KDB_DEBUG_BB("  no state change\n");
+                       return;
+               }
+               if (--state->ref_count == 0)
+                       debug_kfree(state);
+               bb_jmp->state = NULL;
+       }
+       /* New input state is required.  To save space, check if any other arcs
+        * have the same state and reuse them where possible.  The overall set
+        * of inputs to the target block is now different so the target block
+        * must be rescanned.
+        */
+       bb->changed = 1;
+       for (i = 0; i < bb_jmp_count; ++i) {
+               state = bb_jmp_list[i].state;
+               if (!state)
+                       continue;
+               bb_reg_state->ref_count = state->ref_count;
+               if (memcmp(state, bb_reg_state, size) == 0) {
+                       KDB_DEBUG_BB("  reuse bb_jmp[%d]\n", i);
+                       bb_jmp->state = state;
+                       ++state->ref_count;
+                       return;
+               }
+       }
+       state = debug_kmalloc(size, GFP_ATOMIC);
+       if (!state) {
+               kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
+               bb_giveup = 1;
+               return;
+       }
+       memcpy(state, bb_reg_state, size);
+       state->ref_count = 1;
+       bb_jmp->state = state;
+       KDB_DEBUG_BB("  new state %p\n", state);
+}
+
+/* Isolate the processing for 'mov' so it can be used for 'xadd'/'xchg' as
+ * well.
+ *
+ * xadd/xchg expect this function to return BBOU_NOP for special cases,
+ * otherwise it returns BBOU_RSWD.  All special cases must be handled entirely
+ * within this function, including doing bb_read_operand or bb_write_operand
+ * where necessary.
+ */
+
+static enum bb_operand_usage
+bb_usage_mov(const struct bb_operand *src, const struct bb_operand *dst, int l)
+{
+       int full_register_src, full_register_dst;
+       full_register_src = bb_operand_length(src, bb_decode.opcode[l])
+                           == KDB_WORD_SIZE * 8;
+       full_register_dst = bb_operand_length(dst, bb_decode.opcode[l])
+                           == KDB_WORD_SIZE * 8;
+       /* If both src and dst are full integer registers then record the
+        * register change.
+        */
+       if (src->reg &&
+           bb_is_int_reg(src->base_rc) &&
+           dst->reg &&
+           bb_is_int_reg(dst->base_rc) &&
+           full_register_src &&
+           full_register_dst) {
+               /* Special case for the code that switches stacks in
+                * jprobe_return.  That code must modify RSP but it does it in
+                * a well defined manner.  Do not invalidate RSP.
+                */
+               if (src->base_rc == BBRG_RBX &&
+                   dst->base_rc == BBRG_RSP &&
+                   strcmp(bb_func_name, "jprobe_return") == 0) {
+                       bb_read_operand(src);
+                       return BBOU_NOP;
+               }
+               /* math_abort takes the equivalent of a longjmp structure and
+                * resets the stack.  Ignore this, it leaves RSP well defined.
+                */
+               if (dst->base_rc == BBRG_RSP &&
+                   strcmp(bb_func_name, "math_abort") == 0) {
+                       bb_read_operand(src);
+                       return BBOU_NOP;
+               }
+               bb_reg_set_reg(dst->base_rc, src->base_rc);
+               return BBOU_NOP;
+       }
+       /* If the move is from a full integer register to stack then record it.
+        */
+       if (src->reg &&
+           bb_is_simple_memory(dst) &&
+           bb_is_osp_defined(dst->base_rc) &&
+           full_register_src) {
+               /* Ugly special case.  Initializing list heads on stack causes
+                * false references to stack variables when the list head is
+                * used.  Static code analysis cannot detect that the list head
+                * has been changed by a previous execution loop and that a
+                * basic block is only executed after the list head has been
+                * changed.
+                *
+                * These false references can result in valid stack variables
+                * being incorrectly cleared on some logic paths.  Ignore
+                * stores to stack variables which point to themselves or to
+                * the previous word so the list head initialization is not
+                * recorded.
+                */
+               if (bb_is_osp_defined(src->base_rc)) {
+                       int stack1 = bb_reg_code_offset(src->base_rc);
+                       int stack2 = bb_reg_code_offset(dst->base_rc) +
+                                    dst->disp;
+                       if (stack1 == stack2 ||
+                           stack1 == stack2 - KDB_WORD_SIZE)
+                               return BBOU_NOP;
+               }
+               bb_memory_set_reg(dst->base_rc, src->base_rc, dst->disp);
+               return BBOU_NOP;
+       }
+       /* If the move is from stack to a full integer register then record it.
+        */
+       if (bb_is_simple_memory(src) &&
+           bb_is_osp_defined(src->base_rc) &&
+           dst->reg &&
+           bb_is_int_reg(dst->base_rc) &&
+           full_register_dst) {
+#ifdef CONFIG_X86_32
+               /* mov from TSS_sysenter_sp0+offset to esp to fix up the
+                * sysenter stack, it leaves esp well defined.  mov
+                * TSS_ysenter_sp0+offset(%esp),%esp is followed by up to 5
+                * push instructions to mimic the hardware stack push.  If
+                * TSS_sysenter_sp0 is offset then only 3 words will be
+                * pushed.
+                */
+               if (dst->base_rc == BBRG_RSP &&
+                   src->disp >= TSS_sysenter_sp0 &&
+                   bb_is_osp_defined(BBRG_RSP)) {
+                       int pushes;
+                       pushes = src->disp == TSS_sysenter_sp0 ? 5 : 3;
+                       bb_reg_code_set_offset(BBRG_RSP,
+                               bb_reg_code_offset(BBRG_RSP) +
+                                       pushes * KDB_WORD_SIZE);
+                       KDB_DEBUG_BB_OFFSET(
+                               bb_reg_code_offset(BBRG_RSP),
+                               "  sysenter fixup, RSP",
+                              "\n");
+                       return BBOU_NOP;
+               }
+#endif /* CONFIG_X86_32 */
+               bb_read_operand(src);
+               bb_reg_set_memory(dst->base_rc, src->base_rc, src->disp);
+               return BBOU_NOP;
+       }
+       /* move %gs:0x<nn>,%rsp is used to unconditionally switch to another
+        * stack.  Ignore this special case, it is handled by the stack
+        * unwinding code.
+        */
+       if (src->segment &&
+           strcmp(src->segment, "%gs") == 0 &&
+           dst->reg &&
+           dst->base_rc == BBRG_RSP)
+               return BBOU_NOP;
+       /* move %reg,%reg is a nop */
+       if (src->reg &&
+           dst->reg &&
+           !src->segment &&
+           !dst->segment &&
+           strcmp(src->base, dst->base) == 0)
+               return BBOU_NOP;
+       /* Special case for the code that switches stacks in the scheduler
+        * (switch_to()).  That code must modify RSP but it does it in a well
+        * defined manner.  Do not invalidate RSP.
+        */
+       if (dst->reg &&
+           dst->base_rc == BBRG_RSP &&
+           full_register_dst &&
+           bb_is_scheduler_address()) {
+               bb_read_operand(src);
+               return BBOU_NOP;
+       }
+       /* Special case for the code that switches stacks in resume from
+        * hibernation code.  That code must modify RSP but it does it in a
+        * well defined manner.  Do not invalidate RSP.
+        */
+       if (src->memory &&
+           dst->reg &&
+           dst->base_rc == BBRG_RSP &&
+           full_register_dst &&
+           strcmp(bb_func_name, "restore_image") == 0) {
+               bb_read_operand(src);
+               return BBOU_NOP;
+       }
+       return BBOU_RSWD;
+}
+
+static enum bb_operand_usage
+bb_usage_xadd(const struct bb_operand *src, const struct bb_operand *dst)
+{
+       /* Simulate xadd as a series of instructions including mov, that way we
+        * get the benefit of all the special cases already handled by
+        * BBOU_MOV.
+        *
+        * tmp = src + dst, src = dst, dst = tmp.
+        *
+        * For tmp, pick a register that is undefined.  If all registers are
+        * defined then pick one that is not being used by xadd.
+        */
+       enum bb_reg_code reg = BBRG_UNDEFINED;
+       struct bb_operand tmp;
+       struct bb_reg_contains save_tmp;
+       enum bb_operand_usage usage;
+       int undefined = 0;
+       for (reg = BBRG_RAX; reg < BBRG_RAX + KDB_INT_REGISTERS; ++reg) {
+               if (bb_reg_code_value(reg) == BBRG_UNDEFINED) {
+                       undefined = 1;
+                       break;
+               }
+       }
+       if (!undefined) {
+               for (reg = BBRG_RAX; reg < BBRG_RAX + KDB_INT_REGISTERS; ++reg) {
+                       if (reg != src->base_rc &&
+                           reg != src->index_rc &&
+                           reg != dst->base_rc &&
+                           reg != dst->index_rc &&
+                           reg != BBRG_RSP)
+                               break;
+               }
+       }
+       KDB_DEBUG_BB("  %s saving tmp %s\n", __FUNCTION__, bbrg_name[reg]);
+       save_tmp = bb_reg_state->contains[reg - BBRG_RAX];
+       bb_reg_set_undef(reg);
+       memset(&tmp, 0, sizeof(tmp));
+       tmp.present = 1;
+       tmp.reg = 1;
+       tmp.base = debug_kmalloc(strlen(bbrg_name[reg]) + 2, GFP_ATOMIC);
+       if (tmp.base) {
+               tmp.base[0] = '%';
+               strcpy(tmp.base + 1, bbrg_name[reg]);
+       }
+       tmp.base_rc = reg;
+       bb_read_operand(src);
+       bb_read_operand(dst);
+       if (bb_usage_mov(src, dst, sizeof("xadd")-1) == BBOU_NOP)
+               usage = BBOU_RSRD;
+       else
+               usage = BBOU_RSRDWS;
+       bb_usage_mov(&tmp, dst, sizeof("xadd")-1);
+       KDB_DEBUG_BB("  %s restoring tmp %s\n", __FUNCTION__, bbrg_name[reg]);
+       bb_reg_state->contains[reg - BBRG_RAX] = save_tmp;
+       debug_kfree(tmp.base);
+       return usage;
+}
+
+static enum bb_operand_usage
+bb_usage_xchg(const struct bb_operand *src, const struct bb_operand *dst)
+{
+       /* Simulate xchg as a series of mov instructions, that way we get the
+        * benefit of all the special cases already handled by BBOU_MOV.
+        *
+        * mov dst,tmp; mov src,dst; mov tmp,src;
+        *
+        * For tmp, pick a register that is undefined.  If all registers are
+        * defined then pick one that is not being used by xchg.
+        */
+       enum bb_reg_code reg = BBRG_UNDEFINED;
+       int rs = BBOU_RS, rd = BBOU_RD, ws = BBOU_WS, wd = BBOU_WD;
+       struct bb_operand tmp;
+       struct bb_reg_contains save_tmp;
+       int undefined = 0;
+       for (reg = BBRG_RAX; reg < BBRG_RAX + KDB_INT_REGISTERS; ++reg) {
+               if (bb_reg_code_value(reg) == BBRG_UNDEFINED) {
+                       undefined = 1;
+                       break;
+               }
+       }
+       if (!undefined) {
+               for (reg = BBRG_RAX; reg < BBRG_RAX + KDB_INT_REGISTERS; ++reg) {
+                       if (reg != src->base_rc &&
+                           reg != src->index_rc &&
+                           reg != dst->base_rc &&
+                           reg != dst->index_rc &&
+                           reg != BBRG_RSP)
+                               break;
+               }
+       }
+       KDB_DEBUG_BB("  %s saving tmp %s\n", __FUNCTION__, bbrg_name[reg]);
+       save_tmp = bb_reg_state->contains[reg - BBRG_RAX];
+       memset(&tmp, 0, sizeof(tmp));
+       tmp.present = 1;
+       tmp.reg = 1;
+       tmp.base = debug_kmalloc(strlen(bbrg_name[reg]) + 2, GFP_ATOMIC);
+       if (tmp.base) {
+               tmp.base[0] = '%';
+               strcpy(tmp.base + 1, bbrg_name[reg]);
+       }
+       tmp.base_rc = reg;
+       if (bb_usage_mov(dst, &tmp, sizeof("xchg")-1) == BBOU_NOP)
+               rd = 0;
+       if (bb_usage_mov(src, dst, sizeof("xchg")-1) == BBOU_NOP) {
+               rs = 0;
+               wd = 0;
+       }
+       if (bb_usage_mov(&tmp, src, sizeof("xchg")-1) == BBOU_NOP)
+               ws = 0;
+       KDB_DEBUG_BB("  %s restoring tmp %s\n", __FUNCTION__, bbrg_name[reg]);
+       bb_reg_state->contains[reg - BBRG_RAX] = save_tmp;
+       debug_kfree(tmp.base);
+       return rs | rd | ws | wd;
+}
+
+/* Invalidate all the scratch registers */
+
+static void
+bb_invalidate_scratch_reg(void)
+{
+       int i, j;
+       for (i = BBRG_RAX; i < BBRG_RAX + KDB_INT_REGISTERS; ++i) {
+               for (j = 0; j < ARRAY_SIZE(bb_preserved_reg); ++j) {
+                       if (i == bb_preserved_reg[j])
+                               goto preserved;
+               }
+               bb_reg_set_undef(i);
+preserved:
+               continue;
+       }
+}
+
+static void
+bb_pass2_computed_jmp(const struct bb_operand *src)
+{
+       unsigned long table = src->disp;
+       kdb_machreg_t addr;
+       while (!bb_giveup) {
+               if (kdb_getword(&addr, table, sizeof(addr)))
+                       return;
+               if (addr < bb_func_start || addr >= bb_func_end)
+                       return;
+               bb_transfer(bb_curr_addr, addr, 0);
+               table += KDB_WORD_SIZE;
+       }
+}
+
+/* The current instruction has been decoded and all the information is in
+ * bb_decode.  Based on the opcode, track any operand usage that we care about.
+ */
+
+static void
+bb_usage(void)
+{
+       enum bb_operand_usage usage = bb_decode.match->usage;
+       struct bb_operand *src = &bb_decode.src;
+       struct bb_operand *dst = &bb_decode.dst;
+       struct bb_operand *dst2 = &bb_decode.dst2;
+       int opcode_suffix, operand_length;
+
+       /* First handle all the special usage cases, and map them to a generic
+        * case after catering for the side effects.
+        */
+
+       if (usage == BBOU_IMUL &&
+           src->present && !dst->present && !dst2->present) {
+               /* single operand imul, same effects as mul */
+               usage = BBOU_MUL;
+       }
+
+       /* AT&T syntax uses movs<l1><l2> for move with sign extension, instead
+        * of the Intel movsx.  The AT&T syntax causes problems for the opcode
+        * mapping; movs with sign extension needs to be treated as a generic
+        * read src, write dst, but instead it falls under the movs I/O
+        * instruction.  Fix it.
+        */
+       if (usage == BBOU_MOVS && strlen(bb_decode.opcode) > 5)
+               usage = BBOU_RSWD;
+
+       /* This switch statement deliberately does not use 'default' at the top
+        * level.  That way the compiler will complain if a new BBOU_ enum is
+        * added above and not explicitly handled here.
+        */
+       switch (usage) {
+       case BBOU_UNKNOWN:      /* drop through */
+       case BBOU_RS:           /* drop through */
+       case BBOU_RD:           /* drop through */
+       case BBOU_RSRD:         /* drop through */
+       case BBOU_WS:           /* drop through */
+       case BBOU_RSWS:         /* drop through */
+       case BBOU_RDWS:         /* drop through */
+       case BBOU_RSRDWS:       /* drop through */
+       case BBOU_WD:           /* drop through */
+       case BBOU_RSWD:         /* drop through */
+       case BBOU_RDWD:         /* drop through */
+       case BBOU_RSRDWD:       /* drop through */
+       case BBOU_WSWD:         /* drop through */
+       case BBOU_RSWSWD:       /* drop through */
+       case BBOU_RDWSWD:       /* drop through */
+       case BBOU_RSRDWSWD:
+               break;          /* ignore generic usage for now */
+       case BBOU_ADD:
+               /* Special case for add instructions that adjust registers
+                * which are mapping the stack.
+                */
+               if (dst->reg && bb_is_osp_defined(dst->base_rc)) {
+                       bb_adjust_osp_instruction(1);
+                       usage = BBOU_RS;
+               } else {
+                       usage = BBOU_RSRDWD;
+               }
+               break;
+       case BBOU_CALL:
+               /* Invalidate the scratch registers.  Functions sync_regs and
+                * save_v86_state are special, their return value is the new
+                * stack pointer.
+                */
+               bb_reg_state_print(bb_reg_state);
+               bb_invalidate_scratch_reg();
+               if (bb_is_static_disp(src)) {
+                       if (src->disp == bb_sync_regs) {
+                               bb_reg_set_reg(BBRG_RAX, BBRG_RSP);
+                       } else if (src->disp == bb_save_v86_state) {
+                               bb_reg_set_reg(BBRG_RAX, BBRG_RSP);
+                               bb_adjust_osp(BBRG_RAX, +KDB_WORD_SIZE);
+                       }
+               }
+               usage = BBOU_NOP;
+               break;
+       case BBOU_CBW:
+               /* Convert word in RAX.  Read RAX, write RAX */
+               bb_reg_read(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RAX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_CMOV:
+               /* cmove %gs:0x<nn>,%rsp is used to conditionally switch to
+                * another stack.  Ignore this special case, it is handled by
+                * the stack unwinding code.
+                */
+               if (src->segment &&
+                   strcmp(src->segment, "%gs") == 0 &&
+                   dst->reg &&
+                   dst->base_rc == BBRG_RSP)
+                       usage = BBOU_NOP;
+               else
+                       usage = BBOU_RSWD;
+               break;
+       case BBOU_CMPXCHG:
+               /* Read RAX, write RAX plus src read, dst write */
+               bb_reg_read(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RAX);
+               usage = BBOU_RSWD;
+               break;
+       case BBOU_CMPXCHGD:
+               /* Read RAX, RBX, RCX, RDX, write RAX, RDX plus src read/write */
+               bb_reg_read(BBRG_RAX);
+               bb_reg_read(BBRG_RBX);
+               bb_reg_read(BBRG_RCX);
+               bb_reg_read(BBRG_RDX);
+               bb_reg_set_undef(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RDX);
+               usage = BBOU_RSWS;
+               break;
+       case BBOU_CPUID:
+               /* Read RAX, write RAX, RBX, RCX, RDX */
+               bb_reg_read(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RBX);
+               bb_reg_set_undef(BBRG_RCX);
+               bb_reg_set_undef(BBRG_RDX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_CWD:
+               /* Convert word in RAX, RDX.  Read RAX, write RDX */
+               bb_reg_read(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RDX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_DIV:  /* drop through */
+       case BBOU_IDIV:
+               /* The 8 bit variants only affect RAX, the 16, 32 and 64 bit
+                * variants affect RDX as well.
+                */
+               switch (usage) {
+               case BBOU_DIV:
+                       opcode_suffix = bb_decode.opcode[3];
+                       break;
+               case BBOU_IDIV:
+                       opcode_suffix = bb_decode.opcode[4];
+                       break;
+               default:
+                       opcode_suffix = 'q';
+                       break;
+               }
+               operand_length = bb_operand_length(src, opcode_suffix);
+               bb_reg_read(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RAX);
+               if (operand_length != 8) {
+                       bb_reg_read(BBRG_RDX);
+                       bb_reg_set_undef(BBRG_RDX);
+               }
+               usage = BBOU_RS;
+               break;
+       case BBOU_IMUL:
+               /* Only the two and three operand forms get here.  The one
+                * operand form is treated as mul.
+                */
+               if (dst2->present) {
+                       /* The three operand form is a special case, read the first two
+                        * operands, write the third.
+                        */
+                       bb_read_operand(src);
+                       bb_read_operand(dst);
+                       bb_write_operand(dst2);
+                       usage = BBOU_NOP;
+               } else {
+                       usage = BBOU_RSRDWD;
+               }
+               break;
+       case BBOU_IRET:
+               bb_sanity_check(0);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_JMP:
+               if (bb_is_static_disp(src))
+                       bb_transfer(bb_curr_addr, src->disp, 0);
+               else if (src->indirect &&
+                        src->disp &&
+                        src->base == NULL &&
+                        src->index &&
+                        src->scale == KDB_WORD_SIZE)
+                       bb_pass2_computed_jmp(src);
+               usage = BBOU_RS;
+               break;
+       case BBOU_LAHF:
+               /* Write RAX */
+               bb_reg_set_undef(BBRG_RAX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_LEA:
+               /* dst = src + disp.  Often used to calculate offsets into the
+                * stack, so check if it uses a stack pointer.
+                */
+               usage = BBOU_RSWD;
+               if (bb_is_simple_memory(src)) {
+                      if (bb_is_osp_defined(src->base_rc)) {
+                               bb_reg_set_reg(dst->base_rc, src->base_rc);
+                               bb_adjust_osp_instruction(1);
+                               usage = BBOU_RS;
+                       } else if (src->disp == 0 &&
+                                  src->base_rc == dst->base_rc) {
+                               /* lea 0(%reg),%reg is generated by i386
+                                * GENERIC_NOP7.
+                                */
+                               usage = BBOU_NOP;
+                       } else if (src->disp == 4096 &&
+                                  (src->base_rc == BBRG_R8 ||
+                                   src->base_rc == BBRG_RDI) &&
+                                  strcmp(bb_func_name, "relocate_kernel") == 0) {
+                               /* relocate_kernel: setup a new stack at the
+                                * end of the physical control page, using
+                                * (x86_64) lea 4096(%r8),%rsp or (i386) lea
+                                * 4096(%edi),%esp
+                                */
+                               usage = BBOU_NOP;
+                       }
+               }
+               break;
+       case BBOU_LEAVE:
+               /* RSP = RBP; RBP = *(RSP); RSP += KDB_WORD_SIZE; */
+               bb_reg_set_reg(BBRG_RSP, BBRG_RBP);
+               if (bb_is_osp_defined(BBRG_RSP))
+                       bb_reg_set_memory(BBRG_RBP, BBRG_RSP, 0);
+               else
+                       bb_reg_set_undef(BBRG_RBP);
+               if (bb_is_osp_defined(BBRG_RSP))
+                       bb_adjust_osp(BBRG_RSP, KDB_WORD_SIZE);
+               /* common_interrupt uses leave in a non-standard manner */
+               if (strcmp(bb_func_name, "common_interrupt") != 0)
+                       bb_sanity_check(0);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_LODS:
+               /* Read RSI, write RAX, RSI */
+               bb_reg_read(BBRG_RSI);
+               bb_reg_set_undef(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RSI);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_LOOP:
+               /* Read and write RCX */
+               bb_reg_read(BBRG_RCX);
+               bb_reg_set_undef(BBRG_RCX);
+               if (bb_is_static_disp(src))
+                       bb_transfer(bb_curr_addr, src->disp, 0);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_LSS:
+               /* lss offset(%esp),%esp leaves esp well defined */
+               if (dst->reg &&
+                   dst->base_rc == BBRG_RSP &&
+                   bb_is_simple_memory(src) &&
+                   src->base_rc == BBRG_RSP) {
+                       bb_adjust_osp(BBRG_RSP, 2*KDB_WORD_SIZE + src->disp);
+                       usage = BBOU_NOP;
+               } else {
+                       usage = BBOU_RSWD;
+               }
+               break;
+       case BBOU_MONITOR:
+               /* Read RAX, RCX, RDX */
+               bb_reg_set_undef(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RCX);
+               bb_reg_set_undef(BBRG_RDX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_MOV:
+               usage = bb_usage_mov(src, dst, sizeof("mov")-1);
+               break;
+       case BBOU_MOVS:
+               /* Read RSI, RDI, write RSI, RDI */
+               bb_reg_read(BBRG_RSI);
+               bb_reg_read(BBRG_RDI);
+               bb_reg_set_undef(BBRG_RSI);
+               bb_reg_set_undef(BBRG_RDI);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_MUL:
+               /* imul (one operand form only) or mul.  Read RAX.  If the
+                * operand length is not 8 then write RDX.
+                */
+               if (bb_decode.opcode[0] == 'i')
+                       opcode_suffix = bb_decode.opcode[4];
+               else
+                       opcode_suffix = bb_decode.opcode[3];
+               operand_length = bb_operand_length(src, opcode_suffix);
+               bb_reg_read(BBRG_RAX);
+               if (operand_length != 8)
+                       bb_reg_set_undef(BBRG_RDX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_MWAIT:
+               /* Read RAX, RCX */
+               bb_reg_read(BBRG_RAX);
+               bb_reg_read(BBRG_RCX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_NOP:
+               break;
+       case BBOU_OUTS:
+               /* Read RSI, RDX, write RSI */
+               bb_reg_read(BBRG_RSI);
+               bb_reg_read(BBRG_RDX);
+               bb_reg_set_undef(BBRG_RSI);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_POP:
+               /* Complicated by the fact that you can pop from top of stack
+                * to a stack location, for this case the destination location
+                * is calculated after adjusting RSP.  Analysis of the kernel
+                * code shows that gcc only uses this strange format to get the
+                * flags into a local variable, e.g. pushf; popl 0x10(%esp); so
+                * I am going to ignore this special case.
+                */
+               usage = BBOU_WS;
+               if (!bb_is_osp_defined(BBRG_RSP)) {
+                       if (!bb_is_scheduler_address()) {
+                               kdb_printf("pop when BBRG_RSP is undefined?\n");
+                               bb_giveup = 1;
+                       }
+               } else {
+                       if (src->reg) {
+                               bb_reg_set_memory(src->base_rc, BBRG_RSP, 0);
+                               usage = BBOU_NOP;
+                       }
+                       /* pop %rsp does not adjust rsp */
+                       if (!src->reg ||
+                           src->base_rc != BBRG_RSP)
+                               bb_adjust_osp(BBRG_RSP, KDB_WORD_SIZE);
+               }
+               break;
+       case BBOU_POPF:
+               /* Do not care about flags, just adjust RSP */
+               if (!bb_is_osp_defined(BBRG_RSP)) {
+                       if (!bb_is_scheduler_address()) {
+                               kdb_printf("popf when BBRG_RSP is undefined?\n");
+                               bb_giveup = 1;
+                       }
+               } else {
+                       bb_adjust_osp(BBRG_RSP, KDB_WORD_SIZE);
+               }
+               usage = BBOU_WS;
+               break;
+       case BBOU_PUSH:
+               /* Complicated by the fact that you can push from a stack
+                * location to top of stack, the source location is calculated
+                * before adjusting RSP.  Analysis of the kernel code shows
+                * that gcc only uses this strange format to restore the flags
+                * from a local variable, e.g. pushl 0x10(%esp); popf; so I am
+                * going to ignore this special case.
+                */
+               usage = BBOU_RS;
+               if (!bb_is_osp_defined(BBRG_RSP)) {
+                       if (!bb_is_scheduler_address()) {
+                               kdb_printf("push when BBRG_RSP is undefined?\n");
+                               bb_giveup = 1;
+                       }
+               } else {
+                       bb_adjust_osp(BBRG_RSP, -KDB_WORD_SIZE);
+                       if (src->reg &&
+                           bb_reg_code_offset(BBRG_RSP) <= 0)
+                               bb_memory_set_reg(BBRG_RSP, src->base_rc, 0);
+               }
+               break;
+       case BBOU_PUSHF:
+               /* Do not care about flags, just adjust RSP */
+               if (!bb_is_osp_defined(BBRG_RSP)) {
+                       if (!bb_is_scheduler_address()) {
+                               kdb_printf("pushf when BBRG_RSP is undefined?\n");
+                               bb_giveup = 1;
+                       }
+               } else {
+                       bb_adjust_osp(BBRG_RSP, -KDB_WORD_SIZE);
+               }
+               usage = BBOU_WS;
+               break;
+       case BBOU_RDMSR:
+               /* Read RCX, write RAX, RDX */
+               bb_reg_read(BBRG_RCX);
+               bb_reg_set_undef(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RDX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_RDTSC:
+               /* Write RAX, RDX */
+               bb_reg_set_undef(BBRG_RAX);
+               bb_reg_set_undef(BBRG_RDX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_RET:
+               usage = BBOU_NOP;
+               /* Functions that restore state which was saved by another
+                * function or build new kernel stacks.  We cannot verify what
+                * is being restored so skip the sanity check.
+                */
+               if (strcmp(bb_func_name, "restore_image") == 0 ||
+                   strcmp(bb_func_name, "relocate_kernel") == 0 ||
+                   strcmp(bb_func_name, "identity_mapped") == 0 ||
+                   strcmp(bb_func_name, "xen_iret_crit_fixup") == 0 ||
+                   strcmp(bb_func_name, "math_abort") == 0)
+                       break;
+               bb_sanity_check(0);
+               break;
+       case BBOU_SAHF:
+               /* Read RAX */
+               bb_reg_read(BBRG_RAX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_SCAS:
+               /* Read RAX, RDI, write RDI */
+               bb_reg_read(BBRG_RAX);
+               bb_reg_read(BBRG_RDI);
+               bb_reg_set_undef(BBRG_RDI);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_SUB:
+               /* Special case for sub instructions that adjust registers
+                * which are mapping the stack.
+                */
+               if (dst->reg && bb_is_osp_defined(dst->base_rc)) {
+                       bb_adjust_osp_instruction(-1);
+                       usage = BBOU_RS;
+               } else {
+                       usage = BBOU_RSRDWD;
+               }
+               break;
+       case BBOU_SYSEXIT:
+               bb_sanity_check(1);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_SYSRET:
+               bb_sanity_check(1);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_WRMSR:
+               /* Read RCX, RAX, RDX */
+               bb_reg_read(BBRG_RCX);
+               bb_reg_read(BBRG_RAX);
+               bb_reg_read(BBRG_RDX);
+               usage = BBOU_NOP;
+               break;
+       case BBOU_XADD:
+               usage = bb_usage_xadd(src, dst);
+               break;
+       case BBOU_XCHG:
+               /* i386 do_IRQ with 4K stacks does xchg %ebx,%esp; call
+                * irq_handler; mov %ebx,%esp; to switch stacks.  Ignore this
+                * stack switch when tracking registers, it is handled by
+                * higher level backtrace code.  Convert xchg %ebx,%esp to mov
+                * %esp,%ebx so the later mov %ebx,%esp becomes a NOP and the
+                * stack remains defined so we can backtrace through do_IRQ's
+                * stack switch.
+                *
+                * Ditto for do_softirq.
+                */
+               if (src->reg &&
+                   dst->reg &&
+                   src->base_rc == BBRG_RBX &&
+                   dst->base_rc == BBRG_RSP &&
+                   (strcmp(bb_func_name, "do_IRQ") == 0 ||
+                    strcmp(bb_func_name, "do_softirq") == 0)) {
+                       strcpy(bb_decode.opcode, "mov");
+                       usage = bb_usage_mov(dst, src, sizeof("mov")-1);
+               } else {
+                       usage = bb_usage_xchg(src, dst);
+               }
+               break;
+       case BBOU_XOR:
+               /* xor %reg,%reg only counts as a register write, the original
+                * contents of reg are irrelevant.
+                */
+               if (src->reg && dst->reg && src->base_rc == dst->base_rc)
+                       usage = BBOU_WS;
+               else
+                       usage = BBOU_RSRDWD;
+               break;
+       }
+
+       /* The switch statement above handled all the special cases.  Every
+        * opcode should now have a usage of NOP or one of the generic cases.
+        */
+       if (usage == BBOU_UNKNOWN || usage == BBOU_NOP) {
+               /* nothing to do */
+       } else if (usage >= BBOU_RS && usage <= BBOU_RSRDWSWD) {
+               if (usage & BBOU_RS)
+                       bb_read_operand(src);
+               if (usage & BBOU_RD)
+                       bb_read_operand(dst);
+               if (usage & BBOU_WS)
+                       bb_write_operand(src);
+               if (usage & BBOU_WD)
+                       bb_write_operand(dst);
+       } else {
+               kdb_printf("%s: opcode not fully handled\n", __FUNCTION__);
+               if (!KDB_DEBUG(BB)) {
+                       bb_print_opcode();
+                       if (bb_decode.src.present)
+                               bb_print_operand("src", &bb_decode.src);
+                       if (bb_decode.dst.present)
+                               bb_print_operand("dst", &bb_decode.dst);
+                       if (bb_decode.dst2.present)
+                               bb_print_operand("dst2", &bb_decode.dst2);
+               }
+               bb_giveup = 1;
+       }
+}
+
+static void
+bb_parse_buffer(void)
+{
+       char *p, *src, *dst = NULL, *dst2 = NULL;
+       int paren = 0;
+       p = bb_buffer;
+       memset(&bb_decode, 0, sizeof(bb_decode));
+       KDB_DEBUG_BB(" '%s'\n", p);
+       p += strcspn(p, ":");   /* skip address and function name+offset: */
+       if (*p++ != ':') {
+               kdb_printf("%s: cannot find ':' in buffer '%s'\n",
+                          __FUNCTION__, bb_buffer);
+               bb_giveup = 1;
+               return;
+       }
+       p += strspn(p, " \t");  /* step to opcode */
+       if (strncmp(p, "(bad)", 5) == 0)
+               strcpy(p, "nop");
+       /* separate any opcode prefix */
+       if (strncmp(p, "lock", 4) == 0 ||
+           strncmp(p, "rep", 3) == 0 ||
+           strncmp(p, "rex", 3) == 0 ||
+           strncmp(p, "addr", 4) == 0) {
+               bb_decode.prefix = p;
+               p += strcspn(p, " \t");
+               *p++ = '\0';
+               p += strspn(p, " \t");
+       }
+       bb_decode.opcode = p;
+       strsep(&p, " \t");      /* step to end of opcode */
+       if (bb_parse_opcode())
+               return;
+       if (!p)
+               goto no_operands;
+       p += strspn(p, " \t");  /* step to operand(s) */
+       if (!*p)
+               goto no_operands;
+       src = p;
+       p = strsep(&p, " \t");  /* strip comments after operands */
+       /* split 'src','dst' but ignore ',' inside '(' ')' */
+       while (*p) {
+               if (*p == '(') {
+                       ++paren;
+               } else if (*p == ')') {
+                       --paren;
+               } else if (*p == ',' && paren == 0) {
+                       *p = '\0';
+                       if (dst)
+                               dst2 = p+1;
+                       else
+                               dst = p+1;
+               }
+               ++p;
+       }
+       bb_parse_operand(src, &bb_decode.src);
+       if (KDB_DEBUG(BB))
+               bb_print_operand("src", &bb_decode.src);
+       if (dst && !bb_giveup) {
+               bb_parse_operand(dst, &bb_decode.dst);
+               if (KDB_DEBUG(BB))
+                       bb_print_operand("dst", &bb_decode.dst);
+       }
+       if (dst2 && !bb_giveup) {
+               bb_parse_operand(dst2, &bb_decode.dst2);
+               if (KDB_DEBUG(BB))
+                       bb_print_operand("dst2", &bb_decode.dst2);
+       }
+no_operands:
+       if (!bb_giveup)
+               bb_usage();
+}
+
+static int
+bb_dis_pass2(PTR file, const char *fmt, ...)
+{
+       char *p;
+       int l = strlen(bb_buffer);
+       va_list ap;
+       va_start(ap, fmt);
+       vsnprintf(bb_buffer + l, sizeof(bb_buffer) - l, fmt, ap);
+       va_end(ap);
+       if ((p = strchr(bb_buffer, '\n'))) {
+               *p = '\0';
+               p = bb_buffer;
+               p += strcspn(p, ":");
+               if (*p++ == ':')
+                       bb_fixup_switch_to(p);
+               bb_parse_buffer();
+               bb_buffer[0] = '\0';
+       }
+       return 0;
+}
+
+static void
+bb_printaddr_pass2(bfd_vma addr, disassemble_info *dip)
+{
+       kdb_symtab_t symtab;
+       unsigned int offset;
+       dip->fprintf_func(dip->stream, "0x%lx", addr);
+       kdbnearsym(addr, &symtab);
+       if (symtab.sym_name) {
+               dip->fprintf_func(dip->stream, " <%s", symtab.sym_name);
+               if ((offset = addr - symtab.sym_start))
+                       dip->fprintf_func(dip->stream, "+0x%x", offset);
+               dip->fprintf_func(dip->stream, ">");
+       }
+}
+
+/* Set the starting register and memory state for the current bb */
+
+static void
+bb_start_block0_special(void)
+{
+       int i;
+       short offset_address;
+       enum bb_reg_code reg, value;
+       struct bb_name_state *r;
+       for (i = 0, r = bb_special_cases;
+            i < ARRAY_SIZE(bb_special_cases);
+            ++i, ++r) {
+               if (bb_func_start == r->address && r->fname == NULL)
+                       goto match;
+       }
+       return;
+match:
+       /* Set the running registers */
+       for (reg = BBRG_RAX; reg < r->regs_size; ++reg) {
+               value = r->regs[reg].value;
+               if (test_bit(value, r->skip_regs.bits)) {
+                       /* this regs entry is not defined for this label */
+                       continue;
+               }
+               bb_reg_code_set_value(reg, value);
+               bb_reg_code_set_offset(reg, r->regs[reg].offset);
+       }
+       /* Set any memory contents, e.g. pt_regs.  Adjust RSP as required. */
+       offset_address = 0;
+       for (i = 0; i < r->mem_size; ++i) {
+               offset_address = max_t(int,
+                               r->mem[i].offset_address + KDB_WORD_SIZE,
+                               offset_address);
+       }
+       if (bb_reg_code_offset(BBRG_RSP) > -offset_address)
+               bb_adjust_osp(BBRG_RSP, -offset_address - bb_reg_code_offset(BBRG_RSP));
+       for (i = 0; i < r->mem_size; ++i) {
+               value = r->mem[i].value;
+               if (test_bit(value, r->skip_mem.bits)) {
+                       /* this memory entry is not defined for this label */
+                       continue;
+               }
+               bb_memory_set_reg_value(BBRG_RSP, r->mem[i].offset_address,
+                                       value, 0);
+               bb_reg_set_undef(value);
+       }
+       return;
+}
+
+static void
+bb_pass2_start_block(int number)
+{
+       int i, j, k, first, changed;
+       size_t size;
+       struct bb_jmp *bb_jmp;
+       struct bb_reg_state *state;
+       struct bb_memory_contains *c1, *c2;
+       bb_reg_state->mem_count = bb_reg_state_max;
+       size = bb_reg_state_size(bb_reg_state);
+       memset(bb_reg_state, 0, size);
+
+       if (number == 0) {
+               /* The first block is assumed to have well defined inputs */
+               bb_start_block0();
+               /* Some assembler labels have non-standard entry
+                * states.
+                */
+               bb_start_block0_special();
+               bb_reg_state_print(bb_reg_state);
+               return;
+       }
+
+       /* Merge all the input states for the current bb together */
+       first = 1;
+       changed = 0;
+       for (i = 0; i < bb_jmp_count; ++i) {
+               bb_jmp = bb_jmp_list + i;
+               if (bb_jmp->to != bb_curr->start)
+                       continue;
+               state = bb_jmp->state;
+               if (!state)
+                       continue;
+               if (first) {
+                       size = bb_reg_state_size(state);
+                       memcpy(bb_reg_state, state, size);
+                       KDB_DEBUG_BB("  first state %p\n", state);
+                       bb_reg_state_print(bb_reg_state);
+                       first = 0;
+                       continue;
+               }
+
+               KDB_DEBUG_BB("  merging state %p\n", state);
+               /* Merge the register states */
+               for (j = 0; j < ARRAY_SIZE(state->contains); ++j) {
+                       if (memcmp(bb_reg_state->contains + j,
+                                  state->contains + j,
+                                  sizeof(bb_reg_state->contains[0]))) {
+                               /* Different states for this register from two
+                                * or more inputs, make it undefined.
+                                */
+                               if (bb_reg_state->contains[j].value ==
+                                   BBRG_UNDEFINED) {
+                                       KDB_DEBUG_BB("  ignoring %s\n",
+                                                   bbrg_name[j + BBRG_RAX]);
+                               } else {
+                                       bb_reg_set_undef(BBRG_RAX + j);
+                                       changed = 1;
+                               }
+                       }
+               }
+
+               /* Merge the memory states.  This relies on both
+                * bb_reg_state->memory and state->memory being sorted in
+                * descending order, with undefined entries at the end.
+                */
+               c1 = bb_reg_state->memory;
+               c2 = state->memory;
+               j = k = 0;
+               while (j < bb_reg_state->mem_count &&
+                      k < state->mem_count) {
+                       if (c1->offset_address < c2->offset_address) {
+                               KDB_DEBUG_BB_OFFSET(c2->offset_address,
+                                                   "  ignoring c2->offset_address ",
+                                                   "\n");
+                               ++c2;
+                               ++k;
+                               continue;
+                       }
+                       if (c1->offset_address > c2->offset_address) {
+                               /* Memory location is not in all input states,
+                                * delete the memory location.
+                                */
+                               bb_delete_memory(c1->offset_address);
+                               changed = 1;
+                               ++c1;
+                               ++j;
+                               continue;
+                       }
+                       if (memcmp(c1, c2, sizeof(*c1))) {
+                               /* Same location, different contents, delete
+                                * the memory location.
+                                */
+                               bb_delete_memory(c1->offset_address);
+                               KDB_DEBUG_BB_OFFSET(c2->offset_address,
+                                                   "  ignoring c2->offset_address ",
+                                                   "\n");
+                               changed = 1;
+                       }
+                       ++c1;
+                       ++c2;
+                       ++j;
+                       ++k;
+               }
+               while (j < bb_reg_state->mem_count) {
+                       bb_delete_memory(c1->offset_address);
+                       changed = 1;
+                       ++c1;
+                       ++j;
+               }
+       }
+       if (changed) {
+               KDB_DEBUG_BB("  final state\n");
+               bb_reg_state_print(bb_reg_state);
+       }
+}
+
+/* We have reached the exit point from the current function, either a call to
+ * the next function or the instruction that was about to executed when an
+ * interrupt occurred.  Save the current register state in bb_exit_state.
+ */
+
+static void
+bb_save_exit_state(void)
+{
+       size_t size;
+       debug_kfree(bb_exit_state);
+       bb_exit_state = NULL;
+       bb_reg_state_canonicalize();
+       size = bb_reg_state_size(bb_reg_state);
+       bb_exit_state = debug_kmalloc(size, GFP_ATOMIC);
+       if (!bb_exit_state) {
+               kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
+               bb_giveup = 1;
+               return;
+       }
+       memcpy(bb_exit_state, bb_reg_state, size);
+}
+
+static int
+bb_pass2_do_changed_blocks(int allow_missing)
+{
+       int i, j, missing, changed, maxloops;
+       unsigned long addr;
+       struct bb_jmp *bb_jmp;
+       KDB_DEBUG_BB("\n  %s: allow_missing %d\n", __FUNCTION__, allow_missing);
+       /* Absolute worst case is we have to iterate over all the basic blocks
+        * in an "out of order" state, each iteration losing one register or
+        * memory state.  Any more loops than that is a bug.  "out of order"
+        * means that the layout of blocks in memory does not match the logic
+        * flow through those blocks so (for example) block 27 comes before
+        * block 2.  To allow for out of order blocks, multiply maxloops by the
+        * number of blocks.
+        */
+       maxloops = (KDB_INT_REGISTERS + bb_reg_state_max) * bb_count;
+       changed = 1;
+       do {
+               changed = 0;
+               for (i = 0; i < bb_count; ++i) {
+                       bb_curr = bb_list[i];
+                       if (!bb_curr->changed)
+                               continue;
+                       missing = 0;
+                       for (j = 0, bb_jmp = bb_jmp_list;
+                            j < bb_jmp_count;
+                            ++j, ++bb_jmp) {
+                               if (bb_jmp->to == bb_curr->start &&
+                                   !bb_jmp->state)
+                                       ++missing;
+                       }
+                       if (missing > allow_missing)
+                               continue;
+                       bb_curr->changed = 0;
+                       changed = 1;
+                       KDB_DEBUG_BB("\n  bb[%d]\n", i);
+                       bb_pass2_start_block(i);
+                       for (addr = bb_curr->start;
+                            addr <= bb_curr->end; ) {
+                               bb_curr_addr = addr;
+                               if (addr == bb_exit_addr)
+                                       bb_save_exit_state();
+                               addr += kdba_id_printinsn(addr, &kdb_di);
+                               kdb_di.fprintf_func(NULL, "\n");
+                               if (bb_giveup)
+                                       goto done;
+                       }
+                       if (!bb_exit_state) {
+                               /* ATTRIB_NORET functions are a problem with
+                                * the current gcc.  Allow the trailing address
+                                * a bit of leaway.
+                                */
+                               if (addr == bb_exit_addr ||
+                                   addr == bb_exit_addr + 1)
+                                       bb_save_exit_state();
+                       }
+                       if (bb_curr->drop_through)
+                               bb_transfer(bb_curr->end,
+                                           bb_list[i+1]->start, 1);
+               }
+               if (maxloops-- == 0) {
+                       kdb_printf("\n\n%s maxloops reached\n",
+                                  __FUNCTION__);
+                       bb_giveup = 1;
+                       goto done;
+               }
+       } while(changed);
+done:
+       for (i = 0; i < bb_count; ++i) {
+               bb_curr = bb_list[i];
+               if (bb_curr->changed)
+                       return 1;       /* more to do, increase allow_missing */
+       }
+       return 0;       /* all blocks done */
+}
+
+/* Assume that the current function is a pass through function that does not
+ * refer to its register parameters.  Exclude known asmlinkage functions and
+ * assume the other functions actually use their registers.
+ */
+
+static void
+bb_assume_pass_through(void)
+{
+       static int first_time = 1;
+       if (strncmp(bb_func_name, "sys_", 4) == 0 ||
+           strncmp(bb_func_name, "compat_sys_", 11) == 0 ||
+           strcmp(bb_func_name, "schedule") == 0 ||
+           strcmp(bb_func_name, "do_softirq") == 0 ||
+           strcmp(bb_func_name, "printk") == 0 ||
+           strcmp(bb_func_name, "vprintk") == 0 ||
+           strcmp(bb_func_name, "preempt_schedule") == 0 ||
+           strcmp(bb_func_name, "start_kernel") == 0 ||
+           strcmp(bb_func_name, "csum_partial") == 0 ||
+           strcmp(bb_func_name, "csum_partial_copy_generic") == 0 ||
+           strcmp(bb_func_name, "math_state_restore") == 0 ||
+           strcmp(bb_func_name, "panic") == 0 ||
+           strcmp(bb_func_name, "kdb_printf") == 0 ||
+           strcmp(bb_func_name, "kdb_interrupt") == 0)
+               return;
+       if (bb_asmlinkage_arch())
+               return;
+       bb_reg_params = REGPARM;
+       if (first_time) {
+               kdb_printf("  %s has memory parameters but no register "
+                          "parameters.\n  Assuming it is a 'pass "
+                          "through' function that does not refer to "
+                          "its register\n  parameters and setting %d "
+                          "register parameters\n",
+                          bb_func_name, REGPARM);
+               first_time = 0;
+               return;
+       }
+       kdb_printf("  Assuming %s is 'pass through' with %d register "
+                  "parameters\n",
+                  bb_func_name, REGPARM);
+}
+
+static void
+bb_pass2(void)
+{
+       int allow_missing;
+       if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
+               kdb_printf("%s: start\n", __FUNCTION__);
+
+       kdb_di.fprintf_func = bb_dis_pass2;
+       kdb_di.print_address_func = bb_printaddr_pass2;
+
+       bb_reg_state = debug_kmalloc(sizeof(*bb_reg_state), GFP_ATOMIC);
+       if (!bb_reg_state) {
+               kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
+               bb_giveup = 1;
+               return;
+       }
+       bb_list[0]->changed = 1;
+
+       /* If a block does not have all its input states available then it is
+        * possible for a register to initially appear to hold a known value,
+        * but when other inputs are available then it becomes a variable
+        * value.  The initial false state of "known" can generate false values
+        * for other registers and can even make it look like stack locations
+        * are being changed.
+        *
+        * To avoid these false positives, only process blocks which have all
+        * their inputs defined.  That gives a clean depth first traversal of
+        * the tree, except for loops.  If there are any loops, then start
+        * processing blocks with one missing input, then two missing inputs
+        * etc.
+        *
+        * Absolute worst case is we have to iterate over all the jmp entries,
+        * each iteration allowing one more missing input.  Any more loops than
+        * that is a bug.  Watch out for the corner case of 0 jmp entries.
+        */
+       for (allow_missing = 0; allow_missing <= bb_jmp_count; ++allow_missing) {
+               if (!bb_pass2_do_changed_blocks(allow_missing))
+                       break;
+               if (bb_giveup)
+                       break;
+       }
+       if (allow_missing > bb_jmp_count) {
+               kdb_printf("\n\n%s maxloops reached\n",
+                          __FUNCTION__);
+               bb_giveup = 1;
+               return;
+       }
+
+       if (bb_memory_params && bb_reg_params)
+               bb_reg_params = REGPARM;
+       if (REGPARM &&
+           bb_memory_params &&
+           !bb_reg_params)
+               bb_assume_pass_through();
+       if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM)) {
+               kdb_printf("%s: end bb_reg_params %d bb_memory_params %d\n",
+                          __FUNCTION__, bb_reg_params, bb_memory_params);
+               if (bb_exit_state) {
+                       kdb_printf("%s: bb_exit_state at " kdb_bfd_vma_fmt0 "\n",
+                                  __FUNCTION__, bb_exit_addr);
+                       bb_do_reg_state_print(bb_exit_state);
+               }
+       }
+}
+
+static void
+bb_cleanup(void)
+{
+       int i;
+       struct bb* bb;
+       struct bb_reg_state *state;
+       while (bb_count) {
+               bb = bb_list[0];
+               bb_delete(0);
+       }
+       debug_kfree(bb_list);
+       bb_list = NULL;
+       bb_count = bb_max = 0;
+       for (i = 0; i < bb_jmp_count; ++i) {
+               state = bb_jmp_list[i].state;
+               if (state && --state->ref_count == 0)
+                       debug_kfree(state);
+       }
+       debug_kfree(bb_jmp_list);
+       bb_jmp_list = NULL;
+       bb_jmp_count = bb_jmp_max = 0;
+       debug_kfree(bb_reg_state);
+       bb_reg_state = NULL;
+       bb_reg_state_max = 0;
+       debug_kfree(bb_exit_state);
+       bb_exit_state = NULL;
+       bb_reg_params = bb_memory_params = 0;
+       bb_giveup = 0;
+}
+
+static int
+bb_spurious_global_label(const char *func_name)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(bb_spurious); ++i) {
+               if (strcmp(bb_spurious[i], func_name) == 0)
+                       return 1;
+       }
+       return 0;
+}
+
+/* Given the current actual register contents plus the exit state deduced from
+ * a basic block analysis of the current function, rollback the actual register
+ * contents to the values they had on entry to this function.
+ */
+
+static void
+bb_actual_rollback(const struct kdb_activation_record *ar)
+{
+       int i, offset_address;
+       struct bb_memory_contains *c;
+       enum bb_reg_code reg;
+       unsigned long address, osp = 0;
+       struct bb_actual new[ARRAY_SIZE(bb_actual)];
+
+
+       if (!bb_exit_state) {
+               kdb_printf("%s: no bb_exit_state, cannot rollback\n",
+                          __FUNCTION__);
+               bb_giveup = 1;
+               return;
+       }
+       memcpy(bb_reg_state, bb_exit_state, bb_reg_state_size(bb_exit_state));
+       memset(new, 0, sizeof(new));
+
+       /* The most important register for obtaining saved state is rsp so get
+        * its new value first.  Prefer rsp if it is valid, then other
+        * registers.  Saved values of rsp in memory are unusable without a
+        * register that points to memory.
+        */
+       if (!bb_actual_valid(BBRG_RSP)) {
+               kdb_printf("%s: no starting value for RSP, cannot rollback\n",
+                          __FUNCTION__);
+               bb_giveup = 1;
+               return;
+       }
+       if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
+               kdb_printf("%s: rsp " kdb_bfd_vma_fmt0,
+                          __FUNCTION__, bb_actual_value(BBRG_RSP));
+       i = BBRG_RSP;
+       if (!bb_is_osp_defined(i)) {
+               for (i = BBRG_RAX; i < BBRG_RAX + KDB_INT_REGISTERS; ++i) {
+                       if (bb_is_osp_defined(i) && bb_actual_valid(i))
+                               break;
+               }
+       }
+       if (bb_is_osp_defined(i) && bb_actual_valid(i)) {
+               osp = new[BBRG_RSP - BBRG_RAX].value =
+                     bb_actual_value(i) - bb_reg_code_offset(i);
+               new[BBRG_RSP - BBRG_RAX].valid = 1;
+               if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
+                       kdb_printf(" -> osp " kdb_bfd_vma_fmt0 "\n", osp);
+       } else {
+               bb_actual_set_valid(BBRG_RSP, 0);
+               if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
+                       kdb_printf(" -> undefined\n");
+               kdb_printf("%s: no ending value for RSP, cannot rollback\n",
+                          __FUNCTION__);
+               bb_giveup = 1;
+               return;
+       }
+
+       /* Now the other registers.  First look at register values that have
+        * been copied to other registers.
+        */
+       for (i = BBRG_RAX; i < BBRG_RAX + KDB_INT_REGISTERS; ++i) {
+               reg = bb_reg_code_value(i);
+               if (bb_is_int_reg(reg)) {
+                       new[reg - BBRG_RAX] = bb_actual[i - BBRG_RAX];
+                       if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM)) {
+                               kdb_printf("%s: %s is in %s ",
+                                           __FUNCTION__,
+                                           bbrg_name[reg],
+                                           bbrg_name[i]);
+                               if (bb_actual_valid(i))
+                                       kdb_printf(" -> " kdb_bfd_vma_fmt0 "\n",
+                                                   bb_actual_value(i));
+                               else
+                                       kdb_printf("(invalid)\n");
+                       }
+               }
+       }
+
+       /* Finally register values that have been saved on stack */
+       for (i = 0, c = bb_reg_state->memory;
+            i < bb_reg_state->mem_count;
+            ++i, ++c) {
+               offset_address = c->offset_address;
+               reg = c->value;
+               if (!bb_is_int_reg(reg))
+                       continue;
+               address = osp + offset_address;
+               if (address < ar->stack.logical_start ||
+                   address >= ar->stack.logical_end) {
+                       new[reg - BBRG_RAX].value = 0;
+                       new[reg - BBRG_RAX].valid = 0;
+                       if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
+                               kdb_printf("%s: %s -> undefined\n",
+                                          __FUNCTION__,
+                                          bbrg_name[reg]);
+               } else {
+                       if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM)) {
+                               kdb_printf("%s: %s -> *(osp",
+                                          __FUNCTION__,
+                                          bbrg_name[reg]);
+                               KDB_DEBUG_BB_OFFSET_PRINTF(offset_address, "", " ");
+                               kdb_printf(kdb_bfd_vma_fmt0, address);
+                       }
+                       new[reg - BBRG_RAX].value = *(bfd_vma *)address;
+                       new[reg - BBRG_RAX].valid = 1;
+                       if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
+                               kdb_printf(") = " kdb_bfd_vma_fmt0 "\n",
+                                          new[reg - BBRG_RAX].value);
+               }
+       }
+
+       memcpy(bb_actual, new, sizeof(bb_actual));
+}
+
+/* Return true if the current function is an interrupt handler */
+
+static bool
+bb_interrupt_handler(kdb_machreg_t rip)
+{
+       unsigned long disp8, disp32, target, addr = (unsigned long)rip;
+       unsigned char code[5];
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(bb_hardware_handlers); ++i)
+               if (strcmp(bb_func_name, bb_hardware_handlers[i]) == 0)
+                       return 1;
+
+       /* Given the large number of interrupt handlers, it is easiest to look
+        * at the next instruction and see if it is a jmp to the common exit
+        * routines.
+        */
+       if (kdb_getarea(code, addr) ||
+           kdb_getword(&disp32, addr+1, 4) ||
+           kdb_getword(&disp8, addr+1, 1))
+               return 0;       /* not a valid code address */
+       if (code[0] == 0xe9) {
+               target = addr + (s32) disp32 + 5;       /* jmp disp32 */
+               if (target == bb_ret_from_intr ||
+                   target == bb_common_interrupt ||
+                   target == bb_error_entry)
+                       return 1;
+       }
+       if (code[0] == 0xeb) {
+               target = addr + (s8) disp8 + 2;         /* jmp disp8 */
+               if (target == bb_ret_from_intr ||
+                   target == bb_common_interrupt ||
+                   target == bb_error_entry)
+                       return 1;
+       }
+
+       return 0;
+}
+
+/* Copy argument information that was deduced by the basic block analysis and
+ * rollback into the kdb stack activation record.
+ */
+
+static void
+bb_arguments(struct kdb_activation_record *ar)
+{
+       int i;
+       enum bb_reg_code reg;
+       kdb_machreg_t rsp;
+       ar->args = bb_reg_params + bb_memory_params;
+       bitmap_zero(ar->valid.bits, KDBA_MAXARGS);
+       for (i = 0; i < bb_reg_params; ++i) {
+               reg = bb_param_reg[i];
+               if (bb_actual_valid(reg)) {
+                       ar->arg[i] = bb_actual_value(reg);
+                       set_bit(i, ar->valid.bits);
+               }
+       }
+       if (!bb_actual_valid(BBRG_RSP))
+               return;
+       rsp = bb_actual_value(BBRG_RSP);
+       for (i = bb_reg_params; i < ar->args; ++i) {
+               rsp += KDB_WORD_SIZE;
+               if (kdb_getarea(ar->arg[i], rsp) == 0)
+                       set_bit(i, ar->valid.bits);
+       }
+}
+
+/* Given an exit address from a function, decompose the entire function into
+ * basic blocks and determine the register state at the exit point.
+ */
+
+static void
+kdb_bb(unsigned long exit)
+{
+       kdb_symtab_t symtab;
+       if (!kdbnearsym(exit, &symtab)) {
+               kdb_printf("%s: address " kdb_bfd_vma_fmt0 " not recognised\n",
+                          __FUNCTION__, exit);
+               bb_giveup = 1;
+               return;
+       }
+       bb_exit_addr = exit;
+       bb_mod_name = symtab.mod_name;
+       bb_func_name = symtab.sym_name;
+       bb_func_start = symtab.sym_start;
+       bb_func_end = symtab.sym_end;
+       /* Various global labels exist in the middle of assembler code and have
+        * a non-standard state.  Ignore these labels and use the start of the
+        * previous label instead.
+        */
+       while (bb_spurious_global_label(symtab.sym_name)) {
+               if (!kdbnearsym(symtab.sym_start - 1, &symtab))
+                       break;
+               bb_func_start = symtab.sym_start;
+       }
+       bb_mod_name = symtab.mod_name;
+       bb_func_name = symtab.sym_name;
+       bb_func_start = symtab.sym_start;
+       /* Ignore spurious labels past this point and use the next non-spurious
+        * label as the end point.
+        */
+       if (kdbnearsym(bb_func_end, &symtab)) {
+               while (bb_spurious_global_label(symtab.sym_name)) {
+                       bb_func_end = symtab.sym_end;
+                       if (!kdbnearsym(symtab.sym_end + 1, &symtab))
+                               break;
+               }
+       }
+       bb_pass1();
+       if (!bb_giveup)
+               bb_pass2();
+       if (bb_giveup)
+               kdb_printf("%s: " kdb_bfd_vma_fmt0
+                          " [%s]%s failed at " kdb_bfd_vma_fmt0 "\n\n",
+                          __FUNCTION__, exit,
+                          bb_mod_name, bb_func_name, bb_curr_addr);
+}
+
+static int
+kdb_bb1(int argc, const char **argv)
+{
+       int diag;
+       unsigned long addr;
+       bb_cleanup();   /* in case previous command was interrupted */
+       kdba_id_init(&kdb_di);
+       if (argc != 1)
+               return KDB_ARGCOUNT;
+       if ((diag = kdbgetularg((char *)argv[1], &addr)))
+               return diag;
+       kdb_save_flags();
+       kdb_flags |= KDB_DEBUG_FLAG_BB << KDB_DEBUG_FLAG_SHIFT;
+       kdb_bb(addr);
+       bb_cleanup();
+       kdb_restore_flags();
+       kdbnearsym_cleanup();
+       return 0;
+}
+
+/* Run a basic block analysis on every function in the base kernel.  Used as a
+ * global sanity check to find errors in the basic block code.
+ */
+
+static int
+kdb_bb_all(int argc, const char **argv)
+{
+       loff_t pos = 0;
+       const char *symname;
+       unsigned long addr;
+       int i, max_errors = 20;
+       struct bb_name_state *r;
+       kdb_printf("%s: build variables:"
+                  " CCVERSION \"" __stringify(CCVERSION) "\""
+#ifdef CONFIG_X86_64
+                  " CONFIG_X86_64"
+#endif
+#ifdef CONFIG_4KSTACKS
+                  " CONFIG_4KSTACKS"
+#endif
+#ifdef CONFIG_PREEMPT
+                  " CONFIG_PREEMPT"
+#endif
+#ifdef CONFIG_VM86
+                  " CONFIG_VM86"
+#endif
+#ifdef CONFIG_FRAME_POINTER
+                  " CONFIG_FRAME_POINTER"
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+                  " CONFIG_TRACE_IRQFLAGS"
+#endif
+#ifdef CONFIG_HIBERNATION
+                  " CONFIG_HIBERNATION"
+#endif
+#ifdef CONFIG_KPROBES
+                  " CONFIG_KPROBES"
+#endif
+#ifdef CONFIG_KEXEC
+                  " CONFIG_KEXEC"
+#endif
+#ifdef CONFIG_MATH_EMULATION
+                  " CONFIG_MATH_EMULATION"
+#endif
+#ifdef CONFIG_XEN
+                  " CONFIG_XEN"
+#endif
+#ifdef CONFIG_DEBUG_INFO
+                  " CONFIG_DEBUG_INFO"
+#endif
+#ifdef NO_SIBLINGS
+                  " NO_SIBLINGS"
+#endif
+                  " REGPARM=" __stringify(REGPARM)
+                  "\n\n", __FUNCTION__);
+       for (i = 0, r = bb_special_cases;
+            i < ARRAY_SIZE(bb_special_cases);
+            ++i, ++r) {
+               if (!r->address)
+                       kdb_printf("%s: cannot find special_case name %s\n",
+                                  __FUNCTION__, r->name);
+       }
+       for (i = 0; i < ARRAY_SIZE(bb_spurious); ++i) {
+               if (!kallsyms_lookup_name(bb_spurious[i]))
+                       kdb_printf("%s: cannot find spurious label %s\n",
+                                  __FUNCTION__, bb_spurious[i]);
+       }
+       while ((symname = kdb_walk_kallsyms(&pos))) {
+               if (strcmp(symname, "_stext") == 0 ||
+                   strcmp(symname, "stext") == 0)
+                       break;
+       }
+       if (!symname) {
+               kdb_printf("%s: cannot find _stext\n", __FUNCTION__);
+               return 0;
+       }
+       kdba_id_init(&kdb_di);
+       i = 0;
+       while ((symname = kdb_walk_kallsyms(&pos))) {
+               if (strcmp(symname, "_etext") == 0)
+                       break;
+               if (i++ % 100 == 0)
+                       kdb_printf(".");
+               /* x86_64 has some 16 bit functions that appear between stext
+                * and _etext.  Skip them.
+                */
+               if (strcmp(symname, "verify_cpu") == 0 ||
+                   strcmp(symname, "verify_cpu_noamd") == 0 ||
+                   strcmp(symname, "verify_cpu_sse_test") == 0 ||
+                   strcmp(symname, "verify_cpu_no_longmode") == 0 ||
+                   strcmp(symname, "verify_cpu_sse_ok") == 0 ||
+                   strcmp(symname, "mode_seta") == 0 ||
+                   strcmp(symname, "bad_address") == 0 ||
+                   strcmp(symname, "wakeup_code") == 0 ||
+                   strcmp(symname, "wakeup_code_start") == 0 ||
+                   strcmp(symname, "wakeup_start") == 0 ||
+                   strcmp(symname, "wakeup_32_vector") == 0 ||
+                   strcmp(symname, "wakeup_32") == 0 ||
+                   strcmp(symname, "wakeup_long64_vector") == 0 ||
+                   strcmp(symname, "wakeup_long64") == 0 ||
+                   strcmp(symname, "gdta") == 0 ||
+                   strcmp(symname, "idt_48a") == 0 ||
+                   strcmp(symname, "gdt_48a") == 0 ||
+                   strcmp(symname, "bogus_real_magic") == 0 ||
+                   strcmp(symname, "bogus_64_magic") == 0 ||
+                   strcmp(symname, "no_longmode") == 0 ||
+                   strcmp(symname, "mode_set") == 0 ||
+                   strcmp(symname, "mode_seta") == 0 ||
+                   strcmp(symname, "setbada") == 0 ||
+                   strcmp(symname, "check_vesa") == 0 ||
+                   strcmp(symname, "check_vesaa") == 0 ||
+                   strcmp(symname, "_setbada") == 0 ||
+                   strcmp(symname, "wakeup_stack_begin") == 0 ||
+                   strcmp(symname, "wakeup_stack") == 0 ||
+                   strcmp(symname, "wakeup_level4_pgt") == 0 ||
+                   strcmp(symname, "acpi_copy_wakeup_routine") == 0 ||
+                   strcmp(symname, "wakeup_end") == 0 ||
+                   strcmp(symname, "do_suspend_lowlevel_s4bios") == 0 ||
+                   strcmp(symname, "do_suspend_lowlevel") == 0 ||
+                   strcmp(symname, "wakeup_pmode_return") == 0 ||
+                   strcmp(symname, "restore_registers") == 0)
+                       continue;
+               /* __kprobes_text_end contains branches to the middle of code,
+                * with undefined states.
+                */
+               if (strcmp(symname, "__kprobes_text_end") == 0)
+                       continue;
+               /* Data in the middle of the text segment :( */
+               if (strcmp(symname, "level2_kernel_pgt") == 0 ||
+                   strcmp(symname, "level3_kernel_pgt") == 0)
+                       continue;
+               if (bb_spurious_global_label(symname))
+                       continue;
+               if ((addr = kallsyms_lookup_name(symname)) == 0)
+                       continue;
+               // kdb_printf("BB " kdb_bfd_vma_fmt0 " %s\n", addr, symname);
+               bb_cleanup();   /* in case previous command was interrupted */
+               kdbnearsym_cleanup();
+               kdb_bb(addr);
+               touch_nmi_watchdog();
+               if (bb_giveup) {
+                       if (max_errors-- == 0) {
+                               kdb_printf("%s: max_errors reached, giving up\n",
+                                          __FUNCTION__);
+                               break;
+                       } else {
+                               bb_giveup = 0;
+                       }
+               }
+       }
+       kdb_printf("\n");
+       bb_cleanup();
+       kdbnearsym_cleanup();
+       return 0;
+}
+
+/*
+ *=============================================================================
+ *
+ * Everything above this line is doing basic block analysis, function by
+ * function.  Everything below this line uses the basic block data to do a
+ * complete backtrace over all functions that are used by a process.
+ *
+ *=============================================================================
+ */
+
+
+/*============================================================================*/
+/*                                                                            */
+/* Most of the backtrace code and data is common to x86_64 and i386.  This    */
+/* large ifdef contains all of the differences between the two architectures. */
+/*                                                                            */
+/* Make sure you update the correct section of this ifdef.                    */
+/*                                                                            */
+/*============================================================================*/
+#define XCS "cs"
+#define RSP "sp"
+#define RIP "ip"
+#define ARCH_RSP sp
+#define ARCH_RIP ip
+
+#ifdef CONFIG_X86_64
+
+#define ARCH_NORMAL_PADDING (16 * 8)
+
+/* x86_64 has multiple alternate stacks, with different sizes and different
+ * offsets to get the link from one stack to the next.  Some of the stacks are
+ * referenced via cpu_pda, some via per_cpu orig_ist.  Debug events can even
+ * have multiple nested stacks within the single physical stack, each nested
+ * stack has its own link and some of those links are wrong.
+ *
+ * Consistent it's not!
+ *
+ * Do not assume that these stacks are aligned on their size.
+ */
+#define INTERRUPT_STACK (N_EXCEPTION_STACKS + 1)
+void
+kdba_get_stack_info_alternate(kdb_machreg_t addr, int cpu,
+                             struct kdb_activation_record *ar)
+{
+       static struct {
+               const char *id;
+               unsigned int total_size;
+               unsigned int nested_size;
+               unsigned int next;
+       } *sdp, stack_data[] = {
+               [STACKFAULT_STACK - 1] =  { "stackfault",    EXCEPTION_STKSZ, EXCEPTION_STKSZ, EXCEPTION_STKSZ - 2*sizeof(void *) },
+               [DOUBLEFAULT_STACK - 1] = { "doublefault",   EXCEPTION_STKSZ, EXCEPTION_STKSZ, EXCEPTION_STKSZ - 2*sizeof(void *) },
+               [NMI_STACK - 1] =         { "nmi",           EXCEPTION_STKSZ, EXCEPTION_STKSZ, EXCEPTION_STKSZ - 2*sizeof(void *) },
+               [DEBUG_STACK - 1] =       { "debug",         DEBUG_STKSZ,     EXCEPTION_STKSZ, EXCEPTION_STKSZ - 2*sizeof(void *) },
+               [MCE_STACK - 1] =         { "machine check", EXCEPTION_STKSZ, EXCEPTION_STKSZ, EXCEPTION_STKSZ - 2*sizeof(void *) },
+               [INTERRUPT_STACK - 1] =   { "interrupt",     IRQSTACKSIZE,    IRQSTACKSIZE,    IRQSTACKSIZE    -   sizeof(void *) },
+       };
+       unsigned long total_start = 0, total_size, total_end;
+       int sd, found = 0;
+       extern unsigned long kdba_orig_ist(int, int);
+
+       for (sd = 0, sdp = stack_data;
+            sd < ARRAY_SIZE(stack_data);
+            ++sd, ++sdp) {
+               total_size = sdp->total_size;
+               if (!total_size)
+                       continue;       /* in case stack_data[] has any holes */
+               if (cpu < 0) {
+                       /* Arbitrary address which can be on any cpu, see if it
+                        * falls within any of the alternate stacks
+                        */
+                       int c;
+                       for_each_online_cpu(c) {
+                               if (sd == INTERRUPT_STACK - 1)
+                                       total_end = (unsigned long)cpu_pda(c)->irqstackptr;
+                               else
+                                       total_end = per_cpu(orig_ist, c).ist[sd];
+                               total_start = total_end - total_size;
+                               if (addr >= total_start && addr < total_end) {
+                                       found = 1;
+                                       cpu = c;
+                                       break;
+                               }
+                       }
+                       if (!found)
+                               continue;
+               }
+               /* Only check the supplied or found cpu */
+               if (sd == INTERRUPT_STACK - 1)
+                       total_end = (unsigned long)cpu_pda(cpu)->irqstackptr;
+               else
+                       total_end = per_cpu(orig_ist, cpu).ist[sd];
+               total_start = total_end - total_size;
+               if (addr >= total_start && addr < total_end) {
+                       found = 1;
+                       break;
+               }
+       }
+       if (!found)
+               return;
+       /* find which nested stack the address is in */
+       while (addr > total_start + sdp->nested_size)
+               total_start += sdp->nested_size;
+       ar->stack.physical_start = total_start;
+       ar->stack.physical_end = total_start + sdp->nested_size;
+       ar->stack.logical_start = total_start;
+       ar->stack.logical_end = total_start + sdp->next;
+       ar->stack.next = *(unsigned long *)ar->stack.logical_end;
+       ar->stack.id = sdp->id;
+
+       /* Nasty: when switching to the interrupt stack, the stack state of the
+        * caller is split over two stacks, the original stack and the
+        * interrupt stack.  One word (the previous frame pointer) is stored on
+        * the interrupt stack, the rest of the interrupt data is in the old
+        * frame.  To make the interrupted stack state look as though it is
+        * contiguous, copy the missing word from the interrupt stack to the
+        * original stack and adjust the new stack pointer accordingly.
+        */
+
+       if (sd == INTERRUPT_STACK - 1) {
+               *(unsigned long *)(ar->stack.next - KDB_WORD_SIZE) =
+                       ar->stack.next;
+               ar->stack.next -= KDB_WORD_SIZE;
+       }
+}
+
+/* rip is not in the thread struct for x86_64.  We know that the stack value
+ * was saved in schedule near the label thread_return.  Setting rip to
+ * thread_return lets the stack trace find that we are in schedule and
+ * correctly decode its prologue.
+ */
+
+static kdb_machreg_t
+kdba_bt_stack_rip(const struct task_struct *p)
+{
+       return bb_thread_return;
+}
+
+#else  /* !CONFIG_X86_64 */
+
+#define ARCH_NORMAL_PADDING (19 * 4)
+
+#ifdef CONFIG_4KSTACKS
+static struct thread_info **kdba_hardirq_ctx, **kdba_softirq_ctx;
+#endif /* CONFIG_4KSTACKS */
+
+/* On a 4K stack kernel, hardirq_ctx and softirq_ctx are [NR_CPUS] arrays.  The
+ * first element of each per-cpu stack is a struct thread_info.
+ */
+void
+kdba_get_stack_info_alternate(kdb_machreg_t addr, int cpu,
+                             struct kdb_activation_record *ar)
+{
+#ifdef CONFIG_4KSTACKS
+       struct thread_info *tinfo;
+       tinfo = (struct thread_info *)(addr & -THREAD_SIZE);
+       if (cpu < 0) {
+               /* Arbitrary address, see if it falls within any of the irq
+                * stacks
+                */
+               int found = 0;
+               for_each_online_cpu(cpu) {
+                       if (tinfo == kdba_hardirq_ctx[cpu] ||
+                           tinfo == kdba_softirq_ctx[cpu]) {
+                               found = 1;
+                               break;
+                       }
+               }
+               if (!found)
+                       return;
+       }
+       if (tinfo == kdba_hardirq_ctx[cpu] ||
+           tinfo == kdba_softirq_ctx[cpu]) {
+               ar->stack.physical_start = (kdb_machreg_t)tinfo;
+               ar->stack.physical_end = ar->stack.physical_start + THREAD_SIZE;
+               ar->stack.logical_start = ar->stack.physical_start +
+                                         sizeof(struct thread_info);
+               ar->stack.logical_end = ar->stack.physical_end;
+               ar->stack.next = tinfo->previous_esp;
+               if (tinfo == kdba_hardirq_ctx[cpu])
+                       ar->stack.id = "hardirq_ctx";
+               else
+                       ar->stack.id = "softirq_ctx";
+       }
+#endif /* CONFIG_4KSTACKS */
+}
+
+/* rip is in the thread struct for i386 */
+
+static kdb_machreg_t
+kdba_bt_stack_rip(const struct task_struct *p)
+{
+       return p->thread.ip;
+}
+
+#endif /* CONFIG_X86_64 */
+
+/* Given an address which claims to be on a stack, an optional cpu number and
+ * an optional task address, get information about the stack.
+ *
+ * t == NULL, cpu < 0 indicates an arbitrary stack address with no associated
+ * struct task, the address can be in an alternate stack or any task's normal
+ * stack.
+ *
+ * t != NULL, cpu >= 0 indicates a running task, the address can be in an
+ * alternate stack or that task's normal stack.
+ *
+ * t != NULL, cpu < 0 indicates a blocked task, the address can only be in that
+ * task's normal stack.
+ *
+ * t == NULL, cpu >= 0 is not a valid combination.
+ */
+
+static void
+kdba_get_stack_info(kdb_machreg_t rsp, int cpu,
+                   struct kdb_activation_record *ar,
+                   const struct task_struct *t)
+{
+       struct thread_info *tinfo;
+       struct task_struct *g, *p;
+       memset(&ar->stack, 0, sizeof(ar->stack));
+       if (KDB_DEBUG(ARA))
+               kdb_printf("%s: " RSP "=0x%lx cpu=%d task=%p\n",
+                          __FUNCTION__, rsp, cpu, t);
+       if (t == NULL || cpu >= 0) {
+               kdba_get_stack_info_alternate(rsp, cpu, ar);
+               if (ar->stack.logical_start)
+                       goto out;
+       }
+       rsp &= -THREAD_SIZE;
+       tinfo = (struct thread_info *)rsp;
+       if (t == NULL) {
+               /* Arbitrary stack address without an associated task, see if
+                * it falls within any normal process stack, including the idle
+                * tasks.
+                */
+               kdb_do_each_thread(g, p) {
+                       if (tinfo == task_thread_info(p)) {
+                               t = p;
+                               goto found;
+                       }
+               } kdb_while_each_thread(g, p);
+               for_each_online_cpu(cpu) {
+                       p = idle_task(cpu);
+                       if (tinfo == task_thread_info(p)) {
+                               t = p;
+                               goto found;
+                       }
+               }
+       found:
+               if (KDB_DEBUG(ARA))
+                       kdb_printf("%s: found task %p\n", __FUNCTION__, t);
+       } else if (cpu >= 0) {
+               /* running task */
+               struct kdb_running_process *krp = kdb_running_process + cpu;
+               if (krp->p != t || tinfo != task_thread_info(t))
+                       t = NULL;
+               if (KDB_DEBUG(ARA))
+                       kdb_printf("%s: running task %p\n", __FUNCTION__, t);
+       } else {
+               /* blocked task */
+               if (tinfo != task_thread_info(t))
+                       t = NULL;
+               if (KDB_DEBUG(ARA))
+                       kdb_printf("%s: blocked task %p\n", __FUNCTION__, t);
+       }
+       if (t) {
+               ar->stack.physical_start = rsp;
+               ar->stack.physical_end = rsp + THREAD_SIZE;
+               ar->stack.logical_start = rsp + sizeof(struct thread_info);
+               ar->stack.logical_end = ar->stack.physical_end - ARCH_NORMAL_PADDING;
+               ar->stack.next = 0;
+               ar->stack.id = "normal";
+       }
+out:
+       if (ar->stack.physical_start && KDB_DEBUG(ARA)) {
+               kdb_printf("%s: ar->stack\n", __FUNCTION__);
+               kdb_printf("    physical_start=0x%lx\n", ar->stack.physical_start);
+               kdb_printf("    physical_end=0x%lx\n", ar->stack.physical_end);
+               kdb_printf("    logical_start=0x%lx\n", ar->stack.logical_start);
+               kdb_printf("    logical_end=0x%lx\n", ar->stack.logical_end);
+               kdb_printf("    next=0x%lx\n", ar->stack.next);
+               kdb_printf("    id=%s\n", ar->stack.id);
+               kdb_printf("    set MDCOUNT %ld\n",
+                          (ar->stack.physical_end - ar->stack.physical_start) /
+                          KDB_WORD_SIZE);
+               kdb_printf("    mds " kdb_machreg_fmt0 "\n",
+                          ar->stack.physical_start);
+       }
+}
+
+static void
+bt_print_one(kdb_machreg_t rip, kdb_machreg_t rsp,
+             const struct kdb_activation_record *ar,
+             const kdb_symtab_t *symtab, int argcount)
+{
+       int btsymarg = 0;
+       int nosect = 0;
+
+       kdbgetintenv("BTSYMARG", &btsymarg);
+       kdbgetintenv("NOSECT", &nosect);
+
+       kdb_printf(kdb_machreg_fmt0, rsp);
+       kdb_symbol_print(rip, symtab,
+                        KDB_SP_SPACEB|KDB_SP_VALUE);
+       if (argcount && ar->args) {
+               int i, argc = ar->args;
+               kdb_printf(" (");
+               if (argc > argcount)
+                       argc = argcount;
+               for (i = 0; i < argc; i++) {
+                       if (i)
+                               kdb_printf(", ");
+                       if (test_bit(i, ar->valid.bits))
+                               kdb_printf("0x%lx", ar->arg[i]);
+                       else
+                               kdb_printf("invalid");
+               }
+               kdb_printf(")");
+       }
+       kdb_printf("\n");
+       if (symtab->sym_name) {
+               if (!nosect) {
+                       kdb_printf("                               %s",
+                                  symtab->mod_name);
+                       if (symtab->sec_name && symtab->sec_start)
+                               kdb_printf(" 0x%lx 0x%lx",
+                                          symtab->sec_start, symtab->sec_end);
+                       kdb_printf(" 0x%lx 0x%lx\n",
+                                  symtab->sym_start, symtab->sym_end);
+               }
+       }
+       if (argcount && ar->args && btsymarg) {
+               int i, argc = ar->args;
+               kdb_symtab_t arg_symtab;
+               for (i = 0; i < argc; i++) {
+                       kdb_machreg_t arg = ar->arg[i];
+                       if (test_bit(i, ar->valid.bits) &&
+                           kdbnearsym(arg, &arg_symtab)) {
+                               kdb_printf("                       ARG %2d ", i);
+                               kdb_symbol_print(arg, &arg_symtab,
+                                                KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+                       }
+               }
+       }
+}
+
+static void
+kdba_bt_new_stack(struct kdb_activation_record *ar, kdb_machreg_t *rsp,
+                  int *count, int *suppress)
+{
+       /* Nasty: common_interrupt builds a partial pt_regs, with r15 through
+        * rbx not being filled in.  It passes struct pt_regs* to do_IRQ (in
+        * rdi) but the stack pointer is not adjusted to account for r15
+        * through rbx.  This has two effects :-
+        *
+        * (1) struct pt_regs on an external interrupt actually overlaps with
+        *     the local stack area used by do_IRQ.  Not only are r15-rbx
+        *     undefined, the area that claims to hold their values can even
+        *     change as the irq is processed.
+        *
+        * (2) The back stack pointer saved for the new frame is not pointing
+        *     at pt_regs, it is pointing at rbx within the pt_regs passed to
+        *     do_IRQ.
+        *
+        * There is nothing that I can do about (1) but I have to fix (2)
+        * because kdb backtrace looks for the "start" address of pt_regs as it
+        * walks back through the stacks.  When switching from the interrupt
+        * stack to another stack, we have to assume that pt_regs has been
+        * seen and turn off backtrace supression.
+        */
+       int probable_pt_regs = strcmp(ar->stack.id, "interrupt") == 0;
+       *rsp = ar->stack.next;
+       if (KDB_DEBUG(ARA))
+               kdb_printf("new " RSP "=" kdb_machreg_fmt0 "\n", *rsp);
+       bb_actual_set_value(BBRG_RSP, *rsp);
+       kdba_get_stack_info(*rsp, -1, ar, NULL);
+       if (!ar->stack.physical_start) {
+               kdb_printf("+++ Cannot resolve next stack\n");
+       } else if (!*suppress) {
+               kdb_printf(" ======================= <%s>\n",
+                          ar->stack.id);
+               ++*count;
+       }
+       if (probable_pt_regs)
+               *suppress = 0;
+}
+
+/*
+ * kdba_bt_stack
+ *
+ * Inputs:
+ *     addr    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:
+ *     Ultimately all the bt* commands come through this routine.  If
+ *     old_style is 0 then it uses the basic block analysis to get an accurate
+ *     backtrace with arguments, otherwise it falls back to the old method of
+ *     printing anything on stack that looks like a kernel address.
+ *
+ *     Allowing for the stack data pushed by the hardware is tricky.  We
+ *     deduce the presence of hardware pushed data by looking for interrupt
+ *     handlers, either by name or by the code that they contain.  This
+ *     information must be applied to the next function up the stack, because
+ *     the hardware data is above the saved rip for the interrupted (next)
+ *     function.
+ *
+ *     To make things worse, the amount of data pushed is arch specific and
+ *     may depend on the rsp for the next function, not the current function.
+ *     The number of bytes pushed by hardware cannot be calculated until we
+ *     are actually processing the stack for the interrupted function and have
+ *     its rsp.
+ *
+ *     It is also possible for an interrupt to occur in user space and for the
+ *     interrupt handler to also be interrupted.  Check the code selector
+ *     whenever the previous function is an interrupt handler and stop
+ *     backtracing if the interrupt was not in kernel space.
+ */
+
+static int
+kdba_bt_stack(kdb_machreg_t addr, int argcount, const struct task_struct *p,
+              int old_style)
+{
+       struct kdb_activation_record ar;
+       kdb_machreg_t rip = 0, rsp = 0, prev_rsp, cs;
+       kdb_symtab_t symtab;
+       int rip_at_rsp = 0, count = 0, btsp = 0, suppress,
+           interrupt_handler = 0, prev_interrupt_handler = 0, hardware_pushed,
+           prev_noret = 0;
+       struct pt_regs *regs = NULL;
+
+       kdbgetintenv("BTSP", &btsp);
+       suppress = !btsp;
+       memset(&ar, 0, sizeof(ar));
+       if (old_style)
+               kdb_printf("Using old style backtrace, unreliable with no arguments\n");
+
+       /*
+        * 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.
+        *
+        * Warning: type in the wrong address and you will get garbage in the
+        * backtrace.
+        */
+       if (addr) {
+               rsp = addr;
+               kdb_getword(&rip, rsp, sizeof(rip));
+               rip_at_rsp = 1;
+               suppress = 0;
+               kdba_get_stack_info(rsp, -1, &ar, NULL);
+       } else {
+               if (task_curr(p)) {
+                       struct kdb_running_process *krp =
+                           kdb_running_process + task_cpu(p);
+                       kdb_machreg_t cs;
+                       regs = krp->regs;
+                       if (krp->seqno &&
+                           krp->p == p &&
+                           krp->seqno >= kdb_seqno - 1 &&
+                           !KDB_NULL_REGS(regs)) {
+                               /* valid saved state, continue processing */
+                       } else {
+                               kdb_printf
+                                   ("Process did not save state, cannot backtrace\n");
+                               kdb_ps1(p);
+                               return 0;
+                       }
+                       kdba_getregcontents(XCS, regs, &cs);
+                       if ((cs & 0xffff) != __KERNEL_CS) {
+                               kdb_printf("Stack is not in kernel space, backtrace not available\n");
+                               return 0;
+                       }
+                       rip = krp->arch.ARCH_RIP;
+                       rsp = krp->arch.ARCH_RSP;
+                       kdba_get_stack_info(rsp, kdb_process_cpu(p), &ar, p);
+               } else {
+                       /* Not on cpu, assume blocked.  Blocked tasks do not
+                        * have pt_regs.  p->thread contains some data, alas
+                        * what it contains differs between i386 and x86_64.
+                        */
+                       rip = kdba_bt_stack_rip(p);
+                       rsp = p->thread.sp;
+                       suppress = 0;
+                       kdba_get_stack_info(rsp, -1, &ar, p);
+               }
+       }
+       if (!ar.stack.physical_start) {
+               kdb_printf(RSP "=0x%lx is not in a valid kernel stack, backtrace not available\n",
+                          rsp);
+               return 0;
+       }
+       memset(&bb_actual, 0, sizeof(bb_actual));
+       bb_actual_set_value(BBRG_RSP, rsp);
+       bb_actual_set_valid(BBRG_RSP, 1);
+
+       kdb_printf(RSP "%*s" RIP "%*sFunction (args)\n",
+                  2*KDB_WORD_SIZE, " ",
+                  2*KDB_WORD_SIZE, " ");
+       if (ar.stack.next && !suppress)
+               kdb_printf(" ======================= <%s>\n",
+                          ar.stack.id);
+
+       bb_cleanup();
+       /* Run through all the stacks */
+       while (ar.stack.physical_start) {
+               if (rip_at_rsp) {
+                       rip = *(kdb_machreg_t *)rsp;
+                       /* I wish that gcc was fixed to include a nop
+                        * instruction after ATTRIB_NORET functions.  The lack
+                        * of a nop means that the return address points to the
+                        * start of next function, so fudge it to point to one
+                        * byte previous.
+                        *
+                        * No, we cannot just decrement all rip values.
+                        * Sometimes an rip legally points to the start of a
+                        * function, e.g. interrupted code or hand crafted
+                        * assembler.
+                        */
+                       if (prev_noret) {
+                               kdbnearsym(rip, &symtab);
+                               if (rip == symtab.sym_start) {
+                                       --rip;
+                                       if (KDB_DEBUG(ARA))
+                                               kdb_printf("\tprev_noret, " RIP
+                                                          "=0x%lx\n", rip);
+                               }
+                       }
+               }
+               kdbnearsym(rip, &symtab);
+               if (old_style) {
+                       if (__kernel_text_address(rip) && !suppress) {
+                               bt_print_one(rip, rsp, &ar, &symtab, 0);
+                               ++count;
+                       }
+                       if (rsp == (unsigned long)regs) {
+                               if (ar.stack.next && suppress)
+                                       kdb_printf(" ======================= <%s>\n",
+                                                  ar.stack.id);
+                               ++count;
+                               suppress = 0;
+                       }
+                       rsp += sizeof(rip);
+                       rip_at_rsp = 1;
+                       if (rsp >= ar.stack.logical_end) {
+                               if (!ar.stack.next)
+                                       break;
+                               kdba_bt_new_stack(&ar, &rsp, &count, &suppress);
+                               rip_at_rsp = 0;
+                               continue;
+                       }
+               } else {
+                       /* Start each analysis with no dynamic data from the
+                        * previous kdb_bb() run.
+                        */
+                       bb_cleanup();
+                       kdb_bb(rip);
+                       if (bb_giveup)
+                               break;
+                       prev_interrupt_handler = interrupt_handler;
+                       interrupt_handler = bb_interrupt_handler(rip);
+                       prev_rsp = rsp;
+                       if (rip_at_rsp) {
+                               if (prev_interrupt_handler) {
+                                       cs = *((kdb_machreg_t *)rsp + 1) & 0xffff;
+                                       hardware_pushed =
+                                               bb_hardware_pushed_arch(rsp, &ar);
+                               } else {
+                                       cs = __KERNEL_CS;
+                                       hardware_pushed = 0;
+                               }
+                               rsp += sizeof(rip) + hardware_pushed;
+                               if (KDB_DEBUG(ARA))
+                                       kdb_printf("%s: " RSP " "
+                                                  kdb_machreg_fmt0
+                                                  " -> " kdb_machreg_fmt0
+                                                  " hardware_pushed %d"
+                                                  " prev_interrupt_handler %d"
+                                                  " cs 0x%lx\n",
+                                                  __FUNCTION__,
+                                                  prev_rsp,
+                                                  rsp,
+                                                  hardware_pushed,
+                                                  prev_interrupt_handler,
+                                                  cs);
+                               if (rsp >= ar.stack.logical_end &&
+                                   ar.stack.next) {
+                                       kdba_bt_new_stack(&ar, &rsp, &count,
+                                                          &suppress);
+                                       rip_at_rsp = 0;
+                                       continue;
+                               }
+                               bb_actual_set_value(BBRG_RSP, rsp);
+                       } else {
+                               cs = __KERNEL_CS;
+                       }
+                       rip_at_rsp = 1;
+                       bb_actual_rollback(&ar);
+                       if (bb_giveup)
+                               break;
+                       if (bb_actual_value(BBRG_RSP) < rsp) {
+                               kdb_printf("%s: " RSP " is going backwards, "
+                                          kdb_machreg_fmt0 " -> "
+                                          kdb_machreg_fmt0 "\n",
+                                          __FUNCTION__,
+                                          rsp,
+                                          bb_actual_value(BBRG_RSP));
+                               bb_giveup = 1;
+                               break;
+                       }
+                       bb_arguments(&ar);
+                       if (!suppress) {
+                               bt_print_one(rip, prev_rsp, &ar, &symtab, argcount);
+                               ++count;
+                       }
+                       /* Functions that terminate the backtrace */
+                       if (strcmp(bb_func_name, "cpu_idle") == 0 ||
+                           strcmp(bb_func_name, "child_rip") == 0)
+                               break;
+                       if (rsp >= ar.stack.logical_end &&
+                           !ar.stack.next)
+                               break;
+                       if (rsp <= (unsigned long)regs &&
+                           bb_actual_value(BBRG_RSP) > (unsigned long)regs) {
+                               if (ar.stack.next && suppress)
+                                       kdb_printf(" ======================= <%s>\n",
+                                                  ar.stack.id);
+                               ++count;
+                               suppress = 0;
+                       }
+                       if (cs != __KERNEL_CS) {
+                               kdb_printf("Reached user space\n");
+                               break;
+                       }
+                       rsp = bb_actual_value(BBRG_RSP);
+               }
+               prev_noret = bb_noret(bb_func_name);
+               if (count > 200)
+                       break;
+       }
+       if (bb_giveup)
+               return 1;
+       bb_cleanup();
+       kdbnearsym_cleanup();
+
+       if (count > 200) {
+               kdb_printf("bt truncated, count limit reached\n");
+               return 1;
+       } else if (suppress) {
+               kdb_printf
+                   ("bt did not find pt_regs - no trace produced.  Suggest 'set BTSP 1'\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+/*
+ * kdba_bt_address
+ *
+ *     Do a backtrace starting at a specified stack address.  Use this if the
+ *     heuristics get the 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 %rsp comes in handy when examining the stack to do a manual
+ *     traceback.
+ */
+
+int kdba_bt_address(kdb_machreg_t addr, int argcount)
+{
+       int ret;
+       kdba_id_init(&kdb_di);                  /* kdb_bb needs this done once */
+       ret = kdba_bt_stack(addr, argcount, NULL, 0);
+       if (ret == 1)
+               ret = kdba_bt_stack(addr, argcount, NULL, 1);
+       return ret;
+}
+
+/*
+ * 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(const struct task_struct *p, int argcount)
+{
+       int ret;
+       kdba_id_init(&kdb_di);                  /* kdb_bb needs this done once */
+       ret = kdba_bt_stack(0, argcount, p, 0);
+       if (ret == 1)
+               ret = kdba_bt_stack(0, argcount, p, 1);
+       return ret;
+}
+
+static int __init kdba_bt_x86_init(void)
+{
+       int i, c, cp = -1;
+       struct bb_name_state *r;
+
+       kdb_register_repeat("bb1", kdb_bb1, "<vaddr>",  "Analyse one basic block", 0, KDB_REPEAT_NONE);
+       kdb_register_repeat("bb_all", kdb_bb_all, "",   "Backtrace check on all built in functions", 0, KDB_REPEAT_NONE);
+
+       /* Split the opcode usage table by the first letter of each set of
+        * opcodes, for faster mapping of opcode to its operand usage.
+        */
+       for (i = 0; i < ARRAY_SIZE(bb_opcode_usage_all); ++i) {
+               c = bb_opcode_usage_all[i].opcode[0] - 'a';
+               if (c != cp) {
+                       cp = c;
+                       bb_opcode_usage[c].opcode = bb_opcode_usage_all + i;
+               }
+               ++bb_opcode_usage[c].size;
+       }
+
+       bb_common_interrupt = kallsyms_lookup_name("common_interrupt");
+       bb_error_entry = kallsyms_lookup_name("error_entry");
+       bb_ret_from_intr = kallsyms_lookup_name("ret_from_intr");
+       bb_thread_return = kallsyms_lookup_name("thread_return");
+       bb_sync_regs = kallsyms_lookup_name("sync_regs");
+       bb_save_v86_state = kallsyms_lookup_name("save_v86_state");
+       bb__sched_text_start = kallsyms_lookup_name("__sched_text_start");
+       bb__sched_text_end = kallsyms_lookup_name("__sched_text_end");
+       for (i = 0, r = bb_special_cases;
+            i < ARRAY_SIZE(bb_special_cases);
+            ++i, ++r) {
+               r->address = kallsyms_lookup_name(r->name);
+       }
+
+#ifdef CONFIG_4KSTACKS
+       kdba_hardirq_ctx = (struct thread_info **)kallsyms_lookup_name("hardirq_ctx");
+       kdba_softirq_ctx = (struct thread_info **)kallsyms_lookup_name("softirq_ctx");
+#endif /* CONFIG_4KSTACKS */
+
+       return 0;
+}
+
+static void __exit kdba_bt_x86_exit(void)
+{
+       kdb_unregister("bb1");
+       kdb_unregister("bb_all");
+}
+
+module_init(kdba_bt_x86_init)
+module_exit(kdba_bt_x86_exit)
diff --git a/arch/x86/kdb/kdba_id.c b/arch/x86/kdb/kdba_id.c
new file mode 100644 (file)
index 0000000..e4e52d2
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Kernel Debugger Architecture Dependent Instruction Disassembly
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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 */
+static 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",
+                       (int)(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%lx", 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_64") == 0) {
+                       dip->mach = bfd_mach_x86_64;
+               } else 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
+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;
+#ifdef CONFIG_X86_64
+       dip->mach                   = bfd_mach_x86_64;
+#endif
+#ifdef CONFIG_X86_32
+       dip->mach                   = bfd_mach_i386_i386;
+#endif
+       dip->endian                 = BFD_ENDIAN_LITTLE;
+
+       dip->display_endian         = BFD_ENDIAN_LITTLE;
+}
diff --git a/arch/x86/kdb/kdba_io.c b/arch/x86/kdb/kdba_io.c
new file mode 100644 (file)
index 0000000..087d468
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ * Kernel Debugger Architecture Dependent Console I/O handler
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2006 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <linux/delay.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 <pc_keyb.h>
+
+#ifdef CONFIG_VT_CONSOLE
+#define KDB_BLINK_LED 1
+#else
+#undef KDB_BLINK_LED
+#endif
+
+#ifdef CONFIG_KDB_USB
+
+/* support up to 8 USB keyboards (probably excessive, but...) */
+#define KDB_USB_NUM_KEYBOARDS   8
+struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS];
+
+extern int kdb_no_usb;
+
+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
+};
+
+/*
+ * kdb_usb_keyboard_attach()
+ * Attach a USB keyboard to kdb.
+ */
+int
+kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func)
+{
+        int     i;
+        int     rc = -1;
+
+        if (kdb_no_usb)
+                return 0;
+
+        /*
+         * Search through the array of KDB USB keyboards (kdb_usb_kbds)
+         * looking for a free index. If found, assign the keyboard to
+         * the array index.
+         */
+
+        for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) {
+                if (kdb_usb_kbds[i].urb) /* index is already assigned */
+                        continue;
+
+                /* found a free array index */
+                kdb_usb_kbds[i].urb = urb;
+                kdb_usb_kbds[i].buffer = buffer;
+                kdb_usb_kbds[i].poll_func = poll_func;
+
+                rc = 0; /* success */
+
+                break;
+        }
+
+        return rc;
+}
+EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach);
+
+/*
+ * kdb_usb_keyboard_detach()
+ * Detach a USB keyboard from kdb.
+ */
+int
+kdb_usb_keyboard_detach(struct urb *urb)
+{
+        int     i;
+        int     rc = -1;
+
+        if (kdb_no_usb)
+                return 0;
+
+        /*
+         * Search through the array of KDB USB keyboards (kdb_usb_kbds)
+         * looking for the index with the matching URB. If found,
+         * clear the array index.
+         */
+
+        for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) {
+                if (kdb_usb_kbds[i].urb != urb)
+                        continue;
+
+                /* found it, clear the index */
+                kdb_usb_kbds[i].urb = NULL;
+                kdb_usb_kbds[i].buffer = NULL;
+                kdb_usb_kbds[i].poll_func = NULL;
+                kdb_usb_kbds[i].caps_lock = 0;
+
+                rc = 0; /* success */
+
+                break;
+        }
+
+        return rc;
+}
+EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach);
+
+/*
+ * get_usb_char
+ * This function drives the USB attached keyboards.
+ * Fetch the USB scancode and decode it.
+ */
+static int
+get_usb_char(void)
+{
+        int     i;
+        int     ret;
+        unsigned char keycode, spec;
+        extern u_short plain_map[], shift_map[], ctrl_map[];
+
+        if (kdb_no_usb)
+                return -1;
+
+        /*
+         * Loop through all the USB keyboard(s) and return
+         * the first character obtained from them.
+         */
+
+        for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) {
+                /* skip uninitialized keyboard array entries */
+                if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer ||
+                    !kdb_usb_kbds[i].poll_func)
+                        continue;
+
+                /* Transfer char */
+                ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb);
+                if (ret == -EBUSY && kdb_usb_kbds[i].poll_ret != -EBUSY)
+                        kdb_printf("NOTICE: USB HD driver BUSY. "
+                            "USB keyboard has been disabled.\n");
+
+                kdb_usb_kbds[i].poll_ret = ret;
+
+                if (ret < 0) /* error or no characters, try the next kbd */
+                        continue;
+
+                spec = kdb_usb_kbds[i].buffer[0];
+                keycode = kdb_usb_kbds[i].buffer[2];
+                kdb_usb_kbds[i].buffer[0] = (char)0;
+                kdb_usb_kbds[i].buffer[2] = (char)0;
+
+                if(kdb_usb_kbds[i].buffer[3]) {
+                        kdb_usb_kbds[i].buffer[3] = (char)0;
+                        continue;
+                }
+
+                /* 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 */
+                                kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock);
+                                break;
+                        case 0x0E: /* Backspace */
+                                return 8;
+                        case 0x0F: /* TAB */
+                                return 9;
+                        case 0x77: /* Pause */
+                                break ;
+                        default:
+                                if(!kdb_usb_kbds[i].caps_lock) {
+                                        return plain_map[keycode];
+                                }
+                                else {
+                                        return shift_map[keycode];
+                                }
+                        }
+                }
+        }
+
+        /* no chars were returned from any of the USB keyboards */
+
+        return -1;
+}
+#endif /* CONFIG_KDB_USB */
+
+/*
+ * 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)
+{
+       int timeout;
+       for (timeout = 200 * 1000; timeout && (inb(KBD_STATUS_REG) & KBD_STAT_IBF); timeout--);
+       outb(byte, KBD_DATA_REG);
+       udelay(40);
+       for (timeout = 200 * 1000; timeout && (~inb(KBD_STATUS_REG) & KBD_STAT_OBF); timeout--);
+       inb(KBD_DATA_REG);
+       udelay(40);
+}
+
+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_8250_CONSOLE) || defined(CONFIG_SERIAL_CORE_CONSOLE)
+#define CONFIG_SERIAL_CONSOLE
+#endif
+
+#if defined(CONFIG_SERIAL_CONSOLE)
+
+struct kdb_serial kdb_serial;
+
+static 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((void __iomem *)(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;
+
+/*
+ * 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 (KDB_FLAG(NO_I8042) || KDB_FLAG(NO_VT_CONSOLE) ||
+           (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.
+ */
+static 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)
+{
+#ifdef CONFIG_VT_CONSOLE
+       int timeout;
+       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);
+       for (timeout = 200 * 1000; timeout &&
+                       (!(kbd_read_status() & KBD_STAT_OBF)); timeout--);
+       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);
+#endif /* CONFIG_VT_CONSOLE */
+}
+
+void kdba_local_arch_cleanup(void)
+{
+#ifdef CONFIG_VT_CONSOLE
+       int timeout;
+       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);
+       for (timeout = 200 * 1000; timeout &&
+                       (!(kbd_read_status() & KBD_STAT_OBF)); timeout--);
+       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);
+#endif /* CONFIG_VT_CONSOLE */
+}
diff --git a/arch/x86/kdb/kdba_support.c b/arch/x86/kdb/kdba_support.c
new file mode 100644 (file)
index 0000000..c744e41
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Kernel Debugger Architecture Independent Support Functions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2008 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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/hardirq.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kdebug.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/uaccess.h>
+#include <asm/hw_irq.h>
+#include <asm/desc.h>
+
+#ifdef CONFIG_KDB_KDUMP
+void kdba_kdump_prepare(struct pt_regs *regs)
+{
+       int i;
+       struct pt_regs r;
+       if (regs == NULL)
+               regs = &r;
+
+       machine_crash_shutdown_begin();
+
+       for (i = 1; i < NR_CPUS; ++i) {
+               if (!cpu_online(i))
+                       continue;
+
+               KDB_STATE_SET_CPU(KEXEC, i);
+       }
+
+       machine_crash_shutdown_end(regs);
+}
+
+extern void halt_current_cpu(struct pt_regs *);
+
+void kdba_kdump_shutdown_slave(struct pt_regs *regs)
+{
+#ifndef CONFIG_XEN
+       halt_current_cpu(regs);
+#endif /* CONFIG_XEN */
+}
+
+#endif
diff --git a/arch/x86/kdb/kdbasupport_32.c b/arch/x86/kdb/kdbasupport_32.c
new file mode 100644 (file)
index 0000000..f8d5d7b
--- /dev/null
@@ -0,0 +1,1072 @@
+/*
+ * Kernel Debugger Architecture Independent Support Functions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2006 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/string.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/ptrace.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/hardirq.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/uaccess.h>
+#include <asm/desc.h>
+
+static kdb_machreg_t
+kdba_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;
+}
+
+static 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;
+       }
+}
+
+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
+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)
+{
+       int cpu = smp_processor_id();
+
+       kdb_machreg_t dr7;
+
+       dr7 = kdba_getdr7();
+
+       kdba_putdr(bp->bp_hard[cpu]->bph_reg, bp->bp_addr);
+
+       dr7 |= DR7_GE;
+       if (cpu_has_de)
+               set_in_cr4(X86_CR4_DE);
+
+       switch (bp->bp_hard[cpu]->bph_reg){
+       case 0:
+               DR7_RW0SET(dr7,bp->bp_hard[cpu]->bph_mode);
+               DR7_LEN0SET(dr7,bp->bp_hard[cpu]->bph_length);
+               DR7_G0SET(dr7);
+               break;
+       case 1:
+               DR7_RW1SET(dr7,bp->bp_hard[cpu]->bph_mode);
+               DR7_LEN1SET(dr7,bp->bp_hard[cpu]->bph_length);
+               DR7_G1SET(dr7);
+               break;
+       case 2:
+               DR7_RW2SET(dr7,bp->bp_hard[cpu]->bph_mode);
+               DR7_LEN2SET(dr7,bp->bp_hard[cpu]->bph_length);
+               DR7_G2SET(dr7);
+               break;
+       case 3:
+               DR7_RW3SET(dr7,bp->bp_hard[cpu]->bph_mode);
+               DR7_LEN3SET(dr7,bp->bp_hard[cpu]->bph_length);
+               DR7_G3SET(dr7);
+               break;
+       default:
+               kdb_printf("kdb: Bad debug register!! %ld\n",
+                          bp->bp_hard[cpu]->bph_reg);
+               break;
+       }
+
+       kdba_putdr7(dr7);
+       return;
+}
+
+void
+kdba_removedbreg(kdb_bp_t *bp)
+{
+       int regnum;
+       kdb_machreg_t dr7;
+       int cpu = smp_processor_id();
+
+       if (!bp->bp_hard[cpu])
+               return;
+
+       regnum = bp->bp_hard[cpu]->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);
+}
+
+
+/*
+ * 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 sp are *not* on the stack.
+ */
+
+static struct kdbregs {
+       char   *reg_name;
+       size_t  reg_offset;
+} kdbreglist[] = {
+       { "ax",         offsetof(struct pt_regs, ax) },
+       { "bx",         offsetof(struct pt_regs, bx) },
+       { "cx",         offsetof(struct pt_regs, cx) },
+       { "dx",         offsetof(struct pt_regs, dx) },
+
+       { "si",         offsetof(struct pt_regs, si) },
+       { "di",         offsetof(struct pt_regs, di) },
+       { "sp",         offsetof(struct pt_regs, sp) },
+       { "ip",         offsetof(struct pt_regs, ip) },
+
+       { "bp",         offsetof(struct pt_regs, bp) },
+       { "ss",         offsetof(struct pt_regs, ss) },
+       { "cs",         offsetof(struct pt_regs, cs) },
+       { "flags",      offsetof(struct pt_regs, flags) },
+
+       { "ds",         offsetof(struct pt_regs, ds) },
+       { "es",         offsetof(struct pt_regs, es) },
+       { "origax",     offsetof(struct pt_regs, orig_ax) },
+
+};
+
+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) {
+               unsigned long flags;
+               local_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.sp0 - 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, use bt* or pid to select a different task\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->cs & 0xffff) == __KERNEL_CS) {
+                       /* sp 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->cs & 0xffff) == __KERNEL_CS) {
+                       /* No cpl switch, sp and ss are not on stack */
+                       if (strcmp(kdbreglist[i].reg_name, "sp") == 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.sp0 - 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, use bt* or pid to select a different task\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:
+ *     r               Memory Type Range Registers (extra defines register)
+ *
+ * MSR on i386/x86_64 are handled by rdmsr/wrmsr commands.
+ */
+
+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.sp0 - sizeof(struct pt_regs));
+       }
+
+       if (type == NULL) {
+               struct kdbregs *rlp;
+               kdb_machreg_t contents;
+
+               if (!regs) {
+                       kdb_printf("%s: pt_regs not available, use bt* or pid to select a different task\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] = kdba_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 'r':
+               break;
+       default:
+               return KDB_BADREG;
+       }
+
+       /* NOTREACHED */
+       return 0;
+}
+EXPORT_SYMBOL(kdba_dumpregs);
+
+kdb_machreg_t
+kdba_getpc(struct pt_regs *regs)
+{
+       return regs ? regs->ip : 0;
+}
+
+int
+kdba_setpc(struct pt_regs *regs, kdb_machreg_t newpc)
+{
+       if (KDB_NULL_REGS(regs))
+               return KDB_BADREG;
+       regs->ip = 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 SILENT or CPU_UP 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 ip and sp 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;
+       ret = kdb_save_running(regs, reason, reason2, error, db_result);
+       kdb_unsave_running(regs);
+       return ret;
+}
+
+void
+kdba_disableint(kdb_intstate_t *state)
+{
+       unsigned long *fp = (unsigned long *)state;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       *fp = flags;
+}
+
+void
+kdba_restoreint(kdb_intstate_t *state)
+{
+       unsigned long flags = *(int *)state;
+       local_irq_restore(flags);
+}
+
+void
+kdba_setsinglestep(struct pt_regs *regs)
+{
+       if (KDB_NULL_REGS(regs))
+               return;
+       if (regs->flags & EF_IE)
+               KDB_STATE_SET(A_IF);
+       else
+               KDB_STATE_CLEAR(A_IF);
+       regs->flags = (regs->flags | EF_TF) & ~EF_IE;
+}
+
+void
+kdba_clearsinglestep(struct pt_regs *regs)
+{
+       if (KDB_NULL_REGS(regs))
+               return;
+       if (KDB_STATE(A_IF))
+               regs->flags |= EF_IE;
+       else
+               regs->flags &= ~EF_IE;
+}
+
+int asmlinkage
+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 */
+       return 0;
+}
+
+void asmlinkage
+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 */
+}
+
+/*
+ * kdba_pt_regs
+ *
+ *     Format a struct pt_regs
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     If no address is supplied, it uses the last irq pt_regs.
+ */
+
+static int
+kdba_pt_regs(int argc, const char **argv)
+{
+       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) get_irq_regs();
+       } else if (argc == 1) {
+               nextarg = 1;
+               diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
+               if (diag)
+                       return diag;
+       } else {
+               return KDB_ARGCOUNT;
+       }
+
+       p = (struct pt_regs *) addr;
+       kdb_printf("struct pt_regs 0x%p-0x%p\n", p, (unsigned char *)p + sizeof(*p) - 1);
+       kdb_print_nameval("bx", p->bx);
+       kdb_print_nameval("cx", p->cx);
+       kdb_print_nameval("dx", p->dx);
+       kdb_print_nameval("si", p->si);
+       kdb_print_nameval("di", p->di);
+       kdb_print_nameval("bp", p->bp);
+       kdb_print_nameval("ax", p->ax);
+       kdb_printf(fmt, "ds", p->ds);
+       kdb_printf(fmt, "es", p->es);
+       kdb_print_nameval("orig_ax", p->orig_ax);
+       kdb_print_nameval("ip", p->ip);
+       kdb_printf(fmt, "cs", p->cs);
+       kdb_printf(fmt, "flags", p->flags);
+       kdb_printf(fmt, "sp", p->sp);
+       kdb_printf(fmt, "ss", p->ss);
+       return 0;
+}
+
+/*
+ * kdba_stackdepth
+ *
+ *     Print processes that are using more than a specific percentage of their
+ *     stack.
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     If no percentage is supplied, it uses 60.
+ */
+
+static void
+kdba_stackdepth1(struct task_struct *p, unsigned long sp)
+{
+       struct thread_info *tinfo;
+       int used;
+       const char *type;
+       kdb_ps1(p);
+       do {
+               tinfo = (struct thread_info *)(sp & -THREAD_SIZE);
+               used = sizeof(*tinfo) + THREAD_SIZE - (sp & (THREAD_SIZE-1));
+               type = NULL;
+               if (kdb_task_has_cpu(p)) {
+                       struct kdb_activation_record ar;
+                       memset(&ar, 0, sizeof(ar));
+                       kdba_get_stack_info_alternate(sp, -1, &ar);
+                       type = ar.stack.id;
+               }
+               if (!type)
+                       type = "process";
+               kdb_printf("  %s stack %p sp %lx used %d\n", type, tinfo, sp, used);
+               sp = tinfo->previous_esp;
+       } while (sp);
+}
+
+static int
+kdba_stackdepth(int argc, const char **argv)
+{
+       int diag, cpu, threshold, used, over;
+       unsigned long percentage;
+       unsigned long esp;
+       long offset = 0;
+       int nextarg;
+       struct task_struct *p, *g;
+       struct kdb_running_process *krp;
+       struct thread_info *tinfo;
+
+       if (argc == 0) {
+               percentage = 60;
+       } else if (argc == 1) {
+               nextarg = 1;
+               diag = kdbgetaddrarg(argc, argv, &nextarg, &percentage, &offset, NULL);
+               if (diag)
+                       return diag;
+       } else {
+               return KDB_ARGCOUNT;
+       }
+       percentage = max_t(int, percentage, 1);
+       percentage = min_t(int, percentage, 100);
+       threshold = ((2 * THREAD_SIZE * percentage) / 100 + 1) >> 1;
+       kdb_printf("stackdepth: processes using more than %ld%% (%d bytes) of stack\n",
+               percentage, threshold);
+
+       /* Run the active tasks first, they can have multiple stacks */
+       for (cpu = 0, krp = kdb_running_process; cpu < NR_CPUS; ++cpu, ++krp) {
+               if (!cpu_online(cpu))
+                       continue;
+               p = krp->p;
+               esp = krp->arch.sp;
+               over = 0;
+               do {
+                       tinfo = (struct thread_info *)(esp & -THREAD_SIZE);
+                       used = sizeof(*tinfo) + THREAD_SIZE - (esp & (THREAD_SIZE-1));
+                       if (used >= threshold)
+                               over = 1;
+                       esp = tinfo->previous_esp;
+               } while (esp);
+               if (over)
+                       kdba_stackdepth1(p, krp->arch.sp);
+       }
+       /* Now the tasks that are not on cpus */
+       kdb_do_each_thread(g, p) {
+               if (kdb_task_has_cpu(p))
+                       continue;
+               esp = p->thread.sp;
+               used = sizeof(*tinfo) + THREAD_SIZE - (esp & (THREAD_SIZE-1));
+               over = used >= threshold;
+               if (over)
+                       kdba_stackdepth1(p, esp);
+       } kdb_while_each_thread(g, p);
+
+       return 0;
+}
+
+asmlinkage int kdb_call(void);
+
+/* Executed once on each cpu at startup. */
+void
+kdba_cpu_up(void)
+{
+}
+
+static int __init
+kdba_arch_init(void)
+{
+#ifdef CONFIG_SMP
+       set_intr_gate(KDB_VECTOR, kdb_interrupt);
+#endif
+       set_intr_gate(KDBENTER_VECTOR, kdb_call);
+       return 0;
+}
+
+arch_initcall(kdba_arch_init);
+
+/*
+ * kdba_init
+ *
+ *     Architecture specific initialization.
+ *
+ * Parameters:
+ *     None.
+ * Returns:
+ *     None.
+ * Locking:
+ *     None.
+ * Remarks:
+ *     None.
+ */
+
+void __init
+kdba_init(void)
+{
+       kdba_arch_init();       /* Need to register KDBENTER_VECTOR early */
+       kdb_register("pt_regs", kdba_pt_regs, "address", "Format struct pt_regs", 0);
+       kdb_register("stackdepth", kdba_stackdepth, "[percentage]", "Print processes using >= stack percentage", 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 SILENT or CPU_UP 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;
+}
+
+void
+kdba_set_current_task(const struct task_struct *p)
+{
+       kdb_current_task = p;
+       if (kdb_task_has_cpu(p)) {
+               struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+               kdb_current_regs = krp->regs;
+               return;
+       }
+       kdb_current_regs = NULL;
+}
+
+/*
+ * 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,
+ */
+
+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_inatomic((void __user *)to_xxx, from, size);
+       set_fs(oldfs);
+       return r;
+}
+
+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_inatomic((void __user *)to, (void *)from_xxx, 1);
+               break;
+       case 2:
+               r = __copy_to_user_inatomic((void __user *)to, (void *)from_xxx, 2);
+               break;
+       case 4:
+               r = __copy_to_user_inatomic((void __user *)to, (void *)from_xxx, 4);
+               break;
+       case 8:
+               r = __copy_to_user_inatomic((void __user *)to, (void *)from_xxx, 8);
+               break;
+       default:
+               r = __copy_to_user_inatomic((void __user *)to, (void *)from_xxx, size);
+               break;
+       }
+       set_fs(oldfs);
+       return r;
+}
+
+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));
+}
+
+#ifdef CONFIG_SMP
+
+#include <mach_ipi.h>
+
+/* When first entering KDB, try a normal IPI.  That reduces backtrace problems
+ * on the other cpus.
+ */
+void
+smp_kdb_stop(void)
+{
+       if (!KDB_FLAG(NOIPI))
+               send_IPI_allbutself(KDB_VECTOR);
+}
+
+/* The normal KDB IPI handler */
+void
+smp_kdb_interrupt(struct pt_regs *regs)
+{
+       struct pt_regs *old_regs = set_irq_regs(regs);
+       ack_APIC_irq();
+       irq_enter();
+       kdb_ipi(regs, NULL);
+       irq_exit();
+       set_irq_regs(old_regs);
+}
+
+/* Invoked once from kdb_wait_for_cpus when waiting for cpus.  For those cpus
+ * that have not responded to the normal KDB interrupt yet, hit them with an
+ * NMI event.
+ */
+void
+kdba_wait_for_cpus(void)
+{
+       int c;
+       if (KDB_FLAG(CATASTROPHIC))
+               return;
+       kdb_printf("  Sending NMI to non-responding cpu(s): ");
+       for_each_online_cpu(c) {
+               if (kdb_running_process[c].seqno < kdb_seqno - 1) {
+                       kdb_printf(" %d", c);
+                       send_IPI_mask(cpumask_of_cpu(c), NMI_VECTOR);
+               }
+       }
+       kdb_printf(".\n");
+}
+
+#endif /* CONFIG_SMP */
diff --git a/arch/x86/kdb/kdbasupport_64.c b/arch/x86/kdb/kdbasupport_64.c
new file mode 100644 (file)
index 0000000..9f5cb6d
--- /dev/null
@@ -0,0 +1,1022 @@
+/*
+ * Kernel Debugger Architecture Independent Support Functions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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/hardirq.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kdebug.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/uaccess.h>
+#include <asm/hw_irq.h>
+#include <asm/desc.h>
+
+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)
+{
+       int cpu = smp_processor_id();
+
+       kdb_machreg_t   dr7;
+
+       dr7 = kdba_getdr7();
+
+       kdba_putdr(bp->bp_hard[cpu]->bph_reg, bp->bp_addr);
+
+       dr7 |= DR7_GE;
+       if (cpu_has_de)
+               set_in_cr4(X86_CR4_DE);
+
+       switch (bp->bp_hard[cpu]->bph_reg){
+       case 0:
+               DR7_RW0SET(dr7,bp->bp_hard[cpu]->bph_mode);
+               DR7_LEN0SET(dr7,bp->bp_hard[cpu]->bph_length);
+               DR7_G0SET(dr7);
+               break;
+       case 1:
+               DR7_RW1SET(dr7,bp->bp_hard[cpu]->bph_mode);
+               DR7_LEN1SET(dr7,bp->bp_hard[cpu]->bph_length);
+               DR7_G1SET(dr7);
+               break;
+       case 2:
+               DR7_RW2SET(dr7,bp->bp_hard[cpu]->bph_mode);
+               DR7_LEN2SET(dr7,bp->bp_hard[cpu]->bph_length);
+               DR7_G2SET(dr7);
+               break;
+       case 3:
+               DR7_RW3SET(dr7,bp->bp_hard[cpu]->bph_mode);
+               DR7_LEN3SET(dr7,bp->bp_hard[cpu]->bph_length);
+               DR7_G3SET(dr7);
+               break;
+       default:
+               kdb_printf("kdb: Bad debug register!! %ld\n",
+                          bp->bp_hard[cpu]->bph_reg);
+               break;
+       }
+
+       kdba_putdr7(dr7);
+       return;
+}
+
+void
+kdba_removedbreg(kdb_bp_t *bp)
+{
+       int             regnum;
+       kdb_machreg_t   dr7;
+       int cpu = smp_processor_id();
+
+       if (!bp->bp_hard[cpu])
+               return;
+
+       regnum = bp->bp_hard[cpu]->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__ ("movq %%db0,%0\n\t":"=r"(contents));
+               break;
+       case 1:
+               __asm__ ("movq %%db1,%0\n\t":"=r"(contents));
+               break;
+       case 2:
+               __asm__ ("movq %%db2,%0\n\t":"=r"(contents));
+               break;
+       case 3:
+               __asm__ ("movq %%db3,%0\n\t":"=r"(contents));
+               break;
+       case 4:
+       case 5:
+               break;
+       case 6:
+               __asm__ ("movq %%db6,%0\n\t":"=r"(contents));
+               break;
+       case 7:
+               __asm__ ("movq %%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__ ("movq %%cr0,%0\n\t":"=r"(contents));
+               break;
+       case 1:
+               break;
+       case 2:
+               __asm__ ("movq %%cr2,%0\n\t":"=r"(contents));
+               break;
+       case 3:
+               __asm__ ("movq %%cr3,%0\n\t":"=r"(contents));
+               break;
+       case 4:
+               __asm__ ("movq %%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__ ("movq %0,%%db0\n\t"::"r"(contents));
+               break;
+       case 1:
+               __asm__ ("movq %0,%%db1\n\t"::"r"(contents));
+               break;
+       case 2:
+               __asm__ ("movq %0,%%db2\n\t"::"r"(contents));
+               break;
+       case 3:
+               __asm__ ("movq %0,%%db3\n\t"::"r"(contents));
+               break;
+       case 4:
+       case 5:
+               break;
+       case 6:
+               __asm__ ("movq %0,%%db6\n\t"::"r"(contents));
+               break;
+       case 7:
+               __asm__ ("movq %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
+ *        krsp          - Prints kernel stack pointer at time of fault
+ *        crsp          - 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 sp are *not* on the stack.
+ */
+
+static struct kdbregs {
+       char   *reg_name;
+       size_t  reg_offset;
+} kdbreglist[] = {
+       { "r15",        offsetof(struct pt_regs, r15) },
+       { "r14",        offsetof(struct pt_regs, r14) },
+       { "r13",        offsetof(struct pt_regs, r13) },
+       { "r12",        offsetof(struct pt_regs, r12) },
+       { "bp",         offsetof(struct pt_regs, bp) },
+       { "bx",         offsetof(struct pt_regs, bx) },
+       { "r11",        offsetof(struct pt_regs, r11) },
+       { "r10",        offsetof(struct pt_regs, r10) },
+       { "r9",         offsetof(struct pt_regs, r9) },
+       { "r8",         offsetof(struct pt_regs, r8) },
+       { "ax",         offsetof(struct pt_regs, ax) },
+       { "cx",         offsetof(struct pt_regs, cx) },
+       { "dx",         offsetof(struct pt_regs, dx) },
+       { "si",         offsetof(struct pt_regs, si) },
+       { "di",         offsetof(struct pt_regs, di) },
+       { "orig_ax",    offsetof(struct pt_regs, orig_ax) },
+       { "ip",         offsetof(struct pt_regs, ip) },
+       { "cs",         offsetof(struct pt_regs, cs) },
+       { "flags",      offsetof(struct pt_regs, flags) },
+       { "sp",         offsetof(struct pt_regs, sp) },
+       { "ss",         offsetof(struct pt_regs, ss) },
+};
+
+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, "&regs") == 0) {
+               *contents = (unsigned long)regs;
+               return 0;
+       }
+
+       if (strcmp(regname, "krsp") == 0) {
+               *contents = (unsigned long)regs + sizeof(struct pt_regs);
+               if ((regs->cs & 0xffff) == __KERNEL_CS) {
+                       /* sp and ss are not on stack */
+                       *contents -= 2*4;
+               }
+               return 0;
+       }
+
+       if (strcmp(regname, "crsp") == 0) {
+               asm volatile("movq %%rsp,%0":"=m" (*contents));
+               return 0;
+       }
+
+       if (strcmp(regname, "ceflags") == 0) {
+               unsigned long flags;
+               local_save_flags(flags);
+               *contents = flags;
+               return 0;
+       }
+
+       if (regname[0] == '%') {
+               /* User registers:  %%r[a-c]x, etc */
+               regname++;
+               regs = (struct pt_regs *)
+                       (current->thread.sp0 - sizeof(struct pt_regs));
+       }
+
+       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->cs & 0xffff) == __KERNEL_CS) {
+                       /* No cpl switch, sp is not on stack */
+                       if (strcmp(kdbreglist[i].reg_name, "sp") == 0) {
+                               *contents = (kdb_machreg_t)regs +
+                                       sizeof(struct pt_regs) - 2*8;
+                               return(0);
+                       }
+#if 0  /* FIXME */
+                       if (strcmp(kdbreglist[i].reg_name, "ss") == 0) {
+                               kdb_machreg_t r;
+
+                               r = (kdb_machreg_t)regs +
+                                       sizeof(struct pt_regs) - 2*8;
+                               *contents = (kdb_machreg_t)SS(r);       /* XXX */
+                               return(0);
+                       }
+#endif
+               }
+               *contents = *(unsigned long *)((unsigned long)regs +
+                               kdbreglist[i].reg_offset);
+               return(0);
+       }
+
+       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;
+       }
+       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 *)
+                       (current->thread.sp0 - sizeof(struct pt_regs));
+       }
+
+       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;
+       }
+
+       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;
+       }
+
+       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
+ * Following not yet implemented:
+ *     r               Memory Type Range Registers (extra defines register)
+ *
+ * MSR on i386/x86_64 are handled by rdmsr/wrmsr commands.
+ */
+
+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 *)
+                       (current->thread.sp0 - sizeof(struct pt_regs));
+       }
+
+       if (type == NULL) {
+               struct kdbregs *rlp;
+               kdb_machreg_t contents;
+
+               for (i=0, rlp=kdbreglist; i<nkdbreglist; i++,rlp++) {
+                       kdb_printf("%8s = ", rlp->reg_name);
+                       kdba_getregcontents(rlp->reg_name, regs, &contents);
+                       kdb_printf("0x%016lx ", contents);
+                       if ((++count % 2) == 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 'r':
+               break;
+       default:
+               return KDB_BADREG;
+       }
+
+       /* NOTREACHED */
+       return 0;
+}
+EXPORT_SYMBOL(kdba_dumpregs);
+
+kdb_machreg_t
+kdba_getpc(struct pt_regs *regs)
+{
+       return regs->ip;
+}
+
+int
+kdba_setpc(struct pt_regs *regs, kdb_machreg_t newpc)
+{
+       if (KDB_NULL_REGS(regs))
+               return KDB_BADREG;
+       regs->ip = 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.
+ *     ef              The exception frame at time of fault/breakpoint.  If reason
+ *                     is SILENT or CPU_UP 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 ip and sp 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;
+
+       if (regs)
+               kdba_getregcontents("sp", regs, &(current->thread.sp));
+       ret = kdb_save_running(regs, reason, reason2, error, db_result);
+       kdb_unsave_running(regs);
+       return ret;
+}
+
+void
+kdba_disableint(kdb_intstate_t *state)
+{
+       unsigned long *fp = (unsigned long *)state;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       *fp = flags;
+}
+
+void
+kdba_restoreint(kdb_intstate_t *state)
+{
+       unsigned long flags = *(unsigned long *)state;
+       local_irq_restore(flags);
+}
+
+void
+kdba_setsinglestep(struct pt_regs *regs)
+{
+       if (KDB_NULL_REGS(regs))
+               return;
+       if (regs->flags & X86_EFLAGS_IF)
+               KDB_STATE_SET(A_IF);
+       else
+               KDB_STATE_CLEAR(A_IF);
+       regs->flags = (regs->flags | X86_EFLAGS_TF) & ~X86_EFLAGS_IF;
+}
+
+void
+kdba_clearsinglestep(struct pt_regs *regs)
+{
+       if (KDB_NULL_REGS(regs))
+               return;
+       if (KDB_STATE(A_IF))
+               regs->flags |= X86_EFLAGS_IF;
+       else
+               regs->flags &= ~X86_EFLAGS_IF;
+}
+
+int asmlinkage
+kdba_setjmp(kdb_jmp_buf *jb)
+{
+#ifdef CONFIG_FRAME_POINTER
+       __asm__ __volatile__
+               ("movq %%rbx, (0*8)(%%rdi);"
+               "movq %%rcx, (1*8)(%%rdi);"
+               "movq %%r12, (2*8)(%%rdi);"
+               "movq %%r13, (3*8)(%%rdi);"
+               "movq %%r14, (4*8)(%%rdi);"
+               "movq %%r15, (5*8)(%%rdi);"
+               "leaq 16(%%rsp), %%rdx;"
+               "movq %%rdx, (6*8)(%%rdi);"
+               "movq %%rax, (7*8)(%%rdi)"
+               :
+               : "a" (__builtin_return_address(0)),
+                 "c" (__builtin_frame_address(1))
+               );
+#else   /* !CONFIG_FRAME_POINTER */
+       __asm__ __volatile__
+               ("movq %%rbx, (0*8)(%%rdi);"
+               "movq %%rbp, (1*8)(%%rdi);"
+               "movq %%r12, (2*8)(%%rdi);"
+               "movq %%r13, (3*8)(%%rdi);"
+               "movq %%r14, (4*8)(%%rdi);"
+               "movq %%r15, (5*8)(%%rdi);"
+               "leaq 8(%%rsp), %%rdx;"
+               "movq %%rdx, (6*8)(%%rdi);"
+               "movq %%rax, (7*8)(%%rdi)"
+               :
+               : "a" (__builtin_return_address(0))
+               );
+#endif   /* CONFIG_FRAME_POINTER */
+       return 0;
+}
+
+void asmlinkage
+kdba_longjmp(kdb_jmp_buf *jb, int reason)
+{
+       __asm__("movq (0*8)(%rdi),%rbx;"
+               "movq (1*8)(%rdi),%rbp;"
+               "movq (2*8)(%rdi),%r12;"
+               "movq (3*8)(%rdi),%r13;"
+               "movq (4*8)(%rdi),%r14;"
+               "movq (5*8)(%rdi),%r15;"
+               "movq (7*8)(%rdi),%rdx;"
+               "movq (6*8)(%rdi),%rsp;"
+               "mov %rsi, %rax;"
+               "jmpq *%rdx");
+}
+
+/*
+ * kdba_pt_regs
+ *
+ *     Format a struct pt_regs
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     If no address is supplied, it uses the current irq pt_regs.
+ */
+
+static int
+kdba_pt_regs(int argc, const char **argv)
+{
+       int diag;
+       kdb_machreg_t addr;
+       long offset = 0;
+       int nextarg;
+       struct pt_regs *p;
+       static const char *fmt = "  %-11.11s 0x%lx\n";
+       static int first_time = 1;
+
+       if (argc == 0) {
+               addr = (kdb_machreg_t) get_irq_regs();
+       } else if (argc == 1) {
+               nextarg = 1;
+               diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
+               if (diag)
+                       return diag;
+       } else {
+               return KDB_ARGCOUNT;
+       }
+
+       p = (struct pt_regs *) addr;
+       if (first_time) {
+               first_time = 0;
+               kdb_printf("\n+++ Warning: x86_64 pt_regs are not always "
+                          "completely defined, r15-bx may be invalid\n\n");
+       }
+       kdb_printf("struct pt_regs 0x%p-0x%p\n", p, (unsigned char *)p + sizeof(*p) - 1);
+       kdb_print_nameval("r15", p->r15);
+       kdb_print_nameval("r14", p->r14);
+       kdb_print_nameval("r13", p->r13);
+       kdb_print_nameval("r12", p->r12);
+       kdb_print_nameval("bp", p->bp);
+       kdb_print_nameval("bx", p->bx);
+       kdb_print_nameval("r11", p->r11);
+       kdb_print_nameval("r10", p->r10);
+       kdb_print_nameval("r9", p->r9);
+       kdb_print_nameval("r8", p->r8);
+       kdb_print_nameval("ax", p->ax);
+       kdb_print_nameval("cx", p->cx);
+       kdb_print_nameval("dx", p->dx);
+       kdb_print_nameval("si", p->si);
+       kdb_print_nameval("di", p->di);
+       kdb_print_nameval("orig_ax", p->orig_ax);
+       kdb_print_nameval("ip", p->ip);
+       kdb_printf(fmt, "cs", p->cs);
+       kdb_printf(fmt, "flags", p->flags);
+       kdb_printf(fmt, "sp", p->sp);
+       kdb_printf(fmt, "ss", p->ss);
+       return 0;
+}
+
+/*
+ * kdba_cpu_pda
+ *
+ *     Format a struct cpu_pda
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     If no cpu is supplied, it prints the current cpu.  If the cpu is '*'
+ *     then it prints all cpus.
+ */
+
+static int
+kdba_cpu_pda(int argc, const char **argv)
+{
+       int diag, nextarg, all_cpus = 0;
+       long offset = 0;
+       unsigned long cpu;
+       struct x8664_pda *c;
+       static const char *fmtl = "  %-17.17s 0x%lx\n";
+       static const char *fmtd = "  %-17.17s %d\n";
+       static const char *fmtp = "  %-17.17s 0x%p\n";
+
+       if (argc == 0) {
+               cpu = smp_processor_id();
+       } else if (argc == 1) {
+               if (strcmp(argv[1], "*") == 0) {
+                       all_cpus = 1;
+                       cpu = 0;
+               } else {
+                       nextarg = 1;
+                       diag = kdbgetaddrarg(argc, argv, &nextarg, &cpu, &offset, NULL);
+                       if (diag)
+                               return diag;
+               }
+       } else {
+               return KDB_ARGCOUNT;
+       }
+
+       for (; cpu < NR_CPUS; ++cpu) {
+               if (cpu_online(cpu)) {
+                       c = cpu_pda(cpu);
+                       kdb_printf("struct cpu_pda 0x%p-0x%p\n", c, (unsigned char *)c + sizeof(*c) - 1);
+                       kdb_printf(fmtp, "pcurrent", c->pcurrent);
+                       kdb_printf(fmtl, "data_offset", c->data_offset);
+                       kdb_printf(fmtl, "kernelstack", c->kernelstack);
+                       kdb_printf(fmtl, "oldrsp", c->oldrsp);
+                       kdb_printf(fmtd, "irqcount", c->irqcount);
+                       kdb_printf(fmtd, "cpunumber", c->cpunumber);
+                       kdb_printf(fmtp, "irqstackptr", c->irqstackptr);
+                       kdb_printf(fmtp, "nodenumber", cpu_to_node(cpu));
+                       kdb_printf(fmtd, "__softirq_pending", c->__softirq_pending);
+                       kdb_printf(fmtd, "__nmi_count", c->__nmi_count);
+                       kdb_printf(fmtd, "mmu_state", c->mmu_state);
+                       kdb_printf(fmtp, "active_mm", c->active_mm);
+                       kdb_printf(fmtd, "apic_timer_irqs", c->apic_timer_irqs);
+               }
+               if (!all_cpus)
+                       break;
+       }
+       return 0;
+}
+
+/*
+ * kdba_entry
+ *
+ *     This is the interface routine between
+ *     the notifier die_chain and kdb
+ */
+static int kdba_entry( struct notifier_block *b, unsigned long val, void *v)
+{
+       struct die_args *args = v;
+       int err, trap, ret = 0;
+       struct pt_regs *regs;
+
+       regs = args->regs;
+       err  = args->err;
+       trap  = args->trapnr;
+       switch (val){
+#ifdef CONFIG_SMP
+               case DIE_NMI_IPI:
+                       ret = kdb_ipi(regs, NULL);
+                       break;
+#endif /* CONFIG_SMP */
+               case DIE_OOPS:
+                       ret = kdb(KDB_REASON_OOPS, err, regs);
+                       break;
+               case DIE_CALL:
+                       ret = kdb(KDB_REASON_ENTER, err, regs);
+                       break;
+               case DIE_DEBUG:
+                       ret = kdb(KDB_REASON_DEBUG, err, regs);
+                       break;
+               case DIE_NMIWATCHDOG:
+                       ret = kdb(KDB_REASON_NMI, err, regs);
+                       break;
+               case DIE_INT3:
+                        ret = kdb(KDB_REASON_BREAK, err, regs);
+                       // falls thru
+               default:
+                       break;
+       }
+       return (ret ? NOTIFY_STOP : NOTIFY_DONE);
+}
+
+/*
+ * notifier block for kdb entry
+ */
+static struct notifier_block kdba_notifier = {
+       .notifier_call = kdba_entry
+};
+
+asmlinkage int kdb_call(void);
+
+/* Executed once on each cpu at startup. */
+void
+kdba_cpu_up(void)
+{
+}
+
+static int __init
+kdba_arch_init(void)
+{
+#ifdef CONFIG_SMP
+       set_intr_gate(KDB_VECTOR, kdb_interrupt);
+#endif
+       set_intr_gate(KDBENTER_VECTOR, kdb_call);
+       return 0;
+}
+
+arch_initcall(kdba_arch_init);
+
+/*
+ * kdba_init
+ *
+ *     Architecture specific initialization.
+ *
+ * Parameters:
+ *     None.
+ * Returns:
+ *     None.
+ * Locking:
+ *     None.
+ * Remarks:
+ *     None.
+ */
+
+void __init
+kdba_init(void)
+{
+       kdba_arch_init();       /* Need to register KDBENTER_VECTOR early */
+       kdb_register("pt_regs", kdba_pt_regs, "address", "Format struct pt_regs", 0);
+       kdb_register("cpu_pda", kdba_cpu_pda, "<cpu>", "Format struct cpu_pda", 0);
+       register_die_notifier(&kdba_notifier);
+       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
+ *     ef              The exception frame at time of fault/breakpoint.  If reason
+ *                     is SILENT or CPU_UP 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 *ef)
+{
+       return;
+}
+
+void
+kdba_set_current_task(const struct task_struct *p)
+{
+       kdb_current_task = p;
+       if (kdb_task_has_cpu(p)) {
+               struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+               kdb_current_regs = krp->regs;
+               return;
+       }
+       kdb_current_regs = NULL;
+}
+
+#ifdef CONFIG_SMP
+
+#include <mach_ipi.h>
+
+/* When first entering KDB, try a normal IPI.  That reduces backtrace problems
+ * on the other cpus.
+ */
+void
+smp_kdb_stop(void)
+{
+       if (!KDB_FLAG(NOIPI))
+               send_IPI_allbutself(KDB_VECTOR);
+}
+
+/* The normal KDB IPI handler */
+extern asmlinkage void smp_kdb_interrupt(struct pt_regs *regs);        /* for sparse */
+asmlinkage void
+smp_kdb_interrupt(struct pt_regs *regs)
+{
+       struct pt_regs *old_regs = set_irq_regs(regs);
+       ack_APIC_irq();
+       irq_enter();
+       kdb_ipi(regs, NULL);
+       irq_exit();
+       set_irq_regs(old_regs);
+}
+
+/* Invoked once from kdb_wait_for_cpus when waiting for cpus.  For those cpus
+ * that have not responded to the normal KDB interrupt yet, hit them with an
+ * NMI event.
+ */
+void
+kdba_wait_for_cpus(void)
+{
+       int c;
+       if (KDB_FLAG(CATASTROPHIC))
+               return;
+       kdb_printf("  Sending NMI to non-responding cpus: ");
+       for_each_online_cpu(c) {
+               if (kdb_running_process[c].seqno < kdb_seqno - 1) {
+                       kdb_printf(" %d", c);
+                       send_IPI_mask(cpumask_of_cpu(c), NMI_VECTOR);
+               }
+       }
+       kdb_printf(".\n");
+}
+
+#endif /* CONFIG_SMP */
diff --git a/arch/x86/kdb/pc_keyb.h b/arch/x86/kdb/pc_keyb.h
new file mode 100644 (file)
index 0000000..362bb71
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *     include/linux/pc_keyb.h
+ *
+ *     PC Keyboard And Keyboard Controller
+ *
+ *     (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+/*
+ *     Configuration Switches
+ */
+
+#undef KBD_REPORT_ERR                  /* Report keyboard errors */
+#define        KBD_REPORT_UNKN                 /* Report unknown scan codes */
+#define        KBD_REPORT_TIMEOUTS             /* Report keyboard timeouts */
+#undef KBD_IS_FOCUS_9000               /* We have the brain-damaged FOCUS-9000 keyboard */
+#undef INITIALIZE_MOUSE                /* Define if your PS/2 mouse needs initialization. */
+
+
+
+#define KBD_INIT_TIMEOUT 1000          /* Timeout in ms for initializing the keyboard */
+#define KBC_TIMEOUT 250                        /* Timeout in ms for sending to keyboard controller */
+#define KBD_TIMEOUT 1000               /* Timeout in ms for keyboard command acknowledge */
+
+/*
+ *     Internal variables of the driver
+ */
+
+extern unsigned char pckbd_read_mask;
+extern unsigned char aux_device_present;
+
+/*
+ *     Keyboard Controller Registers on normal PCs.
+ */
+
+#define KBD_STATUS_REG         0x64    /* Status register (R) */
+#define KBD_CNTL_REG           0x64    /* Controller command register (W) */
+#define KBD_DATA_REG           0x60    /* Keyboard data register (R/W) */
+
+/*
+ *     Keyboard Controller Commands
+ */
+
+#define KBD_CCMD_READ_MODE     0x20    /* Read mode bits */
+#define KBD_CCMD_WRITE_MODE    0x60    /* Write mode bits */
+#define KBD_CCMD_GET_VERSION   0xA1    /* Get controller version */
+#define KBD_CCMD_MOUSE_DISABLE 0xA7    /* Disable mouse interface */
+#define KBD_CCMD_MOUSE_ENABLE  0xA8    /* Enable mouse interface */
+#define KBD_CCMD_TEST_MOUSE    0xA9    /* Mouse interface test */
+#define KBD_CCMD_SELF_TEST     0xAA    /* Controller self test */
+#define KBD_CCMD_KBD_TEST      0xAB    /* Keyboard interface test */
+#define KBD_CCMD_KBD_DISABLE   0xAD    /* Keyboard interface disable */
+#define KBD_CCMD_KBD_ENABLE    0xAE    /* Keyboard interface enable */
+#define KBD_CCMD_WRITE_AUX_OBUF        0xD3    /* Write to output buffer as if
+                                          initiated by the auxiliary device */
+#define KBD_CCMD_WRITE_MOUSE   0xD4    /* Write the following byte to the mouse */
+
+/*
+ *     Keyboard Commands
+ */
+
+#define KBD_CMD_SET_LEDS       0xED    /* Set keyboard leds */
+#define KBD_CMD_SET_RATE       0xF3    /* Set typematic rate */
+#define KBD_CMD_ENABLE         0xF4    /* Enable scanning */
+#define KBD_CMD_DISABLE                0xF5    /* Disable scanning */
+#define KBD_CMD_RESET          0xFF    /* Reset */
+
+/*
+ *     Keyboard Replies
+ */
+
+#define KBD_REPLY_POR          0xAA    /* Power on reset */
+#define KBD_REPLY_ACK          0xFA    /* Command ACK */
+#define KBD_REPLY_RESEND       0xFE    /* Command NACK, send the cmd again */
+
+/*
+ *     Status Register Bits
+ */
+
+#define KBD_STAT_OBF           0x01    /* Keyboard output buffer full */
+#define KBD_STAT_IBF           0x02    /* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST      0x04    /* Self test successful */
+#define KBD_STAT_CMD           0x08    /* Last write was a command write (0=data) */
+#define KBD_STAT_UNLOCKED      0x10    /* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF     0x20    /* Mouse output buffer full */
+#define KBD_STAT_GTO           0x40    /* General receive/xmit timeout */
+#define KBD_STAT_PERR          0x80    /* Parity error */
+
+#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
+
+/*
+ *     Controller Mode Register Bits
+ */
+
+#define KBD_MODE_KBD_INT       0x01    /* Keyboard data generate IRQ1 */
+#define KBD_MODE_MOUSE_INT     0x02    /* Mouse data generate IRQ12 */
+#define KBD_MODE_SYS           0x04    /* The system flag (?) */
+#define KBD_MODE_NO_KEYLOCK    0x08    /* The keylock doesn't affect the keyboard if set */
+#define KBD_MODE_DISABLE_KBD   0x10    /* Disable keyboard interface */
+#define KBD_MODE_DISABLE_MOUSE 0x20    /* Disable mouse interface */
+#define KBD_MODE_KCC           0x40    /* Scan code conversion to PC format */
+#define KBD_MODE_RFU           0x80
+
+/*
+ *     Mouse Commands
+ */
+
+#define AUX_SET_RES            0xE8    /* Set resolution */
+#define AUX_SET_SCALE11                0xE6    /* Set 1:1 scaling */
+#define AUX_SET_SCALE21                0xE7    /* Set 2:1 scaling */
+#define AUX_GET_SCALE          0xE9    /* Get scaling factor */
+#define AUX_SET_STREAM         0xEA    /* Set stream mode */
+#define AUX_SET_SAMPLE         0xF3    /* Set sample rate */
+#define AUX_ENABLE_DEV         0xF4    /* Enable aux device */
+#define AUX_DISABLE_DEV                0xF5    /* Disable aux device */
+#define AUX_RESET              0xFF    /* Reset aux device */
+#define AUX_ACK                        0xFA    /* Command byte ACK. */
+
+#define AUX_BUF_SIZE           2048    /* This might be better divisible by
+                                          three to make overruns stay in sync
+                                          but then the read function would need
+                                          a lock etc - ick */
+
+struct aux_queue {
+       unsigned long head;
+       unsigned long tail;
+       wait_queue_head_t proc_list;
+       struct fasync_struct *fasync;
+       unsigned char buf[AUX_BUF_SIZE];
+};
+
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
diff --git a/arch/x86/kdb/x86_64-dis.c b/arch/x86/kdb/x86_64-dis.c
new file mode 100644 (file)
index 0000000..131a761
--- /dev/null
@@ -0,0 +1,4686 @@
+/* Print i386 instructions for GDB, the GNU debugger.
+   Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Run through col -b to remove trailing whitespace and various #ifdef/ifndef
+ * __KERNEL__ added.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+/* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+   July 1988
+    modified by John Hassey (hassey@dg-rtp.dg.com)
+    x86-64 support added by Jan Hubicka (jh@suse.cz)
+    VIA PadLock support by Michal Ludvig (mludvig@suse.cz).  */
+
+/* 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>
+#define abort() BUG()
+#else  /* __KERNEL__ */
+#include "dis-asm.h"
+#include "sysdep.h"
+#include "opintl.h"
+#endif /* __KERNEL__ */
+
+#define MAXLEN 20
+
+#ifndef __KERNEL__
+#include <setjmp.h>
+#endif /* __KERNEL__ */
+
+#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 (struct disassemble_info *, bfd_byte *);
+static void ckprefix (void);
+static const char *prefix_name (int, int);
+static int print_insn (bfd_vma, disassemble_info *);
+static void dofloat (int);
+static void OP_ST (int, int);
+static void OP_STi (int, int);
+static int putop (const char *, int);
+static void oappend (const char *);
+static void append_seg (void);
+static void OP_indirE (int, int);
+static void print_operand_value (char *, int, bfd_vma);
+static void OP_E (int, int);
+static void OP_G (int, int);
+static bfd_vma get64 (void);
+static bfd_signed_vma get32 (void);
+static bfd_signed_vma get32s (void);
+static int get16 (void);
+static void set_op (bfd_vma, int);
+static void OP_REG (int, int);
+static void OP_IMREG (int, int);
+static void OP_I (int, int);
+static void OP_I64 (int, int);
+static void OP_sI (int, int);
+static void OP_J (int, int);
+static void OP_SEG (int, int);
+static void OP_DIR (int, int);
+static void OP_OFF (int, int);
+static void OP_OFF64 (int, int);
+static void ptr_reg (int, int);
+static void OP_ESreg (int, int);
+static void OP_DSreg (int, int);
+static void OP_C (int, int);
+static void OP_D (int, int);
+static void OP_T (int, int);
+static void OP_Rd (int, int);
+static void OP_MMX (int, int);
+static void OP_XMM (int, int);
+static void OP_EM (int, int);
+static void OP_EX (int, int);
+static void OP_MS (int, int);
+static void OP_XS (int, int);
+static void OP_M (int, int);
+static void OP_VMX (int, int);
+static void OP_0fae (int, int);
+static void OP_0f07 (int, int);
+static void NOP_Fixup (int, int);
+static void OP_3DNowSuffix (int, int);
+static void OP_SIMD_Suffix (int, int);
+static void SIMD_Fixup (int, int);
+static void PNI_Fixup (int, int);
+static void SVME_Fixup (int, int);
+static void INVLPG_Fixup (int, int);
+static void BadOp (void);
+static void SEG_Fixup (int, int);
+static void VMX_Fixup (int, int);
+
+struct dis_private {
+  /* Points to first byte not fetched. */
+  bfd_byte *max_fetched;
+  bfd_byte the_buffer[MAXLEN];
+  bfd_vma insn_start;
+  int orig_sizeflag;
+#ifndef __KERNEL__
+  jmp_buf bailout;
+#endif /* __KERNEL__ */
+};
+
+/* The opcode for the fwait instruction, which we treat as a prefix
+   when we can.         */
+#define FWAIT_OPCODE (0x9b)
+
+/* Set to 1 for 64bit mode disassembly.         */
+static int mode_64bit;
+
+/* Flags for the prefixes for the current instruction. See below.  */
+static int prefixes;
+
+/* REX prefix the current instruction. See below.  */
+static int rex;
+/* Bits of REX we've already used.  */
+static int rex_used;
+#define REX_MODE64     8
+#define REX_EXTX       4
+#define REX_EXTY       2
+#define REX_EXTZ       1
+/* Mark parts used in the REX prefix.  When we are testing for
+   empty prefix (for 8bit register REX extension), just mask it
+   out.         Otherwise test for REX bit is excuse for existence of REX
+   only in case value is nonzero.  */
+#define USED_REX(value)                                        \
+  {                                                    \
+    if (value)                                         \
+      rex_used |= (rex & value) ? (value) | 0x40 : 0;  \
+    else                                               \
+      rex_used |= 0x40;                                        \
+  }
+
+/* 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 (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  /* __KERNEL__ */
+       /* XXX - what to do? */
+       kdb_printf("Hmm. longjmp.\n");
+#endif /* __KERNEL__ */
+    }
+  else
+    priv->max_fetched = addr;
+  return 1;
+}
+
+#define XX NULL, 0
+
+#define Eb OP_E, b_mode
+#define Ev OP_E, v_mode
+#define Ed OP_E, d_mode
+#define Eq OP_E, q_mode
+#define Edq OP_E, dq_mode
+#define Edqw OP_E, dqw_mode
+#define indirEv OP_indirE, branch_v_mode
+#define indirEp OP_indirE, f_mode
+#define Em OP_E, m_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_M, 0              /* lea, lgdt, etc. */
+#define Mp OP_M, f_mode                /* 32 or 48 bit memory operand for LDS, LES etc */
+#define Gb OP_G, b_mode
+#define Gv OP_G, v_mode
+#define Gd OP_G, d_mode
+#define Gdq OP_G, dq_mode
+#define Gm OP_G, m_mode
+#define Gw OP_G, w_mode
+#define Rd OP_Rd, d_mode
+#define Rm OP_Rd, m_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode      /* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iq OP_I, q_mode
+#define Iv64 OP_I64, v_mode
+#define Iw OP_I, w_mode
+#define I1 OP_I, const_1_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#define Cm OP_C, m_mode
+#define Dm OP_D, m_mode
+#define Td OP_T, d_mode
+#define Sv SEG_Fixup, v_mode
+
+#define RMeAX OP_REG, eAX_reg
+#define RMeBX OP_REG, eBX_reg
+#define RMeCX OP_REG, eCX_reg
+#define RMeDX OP_REG, eDX_reg
+#define RMeSP OP_REG, eSP_reg
+#define RMeBP OP_REG, eBP_reg
+#define RMeSI OP_REG, eSI_reg
+#define RMeDI OP_REG, eDI_reg
+#define RMrAX OP_REG, rAX_reg
+#define RMrBX OP_REG, rBX_reg
+#define RMrCX OP_REG, rCX_reg
+#define RMrDX OP_REG, rDX_reg
+#define RMrSP OP_REG, rSP_reg
+#define RMrBP OP_REG, rBP_reg
+#define RMrSI OP_REG, rSI_reg
+#define RMrDI OP_REG, rDI_reg
+#define RMAL OP_REG, al_reg
+#define RMAL OP_REG, al_reg
+#define RMCL OP_REG, cl_reg
+#define RMDL OP_REG, dl_reg
+#define RMBL OP_REG, bl_reg
+#define RMAH OP_REG, ah_reg
+#define RMCH OP_REG, ch_reg
+#define RMDH OP_REG, dh_reg
+#define RMBH OP_REG, bh_reg
+#define RMAX OP_REG, ax_reg
+#define RMDX OP_REG, dx_reg
+
+#define eAX OP_IMREG, eAX_reg
+#define eBX OP_IMREG, eBX_reg
+#define eCX OP_IMREG, eCX_reg
+#define eDX OP_IMREG, eDX_reg
+#define eSP OP_IMREG, eSP_reg
+#define eBP OP_IMREG, eBP_reg
+#define eSI OP_IMREG, eSI_reg
+#define eDI OP_IMREG, eDI_reg
+#define AL OP_IMREG, al_reg
+#define AL OP_IMREG, al_reg
+#define CL OP_IMREG, cl_reg
+#define DL OP_IMREG, dl_reg
+#define BL OP_IMREG, bl_reg
+#define AH OP_IMREG, ah_reg
+#define CH OP_IMREG, ch_reg
+#define DH OP_IMREG, dh_reg
+#define BH OP_IMREG, bh_reg
+#define AX OP_IMREG, ax_reg
+#define DX OP_IMREG, dx_reg
+#define indirDX OP_IMREG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, 0
+#define Ob OP_OFF, b_mode
+#define Ob64 OP_OFF64, b_mode
+#define Ov OP_OFF, v_mode
+#define Ov64 OP_OFF64, 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 XS OP_XS, v_mode
+#define VM OP_VMX, q_mode
+#define OPSUF OP_3DNowSuffix, 0
+#define OPSIMD OP_SIMD_Suffix, 0
+
+#define cond_jump_flag NULL, cond_jump_mode
+#define loop_jcxz_flag NULL, loop_jcxz_mode
+
+/* bits in sizeflag */
+#define SUFFIX_ALWAYS 4
+#define AFLAG 2
+#define DFLAG 1
+
+#define b_mode 1  /* byte operand */
+#define v_mode 2  /* operand size depends on prefixes */
+#define w_mode 3  /* word operand */
+#define d_mode 4  /* double word operand  */
+#define q_mode 5  /* quad word operand */
+#define t_mode 6  /* ten-byte operand */
+#define x_mode 7  /* 16-byte XMM operand */
+#define m_mode 8  /* d_mode in 32bit, q_mode in 64bit mode.  */
+#define cond_jump_mode 9
+#define loop_jcxz_mode 10
+#define dq_mode 11 /* operand size depends on REX prefixes.  */
+#define dqw_mode 12 /* registers like dq_mode, memory like w_mode.  */
+#define f_mode 13 /* 4- or 6-byte pointer operand */
+#define const_1_mode 14
+#define branch_v_mode 15 /* v_mode for branch. */
+
+#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 rAX_reg 132
+#define rCX_reg 133
+#define rDX_reg 134
+#define rBX_reg 135
+#define rSP_reg 136
+#define rBP_reg 137
+#define rSI_reg 138
+#define rDI_reg 139
+
+#define indir_dx_reg 150
+
+#define FLOATCODE 1
+#define USE_GROUPS 2
+#define USE_PREFIX_USER_TABLE 3
+#define X86_64_SPECIAL 4
+
+#define FLOAT    NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
+
+#define GRP1b    NULL, NULL, USE_GROUPS, NULL,  0, NULL, 0
+#define GRP1S    NULL, NULL, USE_GROUPS, NULL,  1, NULL, 0
+#define GRP1Ss   NULL, NULL, USE_GROUPS, NULL,  2, NULL, 0
+#define GRP2b    NULL, NULL, USE_GROUPS, NULL,  3, NULL, 0
+#define GRP2S    NULL, NULL, USE_GROUPS, NULL,  4, NULL, 0
+#define GRP2b_one NULL, NULL, USE_GROUPS, NULL,         5, NULL, 0
+#define GRP2S_one NULL, NULL, USE_GROUPS, NULL,         6, NULL, 0
+#define GRP2b_cl  NULL, NULL, USE_GROUPS, NULL,         7, NULL, 0
+#define GRP2S_cl  NULL, NULL, USE_GROUPS, NULL,         8, NULL, 0
+#define GRP3b    NULL, NULL, USE_GROUPS, NULL,  9, NULL, 0
+#define GRP3S    NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0
+#define GRP4     NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0
+#define GRP5     NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0
+#define GRP6     NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0
+#define GRP7     NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0
+#define GRP8     NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0
+#define GRP9     NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0
+#define GRP10    NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0
+#define GRP11    NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0
+#define GRP12    NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0
+#define GRP13    NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0
+#define GRP14    NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0
+#define GRPAMD   NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0
+#define GRPPADLCK1 NULL, NULL, USE_GROUPS, NULL, 23, NULL, 0
+#define GRPPADLCK2 NULL, NULL, USE_GROUPS, NULL, 24, NULL, 0
+
+#define PREGRP0          NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  0, NULL, 0
+#define PREGRP1          NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  1, NULL, 0
+#define PREGRP2          NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  2, NULL, 0
+#define PREGRP3          NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  3, NULL, 0
+#define PREGRP4          NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  4, NULL, 0
+#define PREGRP5          NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  5, NULL, 0
+#define PREGRP6          NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  6, NULL, 0
+#define PREGRP7          NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  7, NULL, 0
+#define PREGRP8          NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  8, NULL, 0
+#define PREGRP9          NULL, NULL, USE_PREFIX_USER_TABLE, NULL,  9, NULL, 0
+#define PREGRP10  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0
+#define PREGRP11  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0
+#define PREGRP12  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0
+#define PREGRP13  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0
+#define PREGRP14  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0
+#define PREGRP15  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0
+#define PREGRP16  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0
+#define PREGRP17  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0
+#define PREGRP18  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0
+#define PREGRP19  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0
+#define PREGRP20  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0
+#define PREGRP21  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0
+#define PREGRP22  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0
+#define PREGRP23  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0
+#define PREGRP24  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0
+#define PREGRP25  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0
+#define PREGRP26  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0
+#define PREGRP27  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 27, NULL, 0
+#define PREGRP28  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 28, NULL, 0
+#define PREGRP29  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 29, NULL, 0
+#define PREGRP30  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 30, NULL, 0
+#define PREGRP31  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 31, NULL, 0
+#define PREGRP32  NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 32, NULL, 0
+
+#define X86_64_0  NULL, NULL, X86_64_SPECIAL, NULL,  0, NULL, 0
+
+typedef void (*op_rtn) (int bytemode, int sizeflag);
+
+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
+   'C' => print 's' or 'l' ('w' or 'd' in Intel mode) depending on operand
+   .     size prefix
+   'E' => print 'e' if 32-bit form of jcxz
+   'F' => print 'w' or 'l' depending on address size prefix (loop insns)
+   'H' => print ",pt" or ",pn" branch hint
+   'I' => honor following macro letter even in Intel mode (implemented only
+   .     for some of the macro letters)
+   'J' => print 'l'
+   'L' => print 'l' if suffix_always is true
+   'N' => print 'n' if instruction has no wait "prefix"
+   'O' => print 'd', or 'o'
+   'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
+   .     or suffix_always is true.  print 'q' if rex prefix is present.
+   'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
+   .     is true
+   'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode)
+   'S' => print 'w', 'l' or 'q' if suffix_always is true
+   'T' => print 'q' in 64bit mode and behave as 'P' otherwise
+   'U' => print 'q' in 64bit mode and behave as 'Q' otherwise
+   'W' => print 'b' or 'w' ("w" or "de" in intel mode)
+   'X' => print 's', 'd' depending on data16 prefix (for XMM)
+   'Y' => 'q' if instruction has an REX 64bit overwrite prefix
+
+   Many of the above letters print nothing in Intel mode.  See "putop"
+   for the details.
+
+   Braces '{' and '}', and vertical bars '|', indicate alternative
+   mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel
+   modes.  In cases where there are only two alternatives, the X86_64
+   instruction is reserved, and "(bad)" is printed.
+*/
+
+static const struct dis386 dis386[] = {
+  /* 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 },
+  { "push{T|}",                es, XX, XX },
+  { "pop{T|}",         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 },
+  { "push{T|}",                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 },
+  { "push{T|}",                ss, XX, XX },
+  { "popT|}",          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 },
+  { "push{T|}",                ds, XX, XX },
+  { "pop{T|}",         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 */
+  { "inc{S|}",         RMeAX, XX, XX },
+  { "inc{S|}",         RMeCX, XX, XX },
+  { "inc{S|}",         RMeDX, XX, XX },
+  { "inc{S|}",         RMeBX, XX, XX },
+  { "inc{S|}",         RMeSP, XX, XX },
+  { "inc{S|}",         RMeBP, XX, XX },
+  { "inc{S|}",         RMeSI, XX, XX },
+  { "inc{S|}",         RMeDI, XX, XX },
+  /* 48 */
+  { "dec{S|}",         RMeAX, XX, XX },
+  { "dec{S|}",         RMeCX, XX, XX },
+  { "dec{S|}",         RMeDX, XX, XX },
+  { "dec{S|}",         RMeBX, XX, XX },
+  { "dec{S|}",         RMeSP, XX, XX },
+  { "dec{S|}",         RMeBP, XX, XX },
+  { "dec{S|}",         RMeSI, XX, XX },
+  { "dec{S|}",         RMeDI, XX, XX },
+  /* 50 */
+  { "pushS",           RMrAX, XX, XX },
+  { "pushS",           RMrCX, XX, XX },
+  { "pushS",           RMrDX, XX, XX },
+  { "pushS",           RMrBX, XX, XX },
+  { "pushS",           RMrSP, XX, XX },
+  { "pushS",           RMrBP, XX, XX },
+  { "pushS",           RMrSI, XX, XX },
+  { "pushS",           RMrDI, XX, XX },
+  /* 58 */
+  { "popS",            RMrAX, XX, XX },
+  { "popS",            RMrCX, XX, XX },
+  { "popS",            RMrDX, XX, XX },
+  { "popS",            RMrBX, XX, XX },
+  { "popS",            RMrSP, XX, XX },
+  { "popS",            RMrBP, XX, XX },
+  { "popS",            RMrSI, XX, XX },
+  { "popS",            RMrDI, XX, XX },
+  /* 60 */
+  { "pusha{P|}",       XX, XX, XX },
+  { "popa{P|}",                XX, XX, XX },
+  { "bound{S|}",       Gv, Ma, XX },
+  { X86_64_0 },
+  { "(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 */
+  { "pushT",           Iq, XX, XX },
+  { "imulS",           Gv, Ev, Iv },
+  { "pushT",           sIb, XX, XX },
+  { "imulS",           Gv, Ev, sIb },
+  { "ins{b||b|}",      Yb, indirDX, XX },
+  { "ins{R||R|}",      Yv, indirDX, XX },
+  { "outs{b||b|}",     indirDX, Xb, XX },
+  { "outs{R||R|}",     indirDX, Xv, XX },
+  /* 70 */
+  { "joH",             Jb, XX, cond_jump_flag },
+  { "jnoH",            Jb, XX, cond_jump_flag },
+  { "jbH",             Jb, XX, cond_jump_flag },
+  { "jaeH",            Jb, XX, cond_jump_flag },
+  { "jeH",             Jb, XX, cond_jump_flag },
+  { "jneH",            Jb, XX, cond_jump_flag },
+  { "jbeH",            Jb, XX, cond_jump_flag },
+  { "jaH",             Jb, XX, cond_jump_flag },
+  /* 78 */
+  { "jsH",             Jb, XX, cond_jump_flag },
+  { "jnsH",            Jb, XX, cond_jump_flag },
+  { "jpH",             Jb, XX, cond_jump_flag },
+  { "jnpH",            Jb, XX, cond_jump_flag },
+  { "jlH",             Jb, XX, cond_jump_flag },
+  { "jgeH",            Jb, XX, cond_jump_flag },
+  { "jleH",            Jb, XX, cond_jump_flag },
+  { "jgH",             Jb, XX, cond_jump_flag },
+  /* 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",            Sv, Sw, XX },
+  { "leaS",            Gv, M, XX },
+  { "movQ",            Sw, Sv, XX },
+  { "popU",            Ev, XX, XX },
+  /* 90 */
+  { "nop",             NOP_Fixup, 0, XX, XX },
+  { "xchgS",           RMeCX, eAX, XX },
+  { "xchgS",           RMeDX, eAX, XX },
+  { "xchgS",           RMeBX, eAX, XX },
+  { "xchgS",           RMeSP, eAX, XX },
+  { "xchgS",           RMeBP, eAX, XX },
+  { "xchgS",           RMeSI, eAX, XX },
+  { "xchgS",           RMeDI, eAX, XX },
+  /* 98 */
+  { "cW{tR||tR|}",     XX, XX, XX },
+  { "cR{tO||tO|}",     XX, XX, XX },
+  { "Jcall{T|}",       Ap, XX, XX },
+  { "(bad)",           XX, XX, XX },   /* fwait */
+  { "pushfT",          XX, XX, XX },
+  { "popfT",           XX, XX, XX },
+  { "sahf{|}",         XX, XX, XX },
+  { "lahf{|}",         XX, XX, XX },
+  /* a0 */
+  { "movB",            AL, Ob64, XX },
+  { "movS",            eAX, Ov64, XX },
+  { "movB",            Ob64, AL, XX },
+  { "movS",            Ov64, eAX, XX },
+  { "movs{b||b|}",     Yb, Xb, XX },
+  { "movs{R||R|}",     Yv, Xv, XX },
+  { "cmps{b||b|}",     Xb, Yb, XX },
+  { "cmps{R||R|}",     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",            RMAL, Ib, XX },
+  { "movB",            RMCL, Ib, XX },
+  { "movB",            RMDL, Ib, XX },
+  { "movB",            RMBL, Ib, XX },
+  { "movB",            RMAH, Ib, XX },
+  { "movB",            RMCH, Ib, XX },
+  { "movB",            RMDH, Ib, XX },
+  { "movB",            RMBH, Ib, XX },
+  /* b8 */
+  { "movS",            RMeAX, Iv64, XX },
+  { "movS",            RMeCX, Iv64, XX },
+  { "movS",            RMeDX, Iv64, XX },
+  { "movS",            RMeBX, Iv64, XX },
+  { "movS",            RMeSP, Iv64, XX },
+  { "movS",            RMeBP, Iv64, XX },
+  { "movS",            RMeSI, Iv64, XX },
+  { "movS",            RMeDI, Iv64, XX },
+  /* c0 */
+  { GRP2b },
+  { GRP2S },
+  { "retT",            Iw, XX, XX },
+  { "retT",            XX, XX, XX },
+  { "les{S|}",         Gv, Mp, XX },
+  { "ldsS",            Gv, Mp, XX },
+  { "movA",            Eb, Ib, XX },
+  { "movQ",            Ev, Iv, XX },
+  /* c8 */
+  { "enterT",          Iw, Ib, XX },
+  { "leaveT",          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 */
+  { "loopneFH",                Jb, XX, loop_jcxz_flag },
+  { "loopeFH",         Jb, XX, loop_jcxz_flag },
+  { "loopFH",          Jb, XX, loop_jcxz_flag },
+  { "jEcxzH",          Jb, XX, loop_jcxz_flag },
+  { "inB",             AL, Ib, XX },
+  { "inS",             eAX, Ib, XX },
+  { "outB",            Ib, AL, XX },
+  { "outS",            Ib, eAX, XX },
+  /* e8 */
+  { "callT",           Jv, XX, XX },
+  { "jmpT",            Jv, XX, XX },
+  { "Jjmp{T|}",                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 */
+  { "icebp",           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[] = {
+  /* 00 */
+  { GRP6 },
+  { GRP7 },
+  { "larS",            Gv, Ew, XX },
+  { "lslS",            Gv, Ew, XX },
+  { "(bad)",           XX, XX, XX },
+  { "syscall",         XX, XX, XX },
+  { "clts",            XX, XX, XX },
+  { "sysretP",         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 },
+  { PREGRP30 },
+  { "movlpX",          EX, XM, SIMD_Fixup, 'h' },
+  { "unpcklpX",                XM, EX, XX },
+  { "unpckhpX",                XM, EX, XX },
+  { PREGRP31 },
+  { "movhpX",          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 */
+  { "movL",            Rm, Cm, XX },
+  { "movL",            Rm, Dm, XX },
+  { "movL",            Cm, Rm, XX },
+  { "movL",            Dm, Rm, XX },
+  { "movL",            Rd, Td, XX },
+  { "(bad)",           XX, XX, XX },
+  { "movL",            Td, Rd, XX },
+  { "(bad)",           XX, XX, XX },
+  /* 28 */
+  { "movapX",          XM, EX, XX },
+  { "movapX",          EX, XM, XX },
+  { PREGRP2 },
+  { "movntpX",         Ev, XM, XX },
+  { PREGRP4 },
+  { PREGRP3 },
+  { "ucomisX",         XM,EX, XX },
+  { "comisX",          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 */
+  { "movmskpX",                Gdq, XS, XX },
+  { PREGRP13 },
+  { PREGRP12 },
+  { PREGRP11 },
+  { "andpX",           XM, EX, XX },
+  { "andnpX",          XM, EX, XX },
+  { "orpX",            XM, EX, XX },
+  { "xorpX",           XM, EX, XX },
+  /* 58 */
+  { PREGRP0 },
+  { PREGRP10 },
+  { PREGRP17 },
+  { PREGRP16 },
+  { 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 },
+  { PREGRP26 },
+  { PREGRP24 },
+  { "movd",            MX, Edq, XX },
+  { PREGRP19 },
+  /* 70 */
+  { PREGRP22 },
+  { GRP10 },
+  { GRP11 },
+  { GRP12 },
+  { "pcmpeqb",         MX, EM, XX },
+  { "pcmpeqw",         MX, EM, XX },
+  { "pcmpeqd",         MX, EM, XX },
+  { "emms",            XX, XX, XX },
+  /* 78 */
+  { "vmread",          Em, Gm, XX },
+  { "vmwrite",         Gm, Em, XX },
+  { "(bad)",           XX, XX, XX },
+  { "(bad)",           XX, XX, XX },
+  { PREGRP28 },
+  { PREGRP29 },
+  { PREGRP23 },
+  { PREGRP20 },
+  /* 80 */
+  { "joH",             Jv, XX, cond_jump_flag },
+  { "jnoH",            Jv, XX, cond_jump_flag },
+  { "jbH",             Jv, XX, cond_jump_flag },
+  { "jaeH",            Jv, XX, cond_jump_flag },
+  { "jeH",             Jv, XX, cond_jump_flag },
+  { "jneH",            Jv, XX, cond_jump_flag },
+  { "jbeH",            Jv, XX, cond_jump_flag },
+  { "jaH",             Jv, XX, cond_jump_flag },
+  /* 88 */
+  { "jsH",             Jv, XX, cond_jump_flag },
+  { "jnsH",            Jv, XX, cond_jump_flag },
+  { "jpH",             Jv, XX, cond_jump_flag },
+  { "jnpH",            Jv, XX, cond_jump_flag },
+  { "jlH",             Jv, XX, cond_jump_flag },
+  { "jgeH",            Jv, XX, cond_jump_flag },
+  { "jleH",            Jv, XX, cond_jump_flag },
+  { "jgH",             Jv, XX, cond_jump_flag },
+  /* 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 */
+  { "pushT",           fs, XX, XX },
+  { "popT",            fs, XX, XX },
+  { "cpuid",           XX, XX, XX },
+  { "btS",             Ev, Gv, XX },
+  { "shldS",           Ev, Gv, Ib },
+  { "shldS",           Ev, Gv, CL },
+  { GRPPADLCK2 },
+  { GRPPADLCK1 },
+  /* a8 */
+  { "pushT",           gs, XX, XX },
+  { "popT",            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 },
+  { "movz{bR|x|bR|x}", Gv, Eb, XX },
+  { "movz{wR|x|wR|x}", 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 },
+  { "movs{bR|x|bR|x}", Gv, Eb, XX },
+  { "movs{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movsww ! */
+  /* c0 */
+  { "xaddB",           Eb, Gb, XX },
+  { "xaddS",           Ev, Gv, XX },
+  { PREGRP1 },
+  { "movntiS",         Ev, Gv, XX },
+  { "pinsrw",          MX, Edqw, Ib },
+  { "pextrw",          Gdq, MS, Ib },
+  { "shufpX",          XM, EX, Ib },
+  { GRP9 },
+  /* c8 */
+  { "bswap",           RMeAX, XX, XX },
+  { "bswap",           RMeCX, XX, XX },
+  { "bswap",           RMeDX, XX, XX },
+  { "bswap",           RMeBX, XX, XX },
+  { "bswap",           RMeSP, XX, XX },
+  { "bswap",           RMeBP, XX, XX },
+  { "bswap",           RMeSI, XX, XX },
+  { "bswap",           RMeDI, XX, XX },
+  /* d0 */
+  { PREGRP27 },
+  { "psrlw",           MX, EM, XX },
+  { "psrld",           MX, EM, XX },
+  { "psrlq",           MX, EM, XX },
+  { "paddq",           MX, EM, XX },
+  { "pmullw",          MX, EM, XX },
+  { PREGRP21 },
+  { "pmovmskb",                Gdq, MS, 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 },
+  { PREGRP15 },
+  { PREGRP25 },
+  /* 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 */
+  { PREGRP32 },
+  { "psllw",           MX, EM, XX },
+  { "pslld",           MX, EM, XX },
+  { "psllq",           MX, EM, XX },
+  { "pmuludq",         MX, EM, XX },
+  { "pmaddwd",         MX, EM, XX },
+  { "psadbw",          MX, EM, XX },
+  { PREGRP18 },
+  /* f8 */
+  { "psubb",           MX, EM, XX },
+  { "psubw",           MX, EM, XX },
+  { "psubd",           MX, EM, XX },
+  { "psubq",           MX, EM, 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,0,1,0,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,1,1,1,1,1,1, /* 5f */
+  /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
+  /* 70 */ 1,1,1,1,1,1,1,0,1,1,0,0,1,1,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 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
+  /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
+  /* f0 */ 1,1,1,1,1,1,1,1,1,1,1,1,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_SSE_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,1,0,0,0,1,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,1,1,1,1,1,1, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */
+  /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, /* 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 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 1,0,0,0,0,0,0,1,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 unsigned char need_modrm;
+
+/* If we are accessing mod/rm/reg without need_modrm set, then the
+   values are stale.  Hitting this abort likely indicates that you
+   need to update onebyte_has_modrm or twobyte_has_modrm.  */
+#define MODRM_CHECK  if (!need_modrm) abort ()
+
+static const char **names64;
+static const char **names32;
+static const char **names16;
+static const char **names8;
+static const char **names8rex;
+static const char **names_seg;
+static const char **index16;
+
+static const char *intel_names64[] = {
+  "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+};
+static const char *intel_names32[] = {
+  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
+  "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
+};
+static const char *intel_names16[] = {
+  "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
+  "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
+};
+static const char *intel_names8[] = {
+  "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
+};
+static const char *intel_names8rex[] = {
+  "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
+  "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
+};
+static const char *intel_names_seg[] = {
+  "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
+};
+static const char *intel_index16[] = {
+  "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
+};
+
+static const char *att_names64[] = {
+  "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
+  "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+};
+static const char *att_names32[] = {
+  "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
+  "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
+};
+static const char *att_names16[] = {
+  "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
+  "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
+};
+static const char *att_names8[] = {
+  "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
+};
+static const char *att_names8rex[] = {
+  "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
+  "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
+};
+static const char *att_names_seg[] = {
+  "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?",
+};
+static const char *att_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, I1, XX },
+    { "rorA",  Eb, I1, XX },
+    { "rclA",  Eb, I1, XX },
+    { "rcrA",  Eb, I1, XX },
+    { "shlA",  Eb, I1, XX },
+    { "shrA",  Eb, I1, XX },
+    { "(bad)", XX, XX, XX },
+    { "sarA",  Eb, I1, XX },
+  },
+  /* GRP2S_one */
+  {
+    { "rolQ",  Ev, I1, XX },
+    { "rorQ",  Ev, I1, XX },
+    { "rclQ",  Ev, I1, XX },
+    { "rcrQ",  Ev, I1, XX },
+    { "shlQ",  Ev, I1, XX },
+    { "shrQ",  Ev, I1, XX },
+    { "(bad)", XX, XX, XX},
+    { "sarQ",  Ev, I1, 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 },
+    { "mulA",  Eb, XX, XX },   /* Don't print the implicit %al register,  */
+    { "imulA", Eb, XX, XX },   /* to distinguish these opcodes from other */
+    { "divA",  Eb, XX, XX },   /* mul/imul opcodes.  Do the same for div  */
+    { "idivA", Eb, XX, XX }    /* and idiv for consistency.               */
+  },
+  /* GRP3S */
+  {
+    { "testQ", Ev, Iv, XX },
+    { "(bad)", XX, XX, XX },
+    { "notQ",  Ev, XX, XX },
+    { "negQ",  Ev, XX, XX },
+    { "mulQ",  Ev, XX, XX },   /* Don't print the implicit register.  */
+    { "imulQ", Ev, XX, XX },
+    { "divQ",  Ev, XX, XX },
+    { "idivQ", Ev, XX, 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 },
+    { "callT", indirEv, XX, XX },
+    { "JcallT", indirEp, XX, XX },
+    { "jmpT",  indirEv, XX, XX },
+    { "JjmpT", indirEp, XX, XX },
+    { "pushU", Ev, XX, XX },
+    { "(bad)", XX, XX, XX },
+  },
+  /* GRP6 */
+  {
+    { "sldtQ", Ev, XX, XX },
+    { "strQ",  Ev, 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 */
+  {
+    { "sgdtIQ", VMX_Fixup, 0, XX, XX },
+    { "sidtIQ", PNI_Fixup, 0, XX, XX },
+    { "lgdt{Q|Q||}",    M, XX, XX },
+    { "lidt{Q|Q||}",    SVME_Fixup, 0, XX, XX },
+    { "smswQ", Ev, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "lmsw",  Ew, XX, XX },
+    { "invlpg", INVLPG_Fixup, w_mode, 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", Eq, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "",      VM, XX, XX },           /* See OP_VMX.  */
+    { "vmptrst", Eq, 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 },
+    { "psrldq", MS, Ib, XX },
+    { "(bad)", XX, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "psllq", MS, Ib, XX },
+    { "pslldq", MS, Ib, XX },
+  },
+  /* GRP13 */
+  {
+    { "fxsave", Ev, XX, XX },
+    { "fxrstor", Ev, XX, XX },
+    { "ldmxcsr", Ev, XX, XX },
+    { "stmxcsr", Ev, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "lfence", OP_0fae, 0, XX, XX },
+    { "mfence", OP_0fae, 0, XX, XX },
+    { "clflush", OP_0fae, 0, 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 },
+  },
+  /* GRPPADLCK1 */
+  {
+    { "xstore-rng", OP_0f07, 0, XX, XX },
+    { "xcrypt-ecb", OP_0f07, 0, XX, XX },
+    { "xcrypt-cbc", OP_0f07, 0, XX, XX },
+    { "xcrypt-ctr", OP_0f07, 0, XX, XX },
+    { "xcrypt-cfb", OP_0f07, 0, XX, XX },
+    { "xcrypt-ofb", OP_0f07, 0, XX, XX },
+    { "(bad)", OP_0f07, 0, XX, XX },
+    { "(bad)", OP_0f07, 0, XX, XX },
+  },
+  /* GRPPADLCK2 */
+  {
+    { "montmul", OP_0f07, 0, XX, XX },
+    { "xsha1",  OP_0f07, 0, XX, XX },
+    { "xsha256", OP_0f07, 0, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX },
+    { "(bad)",  OP_0f07, 0, XX, XX },
+  }
+};
+
+static const struct dis386 prefix_user_table[][4] = {
+  /* PREGRP0 */
+  {
+    { "addps", XM, EX, XX },
+    { "addss", XM, EX, XX },
+    { "addpd", XM, EX, XX },
+    { "addsd", XM, EX, XX },
+  },
+  /* PREGRP1 */
+  {
+    { "", XM, EX, OPSIMD },    /* See OP_SIMD_SUFFIX.  */
+    { "", XM, EX, OPSIMD },
+    { "", XM, EX, OPSIMD },
+    { "", XM, EX, OPSIMD },
+  },
+  /* PREGRP2 */
+  {
+    { "cvtpi2ps", XM, EM, XX },
+    { "cvtsi2ssY", XM, Ev, XX },
+    { "cvtpi2pd", XM, EM, XX },
+    { "cvtsi2sdY", XM, Ev, XX },
+  },
+  /* PREGRP3 */
+  {
+    { "cvtps2pi", MX, EX, XX },
+    { "cvtss2siY", Gv, EX, XX },
+    { "cvtpd2pi", MX, EX, XX },
+    { "cvtsd2siY", Gv, EX, XX },
+  },
+  /* PREGRP4 */
+  {
+    { "cvttps2pi", MX, EX, XX },
+    { "cvttss2siY", Gv, EX, XX },
+    { "cvttpd2pi", MX, EX, XX },
+    { "cvttsd2siY", Gv, EX, XX },
+  },
+  /* PREGRP5 */
+  {
+    { "divps", XM, EX, XX },
+    { "divss", XM, EX, XX },
+    { "divpd", XM, EX, XX },
+    { "divsd", XM, EX, XX },
+  },
+  /* PREGRP6 */
+  {
+    { "maxps", XM, EX, XX },
+    { "maxss", XM, EX, XX },
+    { "maxpd", XM, EX, XX },
+    { "maxsd", XM, EX, XX },
+  },
+  /* PREGRP7 */
+  {
+    { "minps", XM, EX, XX },
+    { "minss", XM, EX, XX },
+    { "minpd", XM, EX, XX },
+    { "minsd", XM, EX, XX },
+  },
+  /* PREGRP8 */
+  {
+    { "movups", XM, EX, XX },
+    { "movss", XM, EX, XX },
+    { "movupd", XM, EX, XX },
+    { "movsd", XM, EX, XX },
+  },
+  /* PREGRP9 */
+  {
+    { "movups", EX, XM, XX },
+    { "movss", EX, XM, XX },
+    { "movupd", EX, XM, XX },
+    { "movsd", EX, XM, XX },
+  },
+  /* PREGRP10 */
+  {
+    { "mulps", XM, EX, XX },
+    { "mulss", XM, EX, XX },
+    { "mulpd", XM, EX, XX },
+    { "mulsd", XM, EX, XX },
+  },
+  /* PREGRP11 */
+  {
+    { "rcpps", XM, EX, XX },
+    { "rcpss", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP12 */
+  {
+    { "rsqrtps", XM, EX, XX },
+    { "rsqrtss", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP13 */
+  {
+    { "sqrtps", XM, EX, XX },
+    { "sqrtss", XM, EX, XX },
+    { "sqrtpd", XM, EX, XX },
+    { "sqrtsd", XM, EX, XX },
+  },
+  /* PREGRP14 */
+  {
+    { "subps", XM, EX, XX },
+    { "subss", XM, EX, XX },
+    { "subpd", XM, EX, XX },
+    { "subsd", XM, EX, XX },
+  },
+  /* PREGRP15 */
+  {
+    { "(bad)", XM, EX, XX },
+    { "cvtdq2pd", XM, EX, XX },
+    { "cvttpd2dq", XM, EX, XX },
+    { "cvtpd2dq", XM, EX, XX },
+  },
+  /* PREGRP16 */
+  {
+    { "cvtdq2ps", XM, EX, XX },
+    { "cvttps2dq",XM, EX, XX },
+    { "cvtps2dq",XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP17 */
+  {
+    { "cvtps2pd", XM, EX, XX },
+    { "cvtss2sd", XM, EX, XX },
+    { "cvtpd2ps", XM, EX, XX },
+    { "cvtsd2ss", XM, EX, XX },
+  },
+  /* PREGRP18 */
+  {
+    { "maskmovq", MX, MS, XX },
+    { "(bad)", XM, EX, XX },
+    { "maskmovdqu", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP19 */
+  {
+    { "movq", MX, EM, XX },
+    { "movdqu", XM, EX, XX },
+    { "movdqa", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP20 */
+  {
+    { "movq", EM, MX, XX },
+    { "movdqu", EX, XM, XX },
+    { "movdqa", EX, XM, XX },
+    { "(bad)", EX, XM, XX },
+  },
+  /* PREGRP21 */
+  {
+    { "(bad)", EX, XM, XX },
+    { "movq2dq", XM, MS, XX },
+    { "movq", EX, XM, XX },
+    { "movdq2q", MX, XS, XX },
+  },
+  /* PREGRP22 */
+  {
+    { "pshufw", MX, EM, Ib },
+    { "pshufhw", XM, EX, Ib },
+    { "pshufd", XM, EX, Ib },
+    { "pshuflw", XM, EX, Ib },
+  },
+  /* PREGRP23 */
+  {
+    { "movd", Edq, MX, XX },
+    { "movq", XM, EX, XX },
+    { "movd", Edq, XM, XX },
+    { "(bad)", Ed, XM, XX },
+  },
+  /* PREGRP24 */
+  {
+    { "(bad)", MX, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "punpckhqdq", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP25 */
+  {
+    { "movntq", EM, MX, XX },
+    { "(bad)", EM, XM, XX },
+    { "movntdq", EM, XM, XX },
+    { "(bad)", EM, XM, XX },
+  },
+  /* PREGRP26 */
+  {
+    { "(bad)", MX, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "punpcklqdq", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP27 */
+  {
+    { "(bad)", MX, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "addsubpd", XM, EX, XX },
+    { "addsubps", XM, EX, XX },
+  },
+  /* PREGRP28 */
+  {
+    { "(bad)", MX, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "haddpd", XM, EX, XX },
+    { "haddps", XM, EX, XX },
+  },
+  /* PREGRP29 */
+  {
+    { "(bad)", MX, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "hsubpd", XM, EX, XX },
+    { "hsubps", XM, EX, XX },
+  },
+  /* PREGRP30 */
+  {
+    { "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */
+    { "movsldup", XM, EX, XX },
+    { "movlpd", XM, EX, XX },
+    { "movddup", XM, EX, XX },
+  },
+  /* PREGRP31 */
+  {
+    { "movhpX", XM, EX, SIMD_Fixup, 'l' },
+    { "movshdup", XM, EX, XX },
+    { "movhpd", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+  },
+  /* PREGRP32 */
+  {
+    { "(bad)", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "(bad)", XM, EX, XX },
+    { "lddqu", XM, M, XX },
+  },
+};
+
+static const struct dis386 x86_64_table[][2] = {
+  {
+    { "arpl", Ew, Gw, XX },
+    { "movs{||lq|xd}", Gv, Ed, XX },
+  },
+};
+
+#ifdef __KERNEL__
+#define INTERNAL_DISASSEMBLER_ERROR "<internal disassembler error>"
+#else  /* __KERNEL__ */
+#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
+#endif /* __KERNEL__ */
+
+static void
+ckprefix (void)
+{
+  int newrex;
+  rex = 0;
+  prefixes = 0;
+  used_prefixes = 0;
+  rex_used = 0;
+  while (1)
+    {
+      FETCH_DATA (the_info, codep + 1);
+      newrex = 0;
+      switch (*codep)
+       {
+       /* REX prefixes family.  */
+       case 0x40:
+       case 0x41:
+       case 0x42:
+       case 0x43:
+       case 0x44:
+       case 0x45:
+       case 0x46:
+       case 0x47:
+       case 0x48:
+       case 0x49:
+       case 0x4a:
+       case 0x4b:
+       case 0x4c:
+       case 0x4d:
+       case 0x4e:
+       case 0x4f:
+           if (mode_64bit)
+             newrex = *codep;
+           else
+             return;
+         break;
+       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;
+       }
+      /* Rex is ignored when followed by another prefix.  */
+      if (rex)
+       {
+         oappend (prefix_name (rex, 0));
+         oappend (" ");
+       }
+      rex = newrex;
+      codep++;
+    }
+}
+
+/* Return the name of the prefix byte PREF, or NULL if PREF is not a
+   prefix byte.         */
+
+static const char *
+prefix_name (int pref, int sizeflag)
+{
+  switch (pref)
+    {
+    /* REX prefixes family.  */
+    case 0x40:
+      return "rex";
+    case 0x41:
+      return "rexZ";
+    case 0x42:
+      return "rexY";
+    case 0x43:
+      return "rexYZ";
+    case 0x44:
+      return "rexX";
+    case 0x45:
+      return "rexXZ";
+    case 0x46:
+      return "rexXY";
+    case 0x47:
+      return "rexXYZ";
+    case 0x48:
+      return "rex64";
+    case 0x49:
+      return "rex64Z";
+    case 0x4a:
+      return "rex64Y";
+    case 0x4b:
+      return "rex64YZ";
+    case 0x4c:
+      return "rex64X";
+    case 0x4d:
+      return "rex64XZ";
+    case 0x4e:
+      return "rex64XY";
+    case 0x4f:
+      return "rex64XYZ";
+    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:
+      if (mode_64bit)
+       return (sizeflag & AFLAG) ? "addr32" : "addr64";
+      else
+       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 int two_source_ops;
+static bfd_vma op_address[3];
+static bfd_vma op_riprel[3];
+static bfd_vma 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 char intel_syntax;
+static char open_char;
+static char close_char;
+static char separator_char;
+static char scale_char;
+
+/* Here for backwards compatibility.  When gdb stops using
+   print_insn_i386_att and print_insn_i386_intel these functions can
+   disappear, and print_insn_i386 be merged into print_insn.  */
+int
+print_insn_i386_att (bfd_vma pc, disassemble_info *info)
+{
+  intel_syntax = 0;
+
+  return print_insn (pc, info);
+}
+
+int
+print_insn_i386_intel (bfd_vma pc, disassemble_info *info)
+{
+  intel_syntax = 1;
+
+  return print_insn (pc, info);
+}
+
+int
+print_insn_i386 (bfd_vma pc, disassemble_info *info)
+{
+  intel_syntax = -1;
+
+  return print_insn (pc, info);
+}
+
+static int
+print_insn (bfd_vma pc, disassemble_info *info)
+{
+  const struct dis386 *dp;
+  int i;
+  char *first, *second, *third;
+  int needcomma;
+  unsigned char uses_SSE_prefix, uses_LOCK_prefix;
+  int sizeflag;
+  const char *p;
+  struct dis_private priv;
+
+  mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
+               || info->mach == bfd_mach_x86_64);
+
+  if (intel_syntax == (char) -1)
+    intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
+                   || info->mach == bfd_mach_x86_64_intel_syntax);
+
+  if (info->mach == bfd_mach_i386_i386
+      || info->mach == bfd_mach_x86_64
+      || info->mach == bfd_mach_i386_i386_intel_syntax
+      || info->mach == bfd_mach_x86_64_intel_syntax)
+    priv.orig_sizeflag = AFLAG | DFLAG;
+  else if (info->mach == bfd_mach_i386_i8086)
+    priv.orig_sizeflag = 0;
+  else
+    abort ();
+
+  for (p = info->disassembler_options; p != NULL; )
+    {
+      if (strncmp (p, "x86-64", 6) == 0)
+       {
+         mode_64bit = 1;
+         priv.orig_sizeflag = AFLAG | DFLAG;
+       }
+      else if (strncmp (p, "i386", 4) == 0)
+       {
+         mode_64bit = 0;
+         priv.orig_sizeflag = AFLAG | DFLAG;
+       }
+      else if (strncmp (p, "i8086", 5) == 0)
+       {
+         mode_64bit = 0;
+         priv.orig_sizeflag = 0;
+       }
+      else if (strncmp (p, "intel", 5) == 0)
+       {
+         intel_syntax = 1;
+       }
+      else if (strncmp (p, "att", 3) == 0)
+       {
+         intel_syntax = 0;
+       }
+      else if (strncmp (p, "addr", 4) == 0)
+       {
+         if (p[4] == '1' && p[5] == '6')
+           priv.orig_sizeflag &= ~AFLAG;
+         else if (p[4] == '3' && p[5] == '2')
+           priv.orig_sizeflag |= AFLAG;
+       }
+      else if (strncmp (p, "data", 4) == 0)
+       {
+         if (p[4] == '1' && p[5] == '6')
+           priv.orig_sizeflag &= ~DFLAG;
+         else if (p[4] == '3' && p[5] == '2')
+           priv.orig_sizeflag |= DFLAG;
+       }
+      else if (strncmp (p, "suffix", 6) == 0)
+       priv.orig_sizeflag |= SUFFIX_ALWAYS;
+
+      p = strchr (p, ',');
+      if (p != NULL)
+       p++;
+    }
+
+  if (intel_syntax)
+    {
+      names64 = intel_names64;
+      names32 = intel_names32;
+      names16 = intel_names16;
+      names8 = intel_names8;
+      names8rex = intel_names8rex;
+      names_seg = intel_names_seg;
+      index16 = intel_index16;
+      open_char = '[';
+      close_char = ']';
+      separator_char = '+';
+      scale_char = '*';
+    }
+  else
+    {
+      names64 = att_names64;
+      names32 = att_names32;
+      names16 = att_names16;
+      names8 = att_names8;
+      names8rex = att_names8rex;
+      names_seg = att_names_seg;
+      index16 = att_index16;
+      open_char = '(';
+      close_char =  ')';
+      separator_char = ',';
+      scale_char = ',';
+    }
+
+  /* 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 = &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 = priv.the_buffer;
+  codep = priv.the_buffer;
+
+#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 > priv.the_buffer)
+       {
+         name = prefix_name (priv.the_buffer[0], priv.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) priv.the_buffer[0]);
+           }
+
+         return 1;
+       }
+
+      return -1;
+    }
+#endif /* __KERNEL__ */
+
+  obufp = obuf;
+  ckprefix ();
+
+  insn_codep = codep;
+  sizeflag = priv.orig_sizeflag;
+
+  FETCH_DATA (info, codep + 1);
+  two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
+
+  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 (priv.the_buffer[0], priv.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);
+      dp = &dis386_twobyte[*++codep];
+      need_modrm = twobyte_has_modrm[*codep];
+      uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep];
+      uses_LOCK_prefix = (*codep & ~0x02) == 0x20;
+    }
+  else
+    {
+      dp = &dis386[*codep];
+      need_modrm = onebyte_has_modrm[*codep];
+      uses_SSE_prefix = 0;
+      uses_LOCK_prefix = 0;
+    }
+  codep++;
+
+  if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ))
+    {
+      oappend ("repz ");
+      used_prefixes |= PREFIX_REPZ;
+    }
+  if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ))
+    {
+      oappend ("repnz ");
+      used_prefixes |= PREFIX_REPNZ;
+    }
+  if (!uses_LOCK_prefix && (prefixes & PREFIX_LOCK))
+    {
+      oappend ("lock ");
+      used_prefixes |= PREFIX_LOCK;
+    }
+
+  if (prefixes & PREFIX_ADDR)
+    {
+      sizeflag ^= AFLAG;
+      if (dp->bytemode3 != loop_jcxz_mode || intel_syntax)
+       {
+         if ((sizeflag & AFLAG) || mode_64bit)
+           oappend ("addr32 ");
+         else
+           oappend ("addr16 ");
+         used_prefixes |= PREFIX_ADDR;
+       }
+    }
+
+  if (!uses_SSE_prefix && (prefixes & PREFIX_DATA))
+    {
+      sizeflag ^= DFLAG;
+      if (dp->bytemode3 == cond_jump_mode
+         && dp->bytemode1 == v_mode
+         && !intel_syntax)
+       {
+         if (sizeflag & DFLAG)
+           oappend ("data32 ");
+         else
+           oappend ("data16 ");
+         used_prefixes |= PREFIX_DATA;
+       }
+    }
+
+  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
+    {
+      int index;
+      if (dp->name == NULL)
+       {
+         switch (dp->bytemode1)
+           {
+           case USE_GROUPS:
+             dp = &grps[dp->bytemode2][reg];
+             break;
+
+           case USE_PREFIX_USER_TABLE:
+             index = 0;
+             used_prefixes |= (prefixes & PREFIX_REPZ);
+             if (prefixes & PREFIX_REPZ)
+               index = 1;
+             else
+               {
+                 used_prefixes |= (prefixes & PREFIX_DATA);
+                 if (prefixes & PREFIX_DATA)
+                   index = 2;
+                 else
+                   {
+                     used_prefixes |= (prefixes & PREFIX_REPNZ);
+                     if (prefixes & PREFIX_REPNZ)
+                       index = 3;
+                   }
+               }
+             dp = &prefix_user_table[dp->bytemode2][index];
+             break;
+
+           case X86_64_SPECIAL:
+             dp = &x86_64_table[dp->bytemode2][mode_64bit];
+             break;
+
+           default:
+             oappend (INTERNAL_DISASSEMBLER_ERROR);
+             break;
+           }
+       }
+
+      if (putop (dp->name, sizeflag) == 0)
+       {
+         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 (priv.the_buffer[0], priv.orig_sizeflag);
+      if (name == NULL)
+       name = INTERNAL_DISASSEMBLER_ERROR;
+      (*info->fprintf_func) (info->stream, "%s", name);
+      return 1;
+    }
+  if (rex & ~rex_used)
+    {
+      const char *name;
+      name = prefix_name (rex | 0x40, priv.orig_sizeflag);
+      if (name == NULL)
+       name = INTERNAL_DISASSEMBLER_ERROR;
+      (*info->fprintf_func) (info->stream, "%s ", name);
+    }
+
+  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 && !op_riprel[0])
+       (*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 && !op_riprel[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 && !op_riprel[2])
+       (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
+      else
+       (*info->fprintf_func) (info->stream, "%s", third);
+    }
+  for (i = 0; i < 3; i++)
+    if (op_index[i] != -1 && op_riprel[i])
+      {
+       (*info->fprintf_func) (info->stream, "        # ");
+       (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep
+                                               + op_address[op_index[i]]), info);
+      }
+  return codep - priv.the_buffer;
+}
+
+static const char *float_mem[] = {
+  /* d8 */
+  "fadd{s||s|}",
+  "fmul{s||s|}",
+  "fcom{s||s|}",
+  "fcomp{s||s|}",
+  "fsub{s||s|}",
+  "fsubr{s||s|}",
+  "fdiv{s||s|}",
+  "fdivr{s||s|}",
+  /* d9 */
+  "fld{s||s|}",
+  "(bad)",
+  "fst{s||s|}",
+  "fstp{s||s|}",
+  "fldenvIC",
+  "fldcw",
+  "fNstenvIC",
+  "fNstcw",
+  /* da */
+  "fiadd{l||l|}",
+  "fimul{l||l|}",
+  "ficom{l||l|}",
+  "ficomp{l||l|}",
+  "fisub{l||l|}",
+  "fisubr{l||l|}",
+  "fidiv{l||l|}",
+  "fidivr{l||l|}",
+  /* db */
+  "fild{l||l|}",
+  "fisttp{l||l|}",
+  "fist{l||l|}",
+  "fistp{l||l|}",
+  "(bad)",
+  "fld{t||t|}",
+  "(bad)",
+  "fstp{t||t|}",
+  /* dc */
+  "fadd{l||l|}",
+  "fmul{l||l|}",
+  "fcom{l||l|}",
+  "fcomp{l||l|}",
+  "fsub{l||l|}",
+  "fsubr{l||l|}",
+  "fdiv{l||l|}",
+  "fdivr{l||l|}",
+  /* dd */
+  "fld{l||l|}",
+  "fisttp{ll||ll|}",
+  "fst{l||l|}",
+  "fstp{l||l|}",
+  "frstorIC",
+  "(bad)",
+  "fNsaveIC",
+  "fNstsw",
+  /* de */
+  "fiadd",
+  "fimul",
+  "ficom",
+  "ficomp",
+  "fisub",
+  "fisubr",
+  "fidiv",
+  "fidivr",
+  /* df */
+  "fild",
+  "fisttp",
+  "fist",
+  "fistp",
+  "fbld",
+  "fild{ll||ll|}",
+  "fbstp",
+  "fistp{ll||ll|}",
+};
+
+static const unsigned char float_mem_mode[] = {
+  /* d8 */
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  /* d9 */
+  d_mode,
+  0,
+  d_mode,
+  d_mode,
+  0,
+  w_mode,
+  0,
+  w_mode,
+  /* da */
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  /* db */
+  d_mode,
+  d_mode,
+  d_mode,
+  d_mode,
+  0,
+  t_mode,
+  0,
+  t_mode,
+  /* dc */
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  /* dd */
+  q_mode,
+  q_mode,
+  q_mode,
+  q_mode,
+  0,
+  0,
+  0,
+  w_mode,
+  /* de */
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  /* df */
+  w_mode,
+  w_mode,
+  w_mode,
+  w_mode,
+  t_mode,
+  q_mode,
+  t_mode,
+  q_mode
+};
+
+#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 */
+  {
+    { "ffreep", STi, 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 (int sizeflag)
+{
+  const struct dis386 *dp;
+  unsigned char floatop;
+
+  floatop = codep[-1];
+
+  if (mod != 3)
+    {
+      int fp_indx = (floatop - 0xd8) * 8 + reg;
+
+      putop (float_mem[fp_indx], sizeflag);
+      obufp = op1out;
+      OP_E (float_mem_mode[fp_indx], sizeflag);
+      return;
+    }
+  /* Skip mod/rm byte. */
+  MODRM_CHECK;
+  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);
+    }
+}
+
+static void
+OP_ST (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  oappend ("%st");
+}
+
+static void
+OP_STi (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  sprintf (scratchbuf, "%%st(%d)", rm);
+  oappend (scratchbuf + intel_syntax);
+}
+
+/* Capital letters in template are macros.  */
+static int
+putop (const char *template, int sizeflag)
+{
+  const char *p;
+  int alt = 0;
+
+  for (p = template; *p; p++)
+    {
+      switch (*p)
+       {
+       default:
+         *obufp++ = *p;
+         break;
+       case '{':
+         alt = 0;
+         if (intel_syntax)
+           alt += 1;
+         if (mode_64bit)
+           alt += 2;
+         while (alt != 0)
+           {
+             while (*++p != '|')
+               {
+                 if (*p == '}')
+                   {
+                     /* Alternative not valid.  */
+                     strcpy (obuf, "(bad)");
+                     obufp = obuf + 5;
+                     return 1;
+                   }
+                 else if (*p == '\0')
+                   abort ();
+               }
+             alt--;
+           }
+         /* Fall through.  */
+       case 'I':
+         alt = 1;
+         continue;
+       case '|':
+         while (*++p != '}')
+           {
+             if (*p == '\0')
+               abort ();
+           }
+         break;
+       case '}':
+         break;
+       case 'A':
+         if (intel_syntax)
+           break;
+         if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
+           *obufp++ = 'b';
+         break;
+       case 'B':
+         if (intel_syntax)
+           break;
+         if (sizeflag & SUFFIX_ALWAYS)
+           *obufp++ = 'b';
+         break;
+       case 'C':
+         if (intel_syntax && !alt)
+           break;
+         if ((prefixes & PREFIX_DATA) || (sizeflag & SUFFIX_ALWAYS))
+           {
+             if (sizeflag & DFLAG)
+               *obufp++ = intel_syntax ? 'd' : 'l';
+             else
+               *obufp++ = intel_syntax ? 'w' : 's';
+             used_prefixes |= (prefixes & PREFIX_DATA);
+           }
+         break;
+       case 'E':               /* For jcxz/jecxz */
+         if (mode_64bit)
+           {
+             if (sizeflag & AFLAG)
+               *obufp++ = 'r';
+             else
+               *obufp++ = 'e';
+           }
+         else
+           if (sizeflag & AFLAG)
+             *obufp++ = 'e';
+         used_prefixes |= (prefixes & PREFIX_ADDR);
+         break;
+       case 'F':
+         if (intel_syntax)
+           break;
+         if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
+           {
+             if (sizeflag & AFLAG)
+               *obufp++ = mode_64bit ? 'q' : 'l';
+             else
+               *obufp++ = mode_64bit ? 'l' : 'w';
+             used_prefixes |= (prefixes & PREFIX_ADDR);
+           }
+         break;
+       case 'H':
+         if (intel_syntax)
+           break;
+         if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_CS
+             || (prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_DS)
+           {
+             used_prefixes |= prefixes & (PREFIX_CS | PREFIX_DS);
+             *obufp++ = ',';
+             *obufp++ = 'p';
+             if (prefixes & PREFIX_DS)
+               *obufp++ = 't';
+             else
+               *obufp++ = 'n';
+           }
+         break;
+       case 'J':
+         if (intel_syntax)
+           break;
+         *obufp++ = 'l';
+         break;
+       case 'L':
+         if (intel_syntax)
+           break;
+         if (sizeflag & SUFFIX_ALWAYS)
+           *obufp++ = 'l';
+         break;
+       case 'N':
+         if ((prefixes & PREFIX_FWAIT) == 0)
+           *obufp++ = 'n';
+         else
+           used_prefixes |= PREFIX_FWAIT;
+         break;
+       case 'O':
+         USED_REX (REX_MODE64);
+         if (rex & REX_MODE64)
+           *obufp++ = 'o';
+         else
+           *obufp++ = 'd';
+         break;
+       case 'T':
+         if (intel_syntax)
+           break;
+         if (mode_64bit)
+           {
+             *obufp++ = 'q';
+             break;
+           }
+         /* Fall through.  */
+       case 'P':
+         if (intel_syntax)
+           break;
+         if ((prefixes & PREFIX_DATA)
+             || (rex & REX_MODE64)
+             || (sizeflag & SUFFIX_ALWAYS))
+           {
+             USED_REX (REX_MODE64);
+             if (rex & REX_MODE64)
+               *obufp++ = 'q';
+             else
+               {
+                  if (sizeflag & DFLAG)
+                     *obufp++ = 'l';
+                  else
+                    *obufp++ = 'w';
+                  used_prefixes |= (prefixes & PREFIX_DATA);
+               }
+           }
+         break;
+       case 'U':
+         if (intel_syntax)
+           break;
+         if (mode_64bit)
+           {
+             *obufp++ = 'q';
+             break;
+           }
+         /* Fall through.  */
+       case 'Q':
+         if (intel_syntax && !alt)
+           break;
+         USED_REX (REX_MODE64);
+         if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
+           {
+             if (rex & REX_MODE64)
+               *obufp++ = 'q';
+             else
+               {
+                 if (sizeflag & DFLAG)
+                   *obufp++ = intel_syntax ? 'd' : 'l';
+                 else
+                   *obufp++ = 'w';
+                 used_prefixes |= (prefixes & PREFIX_DATA);
+               }
+           }
+         break;
+       case 'R':
+         USED_REX (REX_MODE64);
+         if (intel_syntax)
+           {
+             if (rex & REX_MODE64)
+               {
+                 *obufp++ = 'q';
+                 *obufp++ = 't';
+               }
+             else if (sizeflag & DFLAG)
+               {
+                 *obufp++ = 'd';
+                 *obufp++ = 'q';
+               }
+             else
+               {
+                 *obufp++ = 'w';
+                 *obufp++ = 'd';
+               }
+           }
+         else
+           {
+             if (rex & REX_MODE64)
+               *obufp++ = 'q';
+             else if (sizeflag & DFLAG)
+               *obufp++ = 'l';
+             else
+               *obufp++ = 'w';
+           }
+         if (!(rex & REX_MODE64))
+           used_prefixes |= (prefixes & PREFIX_DATA);
+         break;
+       case 'S':
+         if (intel_syntax)
+           break;
+         if (sizeflag & SUFFIX_ALWAYS)
+           {
+             if (rex & REX_MODE64)
+               *obufp++ = 'q';
+             else
+               {
+                 if (sizeflag & DFLAG)
+                   *obufp++ = 'l';
+                 else
+                   *obufp++ = 'w';
+                 used_prefixes |= (prefixes & PREFIX_DATA);
+               }
+           }
+         break;
+       case 'X':
+         if (prefixes & PREFIX_DATA)
+           *obufp++ = 'd';
+         else
+           *obufp++ = 's';
+         used_prefixes |= (prefixes & PREFIX_DATA);
+         break;
+       case 'Y':
+         if (intel_syntax)
+           break;
+         if (rex & REX_MODE64)
+           {
+             USED_REX (REX_MODE64);
+             *obufp++ = 'q';
+           }
+         break;
+         /* implicit operand size 'l' for i386 or 'q' for x86-64 */
+       case 'W':
+         /* operand size flag for cwtl, cbtw */
+         USED_REX (0);
+         if (rex)
+           *obufp++ = 'l';
+         else if (sizeflag & DFLAG)
+           *obufp++ = 'w';
+         else
+           *obufp++ = 'b';
+         if (intel_syntax)
+           {
+             if (rex)
+               {
+                 *obufp++ = 'q';
+                 *obufp++ = 'e';
+               }
+             if (sizeflag & DFLAG)
+               {
+                 *obufp++ = 'd';
+                 *obufp++ = 'e';
+               }
+             else
+               {
+                 *obufp++ = 'w';
+               }
+           }
+         if (!rex)
+           used_prefixes |= (prefixes & PREFIX_DATA);
+         break;
+       }
+      alt = 0;
+    }
+  *obufp = 0;
+  return 0;
+}
+
+static void
+oappend (const char *s)
+{
+  strcpy (obufp, s);
+  obufp += strlen (s);
+}
+
+static void
+append_seg (void)
+{
+  if (prefixes & PREFIX_CS)
+    {
+      used_prefixes |= PREFIX_CS;
+      oappend ("%cs:" + intel_syntax);
+    }
+  if (prefixes & PREFIX_DS)
+    {
+      used_prefixes |= PREFIX_DS;
+      oappend ("%ds:" + intel_syntax);
+    }
+  if (prefixes & PREFIX_SS)
+    {
+      used_prefixes |= PREFIX_SS;
+      oappend ("%ss:" + intel_syntax);
+    }
+  if (prefixes & PREFIX_ES)
+    {
+      used_prefixes |= PREFIX_ES;
+      oappend ("%es:" + intel_syntax);
+    }
+  if (prefixes & PREFIX_FS)
+    {
+      used_prefixes |= PREFIX_FS;
+      oappend ("%fs:" + intel_syntax);
+    }
+  if (prefixes & PREFIX_GS)
+    {
+      used_prefixes |= PREFIX_GS;
+      oappend ("%gs:" + intel_syntax);
+    }
+}
+
+static void
+OP_indirE (int bytemode, int sizeflag)
+{
+  if (!intel_syntax)
+    oappend ("*");
+  OP_E (bytemode, sizeflag);
+}
+
+static void
+print_operand_value (char *buf, int hex, bfd_vma disp)
+{
+  if (mode_64bit)
+    {
+      if (hex)
+       {
+         char tmp[30];
+         int i;
+         buf[0] = '0';
+         buf[1] = 'x';
+         sprintf_vma (tmp, disp);
+         for (i = 0; tmp[i] == '0' && tmp[i + 1]; i++);
+         strcpy (buf + 2, tmp + i);
+       }
+      else
+       {
+         bfd_signed_vma v = disp;
+         char tmp[30];
+         int i;
+         if (v < 0)
+           {
+             *(buf++) = '-';
+             v = -disp;
+             /* Check for possible overflow on 0x8000000000000000.  */
+             if (v < 0)
+               {
+                 strcpy (buf, "9223372036854775808");
+                 return;
+               }
+           }
+         if (!v)
+           {
+             strcpy (buf, "0");
+             return;
+           }
+
+         i = 0;
+         tmp[29] = 0;
+         while (v)
+           {
+             tmp[28 - i] = (v % 10) + '0';
+             v /= 10;
+             i++;
+           }
+         strcpy (buf, tmp + 29 - i);
+       }
+    }
+  else
+    {
+      if (hex)
+       sprintf (buf, "0x%x", (unsigned int) disp);
+      else
+       sprintf (buf, "%d", (int) disp);
+    }
+}
+
+static void
+OP_E (int bytemode, int sizeflag)
+{
+  bfd_vma disp;
+  int add = 0;
+  int riprel = 0;
+  USED_REX (REX_EXTZ);
+  if (rex & REX_EXTZ)
+    add += 8;
+
+  /* Skip mod/rm byte. */
+  MODRM_CHECK;
+  codep++;
+
+  if (mod == 3)
+    {
+      switch (bytemode)
+       {
+       case b_mode:
+         USED_REX (0);
+         if (rex)
+           oappend (names8rex[rm + add]);
+         else
+           oappend (names8[rm + add]);
+         break;
+       case w_mode:
+         oappend (names16[rm + add]);
+         break;
+       case d_mode:
+         oappend (names32[rm + add]);
+         break;
+       case q_mode:
+         oappend (names64[rm + add]);
+         break;
+       case m_mode:
+         if (mode_64bit)
+           oappend (names64[rm + add]);
+         else
+           oappend (names32[rm + add]);
+         break;
+       case branch_v_mode:
+         if (mode_64bit)
+           oappend (names64[rm + add]);
+         else
+           {
+             if ((sizeflag & DFLAG) || bytemode != branch_v_mode)
+               oappend (names32[rm + add]);
+             else
+               oappend (names16[rm + add]);
+             used_prefixes |= (prefixes & PREFIX_DATA);
+           }
+         break;
+       case v_mode:
+       case dq_mode:
+       case dqw_mode:
+         USED_REX (REX_MODE64);
+         if (rex & REX_MODE64)
+           oappend (names64[rm + add]);
+         else if ((sizeflag & DFLAG) || bytemode != v_mode)
+           oappend (names32[rm + add]);
+         else
+           oappend (names16[rm + add]);
+         used_prefixes |= (prefixes & PREFIX_DATA);
+         break;
+       case 0:
+         break;
+       default:
+         oappend (INTERNAL_DISASSEMBLER_ERROR);
+         break;
+       }
+      return;
+    }
+
+  disp = 0;
+  append_seg ();
+
+  if ((sizeflag & AFLAG) || mode_64bit) /* 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);
+         index = (*codep >> 3) & 7;
+         if (mode_64bit || index != 0x4)
+           /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored.  */
+           scale = (*codep >> 6) & 3;
+         base = *codep & 7;
+         USED_REX (REX_EXTY);
+         if (rex & REX_EXTY)
+           index += 8;
+         codep++;
+       }
+      base += add;
+
+      switch (mod)
+       {
+       case 0:
+         if ((base & 7) == 5)
+           {
+             havebase = 0;
+             if (mode_64bit && !havesib)
+               riprel = 1;
+             disp = get32s ();
+           }
+         break;
+       case 1:
+         FETCH_DATA (the_info, codep + 1);
+         disp = *codep++;
+         if ((disp & 0x80) != 0)
+           disp -= 0x100;
+         break;
+       case 2:
+         disp = get32s ();
+         break;
+       }
+
+      if (!intel_syntax)
+       if (mod != 0 || (base & 7) == 5)
+         {
+           print_operand_value (scratchbuf, !riprel, disp);
+           oappend (scratchbuf);
+           if (riprel)
+             {
+               set_op (disp, 1);
+               oappend ("(%rip)");
+             }
+         }
+
+      if (havebase || (havesib && (index != 4 || scale != 0)))
+       {
+         if (intel_syntax)
+           {
+             switch (bytemode)
+               {
+               case b_mode:
+                 oappend ("BYTE PTR ");
+                 break;
+               case w_mode:
+               case dqw_mode:
+                 oappend ("WORD PTR ");
+                 break;
+               case branch_v_mode:
+               case v_mode:
+               case dq_mode:
+                 USED_REX (REX_MODE64);
+                 if (rex & REX_MODE64)
+                   oappend ("QWORD PTR ");
+                 else if ((sizeflag & DFLAG) || bytemode == dq_mode)
+                   oappend ("DWORD PTR ");
+                 else
+                   oappend ("WORD PTR ");
+                 used_prefixes |= (prefixes & PREFIX_DATA);
+                 break;
+               case d_mode:
+                 oappend ("DWORD PTR ");
+                 break;
+               case q_mode:
+                 oappend ("QWORD PTR ");
+                 break;
+               case m_mode:
+                 if (mode_64bit)
+                   oappend ("QWORD PTR ");
+                 else
+                   oappend ("DWORD PTR ");
+                 break;
+               case f_mode:
+                 if (sizeflag & DFLAG)
+                   {
+                     used_prefixes |= (prefixes & PREFIX_DATA);
+                     oappend ("FWORD PTR ");
+                   }
+                 else
+                   oappend ("DWORD PTR ");
+                 break;
+               case t_mode:
+                 oappend ("TBYTE PTR ");
+                 break;
+               case x_mode:
+                 oappend ("XMMWORD PTR ");
+                 break;
+               default:
+                 break;
+               }
+           }
+         *obufp++ = open_char;
+         if (intel_syntax && riprel)
+           oappend ("rip + ");
+         *obufp = '\0';
+         if (havebase)
+           oappend (mode_64bit && (sizeflag & AFLAG)
+                    ? names64[base] : names32[base]);
+         if (havesib)
+           {
+             if (index != 4)
+               {
+                 if (!intel_syntax || havebase)
+                   {
+                     *obufp++ = separator_char;
+                     *obufp = '\0';
+                   }
+                 oappend (mode_64bit && (sizeflag & AFLAG)
+                          ? names64[index] : names32[index]);
+               }
+             if (scale != 0 || (!intel_syntax && index != 4))
+               {
+                 *obufp++ = scale_char;
+                 *obufp = '\0';
+                 sprintf (scratchbuf, "%d", 1 << scale);
+                 oappend (scratchbuf);
+               }
+           }
+         if (intel_syntax && disp)
+           {
+             if ((bfd_signed_vma) disp > 0)
+               {
+                 *obufp++ = '+';
+                 *obufp = '\0';
+               }
+             else if (mod != 1)
+               {
+                 *obufp++ = '-';
+                 *obufp = '\0';
+                 disp = - (bfd_signed_vma) disp;
+               }
+
+             print_operand_value (scratchbuf, mod != 1, disp);
+             oappend (scratchbuf);
+           }
+
+         *obufp++ = close_char;
+         *obufp = '\0';
+       }
+      else if (intel_syntax)
+       {
+         if (mod != 0 || (base & 7) == 5)
+           {
+             if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+                             | PREFIX_ES | PREFIX_FS | PREFIX_GS))
+               ;
+             else
+               {
+                 oappend (names_seg[ds_reg - es_reg]);
+                 oappend (":");
+               }
+             print_operand_value (scratchbuf, 1, 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)
+         {
+           print_operand_value (scratchbuf, 0, disp);
+           oappend (scratchbuf);
+         }
+
+      if (mod != 0 || rm != 6)
+       {
+         *obufp++ = open_char;
+         *obufp = '\0';
+         oappend (index16[rm]);
+         if (intel_syntax && disp)
+           {
+             if ((bfd_signed_vma) disp > 0)
+               {
+                 *obufp++ = '+';
+                 *obufp = '\0';
+               }
+             else if (mod != 1)
+               {
+                 *obufp++ = '-';
+                 *obufp = '\0';
+                 disp = - (bfd_signed_vma) disp;
+               }
+
+             print_operand_value (scratchbuf, mod != 1, disp);
+             oappend (scratchbuf);
+           }
+
+         *obufp++ = close_char;
+         *obufp = '\0';
+       }
+      else if (intel_syntax)
+       {
+         if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+                         | PREFIX_ES | PREFIX_FS | PREFIX_GS))
+           ;
+         else
+           {
+             oappend (names_seg[ds_reg - es_reg]);
+             oappend (":");
+           }
+         print_operand_value (scratchbuf, 1, disp & 0xffff);
+         oappend (scratchbuf);
+       }
+    }
+}
+
+static void
+OP_G (int bytemode, int sizeflag)
+{
+  int add = 0;
+  USED_REX (REX_EXTX);
+  if (rex & REX_EXTX)
+    add += 8;
+  switch (bytemode)
+    {
+    case b_mode:
+      USED_REX (0);
+      if (rex)
+       oappend (names8rex[reg + add]);
+      else
+       oappend (names8[reg + add]);
+      break;
+    case w_mode:
+      oappend (names16[reg + add]);
+      break;
+    case d_mode:
+      oappend (names32[reg + add]);
+      break;
+    case q_mode:
+      oappend (names64[reg + add]);
+      break;
+    case v_mode:
+    case dq_mode:
+    case dqw_mode:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       oappend (names64[reg + add]);
+      else if ((sizeflag & DFLAG) || bytemode != v_mode)
+       oappend (names32[reg + add]);
+      else
+       oappend (names16[reg + add]);
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    case m_mode:
+      if (mode_64bit)
+       oappend (names64[reg + add]);
+      else
+       oappend (names32[reg + add]);
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      break;
+    }
+}
+
+static bfd_vma
+get64 (void)
+{
+  bfd_vma x;
+#ifdef BFD64
+  unsigned int a;
+  unsigned int b;
+
+  FETCH_DATA (the_info, codep + 8);
+  a = *codep++ & 0xff;
+  a |= (*codep++ & 0xff) << 8;
+  a |= (*codep++ & 0xff) << 16;
+  a |= (*codep++ & 0xff) << 24;
+  b = *codep++ & 0xff;
+  b |= (*codep++ & 0xff) << 8;
+  b |= (*codep++ & 0xff) << 16;
+  b |= (*codep++ & 0xff) << 24;
+  x = a + ((bfd_vma) b << 32);
+#else
+  abort ();
+  x = 0;
+#endif
+  return x;
+}
+
+static bfd_signed_vma
+get32 (void)
+{
+  bfd_signed_vma x = 0;
+
+  FETCH_DATA (the_info, codep + 4);
+  x = *codep++ & (bfd_signed_vma) 0xff;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
+  return x;
+}
+
+static bfd_signed_vma
+get32s (void)
+{
+  bfd_signed_vma x = 0;
+
+  FETCH_DATA (the_info, codep + 4);
+  x = *codep++ & (bfd_signed_vma) 0xff;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
+  x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
+
+  x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31);
+
+  return x;
+}
+
+static int
+get16 (void)
+{
+  int x = 0;
+
+  FETCH_DATA (the_info, codep + 2);
+  x = *codep++ & 0xff;
+  x |= (*codep++ & 0xff) << 8;
+  return x;
+}
+
+static void
+set_op (bfd_vma op, int riprel)
+{
+  op_index[op_ad] = op_ad;
+  if (mode_64bit)
+    {
+      op_address[op_ad] = op;
+      op_riprel[op_ad] = riprel;
+    }
+  else
+    {
+      /* Mask to get a 32-bit address. */
+      op_address[op_ad] = op & 0xffffffff;
+      op_riprel[op_ad] = riprel & 0xffffffff;
+    }
+}
+
+static void
+OP_REG (int code, int sizeflag)
+{
+  const char *s;
+  int add = 0;
+  USED_REX (REX_EXTZ);
+  if (rex & REX_EXTZ)
+    add = 8;
+
+  switch (code)
+    {
+    case indir_dx_reg:
+      if (intel_syntax)
+       s = "[dx]";
+      else
+       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 + add];
+      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 + add];
+      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:
+      USED_REX (0);
+      if (rex)
+       s = names8rex[code - al_reg + add];
+      else
+       s = names8[code - al_reg];
+      break;
+    case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
+    case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
+      if (mode_64bit)
+       {
+         s = names64[code - rAX_reg + add];
+         break;
+       }
+      code += eAX_reg - rAX_reg;
+      /* Fall through. */
+    case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+    case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       s = names64[code - eAX_reg + add];
+      else if (sizeflag & DFLAG)
+       s = names32[code - eAX_reg + add];
+      else
+       s = names16[code - eAX_reg + add];
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    default:
+      s = INTERNAL_DISASSEMBLER_ERROR;
+      break;
+    }
+  oappend (s);
+}
+
+static void
+OP_IMREG (int code, int sizeflag)
+{
+  const char *s;
+
+  switch (code)
+    {
+    case indir_dx_reg:
+      if (intel_syntax)
+       s = "[dx]";
+      else
+       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:
+      USED_REX (0);
+      if (rex)
+       s = names8rex[code - al_reg];
+      else
+       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:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       s = names64[code - eAX_reg];
+      else 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 (int bytemode, int sizeflag)
+{
+  bfd_signed_vma op;
+  bfd_signed_vma mask = -1;
+
+  switch (bytemode)
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++;
+      mask = 0xff;
+      break;
+    case q_mode:
+      if (mode_64bit)
+       {
+         op = get32s ();
+         break;
+       }
+      /* Fall through. */
+    case v_mode:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       op = get32s ();
+      else if (sizeflag & DFLAG)
+       {
+         op = get32 ();
+         mask = 0xffffffff;
+       }
+      else
+       {
+         op = get16 ();
+         mask = 0xfffff;
+       }
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    case w_mode:
+      mask = 0xfffff;
+      op = get16 ();
+      break;
+    case const_1_mode:
+      if (intel_syntax)
+       oappend ("1");
+      return;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+
+  op &= mask;
+  scratchbuf[0] = '$';
+  print_operand_value (scratchbuf + 1, 1, op);
+  oappend (scratchbuf + intel_syntax);
+  scratchbuf[0] = '\0';
+}
+
+static void
+OP_I64 (int bytemode, int sizeflag)
+{
+  bfd_signed_vma op;
+  bfd_signed_vma mask = -1;
+
+  if (!mode_64bit)
+    {
+      OP_I (bytemode, sizeflag);
+      return;
+    }
+
+  switch (bytemode)
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++;
+      mask = 0xff;
+      break;
+    case v_mode:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       op = get64 ();
+      else if (sizeflag & DFLAG)
+       {
+         op = get32 ();
+         mask = 0xffffffff;
+       }
+      else
+       {
+         op = get16 ();
+         mask = 0xfffff;
+       }
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    case w_mode:
+      mask = 0xfffff;
+      op = get16 ();
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+
+  op &= mask;
+  scratchbuf[0] = '$';
+  print_operand_value (scratchbuf + 1, 1, op);
+  oappend (scratchbuf + intel_syntax);
+  scratchbuf[0] = '\0';
+}
+
+static void
+OP_sI (int bytemode, int sizeflag)
+{
+  bfd_signed_vma op;
+  bfd_signed_vma mask = -1;
+
+  switch (bytemode)
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++;
+      if ((op & 0x80) != 0)
+       op -= 0x100;
+      mask = 0xffffffff;
+      break;
+    case v_mode:
+      USED_REX (REX_MODE64);
+      if (rex & REX_MODE64)
+       op = get32s ();
+      else if (sizeflag & DFLAG)
+       {
+         op = get32s ();
+         mask = 0xffffffff;
+       }
+      else
+       {
+         mask = 0xffffffff;
+         op = get16 ();
+         if ((op & 0x8000) != 0)
+           op -= 0x10000;
+       }
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    case w_mode:
+      op = get16 ();
+      mask = 0xffffffff;
+      if ((op & 0x8000) != 0)
+       op -= 0x10000;
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+
+  scratchbuf[0] = '$';
+  print_operand_value (scratchbuf + 1, 1, op);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_J (int bytemode, int sizeflag)
+{
+  bfd_vma disp;
+  bfd_vma 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 = get32s ();
+      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;
+       }
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+  disp = (start_pc + codep - start_codep + disp) & mask;
+  set_op (disp, 0);
+  print_operand_value (scratchbuf, 1, disp);
+  oappend (scratchbuf);
+}
+
+static void
+OP_SEG (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  oappend (names_seg[reg]);
+}
+
+static void
+OP_DIR (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);
+  if (intel_syntax)
+    sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
+  else
+    sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
+  oappend (scratchbuf);
+}
+
+static void
+OP_OFF (int bytemode ATTRIBUTE_UNUSED, int sizeflag)
+{
+  bfd_vma off;
+
+  append_seg ();
+
+  if ((sizeflag & AFLAG) || mode_64bit)
+    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[ds_reg - es_reg]);
+         oappend (":");
+       }
+    }
+  print_operand_value (scratchbuf, 1, off);
+  oappend (scratchbuf);
+}
+
+static void
+OP_OFF64 (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  bfd_vma off;
+
+  if (!mode_64bit)
+    {
+      OP_OFF (bytemode, sizeflag);
+      return;
+    }
+
+  append_seg ();
+
+  off = get64 ();
+
+  if (intel_syntax)
+    {
+      if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+                       | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+       {
+         oappend (names_seg[ds_reg - es_reg]);
+         oappend (":");
+       }
+    }
+  print_operand_value (scratchbuf, 1, off);
+  oappend (scratchbuf);
+}
+
+static void
+ptr_reg (int code, int sizeflag)
+{
+  const char *s;
+
+  *obufp++ = open_char;
+  used_prefixes |= (prefixes & PREFIX_ADDR);
+  if (mode_64bit)
+    {
+      if (!(sizeflag & AFLAG))
+       s = names32[code - eAX_reg];
+      else
+       s = names64[code - eAX_reg];
+    }
+  else if (sizeflag & AFLAG)
+    s = names32[code - eAX_reg];
+  else
+    s = names16[code - eAX_reg];
+  oappend (s);
+  *obufp++ = close_char;
+  *obufp = 0;
+}
+
+static void
+OP_ESreg (int code, int sizeflag)
+{
+  if (intel_syntax)
+    {
+      if (codep[-1] & 1)
+       {
+         USED_REX (REX_MODE64);
+         used_prefixes |= (prefixes & PREFIX_DATA);
+         if (rex & REX_MODE64)
+           oappend ("QWORD PTR ");
+         else if ((sizeflag & DFLAG))
+           oappend ("DWORD PTR ");
+         else
+           oappend ("WORD PTR ");
+       }
+      else
+       oappend ("BYTE PTR ");
+    }
+
+  oappend ("%es:" + intel_syntax);
+  ptr_reg (code, sizeflag);
+}
+
+static void
+OP_DSreg (int code, int sizeflag)
+{
+  if (intel_syntax)
+    {
+      if (codep[-1] != 0xd7 && (codep[-1] & 1))
+       {
+         USED_REX (REX_MODE64);
+         used_prefixes |= (prefixes & PREFIX_DATA);
+         if (rex & REX_MODE64)
+           oappend ("QWORD PTR ");
+         else if ((sizeflag & DFLAG))
+           oappend ("DWORD PTR ");
+         else
+           oappend ("WORD PTR ");
+       }
+      else
+       oappend ("BYTE PTR ");
+    }
+
+  if ((prefixes
+       & (PREFIX_CS
+         | PREFIX_DS
+         | PREFIX_SS
+         | PREFIX_ES
+         | PREFIX_FS
+         | PREFIX_GS)) == 0)
+    prefixes |= PREFIX_DS;
+  append_seg ();
+  ptr_reg (code, sizeflag);
+}
+
+static void
+OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  int add = 0;
+  if (rex & REX_EXTX)
+    {
+      USED_REX (REX_EXTX);
+      add = 8;
+    }
+  else if (!mode_64bit && (prefixes & PREFIX_LOCK))
+    {
+      used_prefixes |= PREFIX_LOCK;
+      add = 8;
+    }
+  sprintf (scratchbuf, "%%cr%d", reg + add);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_D (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  int add = 0;
+  USED_REX (REX_EXTX);
+  if (rex & REX_EXTX)
+    add = 8;
+  if (intel_syntax)
+    sprintf (scratchbuf, "db%d", reg + add);
+  else
+    sprintf (scratchbuf, "%%db%d", reg + add);
+  oappend (scratchbuf);
+}
+
+static void
+OP_T (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  sprintf (scratchbuf, "%%tr%d", reg);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_Rd (int bytemode, int sizeflag)
+{
+  if (mod == 3)
+    OP_E (bytemode, sizeflag);
+  else
+    BadOp ();
+}
+
+static void
+OP_MMX (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  used_prefixes |= (prefixes & PREFIX_DATA);
+  if (prefixes & PREFIX_DATA)
+    {
+      int add = 0;
+      USED_REX (REX_EXTX);
+      if (rex & REX_EXTX)
+       add = 8;
+      sprintf (scratchbuf, "%%xmm%d", reg + add);
+    }
+  else
+    sprintf (scratchbuf, "%%mm%d", reg);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_XMM (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  int add = 0;
+  USED_REX (REX_EXTX);
+  if (rex & REX_EXTX)
+    add = 8;
+  sprintf (scratchbuf, "%%xmm%d", reg + add);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_EM (int bytemode, int sizeflag)
+{
+  if (mod != 3)
+    {
+      if (intel_syntax && bytemode == v_mode)
+       {
+         bytemode = (prefixes & PREFIX_DATA) ? x_mode : q_mode;
+         used_prefixes |= (prefixes & PREFIX_DATA);
+       }
+      OP_E (bytemode, sizeflag);
+      return;
+    }
+
+  /* Skip mod/rm byte. */
+  MODRM_CHECK;
+  codep++;
+  used_prefixes |= (prefixes & PREFIX_DATA);
+  if (prefixes & PREFIX_DATA)
+    {
+      int add = 0;
+
+      USED_REX (REX_EXTZ);
+      if (rex & REX_EXTZ)
+       add = 8;
+      sprintf (scratchbuf, "%%xmm%d", rm + add);
+    }
+  else
+    sprintf (scratchbuf, "%%mm%d", rm);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_EX (int bytemode, int sizeflag)
+{
+  int add = 0;
+  if (mod != 3)
+    {
+      if (intel_syntax && bytemode == v_mode)
+       {
+         switch (prefixes & (PREFIX_DATA|PREFIX_REPZ|PREFIX_REPNZ))
+           {
+           case 0:            bytemode = x_mode; break;
+           case PREFIX_REPZ:  bytemode = d_mode; used_prefixes |= PREFIX_REPZ;  break;
+           case PREFIX_DATA:  bytemode = x_mode; used_prefixes |= PREFIX_DATA;  break;
+           case PREFIX_REPNZ: bytemode = q_mode; used_prefixes |= PREFIX_REPNZ; break;
+           default:           bytemode = 0; break;
+           }
+       }
+      OP_E (bytemode, sizeflag);
+      return;
+    }
+  USED_REX (REX_EXTZ);
+  if (rex & REX_EXTZ)
+    add = 8;
+
+  /* Skip mod/rm byte. */
+  MODRM_CHECK;
+  codep++;
+  sprintf (scratchbuf, "%%xmm%d", rm + add);
+  oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_MS (int bytemode, int sizeflag)
+{
+  if (mod == 3)
+    OP_EM (bytemode, sizeflag);
+  else
+    BadOp ();
+}
+
+static void
+OP_XS (int bytemode, int sizeflag)
+{
+  if (mod == 3)
+    OP_EX (bytemode, sizeflag);
+  else
+    BadOp ();
+}
+
+static void
+OP_M (int bytemode, int sizeflag)
+{
+  if (mod == 3)
+    BadOp ();  /* bad lea,lds,les,lfs,lgs,lss modrm */
+  else
+    OP_E (bytemode, sizeflag);
+}
+
+static void
+OP_0f07 (int bytemode, int sizeflag)
+{
+  if (mod != 3 || rm != 0)
+    BadOp ();
+  else
+    OP_E (bytemode, sizeflag);
+}
+
+static void
+OP_0fae (int bytemode, int sizeflag)
+{
+  if (mod == 3)
+    {
+      if (reg == 7)
+       strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence");
+
+      if (reg < 5 || rm != 0)
+       {
+         BadOp ();     /* bad sfence, mfence, or lfence */
+         return;
+       }
+    }
+  else if (reg != 7)
+    {
+      BadOp ();                /* bad clflush */
+      return;
+    }
+
+  OP_E (bytemode, sizeflag);
+}
+
+static void
+NOP_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  /* NOP with REPZ prefix is called PAUSE.  */
+  if (prefixes == PREFIX_REPZ)
+    strcpy (obuf, "pause");
+}
+
+static const char *const 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 (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 (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)
+    {
+      char suffix1 = 'p', suffix2 = 's';
+      used_prefixes |= (prefixes & PREFIX_REPZ);
+      if (prefixes & PREFIX_REPZ)
+       suffix1 = 's';
+      else
+       {
+         used_prefixes |= (prefixes & PREFIX_DATA);
+         if (prefixes & PREFIX_DATA)
+           suffix2 = 'd';
+         else
+           {
+             used_prefixes |= (prefixes & PREFIX_REPNZ);
+             if (prefixes & PREFIX_REPNZ)
+               suffix1 = 's', suffix2 = 'd';
+           }
+       }
+      sprintf (scratchbuf, "cmp%s%c%c",
+              simd_cmp_op[cmp_type], suffix1, suffix2);
+      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 (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
+PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
+{
+  if (mod == 3 && reg == 1 && rm <= 1)
+    {
+      /* Override "sidt".  */
+      char *p = obuf + strlen (obuf) - 4;
+
+      /* We might have a suffix when disassembling with -Msuffix.  */
+      if (*p == 'i')
+       --p;
+
+      if (rm)
+       {
+         /* mwait %eax,%ecx  */
+         strcpy (p, "mwait");
+         if (!intel_syntax)
+           strcpy (op1out, names32[0]);
+       }
+      else
+       {
+         /* monitor %eax,%ecx,%edx"  */
+         strcpy (p, "monitor");
+         if (!intel_syntax)
+           {
+             if (!mode_64bit)
+               strcpy (op1out, names32[0]);
+             else if (!(prefixes & PREFIX_ADDR))
+               strcpy (op1out, names64[0]);
+             else
+               {
+                 strcpy (op1out, names32[0]);
+                 used_prefixes |= PREFIX_ADDR;
+               }
+             strcpy (op3out, names32[2]);
+           }
+       }
+      if (!intel_syntax)
+       {
+         strcpy (op2out, names32[1]);
+         two_source_ops = 1;
+       }
+
+      codep++;
+    }
+  else
+    OP_M (0, sizeflag);
+}
+
+static void
+SVME_Fixup (int bytemode, int sizeflag)
+{
+  const char *alt;
+  char *p;
+
+  switch (*codep)
+    {
+    case 0xd8:
+      alt = "vmrun";
+      break;
+    case 0xd9:
+      alt = "vmmcall";
+      break;
+    case 0xda:
+      alt = "vmload";
+      break;
+    case 0xdb:
+      alt = "vmsave";
+      break;
+    case 0xdc:
+      alt = "stgi";
+      break;
+    case 0xdd:
+      alt = "clgi";
+      break;
+    case 0xde:
+      alt = "skinit";
+      break;
+    case 0xdf:
+      alt = "invlpga";
+      break;
+    default:
+      OP_M (bytemode, sizeflag);
+      return;
+    }
+  /* Override "lidt".  */
+  p = obuf + strlen (obuf) - 4;
+  /* We might have a suffix.  */
+  if (*p == 'i')
+    --p;
+  strcpy (p, alt);
+  if (!(prefixes & PREFIX_ADDR))
+    {
+      ++codep;
+      return;
+    }
+  used_prefixes |= PREFIX_ADDR;
+  switch (*codep++)
+    {
+    case 0xdf:
+      strcpy (op2out, names32[1]);
+      two_source_ops = 1;
+         /* Fall through.  */
+    case 0xd8:
+    case 0xda:
+    case 0xdb:
+      *obufp++ = open_char;
+      if (mode_64bit || (sizeflag & AFLAG))
+       alt = names32[0];
+      else
+       alt = names16[0];
+      strcpy (obufp, alt);
+      obufp += strlen (alt);
+      *obufp++ = close_char;
+      *obufp = '\0';
+      break;
+    }
+}
+
+static void
+INVLPG_Fixup (int bytemode, int sizeflag)
+{
+  const char *alt;
+
+  switch (*codep)
+    {
+    case 0xf8:
+      alt = "swapgs";
+      break;
+    case 0xf9:
+      alt = "rdtscp";
+      break;
+    default:
+      OP_M (bytemode, sizeflag);
+      return;
+    }
+  /* Override "invlpg".         */
+  strcpy (obuf + strlen (obuf) - 6, alt);
+  codep++;
+}
+
+static void
+BadOp (void)
+{
+  /* Throw away prefixes and 1st. opcode byte. */
+  codep = insn_codep + 1;
+  oappend ("(bad)");
+}
+
+static void
+SEG_Fixup (int extrachar, int sizeflag)
+{
+  if (mod == 3)
+    {
+      /* We need to add a proper suffix with
+
+               movw %ds,%ax
+               movl %ds,%eax
+               movq %ds,%rax
+               movw %ax,%ds
+               movl %eax,%ds
+               movq %rax,%ds
+       */
+      const char *suffix;
+
+      if (prefixes & PREFIX_DATA)
+       suffix = "w";
+      else
+       {
+         USED_REX (REX_MODE64);
+         if (rex & REX_MODE64)
+           suffix = "q";
+         else
+           suffix = "l";
+       }
+      strcat (obuf, suffix);
+    }
+  else
+    {
+      /* We need to fix the suffix for
+
+               movw %ds,(%eax)
+               movw %ds,(%rax)
+               movw (%eax),%ds
+               movw (%rax),%ds
+
+        Override "mov[l|q]".  */
+      char *p = obuf + strlen (obuf) - 1;
+
+      /* We might not have a suffix.  */
+      if (*p == 'v')
+       ++p;
+      *p = 'w';
+    }
+
+  OP_E (extrachar, sizeflag);
+}
+
+static void
+VMX_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
+{
+  if (mod == 3 && reg == 0 && rm >=1 && rm <= 4)
+    {
+      /* Override "sgdt".  */
+      char *p = obuf + strlen (obuf) - 4;
+
+      /* We might have a suffix when disassembling with -Msuffix.  */
+      if (*p == 'g')
+       --p;
+
+      switch (rm)
+       {
+       case 1:
+         strcpy (p, "vmcall");
+         break;
+       case 2:
+         strcpy (p, "vmlaunch");
+         break;
+       case 3:
+         strcpy (p, "vmresume");
+         break;
+       case 4:
+         strcpy (p, "vmxoff");
+         break;
+       }
+
+      codep++;
+    }
+  else
+    OP_E (0, sizeflag);
+}
+
+static void
+OP_VMX (int bytemode, int sizeflag)
+{
+  used_prefixes |= (prefixes & (PREFIX_DATA | PREFIX_REPZ));
+  if (prefixes & PREFIX_DATA)
+    strcpy (obuf, "vmclear");
+  else if (prefixes & PREFIX_REPZ)
+    strcpy (obuf, "vmxon");
+  else
+    strcpy (obuf, "vmptrld");
+  OP_E (bytemode, sizeflag);
+}
index 2685538..70fee0f 100644 (file)
@@ -35,13 +35,38 @@ static int crashing_cpu;
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
 static atomic_t waiting_for_crash_ipi;
 
+#ifdef CONFIG_KDB_KDUMP
+void halt_current_cpu(struct pt_regs *regs)
+{
+#ifdef CONFIG_X86_32
+       struct pt_regs fixed_regs;
+#endif
+       local_irq_disable();
+#ifdef CONFIG_X86_32
+       if (!user_mode_vm(regs)) {
+               crash_fixup_ss_esp(&fixed_regs, regs);
+               regs = &fixed_regs;
+       }
+#endif
+       crash_save_cpu(regs, raw_smp_processor_id());
+       disable_local_APIC();
+       atomic_dec(&waiting_for_crash_ipi);
+       /* Assume hlt works */
+       halt();
+       for(;;)
+               cpu_relax();
+}
+#endif /* CONFIG_KDB_KDUMP */
+
 static int crash_nmi_callback(struct notifier_block *self,
                        unsigned long val, void *data)
 {
        struct pt_regs *regs;
+#ifndef CONFIG_KDB_KDUMP
 #ifdef CONFIG_X86_32
        struct pt_regs fixed_regs;
 #endif
+#endif /* !CONFIG_KDB_KDUMP */
        int cpu;
 
        if (val != DIE_NMI_IPI)
@@ -56,6 +81,9 @@ static int crash_nmi_callback(struct notifier_block *self,
         */
        if (cpu == crashing_cpu)
                return NOTIFY_STOP;
+#ifdef CONFIG_KDB_KDUMP
+       halt_current_cpu(regs);
+#else
        local_irq_disable();
 
 #ifdef CONFIG_X86_32
@@ -71,6 +99,7 @@ static int crash_nmi_callback(struct notifier_block *self,
        halt();
        for (;;)
                cpu_relax();
+#endif /* !CONFIG_KDB_KDUMP */
 
        return 1;
 }
@@ -87,6 +116,43 @@ static struct notifier_block crash_nmi_nb = {
        .notifier_call = crash_nmi_callback,
 };
 
+#ifdef CONFIG_KDB_KDUMP
+static void wait_other_cpus(void)
+{
+       unsigned long msecs;
+
+       msecs = 1000; /* Wait at most a second for the other cpus to stop */
+       while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+               udelay(1000);
+       msecs--;
+       }
+}
+
+static void nmi_shootdown_cpus_init(void)
+{
+       atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+}
+
+static void nmi_shootdown_cpus(void)
+{
+       nmi_shootdown_cpus_init();
+
+       /* Would it be better to replace the trap vector here? */
+       if (register_die_notifier(&crash_nmi_nb))
+               return;         /* return what? */
+       /* Ensure the new callback function is set before sending
+        * out the NMI
+        */
+       wmb();
+
+       smp_send_nmi_allbutself();
+
+       wait_other_cpus();
+       /* Leave the nmi callback set */
+
+       disable_local_APIC();
+}
+#else
 static void nmi_shootdown_cpus(void)
 {
        unsigned long msecs;
@@ -111,12 +177,22 @@ static void nmi_shootdown_cpus(void)
        /* Leave the nmi callback set */
        disable_local_APIC();
 }
-#else
+#endif /* !CONFIG_KDB_KDUMP */
+
+#else /* defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) */
+
 static void nmi_shootdown_cpus(void)
 {
        /* There are no cpus to shootdown */
 }
-#endif
+
+#ifdef CONFIG_KDB_KDUMP
+static void nmi_shootdown_cpus_init(void) {};
+static void wait_other_cpus() {}
+static void halt_current_cpu(struct pt_regs *regs) {};
+#endif /* CONFIG_KDB_KDUMP */
+
+#endif /* defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) */
 
 void native_machine_crash_shutdown(struct pt_regs *regs)
 {
@@ -143,3 +219,33 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
 #endif
        crash_save_cpu(regs, safe_smp_processor_id());
 }
+
+#ifdef CONFIG_KDB_KDUMP
+void machine_crash_shutdown_begin(void)
+{
+       local_irq_disable();
+
+       /* Make a note of crashing cpu. Will be used in NMI callback.*/
+       crashing_cpu = safe_smp_processor_id();
+#ifndef CONFIG_XEN
+       nmi_shootdown_cpus_init();
+#endif /* CONFIG_XEN */
+}
+
+void machine_crash_shutdown_end(struct pt_regs *regs)
+{
+#ifndef CONFIG_XEN
+       wait_other_cpus();
+
+       local_irq_disable();
+       lapic_shutdown();
+#if defined(CONFIG_X86_IO_APIC)
+       disable_IO_APIC();
+#endif
+#ifdef CONFIG_HPET_TIMER
+       hpet_disable();
+#endif
+#endif /* CONFIG_XEN */
+       crash_save_cpu(regs,safe_smp_processor_id());
+}
+#endif /* CONFIG_KDB_KDUMP */
index 109792b..40981e9 100644 (file)
@@ -1015,6 +1015,26 @@ ENTRY(alignment_check)
        CFI_ENDPROC
 END(alignment_check)
 
+#ifdef CONFIG_KDB
+
+ENTRY(kdb_call)
+       RING0_INT_FRAME
+       pushl %eax              # save orig EAX
+       CFI_ADJUST_CFA_OFFSET 4
+       SAVE_ALL
+       movl %esp,%ecx          # struct pt_regs
+       movl $0,%edx            # error_code
+       movl $1,%eax            # KDB_REASON_ENTER
+       call  kdb
+       jmp restore_all
+       CFI_ENDPROC
+
+#ifdef CONFIG_SMP
+BUILD_INTERRUPT(kdb_interrupt,KDB_VECTOR)
+#endif /* CONFIG_SMP */
+
+#endif /* CONFIG_KDB */
+
 ENTRY(divide_error)
        RING0_INT_FRAME
        pushl $0                        # no error code
index 89434d4..290c058 100644 (file)
@@ -1467,3 +1467,30 @@ ENTRY(xen_failsafe_callback)
 END(xen_failsafe_callback)
 
 #endif /* CONFIG_XEN */
+
+#ifdef CONFIG_KDB
+
+#ifdef CONFIG_SMP
+ENTRY(kdb_interrupt)
+       apicinterrupt KDB_VECTOR,smp_kdb_interrupt
+END(kdb_interrupt)
+#endif /* CONFIG_SMP */
+
+ENTRY(kdb_call)
+       INTR_FRAME
+       cld
+       pushq $-1                       # orig_eax
+       CFI_ADJUST_CFA_OFFSET 8
+       SAVE_ALL
+       movq $1,%rdi                    # KDB_REASON_ENTER
+       movq $0,%rsi                    # error_code
+       movq %rsp,%rdx                  # struct pt_regs
+       call kdb
+       RESTORE_ALL
+       addq $8,%rsp                    # forget orig_eax
+       CFI_ADJUST_CFA_OFFSET -8
+       iretq
+       CFI_ENDPROC
+END(kdb_call)
+
+#endif /* CONFIG_KDB */
index 09cddb5..7e63c83 100644 (file)
 #include <linux/sysdev.h>
 #include <linux/pci.h>
 #include <linux/msi.h>
+
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
 #include <linux/htirq.h>
 #include <linux/freezer.h>
 #include <linux/kthread.h>
@@ -1189,6 +1193,10 @@ next:
                return -ENOSPC;
        if (test_and_set_bit(vector, used_vectors))
                goto next;
+#ifdef CONFIG_KDB
+       if (vector == KDBENTER_VECTOR)
+               goto next;
+#endif
 
        current_vector = vector;
        current_offset = offset;
index 61a83b7..d2cab6a 100644 (file)
 #endif
 #include <linux/bootmem.h>
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
+
 #include <asm/idle.h>
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -766,6 +770,10 @@ next:
                        continue;
                if (vector == IA32_SYSCALL_VECTOR)
                        goto next;
+#ifdef CONFIG_KDB
+               if (vector == KDBENTER_VECTOR)
+                       goto next;
+#endif /* CONFIG_KDB */
                for_each_cpu_mask_nr(new_cpu, new_mask)
                        if (per_cpu(vector_irq, new_cpu)[vector] != -1)
                                goto next;
index 724adfc..d4efb7f 100644 (file)
@@ -3,6 +3,9 @@
 #include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/efi.h>
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
 #include <acpi/reboot.h>
 #include <asm/io.h>
 #include <asm/apic.h>
@@ -429,6 +432,14 @@ void native_machine_shutdown(void)
        /* Make certain I only run on the appropriate processor */
        set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id));
 
+#if defined(CONFIG_X86_32) && defined(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 /* defined(CONFIG_X86_32) && defined(CONFIG_KDB) */
        /* O.K Now that I'm on the appropriate processor,
         * stop all of the others.
         */
index d0c845f..9478003 100644 (file)
 #include <linux/edac.h>
 #endif
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
+
 #include <asm/arch_hooks.h>
 #include <asm/stacktrace.h>
 #include <asm/processor.h>
@@ -395,6 +399,9 @@ void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
        add_taint(TAINT_DIE);
        __raw_spin_unlock(&die_lock);
        raw_local_irq_restore(flags);
+#ifdef CONFIG_KDB
+       kdb(KDB_REASON_OOPS, signr, regs);
+#endif /* CONFIG_KDB */
 
        if (!regs)
                return;
@@ -465,6 +472,9 @@ void die(const char *str, struct pt_regs *regs, long err)
                printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
        }
 
+#ifdef CONFIG_KDB
+       kdb_diemsg = str;
+#endif /* CONFIG_KDB */
        oops_end(flags, regs, SIGSEGV);
 }
 
@@ -575,7 +585,7 @@ void do_##name(struct pt_regs *regs, long error_code)                       \
 }
 
 DO_VM86_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
-#ifndef CONFIG_KPROBES
+#if !defined(CONFIG_KPROBES) && !defined(CONFIG_KDB)
 DO_VM86_ERROR(3, SIGTRAP, "int3", int3)
 #endif
 DO_VM86_ERROR(4, SIGSEGV, "overflow", overflow)
@@ -718,6 +728,10 @@ io_check_error(unsigned char reason, struct pt_regs *regs)
 static notrace __kprobes void
 unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
 {
+#ifdef CONFIG_KDB
+       (void)kdb(KDB_REASON_NMI, reason, regs);
+#endif /* CONFIG_KDB */
+
        if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
                return;
 #ifdef CONFIG_MCA
@@ -758,6 +772,9 @@ void notrace __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
        printk(" on CPU%d, ip %08lx, registers:\n",
                smp_processor_id(), regs->ip);
        show_registers(regs);
+#ifdef CONFIG_KDB
+       kdb(KDB_REASON_NMI, 0, regs);
+#endif /* CONFIG_KDB */
        if (do_panic)
                panic("Non maskable interrupt");
        console_silent();
@@ -787,6 +804,16 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
        if (!cpu)
                reason = get_nmi_reason();
 
+#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, NULL)) {
+               return;
+       }
+#endif /* defined(CONFIG_SMP) && defined(CONFIG_KDB) */
+
        if (!(reason & 0xc0)) {
                if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
                                                                == NOTIFY_STOP)
@@ -854,6 +881,10 @@ void __kprobes do_int3(struct pt_regs *regs, long error_code)
 {
        trace_hardirqs_fixup();
 
+#ifdef  CONFIG_KDB
+       if (kdb(KDB_REASON_BREAK, error_code, regs))
+               return;
+#endif
        if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
                        == NOTIFY_STOP)
                return;
@@ -904,6 +935,11 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code)
        clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
        tsk->thread.debugctlmsr = 0;
 
+#ifdef CONFIG_KDB
+       if (kdb(KDB_REASON_DEBUG, error_code, regs))
+               return;
+#endif /* CONFIG_KDB */
+
        if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
                                                SIGTRAP) == NOTIFY_STOP)
                return;
@@ -958,6 +994,16 @@ clear_TF_reenable:
        return;
 }
 
+#if    defined(CONFIG_KDB) && !defined(CONFIG_KPROBES)
+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 && !CONFIG_KPROBES */
+
+
 /*
  * Note that we play around with the 'TS' bit in an attempt to get
  * the correct behaviour even in the presence of the asynchronous
index 037ba5c..cb15b15 100644 (file)
@@ -583,6 +583,8 @@ die_nmi(char *str, struct pt_regs *regs, int do_panic)
        printk(" on CPU%d, ip %08lx, registers:\n",
                smp_processor_id(), regs->ip);
        show_registers(regs);
+       if (strncmp(str, "NMI Watchdog", 12) == 0)
+               notify_die(DIE_NMIWATCHDOG, "nmi_watchdog", regs, 0, 2, SIGINT);
        if (kexec_should_crash(current))
                crash_kexec(regs);
        if (do_panic || panic_on_oops)
index 9597648..40b8096 100644 (file)
@@ -43,6 +43,9 @@
 #include <linux/reboot.h>
 #include <linux/notifier.h>
 #include <linux/jiffies.h>
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
 
 extern void ctrl_alt_del(void);
 
@@ -1180,6 +1183,13 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
                        if (keycode < BTN_MISC && printk_ratelimit())
                                printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
 
+#ifdef CONFIG_KDB
+       if (down && !rep && keycode == KEY_PAUSE && kdb_on == 1) {
+               kdb(KDB_REASON_KEYBOARD, 0, get_irq_regs());
+               return;
+       }
+#endif /* CONFIG_KDB */
+
 #ifdef CONFIG_BOOTSPLASH
        /* This code has to be redone for some non-x86 platforms */
        if (down == 1 && (keycode == 0x3c || keycode == 0x01)) {        /* F2 and ESC on PC keyboard */
index 27fe4d8..0bcc05e 100644 (file)
 #define DRIVER_DESC "USB HID core driver"
 #define DRIVER_LICENSE "GPL"
 
+#ifdef CONFIG_KDB_USB
+#include <linux/kdb.h>
+#endif
+
 static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
                                "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
 /*
@@ -940,6 +944,15 @@ static void hid_disconnect(struct usb_interface *intf)
 
        usbhid = hid->driver_data;
 
+#ifdef CONFIG_KDB_USB
+       /*
+        * If the URB was for a Keyboard, detach it from kdb.
+        * If the URB was for another type of device, just
+        * allow kdb_usb_keyboard_detach() to silently fail.
+        */
+       kdb_usb_keyboard_detach(usbhid->urbin);
+#endif
+
        spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
        usb_set_intfdata(intf, NULL);
        set_bit(HID_DISCONNECTED, &usbhid->iofl);
@@ -1037,6 +1050,21 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
        printk(": USB HID v%x.%02x %s [%s] on %s\n",
                hid->version >> 8, hid->version & 0xff, c, hid->name, path);
 
+#ifdef CONFIG_KDB_USB
+       /* Attach USB keyboards to kdb */
+       if (!strcmp(c, "Keyboard")) {
+               int     ret;
+               struct usbhid_device *usbhid = hid->driver_data;
+               extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev);
+               ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf,
+                   usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)));
+
+               if (ret == -1)
+                       printk(": FAILED to register keyboard (%s) "
+                              "with KDB\n", path);
+       }
+#endif /* CONFIG_KDB_USB */
+
        return 0;
 }
 
index 0caaafe..e899695 100644 (file)
@@ -30,6 +30,9 @@
 #include <linux/init.h>
 #include <linux/usb/input.h>
 #include <linux/hid.h>
+#ifdef CONFIG_KDB_USB
+#include <linux/kdb.h>
+#endif
 
 /*
  * Version Information
@@ -289,6 +292,16 @@ static int usb_kbd_probe(struct usb_interface *iface,
        usb_fill_int_urb(kbd->irq, dev, pipe,
                         kbd->new, (maxp > 8 ? 8 : maxp),
                         usb_kbd_irq, kbd, endpoint->bInterval);
+
+#ifdef CONFIG_KDB_USB
+       /* Attach keyboard to kdb */
+       extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev);
+
+       kdb_usb_keyboard_attach(kbd->irq, kbd->new,
+                               usb_hcd_get_kdb_poll_func(dev));
+
+#endif /* CONFIG_KDB_USB */
+
        kbd->irq->transfer_dma = kbd->new_dma;
        kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -326,6 +339,10 @@ static void usb_kbd_disconnect(struct usb_interface *intf)
 
        usb_set_intfdata(intf, NULL);
        if (kbd) {
+#ifdef CONFIG_KDB_USB
+              /* Detach the keyboard from kdb */
+               kdb_usb_keyboard_detach(kbd->irq);
+#endif /* CONFIG_KDB_USB */
                usb_kill_urb(kbd->irq);
                input_unregister_device(kbd->dev);
                usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
index 342e12f..9889669 100644 (file)
 #include <asm/irq.h>
 
 #include "8250.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;
+#else
+#define KDB_8250() 0
+#endif /* CONFIG_KDB */
 
 /*
  * Configuration:
@@ -1304,6 +1319,20 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
                         * just force the read character to be 0
                         */
                        ch = 0;
+#ifdef CONFIG_KDB
+               if ((up->port.line == kdb_serial_line) && kdb_on == 1) {
+                   if (ch == *kdb_serial_ptr) {
+                       if (!(*++kdb_serial_ptr)) {
+                               atomic_inc(&kdb_8250);
+                               kdb(KDB_REASON_KEYBOARD, 0, get_irq_regs());
+                               atomic_dec(&kdb_8250);
+                               kdb_serial_ptr = kdb_serial_str;
+                               break;
+                       }
+                   } else
+                       kdb_serial_ptr = kdb_serial_str;
+               }
+#endif /* CONFIG_KDB */
 
                flag = TTY_NORMAL;
                up->port.icount.rx++;
@@ -2553,7 +2582,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
        if (up->port.sysrq) {
                /* serial8250_handle_port() already took the lock */
                locked = 0;
-       } else if (oops_in_progress) {
+       } else if (oops_in_progress || KDB_8250()) {
                locked = spin_trylock(&up->port.lock);
        } else
                spin_lock(&up->port.lock);
@@ -2611,6 +2640,30 @@ static int __init serial8250_console_setup(struct console *co, char *options)
        if (!port->iobase && !port->membase)
                return -ENODEV;
 
+#ifdef CONFIG_KDB
+       /*
+        * Remember the line number of the first serial
+        * console.  We'll make this the kdb serial console too.
+        */
+       if (co && kdb_serial_line == -1) {
+               kdb_serial_line = co->index;
+               kdb_serial.io_type = port->iotype;
+               switch (port->iotype) {
+               case SERIAL_IO_MEM:
+#ifdef  SERIAL_IO_MEM32
+               case SERIAL_IO_MEM32:
+#endif
+                       kdb_serial.iobase = (unsigned long)(port->membase);
+                       kdb_serial.ioreg_shift = port->regshift;
+                       break;
+               default:
+                       kdb_serial.iobase = port->iobase;
+                       kdb_serial.ioreg_shift = 0;
+                       break;
+               }
+       }
+#endif /* CONFIG_KDB */
+
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
 
index f279745..7df450c 100644 (file)
 #include <asm/fixmap.h>
 #endif
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+static int  kdb_serial_line = -1;
+#endif /* CONFIG_KDB */
+
 struct early_serial8250_device {
        struct uart_port port;
        char options[16];               /* e.g., 115200n8 */
@@ -231,6 +236,30 @@ int __init setup_early_serial8250_console(char *cmdline)
 
        register_console(&early_serial8250_console);
 
+#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 = early_serial8250_console.index;
+               kdb_serial.io_type = early_device.port.iotype;
+               switch (early_device.port.iotype) {
+               case SERIAL_IO_MEM:
+#ifdef  SERIAL_IO_MEM32
+               case SERIAL_IO_MEM32:
+#endif
+                       kdb_serial.iobase = (unsigned long)(early_device.port.membase);
+                       kdb_serial.ioreg_shift = early_device.port.regshift;
+                       break;
+               default:
+                       kdb_serial.iobase = early_device.port.iobase;
+                       kdb_serial.ioreg_shift = 0;
+                       break;
+               }
+       }
+#endif /* CONFIG_KDB */
+
        return 0;
 }
 
index b73e3c0..12c59ab 100644 (file)
 #include <linux/delay.h> /* for mdelay */
 #include <linux/miscdevice.h>
 #include <linux/serial_core.h>
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/serial_reg.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 char *kdb_serial_ptr = (char *)kdb_serial_str;
+#endif /* CONFIG_KDB */
+
 
 #include <asm/io.h>
 #include <asm/sn/simulator.h>
@@ -485,6 +501,26 @@ sn_receive_chars(struct sn_cons_port *port, unsigned long flags)
                               "obtaining data from the console (0x%0x)\n", ch);
                        break;
                }
+#ifdef CONFIG_KDB
+       if (kdb_on == 1) {
+               if (ch == *kdb_serial_ptr) {
+                       if (!(*++kdb_serial_ptr)) {
+                               spin_unlock_irqrestore(&port->sc_port.lock, flags);
+                               if (!get_irq_regs()) {
+                                       KDB_STATE_SET(KEYBOARD);
+                                       KDB_ENTER();   /* to get some registers */
+                               } else
+                                       kdb(KDB_REASON_KEYBOARD, 0, get_irq_regs());
+                               kdb_serial_ptr = (char *)kdb_serial_str;
+                               spin_lock_irqsave(&port->sc_port.lock, flags);
+                               break;
+                       }
+               }
+               else
+                       kdb_serial_ptr = (char *)kdb_serial_str;
+       }
+#endif /* CONFIG_KDB */
+
 #ifdef CONFIG_MAGIC_SYSRQ
                 if (sysrq_requested) {
                         unsigned long sysrq_timeout = sysrq_requested + HZ*5;
@@ -1008,6 +1044,15 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count)
  */
 static int sn_sal_console_setup(struct console *co, char *options)
 {
+#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;
 }
 
@@ -1083,3 +1128,31 @@ static int __init sn_sal_serial_console_init(void)
 }
 
 console_initcall(sn_sal_serial_console_init);
+
+#ifdef CONFIG_KDB
+int
+l1_control_in_polled(int offset)
+{
+       int sal_call_status = 0, input;
+       int ret = 0;
+       if (offset == UART_LSR) {
+               ret = (UART_LSR_THRE | UART_LSR_TEMT);  /* can send anytime */
+               sal_call_status = ia64_sn_console_check(&input);
+               if (!sal_call_status && input) {
+                       /* input pending */
+                       ret |= UART_LSR_DR;
+               }
+       }
+       return ret;
+}
+
+int
+l1_serial_in_polled(void)
+{
+       int ch;
+       if (!ia64_sn_console_getc(&ch))
+               return ch;
+       else
+               return 0;
+}
+#endif /* CONFIG_KDB */
index f7bfd72..d51eb00 100644 (file)
@@ -2002,6 +2002,20 @@ usb_hcd_platform_shutdown(struct platform_device* dev)
 }
 EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown);
 
+#ifdef CONFIG_KDB_USB
+void *
+usb_hcd_get_kdb_poll_func(struct usb_device *udev)
+{
+       struct usb_hcd  *hcd = bus_to_hcd(udev->bus);
+
+       if (hcd && hcd->driver)
+               return (void *)(hcd->driver->kdb_poll_char);
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func);
+#endif /* CONFIG_KDB_USB */
+
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_USB_MON)
index 5b0b59b..c6d3216 100644 (file)
@@ -219,6 +219,10 @@ struct hc_driver {
        void    (*relinquish_port)(struct usb_hcd *, int);
                /* has a port been handed over to a companion? */
        int     (*port_handed_over)(struct usb_hcd *, int);
+#ifdef CONFIG_KDB_USB
+       /* KDB poll function for this HC */
+       int     (*kdb_poll_char)(struct urb *urb);
+#endif /* CONFIG_KDB_USB */
 };
 
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
index d9d53f2..59cc052 100644 (file)
@@ -986,6 +986,48 @@ static int ehci_get_frame (struct usb_hcd *hcd)
                ehci->periodic_size;
 }
 
+#ifdef CONFIG_KDB_USB
+
+int
+ehci_kdb_poll_char(struct urb *urb)
+{
+        struct ehci_hcd *ehci;
+
+        /* just to make sure */
+        if (!urb || !urb->dev || !urb->dev->bus)
+                return -1;
+
+        ehci = (struct ehci_hcd *) hcd_to_ehci(bus_to_hcd(urb->dev->bus));
+
+        /* make sure */
+        if (!ehci)
+                return -1;
+
+        if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
+                return -1;
+
+       /*
+        * If ehci->lock is held coming into this routine, it could
+        * mean KDB was entered while the HC driver was in the midst
+        * of processing URBs. Therefore it could be dangerous to
+        * processes URBs from this poll routine. And, we can't wait on
+        * the lock since we are in KDB and kernel threads (including the
+        * one holding the lock) are suspended.
+        * So, we punt and return an error. Keyboards attached to this
+        * HC will not be useable from KDB at this time.
+        */
+       if (spin_is_locked(&ehci->lock))
+               return -EBUSY;
+
+       /* processes the URB */
+        if (qh_completions_kdb(ehci, urb->hcpriv, urb))
+                return 0;
+
+        return -1;
+}
+
+#endif /* CONFIG_KDB_USB */
+
 /*-------------------------------------------------------------------------*/
 
 #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
index c46a58f..9a0db19 100644 (file)
 #error "This file is PCI bus glue.  CONFIG_PCI must be defined."
 #endif
 
+#ifdef CONFIG_KDB_USB
+#include <linux/kdb.h>
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 /* called after powerup, by probe or system-pm "wakeup" */
@@ -380,6 +384,10 @@ static const struct hc_driver ehci_pci_hc_driver = {
        .bus_resume =           ehci_bus_resume,
        .relinquish_port =      ehci_relinquish_port,
        .port_handed_over =     ehci_port_handed_over,
+
+#ifdef CONFIG_KDB_USB
+       .kdb_poll_char =        ehci_kdb_poll_char,
+#endif
 };
 
 /*-------------------------------------------------------------------------*/
index 3712b92..5544b0c 100644 (file)
@@ -468,6 +468,228 @@ halt:
        return count;
 }
 
+#ifdef CONFIG_KDB_USB
+/*
+ * This routine is basically a copy of qh_completions() for use by KDB.
+ * It is modified to only work on qtds which are associated
+ * with 'kdburb'. Also, there are some fixups related to locking.
+ */
+unsigned
+qh_completions_kdb(struct ehci_hcd *ehci, struct ehci_qh *qh, struct urb *kdburb)
+{
+       struct ehci_qtd         *last = NULL, *end = qh->dummy;
+       struct list_head        *entry, *tmp;
+       int                     last_status = -EINPROGRESS;
+       int                     stopped;
+       unsigned                count = 0;
+       int                     do_status = 0;
+       u8                      state;
+       u32                     halt = HALT_BIT(ehci);
+
+        /* verify params are valid */
+        if (!qh || !kdburb)
+                return 0;
+
+       if (unlikely (list_empty (&qh->qtd_list)))
+               return count;
+
+       /* completions (or tasks on other cpus) must never clobber HALT
+        * till we've gone through and cleaned everything up, even when
+        * they add urbs to this qh's queue or mark them for unlinking.
+        *
+        * NOTE:  unlinking expects to be done in queue order.
+        */
+       state = qh->qh_state;
+       qh->qh_state = QH_STATE_COMPLETING;
+       stopped = (state == QH_STATE_IDLE);
+
+       /* remove de-activated QTDs from front of queue.
+        * after faults (including short reads), cleanup this urb
+        * then let the queue advance.
+        * if queue is stopped, handles unlinks.
+        */
+       list_for_each_safe (entry, tmp, &qh->qtd_list) {
+               struct ehci_qtd *qtd;
+               struct urb      *urb;
+               u32             token = 0;
+               int             qtd_status;
+
+               qtd = list_entry (entry, struct ehci_qtd, qtd_list);
+               urb = qtd->urb;
+
+                if (urb != kdburb)
+                        continue;
+
+               /* clean up any state from previous QTD ...*/
+               if (last) {
+                       if (likely (last->urb != urb)) {
+                               /*
+                                * Lock hackery here...
+                                * ehci_urb_done() makes the assumption
+                                * that it's called with ehci->lock held.
+                                * So, lock it if it isn't already.
+                                */
+                               if (!spin_is_locked(&ehci->lock))
+                                       spin_lock(&ehci->lock);
+
+                               ehci_urb_done(ehci, last->urb, last_status);
+
+                                /*
+                                 * ehci_urb_done() releases and reacquires
+                                * ehci->lock, so release it here.
+                                 */
+                                if (spin_is_locked(&ehci->lock))
+                                        spin_unlock (&ehci->lock);
+
+                               count++;
+                       }
+                       ehci_qtd_free (ehci, last);
+                       last = NULL;
+                       last_status = -EINPROGRESS;
+               }
+
+               /* ignore urbs submitted during completions we reported */
+               if (qtd == end)
+                       break;
+
+               /* hardware copies qtd out of qh overlay */
+               rmb ();
+               token = hc32_to_cpu(ehci, qtd->hw_token);
+
+               /* always clean up qtds the hc de-activated */
+               if ((token & QTD_STS_ACTIVE) == 0) {
+
+                       if ((token & QTD_STS_HALT) != 0) {
+                               stopped = 1;
+
+                       /* magic dummy for some short reads; qh won't advance.
+                        * that silicon quirk can kick in with this dummy too.
+                        */
+                       } else if (IS_SHORT_READ (token)
+                                       && !(qtd->hw_alt_next
+                                               & EHCI_LIST_END(ehci))) {
+                               stopped = 1;
+                               goto halt;
+                       }
+
+               /* stop scanning when we reach qtds the hc is using */
+               } else if (likely (!stopped
+                               && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
+                       break;
+
+               } else {
+                       stopped = 1;
+
+                       if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)))
+                               last_status = -ESHUTDOWN;
+
+                       /* ignore active urbs unless some previous qtd
+                        * for the urb faulted (including short read) or
+                        * its urb was canceled.  we may patch qh or qtds.
+                        */
+                       if (likely(last_status == -EINPROGRESS &&
+                                       !urb->unlinked))
+                               continue;
+
+                       /* issue status after short control reads */
+                       if (unlikely (do_status != 0)
+                                       && QTD_PID (token) == 0 /* OUT */) {
+                               do_status = 0;
+                               continue;
+                       }
+
+                       /* token in overlay may be most current */
+                       if (state == QH_STATE_IDLE
+                                       && cpu_to_hc32(ehci, qtd->qtd_dma)
+                                               == qh->hw_current)
+                               token = hc32_to_cpu(ehci, qh->hw_token);
+
+                       /* force halt for unlinked or blocked qh, so we'll
+                        * patch the qh later and so that completions can't
+                        * activate it while we "know" it's stopped.
+                        */
+                       if ((halt & qh->hw_token) == 0) {
+halt:
+                               qh->hw_token |= halt;
+                               wmb ();
+                       }
+               }
+
+               /* remove it from the queue */
+               qtd_status = qtd_copy_status(ehci, urb, qtd->length, token);
+               if (unlikely(qtd_status == -EREMOTEIO)) {
+                       do_status = (!urb->unlinked &&
+                                       usb_pipecontrol(urb->pipe));
+                       qtd_status = 0;
+               }
+               if (likely(last_status == -EINPROGRESS))
+                       last_status = qtd_status;
+
+               if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
+                       last = list_entry (qtd->qtd_list.prev,
+                                       struct ehci_qtd, qtd_list);
+                       last->hw_next = qtd->hw_next;
+               }
+               list_del (&qtd->qtd_list);
+               last = qtd;
+       }
+
+       /* last urb's completion might still need calling */
+       if (likely (last != NULL)) {
+               /*
+                * Lock hackery here...
+                * ehci_urb_done() makes the assumption
+                * that it's called with ehci->lock held.
+                * So, lock it if it isn't already.
+                */
+               if (!spin_is_locked(&ehci->lock))
+                       spin_lock(&ehci->lock);
+
+               ehci_urb_done(ehci, last->urb, last_status);
+
+               /*
+                * ehci_urb_done() releases and reacquires
+                * ehci->lock, so release it here.
+                */
+                if (spin_is_locked(&ehci->lock))
+                       spin_unlock (&ehci->lock);
+
+               count++;
+               ehci_qtd_free (ehci, last);
+       }
+
+       /* restore original state; caller must unlink or relink */
+       qh->qh_state = state;
+
+       /* be sure the hardware's done with the qh before refreshing
+        * it after fault cleanup, or recovering from silicon wrongly
+        * overlaying the dummy qtd (which reduces DMA chatter).
+        */
+       if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) {
+               switch (state) {
+               case QH_STATE_IDLE:
+                       qh_refresh(ehci, qh);
+                       break;
+               case QH_STATE_LINKED:
+                       /* should be rare for periodic transfers,
+                        * except maybe high bandwidth ...
+                        */
+                       if ((cpu_to_hc32(ehci, QH_SMASK)
+                                       & qh->hw_info2) != 0) {
+                               intr_deschedule (ehci, qh);
+                               (void) qh_schedule (ehci, qh);
+                       } else
+                               unlink_async (ehci, qh);
+                       break;
+               /* otherwise, unlink already started */
+               }
+       }
+
+       return count;
+}
+
+#endif /* CONFIG_KDB_USB */
+
 /*-------------------------------------------------------------------------*/
 
 // high bandwidth multiplier, as encoded in highspeed endpoint descriptors
index 26bc479..859bbad 100644 (file)
@@ -963,6 +963,73 @@ static int ohci_restart (struct ohci_hcd *ohci)
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_KDB_USB
+
+int
+ohci_kdb_poll_char(struct urb *urb)
+{
+       struct ohci_hcd *ohci;
+       struct ohci_regs * regs;
+
+        /* just to make sure */
+        if (!urb || !urb->dev || !urb->dev->bus)
+                return -1;
+
+       ohci = (struct ohci_hcd *) hcd_to_ohci(bus_to_hcd(urb->dev->bus));
+
+        /* make sure */
+        if (!ohci || !ohci->hcca)
+                return -1;
+
+        if (!HC_IS_RUNNING (ohci_to_hcd(ohci)->state))
+                return -1;
+
+       /*
+        * If ohci->lock is held coming into this routine, it could
+        * mean KDB was entered while the HC driver was in the midst
+        * of processing URBs. Therefore it could be dangerous to
+        * processes URBs from this poll routine. And, we can't wait on
+        * the lock since we are in KDB and kernel threads (including the
+        * one holding the lock) are suspended.
+        * So, we punt and return an error. Keyboards attached to this
+        * HC will not be useable from KDB at this time.
+        */
+       if (spin_is_locked(&ohci->lock))
+               return -EBUSY;
+
+       regs = ohci->regs;
+
+       /* if the urb is not currently in progress resubmit it */
+       if (urb->status != -EINPROGRESS) {
+
+               if (usb_submit_urb (urb, GFP_ATOMIC))
+                       return -1;
+
+               /* make sure the HC registers are set correctly */
+               ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
+               ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrstatus);
+               ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
+
+               // flush those pci writes
+               (void) ohci_readl (ohci, &ohci->regs->control);
+       }
+
+       if (ohci->hcca->done_head) {
+               dl_done_list_kdb (ohci, urb);
+               ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrstatus);
+               // flush the pci write
+               (void) ohci_readl (ohci, &ohci->regs->control);
+
+               return 0;
+       }
+
+       return -1;
+}
+
+#endif /* CONFIG_KDB_USB */
+
+/*-------------------------------------------------------------------------*/
+
 #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
 
 MODULE_AUTHOR (DRIVER_AUTHOR);
index 4696cc9..370cfc4 100644 (file)
 #error "This file is PCI bus glue.  CONFIG_PCI must be defined."
 #endif
 
+#ifdef CONFIG_KDB_USB
+#include <linux/kdb.h>
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int broken_suspend(struct usb_hcd *hcd)
@@ -235,6 +239,7 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
                ohci_err (ohci, "can't start\n");
                ohci_stop (hcd);
        }
+
        return ret;
 }
 
@@ -333,6 +338,9 @@ static const struct hc_driver ohci_pci_hc_driver = {
        .bus_resume =           ohci_bus_resume,
 #endif
        .start_port_reset =     ohci_start_port_reset,
+#ifdef CONFIG_KDB_USB
+       .kdb_poll_char =        ohci_kdb_poll_char,
+#endif
 };
 
 /*-------------------------------------------------------------------------*/
index 6a9b4c5..c2db7ee 100644 (file)
@@ -1121,3 +1121,65 @@ dl_done_list (struct ohci_hcd *ohci)
                td = td_next;
        }
 }
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_KDB_USB
+static void
+dl_done_list_kdb (struct ohci_hcd *ohci, struct urb *kdburb)
+{
+       struct td       *td = dl_reverse_done_list (ohci);
+
+       while (td) {
+               struct td       *td_next = td->next_dl_td;
+               struct urb      *urb = td->urb;
+               urb_priv_t      *urb_priv = urb->hcpriv;
+               struct ed       *ed = td->ed;
+
+               if (urb != kdburb) {
+                       td = td_next;
+                       continue;
+               }
+
+               /* update URB's length and status from TD */
+               td_done (ohci, urb, td);
+               urb_priv->td_cnt++;
+
+               /* If all this urb's TDs are done, just resubmit it */
+               if (urb_priv->td_cnt == urb_priv->length) {
+                       urb->actual_length = 0;
+                       urb->status = -EINPROGRESS;
+                       td_submit_urb (ohci, urb);
+               }
+
+               /* clean schedule:  unlink EDs that are no longer busy */
+               if (list_empty (&ed->td_list)) {
+                       if (ed->state == ED_OPER)
+                               start_ed_unlink (ohci, ed);
+
+               /* ... reenabling halted EDs only after fault cleanup */
+               } else if ((ed->hwINFO & cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE))
+                                       == cpu_to_hc32 (ohci, ED_SKIP)) {
+                       td = list_entry (ed->td_list.next, struct td, td_list);
+                       if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) {
+                               ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP);
+                               /* ... hc may need waking-up */
+                               switch (ed->type) {
+                               case PIPE_CONTROL:
+                                       ohci_writel (ohci, OHCI_CLF,
+                                               &ohci->regs->cmdstatus);
+                                       break;
+                               case PIPE_BULK:
+                                       ohci_writel (ohci, OHCI_BLF,
+                                               &ohci->regs->cmdstatus);
+                                       break;
+                               }
+                       }
+               }
+
+               td = td_next;
+       }
+}
+
+#endif /* CONFIG_KDB_USB */
index 8ae221d..b00b766 100644 (file)
 #include <asm/pgtable.h>
 #include "internal.h"
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif
+
 void get_vmalloc_info(struct vmalloc_info *vmi)
 {
        struct vm_struct *vma;
        unsigned long free_area_size;
        unsigned long prev_end;
+#ifdef CONFIG_KDB
+       int get_lock = !KDB_IS_RUNNING();
+#else
+#define        get_lock 1
+#endif
+
 
        vmi->used = 0;
 
@@ -30,7 +40,8 @@ void get_vmalloc_info(struct vmalloc_info *vmi)
 
                prev_end = VMALLOC_START;
 
-               read_lock(&vmlist_lock);
+               if (get_lock)
+                       read_lock(&vmlist_lock);
 
                for (vma = vmlist; vma; vma = vma->next) {
                        unsigned long addr = (unsigned long) vma->addr;
@@ -55,6 +66,7 @@ void get_vmalloc_info(struct vmalloc_info *vmi)
                if (VMALLOC_END - prev_end > vmi->largest_chunk)
                        vmi->largest_chunk = VMALLOC_END - prev_end;
 
-               read_unlock(&vmlist_lock);
+               if (get_lock)
+                       read_unlock(&vmlist_lock);
        }
 }
index ded9698..88e2eb7 100644 (file)
@@ -232,6 +232,120 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
 #undef K
 }
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+/* Like meminfo_read_proc() but without the locks and using kdb_printf() */
+void
+kdb_meminfo_read_proc(void)
+{
+       struct sysinfo i;
+       unsigned long committed;
+       unsigned long allowed;
+       struct vmalloc_info vmi;
+       long cached;
+
+/*
+ * display in kilobytes.
+ */
+#define K(x) ((x) << (PAGE_SHIFT - 10))
+       si_meminfo(&i);
+       kdb_si_swapinfo(&i);
+       committed = atomic_read(&vm_committed_space);
+       allowed = ((totalram_pages - hugetlb_total_pages())
+               * sysctl_overcommit_ratio / 100) + total_swap_pages;
+
+       cached = global_page_state(NR_FILE_PAGES) -
+                       total_swapcache_pages - i.bufferram;
+       if (cached < 0)
+               cached = 0;
+
+       get_vmalloc_info(&vmi);
+
+       kdb_printf(
+               "MemTotal:     %8lu kB\n"
+               "MemFree:      %8lu kB\n"
+               "Buffers:      %8lu kB\n",
+               K(i.totalram),
+               K(i.freeram),
+               K(i.bufferram)
+               );
+       kdb_printf(
+               "Cached:       %8lu kB\n"
+               "SwapCached:   %8lu kB\n"
+               "Active:       %8lu kB\n"
+               "Inactive:     %8lu kB\n",
+               K(cached),
+               K(total_swapcache_pages),
+               K(global_page_state(NR_ACTIVE)),
+               K(global_page_state(NR_INACTIVE))
+               );
+#ifdef CONFIG_HIGHMEM
+       kdb_printf(
+               "HighTotal:    %8lu kB\n"
+               "HighFree:     %8lu kB\n"
+               "LowTotal:     %8lu kB\n"
+               "LowFree:      %8lu kB\n",
+               K(i.totalhigh),
+               K(i.freehigh),
+               K(i.totalram-i.totalhigh),
+               K(i.freeram-i.freehigh)
+               );
+#endif
+       kdb_printf(
+               "SwapTotal:    %8lu kB\n"
+               "SwapFree:     %8lu kB\n"
+               "Dirty:        %8lu kB\n",
+               K(i.totalswap),
+               K(i.freeswap),
+               K(global_page_state(NR_FILE_DIRTY))
+               );
+       kdb_printf(
+               "Writeback:    %8lu kB\n"
+               "AnonPages:    %8lu kB\n"
+               "Mapped:       %8lu kB\n",
+               K(global_page_state(NR_WRITEBACK)),
+               K(global_page_state(NR_ANON_PAGES)),
+               K(global_page_state(NR_FILE_MAPPED))
+               );
+       kdb_printf(
+               "Slab:         %8lu kB\n"
+               "SReclaimable: %8lu kB\n"
+               "SUnreclaim:   %8lu kB\n",
+               K(global_page_state(NR_SLAB_RECLAIMABLE) +
+                               global_page_state(NR_SLAB_UNRECLAIMABLE)),
+               K(global_page_state(NR_SLAB_RECLAIMABLE)),
+               K(global_page_state(NR_SLAB_UNRECLAIMABLE))
+               );
+       kdb_printf(
+               "PageTables:   %8lu kB\n"
+               "NFS_Unstable: %8lu kB\n"
+               "Bounce:       %8lu kB\n",
+               K(global_page_state(NR_PAGETABLE)),
+               K(global_page_state(NR_UNSTABLE_NFS)),
+               K(global_page_state(NR_BOUNCE))
+               );
+       kdb_printf(
+               "CommitLimit:  %8lu kB\n"
+               "Committed_AS: %8lu kB\n"
+               "VmallocTotal: %8lu kB\n",
+               K(allowed),
+               K(committed),
+               (unsigned long)VMALLOC_TOTAL >> 10
+               );
+       kdb_printf(
+               "VmallocUsed:  %8lu kB\n"
+               "VmallocChunk: %8lu kB\n",
+               vmi.used >> 10,
+               vmi.largest_chunk >> 10
+               );
+
+#ifdef CONFIG_HUGETLBFS
+       kdb_hugetlb_report_meminfo();
+#endif
+}
+#endif /* CONFIG_KDB */
+
 static int fragmentation_open(struct inode *inode, struct file *file)
 {
        (void)inode;
diff --git a/include/asm-x86/ansidecl.h b/include/asm-x86/ansidecl.h
new file mode 100644 (file)
index 0000000..6354d8b
--- /dev/null
@@ -0,0 +1,5 @@
+#ifdef CONFIG_X86_32
+# include "ansidecl_32.h"
+#else
+# include "ansidecl_64.h"
+#endif
diff --git a/include/asm-x86/ansidecl_32.h b/include/asm-x86/ansidecl_32.h
new file mode 100644 (file)
index 0000000..2033011
--- /dev/null
@@ -0,0 +1,383 @@
+/* ANSI and traditional C compatability macros
+   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+   Macro               ANSI C definition       Traditional C definition
+   -----               ---- - ----------       ----------- - ----------
+   ANSI_PROTOTYPES     1                       not defined
+   PTR                 `void *'                `char *'
+   PTRCONST            `void *const'           `char *'
+   LONG_DOUBLE         `long double'           `double'
+   const               not defined             `'
+   volatile            not defined             `'
+   signed              not defined             `'
+   VA_START(ap, var)   va_start(ap, var)       va_start(ap)
+
+   Note that it is safe to write "void foo();" indicating a function
+   with no return value, in all K+R compilers we have been able to test.
+
+   For declaring functions with prototypes, we also provide these:
+
+   PARAMS ((prototype))
+   -- for functions which take a fixed number of arguments.  Use this
+   when declaring the function.  When defining the function, write a
+   K+R style argument list.  For example:
+
+       char *strcpy PARAMS ((char *dest, char *source));
+       ...
+       char *
+       strcpy (dest, source)
+            char *dest;
+            char *source;
+       { ... }
+
+
+   VPARAMS ((prototype, ...))
+   -- for functions which take a variable number of arguments.  Use
+   PARAMS to declare the function, VPARAMS to define it.  For example:
+
+       int printf PARAMS ((const char *format, ...));
+       ...
+       int
+       printf VPARAMS ((const char *format, ...))
+       {
+          ...
+       }
+
+   For writing functions which take variable numbers of arguments, we
+   also provide the VA_OPEN, VA_CLOSE, and VA_FIXEDARG macros.  These
+   hide the differences between K+R <varargs.h> and C89 <stdarg.h> more
+   thoroughly than the simple VA_START() macro mentioned above.
+
+   VA_OPEN and VA_CLOSE are used *instead of* va_start and va_end.
+   Immediately after VA_OPEN, put a sequence of VA_FIXEDARG calls
+   corresponding to the list of fixed arguments.  Then use va_arg
+   normally to get the variable arguments, or pass your va_list object
+   around.  You do not declare the va_list yourself; VA_OPEN does it
+   for you.
+
+   Here is a complete example:
+
+       int
+       printf VPARAMS ((const char *format, ...))
+       {
+          int result;
+
+          VA_OPEN (ap, format);
+          VA_FIXEDARG (ap, const char *, format);
+
+          result = vfprintf (stdout, format, ap);
+          VA_CLOSE (ap);
+
+          return result;
+       }
+
+
+   You can declare variables either before or after the VA_OPEN,
+   VA_FIXEDARG sequence.  Also, VA_OPEN and VA_CLOSE are the beginning
+   and end of a block.  They must appear at the same nesting level,
+   and any variables declared after VA_OPEN go out of scope at
+   VA_CLOSE.  Unfortunately, with a K+R compiler, that includes the
+   argument list.  You can have multiple instances of VA_OPEN/VA_CLOSE
+   pairs in a single function in case you need to traverse the
+   argument list more than once.
+
+   For ease of writing code which uses GCC extensions but needs to be
+   portable to other compilers, we provide the GCC_VERSION macro that
+   simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
+   wrappers around __attribute__.  Also, __extension__ will be #defined
+   to nothing if it doesn't work.  See below.
+
+   This header also defines a lot of obsolete macros:
+   CONST, VOLATILE, SIGNED, PROTO, EXFUN, DEFUN, DEFUN_VOID,
+   AND, DOTS, NOARGS.  Don't use them.  */
+
+#ifndef        _ANSIDECL_H
+#define _ANSIDECL_H    1
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+/* Using MACRO(x,y) in cpp #if conditionals does not work with some
+   older preprocessors.  Thus we can't define something like this:
+
+#define HAVE_GCC_VERSION(MAJOR, MINOR) \
+  (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR)))
+
+and then test "#if HAVE_GCC_VERSION(2,7)".
+
+So instead we use the macro below and test it against specific values.  */
+
+/* This macro simplifies testing whether we are using gcc, and if it
+   is of a particular minimum version. (Both major & minor numbers are
+   significant.)  This macro will evaluate to 0 if we are not using
+   gcc at all.  */
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif /* GCC_VERSION */
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus))
+/* 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__.  */
+/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other
+   C++ compilers, does not define __STDC__, though it acts as if this
+   was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
+
+#define ANSI_PROTOTYPES        1
+#define PTR            void *
+#define PTRCONST       void *const
+#define LONG_DOUBLE    long double
+
+/* PARAMS is often defined elsewhere (e.g. by libintl.h), so wrap it in
+   a #ifndef.  */
+#ifndef PARAMS
+#define PARAMS(ARGS)           ARGS
+#endif
+
+#define VPARAMS(ARGS)          ARGS
+#define VA_START(VA_LIST, VAR) va_start(VA_LIST, VAR)
+
+/* variadic function helper macros */
+/* "struct Qdmy" swallows the semicolon after VA_OPEN/VA_FIXEDARG's
+   use without inhibiting further decls and without declaring an
+   actual variable.  */
+#define VA_OPEN(AP, VAR)       { va_list AP; va_start(AP, VAR); { struct Qdmy
+#define VA_CLOSE(AP)           } va_end(AP); }
+#define VA_FIXEDARG(AP, T, N)  struct Qdmy
+
+#undef const
+#undef volatile
+#undef signed
+
+#ifdef __KERNEL__
+#ifndef        __STDC_VERSION__
+#define        __STDC_VERSION__ 0
+#endif
+#endif /* __KERNEL__ */
+
+/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
+   it too, but it's not in C89.  */
+#undef inline
+#if __STDC_VERSION__ > 199901L
+/* it's a keyword */
+#else
+# if GCC_VERSION >= 2007
+#  define inline __inline__   /* __inline__ prevents -pedantic warnings */
+# else
+#  define inline  /* nothing */
+# endif
+#endif
+
+/* These are obsolete.  Do not use.  */
+#ifndef IN_GCC
+#define CONST          const
+#define VOLATILE       volatile
+#define SIGNED         signed
+
+#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)
+#define AND            ,
+#define DOTS           , ...
+#define NOARGS         void
+#endif /* ! IN_GCC */
+
+#else  /* Not ANSI C.  */
+
+#undef  ANSI_PROTOTYPES
+#define PTR            char *
+#define PTRCONST       PTR
+#define LONG_DOUBLE    double
+
+#define PARAMS(args)           ()
+#define VPARAMS(args)          (va_alist) va_dcl
+#define VA_START(va_list, var) va_start(va_list)
+
+#define VA_OPEN(AP, VAR)               { va_list AP; va_start(AP); { struct Qdmy
+#define VA_CLOSE(AP)                   } va_end(AP); }
+#define VA_FIXEDARG(AP, TYPE, NAME)    TYPE NAME = va_arg(AP, TYPE)
+
+/* some systems define these in header files for non-ansi mode */
+#undef const
+#undef volatile
+#undef signed
+#undef inline
+#define const
+#define volatile
+#define signed
+#define inline
+
+#ifndef IN_GCC
+#define CONST
+#define VOLATILE
+#define SIGNED
+
+#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()
+#define AND            ;
+#define DOTS
+#define NOARGS
+#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 (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+/* Attribute __malloc__ on functions was valid as of gcc 2.96. */
+#ifndef ATTRIBUTE_MALLOC
+# if (GCC_VERSION >= 2096)
+#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+#  define ATTRIBUTE_MALLOC
+# endif /* GNUC >= 2.96 */
+#endif /* ATTRIBUTE_MALLOC */
+
+/* Attributes on labels were valid as of gcc 2.93. */
+#ifndef ATTRIBUTE_UNUSED_LABEL
+# if (!defined (__cplusplus) && GCC_VERSION >= 2093)
+#  define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
+# else
+#  define ATTRIBUTE_UNUSED_LABEL
+# endif /* !__cplusplus && GNUC >= 2.93 */
+#endif /* ATTRIBUTE_UNUSED_LABEL */
+
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif /* ATTRIBUTE_UNUSED */
+
+/* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the
+   identifier name.  */
+#if ! defined(__cplusplus) || (GCC_VERSION >= 3004)
+# define ARG_UNUSED(NAME) NAME ATTRIBUTE_UNUSED
+#else /* !__cplusplus || GNUC >= 3.4 */
+# define ARG_UNUSED(NAME) NAME
+#endif /* !__cplusplus || GNUC >= 3.4 */
+
+#ifndef ATTRIBUTE_NORETURN
+#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#endif /* ATTRIBUTE_NORETURN */
+
+/* Attribute `nonnull' was valid as of gcc 3.3.  */
+#ifndef ATTRIBUTE_NONNULL
+# if (GCC_VERSION >= 3003)
+#  define ATTRIBUTE_NONNULL(m) __attribute__ ((__nonnull__ (m)))
+# else
+#  define ATTRIBUTE_NONNULL(m)
+# endif /* GNUC >= 3.3 */
+#endif /* ATTRIBUTE_NONNULL */
+
+/* Attribute `pure' was valid as of gcc 3.0.  */
+#ifndef ATTRIBUTE_PURE
+# if (GCC_VERSION >= 3000)
+#  define ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+#  define ATTRIBUTE_PURE
+# endif /* GNUC >= 3.0 */
+#endif /* ATTRIBUTE_PURE */
+
+/* Use ATTRIBUTE_PRINTF when the format specifier must not be NULL.
+   This was the case for the `printf' format attribute by itself
+   before GCC 3.3, but as of 3.3 we need to add the `nonnull'
+   attribute to retain this behavior.  */
+#ifndef ATTRIBUTE_PRINTF
+#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) ATTRIBUTE_NONNULL(m)
+#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 */
+
+/* Use ATTRIBUTE_FPTR_PRINTF when the format attribute is to be set on
+   a function pointer.  Format attributes were allowed on function
+   pointers as of gcc 3.1.  */
+#ifndef ATTRIBUTE_FPTR_PRINTF
+# if (GCC_VERSION >= 3001)
+#  define ATTRIBUTE_FPTR_PRINTF(m, n) ATTRIBUTE_PRINTF(m, n)
+# else
+#  define ATTRIBUTE_FPTR_PRINTF(m, n)
+# endif /* GNUC >= 3.1 */
+# define ATTRIBUTE_FPTR_PRINTF_1 ATTRIBUTE_FPTR_PRINTF(1, 2)
+# define ATTRIBUTE_FPTR_PRINTF_2 ATTRIBUTE_FPTR_PRINTF(2, 3)
+# define ATTRIBUTE_FPTR_PRINTF_3 ATTRIBUTE_FPTR_PRINTF(3, 4)
+# define ATTRIBUTE_FPTR_PRINTF_4 ATTRIBUTE_FPTR_PRINTF(4, 5)
+# define ATTRIBUTE_FPTR_PRINTF_5 ATTRIBUTE_FPTR_PRINTF(5, 6)
+#endif /* ATTRIBUTE_FPTR_PRINTF */
+
+/* Use ATTRIBUTE_NULL_PRINTF when the format specifier may be NULL.  A
+   NULL format specifier was allowed as of gcc 3.3.  */
+#ifndef ATTRIBUTE_NULL_PRINTF
+# if (GCC_VERSION >= 3003)
+#  define ATTRIBUTE_NULL_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
+# else
+#  define ATTRIBUTE_NULL_PRINTF(m, n)
+# endif /* GNUC >= 3.3 */
+# define ATTRIBUTE_NULL_PRINTF_1 ATTRIBUTE_NULL_PRINTF(1, 2)
+# define ATTRIBUTE_NULL_PRINTF_2 ATTRIBUTE_NULL_PRINTF(2, 3)
+# define ATTRIBUTE_NULL_PRINTF_3 ATTRIBUTE_NULL_PRINTF(3, 4)
+# define ATTRIBUTE_NULL_PRINTF_4 ATTRIBUTE_NULL_PRINTF(4, 5)
+# define ATTRIBUTE_NULL_PRINTF_5 ATTRIBUTE_NULL_PRINTF(5, 6)
+#endif /* ATTRIBUTE_NULL_PRINTF */
+
+/* Attribute `sentinel' was valid as of gcc 3.5.  */
+#ifndef ATTRIBUTE_SENTINEL
+# if (GCC_VERSION >= 3005)
+#  define ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__))
+# else
+#  define ATTRIBUTE_SENTINEL
+# endif /* GNUC >= 3.5 */
+#endif /* ATTRIBUTE_SENTINEL */
+
+
+#ifndef ATTRIBUTE_ALIGNED_ALIGNOF
+# if (GCC_VERSION >= 3000)
+#  define ATTRIBUTE_ALIGNED_ALIGNOF(m) __attribute__ ((__aligned__ (__alignof__ (m))))
+# else
+#  define ATTRIBUTE_ALIGNED_ALIGNOF(m)
+# endif /* GNUC >= 3.0 */
+#endif /* ATTRIBUTE_ALIGNED_ALIGNOF */
+
+/* We use __extension__ in some places to suppress -pedantic warnings
+   about GCC extensions.  This feature didn't work properly before
+   gcc 2.8.  */
+#if GCC_VERSION < 2008
+#define __extension__
+#endif
+
+#endif /* ansidecl.h   */
diff --git a/include/asm-x86/ansidecl_64.h b/include/asm-x86/ansidecl_64.h
new file mode 100644 (file)
index 0000000..2033011
--- /dev/null
@@ -0,0 +1,383 @@
+/* ANSI and traditional C compatability macros
+   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+   Macro               ANSI C definition       Traditional C definition
+   -----               ---- - ----------       ----------- - ----------
+   ANSI_PROTOTYPES     1                       not defined
+   PTR                 `void *'                `char *'
+   PTRCONST            `void *const'           `char *'
+   LONG_DOUBLE         `long double'           `double'
+   const               not defined             `'
+   volatile            not defined             `'
+   signed              not defined             `'
+   VA_START(ap, var)   va_start(ap, var)       va_start(ap)
+
+   Note that it is safe to write "void foo();" indicating a function
+   with no return value, in all K+R compilers we have been able to test.
+
+   For declaring functions with prototypes, we also provide these:
+
+   PARAMS ((prototype))
+   -- for functions which take a fixed number of arguments.  Use this
+   when declaring the function.  When defining the function, write a
+   K+R style argument list.  For example:
+
+       char *strcpy PARAMS ((char *dest, char *source));
+       ...
+       char *
+       strcpy (dest, source)
+            char *dest;
+            char *source;
+       { ... }
+
+
+   VPARAMS ((prototype, ...))
+   -- for functions which take a variable number of arguments.  Use
+   PARAMS to declare the function, VPARAMS to define it.  For example:
+
+       int printf PARAMS ((const char *format, ...));
+       ...
+       int
+       printf VPARAMS ((const char *format, ...))
+       {
+          ...
+       }
+
+   For writing functions which take variable numbers of arguments, we
+   also provide the VA_OPEN, VA_CLOSE, and VA_FIXEDARG macros.  These
+   hide the differences between K+R <varargs.h> and C89 <stdarg.h> more
+   thoroughly than the simple VA_START() macro mentioned above.
+
+   VA_OPEN and VA_CLOSE are used *instead of* va_start and va_end.
+   Immediately after VA_OPEN, put a sequence of VA_FIXEDARG calls
+   corresponding to the list of fixed arguments.  Then use va_arg
+   normally to get the variable arguments, or pass your va_list object
+   around.  You do not declare the va_list yourself; VA_OPEN does it
+   for you.
+
+   Here is a complete example:
+
+       int
+       printf VPARAMS ((const char *format, ...))
+       {
+          int result;
+
+          VA_OPEN (ap, format);
+          VA_FIXEDARG (ap, const char *, format);
+
+          result = vfprintf (stdout, format, ap);
+          VA_CLOSE (ap);
+
+          return result;
+       }
+
+
+   You can declare variables either before or after the VA_OPEN,
+   VA_FIXEDARG sequence.  Also, VA_OPEN and VA_CLOSE are the beginning
+   and end of a block.  They must appear at the same nesting level,
+   and any variables declared after VA_OPEN go out of scope at
+   VA_CLOSE.  Unfortunately, with a K+R compiler, that includes the
+   argument list.  You can have multiple instances of VA_OPEN/VA_CLOSE
+   pairs in a single function in case you need to traverse the
+   argument list more than once.
+
+   For ease of writing code which uses GCC extensions but needs to be
+   portable to other compilers, we provide the GCC_VERSION macro that
+   simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
+   wrappers around __attribute__.  Also, __extension__ will be #defined
+   to nothing if it doesn't work.  See below.
+
+   This header also defines a lot of obsolete macros:
+   CONST, VOLATILE, SIGNED, PROTO, EXFUN, DEFUN, DEFUN_VOID,
+   AND, DOTS, NOARGS.  Don't use them.  */
+
+#ifndef        _ANSIDECL_H
+#define _ANSIDECL_H    1
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+/* Using MACRO(x,y) in cpp #if conditionals does not work with some
+   older preprocessors.  Thus we can't define something like this:
+
+#define HAVE_GCC_VERSION(MAJOR, MINOR) \
+  (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR)))
+
+and then test "#if HAVE_GCC_VERSION(2,7)".
+
+So instead we use the macro below and test it against specific values.  */
+
+/* This macro simplifies testing whether we are using gcc, and if it
+   is of a particular minimum version. (Both major & minor numbers are
+   significant.)  This macro will evaluate to 0 if we are not using
+   gcc at all.  */
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif /* GCC_VERSION */
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus))
+/* 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__.  */
+/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other
+   C++ compilers, does not define __STDC__, though it acts as if this
+   was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
+
+#define ANSI_PROTOTYPES        1
+#define PTR            void *
+#define PTRCONST       void *const
+#define LONG_DOUBLE    long double
+
+/* PARAMS is often defined elsewhere (e.g. by libintl.h), so wrap it in
+   a #ifndef.  */
+#ifndef PARAMS
+#define PARAMS(ARGS)           ARGS
+#endif
+
+#define VPARAMS(ARGS)          ARGS
+#define VA_START(VA_LIST, VAR) va_start(VA_LIST, VAR)
+
+/* variadic function helper macros */
+/* "struct Qdmy" swallows the semicolon after VA_OPEN/VA_FIXEDARG's
+   use without inhibiting further decls and without declaring an
+   actual variable.  */
+#define VA_OPEN(AP, VAR)       { va_list AP; va_start(AP, VAR); { struct Qdmy
+#define VA_CLOSE(AP)           } va_end(AP); }
+#define VA_FIXEDARG(AP, T, N)  struct Qdmy
+
+#undef const
+#undef volatile
+#undef signed
+
+#ifdef __KERNEL__
+#ifndef        __STDC_VERSION__
+#define        __STDC_VERSION__ 0
+#endif
+#endif /* __KERNEL__ */
+
+/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
+   it too, but it's not in C89.  */
+#undef inline
+#if __STDC_VERSION__ > 199901L
+/* it's a keyword */
+#else
+# if GCC_VERSION >= 2007
+#  define inline __inline__   /* __inline__ prevents -pedantic warnings */
+# else
+#  define inline  /* nothing */
+# endif
+#endif
+
+/* These are obsolete.  Do not use.  */
+#ifndef IN_GCC
+#define CONST          const
+#define VOLATILE       volatile
+#define SIGNED         signed
+
+#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)
+#define AND            ,
+#define DOTS           , ...
+#define NOARGS         void
+#endif /* ! IN_GCC */
+
+#else  /* Not ANSI C.  */
+
+#undef  ANSI_PROTOTYPES
+#define PTR            char *
+#define PTRCONST       PTR
+#define LONG_DOUBLE    double
+
+#define PARAMS(args)           ()
+#define VPARAMS(args)          (va_alist) va_dcl
+#define VA_START(va_list, var) va_start(va_list)
+
+#define VA_OPEN(AP, VAR)               { va_list AP; va_start(AP); { struct Qdmy
+#define VA_CLOSE(AP)                   } va_end(AP); }
+#define VA_FIXEDARG(AP, TYPE, NAME)    TYPE NAME = va_arg(AP, TYPE)
+
+/* some systems define these in header files for non-ansi mode */
+#undef const
+#undef volatile
+#undef signed
+#undef inline
+#define const
+#define volatile
+#define signed
+#define inline
+
+#ifndef IN_GCC
+#define CONST
+#define VOLATILE
+#define SIGNED
+
+#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()
+#define AND            ;
+#define DOTS
+#define NOARGS
+#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 (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+/* Attribute __malloc__ on functions was valid as of gcc 2.96. */
+#ifndef ATTRIBUTE_MALLOC
+# if (GCC_VERSION >= 2096)
+#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+#  define ATTRIBUTE_MALLOC
+# endif /* GNUC >= 2.96 */
+#endif /* ATTRIBUTE_MALLOC */
+
+/* Attributes on labels were valid as of gcc 2.93. */
+#ifndef ATTRIBUTE_UNUSED_LABEL
+# if (!defined (__cplusplus) && GCC_VERSION >= 2093)
+#  define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
+# else
+#  define ATTRIBUTE_UNUSED_LABEL
+# endif /* !__cplusplus && GNUC >= 2.93 */
+#endif /* ATTRIBUTE_UNUSED_LABEL */
+
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif /* ATTRIBUTE_UNUSED */
+
+/* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the
+   identifier name.  */
+#if ! defined(__cplusplus) || (GCC_VERSION >= 3004)
+# define ARG_UNUSED(NAME) NAME ATTRIBUTE_UNUSED
+#else /* !__cplusplus || GNUC >= 3.4 */
+# define ARG_UNUSED(NAME) NAME
+#endif /* !__cplusplus || GNUC >= 3.4 */
+
+#ifndef ATTRIBUTE_NORETURN
+#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#endif /* ATTRIBUTE_NORETURN */
+
+/* Attribute `nonnull' was valid as of gcc 3.3.  */
+#ifndef ATTRIBUTE_NONNULL
+# if (GCC_VERSION >= 3003)
+#  define ATTRIBUTE_NONNULL(m) __attribute__ ((__nonnull__ (m)))
+# else
+#  define ATTRIBUTE_NONNULL(m)
+# endif /* GNUC >= 3.3 */
+#endif /* ATTRIBUTE_NONNULL */
+
+/* Attribute `pure' was valid as of gcc 3.0.  */
+#ifndef ATTRIBUTE_PURE
+# if (GCC_VERSION >= 3000)
+#  define ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+#  define ATTRIBUTE_PURE
+# endif /* GNUC >= 3.0 */
+#endif /* ATTRIBUTE_PURE */
+
+/* Use ATTRIBUTE_PRINTF when the format specifier must not be NULL.
+   This was the case for the `printf' format attribute by itself
+   before GCC 3.3, but as of 3.3 we need to add the `nonnull'
+   attribute to retain this behavior.  */
+#ifndef ATTRIBUTE_PRINTF
+#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) ATTRIBUTE_NONNULL(m)
+#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 */
+
+/* Use ATTRIBUTE_FPTR_PRINTF when the format attribute is to be set on
+   a function pointer.  Format attributes were allowed on function
+   pointers as of gcc 3.1.  */
+#ifndef ATTRIBUTE_FPTR_PRINTF
+# if (GCC_VERSION >= 3001)
+#  define ATTRIBUTE_FPTR_PRINTF(m, n) ATTRIBUTE_PRINTF(m, n)
+# else
+#  define ATTRIBUTE_FPTR_PRINTF(m, n)
+# endif /* GNUC >= 3.1 */
+# define ATTRIBUTE_FPTR_PRINTF_1 ATTRIBUTE_FPTR_PRINTF(1, 2)
+# define ATTRIBUTE_FPTR_PRINTF_2 ATTRIBUTE_FPTR_PRINTF(2, 3)
+# define ATTRIBUTE_FPTR_PRINTF_3 ATTRIBUTE_FPTR_PRINTF(3, 4)
+# define ATTRIBUTE_FPTR_PRINTF_4 ATTRIBUTE_FPTR_PRINTF(4, 5)
+# define ATTRIBUTE_FPTR_PRINTF_5 ATTRIBUTE_FPTR_PRINTF(5, 6)
+#endif /* ATTRIBUTE_FPTR_PRINTF */
+
+/* Use ATTRIBUTE_NULL_PRINTF when the format specifier may be NULL.  A
+   NULL format specifier was allowed as of gcc 3.3.  */
+#ifndef ATTRIBUTE_NULL_PRINTF
+# if (GCC_VERSION >= 3003)
+#  define ATTRIBUTE_NULL_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
+# else
+#  define ATTRIBUTE_NULL_PRINTF(m, n)
+# endif /* GNUC >= 3.3 */
+# define ATTRIBUTE_NULL_PRINTF_1 ATTRIBUTE_NULL_PRINTF(1, 2)
+# define ATTRIBUTE_NULL_PRINTF_2 ATTRIBUTE_NULL_PRINTF(2, 3)
+# define ATTRIBUTE_NULL_PRINTF_3 ATTRIBUTE_NULL_PRINTF(3, 4)
+# define ATTRIBUTE_NULL_PRINTF_4 ATTRIBUTE_NULL_PRINTF(4, 5)
+# define ATTRIBUTE_NULL_PRINTF_5 ATTRIBUTE_NULL_PRINTF(5, 6)
+#endif /* ATTRIBUTE_NULL_PRINTF */
+
+/* Attribute `sentinel' was valid as of gcc 3.5.  */
+#ifndef ATTRIBUTE_SENTINEL
+# if (GCC_VERSION >= 3005)
+#  define ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__))
+# else
+#  define ATTRIBUTE_SENTINEL
+# endif /* GNUC >= 3.5 */
+#endif /* ATTRIBUTE_SENTINEL */
+
+
+#ifndef ATTRIBUTE_ALIGNED_ALIGNOF
+# if (GCC_VERSION >= 3000)
+#  define ATTRIBUTE_ALIGNED_ALIGNOF(m) __attribute__ ((__aligned__ (__alignof__ (m))))
+# else
+#  define ATTRIBUTE_ALIGNED_ALIGNOF(m)
+# endif /* GNUC >= 3.0 */
+#endif /* ATTRIBUTE_ALIGNED_ALIGNOF */
+
+/* We use __extension__ in some places to suppress -pedantic warnings
+   about GCC extensions.  This feature didn't work properly before
+   gcc 2.8.  */
+#if GCC_VERSION < 2008
+#define __extension__
+#endif
+
+#endif /* ansidecl.h   */
diff --git a/include/asm-x86/bfd.h b/include/asm-x86/bfd.h
new file mode 100644 (file)
index 0000000..058cf34
--- /dev/null
@@ -0,0 +1,5 @@
+#ifdef CONFIG_X86_32
+# include "bfd_32.h"
+#else
+# include "bfd_64.h"
+#endif
diff --git a/include/asm-x86/bfd_32.h b/include/asm-x86/bfd_32.h
new file mode 100644 (file)
index 0000000..2249f52
--- /dev/null
@@ -0,0 +1,4921 @@
+/* DO NOT EDIT!  -*- buffer-read-only: t -*-  This file is automatically
+   generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c",
+   "bfdio.c", "bfdwin.c", "section.c", "archures.c", "reloc.c",
+   "syms.c", "bfd.c", "archive.c", "corefile.c", "targets.c", "format.c",
+   "linker.c" and "simple.c".
+   Run "make headers" in your build bfd/ to regenerate.  */
+
+/* Main header file for the bfd library -- portable access to object files.
+
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+   Contributed by Cygnus Support.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __KERNEL__
+#include <asm/ansidecl.h>
+#else  /* __KERNEL__ */
+#include "ansidecl.h"
+#include "symcat.h"
+#endif /* __KERNEL__ */
+#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+#ifndef SABER
+/* This 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 XCONCAT2 macro will
+   cause the inner CONCAT2 macros to be evaluated first, producing
+   still-valid pp-tokens.  Then the final concatenation can be done.  */
+#undef CONCAT4
+#define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d))
+#endif
+#endif
+
+/* The word size used by BFD on the host.  This may be 64 with a 32
+   bit target if the host is 64 bit, or if other 64 bit targets have
+   been selected with --enable-targets, or if --enable-64-bit-bfd.  */
+#ifdef __KERNEL__
+#define BFD_ARCH_SIZE 32
+#else  /* __KERNEL__ */
+#define BFD_ARCH_SIZE 64
+#endif /* __KERNEL__ */
+
+/* The word size of the default bfd target.  */
+#define BFD_DEFAULT_TARGET_SIZE 32
+
+#define BFD_HOST_64BIT_LONG 0
+#define BFD_HOST_LONG_LONG 1
+#if 1
+#define BFD_HOST_64_BIT long long
+#define BFD_HOST_U_64_BIT unsigned long long
+typedef BFD_HOST_64_BIT bfd_int64_t;
+typedef BFD_HOST_U_64_BIT bfd_uint64_t;
+#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;
+
+/* Boolean type used in bfd.  Too many systems define their own
+   versions of "boolean" for us to safely typedef a "boolean" of
+   our own.  Using an enum for "bfd_boolean" has its own set of
+   problems, with strange looking casts required to avoid warnings
+   on some older compilers.  Thus we just use an int.
+
+   General rule: Functions which are bfd_boolean return TRUE on
+   success and FALSE on failure (unless they're a predicate).  */
+
+typedef int bfd_boolean;
+#undef FALSE
+#undef TRUE
+#define FALSE 0
+#define TRUE 1
+
+#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 HALF_BFD_SIZE_TYPE \
+  (((bfd_size_type) 1) << (8 * sizeof (bfd_size_type) / 2))
+
+#ifndef BFD_HOST_64_BIT
+/* Fall back on a 32 bit type.  The idea is to make these types always
+   available for function return types, but in the case that
+   BFD_HOST_64_BIT is undefined such a function should abort or
+   otherwise signal an error.  */
+typedef bfd_signed_vma bfd_int64_t;
+typedef bfd_vma bfd_uint64_t;
+#endif
+
+/* An offset into a file.  BFD always uses the largest possible offset
+   based on the build time availability of fseek, fseeko, or fseeko64.  */
+typedef BFD_HOST_64_BIT file_ptr;
+typedef unsigned BFD_HOST_64_BIT ufile_ptr;
+
+extern void bfd_sprintf_vma (bfd *, char *, bfd_vma);
+extern void bfd_fprintf_vma (bfd *, void *, bfd_vma);
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+#define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+\f
+/* File formats.  */
+
+typedef enum bfd_format
+{
+  bfd_unknown = 0,     /* File format is unknown.  */
+  bfd_object,          /* Linker/assembler/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
+
+/* The sections in this BFD specify a memory page.  */
+#define HAS_LOAD_PAGE 0x1000
+
+/* This BFD has been created by the linker and doesn't correspond
+   to any input file.  */
+#define BFD_LINKER_CREATED 0x2000
+\f
+/* 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.  */
+  union
+  {
+    file_ptr pos;
+    bfd *abfd;
+  } u;                 /* bfd* or file position.  */
+  int namidx;          /* Index into string table.  */
+};
+\f
+/* Linenumber stuff.  */
+typedef struct lineno_cache_entry
+{
+  unsigned int line_number;    /* Linenumber from start of function.  */
+  union
+  {
+    struct bfd_symbol *sym;    /* Function name.  */
+    bfd_vma offset;                    /* Offset into section.  */
+  } u;
+}
+alent;
+\f
+/* Object and core file sections.  */
+
+#define        align_power(addr, align)        \
+  (((addr) + ((bfd_vma) 1 << (align)) - 1) & ((bfd_vma) -1 << (align)))
+
+typedef struct bfd_section *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_lma(bfd, ptr) ((ptr)->lma + 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) ((ptr)->size)
+#define bfd_get_section_size(ptr) ((ptr)->size)
+#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 = 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)
+/* Find the address one past the end of SEC.  */
+#define bfd_get_section_limit(bfd, sec) \
+  (((sec)->rawsize ? (sec)->rawsize : (sec)->size) \
+   / bfd_octets_per_byte (bfd))
+
+typedef struct stat stat_type;
+\f
+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 (int);
+\f
+/* 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)
+    (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
+   /* An objalloc for this hash table.  This is a struct objalloc *,
+     but we use void * to avoid requiring the inclusion of objalloc.h.  */
+  void *memory;
+};
+
+/* Initialize a hash table.  */
+extern bfd_boolean bfd_hash_table_init
+  (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 bfd_boolean bfd_hash_table_init_n
+  (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
+  (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
+  (struct bfd_hash_table *, const char *, bfd_boolean create,
+   bfd_boolean copy);
+
+/* Replace an entry in a hash table.  */
+extern void bfd_hash_replace
+  (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
+  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
+
+/* Grab some space for a hash table entry.  */
+extern void *bfd_hash_allocate
+  (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
+  (struct bfd_hash_table *,
+   bfd_boolean (*) (struct bfd_hash_entry *, void *),
+   void *info);
+
+/* Allows the default size of a hash table to be configured. New hash
+   tables allocated using bfd_hash_table_init will be created with
+   this size.  */
+extern void bfd_hash_set_default_size (bfd_size_type);
+
+/* This structure is used to keep track of stabs in sections
+   information while linking.  */
+
+struct stab_info
+{
+  /* A hash table used to hold stabs strings.  */
+  struct bfd_strtab_hash *strings;
+  /* The header file hash table.  */
+  struct bfd_hash_table includes;
+  /* The first .stabstr section.  */
+  struct bfd_section *stabstr;
+};
+
+#define COFF_SWAP_TABLE (void *) &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_bread (void *, bfd_size_type, bfd *);
+extern bfd_size_type bfd_bwrite (const void *, bfd_size_type, bfd *);
+extern int bfd_seek (bfd *, file_ptr, int);
+extern file_ptr bfd_tell (bfd *);
+extern int bfd_flush (bfd *);
+extern int bfd_stat (bfd *, struct stat *);
+
+/* Deprecated old routines.  */
+#if __GNUC__
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD)                           \
+  (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__),     \
+   bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD)                          \
+  (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__),    \
+   bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#else
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD)                           \
+  (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \
+   bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD)                          \
+  (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\
+   bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#endif
+extern void warn_deprecated (const char *, const char *, int, const char *);
+
+/* 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_family_coff(abfd) \
+  (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \
+   bfd_get_flavour (abfd) == bfd_target_xcoff_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_dynamic_symcount(abfd) ((abfd)->dynsymcount)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE)
+
+extern bfd_boolean bfd_cache_close
+  (bfd *abfd);
+/* NB: This declaration should match the autogenerated one in libbfd.h.  */
+
+extern bfd_boolean bfd_cache_close_all (void);
+
+extern bfd_boolean bfd_record_phdr
+  (bfd *, unsigned long, bfd_boolean, flagword, bfd_boolean, bfd_vma,
+   bfd_boolean, bfd_boolean, unsigned int, struct bfd_section **);
+
+/* Byte swapping routines.  */
+
+bfd_uint64_t bfd_getb64 (const void *);
+bfd_uint64_t bfd_getl64 (const void *);
+bfd_int64_t bfd_getb_signed_64 (const void *);
+bfd_int64_t bfd_getl_signed_64 (const void *);
+bfd_vma bfd_getb32 (const void *);
+bfd_vma bfd_getl32 (const void *);
+bfd_signed_vma bfd_getb_signed_32 (const void *);
+bfd_signed_vma bfd_getl_signed_32 (const void *);
+bfd_vma bfd_getb16 (const void *);
+bfd_vma bfd_getl16 (const void *);
+bfd_signed_vma bfd_getb_signed_16 (const void *);
+bfd_signed_vma bfd_getl_signed_16 (const void *);
+void bfd_putb64 (bfd_uint64_t, void *);
+void bfd_putl64 (bfd_uint64_t, void *);
+void bfd_putb32 (bfd_vma, void *);
+void bfd_putl32 (bfd_vma, void *);
+void bfd_putb16 (bfd_vma, void *);
+void bfd_putl16 (bfd_vma, void *);
+
+/* Byte swapping routines which take size and endiannes as arguments.  */
+
+bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean);
+void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean);
+
+extern bfd_boolean bfd_section_already_linked_table_init (void);
+extern void bfd_section_already_linked_table_free (void);
+\f
+/* Externally visible ECOFF routines.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct bfd_symbol;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value
+  (bfd * abfd);
+extern bfd_boolean bfd_ecoff_set_gp_value
+  (bfd *abfd, bfd_vma gp_value);
+extern bfd_boolean bfd_ecoff_set_regmasks
+  (bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+   unsigned long *cprmask);
+extern void *bfd_ecoff_debug_init
+  (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
+  (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+   const struct ecoff_debug_swap *output_swap, struct bfd_link_info *);
+extern bfd_boolean bfd_ecoff_debug_accumulate
+  (void *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 bfd_boolean bfd_ecoff_debug_accumulate_other
+  (void *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 bfd_boolean bfd_ecoff_debug_externals
+  (bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap, bfd_boolean relocatable,
+   bfd_boolean (*get_extr) (struct bfd_symbol *, struct ecoff_extr *),
+   void (*set_index) (struct bfd_symbol *, bfd_size_type));
+extern bfd_boolean bfd_ecoff_debug_one_external
+  (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
+  (bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap);
+extern bfd_boolean bfd_ecoff_write_debug
+  (bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap, file_ptr where);
+extern bfd_boolean bfd_ecoff_write_accumulated_debug
+  (void *handle, bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap,
+   struct bfd_link_info *info, file_ptr where);
+
+/* Externally visible ELF routines.  */
+
+struct bfd_link_needed_list
+{
+  struct bfd_link_needed_list *next;
+  bfd *by;
+  const char *name;
+};
+
+enum dynamic_lib_link_class {
+  DYN_NORMAL = 0,
+  DYN_AS_NEEDED = 1,
+  DYN_DT_NEEDED = 2,
+  DYN_NO_ADD_NEEDED = 4,
+  DYN_NO_NEEDED = 8
+};
+
+extern bfd_boolean bfd_elf_record_link_assignment
+  (struct bfd_link_info *, const char *, bfd_boolean);
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_elf_get_bfd_needed_list
+  (bfd *, struct bfd_link_needed_list **);
+extern bfd_boolean bfd_elf_size_dynamic_sections
+  (bfd *, const char *, const char *, const char *, const char * const *,
+   struct bfd_link_info *, struct bfd_section **,
+   struct bfd_elf_version_tree *);
+extern bfd_boolean bfd_elf_size_dynsym_hash_dynstr
+  (bfd *, struct bfd_link_info *);
+extern void bfd_elf_set_dt_needed_name
+  (bfd *, const char *);
+extern const char *bfd_elf_get_dt_soname
+  (bfd *);
+extern void bfd_elf_set_dyn_lib_class
+  (bfd *, int);
+extern int bfd_elf_get_dyn_lib_class
+  (bfd *);
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_elf_discard_info
+  (bfd *, struct bfd_link_info *);
+extern unsigned int _bfd_elf_default_action_discarded
+  (struct bfd_section *);
+
+/* Return an upper bound on the number of bytes required to store a
+   copy of ABFD's program header table entries.  Return -1 if an error
+   occurs; bfd_get_error will return an appropriate code.  */
+extern long bfd_get_elf_phdr_upper_bound
+  (bfd *abfd);
+
+/* Copy ABFD's program header table entries to *PHDRS.  The entries
+   will be stored as an array of Elf_Internal_Phdr structures, as
+   defined in include/elf/internal.h.  To find out how large the
+   buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+   Return the number of program header table entries read, or -1 if an
+   error occurs; bfd_get_error will return an appropriate code.  */
+extern int bfd_get_elf_phdrs
+  (bfd *abfd, void *phdrs);
+
+/* Create a new BFD as if by bfd_openr.  Rather than opening a file,
+   reconstruct an ELF file by reading the segments out of remote memory
+   based on the ELF file header at EHDR_VMA and the ELF program headers it
+   points to.  If not null, *LOADBASEP is filled in with the difference
+   between the VMAs from which the segments were read, and the VMAs the
+   file headers (and hence BFD's idea of each section's VMA) put them at.
+
+   The function TARGET_READ_MEMORY is called to copy LEN bytes from the
+   remote memory at target address VMA into the local buffer at MYADDR; it
+   should return zero on success or an `errno' code on failure.  TEMPL must
+   be a BFD for an ELF target with the word size and byte order found in
+   the remote memory.  */
+extern bfd *bfd_elf_bfd_from_remote_memory
+  (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep,
+   int (*target_read_memory) (bfd_vma vma, bfd_byte *myaddr, int len));
+
+/* Return the arch_size field of an elf bfd, or -1 if not elf.  */
+extern int bfd_get_arch_size
+  (bfd *);
+
+/* Return TRUE if address "naturally" sign extends, or -1 if not elf.  */
+extern int bfd_get_sign_extend_vma
+  (bfd *);
+
+extern struct bfd_section *_bfd_elf_tls_setup
+  (bfd *, struct bfd_link_info *);
+
+extern void _bfd_elf_provide_symbol
+  (struct bfd_link_info *, const char *, bfd_vma, struct bfd_section *);
+
+extern void _bfd_elf_provide_section_bound_symbols
+  (struct bfd_link_info *, struct bfd_section *, const char *, const char *);
+
+extern void _bfd_elf_fix_excluded_sec_syms
+  (bfd *, struct bfd_link_info *);
+
+extern bfd_boolean bfd_m68k_elf32_create_embedded_relocs
+  (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *,
+   char **);
+
+/* SunOS shared library support routines for the linker.  */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_sunos_record_link_assignment
+  (bfd *, struct bfd_link_info *, const char *);
+extern bfd_boolean bfd_sunos_size_dynamic_sections
+  (bfd *, struct bfd_link_info *, struct bfd_section **,
+   struct bfd_section **, struct bfd_section **);
+
+/* Linux shared library support routines for the linker.  */
+
+extern bfd_boolean bfd_i386linux_size_dynamic_sections
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_m68klinux_size_dynamic_sections
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_sparclinux_size_dynamic_sections
+  (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.  */
+  void *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
+  (bfd_window *);
+extern void bfd_free_window
+  (bfd_window *);
+extern bfd_boolean bfd_get_file_window
+  (bfd *, file_ptr, bfd_size_type, bfd_window *, bfd_boolean);
+
+/* XCOFF support routines for the linker.  */
+
+extern bfd_boolean bfd_xcoff_link_record_set
+  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_size_type);
+extern bfd_boolean bfd_xcoff_import_symbol
+  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_vma,
+   const char *, const char *, const char *, unsigned int);
+extern bfd_boolean bfd_xcoff_export_symbol
+  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *);
+extern bfd_boolean bfd_xcoff_link_count_reloc
+  (bfd *, struct bfd_link_info *, const char *);
+extern bfd_boolean bfd_xcoff_record_link_assignment
+  (bfd *, struct bfd_link_info *, const char *);
+extern bfd_boolean bfd_xcoff_size_dynamic_sections
+  (bfd *, struct bfd_link_info *, const char *, const char *,
+   unsigned long, unsigned long, unsigned long, bfd_boolean,
+   int, bfd_boolean, bfd_boolean, struct bfd_section **, bfd_boolean);
+extern bfd_boolean bfd_xcoff_link_generate_rtinit
+  (bfd *, const char *, const char *, bfd_boolean);
+
+/* XCOFF support routines for ar.  */
+extern bfd_boolean bfd_xcoff_ar_archive_set_magic
+  (bfd *, char *);
+
+/* Externally visible COFF routines.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern bfd_boolean bfd_coff_get_syment
+  (bfd *, struct bfd_symbol *, struct internal_syment *);
+
+extern bfd_boolean bfd_coff_get_auxent
+  (bfd *, struct bfd_symbol *, int, union internal_auxent *);
+
+extern bfd_boolean bfd_coff_set_symbol_class
+  (bfd *, struct bfd_symbol *, unsigned int);
+
+extern bfd_boolean bfd_m68k_coff_create_embedded_relocs
+  (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **);
+
+/* ARM Interworking support.  Called from linker.  */
+extern bfd_boolean bfd_arm_allocate_interworking_sections
+  (struct bfd_link_info *);
+
+extern bfd_boolean bfd_arm_process_before_allocation
+  (bfd *, struct bfd_link_info *, int);
+
+extern bfd_boolean bfd_arm_get_bfd_for_interworking
+  (bfd *, struct bfd_link_info *);
+
+/* PE ARM Interworking support.  Called from linker.  */
+extern bfd_boolean bfd_arm_pe_allocate_interworking_sections
+  (struct bfd_link_info *);
+
+extern bfd_boolean bfd_arm_pe_process_before_allocation
+  (bfd *, struct bfd_link_info *, int);
+
+extern bfd_boolean bfd_arm_pe_get_bfd_for_interworking
+  (bfd *, struct bfd_link_info *);
+
+/* ELF ARM Interworking support.  Called from linker.  */
+extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections
+  (struct bfd_link_info *);
+
+extern bfd_boolean bfd_elf32_arm_process_before_allocation
+  (bfd *, struct bfd_link_info *, int);
+
+void bfd_elf32_arm_set_target_relocs
+  (struct bfd_link_info *, int, char *, int, int);
+
+extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
+  (bfd *, struct bfd_link_info *);
+
+extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd
+  (bfd *, struct bfd_link_info *);
+
+/* ELF ARM mapping symbol support */
+extern bfd_boolean bfd_is_arm_mapping_symbol_name
+  (const char * name);
+
+/* ARM Note section processing.  */
+extern bfd_boolean bfd_arm_merge_machines
+  (bfd *, bfd *);
+
+extern bfd_boolean bfd_arm_update_notes
+  (bfd *, const char *);
+
+extern unsigned int bfd_arm_get_mach_from_notes
+  (bfd *, const char *);
+
+/* TI COFF load page support.  */
+extern void bfd_ticoff_set_section_load_page
+  (struct bfd_section *, int);
+
+extern int bfd_ticoff_get_section_load_page
+  (struct bfd_section *);
+
+/* H8/300 functions.  */
+extern bfd_vma bfd_h8300_pad_address
+  (bfd *, bfd_vma);
+
+/* IA64 Itanium code generation.  Called from linker.  */
+extern void bfd_elf32_ia64_after_parse
+  (int);
+
+extern void bfd_elf64_ia64_after_parse
+  (int);
+
+/* 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 coff_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;
+};
+
+extern struct coff_comdat_info *bfd_coff_get_comdat_section
+  (bfd *, struct bfd_section *);
+
+/* Extracted from init.c.  */
+void bfd_init (void);
+
+/* Extracted from opncls.c.  */
+bfd *bfd_fopen (const char *filename, const char *target,
+    const char *mode, int fd);
+
+bfd *bfd_openr (const char *filename, const char *target);
+
+bfd *bfd_fdopenr (const char *filename, const char *target, int fd);
+
+bfd *bfd_openstreamr (const char *, const char *, void *);
+
+bfd *bfd_openr_iovec (const char *filename, const char *target,
+    void *(*open) (struct bfd *nbfd,
+    void *open_closure),
+    void *open_closure,
+    file_ptr (*pread) (struct bfd *nbfd,
+    void *stream,
+    void *buf,
+    file_ptr nbytes,
+    file_ptr offset),
+    int (*close) (struct bfd *nbfd,
+    void *stream));
+
+bfd *bfd_openw (const char *filename, const char *target);
+
+bfd_boolean bfd_close (bfd *abfd);
+
+bfd_boolean bfd_close_all_done (bfd *);
+
+bfd *bfd_create (const char *filename, bfd *templ);
+
+bfd_boolean bfd_make_writable (bfd *abfd);
+
+bfd_boolean bfd_make_readable (bfd *abfd);
+
+unsigned long bfd_calc_gnu_debuglink_crc32
+   (unsigned long crc, const unsigned char *buf, bfd_size_type len);
+
+char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir);
+
+struct bfd_section *bfd_create_gnu_debuglink_section
+   (bfd *abfd, const char *filename);
+
+bfd_boolean bfd_fill_in_gnu_debuglink_section
+   (bfd *abfd, struct bfd_section *sect, const char *filename);
+
+/* Extracted from libbfd.c.  */
+
+/* Byte swapping macros for user section data.  */
+
+#define bfd_put_8(abfd, val, ptr) \
+  ((void) (*((unsigned char *) (ptr)) = (val) & 0xff))
+#define bfd_put_signed_8 \
+  bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+  (*(unsigned char *) (ptr) & 0xff)
+#define bfd_get_signed_8(abfd, ptr) \
+  (((*(unsigned char *) (ptr) & 0xff) ^ 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_vma) 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))
+
+/* Aliases for the above, which should eventually go away.  */
+
+#define H_PUT_64  bfd_h_put_64
+#define H_PUT_32  bfd_h_put_32
+#define H_PUT_16  bfd_h_put_16
+#define H_PUT_8   bfd_h_put_8
+#define H_PUT_S64 bfd_h_put_signed_64
+#define H_PUT_S32 bfd_h_put_signed_32
+#define H_PUT_S16 bfd_h_put_signed_16
+#define H_PUT_S8  bfd_h_put_signed_8
+#define H_GET_64  bfd_h_get_64
+#define H_GET_32  bfd_h_get_32
+#define H_GET_16  bfd_h_get_16
+#define H_GET_8   bfd_h_get_8
+#define H_GET_S64 bfd_h_get_signed_64
+#define H_GET_S32 bfd_h_get_signed_32
+#define H_GET_S16 bfd_h_get_signed_16
+#define H_GET_S8  bfd_h_get_signed_8
+
+
+/* Extracted from bfdio.c.  */
+long bfd_get_mtime (bfd *abfd);
+
+long bfd_get_size (bfd *abfd);
+
+/* Extracted from bfdwin.c.  */
+/* Extracted from section.c.  */
+typedef struct bfd_section
+{
+  /* 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;
+
+  /* A unique sequence number.  */
+  int id;
+
+  /* Which section in the bfd; 0..n-1 as sections are created in a bfd.  */
+  int index;
+
+  /* The next section in the list belonging to the BFD, or NULL.  */
+  struct bfd_section *next;
+
+  /* The previous section in the list belonging to the BFD, or NULL.  */
+  struct bfd_section *prev;
+
+  /* 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
+
+  /* A signal to the OS that the section contains read only data.  */
+#define SEC_READONLY   0x008
+
+  /* The section contains code only.  */
+#define SEC_CODE       0x010
+
+  /* The section contains data only.  */
+#define SEC_DATA       0x020
+
+  /* The section will reside in ROM.  */
+#define SEC_ROM        0x040
+
+  /* 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 0x080
+
+  /* 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 0x100
+
+  /* An instruction to the linker to not output the section
+     even if it has information which would normally be written.  */
+#define SEC_NEVER_LOAD 0x200
+
+  /* The section contains thread local data.  */
+#define SEC_THREAD_LOCAL 0x400
+
+  /* The section has GOT references.  This flag is only for the
+     linker, and is currently only used by the elf32-hppa back end.
+     It will be set if global offset table references were detected
+     in this section, which indicate to the linker that the section
+     contains PIC code, and must be handled specially when doing a
+     static link.  */
+#define SEC_HAS_GOT_REF 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 0x1000
+
+  /* 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 0x2000
+
+  /* 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 0x4000
+
+  /* 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 0x8000
+
+  /* The contents of this section are to be sorted based on the sum of
+     the symbol and addend values specified by the associated relocation
+     entries.  Entries without associated relocation entries will be
+     appended to the end of the section in an unspecified order.  */
+#define SEC_SORT_ENTRIES 0x10000
+
+  /* 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 0x20000
+
+  /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+     should handle duplicate sections.  */
+#define SEC_LINK_DUPLICATES 0x40000
+
+  /* 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 0x80000
+
+  /* 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 0x100000
+
+  /* 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 \
+  (SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE)
+
+  /* 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 0x200000
+
+  /* This section should not be subject to garbage collection.  */
+#define SEC_KEEP 0x400000
+
+  /* This section contains "short" data, and should be placed
+     "near" the GP.  */
+#define SEC_SMALL_DATA 0x800000
+
+  /* Attempt to merge identical entities in the section.
+     Entity size is given in the entsize field.  */
+#define SEC_MERGE 0x1000000
+
+  /* If given with SEC_MERGE, entities to merge are zero terminated
+     strings where entsize specifies character size instead of fixed
+     size entries.  */
+#define SEC_STRINGS 0x2000000
+
+  /* This section contains data about section groups.  */
+#define SEC_GROUP 0x4000000
+
+  /* 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 0x10000000
+
+  /* This section contains data which may be shared with other
+     executables or shared objects. This is for COFF only.  */
+#define SEC_COFF_SHARED 0x20000000
+
+  /* When a section with this flag is being linked, then if the size of
+     the input section is less than a page, it should not cross a page
+     boundary.  If the size of the input section is one page or more,
+     it should be aligned on a page boundary.  This is for TI
+     TMS320C54X only.  */
+#define SEC_TIC54X_BLOCK 0x40000000
+
+  /* Conditionally link this section; do not link if there are no
+     references found to any symbol in the section.  This is for TI
+     TMS320C54X only.  */
+#define SEC_TIC54X_CLINK 0x80000000
+
+  /*  End of section flags.  */
+
+  /* Some internal packed boolean fields.  */
+
+  /* See the vma field.  */
+  unsigned int user_set_vma : 1;
+
+  /* A mark flag used by some of the linker backends.  */
+  unsigned int linker_mark : 1;
+
+  /* Another mark flag used by some of the linker backends.  Set for
+     output sections that have an input section.  */
+  unsigned int linker_has_input : 1;
+
+  /* Mark flags used by some linker backends for garbage collection.  */
+  unsigned int gc_mark : 1;
+  unsigned int gc_mark_from_eh : 1;
+
+  /* The following flags are used by the ELF linker. */
+
+  /* Mark sections which have been allocated to segments.  */
+  unsigned int segment_mark : 1;
+
+  /* Type of sec_info information.  */
+  unsigned int sec_info_type:3;
+#define ELF_INFO_TYPE_NONE      0
+#define ELF_INFO_TYPE_STABS     1
+#define ELF_INFO_TYPE_MERGE     2
+#define ELF_INFO_TYPE_EH_FRAME  3
+#define ELF_INFO_TYPE_JUST_SYMS 4
+
+  /* Nonzero if this section uses RELA relocations, rather than REL.  */
+  unsigned int use_rela_p:1;
+
+  /* Bits used by various backends.  The generic code doesn't touch
+     these fields.  */
+
+  /* Nonzero if this section has TLS related relocations.  */
+  unsigned int has_tls_reloc:1;
+
+  /* Nonzero if this section has a gp reloc.  */
+  unsigned int has_gp_reloc:1;
+
+  /* Nonzero if this section needs the relax finalize pass.  */
+  unsigned int need_finalize_relax:1;
+
+  /* Whether relocations have been processed.  */
+  unsigned int reloc_done : 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 octets, as it will be output.
+     Contains a value even if the section has no contents (e.g., the
+     size of <<.bss>>).  */
+  bfd_size_type size;
+
+  /* For input sections, the original size on disk of the section, in
+     octets.  This field is used by the linker relaxation code.  It is
+     currently only set for sections where the linker relaxation scheme
+     doesn't cache altered section and reloc contents (stabs, eh_frame,
+     SEC_MERGE, some coff relaxing targets), and thus the original size
+     needs to be kept to read the section multiple times.
+     For output sections, rawsize holds the section size calculated on
+     a previous linker relaxation pass.  */
+  bfd_size_type rawsize;
+
+  /* If this section is going to be output, then this value is the
+     offset in *bytes* into the output section of the first byte in the
+     input section (byte ==> smallest addressable unit on the
+     target).  In most cases, if this was going to start at the
+     100th octet (8-bit quantity) in the output section, this value
+     would be 100.  However, if the target byte size is 16 bits
+     (bfd_octets_per_byte is "2"), this value would be 50.  */
+  bfd_vma output_offset;
+
+  /* The output section through which to map on output.  */
+  struct bfd_section *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.  */
+  void *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;
+
+  /* Entity size for merging purposes.  */
+  unsigned int entsize;
+
+  /* Points to the kept section if this section is a link-once section,
+     and is discarded.  */
+  struct bfd_section *kept_section;
+
+  /* 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;
+
+  void *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 bfd_symbol *symbol;
+  struct bfd_symbol **symbol_ptr_ptr;
+
+  /* Early in the link process, map_head and map_tail are used to build
+     a list of input sections attached to an output section.  Later,
+     output sections use these fields for a list of bfd_link_order
+     structs.  */
+  union {
+    struct bfd_link_order *link_order;
+    struct bfd_section *s;
+  } map_head, map_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 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 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 asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+/* Pointer to the indirect section.  */
+extern asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+#define bfd_is_const_section(SEC)              \
+ (   ((SEC) == bfd_abs_section_ptr)            \
+  || ((SEC) == bfd_und_section_ptr)            \
+  || ((SEC) == bfd_com_section_ptr)            \
+  || ((SEC) == bfd_ind_section_ptr))
+
+extern const struct bfd_symbol * const bfd_abs_symbol;
+extern const struct bfd_symbol * const bfd_com_symbol;
+extern const struct bfd_symbol * const bfd_und_symbol;
+extern const struct bfd_symbol * const bfd_ind_symbol;
+
+/* Macros to handle insertion and deletion of a bfd's sections.  These
+   only handle the list pointers, ie. do not adjust section_count,
+   target_index etc.  */
+#define bfd_section_list_remove(ABFD, S) \
+  do                                                   \
+    {                                                  \
+      asection *_s = S;                                \
+      asection *_next = _s->next;                      \
+      asection *_prev = _s->prev;                      \
+      if (_prev)                                       \
+        _prev->next = _next;                           \
+      else                                             \
+        (ABFD)->sections = _next;                      \
+      if (_next)                                       \
+        _next->prev = _prev;                           \
+      else                                             \
+        (ABFD)->section_last = _prev;                  \
+    }                                                  \
+  while (0)
+#define bfd_section_list_append(ABFD, S) \
+  do                                                   \
+    {                                                  \
+      asection *_s = S;                                \
+      bfd *_abfd = ABFD;                               \
+      _s->next = NULL;                                 \
+      if (_abfd->section_last)                         \
+        {                                              \
+          _s->prev = _abfd->section_last;              \
+          _abfd->section_last->next = _s;              \
+        }                                              \
+      else                                             \
+        {                                              \
+          _s->prev = NULL;                             \
+          _abfd->sections = _s;                        \
+        }                                              \
+      _abfd->section_last = _s;                        \
+    }                                                  \
+  while (0)
+#define bfd_section_list_prepend(ABFD, S) \
+  do                                                   \
+    {                                                  \
+      asection *_s = S;                                \
+      bfd *_abfd = ABFD;                               \
+      _s->prev = NULL;                                 \
+      if (_abfd->sections)                             \
+        {                                              \
+          _s->next = _abfd->sections;                  \
+          _abfd->sections->prev = _s;                  \
+        }                                              \
+      else                                             \
+        {                                              \
+          _s->next = NULL;                             \
+          _abfd->section_last = _s;                    \
+        }                                              \
+      _abfd->sections = _s;                            \
+    }                                                  \
+  while (0)
+#define bfd_section_list_insert_after(ABFD, A, S) \
+  do                                                   \
+    {                                                  \
+      asection *_a = A;                                \
+      asection *_s = S;                                \
+      asection *_next = _a->next;                      \
+      _s->next = _next;                                \
+      _s->prev = _a;                                   \
+      _a->next = _s;                                   \
+      if (_next)                                       \
+        _next->prev = _s;                              \
+      else                                             \
+        (ABFD)->section_last = _s;                     \
+    }                                                  \
+  while (0)
+#define bfd_section_list_insert_before(ABFD, B, S) \
+  do                                                   \
+    {                                                  \
+      asection *_b = B;                                \
+      asection *_s = S;                                \
+      asection *_prev = _b->prev;                      \
+      _s->prev = _prev;                                \
+      _s->next = _b;                                   \
+      _b->prev = _s;                                   \
+      if (_prev)                                       \
+        _prev->next = _s;                              \
+      else                                             \
+        (ABFD)->sections = _s;                         \
+    }                                                  \
+  while (0)
+#define bfd_section_removed_from_list(ABFD, S) \
+  ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S))
+
+void bfd_section_list_clear (bfd *);
+
+asection *bfd_get_section_by_name (bfd *abfd, const char *name);
+
+asection *bfd_get_section_by_name_if
+   (bfd *abfd,
+    const char *name,
+    bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj),
+    void *obj);
+
+char *bfd_get_unique_section_name
+   (bfd *abfd, const char *templat, int *count);
+
+asection *bfd_make_section_old_way (bfd *abfd, const char *name);
+
+asection *bfd_make_section_anyway_with_flags
+   (bfd *abfd, const char *name, flagword flags);
+
+asection *bfd_make_section_anyway (bfd *abfd, const char *name);
+
+asection *bfd_make_section_with_flags
+   (bfd *, const char *name, flagword flags);
+
+asection *bfd_make_section (bfd *, const char *name);
+
+bfd_boolean bfd_set_section_flags
+   (bfd *abfd, asection *sec, flagword flags);
+
+void bfd_map_over_sections
+   (bfd *abfd,
+    void (*func) (bfd *abfd, asection *sect, void *obj),
+    void *obj);
+
+asection *bfd_sections_find_if
+   (bfd *abfd,
+    bfd_boolean (*operation) (bfd *abfd, asection *sect, void *obj),
+    void *obj);
+
+bfd_boolean bfd_set_section_size
+   (bfd *abfd, asection *sec, bfd_size_type val);
+
+bfd_boolean bfd_set_section_contents
+   (bfd *abfd, asection *section, const void *data,
+    file_ptr offset, bfd_size_type count);
+
+bfd_boolean bfd_get_section_contents
+   (bfd *abfd, asection *section, void *location, file_ptr offset,
+    bfd_size_type count);
+
+bfd_boolean bfd_malloc_and_get_section
+   (bfd *abfd, asection *section, bfd_byte **buf);
+
+bfd_boolean bfd_copy_private_section_data
+   (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))
+bfd_boolean bfd_generic_is_group_section (bfd *, const asection *sec);
+
+bfd_boolean bfd_generic_discard_group (bfd *abfd, asection *group);
+
+/* Extracted from archures.c.  */
+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
+#define bfd_mach_mcf5200  9
+#define bfd_mach_mcf5206e 10
+#define bfd_mach_mcf5307  11
+#define bfd_mach_mcf5407  12
+#define bfd_mach_mcf528x  13
+#define bfd_mach_mcfv4e   14
+#define bfd_mach_mcf521x   15
+#define bfd_mach_mcf5249   16
+#define bfd_mach_mcf547x   17
+#define bfd_mach_mcf548x   18
+  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_or32,      /* OpenRISC 32 */
+
+  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.  */
+#define bfd_mach_sparc_v8plusb         9 /* with cheetah add'ns.  */
+#define bfd_mach_sparc_v9b             10 /* with cheetah 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_v9b \
+   && (mach) != bfd_mach_sparc_sparclite_le)
+/* Nonzero if MACH is a 64 bit sparc architecture.  */
+#define bfd_mach_sparc_64bit_p(mach) \
+  ((mach) >= bfd_mach_sparc_v9 && (mach) != bfd_mach_sparc_v8plusb)
+  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_mips4120              4120
+#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_mips5400              5400
+#define bfd_mach_mips5500              5500
+#define bfd_mach_mips6000              6000
+#define bfd_mach_mips7000              7000
+#define bfd_mach_mips8000              8000
+#define bfd_mach_mips9000              9000
+#define bfd_mach_mips10000             10000
+#define bfd_mach_mips12000             12000
+#define bfd_mach_mips16                16
+#define bfd_mach_mips5                 5
+#define bfd_mach_mips_sb1              12310201 /* octal 'SB', 01 */
+#define bfd_mach_mipsisa32             32
+#define bfd_mach_mipsisa32r2           33
+#define bfd_mach_mipsisa64             64
+#define bfd_mach_mipsisa64r2           65
+  bfd_arch_i386,      /* Intel 386 */
+#define bfd_mach_i386_i386 1
+#define bfd_mach_i386_i8086 2
+#define bfd_mach_i386_i386_intel_syntax 3
+#define bfd_mach_x86_64 64
+#define bfd_mach_x86_64_intel_syntax 65
+  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_m98k,      /* Motorola 98xxx */
+  bfd_arch_pyramid,   /* Pyramid Technology */
+  bfd_arch_h8300,     /* Renesas H8/300 (formerly Hitachi H8/300) */
+#define bfd_mach_h8300    1
+#define bfd_mach_h8300h   2
+#define bfd_mach_h8300s   3
+#define bfd_mach_h8300hn  4
+#define bfd_mach_h8300sn  5
+#define bfd_mach_h8300sx  6
+#define bfd_mach_h8300sxn 7
+  bfd_arch_pdp11,     /* DEC PDP-11 */
+  bfd_arch_powerpc,   /* PowerPC */
+#define bfd_mach_ppc           32
+#define bfd_mach_ppc64         64
+#define bfd_mach_ppc_403       403
+#define bfd_mach_ppc_403gc     4030
+#define bfd_mach_ppc_505       505
+#define bfd_mach_ppc_601       601
+#define bfd_mach_ppc_602       602
+#define bfd_mach_ppc_603       603
+#define bfd_mach_ppc_ec603e    6031
+#define bfd_mach_ppc_604       604
+#define bfd_mach_ppc_620       620
+#define bfd_mach_ppc_630       630
+#define bfd_mach_ppc_750       750
+#define bfd_mach_ppc_860       860
+#define bfd_mach_ppc_a35       35
+#define bfd_mach_ppc_rs64ii    642
+#define bfd_mach_ppc_rs64iii   643
+#define bfd_mach_ppc_7400      7400
+#define bfd_mach_ppc_e500      500
+  bfd_arch_rs6000,    /* IBM RS/6000 */
+#define bfd_mach_rs6k          6000
+#define bfd_mach_rs6k_rs1      6001
+#define bfd_mach_rs6k_rsc      6003
+#define bfd_mach_rs6k_rs2      6002
+  bfd_arch_hppa,      /* HP PA RISC */
+#define bfd_mach_hppa10        10
+#define bfd_mach_hppa11        11
+#define bfd_mach_hppa20        20
+#define bfd_mach_hppa20w       25
+  bfd_arch_d10v,      /* Mitsubishi D10V */
+#define bfd_mach_d10v          1
+#define bfd_mach_d10v_ts2      2
+#define bfd_mach_d10v_ts3      3
+  bfd_arch_d30v,      /* Mitsubishi D30V */
+  bfd_arch_dlx,       /* DLX */
+  bfd_arch_m68hc11,   /* Motorola 68HC11 */
+  bfd_arch_m68hc12,   /* Motorola 68HC12 */
+#define bfd_mach_m6812_default 0
+#define bfd_mach_m6812         1
+#define bfd_mach_m6812s        2
+  bfd_arch_z8k,       /* Zilog Z8000 */
+#define bfd_mach_z8001         1
+#define bfd_mach_z8002         2
+  bfd_arch_h8500,     /* Renesas H8/500 (formerly Hitachi H8/500) */
+  bfd_arch_sh,        /* Renesas / SuperH SH (formerly Hitachi SH) */
+#define bfd_mach_sh            1
+#define bfd_mach_sh2        0x20
+#define bfd_mach_sh_dsp     0x2d
+#define bfd_mach_sh2a       0x2a
+#define bfd_mach_sh2a_nofpu 0x2b
+#define bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu 0x2a1
+#define bfd_mach_sh2a_nofpu_or_sh3_nommu 0x2a2
+#define bfd_mach_sh2a_or_sh4  0x2a3
+#define bfd_mach_sh2a_or_sh3e 0x2a4
+#define bfd_mach_sh2e       0x2e
+#define bfd_mach_sh3        0x30
+#define bfd_mach_sh3_nommu  0x31
+#define bfd_mach_sh3_dsp    0x3d
+#define bfd_mach_sh3e       0x3e
+#define bfd_mach_sh4        0x40
+#define bfd_mach_sh4_nofpu  0x41
+#define bfd_mach_sh4_nommu_nofpu  0x42
+#define bfd_mach_sh4a       0x4a
+#define bfd_mach_sh4a_nofpu 0x4b
+#define bfd_mach_sh4al_dsp  0x4d
+#define bfd_mach_sh5        0x50
+  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_unknown   0
+#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
+#define bfd_mach_arm_5TE       9
+#define bfd_mach_arm_XScale    10
+#define bfd_mach_arm_ep9312    11
+#define bfd_mach_arm_iWMMXt    12
+  bfd_arch_ns32k,     /* National Semiconductors ns32000 */
+  bfd_arch_w65,       /* WDC 65816 */
+  bfd_arch_tic30,     /* Texas Instruments TMS320C30 */
+  bfd_arch_tic4x,     /* Texas Instruments TMS320C3X/4X */
+#define bfd_mach_tic3x         30
+#define bfd_mach_tic4x         40
+  bfd_arch_tic54x,    /* Texas Instruments TMS320C54X */
+  bfd_arch_tic80,     /* TI TMS320c80 (MVP) */
+  bfd_arch_v850,      /* NEC V850 */
+#define bfd_mach_v850          1
+#define bfd_mach_v850e         'E'
+#define bfd_mach_v850e1        '1'
+  bfd_arch_arc,       /* ARC Cores */
+#define bfd_mach_arc_5         5
+#define bfd_mach_arc_6         6
+#define bfd_mach_arc_7         7
+#define bfd_mach_arc_8         8
+ bfd_arch_m32c,     /* Renesas M16C/M32C.  */
+#define bfd_mach_m16c        0x75
+#define bfd_mach_m32c        0x78
+  bfd_arch_m32r,      /* Renesas M32R (formerly Mitsubishi M32R/D) */
+#define bfd_mach_m32r          1 /* For backwards compatibility.  */
+#define bfd_mach_m32rx         'x'
+#define bfd_mach_m32r2         '2'
+  bfd_arch_mn10200,   /* Matsushita MN10200 */
+  bfd_arch_mn10300,   /* Matsushita MN10300 */
+#define bfd_mach_mn10300               300
+#define bfd_mach_am33          330
+#define bfd_mach_am33_2        332
+  bfd_arch_fr30,
+#define bfd_mach_fr30          0x46523330
+  bfd_arch_frv,
+#define bfd_mach_frv           1
+#define bfd_mach_frvsimple     2
+#define bfd_mach_fr300         300
+#define bfd_mach_fr400         400
+#define bfd_mach_fr450         450
+#define bfd_mach_frvtomcat     499     /* fr500 prototype */
+#define bfd_mach_fr500         500
+#define bfd_mach_fr550         550
+  bfd_arch_mcore,
+  bfd_arch_ia64,      /* HP/Intel ia64 */
+#define bfd_mach_ia64_elf64    64
+#define bfd_mach_ia64_elf32    32
+  bfd_arch_ip2k,      /* Ubicom IP2K microcontrollers. */
+#define bfd_mach_ip2022        1
+#define bfd_mach_ip2022ext     2
+ bfd_arch_iq2000,     /* Vitesse IQ2000.  */
+#define bfd_mach_iq2000        1
+#define bfd_mach_iq10          2
+  bfd_arch_ms1,
+#define bfd_mach_ms1           1
+#define bfd_mach_mrisc2        2
+  bfd_arch_pj,
+  bfd_arch_avr,       /* Atmel AVR microcontrollers.  */
+#define bfd_mach_avr1          1
+#define bfd_mach_avr2          2
+#define bfd_mach_avr3          3
+#define bfd_mach_avr4          4
+#define bfd_mach_avr5          5
+  bfd_arch_cr16c,       /* National Semiconductor CompactRISC. */
+#define bfd_mach_cr16c         1
+  bfd_arch_crx,       /*  National Semiconductor CRX.  */
+#define bfd_mach_crx           1
+  bfd_arch_cris,      /* Axis CRIS */
+#define bfd_mach_cris_v0_v10   255
+#define bfd_mach_cris_v32      32
+#define bfd_mach_cris_v10_v32  1032
+  bfd_arch_s390,      /* IBM s390 */
+#define bfd_mach_s390_31       31
+#define bfd_mach_s390_64       64
+  bfd_arch_openrisc,  /* OpenRISC */
+  bfd_arch_mmix,      /* Donald Knuth's educational processor.  */
+  bfd_arch_xstormy16,
+#define bfd_mach_xstormy16     1
+  bfd_arch_msp430,    /* Texas Instruments MSP430 architecture.  */
+#define bfd_mach_msp11          11
+#define bfd_mach_msp110         110
+#define bfd_mach_msp12          12
+#define bfd_mach_msp13          13
+#define bfd_mach_msp14          14
+#define bfd_mach_msp15          15
+#define bfd_mach_msp16          16
+#define bfd_mach_msp31          31
+#define bfd_mach_msp32          32
+#define bfd_mach_msp33          33
+#define bfd_mach_msp41          41
+#define bfd_mach_msp42          42
+#define bfd_mach_msp43          43
+#define bfd_mach_msp44          44
+  bfd_arch_xtensa,    /* Tensilica's Xtensa cores.  */
+#define bfd_mach_xtensa        1
+   bfd_arch_maxq,     /* Dallas MAXQ 10/20 */
+#define bfd_mach_maxq10    10
+#define bfd_mach_maxq20    20
+  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.
+     The default arch should be the first entry for an arch so that
+     all the entries for that arch can be accessed via <<next>>.  */
+  bfd_boolean the_default;
+  const struct bfd_arch_info * (*compatible)
+    (const struct bfd_arch_info *a, const struct bfd_arch_info *b);
+
+  bfd_boolean (*scan) (const struct bfd_arch_info *, const char *);
+
+  const struct bfd_arch_info *next;
+}
+bfd_arch_info_type;
+
+const char *bfd_printable_name (bfd *abfd);
+
+const bfd_arch_info_type *bfd_scan_arch (const char *string);
+
+const char **bfd_arch_list (void);
+
+const bfd_arch_info_type *bfd_arch_get_compatible
+   (const bfd *abfd, const bfd *bbfd, bfd_boolean accept_unknowns);
+
+void bfd_set_arch_info (bfd *abfd, const bfd_arch_info_type *arg);
+
+enum bfd_architecture bfd_get_arch (bfd *abfd);
+
+unsigned long bfd_get_mach (bfd *abfd);
+
+unsigned int bfd_arch_bits_per_byte (bfd *abfd);
+
+unsigned int bfd_arch_bits_per_address (bfd *abfd);
+
+const bfd_arch_info_type *bfd_get_arch_info (bfd *abfd);
+
+const bfd_arch_info_type *bfd_lookup_arch
+   (enum bfd_architecture arch, unsigned long machine);
+
+const char *bfd_printable_arch_mach
+   (enum bfd_architecture arch, unsigned long machine);
+
+unsigned int bfd_octets_per_byte (bfd *abfd);
+
+unsigned int bfd_arch_mach_octets_per_byte
+   (enum bfd_architecture arch, unsigned long machine);
+
+/* Extracted from reloc.c.  */
+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 bfd_symbol **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.  */
+  bfd_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 accommodated (e.g., i960 callj
+     instructions).  */
+  bfd_reloc_status_type (*special_function)
+    (bfd *, arelent *, struct bfd_symbol *, void *, asection *,
+     bfd *, char **);
+
+  /* The textual name of the relocation type.  */
+  char *name;
+
+  /* Some formats record a relocation addend in the section contents
+     rather than with the relocation.  For ELF formats this is the
+     distinction between USE_REL and USE_RELA (though the code checks
+     for USE_REL == 1/0).  The value of this field is TRUE if the
+     addend is recorded with the section contents; when performing a
+     partial link (ld -r) the section contents (the data) will be
+     modified.  The value of this field is FALSE if addends are
+     recorded with the relocation (in arelent.addend); when performing
+     a partial link the relocation will be modified.
+     All relocations for all ELF USE_RELA targets should set this field
+     to FALSE (values of TRUE should be looked on with suspicion).
+     However, the converse is not true: not all relocations of all ELF
+     USE_REL targets set this field to TRUE.  Why this is so is peculiar
+     to each particular target.  For relocs that aren't used in partial
+     links (e.g. GOT stuff) it doesn't matter what this is set to.  */
+  bfd_boolean partial_inplace;
+
+  /* src_mask selects the part of the instruction (or data) to be used
+     in the relocation sum.  If the target relocations don't have an
+     addend in the reloc, eg. ELF USE_REL, src_mask will normally equal
+     dst_mask to extract the addend from the section contents.  If
+     relocations do have an addend in the reloc, eg. ELF USE_RELA, this
+     field should be zero.  Non-zero values for ELF USE_RELA targets are
+     bogus as in those cases the value in the dst_mask part of the
+     section contents should be treated as garbage.  */
+  bfd_vma src_mask;
+
+  /* dst_mask selects which parts of the instruction (or data) are
+     replaced with a relocated value.  */
+  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.  */
+  bfd_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 != NULL)                                 \
+      {                                                 \
+        if (bfd_is_com_section (symbol->section))       \
+          {                                             \
+            relocation = 0;                             \
+          }                                             \
+        else                                            \
+          {                                             \
+            relocation = symbol->value;                 \
+          }                                             \
+      }                                                 \
+  }
+
+unsigned int bfd_get_reloc_size (reloc_howto_type *);
+
+typedef struct relent_chain
+{
+  arelent relent;
+  struct relent_chain *next;
+}
+arelent_chain;
+
+bfd_reloc_status_type bfd_check_overflow
+   (enum complain_overflow how,
+    unsigned int bitsize,
+    unsigned int rightshift,
+    unsigned int addrsize,
+    bfd_vma relocation);
+
+bfd_reloc_status_type bfd_perform_relocation
+   (bfd *abfd,
+    arelent *reloc_entry,
+    void *data,
+    asection *input_section,
+    bfd *output_bfd,
+    char **error_message);
+
+bfd_reloc_status_type bfd_install_relocation
+   (bfd *abfd,
+    arelent *reloc_entry,
+    void *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,
+
+/* Section relative relocations.  Some targets need this for DWARF2.  */
+  BFD_RELOC_32_SECREL,
+
+/* 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_64_PLT_PCREL,
+  BFD_RELOC_32_PLT_PCREL,
+  BFD_RELOC_24_PLT_PCREL,
+  BFD_RELOC_16_PLT_PCREL,
+  BFD_RELOC_8_PLT_PCREL,
+  BFD_RELOC_64_PLTOFF,
+  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_UA16,
+  BFD_RELOC_SPARC_UA32,
+  BFD_RELOC_SPARC_UA64,
+
+/* 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_PLT32,
+  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,
+
+/* SPARC TLS relocations  */
+  BFD_RELOC_SPARC_TLS_GD_HI22,
+  BFD_RELOC_SPARC_TLS_GD_LO10,
+  BFD_RELOC_SPARC_TLS_GD_ADD,
+  BFD_RELOC_SPARC_TLS_GD_CALL,
+  BFD_RELOC_SPARC_TLS_LDM_HI22,
+  BFD_RELOC_SPARC_TLS_LDM_LO10,
+  BFD_RELOC_SPARC_TLS_LDM_ADD,
+  BFD_RELOC_SPARC_TLS_LDM_CALL,
+  BFD_RELOC_SPARC_TLS_LDO_HIX22,
+  BFD_RELOC_SPARC_TLS_LDO_LOX10,
+  BFD_RELOC_SPARC_TLS_LDO_ADD,
+  BFD_RELOC_SPARC_TLS_IE_HI22,
+  BFD_RELOC_SPARC_TLS_IE_LO10,
+  BFD_RELOC_SPARC_TLS_IE_LD,
+  BFD_RELOC_SPARC_TLS_IE_LDX,
+  BFD_RELOC_SPARC_TLS_IE_ADD,
+  BFD_RELOC_SPARC_TLS_LE_HIX22,
+  BFD_RELOC_SPARC_TLS_LE_LOX10,
+  BFD_RELOC_SPARC_TLS_DTPMOD32,
+  BFD_RELOC_SPARC_TLS_DTPMOD64,
+  BFD_RELOC_SPARC_TLS_DTPOFF32,
+  BFD_RELOC_SPARC_TLS_DTPOFF64,
+  BFD_RELOC_SPARC_TLS_TPOFF32,
+  BFD_RELOC_SPARC_TLS_TPOFF64,
+
+/* 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)  */
+  BFD_RELOC_ALPHA_LITERAL,
+  BFD_RELOC_ALPHA_ELF_LITERAL,
+  BFD_RELOC_ALPHA_LITUSE,
+
+/* 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,
+
+/* The GPREL_HI/LO relocations together form a 32-bit offset from the
+GP register.  */
+  BFD_RELOC_ALPHA_GPREL_HI16,
+  BFD_RELOC_ALPHA_GPREL_LO16,
+
+/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must
+share a common GP, and the target address is adjusted for
+STO_ALPHA_STD_GPLOAD.  */
+  BFD_RELOC_ALPHA_BRSGP,
+
+/* Alpha thread-local storage relocations.  */
+  BFD_RELOC_ALPHA_TLSGD,
+  BFD_RELOC_ALPHA_TLSLDM,
+  BFD_RELOC_ALPHA_DTPMOD64,
+  BFD_RELOC_ALPHA_GOTDTPREL16,
+  BFD_RELOC_ALPHA_DTPREL64,
+  BFD_RELOC_ALPHA_DTPREL_HI16,
+  BFD_RELOC_ALPHA_DTPREL_LO16,
+  BFD_RELOC_ALPHA_DTPREL16,
+  BFD_RELOC_ALPHA_GOTTPREL16,
+  BFD_RELOC_ALPHA_TPREL64,
+  BFD_RELOC_ALPHA_TPREL_HI16,
+  BFD_RELOC_ALPHA_TPREL_LO16,
+  BFD_RELOC_ALPHA_TPREL16,
+
+/* 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,
+
+/* High 16 bits of 32-bit pc-relative value  */
+  BFD_RELOC_HI16_PCREL,
+
+/* High 16 bits of 32-bit pc-relative value, adjusted  */
+  BFD_RELOC_HI16_S_PCREL,
+
+/* Low 16 bits of pc-relative value  */
+  BFD_RELOC_LO16_PCREL,
+
+/* MIPS16 high 16 bits of 32-bit value.  */
+  BFD_RELOC_MIPS16_HI16,
+
+/* MIPS16 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_MIPS16_HI16_S,
+
+/* MIPS16 low 16 bits.  */
+  BFD_RELOC_MIPS16_LO16,
+
+/* Relocation against a MIPS literal section.  */
+  BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations.  */
+  BFD_RELOC_MIPS_GOT16,
+  BFD_RELOC_MIPS_CALL16,
+  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,
+  BFD_RELOC_MIPS_SHIFT5,
+  BFD_RELOC_MIPS_SHIFT6,
+  BFD_RELOC_MIPS_INSERT_A,
+  BFD_RELOC_MIPS_INSERT_B,
+  BFD_RELOC_MIPS_DELETE,
+  BFD_RELOC_MIPS_HIGHEST,
+  BFD_RELOC_MIPS_HIGHER,
+  BFD_RELOC_MIPS_SCN_DISP,
+  BFD_RELOC_MIPS_REL16,
+  BFD_RELOC_MIPS_RELGOT,
+  BFD_RELOC_MIPS_JALR,
+  BFD_RELOC_MIPS_TLS_DTPMOD32,
+  BFD_RELOC_MIPS_TLS_DTPREL32,
+  BFD_RELOC_MIPS_TLS_DTPMOD64,
+  BFD_RELOC_MIPS_TLS_DTPREL64,
+  BFD_RELOC_MIPS_TLS_GD,
+  BFD_RELOC_MIPS_TLS_LDM,
+  BFD_RELOC_MIPS_TLS_DTPREL_HI16,
+  BFD_RELOC_MIPS_TLS_DTPREL_LO16,
+  BFD_RELOC_MIPS_TLS_GOTTPREL,
+  BFD_RELOC_MIPS_TLS_TPREL32,
+  BFD_RELOC_MIPS_TLS_TPREL64,
+  BFD_RELOC_MIPS_TLS_TPREL_HI16,
+  BFD_RELOC_MIPS_TLS_TPREL_LO16,
+
+
+/* Fujitsu Frv Relocations.  */
+  BFD_RELOC_FRV_LABEL16,
+  BFD_RELOC_FRV_LABEL24,
+  BFD_RELOC_FRV_LO16,
+  BFD_RELOC_FRV_HI16,
+  BFD_RELOC_FRV_GPREL12,
+  BFD_RELOC_FRV_GPRELU12,
+  BFD_RELOC_FRV_GPREL32,
+  BFD_RELOC_FRV_GPRELHI,
+  BFD_RELOC_FRV_GPRELLO,
+  BFD_RELOC_FRV_GOT12,
+  BFD_RELOC_FRV_GOTHI,
+  BFD_RELOC_FRV_GOTLO,
+  BFD_RELOC_FRV_FUNCDESC,
+  BFD_RELOC_FRV_FUNCDESC_GOT12,
+  BFD_RELOC_FRV_FUNCDESC_GOTHI,
+  BFD_RELOC_FRV_FUNCDESC_GOTLO,
+  BFD_RELOC_FRV_FUNCDESC_VALUE,
+  BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
+  BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
+  BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+  BFD_RELOC_FRV_GOTOFF12,
+  BFD_RELOC_FRV_GOTOFFHI,
+  BFD_RELOC_FRV_GOTOFFLO,
+  BFD_RELOC_FRV_GETTLSOFF,
+  BFD_RELOC_FRV_TLSDESC_VALUE,
+  BFD_RELOC_FRV_GOTTLSDESC12,
+  BFD_RELOC_FRV_GOTTLSDESCHI,
+  BFD_RELOC_FRV_GOTTLSDESCLO,
+  BFD_RELOC_FRV_TLSMOFF12,
+  BFD_RELOC_FRV_TLSMOFFHI,
+  BFD_RELOC_FRV_TLSMOFFLO,
+  BFD_RELOC_FRV_GOTTLSOFF12,
+  BFD_RELOC_FRV_GOTTLSOFFHI,
+  BFD_RELOC_FRV_GOTTLSOFFLO,
+  BFD_RELOC_FRV_TLSOFF,
+  BFD_RELOC_FRV_TLSDESC_RELAX,
+  BFD_RELOC_FRV_GETTLSOFF_RELAX,
+  BFD_RELOC_FRV_TLSOFF_RELAX,
+  BFD_RELOC_FRV_TLSMOFF,
+
+
+/* This is a 24bit GOT-relative reloc for the mn10300.  */
+  BFD_RELOC_MN10300_GOTOFF24,
+
+/* This is a 32bit GOT-relative reloc for the mn10300, offset by two bytes
+in the instruction.  */
+  BFD_RELOC_MN10300_GOT32,
+
+/* This is a 24bit GOT-relative reloc for the mn10300, offset by two bytes
+in the instruction.  */
+  BFD_RELOC_MN10300_GOT24,
+
+/* This is a 16bit GOT-relative reloc for the mn10300, offset by two bytes
+in the instruction.  */
+  BFD_RELOC_MN10300_GOT16,
+
+/* Copy symbol at runtime.  */
+  BFD_RELOC_MN10300_COPY,
+
+/* Create GOT entry.  */
+  BFD_RELOC_MN10300_GLOB_DAT,
+
+/* Create PLT entry.  */
+  BFD_RELOC_MN10300_JMP_SLOT,
+
+/* Adjust by program base.  */
+  BFD_RELOC_MN10300_RELATIVE,
+
+
+/* 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,
+  BFD_RELOC_386_TLS_TPOFF,
+  BFD_RELOC_386_TLS_IE,
+  BFD_RELOC_386_TLS_GOTIE,
+  BFD_RELOC_386_TLS_LE,
+  BFD_RELOC_386_TLS_GD,
+  BFD_RELOC_386_TLS_LDM,
+  BFD_RELOC_386_TLS_LDO_32,
+  BFD_RELOC_386_TLS_IE_32,
+  BFD_RELOC_386_TLS_LE_32,
+  BFD_RELOC_386_TLS_DTPMOD32,
+  BFD_RELOC_386_TLS_DTPOFF32,
+  BFD_RELOC_386_TLS_TPOFF32,
+
+/* x86-64/elf relocations  */
+  BFD_RELOC_X86_64_GOT32,
+  BFD_RELOC_X86_64_PLT32,
+  BFD_RELOC_X86_64_COPY,
+  BFD_RELOC_X86_64_GLOB_DAT,
+  BFD_RELOC_X86_64_JUMP_SLOT,
+  BFD_RELOC_X86_64_RELATIVE,
+  BFD_RELOC_X86_64_GOTPCREL,
+  BFD_RELOC_X86_64_32S,
+  BFD_RELOC_X86_64_DTPMOD64,
+  BFD_RELOC_X86_64_DTPOFF64,
+  BFD_RELOC_X86_64_TPOFF64,
+  BFD_RELOC_X86_64_TLSGD,
+  BFD_RELOC_X86_64_TLSLD,
+  BFD_RELOC_X86_64_DTPOFF32,
+  BFD_RELOC_X86_64_GOTTPOFF,
+  BFD_RELOC_X86_64_TPOFF32,
+  BFD_RELOC_X86_64_GOTOFF64,
+  BFD_RELOC_X86_64_GOTPC32,
+
+/* 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,
+
+/* PDP11 relocations  */
+  BFD_RELOC_PDP11_DISP_8_PCREL,
+  BFD_RELOC_PDP11_DISP_6_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,
+  BFD_RELOC_PPC64_HIGHER,
+  BFD_RELOC_PPC64_HIGHER_S,
+  BFD_RELOC_PPC64_HIGHEST,
+  BFD_RELOC_PPC64_HIGHEST_S,
+  BFD_RELOC_PPC64_TOC16_LO,
+  BFD_RELOC_PPC64_TOC16_HI,
+  BFD_RELOC_PPC64_TOC16_HA,
+  BFD_RELOC_PPC64_TOC,
+  BFD_RELOC_PPC64_PLTGOT16,
+  BFD_RELOC_PPC64_PLTGOT16_LO,
+  BFD_RELOC_PPC64_PLTGOT16_HI,
+  BFD_RELOC_PPC64_PLTGOT16_HA,
+  BFD_RELOC_PPC64_ADDR16_DS,
+  BFD_RELOC_PPC64_ADDR16_LO_DS,
+  BFD_RELOC_PPC64_GOT16_DS,
+  BFD_RELOC_PPC64_GOT16_LO_DS,
+  BFD_RELOC_PPC64_PLT16_LO_DS,
+  BFD_RELOC_PPC64_SECTOFF_DS,
+  BFD_RELOC_PPC64_SECTOFF_LO_DS,
+  BFD_RELOC_PPC64_TOC16_DS,
+  BFD_RELOC_PPC64_TOC16_LO_DS,
+  BFD_RELOC_PPC64_PLTGOT16_DS,
+  BFD_RELOC_PPC64_PLTGOT16_LO_DS,
+
+/* PowerPC and PowerPC64 thread-local storage relocations.  */
+  BFD_RELOC_PPC_TLS,
+  BFD_RELOC_PPC_DTPMOD,
+  BFD_RELOC_PPC_TPREL16,
+  BFD_RELOC_PPC_TPREL16_LO,
+  BFD_RELOC_PPC_TPREL16_HI,
+  BFD_RELOC_PPC_TPREL16_HA,
+  BFD_RELOC_PPC_TPREL,
+  BFD_RELOC_PPC_DTPREL16,
+  BFD_RELOC_PPC_DTPREL16_LO,
+  BFD_RELOC_PPC_DTPREL16_HI,
+  BFD_RELOC_PPC_DTPREL16_HA,
+  BFD_RELOC_PPC_DTPREL,
+  BFD_RELOC_PPC_GOT_TLSGD16,
+  BFD_RELOC_PPC_GOT_TLSGD16_LO,
+  BFD_RELOC_PPC_GOT_TLSGD16_HI,
+  BFD_RELOC_PPC_GOT_TLSGD16_HA,
+  BFD_RELOC_PPC_GOT_TLSLD16,
+  BFD_RELOC_PPC_GOT_TLSLD16_LO,
+  BFD_RELOC_PPC_GOT_TLSLD16_HI,
+  BFD_RELOC_PPC_GOT_TLSLD16_HA,
+  BFD_RELOC_PPC_GOT_TPREL16,
+  BFD_RELOC_PPC_GOT_TPREL16_LO,
+  BFD_RELOC_PPC_GOT_TPREL16_HI,
+  BFD_RELOC_PPC_GOT_TPREL16_HA,
+  BFD_RELOC_PPC_GOT_DTPREL16,
+  BFD_RELOC_PPC_GOT_DTPREL16_LO,
+  BFD_RELOC_PPC_GOT_DTPREL16_HI,
+  BFD_RELOC_PPC_GOT_DTPREL16_HA,
+  BFD_RELOC_PPC64_TPREL16_DS,
+  BFD_RELOC_PPC64_TPREL16_LO_DS,
+  BFD_RELOC_PPC64_TPREL16_HIGHER,
+  BFD_RELOC_PPC64_TPREL16_HIGHERA,
+  BFD_RELOC_PPC64_TPREL16_HIGHEST,
+  BFD_RELOC_PPC64_TPREL16_HIGHESTA,
+  BFD_RELOC_PPC64_DTPREL16_DS,
+  BFD_RELOC_PPC64_DTPREL16_LO_DS,
+  BFD_RELOC_PPC64_DTPREL16_HIGHER,
+  BFD_RELOC_PPC64_DTPREL16_HIGHERA,
+  BFD_RELOC_PPC64_DTPREL16_HIGHEST,
+  BFD_RELOC_PPC64_DTPREL16_HIGHESTA,
+
+/* IBM 370/390 relocations  */
+  BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a constructor 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,
+
+/* ARM 26 bit pc-relative branch.  The lowest bit must be zero and is
+not stored in the instruction.  The 2nd lowest bit comes from a 1 bit
+field in the instruction.  */
+  BFD_RELOC_ARM_PCREL_BLX,
+
+/* Thumb 22 bit pc-relative branch.  The lowest bit must be zero and is
+not stored in the instruction.  The 2nd lowest bit comes from a 1 bit
+field in the instruction.  */
+  BFD_RELOC_THUMB_PCREL_BLX,
+
+/* Thumb 7-, 9-, 12-, 20-, 23-, and 25-bit pc-relative branches.
+The lowest bit must be zero and is not stored in the instruction.
+Note that the corresponding ELF R_ARM_THM_JUMPnn constant has an
+"nn" one smaller in all cases.  Note further that BRANCH23
+corresponds to R_ARM_THM_CALL.  */
+  BFD_RELOC_THUMB_PCREL_BRANCH7,
+  BFD_RELOC_THUMB_PCREL_BRANCH9,
+  BFD_RELOC_THUMB_PCREL_BRANCH12,
+  BFD_RELOC_THUMB_PCREL_BRANCH20,
+  BFD_RELOC_THUMB_PCREL_BRANCH23,
+  BFD_RELOC_THUMB_PCREL_BRANCH25,
+
+/* 12-bit immediate offset, used in ARM-format ldr and str instructions.  */
+  BFD_RELOC_ARM_OFFSET_IMM,
+
+/* 5-bit immediate offset, used in Thumb-format ldr and str instructions.  */
+  BFD_RELOC_ARM_THUMB_OFFSET,
+
+/* Pc-relative or absolute relocation depending on target.  Used for
+entries in .init_array sections.  */
+  BFD_RELOC_ARM_TARGET1,
+
+/* Read-only segment base relative address.  */
+  BFD_RELOC_ARM_ROSEGREL32,
+
+/* Data segment base relative address.  */
+  BFD_RELOC_ARM_SBREL32,
+
+/* This reloc is used for references to RTTI data from exception handling
+tables.  The actual definition depends on the target.  It may be a
+pc-relative or some form of GOT-indirect relocation.  */
+  BFD_RELOC_ARM_TARGET2,
+
+/* 31-bit PC relative address.  */
+  BFD_RELOC_ARM_PREL31,
+
+/* Relocations for setting up GOTs and PLTs for shared libraries.  */
+  BFD_RELOC_ARM_JUMP_SLOT,
+  BFD_RELOC_ARM_GLOB_DAT,
+  BFD_RELOC_ARM_GOT32,
+  BFD_RELOC_ARM_PLT32,
+  BFD_RELOC_ARM_RELATIVE,
+  BFD_RELOC_ARM_GOTOFF,
+  BFD_RELOC_ARM_GOTPC,
+
+/* ARM thread-local storage relocations.  */
+  BFD_RELOC_ARM_TLS_GD32,
+  BFD_RELOC_ARM_TLS_LDO32,
+  BFD_RELOC_ARM_TLS_LDM32,
+  BFD_RELOC_ARM_TLS_DTPOFF32,
+  BFD_RELOC_ARM_TLS_DTPMOD32,
+  BFD_RELOC_ARM_TLS_TPOFF32,
+  BFD_RELOC_ARM_TLS_IE32,
+  BFD_RELOC_ARM_TLS_LE32,
+
+/* 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_T32_IMMEDIATE,
+  BFD_RELOC_ARM_SHIFT_IMM,
+  BFD_RELOC_ARM_SMI,
+  BFD_RELOC_ARM_SWI,
+  BFD_RELOC_ARM_MULTI,
+  BFD_RELOC_ARM_CP_OFF_IMM,
+  BFD_RELOC_ARM_CP_OFF_IMM_S2,
+  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_T32_OFFSET_U8,
+  BFD_RELOC_ARM_T32_OFFSET_IMM,
+  BFD_RELOC_ARM_HWLITERAL,
+  BFD_RELOC_ARM_THUMB_ADD,
+  BFD_RELOC_ARM_THUMB_IMM,
+  BFD_RELOC_ARM_THUMB_SHIFT,
+
+/* Renesas / SuperH SH relocs.  Not all of these appear in object files.  */
+  BFD_RELOC_SH_PCDISP8BY2,
+  BFD_RELOC_SH_PCDISP12BY2,
+  BFD_RELOC_SH_IMM3,
+  BFD_RELOC_SH_IMM3U,
+  BFD_RELOC_SH_DISP12,
+  BFD_RELOC_SH_DISP12BY2,
+  BFD_RELOC_SH_DISP12BY4,
+  BFD_RELOC_SH_DISP12BY8,
+  BFD_RELOC_SH_DISP20,
+  BFD_RELOC_SH_DISP20BY8,
+  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,
+  BFD_RELOC_SH_LOOP_START,
+  BFD_RELOC_SH_LOOP_END,
+  BFD_RELOC_SH_COPY,
+  BFD_RELOC_SH_GLOB_DAT,
+  BFD_RELOC_SH_JMP_SLOT,
+  BFD_RELOC_SH_RELATIVE,
+  BFD_RELOC_SH_GOTPC,
+  BFD_RELOC_SH_GOT_LOW16,
+  BFD_RELOC_SH_GOT_MEDLOW16,
+  BFD_RELOC_SH_GOT_MEDHI16,
+  BFD_RELOC_SH_GOT_HI16,
+  BFD_RELOC_SH_GOTPLT_LOW16,
+  BFD_RELOC_SH_GOTPLT_MEDLOW16,
+  BFD_RELOC_SH_GOTPLT_MEDHI16,
+  BFD_RELOC_SH_GOTPLT_HI16,
+  BFD_RELOC_SH_PLT_LOW16,
+  BFD_RELOC_SH_PLT_MEDLOW16,
+  BFD_RELOC_SH_PLT_MEDHI16,
+  BFD_RELOC_SH_PLT_HI16,
+  BFD_RELOC_SH_GOTOFF_LOW16,
+  BFD_RELOC_SH_GOTOFF_MEDLOW16,
+  BFD_RELOC_SH_GOTOFF_MEDHI16,
+  BFD_RELOC_SH_GOTOFF_HI16,
+  BFD_RELOC_SH_GOTPC_LOW16,
+  BFD_RELOC_SH_GOTPC_MEDLOW16,
+  BFD_RELOC_SH_GOTPC_MEDHI16,
+  BFD_RELOC_SH_GOTPC_HI16,
+  BFD_RELOC_SH_COPY64,
+  BFD_RELOC_SH_GLOB_DAT64,
+  BFD_RELOC_SH_JMP_SLOT64,
+  BFD_RELOC_SH_RELATIVE64,
+  BFD_RELOC_SH_GOT10BY4,
+  BFD_RELOC_SH_GOT10BY8,
+  BFD_RELOC_SH_GOTPLT10BY4,
+  BFD_RELOC_SH_GOTPLT10BY8,
+  BFD_RELOC_SH_GOTPLT32,
+  BFD_RELOC_SH_SHMEDIA_CODE,
+  BFD_RELOC_SH_IMMU5,
+  BFD_RELOC_SH_IMMS6,
+  BFD_RELOC_SH_IMMS6BY32,
+  BFD_RELOC_SH_IMMU6,
+  BFD_RELOC_SH_IMMS10,
+  BFD_RELOC_SH_IMMS10BY2,
+  BFD_RELOC_SH_IMMS10BY4,
+  BFD_RELOC_SH_IMMS10BY8,
+  BFD_RELOC_SH_IMMS16,
+  BFD_RELOC_SH_IMMU16,
+  BFD_RELOC_SH_IMM_LOW16,
+  BFD_RELOC_SH_IMM_LOW16_PCREL,
+  BFD_RELOC_SH_IMM_MEDLOW16,
+  BFD_RELOC_SH_IMM_MEDLOW16_PCREL,
+  BFD_RELOC_SH_IMM_MEDHI16,
+  BFD_RELOC_SH_IMM_MEDHI16_PCREL,
+  BFD_RELOC_SH_IMM_HI16,
+  BFD_RELOC_SH_IMM_HI16_PCREL,
+  BFD_RELOC_SH_PT_16,
+  BFD_RELOC_SH_TLS_GD_32,
+  BFD_RELOC_SH_TLS_LD_32,
+  BFD_RELOC_SH_TLS_LDO_32,
+  BFD_RELOC_SH_TLS_IE_32,
+  BFD_RELOC_SH_TLS_LE_32,
+  BFD_RELOC_SH_TLS_DTPMOD32,
+  BFD_RELOC_SH_TLS_DTPOFF32,
+  BFD_RELOC_SH_TLS_TPOFF32,
+
+/* ARC Cores 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,
+
+/* DLX relocs  */
+  BFD_RELOC_DLX_HI16_S,
+
+/* DLX relocs  */
+  BFD_RELOC_DLX_LO16,
+
+/* DLX relocs  */
+  BFD_RELOC_DLX_JMP26,
+
+/* Renesas M16C/M32C Relocations.  */
+  BFD_RELOC_M16C_8_PCREL8,
+  BFD_RELOC_M16C_16_PCREL8,
+  BFD_RELOC_M16C_8_PCREL16,
+  BFD_RELOC_M16C_8_ELABEL24,
+  BFD_RELOC_M16C_8_ABS16,
+  BFD_RELOC_M16C_16_ABS16,
+  BFD_RELOC_M16C_16_ABS24,
+  BFD_RELOC_M16C_16_ABS32,
+  BFD_RELOC_M16C_24_ABS16,
+  BFD_RELOC_M16C_24_ABS24,
+  BFD_RELOC_M16C_24_ABS32,
+  BFD_RELOC_M16C_32_ABS16,
+  BFD_RELOC_M16C_32_ABS24,
+  BFD_RELOC_M16C_32_ABS32,
+  BFD_RELOC_M16C_40_ABS16,
+  BFD_RELOC_M16C_40_ABS24,
+  BFD_RELOC_M16C_40_ABS32,
+
+/* Renesas M32R (formerly 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,
+
+/* For PIC.  */
+  BFD_RELOC_M32R_GOT24,
+  BFD_RELOC_M32R_26_PLTREL,
+  BFD_RELOC_M32R_COPY,
+  BFD_RELOC_M32R_GLOB_DAT,
+  BFD_RELOC_M32R_JMP_SLOT,
+  BFD_RELOC_M32R_RELATIVE,
+  BFD_RELOC_M32R_GOTOFF,
+  BFD_RELOC_M32R_GOTOFF_HI_ULO,
+  BFD_RELOC_M32R_GOTOFF_HI_SLO,
+  BFD_RELOC_M32R_GOTOFF_LO,
+  BFD_RELOC_M32R_GOTPC24,
+  BFD_RELOC_M32R_GOT16_HI_ULO,
+  BFD_RELOC_M32R_GOT16_HI_SLO,
+  BFD_RELOC_M32R_GOT16_LO,
+  BFD_RELOC_M32R_GOTPC_HI_ULO,
+  BFD_RELOC_M32R_GOTPC_HI_SLO,
+  BFD_RELOC_M32R_GOTPC_LO,
+
+/* 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-contiguously 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-contiguously 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,
+
+/* Used for relaxing indirect function calls.  */
+  BFD_RELOC_V850_LONGCALL,
+
+/* Used for relaxing indirect jumps.  */
+  BFD_RELOC_V850_LONGJUMP,
+
+/* Used to maintain alignment whilst relaxing.  */
+  BFD_RELOC_V850_ALIGN,
+
+/* This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu
+instructions.  */
+  BFD_RELOC_V850_LO16_SPLIT_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 7bit reloc for the tms320c54x, where the least
+significant 7 bits of a 16 bit word are placed into the least
+significant 7 bits of the opcode.  */
+  BFD_RELOC_TIC54X_PARTLS7,
+
+/* This is a 9bit DP reloc for the tms320c54x, where the most
+significant 9 bits of a 16 bit word are placed into the least
+significant 9 bits of the opcode.  */
+  BFD_RELOC_TIC54X_PARTMS9,
+
+/* This is an extended address 23-bit reloc for the tms320c54x.  */
+  BFD_RELOC_TIC54X_23,
+
+/* This is a 16-bit reloc for the tms320c54x, where the least
+significant 16 bits of a 23-bit extended address are placed into
+the opcode.  */
+  BFD_RELOC_TIC54X_16_OF_23,
+
+/* This is a reloc for the tms320c54x, where the most
+significant 7 bits of a 23-bit extended address are placed into
+the opcode.  */
+  BFD_RELOC_TIC54X_MS7_OF_23,
+
+/* 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 are relocations for the GETA instruction.  */
+  BFD_RELOC_MMIX_GETA,
+  BFD_RELOC_MMIX_GETA_1,
+  BFD_RELOC_MMIX_GETA_2,
+  BFD_RELOC_MMIX_GETA_3,
+
+/* These are relocations for a conditional branch instruction.  */
+  BFD_RELOC_MMIX_CBRANCH,
+  BFD_RELOC_MMIX_CBRANCH_J,
+  BFD_RELOC_MMIX_CBRANCH_1,
+  BFD_RELOC_MMIX_CBRANCH_2,
+  BFD_RELOC_MMIX_CBRANCH_3,
+
+/* These are relocations for the PUSHJ instruction.  */
+  BFD_RELOC_MMIX_PUSHJ,
+  BFD_RELOC_MMIX_PUSHJ_1,
+  BFD_RELOC_MMIX_PUSHJ_2,
+  BFD_RELOC_MMIX_PUSHJ_3,
+  BFD_RELOC_MMIX_PUSHJ_STUBBABLE,
+
+/* These are relocations for the JMP instruction.  */
+  BFD_RELOC_MMIX_JMP,
+  BFD_RELOC_MMIX_JMP_1,
+  BFD_RELOC_MMIX_JMP_2,
+  BFD_RELOC_MMIX_JMP_3,
+
+/* This is a relocation for a relative address as in a GETA instruction or
+a branch.  */
+  BFD_RELOC_MMIX_ADDR19,
+
+/* This is a relocation for a relative address as in a JMP instruction.  */
+  BFD_RELOC_MMIX_ADDR27,
+
+/* This is a relocation for an instruction field that may be a general
+register or a value 0..255.  */
+  BFD_RELOC_MMIX_REG_OR_BYTE,
+
+/* This is a relocation for an instruction field that may be a general
+register.  */
+  BFD_RELOC_MMIX_REG,
+
+/* This is a relocation for two instruction fields holding a register and
+an offset, the equivalent of the relocation.  */
+  BFD_RELOC_MMIX_BASE_PLUS_OFFSET,
+
+/* This relocation is an assertion that the expression is not allocated as
+a global register.  It does not modify contents.  */
+  BFD_RELOC_MMIX_LOCAL,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative
+short offset into 7 bits.  */
+  BFD_RELOC_AVR_7_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative
+short offset into 12 bits.  */
+  BFD_RELOC_AVR_13_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually
+program memory address) into 16 bits.  */
+  BFD_RELOC_AVR_16_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+data memory address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_LO8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of data memory address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HI8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of program memory address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HH8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually data memory address) into 8 bit immediate value of SUBI insn.  */
+  BFD_RELOC_AVR_LO8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of data memory address) into 8 bit immediate value of
+SUBI insn.  */
+  BFD_RELOC_AVR_HI8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(most high 8 bit of program memory address) into 8 bit immediate value
+of LDI or SUBI insn.  */
+  BFD_RELOC_AVR_HH8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+command address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_LO8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of command address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HI8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of command address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HH8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually command address) into 8 bit immediate value of SUBI insn.  */
+  BFD_RELOC_AVR_LO8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of 16 bit command address) into 8 bit immediate value
+of SUBI insn.  */
+  BFD_RELOC_AVR_HI8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 6 bit of 22 bit command address) into 8 bit immediate
+value of SUBI insn.  */
+  BFD_RELOC_AVR_HH8_LDI_PM_NEG,
+
+/* This is a 32 bit reloc for the AVR that stores 23 bit value
+into 22 bits.  */
+  BFD_RELOC_AVR_CALL,
+
+/* This is a 16 bit reloc for the AVR that stores all needed bits
+for absolute addressing with ldi with overflow check to linktime  */
+  BFD_RELOC_AVR_LDI,
+
+/* This is a 6 bit reloc for the AVR that stores offset for ldd/std
+instructions  */
+  BFD_RELOC_AVR_6,
+
+/* This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw
+instructions  */
+  BFD_RELOC_AVR_6_ADIW,
+
+/* Direct 12 bit.  */
+  BFD_RELOC_390_12,
+
+/* 12 bit GOT offset.  */
+  BFD_RELOC_390_GOT12,
+
+/* 32 bit PC relative PLT address.  */
+  BFD_RELOC_390_PLT32,
+
+/* Copy symbol at runtime.  */
+  BFD_RELOC_390_COPY,
+
+/* Create GOT entry.  */
+  BFD_RELOC_390_GLOB_DAT,
+
+/* Create PLT entry.  */
+  BFD_RELOC_390_JMP_SLOT,
+
+/* Adjust by program base.  */
+  BFD_RELOC_390_RELATIVE,
+
+/* 32 bit PC relative offset to GOT.  */
+  BFD_RELOC_390_GOTPC,
+
+/* 16 bit GOT offset.  */
+  BFD_RELOC_390_GOT16,
+
+/* PC relative 16 bit shifted by 1.  */
+  BFD_RELOC_390_PC16DBL,
+
+/* 16 bit PC rel. PLT shifted by 1.  */
+  BFD_RELOC_390_PLT16DBL,
+
+/* PC relative 32 bit shifted by 1.  */
+  BFD_RELOC_390_PC32DBL,
+
+/* 32 bit PC rel. PLT shifted by 1.  */
+  BFD_RELOC_390_PLT32DBL,
+
+/* 32 bit PC rel. GOT shifted by 1.  */
+  BFD_RELOC_390_GOTPCDBL,
+
+/* 64 bit GOT offset.  */
+  BFD_RELOC_390_GOT64,
+
+/* 64 bit PC relative PLT address.  */
+  BFD_RELOC_390_PLT64,
+
+/* 32 bit rel. offset to GOT entry.  */
+  BFD_RELOC_390_GOTENT,
+
+/* 64 bit offset to GOT.  */
+  BFD_RELOC_390_GOTOFF64,
+
+/* 12-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT12,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT16,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT32,
+
+/* 64-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT64,
+
+/* 32-bit rel. offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLTENT,
+
+/* 16-bit rel. offset from the GOT to a PLT entry.  */
+  BFD_RELOC_390_PLTOFF16,
+
+/* 32-bit rel. offset from the GOT to a PLT entry.  */
+  BFD_RELOC_390_PLTOFF32,
+
+/* 64-bit rel. offset from the GOT to a PLT entry.  */
+  BFD_RELOC_390_PLTOFF64,
+
+/* s390 tls relocations.  */
+  BFD_RELOC_390_TLS_LOAD,
+  BFD_RELOC_390_TLS_GDCALL,
+  BFD_RELOC_390_TLS_LDCALL,
+  BFD_RELOC_390_TLS_GD32,
+  BFD_RELOC_390_TLS_GD64,
+  BFD_RELOC_390_TLS_GOTIE12,
+  BFD_RELOC_390_TLS_GOTIE32,
+  BFD_RELOC_390_TLS_GOTIE64,
+  BFD_RELOC_390_TLS_LDM32,
+  BFD_RELOC_390_TLS_LDM64,
+  BFD_RELOC_390_TLS_IE32,
+  BFD_RELOC_390_TLS_IE64,
+  BFD_RELOC_390_TLS_IEENT,
+  BFD_RELOC_390_TLS_LE32,
+  BFD_RELOC_390_TLS_LE64,
+  BFD_RELOC_390_TLS_LDO32,
+  BFD_RELOC_390_TLS_LDO64,
+  BFD_RELOC_390_TLS_DTPMOD,
+  BFD_RELOC_390_TLS_DTPOFF,
+  BFD_RELOC_390_TLS_TPOFF,
+
+/* Long displacement extension.  */
+  BFD_RELOC_390_20,
+  BFD_RELOC_390_GOT20,
+  BFD_RELOC_390_GOTPLT20,
+  BFD_RELOC_390_TLS_GOTIE20,
+
+/* Scenix IP2K - 9-bit register number / data address  */
+  BFD_RELOC_IP2K_FR9,
+
+/* Scenix IP2K - 4-bit register/data bank number  */
+  BFD_RELOC_IP2K_BANK,
+
+/* Scenix IP2K - low 13 bits of instruction word address  */
+  BFD_RELOC_IP2K_ADDR16CJP,
+
+/* Scenix IP2K - high 3 bits of instruction word address  */
+  BFD_RELOC_IP2K_PAGE3,
+
+/* Scenix IP2K - ext/low/high 8 bits of data address  */
+  BFD_RELOC_IP2K_LO8DATA,
+  BFD_RELOC_IP2K_HI8DATA,
+  BFD_RELOC_IP2K_EX8DATA,
+
+/* Scenix IP2K - low/high 8 bits of instruction word address  */
+  BFD_RELOC_IP2K_LO8INSN,
+  BFD_RELOC_IP2K_HI8INSN,
+
+/* Scenix IP2K - even/odd PC modifier to modify snb pcl.0  */
+  BFD_RELOC_IP2K_PC_SKIP,
+
+/* Scenix IP2K - 16 bit word address in text section.  */
+  BFD_RELOC_IP2K_TEXT,
+
+/* Scenix IP2K - 7-bit sp or dp offset  */
+  BFD_RELOC_IP2K_FR_OFFSET,
+
+/* Scenix VPE4K coprocessor - data/insn-space addressing  */
+  BFD_RELOC_VPE4KMATH_DATA,
+  BFD_RELOC_VPE4KMATH_INSN,
+
+/* 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 inheritance 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,
+
+/* Intel IA64 Relocations.  */
+  BFD_RELOC_IA64_IMM14,
+  BFD_RELOC_IA64_IMM22,
+  BFD_RELOC_IA64_IMM64,
+  BFD_RELOC_IA64_DIR32MSB,
+  BFD_RELOC_IA64_DIR32LSB,
+  BFD_RELOC_IA64_DIR64MSB,
+  BFD_RELOC_IA64_DIR64LSB,
+  BFD_RELOC_IA64_GPREL22,
+  BFD_RELOC_IA64_GPREL64I,
+  BFD_RELOC_IA64_GPREL32MSB,
+  BFD_RELOC_IA64_GPREL32LSB,
+  BFD_RELOC_IA64_GPREL64MSB,
+  BFD_RELOC_IA64_GPREL64LSB,
+  BFD_RELOC_IA64_LTOFF22,
+  BFD_RELOC_IA64_LTOFF64I,
+  BFD_RELOC_IA64_PLTOFF22,
+  BFD_RELOC_IA64_PLTOFF64I,
+  BFD_RELOC_IA64_PLTOFF64MSB,
+  BFD_RELOC_IA64_PLTOFF64LSB,
+  BFD_RELOC_IA64_FPTR64I,
+  BFD_RELOC_IA64_FPTR32MSB,
+  BFD_RELOC_IA64_FPTR32LSB,
+  BFD_RELOC_IA64_FPTR64MSB,
+  BFD_RELOC_IA64_FPTR64LSB,
+  BFD_RELOC_IA64_PCREL21B,
+  BFD_RELOC_IA64_PCREL21BI,
+  BFD_RELOC_IA64_PCREL21M,
+  BFD_RELOC_IA64_PCREL21F,
+  BFD_RELOC_IA64_PCREL22,
+  BFD_RELOC_IA64_PCREL60B,
+  BFD_RELOC_IA64_PCREL64I,
+  BFD_RELOC_IA64_PCREL32MSB,
+  BFD_RELOC_IA64_PCREL32LSB,
+  BFD_RELOC_IA64_PCREL64MSB,
+  BFD_RELOC_IA64_PCREL64LSB,
+  BFD_RELOC_IA64_LTOFF_FPTR22,
+  BFD_RELOC_IA64_LTOFF_FPTR64I,
+  BFD_RELOC_IA64_LTOFF_FPTR32MSB,
+  BFD_RELOC_IA64_LTOFF_FPTR32LSB,
+  BFD_RELOC_IA64_LTOFF_FPTR64MSB,
+  BFD_RELOC_IA64_LTOFF_FPTR64LSB,
+  BFD_RELOC_IA64_SEGREL32MSB,
+  BFD_RELOC_IA64_SEGREL32LSB,
+  BFD_RELOC_IA64_SEGREL64MSB,
+  BFD_RELOC_IA64_SEGREL64LSB,
+  BFD_RELOC_IA64_SECREL32MSB,
+  BFD_RELOC_IA64_SECREL32LSB,
+  BFD_RELOC_IA64_SECREL64MSB,
+  BFD_RELOC_IA64_SECREL64LSB,
+  BFD_RELOC_IA64_REL32MSB,
+  BFD_RELOC_IA64_REL32LSB,
+  BFD_RELOC_IA64_REL64MSB,
+  BFD_RELOC_IA64_REL64LSB,
+  BFD_RELOC_IA64_LTV32MSB,
+  BFD_RELOC_IA64_LTV32LSB,
+  BFD_RELOC_IA64_LTV64MSB,
+  BFD_RELOC_IA64_LTV64LSB,
+  BFD_RELOC_IA64_IPLTMSB,
+  BFD_RELOC_IA64_IPLTLSB,
+  BFD_RELOC_IA64_COPY,
+  BFD_RELOC_IA64_LTOFF22X,
+  BFD_RELOC_IA64_LDXMOV,
+  BFD_RELOC_IA64_TPREL14,
+  BFD_RELOC_IA64_TPREL22,
+  BFD_RELOC_IA64_TPREL64I,
+  BFD_RELOC_IA64_TPREL64MSB,
+  BFD_RELOC_IA64_TPREL64LSB,
+  BFD_RELOC_IA64_LTOFF_TPREL22,
+  BFD_RELOC_IA64_DTPMOD64MSB,
+  BFD_RELOC_IA64_DTPMOD64LSB,
+  BFD_RELOC_IA64_LTOFF_DTPMOD22,
+  BFD_RELOC_IA64_DTPREL14,
+  BFD_RELOC_IA64_DTPREL22,
+  BFD_RELOC_IA64_DTPREL64I,
+  BFD_RELOC_IA64_DTPREL32MSB,
+  BFD_RELOC_IA64_DTPREL32LSB,
+  BFD_RELOC_IA64_DTPREL64MSB,
+  BFD_RELOC_IA64_DTPREL64LSB,
+  BFD_RELOC_IA64_LTOFF_DTPREL22,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bit high part of an absolute address.  */
+  BFD_RELOC_M68HC11_HI8,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bit low part of an absolute address.  */
+  BFD_RELOC_M68HC11_LO8,
+
+/* Motorola 68HC11 reloc.
+This is the 3 bit of a value.  */
+  BFD_RELOC_M68HC11_3B,
+
+/* Motorola 68HC11 reloc.
+This reloc marks the beginning of a jump/call instruction.
+It is used for linker relaxation to correctly identify beginning
+of instruction and change some branches to use PC-relative
+addressing mode.  */
+  BFD_RELOC_M68HC11_RL_JUMP,
+
+/* Motorola 68HC11 reloc.
+This reloc marks a group of several instructions that gcc generates
+and for which the linker relaxation pass can modify and/or remove
+some of them.  */
+  BFD_RELOC_M68HC11_RL_GROUP,
+
+/* Motorola 68HC11 reloc.
+This is the 16-bit lower part of an address.  It is used for 'call'
+instruction to specify the symbol address without any special
+transformation (due to memory bank window).  */
+  BFD_RELOC_M68HC11_LO16,
+
+/* Motorola 68HC11 reloc.
+This is a 8-bit reloc that specifies the page number of an address.
+It is used by 'call' instruction to specify the page number of
+the symbol.  */
+  BFD_RELOC_M68HC11_PAGE,
+
+/* Motorola 68HC11 reloc.
+This is a 24-bit reloc that represents the address with a 16-bit
+value and a 8-bit page number.  The symbol address is transformed
+to follow the 16K memory bank of 68HC12 (seen as mapped in the window).  */
+  BFD_RELOC_M68HC11_24,
+
+/* Motorola 68HC12 reloc.
+This is the 5 bits of a value.  */
+  BFD_RELOC_M68HC12_5B,
+
+/* NS CR16C Relocations.  */
+  BFD_RELOC_16C_NUM08,
+  BFD_RELOC_16C_NUM08_C,
+  BFD_RELOC_16C_NUM16,
+  BFD_RELOC_16C_NUM16_C,
+  BFD_RELOC_16C_NUM32,
+  BFD_RELOC_16C_NUM32_C,
+  BFD_RELOC_16C_DISP04,
+  BFD_RELOC_16C_DISP04_C,
+  BFD_RELOC_16C_DISP08,
+  BFD_RELOC_16C_DISP08_C,
+  BFD_RELOC_16C_DISP16,
+  BFD_RELOC_16C_DISP16_C,
+  BFD_RELOC_16C_DISP24,
+  BFD_RELOC_16C_DISP24_C,
+  BFD_RELOC_16C_DISP24a,
+  BFD_RELOC_16C_DISP24a_C,
+  BFD_RELOC_16C_REG04,
+  BFD_RELOC_16C_REG04_C,
+  BFD_RELOC_16C_REG04a,
+  BFD_RELOC_16C_REG04a_C,
+  BFD_RELOC_16C_REG14,
+  BFD_RELOC_16C_REG14_C,
+  BFD_RELOC_16C_REG16,
+  BFD_RELOC_16C_REG16_C,
+  BFD_RELOC_16C_REG20,
+  BFD_RELOC_16C_REG20_C,
+  BFD_RELOC_16C_ABS20,
+  BFD_RELOC_16C_ABS20_C,
+  BFD_RELOC_16C_ABS24,
+  BFD_RELOC_16C_ABS24_C,
+  BFD_RELOC_16C_IMM04,
+  BFD_RELOC_16C_IMM04_C,
+  BFD_RELOC_16C_IMM16,
+  BFD_RELOC_16C_IMM16_C,
+  BFD_RELOC_16C_IMM20,
+  BFD_RELOC_16C_IMM20_C,
+  BFD_RELOC_16C_IMM24,
+  BFD_RELOC_16C_IMM24_C,
+  BFD_RELOC_16C_IMM32,
+  BFD_RELOC_16C_IMM32_C,
+
+/* NS CRX Relocations.  */
+  BFD_RELOC_CRX_REL4,
+  BFD_RELOC_CRX_REL8,
+  BFD_RELOC_CRX_REL8_CMP,
+  BFD_RELOC_CRX_REL16,
+  BFD_RELOC_CRX_REL24,
+  BFD_RELOC_CRX_REL32,
+  BFD_RELOC_CRX_REGREL12,
+  BFD_RELOC_CRX_REGREL22,
+  BFD_RELOC_CRX_REGREL28,
+  BFD_RELOC_CRX_REGREL32,
+  BFD_RELOC_CRX_ABS16,
+  BFD_RELOC_CRX_ABS32,
+  BFD_RELOC_CRX_NUM8,
+  BFD_RELOC_CRX_NUM16,
+  BFD_RELOC_CRX_NUM32,
+  BFD_RELOC_CRX_IMM16,
+  BFD_RELOC_CRX_IMM32,
+  BFD_RELOC_CRX_SWITCH8,
+  BFD_RELOC_CRX_SWITCH16,
+  BFD_RELOC_CRX_SWITCH32,
+
+/* These relocs are only used within the CRIS assembler.  They are not
+(at present) written to any object files.  */
+  BFD_RELOC_CRIS_BDISP8,
+  BFD_RELOC_CRIS_UNSIGNED_5,
+  BFD_RELOC_CRIS_SIGNED_6,
+  BFD_RELOC_CRIS_UNSIGNED_6,
+  BFD_RELOC_CRIS_SIGNED_8,
+  BFD_RELOC_CRIS_UNSIGNED_8,
+  BFD_RELOC_CRIS_SIGNED_16,
+  BFD_RELOC_CRIS_UNSIGNED_16,
+  BFD_RELOC_CRIS_LAPCQ_OFFSET,
+  BFD_RELOC_CRIS_UNSIGNED_4,
+
+/* Relocs used in ELF shared libraries for CRIS.  */
+  BFD_RELOC_CRIS_COPY,
+  BFD_RELOC_CRIS_GLOB_DAT,
+  BFD_RELOC_CRIS_JUMP_SLOT,
+  BFD_RELOC_CRIS_RELATIVE,
+
+/* 32-bit offset to symbol-entry within GOT.  */
+  BFD_RELOC_CRIS_32_GOT,
+
+/* 16-bit offset to symbol-entry within GOT.  */
+  BFD_RELOC_CRIS_16_GOT,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_CRIS_32_GOTPLT,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_CRIS_16_GOTPLT,
+
+/* 32-bit offset to symbol, relative to GOT.  */
+  BFD_RELOC_CRIS_32_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to GOT.  */
+  BFD_RELOC_CRIS_32_PLT_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to this relocation.  */
+  BFD_RELOC_CRIS_32_PLT_PCREL,
+
+/* Intel i860 Relocations.  */
+  BFD_RELOC_860_COPY,
+  BFD_RELOC_860_GLOB_DAT,
+  BFD_RELOC_860_JUMP_SLOT,
+  BFD_RELOC_860_RELATIVE,
+  BFD_RELOC_860_PC26,
+  BFD_RELOC_860_PLT26,
+  BFD_RELOC_860_PC16,
+  BFD_RELOC_860_LOW0,
+  BFD_RELOC_860_SPLIT0,
+  BFD_RELOC_860_LOW1,
+  BFD_RELOC_860_SPLIT1,
+  BFD_RELOC_860_LOW2,
+  BFD_RELOC_860_SPLIT2,
+  BFD_RELOC_860_LOW3,
+  BFD_RELOC_860_LOGOT0,
+  BFD_RELOC_860_SPGOT0,
+  BFD_RELOC_860_LOGOT1,
+  BFD_RELOC_860_SPGOT1,
+  BFD_RELOC_860_LOGOTOFF0,
+  BFD_RELOC_860_SPGOTOFF0,
+  BFD_RELOC_860_LOGOTOFF1,
+  BFD_RELOC_860_SPGOTOFF1,
+  BFD_RELOC_860_LOGOTOFF2,
+  BFD_RELOC_860_LOGOTOFF3,
+  BFD_RELOC_860_LOPC,
+  BFD_RELOC_860_HIGHADJ,
+  BFD_RELOC_860_HAGOT,
+  BFD_RELOC_860_HAGOTOFF,
+  BFD_RELOC_860_HAPC,
+  BFD_RELOC_860_HIGH,
+  BFD_RELOC_860_HIGOT,
+  BFD_RELOC_860_HIGOTOFF,
+
+/* OpenRISC Relocations.  */
+  BFD_RELOC_OPENRISC_ABS_26,
+  BFD_RELOC_OPENRISC_REL_26,
+
+/* H8 elf Relocations.  */
+  BFD_RELOC_H8_DIR16A8,
+  BFD_RELOC_H8_DIR16R8,
+  BFD_RELOC_H8_DIR24A8,
+  BFD_RELOC_H8_DIR24R8,
+  BFD_RELOC_H8_DIR32A16,
+
+/* Sony Xstormy16 Relocations.  */
+  BFD_RELOC_XSTORMY16_REL_12,
+  BFD_RELOC_XSTORMY16_12,
+  BFD_RELOC_XSTORMY16_24,
+  BFD_RELOC_XSTORMY16_FPTR16,
+
+/* Relocations used by VAX ELF.  */
+  BFD_RELOC_VAX_GLOB_DAT,
+  BFD_RELOC_VAX_JMP_SLOT,
+  BFD_RELOC_VAX_RELATIVE,
+
+/* Morpho MS1 - 16 bit immediate relocation.  */
+  BFD_RELOC_MS1_PC16,
+
+/* Morpho MS1 - Hi 16 bits of an address.  */
+  BFD_RELOC_MS1_HI16,
+
+/* Morpho MS1 - Low 16 bits of an address.  */
+  BFD_RELOC_MS1_LO16,
+
+/* Morpho MS1 - Used to tell the linker which vtable entries are used.  */
+  BFD_RELOC_MS1_GNU_VTINHERIT,
+
+/* Morpho MS1 - Used to tell the linker which vtable entries are used.  */
+  BFD_RELOC_MS1_GNU_VTENTRY,
+
+/* msp430 specific relocation codes  */
+  BFD_RELOC_MSP430_10_PCREL,
+  BFD_RELOC_MSP430_16_PCREL,
+  BFD_RELOC_MSP430_16,
+  BFD_RELOC_MSP430_16_PCREL_BYTE,
+  BFD_RELOC_MSP430_16_BYTE,
+  BFD_RELOC_MSP430_2X_PCREL,
+  BFD_RELOC_MSP430_RL_PCREL,
+
+/* IQ2000 Relocations.  */
+  BFD_RELOC_IQ2000_OFFSET_16,
+  BFD_RELOC_IQ2000_OFFSET_21,
+  BFD_RELOC_IQ2000_UHI16,
+
+/* Special Xtensa relocation used only by PLT entries in ELF shared
+objects to indicate that the runtime linker should set the value
+to one of its own internal functions or data structures.  */
+  BFD_RELOC_XTENSA_RTLD,
+
+/* Xtensa relocations for ELF shared objects.  */
+  BFD_RELOC_XTENSA_GLOB_DAT,
+  BFD_RELOC_XTENSA_JMP_SLOT,
+  BFD_RELOC_XTENSA_RELATIVE,
+
+/* Xtensa relocation used in ELF object files for symbols that may require
+PLT entries.  Otherwise, this is just a generic 32-bit relocation.  */
+  BFD_RELOC_XTENSA_PLT,
+
+/* Xtensa relocations to mark the difference of two local symbols.
+These are only needed to support linker relaxation and can be ignored
+when not relaxing.  The field is set to the value of the difference
+assuming no relaxation.  The relocation encodes the position of the
+first symbol so the linker can determine whether to adjust the field
+value.  */
+  BFD_RELOC_XTENSA_DIFF8,
+  BFD_RELOC_XTENSA_DIFF16,
+  BFD_RELOC_XTENSA_DIFF32,
+
+/* Generic Xtensa relocations for instruction operands.  Only the slot
+number is encoded in the relocation.  The relocation applies to the
+last PC-relative immediate operand, or if there are no PC-relative
+immediates, to the last immediate operand.  */
+  BFD_RELOC_XTENSA_SLOT0_OP,
+  BFD_RELOC_XTENSA_SLOT1_OP,
+  BFD_RELOC_XTENSA_SLOT2_OP,
+  BFD_RELOC_XTENSA_SLOT3_OP,
+  BFD_RELOC_XTENSA_SLOT4_OP,
+  BFD_RELOC_XTENSA_SLOT5_OP,
+  BFD_RELOC_XTENSA_SLOT6_OP,
+  BFD_RELOC_XTENSA_SLOT7_OP,
+  BFD_RELOC_XTENSA_SLOT8_OP,
+  BFD_RELOC_XTENSA_SLOT9_OP,
+  BFD_RELOC_XTENSA_SLOT10_OP,
+  BFD_RELOC_XTENSA_SLOT11_OP,
+  BFD_RELOC_XTENSA_SLOT12_OP,
+  BFD_RELOC_XTENSA_SLOT13_OP,
+  BFD_RELOC_XTENSA_SLOT14_OP,
+
+/* Alternate Xtensa relocations.  Only the slot is encoded in the
+relocation.  The meaning of these relocations is opcode-specific.  */
+  BFD_RELOC_XTENSA_SLOT0_ALT,
+  BFD_RELOC_XTENSA_SLOT1_ALT,
+  BFD_RELOC_XTENSA_SLOT2_ALT,
+  BFD_RELOC_XTENSA_SLOT3_ALT,
+  BFD_RELOC_XTENSA_SLOT4_ALT,
+  BFD_RELOC_XTENSA_SLOT5_ALT,
+  BFD_RELOC_XTENSA_SLOT6_ALT,
+  BFD_RELOC_XTENSA_SLOT7_ALT,
+  BFD_RELOC_XTENSA_SLOT8_ALT,
+  BFD_RELOC_XTENSA_SLOT9_ALT,
+  BFD_RELOC_XTENSA_SLOT10_ALT,
+  BFD_RELOC_XTENSA_SLOT11_ALT,
+  BFD_RELOC_XTENSA_SLOT12_ALT,
+  BFD_RELOC_XTENSA_SLOT13_ALT,
+  BFD_RELOC_XTENSA_SLOT14_ALT,
+
+/* Xtensa relocations for backward compatibility.  These have all been
+replaced by BFD_RELOC_XTENSA_SLOT0_OP.  */
+  BFD_RELOC_XTENSA_OP0,
+  BFD_RELOC_XTENSA_OP1,
+  BFD_RELOC_XTENSA_OP2,
+
+/* Xtensa relocation to mark that the assembler expanded the
+instructions from an original target.  The expansion size is
+encoded in the reloc size.  */
+  BFD_RELOC_XTENSA_ASM_EXPAND,
+
+/* Xtensa relocation to mark that the linker should simplify
+assembler-expanded instructions.  This is commonly used
+internally by the linker after analysis of a
+BFD_RELOC_XTENSA_ASM_EXPAND.  */
+  BFD_RELOC_XTENSA_ASM_SIMPLIFY,
+  BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *bfd_reloc_type_lookup
+   (bfd *abfd, bfd_reloc_code_real_type code);
+
+const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code);
+
+/* Extracted from syms.c.  */
+
+typedef struct bfd_symbol
+{
+  /* 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 arbitrary
+     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
+
+  /* This symbol is thread local.  Used in ELF.  */
+#define BSF_THREAD_LOCAL  0x40000
+
+  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 bfd_section *section;
+
+  /* Back end special data.  */
+  union
+    {
+      void *p;
+      bfd_vma i;
+    }
+  udata;
+}
+asymbol;
+
+#define bfd_get_symtab_upper_bound(abfd) \
+     BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+
+bfd_boolean bfd_is_local_label (bfd *abfd, asymbol *sym);
+
+bfd_boolean bfd_is_local_label_name (bfd *abfd, const char *name);
+
+#define bfd_is_local_label_name(abfd, name) \
+  BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+
+bfd_boolean bfd_is_target_special_symbol (bfd *abfd, asymbol *sym);
+
+#define bfd_is_target_special_symbol(abfd, sym) \
+  BFD_SEND (abfd, _bfd_is_target_special_symbol, (abfd, sym))
+
+#define bfd_canonicalize_symtab(abfd, location) \
+  BFD_SEND (abfd, _bfd_canonicalize_symtab, (abfd, location))
+
+bfd_boolean bfd_set_symtab
+   (bfd *abfd, asymbol **location, unsigned int count);
+
+void bfd_print_symbol_vandf (bfd *abfd, void *file, asymbol *symbol);
+
+#define bfd_make_empty_symbol(abfd) \
+  BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+
+asymbol *_bfd_generic_make_empty_symbol (bfd *);
+
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+  BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+
+int bfd_decode_symclass (asymbol *symbol);
+
+bfd_boolean bfd_is_undefined_symclass (int symclass);
+
+void bfd_symbol_info (asymbol *symbol, symbol_info *ret);
+
+bfd_boolean bfd_copy_private_symbol_data
+   (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))
+
+/* Extracted from bfd.c.  */
+struct bfd
+{
+  /* A unique identifier of the BFD  */
+  unsigned int id;
+
+  /* The filename the application opened the BFD with.  */
+  const char *filename;
+
+  /* A pointer to the target jump table.  */
+  const struct bfd_target *xvec;
+
+  /* The IOSTREAM, and corresponding IO vector that provide access
+     to the file backing the BFD.  */
+  void *iostream;
+  const struct bfd_iovec *iovec;
+
+  /* Is the file descriptor being cached?  That is, can it be closed as
+     needed, and re-opened when accessed later?  */
+  bfd_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.  */
+  bfd_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...  */
+  ufile_ptr where;
+
+  /* ... and here: (``once'' means at least once).  */
+  bfd_boolean opened_once;
+
+  /* Set if we have a locally maintained mtime value, rather than
+     getting it from the file each time.  */
+  bfd_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 with which the BFD was opened.  */
+  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.  */
+  ufile_ptr origin;
+
+  /* Remember when output has begun, to stop strange things
+     from happening.  */
+  bfd_boolean output_has_begun;
+
+  /* A hash table for section names.  */
+  struct bfd_hash_table section_htab;
+
+  /* Pointer to linked list of sections.  */
+  struct bfd_section *sections;
+
+  /* The last section on the section list.  */
+  struct bfd_section *section_last;
+
+  /* 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 bfd_symbol  **outsymbols;
+
+  /* Used for slurped dynamic symbol tables.  */
+  unsigned int dynsymcount;
+
+  /* Pointer to structure which contains architecture information.  */
+  const struct bfd_arch_info *arch_info;
+
+  /* Flag set if symbols from this BFD should not be exported.  */
+  bfd_boolean no_export;
+
+  /* Stuff only useful for archives.  */
+  void *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.  */
+  bfd_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 mmo_data_struct *mmo_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;
+      struct mach_o_data_struct *mach_o_data;
+      struct mach_o_fat_data_struct *mach_o_fat_data;
+      struct bfd_pef_data_struct *pef_data;
+      struct bfd_pef_xlib_data_struct *pef_xlib_data;
+      struct bfd_sym_data_struct *sym_data;
+      void *any;
+    }
+  tdata;
+
+  /* Used by the application to hold private data.  */
+  void *usrdata;
+
+  /* Where all the allocated stuff under this BFD goes.  This is a
+     struct objalloc *, but we use void * to avoid requiring the inclusion
+     of objalloc.h.  */
+  void *memory;
+};
+
+typedef enum bfd_error
+{
+  bfd_error_no_error = 0,
+  bfd_error_system_call,
+  bfd_error_invalid_target,
+  bfd_error_wrong_format,
+  bfd_error_wrong_object_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 (void);
+
+void bfd_set_error (bfd_error_type error_tag);
+
+const char *bfd_errmsg (bfd_error_type error_tag);
+
+void bfd_perror (const char *message);
+
+typedef void (*bfd_error_handler_type) (const char *, ...);
+
+bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type);
+
+void bfd_set_error_program_name (const char *);
+
+bfd_error_handler_type bfd_get_error_handler (void);
+
+long bfd_get_reloc_upper_bound (bfd *abfd, asection *sect);
+
+long bfd_canonicalize_reloc
+   (bfd *abfd, asection *sec, arelent **loc, asymbol **syms);
+
+void bfd_set_reloc
+   (bfd *abfd, asection *sec, arelent **rel, unsigned int count);
+
+bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags);
+
+int bfd_get_arch_size (bfd *abfd);
+
+int bfd_get_sign_extend_vma (bfd *abfd);
+
+bfd_boolean bfd_set_start_address (bfd *abfd, bfd_vma vma);
+
+unsigned int bfd_get_gp_size (bfd *abfd);
+
+void bfd_set_gp_size (bfd *abfd, unsigned int i);
+
+bfd_vma bfd_scan_vma (const char *string, const char **end, int base);
+
+bfd_boolean bfd_copy_private_header_data (bfd *ibfd, bfd *obfd);
+
+#define bfd_copy_private_header_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_copy_private_header_data, \
+               (ibfd, obfd))
+bfd_boolean bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd);
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+               (ibfd, obfd))
+bfd_boolean bfd_merge_private_bfd_data (bfd *ibfd, bfd *obfd);
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+               (ibfd, obfd))
+bfd_boolean bfd_set_private_flags (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))
+
+#define bfd_find_line(abfd, syms, sym, file, line) \
+       BFD_SEND (abfd, _bfd_find_line, \
+                 (abfd, syms, sym, file, line))
+
+#define bfd_find_inliner_info(abfd, file, func, line) \
+       BFD_SEND (abfd, _bfd_find_inliner_info, \
+                 (abfd, file, func, line))
+
+#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_merge_sections(abfd, link_info) \
+       BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
+#define bfd_is_group_section(abfd, sec) \
+       BFD_SEND (abfd, _bfd_is_group_section, (abfd, sec))
+
+#define bfd_discard_group(abfd, sec) \
+       BFD_SEND (abfd, _bfd_discard_group, (abfd, sec))
+
+#define bfd_link_hash_table_create(abfd) \
+       BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_hash_table_free(abfd, hash) \
+       BFD_SEND (abfd, _bfd_link_hash_table_free, (hash))
+
+#define bfd_link_add_symbols(abfd, info) \
+       BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_link_just_syms(abfd, sec, info) \
+       BFD_SEND (abfd, _bfd_link_just_syms, (sec, 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_synthetic_symtab(abfd, count, syms, dyncount, dynsyms, ret) \
+       BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, count, syms, \
+                                                   dyncount, dynsyms, ret))
+
+#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
+  (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *,
+   bfd_boolean, asymbol **);
+
+bfd_boolean bfd_alt_mach_code (bfd *abfd, int alternative);
+
+struct bfd_preserve
+{
+  void *marker;
+  void *tdata;
+  flagword flags;
+  const struct bfd_arch_info *arch_info;
+  struct bfd_section *sections;
+  struct bfd_section *section_last;
+  unsigned int section_count;
+  struct bfd_hash_table section_htab;
+};
+
+bfd_boolean bfd_preserve_save (bfd *, struct bfd_preserve *);
+
+void bfd_preserve_restore (bfd *, struct bfd_preserve *);
+
+void bfd_preserve_finish (bfd *, struct bfd_preserve *);
+
+/* Extracted from archive.c.  */
+symindex bfd_get_next_mapent
+   (bfd *abfd, symindex previous, carsym **sym);
+
+bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head);
+
+bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous);
+
+/* Extracted from corefile.c.  */
+const char *bfd_core_file_failing_command (bfd *abfd);
+
+int bfd_core_file_failing_signal (bfd *abfd);
+
+bfd_boolean core_file_matches_executable_p
+   (bfd *core_bfd, bfd *exec_bfd);
+
+/* Extracted from targets.c.  */
+#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_xcoff_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,
+  bfd_target_mmo_flavour,
+  bfd_target_mach_o_flavour,
+  bfd_target_pef_flavour,
+  bfd_target_pef_xlib_flavour,
+  bfd_target_sym_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
+{
+  /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc.  */
+  char *name;
+
+ /* The "flavour" of a back end is a general indication about
+    the contents of a file.  */
+  enum bfd_flavour flavour;
+
+  /* The order of bytes within the data area of a file.  */
+  enum bfd_endian byteorder;
+
+ /* The order of bytes within the header parts of a file.  */
+  enum bfd_endian header_byteorder;
+
+  /* A mask of all the flags which an executable may have set -
+     from the set <<BFD_NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>.  */
+  flagword object_flags;
+
+ /* A mask of all the flags which a section may have set - from
+    the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>.  */
+  flagword section_flags;
+
+ /* The character normally found at the front of a symbol.
+    (if any), perhaps `_'.  */
+  char symbol_leading_char;
+
+ /* The pad character for file names within an archive header.  */
+  char ar_pad_char;
+
+  /* The maximum number of characters in an archive header.  */
+  unsigned short ar_max_namelen;
+
+  /* Entries for byte swapping for data. These are different from the
+     other entry points, since they don't take a BFD as the first argument.
+     Certain other handlers could do the same.  */
+  bfd_uint64_t   (*bfd_getx64) (const void *);
+  bfd_int64_t    (*bfd_getx_signed_64) (const void *);
+  void           (*bfd_putx64) (bfd_uint64_t, void *);
+  bfd_vma        (*bfd_getx32) (const void *);
+  bfd_signed_vma (*bfd_getx_signed_32) (const void *);
+  void           (*bfd_putx32) (bfd_vma, void *);
+  bfd_vma        (*bfd_getx16) (const void *);
+  bfd_signed_vma (*bfd_getx_signed_16) (const void *);
+  void           (*bfd_putx16) (bfd_vma, void *);
+
+  /* Byte swapping for the headers.  */
+  bfd_uint64_t   (*bfd_h_getx64) (const void *);
+  bfd_int64_t    (*bfd_h_getx_signed_64) (const void *);
+  void           (*bfd_h_putx64) (bfd_uint64_t, void *);
+  bfd_vma        (*bfd_h_getx32) (const void *);
+  bfd_signed_vma (*bfd_h_getx_signed_32) (const void *);
+  void           (*bfd_h_putx32) (bfd_vma, void *);
+  bfd_vma        (*bfd_h_getx16) (const void *);
+  bfd_signed_vma (*bfd_h_getx_signed_16) (const void *);
+  void           (*bfd_h_putx16) (bfd_vma, void *);
+
+  /* Format dependent routines: these are vectors of entry points
+     within the target vector structure, one for each format to check.  */
+
+  /* Check the format of a file being read.  Return a <<bfd_target *>> or zero.  */
+  const struct bfd_target *(*_bfd_check_format[bfd_type_end]) (bfd *);
+
+  /* Set the format of a file being written.  */
+  bfd_boolean (*_bfd_set_format[bfd_type_end]) (bfd *);
+
+  /* Write cached information into a file being written, at <<bfd_close>>.  */
+  bfd_boolean (*_bfd_write_contents[bfd_type_end]) (bfd *);
+
+
+  /* Generic entry points.  */
+#define BFD_JUMP_TABLE_GENERIC(NAME) \
+  NAME##_close_and_cleanup, \
+  NAME##_bfd_free_cached_info, \
+  NAME##_new_section_hook, \
+  NAME##_get_section_contents, \
+  NAME##_get_section_contents_in_window
+
+  /* Called when the BFD is being closed to do any necessary cleanup.  */
+  bfd_boolean (*_close_and_cleanup) (bfd *);
+  /* Ask the BFD to free all cached information.  */
+  bfd_boolean (*_bfd_free_cached_info) (bfd *);
+  /* Called when a new section is created.  */
+  bfd_boolean (*_new_section_hook) (bfd *, sec_ptr);
+  /* Read the contents of a section.  */
+  bfd_boolean (*_bfd_get_section_contents)
+    (bfd *, sec_ptr, void *, file_ptr, bfd_size_type);
+  bfd_boolean (*_bfd_get_section_contents_in_window)
+    (bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type);
+
+  /* Entry points to copy private data.  */
+#define BFD_JUMP_TABLE_COPY(NAME) \
+  NAME##_bfd_copy_private_bfd_data, \
+  NAME##_bfd_merge_private_bfd_data, \
+  NAME##_bfd_copy_private_section_data, \
+  NAME##_bfd_copy_private_symbol_data, \
+  NAME##_bfd_copy_private_header_data, \
+  NAME##_bfd_set_private_flags, \
+  NAME##_bfd_print_private_bfd_data
+
+  /* Called to copy BFD general private data from one object file
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_bfd_data) (bfd *, bfd *);
+  /* Called to merge BFD general private data from one object file
+     to a common output file when linking.  */
+  bfd_boolean (*_bfd_merge_private_bfd_data) (bfd *, bfd *);
+  /* Called to copy BFD private section data from one object file
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_section_data)
+    (bfd *, sec_ptr, bfd *, sec_ptr);
+  /* Called to copy BFD private symbol data from one symbol
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_symbol_data)
+    (bfd *, asymbol *, bfd *, asymbol *);
+  /* Called to copy BFD private header data from one object file
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_header_data)
+    (bfd *, bfd *);
+  /* Called to set private backend flags.  */
+  bfd_boolean (*_bfd_set_private_flags) (bfd *, flagword);
+
+  /* Called to print private BFD data.  */
+  bfd_boolean (*_bfd_print_private_bfd_data) (bfd *, void *);
+
+  /* Core file entry points.  */
+#define BFD_JUMP_TABLE_CORE(NAME) \
+  NAME##_core_file_failing_command, \
+  NAME##_core_file_failing_signal, \
+  NAME##_core_file_matches_executable_p
+
+  char *      (*_core_file_failing_command) (bfd *);
+  int         (*_core_file_failing_signal) (bfd *);
+  bfd_boolean (*_core_file_matches_executable_p) (bfd *, bfd *);
+
+  /* Archive entry points.  */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME) \
+  NAME##_slurp_armap, \
+  NAME##_slurp_extended_name_table, \
+  NAME##_construct_extended_name_table, \
+  NAME##_truncate_arname, \
+  NAME##_write_armap, \
+  NAME##_read_ar_hdr, \
+  NAME##_openr_next_archived_file, \
+  NAME##_get_elt_at_index, \
+  NAME##_generic_stat_arch_elt, \
+  NAME##_update_armap_timestamp
+
+  bfd_boolean (*_bfd_slurp_armap) (bfd *);
+  bfd_boolean (*_bfd_slurp_extended_name_table) (bfd *);
+  bfd_boolean (*_bfd_construct_extended_name_table)
+    (bfd *, char **, bfd_size_type *, const char **);
+  void        (*_bfd_truncate_arname) (bfd *, const char *, char *);
+  bfd_boolean (*write_armap)
+    (bfd *, unsigned int, struct orl *, unsigned int, int);
+  void *      (*_bfd_read_ar_hdr_fn) (bfd *);
+  bfd *       (*openr_next_archived_file) (bfd *, bfd *);
+#define bfd_get_elt_at_index(b,i) BFD_SEND (b, _bfd_get_elt_at_index, (b,i))
+  bfd *       (*_bfd_get_elt_at_index) (bfd *, symindex);
+  int         (*_bfd_stat_arch_elt) (bfd *, struct stat *);
+  bfd_boolean (*_bfd_update_armap_timestamp) (bfd *);
+
+  /* Entry points used for symbols.  */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME) \
+  NAME##_get_symtab_upper_bound, \
+  NAME##_canonicalize_symtab, \
+  NAME##_make_empty_symbol, \
+  NAME##_print_symbol, \
+  NAME##_get_symbol_info, \
+  NAME##_bfd_is_local_label_name, \
+  NAME##_bfd_is_target_special_symbol, \
+  NAME##_get_lineno, \
+  NAME##_find_nearest_line, \
+  _bfd_generic_find_line, \
+  NAME##_find_inliner_info, \
+  NAME##_bfd_make_debug_symbol, \
+  NAME##_read_minisymbols, \
+  NAME##_minisymbol_to_symbol
+
+  long        (*_bfd_get_symtab_upper_bound) (bfd *);
+  long        (*_bfd_canonicalize_symtab)
+    (bfd *, struct bfd_symbol **);
+  struct bfd_symbol *
+              (*_bfd_make_empty_symbol) (bfd *);
+  void        (*_bfd_print_symbol)
+    (bfd *, void *, struct bfd_symbol *, 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)
+    (bfd *, struct bfd_symbol *, symbol_info *);
+#define bfd_get_symbol_info(b,p,e) BFD_SEND (b, _bfd_get_symbol_info, (b,p,e))
+  bfd_boolean (*_bfd_is_local_label_name) (bfd *, const char *);
+  bfd_boolean (*_bfd_is_target_special_symbol) (bfd *, asymbol *);
+  alent *     (*_get_lineno) (bfd *, struct bfd_symbol *);
+  bfd_boolean (*_bfd_find_nearest_line)
+    (bfd *, struct bfd_section *, struct bfd_symbol **, bfd_vma,
+     const char **, const char **, unsigned int *);
+  bfd_boolean (*_bfd_find_line)
+    (bfd *, struct bfd_symbol **, struct bfd_symbol *,
+     const char **, unsigned int *);
+  bfd_boolean (*_bfd_find_inliner_info)
+    (bfd *, const char **, const char **, unsigned int *);
+ /* 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)
+    (bfd *, void *, unsigned long size);
+#define bfd_read_minisymbols(b, d, m, s) \
+  BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+  long        (*_read_minisymbols)
+    (bfd *, bfd_boolean, void **, 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)
+    (bfd *, bfd_boolean, const void *, asymbol *);
+
+  /* Routines for relocs.  */
+#define BFD_JUMP_TABLE_RELOCS(NAME) \
+  NAME##_get_reloc_upper_bound, \
+  NAME##_canonicalize_reloc, \
+  NAME##_bfd_reloc_type_lookup
+
+  long        (*_get_reloc_upper_bound) (bfd *, sec_ptr);
+  long        (*_bfd_canonicalize_reloc)
+    (bfd *, sec_ptr, arelent **, struct bfd_symbol **);
+  /* See documentation on reloc types.  */
+  reloc_howto_type *
+              (*reloc_type_lookup) (bfd *, bfd_reloc_code_real_type);
+
+  /* Routines used when writing an object file.  */
+#define BFD_JUMP_TABLE_WRITE(NAME) \
+  NAME##_set_arch_mach, \
+  NAME##_set_section_contents
+
+  bfd_boolean (*_bfd_set_arch_mach)
+    (bfd *, enum bfd_architecture, unsigned long);
+  bfd_boolean (*_bfd_set_section_contents)
+    (bfd *, sec_ptr, const void *, file_ptr, bfd_size_type);
+
+  /* Routines used by the linker.  */
+#define BFD_JUMP_TABLE_LINK(NAME) \
+  NAME##_sizeof_headers, \
+  NAME##_bfd_get_relocated_section_contents, \
+  NAME##_bfd_relax_section, \
+  NAME##_bfd_link_hash_table_create, \
+  NAME##_bfd_link_hash_table_free, \
+  NAME##_bfd_link_add_symbols, \
+  NAME##_bfd_link_just_syms, \
+  NAME##_bfd_final_link, \
+  NAME##_bfd_link_split_section, \
+  NAME##_bfd_gc_sections, \
+  NAME##_bfd_merge_sections, \
+  NAME##_bfd_is_group_section, \
+  NAME##_bfd_discard_group, \
+  NAME##_section_already_linked \
+
+  int         (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
+  bfd_byte *  (*_bfd_get_relocated_section_contents)
+    (bfd *, struct bfd_link_info *, struct bfd_link_order *,
+     bfd_byte *, bfd_boolean, struct bfd_symbol **);
+
+  bfd_boolean (*_bfd_relax_section)
+    (bfd *, struct bfd_section *, struct bfd_link_info *, bfd_boolean *);
+
+  /* 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) (bfd *);
+
+  /* Release the memory associated with the linker hash table.  */
+  void        (*_bfd_link_hash_table_free) (struct bfd_link_hash_table *);
+
+  /* Add symbols from this object file into the hash table.  */
+  bfd_boolean (*_bfd_link_add_symbols) (bfd *, struct bfd_link_info *);
+
+  /* Indicate that we are only retrieving symbol values from this section.  */
+  void        (*_bfd_link_just_syms) (asection *, struct bfd_link_info *);
+
+  /* Do a link based on the link_order structures attached to each
+     section of the BFD.  */
+  bfd_boolean (*_bfd_final_link) (bfd *, struct bfd_link_info *);
+
+  /* Should this section be split up into smaller pieces during linking.  */
+  bfd_boolean (*_bfd_link_split_section) (bfd *, struct bfd_section *);
+
+  /* Remove sections that are not referenced from the output.  */
+  bfd_boolean (*_bfd_gc_sections) (bfd *, struct bfd_link_info *);
+
+  /* Attempt to merge SEC_MERGE sections.  */
+  bfd_boolean (*_bfd_merge_sections) (bfd *, struct bfd_link_info *);
+
+  /* Is this section a member of a group?  */
+  bfd_boolean (*_bfd_is_group_section) (bfd *, const struct bfd_section *);
+
+  /* Discard members of a group.  */
+  bfd_boolean (*_bfd_discard_group) (bfd *, struct bfd_section *);
+
+  /* Check if SEC has been already linked during a reloceatable or
+     final link.  */
+  void (*_section_already_linked) (bfd *, struct bfd_section *);
+
+  /* Routines to handle dynamic symbols and relocs.  */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
+  NAME##_get_dynamic_symtab_upper_bound, \
+  NAME##_canonicalize_dynamic_symtab, \
+  NAME##_get_synthetic_symtab, \
+  NAME##_get_dynamic_reloc_upper_bound, \
+  NAME##_canonicalize_dynamic_reloc
+
+  /* Get the amount of memory required to hold the dynamic symbols.  */
+  long        (*_bfd_get_dynamic_symtab_upper_bound) (bfd *);
+  /* Read in the dynamic symbols.  */
+  long        (*_bfd_canonicalize_dynamic_symtab)
+    (bfd *, struct bfd_symbol **);
+  /* Create synthetized symbols.  */
+  long        (*_bfd_get_synthetic_symtab)
+    (bfd *, long, struct bfd_symbol **, long, struct bfd_symbol **,
+     struct bfd_symbol **);
+  /* Get the amount of memory required to hold the dynamic relocs.  */
+  long        (*_bfd_get_dynamic_reloc_upper_bound) (bfd *);
+  /* Read in the dynamic relocs.  */
+  long        (*_bfd_canonicalize_dynamic_reloc)
+    (bfd *, arelent **, struct bfd_symbol **);
+
+  /* Opposite endian version of this target.  */
+  const struct bfd_target * alternative_target;
+
+  /* Data for use by back-end routines, which isn't
+     generic enough to belong in this structure.  */
+  const void *backend_data;
+
+} bfd_target;
+
+bfd_boolean bfd_set_default_target (const char *name);
+
+const bfd_target *bfd_find_target (const char *target_name, bfd *abfd);
+
+const char ** bfd_target_list (void);
+
+const bfd_target *bfd_search_for_target
+   (int (*search_func) (const bfd_target *, void *),
+    void *);
+
+/* Extracted from format.c.  */
+bfd_boolean bfd_check_format (bfd *abfd, bfd_format format);
+
+bfd_boolean bfd_check_format_matches
+   (bfd *abfd, bfd_format format, char ***matching);
+
+bfd_boolean bfd_set_format (bfd *abfd, bfd_format format);
+
+const char *bfd_format_string (bfd_format format);
+
+/* Extracted from linker.c.  */
+bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec);
+
+#define bfd_link_split_section(abfd, sec) \
+       BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
+
+void bfd_section_already_linked (bfd *abfd, asection *sec);
+
+#define bfd_section_already_linked(abfd, sec) \
+       BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+
+/* Extracted from simple.c.  */
+bfd_byte *bfd_simple_get_relocated_section_contents
+   (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/asm-x86/bfd_64.h b/include/asm-x86/bfd_64.h
new file mode 100644 (file)
index 0000000..55432f2
--- /dev/null
@@ -0,0 +1,4917 @@
+/* DO NOT EDIT!  -*- buffer-read-only: t -*-  This file is automatically
+   generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c",
+   "bfdio.c", "bfdwin.c", "section.c", "archures.c", "reloc.c",
+   "syms.c", "bfd.c", "archive.c", "corefile.c", "targets.c", "format.c",
+   "linker.c" and "simple.c".
+   Run "make headers" in your build bfd/ to regenerate.  */
+
+/* Main header file for the bfd library -- portable access to object files.
+
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+   Contributed by Cygnus Support.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __KERNEL__
+#include <asm/ansidecl.h>
+#else  /* __KERNEL__ */
+#include "ansidecl.h"
+#include "symcat.h"
+#endif /* __KERNEL__ */
+#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+#ifndef SABER
+/* This 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 XCONCAT2 macro will
+   cause the inner CONCAT2 macros to be evaluated first, producing
+   still-valid pp-tokens.  Then the final concatenation can be done.  */
+#undef CONCAT4
+#define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d))
+#endif
+#endif
+
+/* The word size used by BFD on the host.  This may be 64 with a 32
+   bit target if the host is 64 bit, or if other 64 bit targets have
+   been selected with --enable-targets, or if --enable-64-bit-bfd.  */
+#define BFD_ARCH_SIZE 64
+
+/* The word size of the default bfd target.  */
+#define BFD_DEFAULT_TARGET_SIZE 64
+
+#define BFD_HOST_64BIT_LONG 1
+#define BFD_HOST_LONG_LONG 1
+#if 1
+#define BFD_HOST_64_BIT long
+#define BFD_HOST_U_64_BIT unsigned long
+typedef BFD_HOST_64_BIT bfd_int64_t;
+typedef BFD_HOST_U_64_BIT bfd_uint64_t;
+#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;
+
+/* Boolean type used in bfd.  Too many systems define their own
+   versions of "boolean" for us to safely typedef a "boolean" of
+   our own.  Using an enum for "bfd_boolean" has its own set of
+   problems, with strange looking casts required to avoid warnings
+   on some older compilers.  Thus we just use an int.
+
+   General rule: Functions which are bfd_boolean return TRUE on
+   success and FALSE on failure (unless they're a predicate).  */
+
+typedef int bfd_boolean;
+#undef FALSE
+#undef TRUE
+#define FALSE 0
+#define TRUE 1
+
+#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 HALF_BFD_SIZE_TYPE \
+  (((bfd_size_type) 1) << (8 * sizeof (bfd_size_type) / 2))
+
+#ifndef BFD_HOST_64_BIT
+/* Fall back on a 32 bit type.  The idea is to make these types always
+   available for function return types, but in the case that
+   BFD_HOST_64_BIT is undefined such a function should abort or
+   otherwise signal an error.  */
+typedef bfd_signed_vma bfd_int64_t;
+typedef bfd_vma bfd_uint64_t;
+#endif
+
+/* An offset into a file.  BFD always uses the largest possible offset
+   based on the build time availability of fseek, fseeko, or fseeko64.  */
+typedef BFD_HOST_64_BIT file_ptr;
+typedef unsigned BFD_HOST_64_BIT ufile_ptr;
+
+extern void bfd_sprintf_vma (bfd *, char *, bfd_vma);
+extern void bfd_fprintf_vma (bfd *, void *, bfd_vma);
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+#define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+\f
+/* File formats.  */
+
+typedef enum bfd_format
+{
+  bfd_unknown = 0,     /* File format is unknown.  */
+  bfd_object,          /* Linker/assembler/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
+
+/* The sections in this BFD specify a memory page.  */
+#define HAS_LOAD_PAGE 0x1000
+
+/* This BFD has been created by the linker and doesn't correspond
+   to any input file.  */
+#define BFD_LINKER_CREATED 0x2000
+\f
+/* 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.  */
+  union
+  {
+    file_ptr pos;
+    bfd *abfd;
+  } u;                 /* bfd* or file position.  */
+  int namidx;          /* Index into string table.  */
+};
+\f
+/* Linenumber stuff.  */
+typedef struct lineno_cache_entry
+{
+  unsigned int line_number;    /* Linenumber from start of function.  */
+  union
+  {
+    struct bfd_symbol *sym;    /* Function name.  */
+    bfd_vma offset;                    /* Offset into section.  */
+  } u;
+}
+alent;
+\f
+/* Object and core file sections.  */
+
+#define        align_power(addr, align)        \
+  (((addr) + ((bfd_vma) 1 << (align)) - 1) & ((bfd_vma) -1 << (align)))
+
+typedef struct bfd_section *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_lma(bfd, ptr) ((ptr)->lma + 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) ((ptr)->size)
+#define bfd_get_section_size(ptr) ((ptr)->size)
+#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 = 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)
+/* Find the address one past the end of SEC.  */
+#define bfd_get_section_limit(bfd, sec) \
+  (((sec)->rawsize ? (sec)->rawsize : (sec)->size) \
+   / bfd_octets_per_byte (bfd))
+
+typedef struct stat stat_type;
+\f
+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 (int);
+\f
+/* 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)
+    (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
+   /* An objalloc for this hash table.  This is a struct objalloc *,
+     but we use void * to avoid requiring the inclusion of objalloc.h.  */
+  void *memory;
+};
+
+/* Initialize a hash table.  */
+extern bfd_boolean bfd_hash_table_init
+  (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 bfd_boolean bfd_hash_table_init_n
+  (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
+  (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
+  (struct bfd_hash_table *, const char *, bfd_boolean create,
+   bfd_boolean copy);
+
+/* Replace an entry in a hash table.  */
+extern void bfd_hash_replace
+  (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
+  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
+
+/* Grab some space for a hash table entry.  */
+extern void *bfd_hash_allocate
+  (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
+  (struct bfd_hash_table *,
+   bfd_boolean (*) (struct bfd_hash_entry *, void *),
+   void *info);
+
+/* Allows the default size of a hash table to be configured. New hash
+   tables allocated using bfd_hash_table_init will be created with
+   this size.  */
+extern void bfd_hash_set_default_size (bfd_size_type);
+
+/* This structure is used to keep track of stabs in sections
+   information while linking.  */
+
+struct stab_info
+{
+  /* A hash table used to hold stabs strings.  */
+  struct bfd_strtab_hash *strings;
+  /* The header file hash table.  */
+  struct bfd_hash_table includes;
+  /* The first .stabstr section.  */
+  struct bfd_section *stabstr;
+};
+
+#define COFF_SWAP_TABLE (void *) &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_bread (void *, bfd_size_type, bfd *);
+extern bfd_size_type bfd_bwrite (const void *, bfd_size_type, bfd *);
+extern int bfd_seek (bfd *, file_ptr, int);
+extern file_ptr bfd_tell (bfd *);
+extern int bfd_flush (bfd *);
+extern int bfd_stat (bfd *, struct stat *);
+
+/* Deprecated old routines.  */
+#if __GNUC__
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD)                           \
+  (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__),     \
+   bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD)                          \
+  (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__),    \
+   bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#else
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD)                           \
+  (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \
+   bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD)                          \
+  (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\
+   bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#endif
+extern void warn_deprecated (const char *, const char *, int, const char *);
+
+/* 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_family_coff(abfd) \
+  (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \
+   bfd_get_flavour (abfd) == bfd_target_xcoff_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_dynamic_symcount(abfd) ((abfd)->dynsymcount)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE)
+
+extern bfd_boolean bfd_cache_close
+  (bfd *abfd);
+/* NB: This declaration should match the autogenerated one in libbfd.h.  */
+
+extern bfd_boolean bfd_cache_close_all (void);
+
+extern bfd_boolean bfd_record_phdr
+  (bfd *, unsigned long, bfd_boolean, flagword, bfd_boolean, bfd_vma,
+   bfd_boolean, bfd_boolean, unsigned int, struct bfd_section **);
+
+/* Byte swapping routines.  */
+
+bfd_uint64_t bfd_getb64 (const void *);
+bfd_uint64_t bfd_getl64 (const void *);
+bfd_int64_t bfd_getb_signed_64 (const void *);
+bfd_int64_t bfd_getl_signed_64 (const void *);
+bfd_vma bfd_getb32 (const void *);
+bfd_vma bfd_getl32 (const void *);
+bfd_signed_vma bfd_getb_signed_32 (const void *);
+bfd_signed_vma bfd_getl_signed_32 (const void *);
+bfd_vma bfd_getb16 (const void *);
+bfd_vma bfd_getl16 (const void *);
+bfd_signed_vma bfd_getb_signed_16 (const void *);
+bfd_signed_vma bfd_getl_signed_16 (const void *);
+void bfd_putb64 (bfd_uint64_t, void *);
+void bfd_putl64 (bfd_uint64_t, void *);
+void bfd_putb32 (bfd_vma, void *);
+void bfd_putl32 (bfd_vma, void *);
+void bfd_putb16 (bfd_vma, void *);
+void bfd_putl16 (bfd_vma, void *);
+
+/* Byte swapping routines which take size and endiannes as arguments.  */
+
+bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean);
+void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean);
+
+extern bfd_boolean bfd_section_already_linked_table_init (void);
+extern void bfd_section_already_linked_table_free (void);
+\f
+/* Externally visible ECOFF routines.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct bfd_symbol;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value
+  (bfd * abfd);
+extern bfd_boolean bfd_ecoff_set_gp_value
+  (bfd *abfd, bfd_vma gp_value);
+extern bfd_boolean bfd_ecoff_set_regmasks
+  (bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+   unsigned long *cprmask);
+extern void *bfd_ecoff_debug_init
+  (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
+  (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+   const struct ecoff_debug_swap *output_swap, struct bfd_link_info *);
+extern bfd_boolean bfd_ecoff_debug_accumulate
+  (void *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 bfd_boolean bfd_ecoff_debug_accumulate_other
+  (void *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 bfd_boolean bfd_ecoff_debug_externals
+  (bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap, bfd_boolean relocatable,
+   bfd_boolean (*get_extr) (struct bfd_symbol *, struct ecoff_extr *),
+   void (*set_index) (struct bfd_symbol *, bfd_size_type));
+extern bfd_boolean bfd_ecoff_debug_one_external
+  (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
+  (bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap);
+extern bfd_boolean bfd_ecoff_write_debug
+  (bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap, file_ptr where);
+extern bfd_boolean bfd_ecoff_write_accumulated_debug
+  (void *handle, bfd *abfd, struct ecoff_debug_info *debug,
+   const struct ecoff_debug_swap *swap,
+   struct bfd_link_info *info, file_ptr where);
+
+/* Externally visible ELF routines.  */
+
+struct bfd_link_needed_list
+{
+  struct bfd_link_needed_list *next;
+  bfd *by;
+  const char *name;
+};
+
+enum dynamic_lib_link_class {
+  DYN_NORMAL = 0,
+  DYN_AS_NEEDED = 1,
+  DYN_DT_NEEDED = 2,
+  DYN_NO_ADD_NEEDED = 4,
+  DYN_NO_NEEDED = 8
+};
+
+extern bfd_boolean bfd_elf_record_link_assignment
+  (struct bfd_link_info *, const char *, bfd_boolean);
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_elf_get_bfd_needed_list
+  (bfd *, struct bfd_link_needed_list **);
+extern bfd_boolean bfd_elf_size_dynamic_sections
+  (bfd *, const char *, const char *, const char *, const char * const *,
+   struct bfd_link_info *, struct bfd_section **,
+   struct bfd_elf_version_tree *);
+extern bfd_boolean bfd_elf_size_dynsym_hash_dynstr
+  (bfd *, struct bfd_link_info *);
+extern void bfd_elf_set_dt_needed_name
+  (bfd *, const char *);
+extern const char *bfd_elf_get_dt_soname
+  (bfd *);
+extern void bfd_elf_set_dyn_lib_class
+  (bfd *, int);
+extern int bfd_elf_get_dyn_lib_class
+  (bfd *);
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_elf_discard_info
+  (bfd *, struct bfd_link_info *);
+extern unsigned int _bfd_elf_default_action_discarded
+  (struct bfd_section *);
+
+/* Return an upper bound on the number of bytes required to store a
+   copy of ABFD's program header table entries.  Return -1 if an error
+   occurs; bfd_get_error will return an appropriate code.  */
+extern long bfd_get_elf_phdr_upper_bound
+  (bfd *abfd);
+
+/* Copy ABFD's program header table entries to *PHDRS.  The entries
+   will be stored as an array of Elf_Internal_Phdr structures, as
+   defined in include/elf/internal.h.  To find out how large the
+   buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+   Return the number of program header table entries read, or -1 if an
+   error occurs; bfd_get_error will return an appropriate code.  */
+extern int bfd_get_elf_phdrs
+  (bfd *abfd, void *phdrs);
+
+/* Create a new BFD as if by bfd_openr.  Rather than opening a file,
+   reconstruct an ELF file by reading the segments out of remote memory
+   based on the ELF file header at EHDR_VMA and the ELF program headers it
+   points to.  If not null, *LOADBASEP is filled in with the difference
+   between the VMAs from which the segments were read, and the VMAs the
+   file headers (and hence BFD's idea of each section's VMA) put them at.
+
+   The function TARGET_READ_MEMORY is called to copy LEN bytes from the
+   remote memory at target address VMA into the local buffer at MYADDR; it
+   should return zero on success or an `errno' code on failure.  TEMPL must
+   be a BFD for an ELF target with the word size and byte order found in
+   the remote memory.  */
+extern bfd *bfd_elf_bfd_from_remote_memory
+  (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep,
+   int (*target_read_memory) (bfd_vma vma, bfd_byte *myaddr, int len));
+
+/* Return the arch_size field of an elf bfd, or -1 if not elf.  */
+extern int bfd_get_arch_size
+  (bfd *);
+
+/* Return TRUE if address "naturally" sign extends, or -1 if not elf.  */
+extern int bfd_get_sign_extend_vma
+  (bfd *);
+
+extern struct bfd_section *_bfd_elf_tls_setup
+  (bfd *, struct bfd_link_info *);
+
+extern void _bfd_elf_provide_symbol
+  (struct bfd_link_info *, const char *, bfd_vma, struct bfd_section *);
+
+extern void _bfd_elf_provide_section_bound_symbols
+  (struct bfd_link_info *, struct bfd_section *, const char *, const char *);
+
+extern void _bfd_elf_fix_excluded_sec_syms
+  (bfd *, struct bfd_link_info *);
+
+extern bfd_boolean bfd_m68k_elf32_create_embedded_relocs
+  (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *,
+   char **);
+
+/* SunOS shared library support routines for the linker.  */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_sunos_record_link_assignment
+  (bfd *, struct bfd_link_info *, const char *);
+extern bfd_boolean bfd_sunos_size_dynamic_sections
+  (bfd *, struct bfd_link_info *, struct bfd_section **,
+   struct bfd_section **, struct bfd_section **);
+
+/* Linux shared library support routines for the linker.  */
+
+extern bfd_boolean bfd_i386linux_size_dynamic_sections
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_m68klinux_size_dynamic_sections
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean bfd_sparclinux_size_dynamic_sections
+  (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.  */
+  void *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
+  (bfd_window *);
+extern void bfd_free_window
+  (bfd_window *);
+extern bfd_boolean bfd_get_file_window
+  (bfd *, file_ptr, bfd_size_type, bfd_window *, bfd_boolean);
+
+/* XCOFF support routines for the linker.  */
+
+extern bfd_boolean bfd_xcoff_link_record_set
+  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_size_type);
+extern bfd_boolean bfd_xcoff_import_symbol
+  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_vma,
+   const char *, const char *, const char *, unsigned int);
+extern bfd_boolean bfd_xcoff_export_symbol
+  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *);
+extern bfd_boolean bfd_xcoff_link_count_reloc
+  (bfd *, struct bfd_link_info *, const char *);
+extern bfd_boolean bfd_xcoff_record_link_assignment
+  (bfd *, struct bfd_link_info *, const char *);
+extern bfd_boolean bfd_xcoff_size_dynamic_sections
+  (bfd *, struct bfd_link_info *, const char *, const char *,
+   unsigned long, unsigned long, unsigned long, bfd_boolean,
+   int, bfd_boolean, bfd_boolean, struct bfd_section **, bfd_boolean);
+extern bfd_boolean bfd_xcoff_link_generate_rtinit
+  (bfd *, const char *, const char *, bfd_boolean);
+
+/* XCOFF support routines for ar.  */
+extern bfd_boolean bfd_xcoff_ar_archive_set_magic
+  (bfd *, char *);
+
+/* Externally visible COFF routines.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern bfd_boolean bfd_coff_get_syment
+  (bfd *, struct bfd_symbol *, struct internal_syment *);
+
+extern bfd_boolean bfd_coff_get_auxent
+  (bfd *, struct bfd_symbol *, int, union internal_auxent *);
+
+extern bfd_boolean bfd_coff_set_symbol_class
+  (bfd *, struct bfd_symbol *, unsigned int);
+
+extern bfd_boolean bfd_m68k_coff_create_embedded_relocs
+  (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **);
+
+/* ARM Interworking support.  Called from linker.  */
+extern bfd_boolean bfd_arm_allocate_interworking_sections
+  (struct bfd_link_info *);
+
+extern bfd_boolean bfd_arm_process_before_allocation
+  (bfd *, struct bfd_link_info *, int);
+
+extern bfd_boolean bfd_arm_get_bfd_for_interworking
+  (bfd *, struct bfd_link_info *);
+
+/* PE ARM Interworking support.  Called from linker.  */
+extern bfd_boolean bfd_arm_pe_allocate_interworking_sections
+  (struct bfd_link_info *);
+
+extern bfd_boolean bfd_arm_pe_process_before_allocation
+  (bfd *, struct bfd_link_info *, int);
+
+extern bfd_boolean bfd_arm_pe_get_bfd_for_interworking
+  (bfd *, struct bfd_link_info *);
+
+/* ELF ARM Interworking support.  Called from linker.  */
+extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections
+  (struct bfd_link_info *);
+
+extern bfd_boolean bfd_elf32_arm_process_before_allocation
+  (bfd *, struct bfd_link_info *, int);
+
+void bfd_elf32_arm_set_target_relocs
+  (struct bfd_link_info *, int, char *, int, int);
+
+extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
+  (bfd *, struct bfd_link_info *);
+
+extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd
+  (bfd *, struct bfd_link_info *);
+
+/* ELF ARM mapping symbol support */
+extern bfd_boolean bfd_is_arm_mapping_symbol_name
+  (const char * name);
+
+/* ARM Note section processing.  */
+extern bfd_boolean bfd_arm_merge_machines
+  (bfd *, bfd *);
+
+extern bfd_boolean bfd_arm_update_notes
+  (bfd *, const char *);
+
+extern unsigned int bfd_arm_get_mach_from_notes
+  (bfd *, const char *);
+
+/* TI COFF load page support.  */
+extern void bfd_ticoff_set_section_load_page
+  (struct bfd_section *, int);
+
+extern int bfd_ticoff_get_section_load_page
+  (struct bfd_section *);
+
+/* H8/300 functions.  */
+extern bfd_vma bfd_h8300_pad_address
+  (bfd *, bfd_vma);
+
+/* IA64 Itanium code generation.  Called from linker.  */
+extern void bfd_elf32_ia64_after_parse
+  (int);
+
+extern void bfd_elf64_ia64_after_parse
+  (int);
+
+/* 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 coff_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;
+};
+
+extern struct coff_comdat_info *bfd_coff_get_comdat_section
+  (bfd *, struct bfd_section *);
+
+/* Extracted from init.c.  */
+void bfd_init (void);
+
+/* Extracted from opncls.c.  */
+bfd *bfd_fopen (const char *filename, const char *target,
+    const char *mode, int fd);
+
+bfd *bfd_openr (const char *filename, const char *target);
+
+bfd *bfd_fdopenr (const char *filename, const char *target, int fd);
+
+bfd *bfd_openstreamr (const char *, const char *, void *);
+
+bfd *bfd_openr_iovec (const char *filename, const char *target,
+    void *(*open) (struct bfd *nbfd,
+    void *open_closure),
+    void *open_closure,
+    file_ptr (*pread) (struct bfd *nbfd,
+    void *stream,
+    void *buf,
+    file_ptr nbytes,
+    file_ptr offset),
+    int (*close) (struct bfd *nbfd,
+    void *stream));
+
+bfd *bfd_openw (const char *filename, const char *target);
+
+bfd_boolean bfd_close (bfd *abfd);
+
+bfd_boolean bfd_close_all_done (bfd *);
+
+bfd *bfd_create (const char *filename, bfd *templ);
+
+bfd_boolean bfd_make_writable (bfd *abfd);
+
+bfd_boolean bfd_make_readable (bfd *abfd);
+
+unsigned long bfd_calc_gnu_debuglink_crc32
+   (unsigned long crc, const unsigned char *buf, bfd_size_type len);
+
+char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir);
+
+struct bfd_section *bfd_create_gnu_debuglink_section
+   (bfd *abfd, const char *filename);
+
+bfd_boolean bfd_fill_in_gnu_debuglink_section
+   (bfd *abfd, struct bfd_section *sect, const char *filename);
+
+/* Extracted from libbfd.c.  */
+
+/* Byte swapping macros for user section data.  */
+
+#define bfd_put_8(abfd, val, ptr) \
+  ((void) (*((unsigned char *) (ptr)) = (val) & 0xff))
+#define bfd_put_signed_8 \
+  bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+  (*(unsigned char *) (ptr) & 0xff)
+#define bfd_get_signed_8(abfd, ptr) \
+  (((*(unsigned char *) (ptr) & 0xff) ^ 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_vma) 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))
+
+/* Aliases for the above, which should eventually go away.  */
+
+#define H_PUT_64  bfd_h_put_64
+#define H_PUT_32  bfd_h_put_32
+#define H_PUT_16  bfd_h_put_16
+#define H_PUT_8   bfd_h_put_8
+#define H_PUT_S64 bfd_h_put_signed_64
+#define H_PUT_S32 bfd_h_put_signed_32
+#define H_PUT_S16 bfd_h_put_signed_16
+#define H_PUT_S8  bfd_h_put_signed_8
+#define H_GET_64  bfd_h_get_64
+#define H_GET_32  bfd_h_get_32
+#define H_GET_16  bfd_h_get_16
+#define H_GET_8   bfd_h_get_8
+#define H_GET_S64 bfd_h_get_signed_64
+#define H_GET_S32 bfd_h_get_signed_32
+#define H_GET_S16 bfd_h_get_signed_16
+#define H_GET_S8  bfd_h_get_signed_8
+
+
+/* Extracted from bfdio.c.  */
+long bfd_get_mtime (bfd *abfd);
+
+long bfd_get_size (bfd *abfd);
+
+/* Extracted from bfdwin.c.  */
+/* Extracted from section.c.  */
+typedef struct bfd_section
+{
+  /* 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;
+
+  /* A unique sequence number.  */
+  int id;
+
+  /* Which section in the bfd; 0..n-1 as sections are created in a bfd.  */
+  int index;
+
+  /* The next section in the list belonging to the BFD, or NULL.  */
+  struct bfd_section *next;
+
+  /* The previous section in the list belonging to the BFD, or NULL.  */
+  struct bfd_section *prev;
+
+  /* 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
+
+  /* A signal to the OS that the section contains read only data.  */
+#define SEC_READONLY   0x008
+
+  /* The section contains code only.  */
+#define SEC_CODE       0x010
+
+  /* The section contains data only.  */
+#define SEC_DATA       0x020
+
+  /* The section will reside in ROM.  */
+#define SEC_ROM        0x040
+
+  /* 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 0x080
+
+  /* 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 0x100
+
+  /* An instruction to the linker to not output the section
+     even if it has information which would normally be written.  */
+#define SEC_NEVER_LOAD 0x200
+
+  /* The section contains thread local data.  */
+#define SEC_THREAD_LOCAL 0x400
+
+  /* The section has GOT references.  This flag is only for the
+     linker, and is currently only used by the elf32-hppa back end.
+     It will be set if global offset table references were detected
+     in this section, which indicate to the linker that the section
+     contains PIC code, and must be handled specially when doing a
+     static link.  */
+#define SEC_HAS_GOT_REF 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 0x1000
+
+  /* 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 0x2000
+
+  /* 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 0x4000
+
+  /* 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 0x8000
+
+  /* The contents of this section are to be sorted based on the sum of
+     the symbol and addend values specified by the associated relocation
+     entries.  Entries without associated relocation entries will be
+     appended to the end of the section in an unspecified order.  */
+#define SEC_SORT_ENTRIES 0x10000
+
+  /* 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 0x20000
+
+  /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+     should handle duplicate sections.  */
+#define SEC_LINK_DUPLICATES 0x40000
+
+  /* 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 0x80000
+
+  /* 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 0x100000
+
+  /* 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 \
+  (SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE)
+
+  /* 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 0x200000
+
+  /* This section should not be subject to garbage collection.  */
+#define SEC_KEEP 0x400000
+
+  /* This section contains "short" data, and should be placed
+     "near" the GP.  */
+#define SEC_SMALL_DATA 0x800000
+
+  /* Attempt to merge identical entities in the section.
+     Entity size is given in the entsize field.  */
+#define SEC_MERGE 0x1000000
+
+  /* If given with SEC_MERGE, entities to merge are zero terminated
+     strings where entsize specifies character size instead of fixed
+     size entries.  */
+#define SEC_STRINGS 0x2000000
+
+  /* This section contains data about section groups.  */
+#define SEC_GROUP 0x4000000
+
+  /* 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 0x10000000
+
+  /* This section contains data which may be shared with other
+     executables or shared objects. This is for COFF only.  */
+#define SEC_COFF_SHARED 0x20000000
+
+  /* When a section with this flag is being linked, then if the size of
+     the input section is less than a page, it should not cross a page
+     boundary.  If the size of the input section is one page or more,
+     it should be aligned on a page boundary.  This is for TI
+     TMS320C54X only.  */
+#define SEC_TIC54X_BLOCK 0x40000000
+
+  /* Conditionally link this section; do not link if there are no
+     references found to any symbol in the section.  This is for TI
+     TMS320C54X only.  */
+#define SEC_TIC54X_CLINK 0x80000000
+
+  /*  End of section flags.  */
+
+  /* Some internal packed boolean fields.  */
+
+  /* See the vma field.  */
+  unsigned int user_set_vma : 1;
+
+  /* A mark flag used by some of the linker backends.  */
+  unsigned int linker_mark : 1;
+
+  /* Another mark flag used by some of the linker backends.  Set for
+     output sections that have an input section.  */
+  unsigned int linker_has_input : 1;
+
+  /* Mark flags used by some linker backends for garbage collection.  */
+  unsigned int gc_mark : 1;
+  unsigned int gc_mark_from_eh : 1;
+
+  /* The following flags are used by the ELF linker. */
+
+  /* Mark sections which have been allocated to segments.  */
+  unsigned int segment_mark : 1;
+
+  /* Type of sec_info information.  */
+  unsigned int sec_info_type:3;
+#define ELF_INFO_TYPE_NONE      0
+#define ELF_INFO_TYPE_STABS     1
+#define ELF_INFO_TYPE_MERGE     2
+#define ELF_INFO_TYPE_EH_FRAME  3
+#define ELF_INFO_TYPE_JUST_SYMS 4
+
+  /* Nonzero if this section uses RELA relocations, rather than REL.  */
+  unsigned int use_rela_p:1;
+
+  /* Bits used by various backends.  The generic code doesn't touch
+     these fields.  */
+
+  /* Nonzero if this section has TLS related relocations.  */
+  unsigned int has_tls_reloc:1;
+
+  /* Nonzero if this section has a gp reloc.  */
+  unsigned int has_gp_reloc:1;
+
+  /* Nonzero if this section needs the relax finalize pass.  */
+  unsigned int need_finalize_relax:1;
+
+  /* Whether relocations have been processed.  */
+  unsigned int reloc_done : 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 octets, as it will be output.
+     Contains a value even if the section has no contents (e.g., the
+     size of <<.bss>>).  */
+  bfd_size_type size;
+
+  /* For input sections, the original size on disk of the section, in
+     octets.  This field is used by the linker relaxation code.  It is
+     currently only set for sections where the linker relaxation scheme
+     doesn't cache altered section and reloc contents (stabs, eh_frame,
+     SEC_MERGE, some coff relaxing targets), and thus the original size
+     needs to be kept to read the section multiple times.
+     For output sections, rawsize holds the section size calculated on
+     a previous linker relaxation pass.  */
+  bfd_size_type rawsize;
+
+  /* If this section is going to be output, then this value is the
+     offset in *bytes* into the output section of the first byte in the
+     input section (byte ==> smallest addressable unit on the
+     target).  In most cases, if this was going to start at the
+     100th octet (8-bit quantity) in the output section, this value
+     would be 100.  However, if the target byte size is 16 bits
+     (bfd_octets_per_byte is "2"), this value would be 50.  */
+  bfd_vma output_offset;
+
+  /* The output section through which to map on output.  */
+  struct bfd_section *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.  */
+  void *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;
+
+  /* Entity size for merging purposes.  */
+  unsigned int entsize;
+
+  /* Points to the kept section if this section is a link-once section,
+     and is discarded.  */
+  struct bfd_section *kept_section;
+
+  /* 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;
+
+  void *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 bfd_symbol *symbol;
+  struct bfd_symbol **symbol_ptr_ptr;
+
+  /* Early in the link process, map_head and map_tail are used to build
+     a list of input sections attached to an output section.  Later,
+     output sections use these fields for a list of bfd_link_order
+     structs.  */
+  union {
+    struct bfd_link_order *link_order;
+    struct bfd_section *s;
+  } map_head, map_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 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 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 asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+/* Pointer to the indirect section.  */
+extern asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+#define bfd_is_const_section(SEC)              \
+ (   ((SEC) == bfd_abs_section_ptr)            \
+  || ((SEC) == bfd_und_section_ptr)            \
+  || ((SEC) == bfd_com_section_ptr)            \
+  || ((SEC) == bfd_ind_section_ptr))
+
+extern const struct bfd_symbol * const bfd_abs_symbol;
+extern const struct bfd_symbol * const bfd_com_symbol;
+extern const struct bfd_symbol * const bfd_und_symbol;
+extern const struct bfd_symbol * const bfd_ind_symbol;
+
+/* Macros to handle insertion and deletion of a bfd's sections.  These
+   only handle the list pointers, ie. do not adjust section_count,
+   target_index etc.  */
+#define bfd_section_list_remove(ABFD, S) \
+  do                                                   \
+    {                                                  \
+      asection *_s = S;                                \
+      asection *_next = _s->next;                      \
+      asection *_prev = _s->prev;                      \
+      if (_prev)                                       \
+        _prev->next = _next;                           \
+      else                                             \
+        (ABFD)->sections = _next;                      \
+      if (_next)                                       \
+        _next->prev = _prev;                           \
+      else                                             \
+        (ABFD)->section_last = _prev;                  \
+    }                                                  \
+  while (0)
+#define bfd_section_list_append(ABFD, S) \
+  do                                                   \
+    {                                                  \
+      asection *_s = S;                                \
+      bfd *_abfd = ABFD;                               \
+      _s->next = NULL;                                 \
+      if (_abfd->section_last)                         \
+        {                                              \
+          _s->prev = _abfd->section_last;              \
+          _abfd->section_last->next = _s;              \
+        }                                              \
+      else                                             \
+        {                                              \
+          _s->prev = NULL;                             \
+          _abfd->sections = _s;                        \
+        }                                              \
+      _abfd->section_last = _s;                        \
+    }                                                  \
+  while (0)
+#define bfd_section_list_prepend(ABFD, S) \
+  do                                                   \
+    {                                                  \
+      asection *_s = S;                                \
+      bfd *_abfd = ABFD;                               \
+      _s->prev = NULL;                                 \
+      if (_abfd->sections)                             \
+        {                                              \
+          _s->next = _abfd->sections;                  \
+          _abfd->sections->prev = _s;                  \
+        }                                              \
+      else                                             \
+        {                                              \
+          _s->next = NULL;                             \
+          _abfd->section_last = _s;                    \
+        }                                              \
+      _abfd->sections = _s;                            \
+    }                                                  \
+  while (0)
+#define bfd_section_list_insert_after(ABFD, A, S) \
+  do                                                   \
+    {                                                  \
+      asection *_a = A;                                \
+      asection *_s = S;                                \
+      asection *_next = _a->next;                      \
+      _s->next = _next;                                \
+      _s->prev = _a;                                   \
+      _a->next = _s;                                   \
+      if (_next)                                       \
+        _next->prev = _s;                              \
+      else                                             \
+        (ABFD)->section_last = _s;                     \
+    }                                                  \
+  while (0)
+#define bfd_section_list_insert_before(ABFD, B, S) \
+  do                                                   \
+    {                                                  \
+      asection *_b = B;                                \
+      asection *_s = S;                                \
+      asection *_prev = _b->prev;                      \
+      _s->prev = _prev;                                \
+      _s->next = _b;                                   \
+      _b->prev = _s;                                   \
+      if (_prev)                                       \
+        _prev->next = _s;                              \
+      else                                             \
+        (ABFD)->sections = _s;                         \
+    }                                                  \
+  while (0)
+#define bfd_section_removed_from_list(ABFD, S) \
+  ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S))
+
+void bfd_section_list_clear (bfd *);
+
+asection *bfd_get_section_by_name (bfd *abfd, const char *name);
+
+asection *bfd_get_section_by_name_if
+   (bfd *abfd,
+    const char *name,
+    bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj),
+    void *obj);
+
+char *bfd_get_unique_section_name
+   (bfd *abfd, const char *templat, int *count);
+
+asection *bfd_make_section_old_way (bfd *abfd, const char *name);
+
+asection *bfd_make_section_anyway_with_flags
+   (bfd *abfd, const char *name, flagword flags);
+
+asection *bfd_make_section_anyway (bfd *abfd, const char *name);
+
+asection *bfd_make_section_with_flags
+   (bfd *, const char *name, flagword flags);
+
+asection *bfd_make_section (bfd *, const char *name);
+
+bfd_boolean bfd_set_section_flags
+   (bfd *abfd, asection *sec, flagword flags);
+
+void bfd_map_over_sections
+   (bfd *abfd,
+    void (*func) (bfd *abfd, asection *sect, void *obj),
+    void *obj);
+
+asection *bfd_sections_find_if
+   (bfd *abfd,
+    bfd_boolean (*operation) (bfd *abfd, asection *sect, void *obj),
+    void *obj);
+
+bfd_boolean bfd_set_section_size
+   (bfd *abfd, asection *sec, bfd_size_type val);
+
+bfd_boolean bfd_set_section_contents
+   (bfd *abfd, asection *section, const void *data,
+    file_ptr offset, bfd_size_type count);
+
+bfd_boolean bfd_get_section_contents
+   (bfd *abfd, asection *section, void *location, file_ptr offset,
+    bfd_size_type count);
+
+bfd_boolean bfd_malloc_and_get_section
+   (bfd *abfd, asection *section, bfd_byte **buf);
+
+bfd_boolean bfd_copy_private_section_data
+   (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))
+bfd_boolean bfd_generic_is_group_section (bfd *, const asection *sec);
+
+bfd_boolean bfd_generic_discard_group (bfd *abfd, asection *group);
+
+/* Extracted from archures.c.  */
+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
+#define bfd_mach_mcf5200  9
+#define bfd_mach_mcf5206e 10
+#define bfd_mach_mcf5307  11
+#define bfd_mach_mcf5407  12
+#define bfd_mach_mcf528x  13
+#define bfd_mach_mcfv4e   14
+#define bfd_mach_mcf521x   15
+#define bfd_mach_mcf5249   16
+#define bfd_mach_mcf547x   17
+#define bfd_mach_mcf548x   18
+  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_or32,      /* OpenRISC 32 */
+
+  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.  */
+#define bfd_mach_sparc_v8plusb         9 /* with cheetah add'ns.  */
+#define bfd_mach_sparc_v9b             10 /* with cheetah 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_v9b \
+   && (mach) != bfd_mach_sparc_sparclite_le)
+/* Nonzero if MACH is a 64 bit sparc architecture.  */
+#define bfd_mach_sparc_64bit_p(mach) \
+  ((mach) >= bfd_mach_sparc_v9 && (mach) != bfd_mach_sparc_v8plusb)
+  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_mips4120              4120
+#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_mips5400              5400
+#define bfd_mach_mips5500              5500
+#define bfd_mach_mips6000              6000
+#define bfd_mach_mips7000              7000
+#define bfd_mach_mips8000              8000
+#define bfd_mach_mips9000              9000
+#define bfd_mach_mips10000             10000
+#define bfd_mach_mips12000             12000
+#define bfd_mach_mips16                16
+#define bfd_mach_mips5                 5
+#define bfd_mach_mips_sb1              12310201 /* octal 'SB', 01 */
+#define bfd_mach_mipsisa32             32
+#define bfd_mach_mipsisa32r2           33
+#define bfd_mach_mipsisa64             64
+#define bfd_mach_mipsisa64r2           65
+  bfd_arch_i386,      /* Intel 386 */
+#define bfd_mach_i386_i386 1
+#define bfd_mach_i386_i8086 2
+#define bfd_mach_i386_i386_intel_syntax 3
+#define bfd_mach_x86_64 64
+#define bfd_mach_x86_64_intel_syntax 65
+  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_m98k,      /* Motorola 98xxx */
+  bfd_arch_pyramid,   /* Pyramid Technology */
+  bfd_arch_h8300,     /* Renesas H8/300 (formerly Hitachi H8/300) */
+#define bfd_mach_h8300    1
+#define bfd_mach_h8300h   2
+#define bfd_mach_h8300s   3
+#define bfd_mach_h8300hn  4
+#define bfd_mach_h8300sn  5
+#define bfd_mach_h8300sx  6
+#define bfd_mach_h8300sxn 7
+  bfd_arch_pdp11,     /* DEC PDP-11 */
+  bfd_arch_powerpc,   /* PowerPC */
+#define bfd_mach_ppc           32
+#define bfd_mach_ppc64         64
+#define bfd_mach_ppc_403       403
+#define bfd_mach_ppc_403gc     4030
+#define bfd_mach_ppc_505       505
+#define bfd_mach_ppc_601       601
+#define bfd_mach_ppc_602       602
+#define bfd_mach_ppc_603       603
+#define bfd_mach_ppc_ec603e    6031
+#define bfd_mach_ppc_604       604
+#define bfd_mach_ppc_620       620
+#define bfd_mach_ppc_630       630
+#define bfd_mach_ppc_750       750
+#define bfd_mach_ppc_860       860
+#define bfd_mach_ppc_a35       35
+#define bfd_mach_ppc_rs64ii    642
+#define bfd_mach_ppc_rs64iii   643
+#define bfd_mach_ppc_7400      7400
+#define bfd_mach_ppc_e500      500
+  bfd_arch_rs6000,    /* IBM RS/6000 */
+#define bfd_mach_rs6k          6000
+#define bfd_mach_rs6k_rs1      6001
+#define bfd_mach_rs6k_rsc      6003
+#define bfd_mach_rs6k_rs2      6002
+  bfd_arch_hppa,      /* HP PA RISC */
+#define bfd_mach_hppa10        10
+#define bfd_mach_hppa11        11
+#define bfd_mach_hppa20        20
+#define bfd_mach_hppa20w       25
+  bfd_arch_d10v,      /* Mitsubishi D10V */
+#define bfd_mach_d10v          1
+#define bfd_mach_d10v_ts2      2
+#define bfd_mach_d10v_ts3      3
+  bfd_arch_d30v,      /* Mitsubishi D30V */
+  bfd_arch_dlx,       /* DLX */
+  bfd_arch_m68hc11,   /* Motorola 68HC11 */
+  bfd_arch_m68hc12,   /* Motorola 68HC12 */
+#define bfd_mach_m6812_default 0
+#define bfd_mach_m6812         1
+#define bfd_mach_m6812s        2
+  bfd_arch_z8k,       /* Zilog Z8000 */
+#define bfd_mach_z8001         1
+#define bfd_mach_z8002         2
+  bfd_arch_h8500,     /* Renesas H8/500 (formerly Hitachi H8/500) */
+  bfd_arch_sh,        /* Renesas / SuperH SH (formerly Hitachi SH) */
+#define bfd_mach_sh            1
+#define bfd_mach_sh2        0x20
+#define bfd_mach_sh_dsp     0x2d
+#define bfd_mach_sh2a       0x2a
+#define bfd_mach_sh2a_nofpu 0x2b
+#define bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu 0x2a1
+#define bfd_mach_sh2a_nofpu_or_sh3_nommu 0x2a2
+#define bfd_mach_sh2a_or_sh4  0x2a3
+#define bfd_mach_sh2a_or_sh3e 0x2a4
+#define bfd_mach_sh2e       0x2e
+#define bfd_mach_sh3        0x30
+#define bfd_mach_sh3_nommu  0x31
+#define bfd_mach_sh3_dsp    0x3d
+#define bfd_mach_sh3e       0x3e
+#define bfd_mach_sh4        0x40
+#define bfd_mach_sh4_nofpu  0x41
+#define bfd_mach_sh4_nommu_nofpu  0x42
+#define bfd_mach_sh4a       0x4a
+#define bfd_mach_sh4a_nofpu 0x4b
+#define bfd_mach_sh4al_dsp  0x4d
+#define bfd_mach_sh5        0x50
+  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_unknown   0
+#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
+#define bfd_mach_arm_5TE       9
+#define bfd_mach_arm_XScale    10
+#define bfd_mach_arm_ep9312    11
+#define bfd_mach_arm_iWMMXt    12
+  bfd_arch_ns32k,     /* National Semiconductors ns32000 */
+  bfd_arch_w65,       /* WDC 65816 */
+  bfd_arch_tic30,     /* Texas Instruments TMS320C30 */
+  bfd_arch_tic4x,     /* Texas Instruments TMS320C3X/4X */
+#define bfd_mach_tic3x         30
+#define bfd_mach_tic4x         40
+  bfd_arch_tic54x,    /* Texas Instruments TMS320C54X */
+  bfd_arch_tic80,     /* TI TMS320c80 (MVP) */
+  bfd_arch_v850,      /* NEC V850 */
+#define bfd_mach_v850          1
+#define bfd_mach_v850e         'E'
+#define bfd_mach_v850e1        '1'
+  bfd_arch_arc,       /* ARC Cores */
+#define bfd_mach_arc_5         5
+#define bfd_mach_arc_6         6
+#define bfd_mach_arc_7         7
+#define bfd_mach_arc_8         8
+ bfd_arch_m32c,     /* Renesas M16C/M32C.  */
+#define bfd_mach_m16c        0x75
+#define bfd_mach_m32c        0x78
+  bfd_arch_m32r,      /* Renesas M32R (formerly Mitsubishi M32R/D) */
+#define bfd_mach_m32r          1 /* For backwards compatibility.  */
+#define bfd_mach_m32rx         'x'
+#define bfd_mach_m32r2         '2'
+  bfd_arch_mn10200,   /* Matsushita MN10200 */
+  bfd_arch_mn10300,   /* Matsushita MN10300 */
+#define bfd_mach_mn10300               300
+#define bfd_mach_am33          330
+#define bfd_mach_am33_2        332
+  bfd_arch_fr30,
+#define bfd_mach_fr30          0x46523330
+  bfd_arch_frv,
+#define bfd_mach_frv           1
+#define bfd_mach_frvsimple     2
+#define bfd_mach_fr300         300
+#define bfd_mach_fr400         400
+#define bfd_mach_fr450         450
+#define bfd_mach_frvtomcat     499     /* fr500 prototype */
+#define bfd_mach_fr500         500
+#define bfd_mach_fr550         550
+  bfd_arch_mcore,
+  bfd_arch_ia64,      /* HP/Intel ia64 */
+#define bfd_mach_ia64_elf64    64
+#define bfd_mach_ia64_elf32    32
+  bfd_arch_ip2k,      /* Ubicom IP2K microcontrollers. */
+#define bfd_mach_ip2022        1
+#define bfd_mach_ip2022ext     2
+ bfd_arch_iq2000,     /* Vitesse IQ2000.  */
+#define bfd_mach_iq2000        1
+#define bfd_mach_iq10          2
+  bfd_arch_ms1,
+#define bfd_mach_ms1           1
+#define bfd_mach_mrisc2        2
+  bfd_arch_pj,
+  bfd_arch_avr,       /* Atmel AVR microcontrollers.  */
+#define bfd_mach_avr1          1
+#define bfd_mach_avr2          2
+#define bfd_mach_avr3          3
+#define bfd_mach_avr4          4
+#define bfd_mach_avr5          5
+  bfd_arch_cr16c,       /* National Semiconductor CompactRISC. */
+#define bfd_mach_cr16c         1
+  bfd_arch_crx,       /*  National Semiconductor CRX.  */
+#define bfd_mach_crx           1
+  bfd_arch_cris,      /* Axis CRIS */
+#define bfd_mach_cris_v0_v10   255
+#define bfd_mach_cris_v32      32
+#define bfd_mach_cris_v10_v32  1032
+  bfd_arch_s390,      /* IBM s390 */
+#define bfd_mach_s390_31       31
+#define bfd_mach_s390_64       64
+  bfd_arch_openrisc,  /* OpenRISC */
+  bfd_arch_mmix,      /* Donald Knuth's educational processor.  */
+  bfd_arch_xstormy16,
+#define bfd_mach_xstormy16     1
+  bfd_arch_msp430,    /* Texas Instruments MSP430 architecture.  */
+#define bfd_mach_msp11          11
+#define bfd_mach_msp110         110
+#define bfd_mach_msp12          12
+#define bfd_mach_msp13          13
+#define bfd_mach_msp14          14
+#define bfd_mach_msp15          15
+#define bfd_mach_msp16          16
+#define bfd_mach_msp31          31
+#define bfd_mach_msp32          32
+#define bfd_mach_msp33          33
+#define bfd_mach_msp41          41
+#define bfd_mach_msp42          42
+#define bfd_mach_msp43          43
+#define bfd_mach_msp44          44
+  bfd_arch_xtensa,    /* Tensilica's Xtensa cores.  */
+#define bfd_mach_xtensa        1
+   bfd_arch_maxq,     /* Dallas MAXQ 10/20 */
+#define bfd_mach_maxq10    10
+#define bfd_mach_maxq20    20
+  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.
+     The default arch should be the first entry for an arch so that
+     all the entries for that arch can be accessed via <<next>>.  */
+  bfd_boolean the_default;
+  const struct bfd_arch_info * (*compatible)
+    (const struct bfd_arch_info *a, const struct bfd_arch_info *b);
+
+  bfd_boolean (*scan) (const struct bfd_arch_info *, const char *);
+
+  const struct bfd_arch_info *next;
+}
+bfd_arch_info_type;
+
+const char *bfd_printable_name (bfd *abfd);
+
+const bfd_arch_info_type *bfd_scan_arch (const char *string);
+
+const char **bfd_arch_list (void);
+
+const bfd_arch_info_type *bfd_arch_get_compatible
+   (const bfd *abfd, const bfd *bbfd, bfd_boolean accept_unknowns);
+
+void bfd_set_arch_info (bfd *abfd, const bfd_arch_info_type *arg);
+
+enum bfd_architecture bfd_get_arch (bfd *abfd);
+
+unsigned long bfd_get_mach (bfd *abfd);
+
+unsigned int bfd_arch_bits_per_byte (bfd *abfd);
+
+unsigned int bfd_arch_bits_per_address (bfd *abfd);
+
+const bfd_arch_info_type *bfd_get_arch_info (bfd *abfd);
+
+const bfd_arch_info_type *bfd_lookup_arch
+   (enum bfd_architecture arch, unsigned long machine);
+
+const char *bfd_printable_arch_mach
+   (enum bfd_architecture arch, unsigned long machine);
+
+unsigned int bfd_octets_per_byte (bfd *abfd);
+
+unsigned int bfd_arch_mach_octets_per_byte
+   (enum bfd_architecture arch, unsigned long machine);
+
+/* Extracted from reloc.c.  */
+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 bfd_symbol **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.  */
+  bfd_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 accommodated (e.g., i960 callj
+     instructions).  */
+  bfd_reloc_status_type (*special_function)
+    (bfd *, arelent *, struct bfd_symbol *, void *, asection *,
+     bfd *, char **);
+
+  /* The textual name of the relocation type.  */
+  char *name;
+
+  /* Some formats record a relocation addend in the section contents
+     rather than with the relocation.  For ELF formats this is the
+     distinction between USE_REL and USE_RELA (though the code checks
+     for USE_REL == 1/0).  The value of this field is TRUE if the
+     addend is recorded with the section contents; when performing a
+     partial link (ld -r) the section contents (the data) will be
+     modified.  The value of this field is FALSE if addends are
+     recorded with the relocation (in arelent.addend); when performing
+     a partial link the relocation will be modified.
+     All relocations for all ELF USE_RELA targets should set this field
+     to FALSE (values of TRUE should be looked on with suspicion).
+     However, the converse is not true: not all relocations of all ELF
+     USE_REL targets set this field to TRUE.  Why this is so is peculiar
+     to each particular target.  For relocs that aren't used in partial
+     links (e.g. GOT stuff) it doesn't matter what this is set to.  */
+  bfd_boolean partial_inplace;
+
+  /* src_mask selects the part of the instruction (or data) to be used
+     in the relocation sum.  If the target relocations don't have an
+     addend in the reloc, eg. ELF USE_REL, src_mask will normally equal
+     dst_mask to extract the addend from the section contents.  If
+     relocations do have an addend in the reloc, eg. ELF USE_RELA, this
+     field should be zero.  Non-zero values for ELF USE_RELA targets are
+     bogus as in those cases the value in the dst_mask part of the
+     section contents should be treated as garbage.  */
+  bfd_vma src_mask;
+
+  /* dst_mask selects which parts of the instruction (or data) are
+     replaced with a relocated value.  */
+  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.  */
+  bfd_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 != NULL)                                 \
+      {                                                 \
+        if (bfd_is_com_section (symbol->section))       \
+          {                                             \
+            relocation = 0;                             \
+          }                                             \
+        else                                            \
+          {                                             \
+            relocation = symbol->value;                 \
+          }                                             \
+      }                                                 \
+  }
+
+unsigned int bfd_get_reloc_size (reloc_howto_type *);
+
+typedef struct relent_chain
+{
+  arelent relent;
+  struct relent_chain *next;
+}
+arelent_chain;
+
+bfd_reloc_status_type bfd_check_overflow
+   (enum complain_overflow how,
+    unsigned int bitsize,
+    unsigned int rightshift,
+    unsigned int addrsize,
+    bfd_vma relocation);
+
+bfd_reloc_status_type bfd_perform_relocation
+   (bfd *abfd,
+    arelent *reloc_entry,
+    void *data,
+    asection *input_section,
+    bfd *output_bfd,
+    char **error_message);
+
+bfd_reloc_status_type bfd_install_relocation
+   (bfd *abfd,
+    arelent *reloc_entry,
+    void *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,
+
+/* Section relative relocations.  Some targets need this for DWARF2.  */
+  BFD_RELOC_32_SECREL,
+
+/* 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_64_PLT_PCREL,
+  BFD_RELOC_32_PLT_PCREL,
+  BFD_RELOC_24_PLT_PCREL,
+  BFD_RELOC_16_PLT_PCREL,
+  BFD_RELOC_8_PLT_PCREL,
+  BFD_RELOC_64_PLTOFF,
+  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_UA16,
+  BFD_RELOC_SPARC_UA32,
+  BFD_RELOC_SPARC_UA64,
+
+/* 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_PLT32,
+  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,
+
+/* SPARC TLS relocations  */
+  BFD_RELOC_SPARC_TLS_GD_HI22,
+  BFD_RELOC_SPARC_TLS_GD_LO10,
+  BFD_RELOC_SPARC_TLS_GD_ADD,
+  BFD_RELOC_SPARC_TLS_GD_CALL,
+  BFD_RELOC_SPARC_TLS_LDM_HI22,
+  BFD_RELOC_SPARC_TLS_LDM_LO10,
+  BFD_RELOC_SPARC_TLS_LDM_ADD,
+  BFD_RELOC_SPARC_TLS_LDM_CALL,
+  BFD_RELOC_SPARC_TLS_LDO_HIX22,
+  BFD_RELOC_SPARC_TLS_LDO_LOX10,
+  BFD_RELOC_SPARC_TLS_LDO_ADD,
+  BFD_RELOC_SPARC_TLS_IE_HI22,
+  BFD_RELOC_SPARC_TLS_IE_LO10,
+  BFD_RELOC_SPARC_TLS_IE_LD,
+  BFD_RELOC_SPARC_TLS_IE_LDX,
+  BFD_RELOC_SPARC_TLS_IE_ADD,
+  BFD_RELOC_SPARC_TLS_LE_HIX22,
+  BFD_RELOC_SPARC_TLS_LE_LOX10,
+  BFD_RELOC_SPARC_TLS_DTPMOD32,
+  BFD_RELOC_SPARC_TLS_DTPMOD64,
+  BFD_RELOC_SPARC_TLS_DTPOFF32,
+  BFD_RELOC_SPARC_TLS_DTPOFF64,
+  BFD_RELOC_SPARC_TLS_TPOFF32,
+  BFD_RELOC_SPARC_TLS_TPOFF64,
+
+/* 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)  */
+  BFD_RELOC_ALPHA_LITERAL,
+  BFD_RELOC_ALPHA_ELF_LITERAL,
+  BFD_RELOC_ALPHA_LITUSE,
+
+/* 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,
+
+/* The GPREL_HI/LO relocations together form a 32-bit offset from the
+GP register.  */
+  BFD_RELOC_ALPHA_GPREL_HI16,
+  BFD_RELOC_ALPHA_GPREL_LO16,
+
+/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must
+share a common GP, and the target address is adjusted for
+STO_ALPHA_STD_GPLOAD.  */
+  BFD_RELOC_ALPHA_BRSGP,
+
+/* Alpha thread-local storage relocations.  */
+  BFD_RELOC_ALPHA_TLSGD,
+  BFD_RELOC_ALPHA_TLSLDM,
+  BFD_RELOC_ALPHA_DTPMOD64,
+  BFD_RELOC_ALPHA_GOTDTPREL16,
+  BFD_RELOC_ALPHA_DTPREL64,
+  BFD_RELOC_ALPHA_DTPREL_HI16,
+  BFD_RELOC_ALPHA_DTPREL_LO16,
+  BFD_RELOC_ALPHA_DTPREL16,
+  BFD_RELOC_ALPHA_GOTTPREL16,
+  BFD_RELOC_ALPHA_TPREL64,
+  BFD_RELOC_ALPHA_TPREL_HI16,
+  BFD_RELOC_ALPHA_TPREL_LO16,
+  BFD_RELOC_ALPHA_TPREL16,
+
+/* 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,
+
+/* High 16 bits of 32-bit pc-relative value  */
+  BFD_RELOC_HI16_PCREL,
+
+/* High 16 bits of 32-bit pc-relative value, adjusted  */
+  BFD_RELOC_HI16_S_PCREL,
+
+/* Low 16 bits of pc-relative value  */
+  BFD_RELOC_LO16_PCREL,
+
+/* MIPS16 high 16 bits of 32-bit value.  */
+  BFD_RELOC_MIPS16_HI16,
+
+/* MIPS16 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_MIPS16_HI16_S,
+
+/* MIPS16 low 16 bits.  */
+  BFD_RELOC_MIPS16_LO16,
+
+/* Relocation against a MIPS literal section.  */
+  BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations.  */
+  BFD_RELOC_MIPS_GOT16,
+  BFD_RELOC_MIPS_CALL16,
+  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,
+  BFD_RELOC_MIPS_SHIFT5,
+  BFD_RELOC_MIPS_SHIFT6,
+  BFD_RELOC_MIPS_INSERT_A,
+  BFD_RELOC_MIPS_INSERT_B,
+  BFD_RELOC_MIPS_DELETE,
+  BFD_RELOC_MIPS_HIGHEST,
+  BFD_RELOC_MIPS_HIGHER,
+  BFD_RELOC_MIPS_SCN_DISP,
+  BFD_RELOC_MIPS_REL16,
+  BFD_RELOC_MIPS_RELGOT,
+  BFD_RELOC_MIPS_JALR,
+  BFD_RELOC_MIPS_TLS_DTPMOD32,
+  BFD_RELOC_MIPS_TLS_DTPREL32,
+  BFD_RELOC_MIPS_TLS_DTPMOD64,
+  BFD_RELOC_MIPS_TLS_DTPREL64,
+  BFD_RELOC_MIPS_TLS_GD,
+  BFD_RELOC_MIPS_TLS_LDM,
+  BFD_RELOC_MIPS_TLS_DTPREL_HI16,
+  BFD_RELOC_MIPS_TLS_DTPREL_LO16,
+  BFD_RELOC_MIPS_TLS_GOTTPREL,
+  BFD_RELOC_MIPS_TLS_TPREL32,
+  BFD_RELOC_MIPS_TLS_TPREL64,
+  BFD_RELOC_MIPS_TLS_TPREL_HI16,
+  BFD_RELOC_MIPS_TLS_TPREL_LO16,
+
+
+/* Fujitsu Frv Relocations.  */
+  BFD_RELOC_FRV_LABEL16,
+  BFD_RELOC_FRV_LABEL24,
+  BFD_RELOC_FRV_LO16,
+  BFD_RELOC_FRV_HI16,
+  BFD_RELOC_FRV_GPREL12,
+  BFD_RELOC_FRV_GPRELU12,
+  BFD_RELOC_FRV_GPREL32,
+  BFD_RELOC_FRV_GPRELHI,
+  BFD_RELOC_FRV_GPRELLO,
+  BFD_RELOC_FRV_GOT12,
+  BFD_RELOC_FRV_GOTHI,
+  BFD_RELOC_FRV_GOTLO,
+  BFD_RELOC_FRV_FUNCDESC,
+  BFD_RELOC_FRV_FUNCDESC_GOT12,
+  BFD_RELOC_FRV_FUNCDESC_GOTHI,
+  BFD_RELOC_FRV_FUNCDESC_GOTLO,
+  BFD_RELOC_FRV_FUNCDESC_VALUE,
+  BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
+  BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
+  BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+  BFD_RELOC_FRV_GOTOFF12,
+  BFD_RELOC_FRV_GOTOFFHI,
+  BFD_RELOC_FRV_GOTOFFLO,
+  BFD_RELOC_FRV_GETTLSOFF,
+  BFD_RELOC_FRV_TLSDESC_VALUE,
+  BFD_RELOC_FRV_GOTTLSDESC12,
+  BFD_RELOC_FRV_GOTTLSDESCHI,
+  BFD_RELOC_FRV_GOTTLSDESCLO,
+  BFD_RELOC_FRV_TLSMOFF12,
+  BFD_RELOC_FRV_TLSMOFFHI,
+  BFD_RELOC_FRV_TLSMOFFLO,
+  BFD_RELOC_FRV_GOTTLSOFF12,
+  BFD_RELOC_FRV_GOTTLSOFFHI,
+  BFD_RELOC_FRV_GOTTLSOFFLO,
+  BFD_RELOC_FRV_TLSOFF,
+  BFD_RELOC_FRV_TLSDESC_RELAX,
+  BFD_RELOC_FRV_GETTLSOFF_RELAX,
+  BFD_RELOC_FRV_TLSOFF_RELAX,
+  BFD_RELOC_FRV_TLSMOFF,
+
+
+/* This is a 24bit GOT-relative reloc for the mn10300.  */
+  BFD_RELOC_MN10300_GOTOFF24,
+
+/* This is a 32bit GOT-relative reloc for the mn10300, offset by two bytes
+in the instruction.  */
+  BFD_RELOC_MN10300_GOT32,
+
+/* This is a 24bit GOT-relative reloc for the mn10300, offset by two bytes
+in the instruction.  */
+  BFD_RELOC_MN10300_GOT24,
+
+/* This is a 16bit GOT-relative reloc for the mn10300, offset by two bytes
+in the instruction.  */
+  BFD_RELOC_MN10300_GOT16,
+
+/* Copy symbol at runtime.  */
+  BFD_RELOC_MN10300_COPY,
+
+/* Create GOT entry.  */
+  BFD_RELOC_MN10300_GLOB_DAT,
+
+/* Create PLT entry.  */
+  BFD_RELOC_MN10300_JMP_SLOT,
+
+/* Adjust by program base.  */
+  BFD_RELOC_MN10300_RELATIVE,
+
+
+/* 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,
+  BFD_RELOC_386_TLS_TPOFF,
+  BFD_RELOC_386_TLS_IE,
+  BFD_RELOC_386_TLS_GOTIE,
+  BFD_RELOC_386_TLS_LE,
+  BFD_RELOC_386_TLS_GD,
+  BFD_RELOC_386_TLS_LDM,
+  BFD_RELOC_386_TLS_LDO_32,
+  BFD_RELOC_386_TLS_IE_32,
+  BFD_RELOC_386_TLS_LE_32,
+  BFD_RELOC_386_TLS_DTPMOD32,
+  BFD_RELOC_386_TLS_DTPOFF32,
+  BFD_RELOC_386_TLS_TPOFF32,
+
+/* x86-64/elf relocations  */
+  BFD_RELOC_X86_64_GOT32,
+  BFD_RELOC_X86_64_PLT32,
+  BFD_RELOC_X86_64_COPY,
+  BFD_RELOC_X86_64_GLOB_DAT,
+  BFD_RELOC_X86_64_JUMP_SLOT,
+  BFD_RELOC_X86_64_RELATIVE,
+  BFD_RELOC_X86_64_GOTPCREL,
+  BFD_RELOC_X86_64_32S,
+  BFD_RELOC_X86_64_DTPMOD64,
+  BFD_RELOC_X86_64_DTPOFF64,
+  BFD_RELOC_X86_64_TPOFF64,
+  BFD_RELOC_X86_64_TLSGD,
+  BFD_RELOC_X86_64_TLSLD,
+  BFD_RELOC_X86_64_DTPOFF32,
+  BFD_RELOC_X86_64_GOTTPOFF,
+  BFD_RELOC_X86_64_TPOFF32,
+  BFD_RELOC_X86_64_GOTOFF64,
+  BFD_RELOC_X86_64_GOTPC32,
+
+/* 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,
+
+/* PDP11 relocations  */
+  BFD_RELOC_PDP11_DISP_8_PCREL,
+  BFD_RELOC_PDP11_DISP_6_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,
+  BFD_RELOC_PPC64_HIGHER,
+  BFD_RELOC_PPC64_HIGHER_S,
+  BFD_RELOC_PPC64_HIGHEST,
+  BFD_RELOC_PPC64_HIGHEST_S,
+  BFD_RELOC_PPC64_TOC16_LO,
+  BFD_RELOC_PPC64_TOC16_HI,
+  BFD_RELOC_PPC64_TOC16_HA,
+  BFD_RELOC_PPC64_TOC,
+  BFD_RELOC_PPC64_PLTGOT16,
+  BFD_RELOC_PPC64_PLTGOT16_LO,
+  BFD_RELOC_PPC64_PLTGOT16_HI,
+  BFD_RELOC_PPC64_PLTGOT16_HA,
+  BFD_RELOC_PPC64_ADDR16_DS,
+  BFD_RELOC_PPC64_ADDR16_LO_DS,
+  BFD_RELOC_PPC64_GOT16_DS,
+  BFD_RELOC_PPC64_GOT16_LO_DS,
+  BFD_RELOC_PPC64_PLT16_LO_DS,
+  BFD_RELOC_PPC64_SECTOFF_DS,
+  BFD_RELOC_PPC64_SECTOFF_LO_DS,
+  BFD_RELOC_PPC64_TOC16_DS,
+  BFD_RELOC_PPC64_TOC16_LO_DS,
+  BFD_RELOC_PPC64_PLTGOT16_DS,
+  BFD_RELOC_PPC64_PLTGOT16_LO_DS,
+
+/* PowerPC and PowerPC64 thread-local storage relocations.  */
+  BFD_RELOC_PPC_TLS,
+  BFD_RELOC_PPC_DTPMOD,
+  BFD_RELOC_PPC_TPREL16,
+  BFD_RELOC_PPC_TPREL16_LO,
+  BFD_RELOC_PPC_TPREL16_HI,
+  BFD_RELOC_PPC_TPREL16_HA,
+  BFD_RELOC_PPC_TPREL,
+  BFD_RELOC_PPC_DTPREL16,
+  BFD_RELOC_PPC_DTPREL16_LO,
+  BFD_RELOC_PPC_DTPREL16_HI,
+  BFD_RELOC_PPC_DTPREL16_HA,
+  BFD_RELOC_PPC_DTPREL,
+  BFD_RELOC_PPC_GOT_TLSGD16,
+  BFD_RELOC_PPC_GOT_TLSGD16_LO,
+  BFD_RELOC_PPC_GOT_TLSGD16_HI,
+  BFD_RELOC_PPC_GOT_TLSGD16_HA,
+  BFD_RELOC_PPC_GOT_TLSLD16,
+  BFD_RELOC_PPC_GOT_TLSLD16_LO,
+  BFD_RELOC_PPC_GOT_TLSLD16_HI,
+  BFD_RELOC_PPC_GOT_TLSLD16_HA,
+  BFD_RELOC_PPC_GOT_TPREL16,
+  BFD_RELOC_PPC_GOT_TPREL16_LO,
+  BFD_RELOC_PPC_GOT_TPREL16_HI,
+  BFD_RELOC_PPC_GOT_TPREL16_HA,
+  BFD_RELOC_PPC_GOT_DTPREL16,
+  BFD_RELOC_PPC_GOT_DTPREL16_LO,
+  BFD_RELOC_PPC_GOT_DTPREL16_HI,
+  BFD_RELOC_PPC_GOT_DTPREL16_HA,
+  BFD_RELOC_PPC64_TPREL16_DS,
+  BFD_RELOC_PPC64_TPREL16_LO_DS,
+  BFD_RELOC_PPC64_TPREL16_HIGHER,
+  BFD_RELOC_PPC64_TPREL16_HIGHERA,
+  BFD_RELOC_PPC64_TPREL16_HIGHEST,
+  BFD_RELOC_PPC64_TPREL16_HIGHESTA,
+  BFD_RELOC_PPC64_DTPREL16_DS,
+  BFD_RELOC_PPC64_DTPREL16_LO_DS,
+  BFD_RELOC_PPC64_DTPREL16_HIGHER,
+  BFD_RELOC_PPC64_DTPREL16_HIGHERA,
+  BFD_RELOC_PPC64_DTPREL16_HIGHEST,
+  BFD_RELOC_PPC64_DTPREL16_HIGHESTA,
+
+/* IBM 370/390 relocations  */
+  BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a constructor 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,
+
+/* ARM 26 bit pc-relative branch.  The lowest bit must be zero and is
+not stored in the instruction.  The 2nd lowest bit comes from a 1 bit
+field in the instruction.  */
+  BFD_RELOC_ARM_PCREL_BLX,
+
+/* Thumb 22 bit pc-relative branch.  The lowest bit must be zero and is
+not stored in the instruction.  The 2nd lowest bit comes from a 1 bit
+field in the instruction.  */
+  BFD_RELOC_THUMB_PCREL_BLX,
+
+/* Thumb 7-, 9-, 12-, 20-, 23-, and 25-bit pc-relative branches.
+The lowest bit must be zero and is not stored in the instruction.
+Note that the corresponding ELF R_ARM_THM_JUMPnn constant has an
+"nn" one smaller in all cases.  Note further that BRANCH23
+corresponds to R_ARM_THM_CALL.  */
+  BFD_RELOC_THUMB_PCREL_BRANCH7,
+  BFD_RELOC_THUMB_PCREL_BRANCH9,
+  BFD_RELOC_THUMB_PCREL_BRANCH12,
+  BFD_RELOC_THUMB_PCREL_BRANCH20,
+  BFD_RELOC_THUMB_PCREL_BRANCH23,
+  BFD_RELOC_THUMB_PCREL_BRANCH25,
+
+/* 12-bit immediate offset, used in ARM-format ldr and str instructions.  */
+  BFD_RELOC_ARM_OFFSET_IMM,
+
+/* 5-bit immediate offset, used in Thumb-format ldr and str instructions.  */
+  BFD_RELOC_ARM_THUMB_OFFSET,
+
+/* Pc-relative or absolute relocation depending on target.  Used for
+entries in .init_array sections.  */
+  BFD_RELOC_ARM_TARGET1,
+
+/* Read-only segment base relative address.  */
+  BFD_RELOC_ARM_ROSEGREL32,
+
+/* Data segment base relative address.  */
+  BFD_RELOC_ARM_SBREL32,
+
+/* This reloc is used for references to RTTI data from exception handling
+tables.  The actual definition depends on the target.  It may be a
+pc-relative or some form of GOT-indirect relocation.  */
+  BFD_RELOC_ARM_TARGET2,
+
+/* 31-bit PC relative address.  */
+  BFD_RELOC_ARM_PREL31,
+
+/* Relocations for setting up GOTs and PLTs for shared libraries.  */
+  BFD_RELOC_ARM_JUMP_SLOT,
+  BFD_RELOC_ARM_GLOB_DAT,
+  BFD_RELOC_ARM_GOT32,
+  BFD_RELOC_ARM_PLT32,
+  BFD_RELOC_ARM_RELATIVE,
+  BFD_RELOC_ARM_GOTOFF,
+  BFD_RELOC_ARM_GOTPC,
+
+/* ARM thread-local storage relocations.  */
+  BFD_RELOC_ARM_TLS_GD32,
+  BFD_RELOC_ARM_TLS_LDO32,
+  BFD_RELOC_ARM_TLS_LDM32,
+  BFD_RELOC_ARM_TLS_DTPOFF32,
+  BFD_RELOC_ARM_TLS_DTPMOD32,
+  BFD_RELOC_ARM_TLS_TPOFF32,
+  BFD_RELOC_ARM_TLS_IE32,
+  BFD_RELOC_ARM_TLS_LE32,
+
+/* 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_T32_IMMEDIATE,
+  BFD_RELOC_ARM_SHIFT_IMM,
+  BFD_RELOC_ARM_SMI,
+  BFD_RELOC_ARM_SWI,
+  BFD_RELOC_ARM_MULTI,
+  BFD_RELOC_ARM_CP_OFF_IMM,
+  BFD_RELOC_ARM_CP_OFF_IMM_S2,
+  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_T32_OFFSET_U8,
+  BFD_RELOC_ARM_T32_OFFSET_IMM,
+  BFD_RELOC_ARM_HWLITERAL,
+  BFD_RELOC_ARM_THUMB_ADD,
+  BFD_RELOC_ARM_THUMB_IMM,
+  BFD_RELOC_ARM_THUMB_SHIFT,
+
+/* Renesas / SuperH SH relocs.  Not all of these appear in object files.  */
+  BFD_RELOC_SH_PCDISP8BY2,
+  BFD_RELOC_SH_PCDISP12BY2,
+  BFD_RELOC_SH_IMM3,
+  BFD_RELOC_SH_IMM3U,
+  BFD_RELOC_SH_DISP12,
+  BFD_RELOC_SH_DISP12BY2,
+  BFD_RELOC_SH_DISP12BY4,
+  BFD_RELOC_SH_DISP12BY8,
+  BFD_RELOC_SH_DISP20,
+  BFD_RELOC_SH_DISP20BY8,
+  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,
+  BFD_RELOC_SH_LOOP_START,
+  BFD_RELOC_SH_LOOP_END,
+  BFD_RELOC_SH_COPY,
+  BFD_RELOC_SH_GLOB_DAT,
+  BFD_RELOC_SH_JMP_SLOT,
+  BFD_RELOC_SH_RELATIVE,
+  BFD_RELOC_SH_GOTPC,
+  BFD_RELOC_SH_GOT_LOW16,
+  BFD_RELOC_SH_GOT_MEDLOW16,
+  BFD_RELOC_SH_GOT_MEDHI16,
+  BFD_RELOC_SH_GOT_HI16,
+  BFD_RELOC_SH_GOTPLT_LOW16,
+  BFD_RELOC_SH_GOTPLT_MEDLOW16,
+  BFD_RELOC_SH_GOTPLT_MEDHI16,
+  BFD_RELOC_SH_GOTPLT_HI16,
+  BFD_RELOC_SH_PLT_LOW16,
+  BFD_RELOC_SH_PLT_MEDLOW16,
+  BFD_RELOC_SH_PLT_MEDHI16,
+  BFD_RELOC_SH_PLT_HI16,
+  BFD_RELOC_SH_GOTOFF_LOW16,
+  BFD_RELOC_SH_GOTOFF_MEDLOW16,
+  BFD_RELOC_SH_GOTOFF_MEDHI16,
+  BFD_RELOC_SH_GOTOFF_HI16,
+  BFD_RELOC_SH_GOTPC_LOW16,
+  BFD_RELOC_SH_GOTPC_MEDLOW16,
+  BFD_RELOC_SH_GOTPC_MEDHI16,
+  BFD_RELOC_SH_GOTPC_HI16,
+  BFD_RELOC_SH_COPY64,
+  BFD_RELOC_SH_GLOB_DAT64,
+  BFD_RELOC_SH_JMP_SLOT64,
+  BFD_RELOC_SH_RELATIVE64,
+  BFD_RELOC_SH_GOT10BY4,
+  BFD_RELOC_SH_GOT10BY8,
+  BFD_RELOC_SH_GOTPLT10BY4,
+  BFD_RELOC_SH_GOTPLT10BY8,
+  BFD_RELOC_SH_GOTPLT32,
+  BFD_RELOC_SH_SHMEDIA_CODE,
+  BFD_RELOC_SH_IMMU5,
+  BFD_RELOC_SH_IMMS6,
+  BFD_RELOC_SH_IMMS6BY32,
+  BFD_RELOC_SH_IMMU6,
+  BFD_RELOC_SH_IMMS10,
+  BFD_RELOC_SH_IMMS10BY2,
+  BFD_RELOC_SH_IMMS10BY4,
+  BFD_RELOC_SH_IMMS10BY8,
+  BFD_RELOC_SH_IMMS16,
+  BFD_RELOC_SH_IMMU16,
+  BFD_RELOC_SH_IMM_LOW16,
+  BFD_RELOC_SH_IMM_LOW16_PCREL,
+  BFD_RELOC_SH_IMM_MEDLOW16,
+  BFD_RELOC_SH_IMM_MEDLOW16_PCREL,
+  BFD_RELOC_SH_IMM_MEDHI16,
+  BFD_RELOC_SH_IMM_MEDHI16_PCREL,
+  BFD_RELOC_SH_IMM_HI16,
+  BFD_RELOC_SH_IMM_HI16_PCREL,
+  BFD_RELOC_SH_PT_16,
+  BFD_RELOC_SH_TLS_GD_32,
+  BFD_RELOC_SH_TLS_LD_32,
+  BFD_RELOC_SH_TLS_LDO_32,
+  BFD_RELOC_SH_TLS_IE_32,
+  BFD_RELOC_SH_TLS_LE_32,
+  BFD_RELOC_SH_TLS_DTPMOD32,
+  BFD_RELOC_SH_TLS_DTPOFF32,
+  BFD_RELOC_SH_TLS_TPOFF32,
+
+/* ARC Cores 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,
+
+/* DLX relocs  */
+  BFD_RELOC_DLX_HI16_S,
+
+/* DLX relocs  */
+  BFD_RELOC_DLX_LO16,
+
+/* DLX relocs  */
+  BFD_RELOC_DLX_JMP26,
+
+/* Renesas M16C/M32C Relocations.  */
+  BFD_RELOC_M16C_8_PCREL8,
+  BFD_RELOC_M16C_16_PCREL8,
+  BFD_RELOC_M16C_8_PCREL16,
+  BFD_RELOC_M16C_8_ELABEL24,
+  BFD_RELOC_M16C_8_ABS16,
+  BFD_RELOC_M16C_16_ABS16,
+  BFD_RELOC_M16C_16_ABS24,
+  BFD_RELOC_M16C_16_ABS32,
+  BFD_RELOC_M16C_24_ABS16,
+  BFD_RELOC_M16C_24_ABS24,
+  BFD_RELOC_M16C_24_ABS32,
+  BFD_RELOC_M16C_32_ABS16,
+  BFD_RELOC_M16C_32_ABS24,
+  BFD_RELOC_M16C_32_ABS32,
+  BFD_RELOC_M16C_40_ABS16,
+  BFD_RELOC_M16C_40_ABS24,
+  BFD_RELOC_M16C_40_ABS32,
+
+/* Renesas M32R (formerly 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,
+
+/* For PIC.  */
+  BFD_RELOC_M32R_GOT24,
+  BFD_RELOC_M32R_26_PLTREL,
+  BFD_RELOC_M32R_COPY,
+  BFD_RELOC_M32R_GLOB_DAT,
+  BFD_RELOC_M32R_JMP_SLOT,
+  BFD_RELOC_M32R_RELATIVE,
+  BFD_RELOC_M32R_GOTOFF,
+  BFD_RELOC_M32R_GOTOFF_HI_ULO,
+  BFD_RELOC_M32R_GOTOFF_HI_SLO,
+  BFD_RELOC_M32R_GOTOFF_LO,
+  BFD_RELOC_M32R_GOTPC24,
+  BFD_RELOC_M32R_GOT16_HI_ULO,
+  BFD_RELOC_M32R_GOT16_HI_SLO,
+  BFD_RELOC_M32R_GOT16_LO,
+  BFD_RELOC_M32R_GOTPC_HI_ULO,
+  BFD_RELOC_M32R_GOTPC_HI_SLO,
+  BFD_RELOC_M32R_GOTPC_LO,
+
+/* 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-contiguously 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-contiguously 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,
+
+/* Used for relaxing indirect function calls.  */
+  BFD_RELOC_V850_LONGCALL,
+
+/* Used for relaxing indirect jumps.  */
+  BFD_RELOC_V850_LONGJUMP,
+
+/* Used to maintain alignment whilst relaxing.  */
+  BFD_RELOC_V850_ALIGN,
+
+/* This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu
+instructions.  */
+  BFD_RELOC_V850_LO16_SPLIT_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 7bit reloc for the tms320c54x, where the least
+significant 7 bits of a 16 bit word are placed into the least
+significant 7 bits of the opcode.  */
+  BFD_RELOC_TIC54X_PARTLS7,
+
+/* This is a 9bit DP reloc for the tms320c54x, where the most
+significant 9 bits of a 16 bit word are placed into the least
+significant 9 bits of the opcode.  */
+  BFD_RELOC_TIC54X_PARTMS9,
+
+/* This is an extended address 23-bit reloc for the tms320c54x.  */
+  BFD_RELOC_TIC54X_23,
+
+/* This is a 16-bit reloc for the tms320c54x, where the least
+significant 16 bits of a 23-bit extended address are placed into
+the opcode.  */
+  BFD_RELOC_TIC54X_16_OF_23,
+
+/* This is a reloc for the tms320c54x, where the most
+significant 7 bits of a 23-bit extended address are placed into
+the opcode.  */
+  BFD_RELOC_TIC54X_MS7_OF_23,
+
+/* 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 are relocations for the GETA instruction.  */
+  BFD_RELOC_MMIX_GETA,
+  BFD_RELOC_MMIX_GETA_1,
+  BFD_RELOC_MMIX_GETA_2,
+  BFD_RELOC_MMIX_GETA_3,
+
+/* These are relocations for a conditional branch instruction.  */
+  BFD_RELOC_MMIX_CBRANCH,
+  BFD_RELOC_MMIX_CBRANCH_J,
+  BFD_RELOC_MMIX_CBRANCH_1,
+  BFD_RELOC_MMIX_CBRANCH_2,
+  BFD_RELOC_MMIX_CBRANCH_3,
+
+/* These are relocations for the PUSHJ instruction.  */
+  BFD_RELOC_MMIX_PUSHJ,
+  BFD_RELOC_MMIX_PUSHJ_1,
+  BFD_RELOC_MMIX_PUSHJ_2,
+  BFD_RELOC_MMIX_PUSHJ_3,
+  BFD_RELOC_MMIX_PUSHJ_STUBBABLE,
+
+/* These are relocations for the JMP instruction.  */
+  BFD_RELOC_MMIX_JMP,
+  BFD_RELOC_MMIX_JMP_1,
+  BFD_RELOC_MMIX_JMP_2,
+  BFD_RELOC_MMIX_JMP_3,
+
+/* This is a relocation for a relative address as in a GETA instruction or
+a branch.  */
+  BFD_RELOC_MMIX_ADDR19,
+
+/* This is a relocation for a relative address as in a JMP instruction.  */
+  BFD_RELOC_MMIX_ADDR27,
+
+/* This is a relocation for an instruction field that may be a general
+register or a value 0..255.  */
+  BFD_RELOC_MMIX_REG_OR_BYTE,
+
+/* This is a relocation for an instruction field that may be a general
+register.  */
+  BFD_RELOC_MMIX_REG,
+
+/* This is a relocation for two instruction fields holding a register and
+an offset, the equivalent of the relocation.  */
+  BFD_RELOC_MMIX_BASE_PLUS_OFFSET,
+
+/* This relocation is an assertion that the expression is not allocated as
+a global register.  It does not modify contents.  */
+  BFD_RELOC_MMIX_LOCAL,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative
+short offset into 7 bits.  */
+  BFD_RELOC_AVR_7_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative
+short offset into 12 bits.  */
+  BFD_RELOC_AVR_13_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually
+program memory address) into 16 bits.  */
+  BFD_RELOC_AVR_16_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+data memory address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_LO8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of data memory address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HI8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of program memory address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HH8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually data memory address) into 8 bit immediate value of SUBI insn.  */
+  BFD_RELOC_AVR_LO8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of data memory address) into 8 bit immediate value of
+SUBI insn.  */
+  BFD_RELOC_AVR_HI8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(most high 8 bit of program memory address) into 8 bit immediate value
+of LDI or SUBI insn.  */
+  BFD_RELOC_AVR_HH8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+command address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_LO8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of command address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HI8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of command address) into 8 bit immediate value of LDI insn.  */
+  BFD_RELOC_AVR_HH8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually command address) into 8 bit immediate value of SUBI insn.  */
+  BFD_RELOC_AVR_LO8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of 16 bit command address) into 8 bit immediate value
+of SUBI insn.  */
+  BFD_RELOC_AVR_HI8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 6 bit of 22 bit command address) into 8 bit immediate
+value of SUBI insn.  */
+  BFD_RELOC_AVR_HH8_LDI_PM_NEG,
+
+/* This is a 32 bit reloc for the AVR that stores 23 bit value
+into 22 bits.  */
+  BFD_RELOC_AVR_CALL,
+
+/* This is a 16 bit reloc for the AVR that stores all needed bits
+for absolute addressing with ldi with overflow check to linktime  */
+  BFD_RELOC_AVR_LDI,
+
+/* This is a 6 bit reloc for the AVR that stores offset for ldd/std
+instructions  */
+  BFD_RELOC_AVR_6,
+
+/* This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw
+instructions  */
+  BFD_RELOC_AVR_6_ADIW,
+
+/* Direct 12 bit.  */
+  BFD_RELOC_390_12,
+
+/* 12 bit GOT offset.  */
+  BFD_RELOC_390_GOT12,
+
+/* 32 bit PC relative PLT address.  */
+  BFD_RELOC_390_PLT32,
+
+/* Copy symbol at runtime.  */
+  BFD_RELOC_390_COPY,
+
+/* Create GOT entry.  */
+  BFD_RELOC_390_GLOB_DAT,
+
+/* Create PLT entry.  */
+  BFD_RELOC_390_JMP_SLOT,
+
+/* Adjust by program base.  */
+  BFD_RELOC_390_RELATIVE,
+
+/* 32 bit PC relative offset to GOT.  */
+  BFD_RELOC_390_GOTPC,
+
+/* 16 bit GOT offset.  */
+  BFD_RELOC_390_GOT16,
+
+/* PC relative 16 bit shifted by 1.  */
+  BFD_RELOC_390_PC16DBL,
+
+/* 16 bit PC rel. PLT shifted by 1.  */
+  BFD_RELOC_390_PLT16DBL,
+
+/* PC relative 32 bit shifted by 1.  */
+  BFD_RELOC_390_PC32DBL,
+
+/* 32 bit PC rel. PLT shifted by 1.  */
+  BFD_RELOC_390_PLT32DBL,
+
+/* 32 bit PC rel. GOT shifted by 1.  */
+  BFD_RELOC_390_GOTPCDBL,
+
+/* 64 bit GOT offset.  */
+  BFD_RELOC_390_GOT64,
+
+/* 64 bit PC relative PLT address.  */
+  BFD_RELOC_390_PLT64,
+
+/* 32 bit rel. offset to GOT entry.  */
+  BFD_RELOC_390_GOTENT,
+
+/* 64 bit offset to GOT.  */
+  BFD_RELOC_390_GOTOFF64,
+
+/* 12-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT12,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT16,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT32,
+
+/* 64-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLT64,
+
+/* 32-bit rel. offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_390_GOTPLTENT,
+
+/* 16-bit rel. offset from the GOT to a PLT entry.  */
+  BFD_RELOC_390_PLTOFF16,
+
+/* 32-bit rel. offset from the GOT to a PLT entry.  */
+  BFD_RELOC_390_PLTOFF32,
+
+/* 64-bit rel. offset from the GOT to a PLT entry.  */
+  BFD_RELOC_390_PLTOFF64,
+
+/* s390 tls relocations.  */
+  BFD_RELOC_390_TLS_LOAD,
+  BFD_RELOC_390_TLS_GDCALL,
+  BFD_RELOC_390_TLS_LDCALL,
+  BFD_RELOC_390_TLS_GD32,
+  BFD_RELOC_390_TLS_GD64,
+  BFD_RELOC_390_TLS_GOTIE12,
+  BFD_RELOC_390_TLS_GOTIE32,
+  BFD_RELOC_390_TLS_GOTIE64,
+  BFD_RELOC_390_TLS_LDM32,
+  BFD_RELOC_390_TLS_LDM64,
+  BFD_RELOC_390_TLS_IE32,
+  BFD_RELOC_390_TLS_IE64,
+  BFD_RELOC_390_TLS_IEENT,
+  BFD_RELOC_390_TLS_LE32,
+  BFD_RELOC_390_TLS_LE64,
+  BFD_RELOC_390_TLS_LDO32,
+  BFD_RELOC_390_TLS_LDO64,
+  BFD_RELOC_390_TLS_DTPMOD,
+  BFD_RELOC_390_TLS_DTPOFF,
+  BFD_RELOC_390_TLS_TPOFF,
+
+/* Long displacement extension.  */
+  BFD_RELOC_390_20,
+  BFD_RELOC_390_GOT20,
+  BFD_RELOC_390_GOTPLT20,
+  BFD_RELOC_390_TLS_GOTIE20,
+
+/* Scenix IP2K - 9-bit register number / data address  */
+  BFD_RELOC_IP2K_FR9,
+
+/* Scenix IP2K - 4-bit register/data bank number  */
+  BFD_RELOC_IP2K_BANK,
+
+/* Scenix IP2K - low 13 bits of instruction word address  */
+  BFD_RELOC_IP2K_ADDR16CJP,
+
+/* Scenix IP2K - high 3 bits of instruction word address  */
+  BFD_RELOC_IP2K_PAGE3,
+
+/* Scenix IP2K - ext/low/high 8 bits of data address  */
+  BFD_RELOC_IP2K_LO8DATA,
+  BFD_RELOC_IP2K_HI8DATA,
+  BFD_RELOC_IP2K_EX8DATA,
+
+/* Scenix IP2K - low/high 8 bits of instruction word address  */
+  BFD_RELOC_IP2K_LO8INSN,
+  BFD_RELOC_IP2K_HI8INSN,
+
+/* Scenix IP2K - even/odd PC modifier to modify snb pcl.0  */
+  BFD_RELOC_IP2K_PC_SKIP,
+
+/* Scenix IP2K - 16 bit word address in text section.  */
+  BFD_RELOC_IP2K_TEXT,
+
+/* Scenix IP2K - 7-bit sp or dp offset  */
+  BFD_RELOC_IP2K_FR_OFFSET,
+
+/* Scenix VPE4K coprocessor - data/insn-space addressing  */
+  BFD_RELOC_VPE4KMATH_DATA,
+  BFD_RELOC_VPE4KMATH_INSN,
+
+/* 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 inheritance 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,
+
+/* Intel IA64 Relocations.  */
+  BFD_RELOC_IA64_IMM14,
+  BFD_RELOC_IA64_IMM22,
+  BFD_RELOC_IA64_IMM64,
+  BFD_RELOC_IA64_DIR32MSB,
+  BFD_RELOC_IA64_DIR32LSB,
+  BFD_RELOC_IA64_DIR64MSB,
+  BFD_RELOC_IA64_DIR64LSB,
+  BFD_RELOC_IA64_GPREL22,
+  BFD_RELOC_IA64_GPREL64I,
+  BFD_RELOC_IA64_GPREL32MSB,
+  BFD_RELOC_IA64_GPREL32LSB,
+  BFD_RELOC_IA64_GPREL64MSB,
+  BFD_RELOC_IA64_GPREL64LSB,
+  BFD_RELOC_IA64_LTOFF22,
+  BFD_RELOC_IA64_LTOFF64I,
+  BFD_RELOC_IA64_PLTOFF22,
+  BFD_RELOC_IA64_PLTOFF64I,
+  BFD_RELOC_IA64_PLTOFF64MSB,
+  BFD_RELOC_IA64_PLTOFF64LSB,
+  BFD_RELOC_IA64_FPTR64I,
+  BFD_RELOC_IA64_FPTR32MSB,
+  BFD_RELOC_IA64_FPTR32LSB,
+  BFD_RELOC_IA64_FPTR64MSB,
+  BFD_RELOC_IA64_FPTR64LSB,
+  BFD_RELOC_IA64_PCREL21B,
+  BFD_RELOC_IA64_PCREL21BI,
+  BFD_RELOC_IA64_PCREL21M,
+  BFD_RELOC_IA64_PCREL21F,
+  BFD_RELOC_IA64_PCREL22,
+  BFD_RELOC_IA64_PCREL60B,
+  BFD_RELOC_IA64_PCREL64I,
+  BFD_RELOC_IA64_PCREL32MSB,
+  BFD_RELOC_IA64_PCREL32LSB,
+  BFD_RELOC_IA64_PCREL64MSB,
+  BFD_RELOC_IA64_PCREL64LSB,
+  BFD_RELOC_IA64_LTOFF_FPTR22,
+  BFD_RELOC_IA64_LTOFF_FPTR64I,
+  BFD_RELOC_IA64_LTOFF_FPTR32MSB,
+  BFD_RELOC_IA64_LTOFF_FPTR32LSB,
+  BFD_RELOC_IA64_LTOFF_FPTR64MSB,
+  BFD_RELOC_IA64_LTOFF_FPTR64LSB,
+  BFD_RELOC_IA64_SEGREL32MSB,
+  BFD_RELOC_IA64_SEGREL32LSB,
+  BFD_RELOC_IA64_SEGREL64MSB,
+  BFD_RELOC_IA64_SEGREL64LSB,
+  BFD_RELOC_IA64_SECREL32MSB,
+  BFD_RELOC_IA64_SECREL32LSB,
+  BFD_RELOC_IA64_SECREL64MSB,
+  BFD_RELOC_IA64_SECREL64LSB,
+  BFD_RELOC_IA64_REL32MSB,
+  BFD_RELOC_IA64_REL32LSB,
+  BFD_RELOC_IA64_REL64MSB,
+  BFD_RELOC_IA64_REL64LSB,
+  BFD_RELOC_IA64_LTV32MSB,
+  BFD_RELOC_IA64_LTV32LSB,
+  BFD_RELOC_IA64_LTV64MSB,
+  BFD_RELOC_IA64_LTV64LSB,
+  BFD_RELOC_IA64_IPLTMSB,
+  BFD_RELOC_IA64_IPLTLSB,
+  BFD_RELOC_IA64_COPY,
+  BFD_RELOC_IA64_LTOFF22X,
+  BFD_RELOC_IA64_LDXMOV,
+  BFD_RELOC_IA64_TPREL14,
+  BFD_RELOC_IA64_TPREL22,
+  BFD_RELOC_IA64_TPREL64I,
+  BFD_RELOC_IA64_TPREL64MSB,
+  BFD_RELOC_IA64_TPREL64LSB,
+  BFD_RELOC_IA64_LTOFF_TPREL22,
+  BFD_RELOC_IA64_DTPMOD64MSB,
+  BFD_RELOC_IA64_DTPMOD64LSB,
+  BFD_RELOC_IA64_LTOFF_DTPMOD22,
+  BFD_RELOC_IA64_DTPREL14,
+  BFD_RELOC_IA64_DTPREL22,
+  BFD_RELOC_IA64_DTPREL64I,
+  BFD_RELOC_IA64_DTPREL32MSB,
+  BFD_RELOC_IA64_DTPREL32LSB,
+  BFD_RELOC_IA64_DTPREL64MSB,
+  BFD_RELOC_IA64_DTPREL64LSB,
+  BFD_RELOC_IA64_LTOFF_DTPREL22,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bit high part of an absolute address.  */
+  BFD_RELOC_M68HC11_HI8,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bit low part of an absolute address.  */
+  BFD_RELOC_M68HC11_LO8,
+
+/* Motorola 68HC11 reloc.
+This is the 3 bit of a value.  */
+  BFD_RELOC_M68HC11_3B,
+
+/* Motorola 68HC11 reloc.
+This reloc marks the beginning of a jump/call instruction.
+It is used for linker relaxation to correctly identify beginning
+of instruction and change some branches to use PC-relative
+addressing mode.  */
+  BFD_RELOC_M68HC11_RL_JUMP,
+
+/* Motorola 68HC11 reloc.
+This reloc marks a group of several instructions that gcc generates
+and for which the linker relaxation pass can modify and/or remove
+some of them.  */
+  BFD_RELOC_M68HC11_RL_GROUP,
+
+/* Motorola 68HC11 reloc.
+This is the 16-bit lower part of an address.  It is used for 'call'
+instruction to specify the symbol address without any special
+transformation (due to memory bank window).  */
+  BFD_RELOC_M68HC11_LO16,
+
+/* Motorola 68HC11 reloc.
+This is a 8-bit reloc that specifies the page number of an address.
+It is used by 'call' instruction to specify the page number of
+the symbol.  */
+  BFD_RELOC_M68HC11_PAGE,
+
+/* Motorola 68HC11 reloc.
+This is a 24-bit reloc that represents the address with a 16-bit
+value and a 8-bit page number.  The symbol address is transformed
+to follow the 16K memory bank of 68HC12 (seen as mapped in the window).  */
+  BFD_RELOC_M68HC11_24,
+
+/* Motorola 68HC12 reloc.
+This is the 5 bits of a value.  */
+  BFD_RELOC_M68HC12_5B,
+
+/* NS CR16C Relocations.  */
+  BFD_RELOC_16C_NUM08,
+  BFD_RELOC_16C_NUM08_C,
+  BFD_RELOC_16C_NUM16,
+  BFD_RELOC_16C_NUM16_C,
+  BFD_RELOC_16C_NUM32,
+  BFD_RELOC_16C_NUM32_C,
+  BFD_RELOC_16C_DISP04,
+  BFD_RELOC_16C_DISP04_C,
+  BFD_RELOC_16C_DISP08,
+  BFD_RELOC_16C_DISP08_C,
+  BFD_RELOC_16C_DISP16,
+  BFD_RELOC_16C_DISP16_C,
+  BFD_RELOC_16C_DISP24,
+  BFD_RELOC_16C_DISP24_C,
+  BFD_RELOC_16C_DISP24a,
+  BFD_RELOC_16C_DISP24a_C,
+  BFD_RELOC_16C_REG04,
+  BFD_RELOC_16C_REG04_C,
+  BFD_RELOC_16C_REG04a,
+  BFD_RELOC_16C_REG04a_C,
+  BFD_RELOC_16C_REG14,
+  BFD_RELOC_16C_REG14_C,
+  BFD_RELOC_16C_REG16,
+  BFD_RELOC_16C_REG16_C,
+  BFD_RELOC_16C_REG20,
+  BFD_RELOC_16C_REG20_C,
+  BFD_RELOC_16C_ABS20,
+  BFD_RELOC_16C_ABS20_C,
+  BFD_RELOC_16C_ABS24,
+  BFD_RELOC_16C_ABS24_C,
+  BFD_RELOC_16C_IMM04,
+  BFD_RELOC_16C_IMM04_C,
+  BFD_RELOC_16C_IMM16,
+  BFD_RELOC_16C_IMM16_C,
+  BFD_RELOC_16C_IMM20,
+  BFD_RELOC_16C_IMM20_C,
+  BFD_RELOC_16C_IMM24,
+  BFD_RELOC_16C_IMM24_C,
+  BFD_RELOC_16C_IMM32,
+  BFD_RELOC_16C_IMM32_C,
+
+/* NS CRX Relocations.  */
+  BFD_RELOC_CRX_REL4,
+  BFD_RELOC_CRX_REL8,
+  BFD_RELOC_CRX_REL8_CMP,
+  BFD_RELOC_CRX_REL16,
+  BFD_RELOC_CRX_REL24,
+  BFD_RELOC_CRX_REL32,
+  BFD_RELOC_CRX_REGREL12,
+  BFD_RELOC_CRX_REGREL22,
+  BFD_RELOC_CRX_REGREL28,
+  BFD_RELOC_CRX_REGREL32,
+  BFD_RELOC_CRX_ABS16,
+  BFD_RELOC_CRX_ABS32,
+  BFD_RELOC_CRX_NUM8,
+  BFD_RELOC_CRX_NUM16,
+  BFD_RELOC_CRX_NUM32,
+  BFD_RELOC_CRX_IMM16,
+  BFD_RELOC_CRX_IMM32,
+  BFD_RELOC_CRX_SWITCH8,
+  BFD_RELOC_CRX_SWITCH16,
+  BFD_RELOC_CRX_SWITCH32,
+
+/* These relocs are only used within the CRIS assembler.  They are not
+(at present) written to any object files.  */
+  BFD_RELOC_CRIS_BDISP8,
+  BFD_RELOC_CRIS_UNSIGNED_5,
+  BFD_RELOC_CRIS_SIGNED_6,
+  BFD_RELOC_CRIS_UNSIGNED_6,
+  BFD_RELOC_CRIS_SIGNED_8,
+  BFD_RELOC_CRIS_UNSIGNED_8,
+  BFD_RELOC_CRIS_SIGNED_16,
+  BFD_RELOC_CRIS_UNSIGNED_16,
+  BFD_RELOC_CRIS_LAPCQ_OFFSET,
+  BFD_RELOC_CRIS_UNSIGNED_4,
+
+/* Relocs used in ELF shared libraries for CRIS.  */
+  BFD_RELOC_CRIS_COPY,
+  BFD_RELOC_CRIS_GLOB_DAT,
+  BFD_RELOC_CRIS_JUMP_SLOT,
+  BFD_RELOC_CRIS_RELATIVE,
+
+/* 32-bit offset to symbol-entry within GOT.  */
+  BFD_RELOC_CRIS_32_GOT,
+
+/* 16-bit offset to symbol-entry within GOT.  */
+  BFD_RELOC_CRIS_16_GOT,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_CRIS_32_GOTPLT,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling.  */
+  BFD_RELOC_CRIS_16_GOTPLT,
+
+/* 32-bit offset to symbol, relative to GOT.  */
+  BFD_RELOC_CRIS_32_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to GOT.  */
+  BFD_RELOC_CRIS_32_PLT_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to this relocation.  */
+  BFD_RELOC_CRIS_32_PLT_PCREL,
+
+/* Intel i860 Relocations.  */
+  BFD_RELOC_860_COPY,
+  BFD_RELOC_860_GLOB_DAT,
+  BFD_RELOC_860_JUMP_SLOT,
+  BFD_RELOC_860_RELATIVE,
+  BFD_RELOC_860_PC26,
+  BFD_RELOC_860_PLT26,
+  BFD_RELOC_860_PC16,
+  BFD_RELOC_860_LOW0,
+  BFD_RELOC_860_SPLIT0,
+  BFD_RELOC_860_LOW1,
+  BFD_RELOC_860_SPLIT1,
+  BFD_RELOC_860_LOW2,
+  BFD_RELOC_860_SPLIT2,
+  BFD_RELOC_860_LOW3,
+  BFD_RELOC_860_LOGOT0,
+  BFD_RELOC_860_SPGOT0,
+  BFD_RELOC_860_LOGOT1,
+  BFD_RELOC_860_SPGOT1,
+  BFD_RELOC_860_LOGOTOFF0,
+  BFD_RELOC_860_SPGOTOFF0,
+  BFD_RELOC_860_LOGOTOFF1,
+  BFD_RELOC_860_SPGOTOFF1,
+  BFD_RELOC_860_LOGOTOFF2,
+  BFD_RELOC_860_LOGOTOFF3,
+  BFD_RELOC_860_LOPC,
+  BFD_RELOC_860_HIGHADJ,
+  BFD_RELOC_860_HAGOT,
+  BFD_RELOC_860_HAGOTOFF,
+  BFD_RELOC_860_HAPC,
+  BFD_RELOC_860_HIGH,
+  BFD_RELOC_860_HIGOT,
+  BFD_RELOC_860_HIGOTOFF,
+
+/* OpenRISC Relocations.  */
+  BFD_RELOC_OPENRISC_ABS_26,
+  BFD_RELOC_OPENRISC_REL_26,
+
+/* H8 elf Relocations.  */
+  BFD_RELOC_H8_DIR16A8,
+  BFD_RELOC_H8_DIR16R8,
+  BFD_RELOC_H8_DIR24A8,
+  BFD_RELOC_H8_DIR24R8,
+  BFD_RELOC_H8_DIR32A16,
+
+/* Sony Xstormy16 Relocations.  */
+  BFD_RELOC_XSTORMY16_REL_12,
+  BFD_RELOC_XSTORMY16_12,
+  BFD_RELOC_XSTORMY16_24,
+  BFD_RELOC_XSTORMY16_FPTR16,
+
+/* Relocations used by VAX ELF.  */
+  BFD_RELOC_VAX_GLOB_DAT,
+  BFD_RELOC_VAX_JMP_SLOT,
+  BFD_RELOC_VAX_RELATIVE,
+
+/* Morpho MS1 - 16 bit immediate relocation.  */
+  BFD_RELOC_MS1_PC16,
+
+/* Morpho MS1 - Hi 16 bits of an address.  */
+  BFD_RELOC_MS1_HI16,
+
+/* Morpho MS1 - Low 16 bits of an address.  */
+  BFD_RELOC_MS1_LO16,
+
+/* Morpho MS1 - Used to tell the linker which vtable entries are used.  */
+  BFD_RELOC_MS1_GNU_VTINHERIT,
+
+/* Morpho MS1 - Used to tell the linker which vtable entries are used.  */
+  BFD_RELOC_MS1_GNU_VTENTRY,
+
+/* msp430 specific relocation codes  */
+  BFD_RELOC_MSP430_10_PCREL,
+  BFD_RELOC_MSP430_16_PCREL,
+  BFD_RELOC_MSP430_16,
+  BFD_RELOC_MSP430_16_PCREL_BYTE,
+  BFD_RELOC_MSP430_16_BYTE,
+  BFD_RELOC_MSP430_2X_PCREL,
+  BFD_RELOC_MSP430_RL_PCREL,
+
+/* IQ2000 Relocations.  */
+  BFD_RELOC_IQ2000_OFFSET_16,
+  BFD_RELOC_IQ2000_OFFSET_21,
+  BFD_RELOC_IQ2000_UHI16,
+
+/* Special Xtensa relocation used only by PLT entries in ELF shared
+objects to indicate that the runtime linker should set the value
+to one of its own internal functions or data structures.  */
+  BFD_RELOC_XTENSA_RTLD,
+
+/* Xtensa relocations for ELF shared objects.  */
+  BFD_RELOC_XTENSA_GLOB_DAT,
+  BFD_RELOC_XTENSA_JMP_SLOT,
+  BFD_RELOC_XTENSA_RELATIVE,
+
+/* Xtensa relocation used in ELF object files for symbols that may require
+PLT entries.  Otherwise, this is just a generic 32-bit relocation.  */
+  BFD_RELOC_XTENSA_PLT,
+
+/* Xtensa relocations to mark the difference of two local symbols.
+These are only needed to support linker relaxation and can be ignored
+when not relaxing.  The field is set to the value of the difference
+assuming no relaxation.  The relocation encodes the position of the
+first symbol so the linker can determine whether to adjust the field
+value.  */
+  BFD_RELOC_XTENSA_DIFF8,
+  BFD_RELOC_XTENSA_DIFF16,
+  BFD_RELOC_XTENSA_DIFF32,
+
+/* Generic Xtensa relocations for instruction operands.  Only the slot
+number is encoded in the relocation.  The relocation applies to the
+last PC-relative immediate operand, or if there are no PC-relative
+immediates, to the last immediate operand.  */
+  BFD_RELOC_XTENSA_SLOT0_OP,
+  BFD_RELOC_XTENSA_SLOT1_OP,
+  BFD_RELOC_XTENSA_SLOT2_OP,
+  BFD_RELOC_XTENSA_SLOT3_OP,
+  BFD_RELOC_XTENSA_SLOT4_OP,
+  BFD_RELOC_XTENSA_SLOT5_OP,
+  BFD_RELOC_XTENSA_SLOT6_OP,
+  BFD_RELOC_XTENSA_SLOT7_OP,
+  BFD_RELOC_XTENSA_SLOT8_OP,
+  BFD_RELOC_XTENSA_SLOT9_OP,
+  BFD_RELOC_XTENSA_SLOT10_OP,
+  BFD_RELOC_XTENSA_SLOT11_OP,
+  BFD_RELOC_XTENSA_SLOT12_OP,
+  BFD_RELOC_XTENSA_SLOT13_OP,
+  BFD_RELOC_XTENSA_SLOT14_OP,
+
+/* Alternate Xtensa relocations.  Only the slot is encoded in the
+relocation.  The meaning of these relocations is opcode-specific.  */
+  BFD_RELOC_XTENSA_SLOT0_ALT,
+  BFD_RELOC_XTENSA_SLOT1_ALT,
+  BFD_RELOC_XTENSA_SLOT2_ALT,
+  BFD_RELOC_XTENSA_SLOT3_ALT,
+  BFD_RELOC_XTENSA_SLOT4_ALT,
+  BFD_RELOC_XTENSA_SLOT5_ALT,
+  BFD_RELOC_XTENSA_SLOT6_ALT,
+  BFD_RELOC_XTENSA_SLOT7_ALT,
+  BFD_RELOC_XTENSA_SLOT8_ALT,
+  BFD_RELOC_XTENSA_SLOT9_ALT,
+  BFD_RELOC_XTENSA_SLOT10_ALT,
+  BFD_RELOC_XTENSA_SLOT11_ALT,
+  BFD_RELOC_XTENSA_SLOT12_ALT,
+  BFD_RELOC_XTENSA_SLOT13_ALT,
+  BFD_RELOC_XTENSA_SLOT14_ALT,
+
+/* Xtensa relocations for backward compatibility.  These have all been
+replaced by BFD_RELOC_XTENSA_SLOT0_OP.  */
+  BFD_RELOC_XTENSA_OP0,
+  BFD_RELOC_XTENSA_OP1,
+  BFD_RELOC_XTENSA_OP2,
+
+/* Xtensa relocation to mark that the assembler expanded the
+instructions from an original target.  The expansion size is
+encoded in the reloc size.  */
+  BFD_RELOC_XTENSA_ASM_EXPAND,
+
+/* Xtensa relocation to mark that the linker should simplify
+assembler-expanded instructions.  This is commonly used
+internally by the linker after analysis of a
+BFD_RELOC_XTENSA_ASM_EXPAND.  */
+  BFD_RELOC_XTENSA_ASM_SIMPLIFY,
+  BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *bfd_reloc_type_lookup
+   (bfd *abfd, bfd_reloc_code_real_type code);
+
+const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code);
+
+/* Extracted from syms.c.  */
+
+typedef struct bfd_symbol
+{
+  /* 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 arbitrary
+     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
+
+  /* This symbol is thread local.  Used in ELF.  */
+#define BSF_THREAD_LOCAL  0x40000
+
+  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 bfd_section *section;
+
+  /* Back end special data.  */
+  union
+    {
+      void *p;
+      bfd_vma i;
+    }
+  udata;
+}
+asymbol;
+
+#define bfd_get_symtab_upper_bound(abfd) \
+     BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+
+bfd_boolean bfd_is_local_label (bfd *abfd, asymbol *sym);
+
+bfd_boolean bfd_is_local_label_name (bfd *abfd, const char *name);
+
+#define bfd_is_local_label_name(abfd, name) \
+  BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+
+bfd_boolean bfd_is_target_special_symbol (bfd *abfd, asymbol *sym);
+
+#define bfd_is_target_special_symbol(abfd, sym) \
+  BFD_SEND (abfd, _bfd_is_target_special_symbol, (abfd, sym))
+
+#define bfd_canonicalize_symtab(abfd, location) \
+  BFD_SEND (abfd, _bfd_canonicalize_symtab, (abfd, location))
+
+bfd_boolean bfd_set_symtab
+   (bfd *abfd, asymbol **location, unsigned int count);
+
+void bfd_print_symbol_vandf (bfd *abfd, void *file, asymbol *symbol);
+
+#define bfd_make_empty_symbol(abfd) \
+  BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+
+asymbol *_bfd_generic_make_empty_symbol (bfd *);
+
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+  BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+
+int bfd_decode_symclass (asymbol *symbol);
+
+bfd_boolean bfd_is_undefined_symclass (int symclass);
+
+void bfd_symbol_info (asymbol *symbol, symbol_info *ret);
+
+bfd_boolean bfd_copy_private_symbol_data
+   (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))
+
+/* Extracted from bfd.c.  */
+struct bfd
+{
+  /* A unique identifier of the BFD  */
+  unsigned int id;
+
+  /* The filename the application opened the BFD with.  */
+  const char *filename;
+
+  /* A pointer to the target jump table.  */
+  const struct bfd_target *xvec;
+
+  /* The IOSTREAM, and corresponding IO vector that provide access
+     to the file backing the BFD.  */
+  void *iostream;
+  const struct bfd_iovec *iovec;
+
+  /* Is the file descriptor being cached?  That is, can it be closed as
+     needed, and re-opened when accessed later?  */
+  bfd_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.  */
+  bfd_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...  */
+  ufile_ptr where;
+
+  /* ... and here: (``once'' means at least once).  */
+  bfd_boolean opened_once;
+
+  /* Set if we have a locally maintained mtime value, rather than
+     getting it from the file each time.  */
+  bfd_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 with which the BFD was opened.  */
+  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.  */
+  ufile_ptr origin;
+
+  /* Remember when output has begun, to stop strange things
+     from happening.  */
+  bfd_boolean output_has_begun;
+
+  /* A hash table for section names.  */
+  struct bfd_hash_table section_htab;
+
+  /* Pointer to linked list of sections.  */
+  struct bfd_section *sections;
+
+  /* The last section on the section list.  */
+  struct bfd_section *section_last;
+
+  /* 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 bfd_symbol  **outsymbols;
+
+  /* Used for slurped dynamic symbol tables.  */
+  unsigned int dynsymcount;
+
+  /* Pointer to structure which contains architecture information.  */
+  const struct bfd_arch_info *arch_info;
+
+  /* Flag set if symbols from this BFD should not be exported.  */
+  bfd_boolean no_export;
+
+  /* Stuff only useful for archives.  */
+  void *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.  */
+  bfd_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 mmo_data_struct *mmo_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;
+      struct mach_o_data_struct *mach_o_data;
+      struct mach_o_fat_data_struct *mach_o_fat_data;
+      struct bfd_pef_data_struct *pef_data;
+      struct bfd_pef_xlib_data_struct *pef_xlib_data;
+      struct bfd_sym_data_struct *sym_data;
+      void *any;
+    }
+  tdata;
+
+  /* Used by the application to hold private data.  */
+  void *usrdata;
+
+  /* Where all the allocated stuff under this BFD goes.  This is a
+     struct objalloc *, but we use void * to avoid requiring the inclusion
+     of objalloc.h.  */
+  void *memory;
+};
+
+typedef enum bfd_error
+{
+  bfd_error_no_error = 0,
+  bfd_error_system_call,
+  bfd_error_invalid_target,
+  bfd_error_wrong_format,
+  bfd_error_wrong_object_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 (void);
+
+void bfd_set_error (bfd_error_type error_tag);
+
+const char *bfd_errmsg (bfd_error_type error_tag);
+
+void bfd_perror (const char *message);
+
+typedef void (*bfd_error_handler_type) (const char *, ...);
+
+bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type);
+
+void bfd_set_error_program_name (const char *);
+
+bfd_error_handler_type bfd_get_error_handler (void);
+
+long bfd_get_reloc_upper_bound (bfd *abfd, asection *sect);
+
+long bfd_canonicalize_reloc
+   (bfd *abfd, asection *sec, arelent **loc, asymbol **syms);
+
+void bfd_set_reloc
+   (bfd *abfd, asection *sec, arelent **rel, unsigned int count);
+
+bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags);
+
+int bfd_get_arch_size (bfd *abfd);
+
+int bfd_get_sign_extend_vma (bfd *abfd);
+
+bfd_boolean bfd_set_start_address (bfd *abfd, bfd_vma vma);
+
+unsigned int bfd_get_gp_size (bfd *abfd);
+
+void bfd_set_gp_size (bfd *abfd, unsigned int i);
+
+bfd_vma bfd_scan_vma (const char *string, const char **end, int base);
+
+bfd_boolean bfd_copy_private_header_data (bfd *ibfd, bfd *obfd);
+
+#define bfd_copy_private_header_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_copy_private_header_data, \
+               (ibfd, obfd))
+bfd_boolean bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd);
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+               (ibfd, obfd))
+bfd_boolean bfd_merge_private_bfd_data (bfd *ibfd, bfd *obfd);
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+               (ibfd, obfd))
+bfd_boolean bfd_set_private_flags (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))
+
+#define bfd_find_line(abfd, syms, sym, file, line) \
+       BFD_SEND (abfd, _bfd_find_line, \
+                 (abfd, syms, sym, file, line))
+
+#define bfd_find_inliner_info(abfd, file, func, line) \
+       BFD_SEND (abfd, _bfd_find_inliner_info, \
+                 (abfd, file, func, line))
+
+#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_merge_sections(abfd, link_info) \
+       BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
+#define bfd_is_group_section(abfd, sec) \
+       BFD_SEND (abfd, _bfd_is_group_section, (abfd, sec))
+
+#define bfd_discard_group(abfd, sec) \
+       BFD_SEND (abfd, _bfd_discard_group, (abfd, sec))
+
+#define bfd_link_hash_table_create(abfd) \
+       BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_hash_table_free(abfd, hash) \
+       BFD_SEND (abfd, _bfd_link_hash_table_free, (hash))
+
+#define bfd_link_add_symbols(abfd, info) \
+       BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_link_just_syms(abfd, sec, info) \
+       BFD_SEND (abfd, _bfd_link_just_syms, (sec, 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_synthetic_symtab(abfd, count, syms, dyncount, dynsyms, ret) \
+       BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, count, syms, \
+                                                   dyncount, dynsyms, ret))
+
+#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
+  (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *,
+   bfd_boolean, asymbol **);
+
+bfd_boolean bfd_alt_mach_code (bfd *abfd, int alternative);
+
+struct bfd_preserve
+{
+  void *marker;
+  void *tdata;
+  flagword flags;
+  const struct bfd_arch_info *arch_info;
+  struct bfd_section *sections;
+  struct bfd_section *section_last;
+  unsigned int section_count;
+  struct bfd_hash_table section_htab;
+};
+
+bfd_boolean bfd_preserve_save (bfd *, struct bfd_preserve *);
+
+void bfd_preserve_restore (bfd *, struct bfd_preserve *);
+
+void bfd_preserve_finish (bfd *, struct bfd_preserve *);
+
+/* Extracted from archive.c.  */
+symindex bfd_get_next_mapent
+   (bfd *abfd, symindex previous, carsym **sym);
+
+bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head);
+
+bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous);
+
+/* Extracted from corefile.c.  */
+const char *bfd_core_file_failing_command (bfd *abfd);
+
+int bfd_core_file_failing_signal (bfd *abfd);
+
+bfd_boolean core_file_matches_executable_p
+   (bfd *core_bfd, bfd *exec_bfd);
+
+/* Extracted from targets.c.  */
+#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_xcoff_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,
+  bfd_target_mmo_flavour,
+  bfd_target_mach_o_flavour,
+  bfd_target_pef_flavour,
+  bfd_target_pef_xlib_flavour,
+  bfd_target_sym_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
+{
+  /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc.  */
+  char *name;
+
+ /* The "flavour" of a back end is a general indication about
+    the contents of a file.  */
+  enum bfd_flavour flavour;
+
+  /* The order of bytes within the data area of a file.  */
+  enum bfd_endian byteorder;
+
+ /* The order of bytes within the header parts of a file.  */
+  enum bfd_endian header_byteorder;
+
+  /* A mask of all the flags which an executable may have set -
+     from the set <<BFD_NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>.  */
+  flagword object_flags;
+
+ /* A mask of all the flags which a section may have set - from
+    the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>.  */
+  flagword section_flags;
+
+ /* The character normally found at the front of a symbol.
+    (if any), perhaps `_'.  */
+  char symbol_leading_char;
+
+ /* The pad character for file names within an archive header.  */
+  char ar_pad_char;
+
+  /* The maximum number of characters in an archive header.  */
+  unsigned short ar_max_namelen;
+
+  /* Entries for byte swapping for data. These are different from the
+     other entry points, since they don't take a BFD as the first argument.
+     Certain other handlers could do the same.  */
+  bfd_uint64_t   (*bfd_getx64) (const void *);
+  bfd_int64_t    (*bfd_getx_signed_64) (const void *);
+  void           (*bfd_putx64) (bfd_uint64_t, void *);
+  bfd_vma        (*bfd_getx32) (const void *);
+  bfd_signed_vma (*bfd_getx_signed_32) (const void *);
+  void           (*bfd_putx32) (bfd_vma, void *);
+  bfd_vma        (*bfd_getx16) (const void *);
+  bfd_signed_vma (*bfd_getx_signed_16) (const void *);
+  void           (*bfd_putx16) (bfd_vma, void *);
+
+  /* Byte swapping for the headers.  */
+  bfd_uint64_t   (*bfd_h_getx64) (const void *);
+  bfd_int64_t    (*bfd_h_getx_signed_64) (const void *);
+  void           (*bfd_h_putx64) (bfd_uint64_t, void *);
+  bfd_vma        (*bfd_h_getx32) (const void *);
+  bfd_signed_vma (*bfd_h_getx_signed_32) (const void *);
+  void           (*bfd_h_putx32) (bfd_vma, void *);
+  bfd_vma        (*bfd_h_getx16) (const void *);
+  bfd_signed_vma (*bfd_h_getx_signed_16) (const void *);
+  void           (*bfd_h_putx16) (bfd_vma, void *);
+
+  /* Format dependent routines: these are vectors of entry points
+     within the target vector structure, one for each format to check.  */
+
+  /* Check the format of a file being read.  Return a <<bfd_target *>> or zero.  */
+  const struct bfd_target *(*_bfd_check_format[bfd_type_end]) (bfd *);
+
+  /* Set the format of a file being written.  */
+  bfd_boolean (*_bfd_set_format[bfd_type_end]) (bfd *);
+
+  /* Write cached information into a file being written, at <<bfd_close>>.  */
+  bfd_boolean (*_bfd_write_contents[bfd_type_end]) (bfd *);
+
+
+  /* Generic entry points.  */
+#define BFD_JUMP_TABLE_GENERIC(NAME) \
+  NAME##_close_and_cleanup, \
+  NAME##_bfd_free_cached_info, \
+  NAME##_new_section_hook, \
+  NAME##_get_section_contents, \
+  NAME##_get_section_contents_in_window
+
+  /* Called when the BFD is being closed to do any necessary cleanup.  */
+  bfd_boolean (*_close_and_cleanup) (bfd *);
+  /* Ask the BFD to free all cached information.  */
+  bfd_boolean (*_bfd_free_cached_info) (bfd *);
+  /* Called when a new section is created.  */
+  bfd_boolean (*_new_section_hook) (bfd *, sec_ptr);
+  /* Read the contents of a section.  */
+  bfd_boolean (*_bfd_get_section_contents)
+    (bfd *, sec_ptr, void *, file_ptr, bfd_size_type);
+  bfd_boolean (*_bfd_get_section_contents_in_window)
+    (bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type);
+
+  /* Entry points to copy private data.  */
+#define BFD_JUMP_TABLE_COPY(NAME) \
+  NAME##_bfd_copy_private_bfd_data, \
+  NAME##_bfd_merge_private_bfd_data, \
+  NAME##_bfd_copy_private_section_data, \
+  NAME##_bfd_copy_private_symbol_data, \
+  NAME##_bfd_copy_private_header_data, \
+  NAME##_bfd_set_private_flags, \
+  NAME##_bfd_print_private_bfd_data
+
+  /* Called to copy BFD general private data from one object file
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_bfd_data) (bfd *, bfd *);
+  /* Called to merge BFD general private data from one object file
+     to a common output file when linking.  */
+  bfd_boolean (*_bfd_merge_private_bfd_data) (bfd *, bfd *);
+  /* Called to copy BFD private section data from one object file
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_section_data)
+    (bfd *, sec_ptr, bfd *, sec_ptr);
+  /* Called to copy BFD private symbol data from one symbol
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_symbol_data)
+    (bfd *, asymbol *, bfd *, asymbol *);
+  /* Called to copy BFD private header data from one object file
+     to another.  */
+  bfd_boolean (*_bfd_copy_private_header_data)
+    (bfd *, bfd *);
+  /* Called to set private backend flags.  */
+  bfd_boolean (*_bfd_set_private_flags) (bfd *, flagword);
+
+  /* Called to print private BFD data.  */
+  bfd_boolean (*_bfd_print_private_bfd_data) (bfd *, void *);
+
+  /* Core file entry points.  */
+#define BFD_JUMP_TABLE_CORE(NAME) \
+  NAME##_core_file_failing_command, \
+  NAME##_core_file_failing_signal, \
+  NAME##_core_file_matches_executable_p
+
+  char *      (*_core_file_failing_command) (bfd *);
+  int         (*_core_file_failing_signal) (bfd *);
+  bfd_boolean (*_core_file_matches_executable_p) (bfd *, bfd *);
+
+  /* Archive entry points.  */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME) \
+  NAME##_slurp_armap, \
+  NAME##_slurp_extended_name_table, \
+  NAME##_construct_extended_name_table, \
+  NAME##_truncate_arname, \
+  NAME##_write_armap, \
+  NAME##_read_ar_hdr, \
+  NAME##_openr_next_archived_file, \
+  NAME##_get_elt_at_index, \
+  NAME##_generic_stat_arch_elt, \
+  NAME##_update_armap_timestamp
+
+  bfd_boolean (*_bfd_slurp_armap) (bfd *);
+  bfd_boolean (*_bfd_slurp_extended_name_table) (bfd *);
+  bfd_boolean (*_bfd_construct_extended_name_table)
+    (bfd *, char **, bfd_size_type *, const char **);
+  void        (*_bfd_truncate_arname) (bfd *, const char *, char *);
+  bfd_boolean (*write_armap)
+    (bfd *, unsigned int, struct orl *, unsigned int, int);
+  void *      (*_bfd_read_ar_hdr_fn) (bfd *);
+  bfd *       (*openr_next_archived_file) (bfd *, bfd *);
+#define bfd_get_elt_at_index(b,i) BFD_SEND (b, _bfd_get_elt_at_index, (b,i))
+  bfd *       (*_bfd_get_elt_at_index) (bfd *, symindex);
+  int         (*_bfd_stat_arch_elt) (bfd *, struct stat *);
+  bfd_boolean (*_bfd_update_armap_timestamp) (bfd *);
+
+  /* Entry points used for symbols.  */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME) \
+  NAME##_get_symtab_upper_bound, \
+  NAME##_canonicalize_symtab, \
+  NAME##_make_empty_symbol, \
+  NAME##_print_symbol, \
+  NAME##_get_symbol_info, \
+  NAME##_bfd_is_local_label_name, \
+  NAME##_bfd_is_target_special_symbol, \
+  NAME##_get_lineno, \
+  NAME##_find_nearest_line, \
+  _bfd_generic_find_line, \
+  NAME##_find_inliner_info, \
+  NAME##_bfd_make_debug_symbol, \
+  NAME##_read_minisymbols, \
+  NAME##_minisymbol_to_symbol
+
+  long        (*_bfd_get_symtab_upper_bound) (bfd *);
+  long        (*_bfd_canonicalize_symtab)
+    (bfd *, struct bfd_symbol **);
+  struct bfd_symbol *
+              (*_bfd_make_empty_symbol) (bfd *);
+  void        (*_bfd_print_symbol)
+    (bfd *, void *, struct bfd_symbol *, 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)
+    (bfd *, struct bfd_symbol *, symbol_info *);
+#define bfd_get_symbol_info(b,p,e) BFD_SEND (b, _bfd_get_symbol_info, (b,p,e))
+  bfd_boolean (*_bfd_is_local_label_name) (bfd *, const char *);
+  bfd_boolean (*_bfd_is_target_special_symbol) (bfd *, asymbol *);
+  alent *     (*_get_lineno) (bfd *, struct bfd_symbol *);
+  bfd_boolean (*_bfd_find_nearest_line)
+    (bfd *, struct bfd_section *, struct bfd_symbol **, bfd_vma,
+     const char **, const char **, unsigned int *);
+  bfd_boolean (*_bfd_find_line)
+    (bfd *, struct bfd_symbol **, struct bfd_symbol *,
+     const char **, unsigned int *);
+  bfd_boolean (*_bfd_find_inliner_info)
+    (bfd *, const char **, const char **, unsigned int *);
+ /* 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)
+    (bfd *, void *, unsigned long size);
+#define bfd_read_minisymbols(b, d, m, s) \
+  BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+  long        (*_read_minisymbols)
+    (bfd *, bfd_boolean, void **, 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)
+    (bfd *, bfd_boolean, const void *, asymbol *);
+
+  /* Routines for relocs.  */
+#define BFD_JUMP_TABLE_RELOCS(NAME) \
+  NAME##_get_reloc_upper_bound, \
+  NAME##_canonicalize_reloc, \
+  NAME##_bfd_reloc_type_lookup
+
+  long        (*_get_reloc_upper_bound) (bfd *, sec_ptr);
+  long        (*_bfd_canonicalize_reloc)
+    (bfd *, sec_ptr, arelent **, struct bfd_symbol **);
+  /* See documentation on reloc types.  */
+  reloc_howto_type *
+              (*reloc_type_lookup) (bfd *, bfd_reloc_code_real_type);
+
+  /* Routines used when writing an object file.  */
+#define BFD_JUMP_TABLE_WRITE(NAME) \
+  NAME##_set_arch_mach, \
+  NAME##_set_section_contents
+
+  bfd_boolean (*_bfd_set_arch_mach)
+    (bfd *, enum bfd_architecture, unsigned long);
+  bfd_boolean (*_bfd_set_section_contents)
+    (bfd *, sec_ptr, const void *, file_ptr, bfd_size_type);
+
+  /* Routines used by the linker.  */
+#define BFD_JUMP_TABLE_LINK(NAME) \
+  NAME##_sizeof_headers, \
+  NAME##_bfd_get_relocated_section_contents, \
+  NAME##_bfd_relax_section, \
+  NAME##_bfd_link_hash_table_create, \
+  NAME##_bfd_link_hash_table_free, \
+  NAME##_bfd_link_add_symbols, \
+  NAME##_bfd_link_just_syms, \
+  NAME##_bfd_final_link, \
+  NAME##_bfd_link_split_section, \
+  NAME##_bfd_gc_sections, \
+  NAME##_bfd_merge_sections, \
+  NAME##_bfd_is_group_section, \
+  NAME##_bfd_discard_group, \
+  NAME##_section_already_linked \
+
+  int         (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
+  bfd_byte *  (*_bfd_get_relocated_section_contents)
+    (bfd *, struct bfd_link_info *, struct bfd_link_order *,
+     bfd_byte *, bfd_boolean, struct bfd_symbol **);
+
+  bfd_boolean (*_bfd_relax_section)
+    (bfd *, struct bfd_section *, struct bfd_link_info *, bfd_boolean *);
+
+  /* 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) (bfd *);
+
+  /* Release the memory associated with the linker hash table.  */
+  void        (*_bfd_link_hash_table_free) (struct bfd_link_hash_table *);
+
+  /* Add symbols from this object file into the hash table.  */
+  bfd_boolean (*_bfd_link_add_symbols) (bfd *, struct bfd_link_info *);
+
+  /* Indicate that we are only retrieving symbol values from this section.  */
+  void        (*_bfd_link_just_syms) (asection *, struct bfd_link_info *);
+
+  /* Do a link based on the link_order structures attached to each
+     section of the BFD.  */
+  bfd_boolean (*_bfd_final_link) (bfd *, struct bfd_link_info *);
+
+  /* Should this section be split up into smaller pieces during linking.  */
+  bfd_boolean (*_bfd_link_split_section) (bfd *, struct bfd_section *);
+
+  /* Remove sections that are not referenced from the output.  */
+  bfd_boolean (*_bfd_gc_sections) (bfd *, struct bfd_link_info *);
+
+  /* Attempt to merge SEC_MERGE sections.  */
+  bfd_boolean (*_bfd_merge_sections) (bfd *, struct bfd_link_info *);
+
+  /* Is this section a member of a group?  */
+  bfd_boolean (*_bfd_is_group_section) (bfd *, const struct bfd_section *);
+
+  /* Discard members of a group.  */
+  bfd_boolean (*_bfd_discard_group) (bfd *, struct bfd_section *);
+
+  /* Check if SEC has been already linked during a reloceatable or
+     final link.  */
+  void (*_section_already_linked) (bfd *, struct bfd_section *);
+
+  /* Routines to handle dynamic symbols and relocs.  */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
+  NAME##_get_dynamic_symtab_upper_bound, \
+  NAME##_canonicalize_dynamic_symtab, \
+  NAME##_get_synthetic_symtab, \
+  NAME##_get_dynamic_reloc_upper_bound, \
+  NAME##_canonicalize_dynamic_reloc
+
+  /* Get the amount of memory required to hold the dynamic symbols.  */
+  long        (*_bfd_get_dynamic_symtab_upper_bound) (bfd *);
+  /* Read in the dynamic symbols.  */
+  long        (*_bfd_canonicalize_dynamic_symtab)
+    (bfd *, struct bfd_symbol **);
+  /* Create synthetized symbols.  */
+  long        (*_bfd_get_synthetic_symtab)
+    (bfd *, long, struct bfd_symbol **, long, struct bfd_symbol **,
+     struct bfd_symbol **);
+  /* Get the amount of memory required to hold the dynamic relocs.  */
+  long        (*_bfd_get_dynamic_reloc_upper_bound) (bfd *);
+  /* Read in the dynamic relocs.  */
+  long        (*_bfd_canonicalize_dynamic_reloc)
+    (bfd *, arelent **, struct bfd_symbol **);
+
+  /* Opposite endian version of this target.  */
+  const struct bfd_target * alternative_target;
+
+  /* Data for use by back-end routines, which isn't
+     generic enough to belong in this structure.  */
+  const void *backend_data;
+
+} bfd_target;
+
+bfd_boolean bfd_set_default_target (const char *name);
+
+const bfd_target *bfd_find_target (const char *target_name, bfd *abfd);
+
+const char ** bfd_target_list (void);
+
+const bfd_target *bfd_search_for_target
+   (int (*search_func) (const bfd_target *, void *),
+    void *);
+
+/* Extracted from format.c.  */
+bfd_boolean bfd_check_format (bfd *abfd, bfd_format format);
+
+bfd_boolean bfd_check_format_matches
+   (bfd *abfd, bfd_format format, char ***matching);
+
+bfd_boolean bfd_set_format (bfd *abfd, bfd_format format);
+
+const char *bfd_format_string (bfd_format format);
+
+/* Extracted from linker.c.  */
+bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec);
+
+#define bfd_link_split_section(abfd, sec) \
+       BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
+
+void bfd_section_already_linked (bfd *abfd, asection *sec);
+
+#define bfd_section_already_linked(abfd, sec) \
+       BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+
+/* Extracted from simple.c.  */
+bfd_byte *bfd_simple_get_relocated_section_contents
+   (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
index b95d167..2af1066 100644 (file)
@@ -16,6 +16,7 @@
 #else
 # define IA32_SYSCALL_VECTOR   0x80
 #endif
+#define KDBENTER_VECTOR        0x81
 
 /*
  * Reserve the lowest usable priority level 0x20 - 0x2f for triggering
@@ -65,6 +66,7 @@
 # define RESCHEDULE_VECTOR             0xfc
 # define CALL_FUNCTION_VECTOR          0xfb
 # define CALL_FUNCTION_SINGLE_VECTOR   0xfa
+#define        KDB_VECTOR                      0xf9
 # define THERMAL_APIC_VECTOR           0xf0
 
 #else
@@ -76,6 +78,7 @@
 #define CALL_FUNCTION_SINGLE_VECTOR    0xfb
 #define THERMAL_APIC_VECTOR            0xfa
 #define THRESHOLD_APIC_VECTOR          0xf9
+#define        KDB_VECTOR                      0xf8
 #define INVALIDATE_TLB_VECTOR_END      0xf7
 #define INVALIDATE_TLB_VECTOR_START    0xf0    /* f0-f7 used for TLB flush */
 
diff --git a/include/asm-x86/kdb.h b/include/asm-x86/kdb.h
new file mode 100644 (file)
index 0000000..8ff924e
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef        _ASM_KDB_H
+#define _ASM_KDB_H
+
+/*
+ * Kernel Debugger Architecture Dependent (x86) Global Headers
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2008 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+/*
+ * 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. The vector is KDB_VECTOR,
+ * defined in hw_irq.h
+ */
+#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;
+
+/*
+ * Per cpu arch specific kdb state.  Must be in range 0xff000000.
+ */
+#define KDB_STATE_A_IF         0x01000000      /* Saved IF flag */
+
+
+#ifdef CONFIG_X86_32
+
+#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"
+
+#else  /* CONFIG_X86_32 */
+
+#define kdb_machreg_fmt                "0x%lx"
+#define kdb_machreg_fmt0       "0x%016lx"
+#define kdb_bfd_vma_fmt                "0x%lx"
+#define kdb_bfd_vma_fmt0       "0x%016lx"
+#define kdb_elfw_addr_fmt      "0x%x"
+#define kdb_elfw_addr_fmt0     "0x%016x"
+
+/*
+ * 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>
+
+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_inatomic((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);
+       r = __copy_to_user_inatomic(to, (void *)from_xxx, size);
+       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));
+}
+
+#endif /* !CONFIG_X86_32 */
+
+static inline unsigned long
+kdba_funcptr_value(void *fp)
+{
+       return (unsigned long)fp;
+}
+
+#endif /* !_ASM_KDB_H */
diff --git a/include/asm-x86/kdbprivate.h b/include/asm-x86/kdbprivate.h
new file mode 100644 (file)
index 0000000..09c2059
--- /dev/null
@@ -0,0 +1,241 @@
+#ifndef _ASM_KDBPRIVATE_H
+#define _ASM_KDBPRIVATE_H
+
+/*
+ * Kernel Debugger Architecture Dependent (x86) Private Headers
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2008 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+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
+
+/* Maximum number of arguments to a function  */
+#define KDBA_MAXARGS    16
+
+/*
+ * 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) */
+       unsigned int    bph_installed;  /* flag: hw bp is installed */
+} kdbhard_bp_t;
+
+#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 */
+
+extern kdb_machreg_t kdba_getdr6(void);
+extern void kdba_putdr6(kdb_machreg_t);
+
+extern kdb_machreg_t kdba_getdr7(void);
+
+struct kdba_running_process {
+       long sp;        /* KDB may be on a different stack */
+       long ip;        /* eip when esp was set */
+};
+
+static inline
+void kdba_unsave_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+}
+
+struct kdb_activation_record;
+extern void kdba_get_stack_info_alternate(kdb_machreg_t addr, int cpu,
+                                         struct kdb_activation_record *ar);
+
+extern void kdba_wait_for_cpus(void);
+
+
+#ifdef CONFIG_X86_32
+
+#define DR_TYPE_EXECUTE        0x0
+#define DR_TYPE_WRITE  0x1
+#define DR_TYPE_IO     0x2
+#define DR_TYPE_RW     0x3
+
+/*
+ * Platform specific environment entries
+ */
+#define KDB_PLATFORM_ENV       "IDMODE=x86", "BYTESPERWORD=4", "IDCOUNT=16"
+
+/*
+ * 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 asmlinkage kdba_setjmp(kdb_jmp_buf *);
+extern void asmlinkage kdba_longjmp(kdb_jmp_buf *, int);
+#define kdba_setjmp kdba_setjmp
+
+extern kdb_jmp_buf  *kdbjmpbuf;
+
+/* Arch specific data saved for running processes */
+static inline
+void kdba_save_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+       k->sp = current_stack_pointer;
+       __asm__ __volatile__ ( " lea 1f,%%eax; movl %%eax,%0 ; 1: " : "=r"(k->ip) : : "eax" );
+}
+
+extern void kdb_interrupt(void);
+
+#define        KDB_INT_REGISTERS       8
+
+#else  /* CONFIG_X86_32 */
+
+extern kdb_machreg_t kdba_getdr(int);
+extern void kdba_putdr(int, kdb_machreg_t);
+
+extern kdb_machreg_t kdb_getcr(int);
+
+/*
+ * Platform specific environment entries
+ */
+#define KDB_PLATFORM_ENV       "IDMODE=x86_64", "BYTESPERWORD=8", "IDCOUNT=16"
+
+/*
+ * reg indicies for x86_64 setjmp/longjmp
+ */
+#define JB_RBX   0
+#define JB_RBP   1
+#define JB_R12   2
+#define JB_R13   3
+#define JB_R14   4
+#define JB_R15   5
+#define JB_RSP   6
+#define JB_PC    7
+
+typedef struct __kdb_jmp_buf {
+        unsigned long   regs[8];       /* kdba_setjmp assumes fixed offsets here */
+} kdb_jmp_buf;
+
+extern int asmlinkage kdba_setjmp(kdb_jmp_buf *);
+extern void asmlinkage kdba_longjmp(kdb_jmp_buf *, int);
+#define kdba_setjmp kdba_setjmp
+
+extern kdb_jmp_buf  *kdbjmpbuf;
+
+/* Arch specific data saved for running processes */
+register unsigned long current_stack_pointer asm("rsp") __used;
+
+static inline
+void kdba_save_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+       k->sp = current_stack_pointer;
+       __asm__ __volatile__ ( " lea 0(%%rip),%%rax; movq %%rax,%0 ; " : "=r"(k->ip) : : "rax" );
+}
+
+extern asmlinkage void kdb_interrupt(void);
+
+#define        KDB_INT_REGISTERS       16
+
+#endif /* !CONFIG_X86_32 */
+
+#endif /* !_ASM_KDBPRIVATE_H */
index 96651bb..185a73e 100644 (file)
@@ -15,6 +15,8 @@ enum die_val {
        DIE_DIE,
        DIE_NMIWATCHDOG,
        DIE_KERNELDEBUG,
+       DIE_KDEBUG_ENTER,
+       DIE_KDEBUG_LEAVE,
        DIE_TRAP,
        DIE_GPF,
        DIE_CALL,
index 5f41741..f94153f 100644 (file)
@@ -21,7 +21,8 @@ D(9)  KM_IRQ0,
 D(10)  KM_IRQ1,
 D(11)  KM_SOFTIRQ0,
 D(12)  KM_SOFTIRQ1,
-D(13)  KM_TYPE_NR
+D(13)  KM_KDB,
+D(14)  KM_TYPE_NR
 };
 
 #undef D
index 8a71db8..ba3cadd 100644 (file)
 /* this struct defines the way the registers are stored on the
    stack during a system call. */
 
+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 */
+};
+
 #ifndef __KERNEL__
 
 struct pt_regs {
index 934dd22..bd366c0 100644 (file)
@@ -143,7 +143,12 @@ void vcs_remove_sysfs(struct tty_struct *tty);
 
 /* Some debug stub to catch some of the obvious races in the VT code */
 #if 1
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#define WARN_CONSOLE_UNLOCKED()        WARN_ON(!is_console_locked() && !oops_in_progress && !atomic_read(&kdb_event))
+#else  /* !CONFIG_KDB */
 #define WARN_CONSOLE_UNLOCKED()        WARN_ON(!is_console_locked() && !oops_in_progress)
+#endif /* CONFIG_KDB */
 #else
 #define WARN_CONSOLE_UNLOCKED()
 #endif
diff --git a/include/linux/dis-asm.h b/include/linux/dis-asm.h
new file mode 100644 (file)
index 0000000..8462fc9
--- /dev/null
@@ -0,0 +1,347 @@
+/* Interface between the opcode library and its callers.
+
+   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   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., 51 Franklin Street - Fifth Floor,
+   Boston, MA 02110-1301, USA.
+
+   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.  */
+
+/* Extracted from binutils 2.16.91.0.2 (OpenSUSE 10.0) and modified for kdb use.
+ * Any trailing whitespace was removed and #ifdef/ifndef __KERNEL__ added as
+ * required.
+ * Keith Owens <kaos@sgi.com> 15 May 2006
+ */
+
+#ifndef DIS_ASM_H
+#define DIS_ASM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __KERNEL__
+#include <asm/ansidecl.h>
+#include <asm/bfd.h>
+typedef void FILE;
+#else  /* __KERNEL__ */
+#include <stdio.h>
+#include "bfd.h"
+#endif /* __KERNEL__ */
+
+typedef int (*fprintf_ftype) (void *, const char*, ...) ATTRIBUTE_FPTR_PRINTF_2;
+
+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;
+  void *stream;
+  void *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 arch/mach-specific bitmask of selected instruction subsets, mainly
+     for processors with run-time-switchable instruction sets.  The default,
+     zero, means that there is no constraint.  CGEN-based opcodes ports
+     may use ISA_foo masks.  */
+  unsigned long insn_sets;
+
+  /* Some targets need information about the current section to accurately
+     display insns.  If this is NULL, the target disassembler function
+     will have to make its best guess.  */
+  asection *section;
+
+  /* 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
+  void *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)
+    (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)
+    (int status, bfd_vma memaddr, struct disassemble_info *info);
+
+  /* Function called to print ADDR.  */
+  void (*print_address_func)
+    (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)
+    (bfd_vma addr, struct disassemble_info * info);
+
+  /* Function called to check if a SYMBOL is can be displayed to the user.
+     This is used by some ports that want to hide special symbols when
+     displaying debugging outout.  */
+  bfd_boolean (* symbol_is_valid)
+    (asymbol *, 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;
+
+  /* The number of zeroes we want to see at the end of a section before we
+     start skipping them.  */
+  unsigned int skip_zeroes;
+
+  /* The number of zeroes to skip at the end of a section.  If the number
+     of zeroes at the end is between SKIP_ZEROES_AT_END and SKIP_ZEROES,
+     they will be disassembled.  If there are fewer than
+     SKIP_ZEROES_AT_END, they will be skipped.  This is a heuristic
+     attempt to avoid disassembling zeroes inserted by section
+     alignment.  */
+  unsigned int skip_zeroes_at_end;
+
+  /* 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;
+
+\f
+/* Standard disassemblers.  Disassemble one instruction at the given
+   target address.  Return number of octets processed.  */
+typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *);
+
+extern int print_insn_big_mips         (bfd_vma, disassemble_info *);
+extern int print_insn_little_mips      (bfd_vma, disassemble_info *);
+extern int print_insn_i386             (bfd_vma, disassemble_info *);
+extern int print_insn_i386_att         (bfd_vma, disassemble_info *);
+extern int print_insn_i386_intel       (bfd_vma, disassemble_info *);
+extern int print_insn_ia64             (bfd_vma, disassemble_info *);
+extern int print_insn_i370             (bfd_vma, disassemble_info *);
+extern int print_insn_m68hc11          (bfd_vma, disassemble_info *);
+extern int print_insn_m68hc12          (bfd_vma, disassemble_info *);
+extern int print_insn_m68k             (bfd_vma, disassemble_info *);
+extern int print_insn_z8001            (bfd_vma, disassemble_info *);
+extern int print_insn_z8002            (bfd_vma, disassemble_info *);
+extern int print_insn_h8300            (bfd_vma, disassemble_info *);
+extern int print_insn_h8300h           (bfd_vma, disassemble_info *);
+extern int print_insn_h8300s           (bfd_vma, disassemble_info *);
+extern int print_insn_h8500            (bfd_vma, disassemble_info *);
+extern int print_insn_alpha            (bfd_vma, disassemble_info *);
+extern int print_insn_big_arm          (bfd_vma, disassemble_info *);
+extern int print_insn_little_arm       (bfd_vma, disassemble_info *);
+extern int print_insn_sparc            (bfd_vma, disassemble_info *);
+extern int print_insn_big_a29k         (bfd_vma, disassemble_info *);
+extern int print_insn_little_a29k      (bfd_vma, disassemble_info *);
+extern int print_insn_avr              (bfd_vma, disassemble_info *);
+extern int print_insn_d10v             (bfd_vma, disassemble_info *);
+extern int print_insn_d30v             (bfd_vma, disassemble_info *);
+extern int print_insn_dlx              (bfd_vma, disassemble_info *);
+extern int print_insn_fr30             (bfd_vma, disassemble_info *);
+extern int print_insn_hppa             (bfd_vma, disassemble_info *);
+extern int print_insn_i860             (bfd_vma, disassemble_info *);
+extern int print_insn_i960             (bfd_vma, disassemble_info *);
+extern int print_insn_ip2k             (bfd_vma, disassemble_info *);
+extern int print_insn_m32r             (bfd_vma, disassemble_info *);
+extern int print_insn_m88k             (bfd_vma, disassemble_info *);
+extern int print_insn_maxq_little      (bfd_vma, disassemble_info *);
+extern int print_insn_maxq_big         (bfd_vma, disassemble_info *);
+extern int print_insn_mcore            (bfd_vma, disassemble_info *);
+extern int print_insn_mmix             (bfd_vma, disassemble_info *);
+extern int print_insn_mn10200          (bfd_vma, disassemble_info *);
+extern int print_insn_mn10300          (bfd_vma, disassemble_info *);
+extern int print_insn_ms1               (bfd_vma, disassemble_info *);
+extern int print_insn_msp430           (bfd_vma, disassemble_info *);
+extern int print_insn_ns32k            (bfd_vma, disassemble_info *);
+extern int print_insn_crx               (bfd_vma, disassemble_info *);
+extern int print_insn_openrisc         (bfd_vma, disassemble_info *);
+extern int print_insn_big_or32         (bfd_vma, disassemble_info *);
+extern int print_insn_little_or32      (bfd_vma, disassemble_info *);
+extern int print_insn_pdp11            (bfd_vma, disassemble_info *);
+extern int print_insn_pj               (bfd_vma, disassemble_info *);
+extern int print_insn_big_powerpc      (bfd_vma, disassemble_info *);
+extern int print_insn_little_powerpc   (bfd_vma, disassemble_info *);
+extern int print_insn_rs6000           (bfd_vma, disassemble_info *);
+extern int print_insn_s390             (bfd_vma, disassemble_info *);
+extern int print_insn_sh               (bfd_vma, disassemble_info *);
+extern int print_insn_tic30            (bfd_vma, disassemble_info *);
+extern int print_insn_tic4x            (bfd_vma, disassemble_info *);
+extern int print_insn_tic54x           (bfd_vma, disassemble_info *);
+extern int print_insn_tic80            (bfd_vma, disassemble_info *);
+extern int print_insn_v850             (bfd_vma, disassemble_info *);
+extern int print_insn_vax              (bfd_vma, disassemble_info *);
+extern int print_insn_w65              (bfd_vma, disassemble_info *);
+extern int print_insn_xstormy16                (bfd_vma, disassemble_info *);
+extern int print_insn_xtensa           (bfd_vma, disassemble_info *);
+extern int print_insn_sh64             (bfd_vma, disassemble_info *);
+extern int print_insn_sh64x_media      (bfd_vma, disassemble_info *);
+extern int print_insn_frv              (bfd_vma, disassemble_info *);
+extern int print_insn_iq2000           (bfd_vma, disassemble_info *);
+extern int print_insn_m32c     (bfd_vma, disassemble_info *);
+
+extern disassembler_ftype arc_get_disassembler (void *);
+extern disassembler_ftype cris_get_disassembler (bfd *);
+
+extern void print_mips_disassembler_options (FILE *);
+extern void print_ppc_disassembler_options (FILE *);
+extern void print_arm_disassembler_options (FILE *);
+extern void parse_arm_disassembler_option (char *);
+extern int get_arm_regname_num_options (void);
+extern int set_arm_regname_option (int);
+extern int get_arm_regnames (int, const char **, const char **, const char *const **);
+extern bfd_boolean arm_symbol_is_valid (asymbol *, struct disassemble_info *);
+
+/* Fetch the disassembler for a given BFD, if that support is available.  */
+extern disassembler_ftype disassembler (bfd *);
+
+/* Amend the disassemble_info structure as necessary for the target architecture.
+   Should only be called after initialising the info->arch field.  */
+extern void disassemble_init_for_target (struct disassemble_info * info);
+
+/* Document any target specific options available from the disassembler.  */
+extern void disassembler_usage (FILE *);
+
+\f
+/* 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
+  (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 (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
+  (bfd_vma, struct disassemble_info *);
+
+/* Always true.  */
+extern int generic_symbol_at_address
+  (bfd_vma, struct disassemble_info *);
+
+/* Also always true.  */
+extern bfd_boolean generic_symbol_is_valid
+  (asymbol *, struct disassemble_info *);
+
+/* Method to initialize a disassemble_info struct.  This should be
+   called by all applications creating such a struct.  */
+extern void init_disassemble_info (struct disassemble_info *info, void *stream,
+                                  fprintf_ftype fprintf_func);
+
+/* For compatibility with existing code.  */
+#define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \
+  init_disassemble_info (&(INFO), (STREAM), (fprintf_ftype) (FPRINTF_FUNC))
+#define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \
+  init_disassemble_info (&(INFO), (STREAM), (fprintf_ftype) (FPRINTF_FUNC))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! defined (DIS_ASM_H) */
diff --git a/include/linux/kdb.h b/include/linux/kdb.h
new file mode 100644 (file)
index 0000000..442409b
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef _KDB_H
+#define _KDB_H
+
+/*
+ * Kernel Debugger Architecture Independent Global Headers
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2000-2007 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <asm/atomic.h>
+
+#ifdef CONFIG_KDB
+/* These are really private, but they must be defined before including
+ * asm-$(ARCH)/kdb.h, so make them public and put them here.
+ */
+extern int kdb_getuserarea_size(void *, unsigned long, size_t);
+extern int kdb_putuserarea_size(unsigned long, void *, size_t);
+
+#include <asm/kdb.h>
+#endif
+
+#define KDB_MAJOR_VERSION      4
+#define KDB_MINOR_VERSION      4
+#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;
+extern atomic_t kdb_event;
+extern atomic_t kdb_8250;
+#ifdef CONFIG_KDB
+#define KDB_IS_RUNNING() (kdb_initial_cpu != -1)
+#define KDB_8250() (atomic_read(&kdb_8250) != 0)
+#else
+#define KDB_IS_RUNNING() (0)
+#define KDB_8250() (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/on-nokey
+ *     or echo "[012]" > /proc/sys/kernel/kdb to change it.
+ */
+extern int kdb_on;
+
+#if defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_SGI_L1_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 */
+#define KDB_FLAG_NO_CONSOLE    (1 << 5)        /* No console is available, kdb is disabled */
+#define KDB_FLAG_NO_VT_CONSOLE (1 << 6)        /* No VT console is available, do not use keyboard */
+#define KDB_FLAG_NO_I8042      (1 << 7)        /* No i8042 chip is available, do not use keyboard */
+#define KDB_FLAG_RECOVERY      (1 << 8)        /* kdb is being entered for an error which has been recovered */
+
+extern volatile int kdb_flags;                 /* Global flags, see kdb_state for per cpu state */
+
+extern void kdb_save_flags(void);
+extern void kdb_restore_flags(void);
+
+#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))
+
+/*
+ * 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_ENTER=1,             /* KDB_ENTER() trap/fault - regs valid */
+       KDB_REASON_ENTER_SLAVE,         /* KDB_ENTER_SLAVE() trap/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_KEYBOARD,            /* Keyboard entry - regs valid */
+       KDB_REASON_NMI,                 /* Non-maskable interrupt; regs valid */
+       KDB_REASON_RECURSE,             /* Recursive entry to kdb; regs probably valid */
+       KDB_REASON_CPU_UP,              /* Add one cpu to kdb; regs invalid */
+       KDB_REASON_SILENT,              /* Silent entry/exit to kdb; regs invalid - internal only */
+} kdb_reason_t;
+
+#ifdef CONFIG_KDB
+extern int kdb(kdb_reason_t, int, struct pt_regs *);
+#else
+#define kdb(reason,error_code,frame) (0)
+#endif
+
+/* Mainly used by kdb code, but this function is sometimes used
+ * by hacked debug code so make it generally available, not private.
+ */
+extern void kdb_printf(const char *,...)
+           __attribute__ ((format (printf, 1, 2)));
+typedef void (*kdb_printf_t)(const char *, ...)
+            __attribute__ ((format (printf, 1, 2)));
+extern void kdb_init(void);
+
+#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 */
+
+#ifdef CONFIG_KDB_USB
+
+#include <linux/usb.h>
+
+extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func);
+extern int kdb_usb_keyboard_detach(struct urb *urb);
+
+#endif /* CONFIG_KDB_USB */
+
+static inline
+int kdb_process_cpu(const struct task_struct *p)
+{
+       unsigned int cpu = task_thread_info(p)->cpu;
+       if (cpu > NR_CPUS)
+               cpu = 0;
+       return cpu;
+}
+
+extern const char kdb_serial_str[];
+
+#ifdef CONFIG_KDB_KDUMP
+/* Define values for kdb_kdump_state */
+extern int kdb_kdump_state;    /* KDB kdump state */
+#define KDB_KDUMP_RESET                0
+#define KDB_KDUMP_KDUMP                1
+
+void kdba_kdump_prepare(struct pt_regs *);
+void machine_crash_shutdown(struct pt_regs *);
+void machine_crash_shutdown_begin(void);
+void machine_crash_shutdown_end(struct pt_regs *);
+
+#endif /* CONFIG_KDB_KDUMP */
+
+#endif /* !_KDB_H */
diff --git a/include/linux/kdbprivate.h b/include/linux/kdbprivate.h
new file mode 100644 (file)
index 0000000..c015dbc
--- /dev/null
@@ -0,0 +1,504 @@
+#ifndef _KDBPRIVATE_H
+#define _KDBPRIVATE_H
+
+/*
+ * Kernel Debugger Architecture Independent Private Headers
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+#include <linux/dis-asm.h>
+#include <asm/kdbprivate.h>
+#include <asm/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)
+
+       /*
+        * Internal debug flags
+        */
+/*     KDB_DEBUG_FLAG_BT       0x0001          Was Stack traceback debug */
+#define KDB_DEBUG_FLAG_BP      0x0002          /* Breakpoint subsystem debug */
+#define KDB_DEBUG_FLAG_BB_SUMM 0x0004          /* Basic block analysis, summary only */
+#define KDB_DEBUG_FLAG_AR      0x0008          /* Activation record, generic */
+#define KDB_DEBUG_FLAG_ARA     0x0010          /* Activation record, arch specific */
+#define KDB_DEBUG_FLAG_BB      0x0020          /* All basic block analysis */
+#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 */
+
+#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)
+
+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;
+
+typedef int (*kdb_func_t)(int, const char **);
+
+       /*
+        * 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;
+extern int kallsyms_symbol_next(char *prefix_name, int flag);
+extern int kallsyms_symbol_complete(char *prefix_name, int max_len);
+
+       /*
+        * 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_getphysword(unsigned long *word,
+                       unsigned long addr, size_t size);
+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 **);
+extern int kdbgetsymval(const char *, kdb_symtab_t *);
+extern int kdbnearsym(unsigned long, kdb_symtab_t *);
+extern void kdbnearsym_cleanup(void);
+extern char *kdb_read(char *buffer, size_t bufsize);
+extern char *kdb_strdup(const char *str, gfp_t type);
+extern void kdb_symbol_print(kdb_machreg_t, const kdb_symtab_t *, unsigned int);
+
+        /*
+         * 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);
+
+       /*
+        * 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_KEYBOARD     0x00020000      /* kdb entered via keyboard on this cpu */
+#define KDB_STATE_KEXEC                0x00040000      /* kexec issued */
+#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())
+
+       /*
+        * 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[NR_CPUS]; /* 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_alloc_hwbp(kdb_bp_t *bp, int *diagp);
+extern void kdba_free_hwbp(kdb_bp_t *bp);
+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);
+
+       /*
+        * 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[];
+
+#ifndef        CONFIG_IA64
+       /*
+        * Data for a single activation record on stack.
+        */
+
+struct kdb_stack_info {
+       kdb_machreg_t physical_start;
+       kdb_machreg_t physical_end;
+       kdb_machreg_t logical_start;
+       kdb_machreg_t logical_end;
+       kdb_machreg_t next;
+       const char *  id;
+};
+
+typedef struct { DECLARE_BITMAP(bits, KDBA_MAXARGS); } valid_t;
+
+struct kdb_activation_record {
+       struct kdb_stack_info   stack;          /* information about current stack */
+       int             args;                   /* number of arguments detected */
+       kdb_machreg_t   arg[KDBA_MAXARGS];      /* -> arguments */
+       valid_t         valid;                  /* is argument n valid? */
+};
+#endif
+
+       /*
+        * Architecture specific Stack Traceback functions.
+        */
+
+struct task_struct;
+
+extern int kdba_bt_address(kdb_machreg_t, int);
+extern int kdba_bt_process(const struct task_struct *, int);
+
+       /*
+        * 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 **);
+extern int kdb_bt(int, const char **);
+
+       /*
+        * 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 unsigned long 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 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(const char *);
+extern char kdb_task_state_char (const struct task_struct *);
+extern unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask);
+extern void kdb_ps_suppressed(void);
+extern void kdb_ps1(const struct task_struct *p);
+extern int kdb_parse(const char *cmdstr);
+extern void kdb_print_nameval(const char *name, unsigned long val);
+extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info, int seqno);
+#ifdef CONFIG_SWAP
+extern void kdb_si_swapinfo(struct sysinfo *);
+#else
+#include <linux/swap.h>
+#define kdb_si_swapinfo(x) si_swapinfo(x)
+#endif
+extern void kdb_meminfo_read_proc(void);
+#ifdef CONFIG_HUGETLB_PAGE
+extern void kdb_hugetlb_report_meminfo(void);
+#endif /* CONFIG_HUGETLB_PAGE */
+extern const char *kdb_walk_kallsyms(loff_t *pos);
+
+       /*
+        * 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 */
+       int irq_depth;                          /* irq count */
+       struct kdba_running_process arch;       /* arch dependent save data */
+};
+
+extern struct kdb_running_process kdb_running_process[/* NR_CPUS */];
+
+extern int kdb_save_running(struct pt_regs *, kdb_reason_t, kdb_reason_t, int, kdb_dbtrap_t);
+extern void kdb_unsave_running(struct pt_regs *);
+extern struct task_struct *kdb_curr_task(int);
+
+/*     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;
+
+#define kdb_task_has_cpu(p) (task_curr(p))
+extern void kdb_runqueue(unsigned long cpu, kdb_printf_t xxx_printf);
+
+/* Simplify coexistence with NPTL */
+#define        kdb_do_each_thread(g, p) do_each_thread(g, p)
+#define        kdb_while_each_thread(g, p) while_each_thread(g, p)
+
+#define GFP_KDB (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
+
+extern void *debug_kmalloc(size_t size, gfp_t flags);
+extern void debug_kfree(void *);
+extern void debug_kusage(void);
+
+extern void kdba_set_current_task(const struct task_struct *);
+extern const struct task_struct *kdb_current_task;
+extern struct pt_regs *kdb_current_regs;
+
+/* 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.
+ */
+
+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);
+extern int kdba_verify_rw(unsigned long addr, size_t size);
+
+#ifndef KDB_RUNNING_PROCESS_ORIGINAL
+#define KDB_RUNNING_PROCESS_ORIGINAL kdb_running_process
+#endif
+
+extern int kdb_wait_for_cpus_secs;
+extern void kdba_cpu_up(void);
+extern char kdb_prompt_str[];
+
+#define        KDB_WORD_SIZE   ((int)sizeof(kdb_machreg_t))
+
+#ifdef CONFIG_KDB_USB
+#include <linux/usb.h>
+
+struct kdb_usb_kbd_info {
+       struct urb *urb;                /* pointer to the URB */
+       unsigned char *buffer;          /* pointer to the kbd char buffer */
+       int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */
+       int     poll_ret;       /* return val from poll_func */
+       int     caps_lock;      /* state of the caps lock for this keyboard */
+};
+#endif /* CONFIG_KDB_USB */
+
+#ifdef CONFIG_KDB_KDUMP
+#define KDUMP_REASON_RESET     0
+extern void kdba_kdump_shutdown_slave(struct pt_regs *);
+extern int kdb_kdump_reason;
+#endif /* CONFIG_KDB_KDUMP */
+
+#endif /* !_KDBPRIVATE_H */
index b93b541..cbd2cb1 100644 (file)
@@ -53,7 +53,14 @@ extern void machine_power_off(void);
 
 extern void machine_shutdown(void);
 struct pt_regs;
+#ifdef CONFIG_KDB_KDUMP
 extern void machine_crash_shutdown(struct pt_regs *);
+extern void machine_crash_shutdown_begin(void);
+extern void machine_crash_shutdown_other_cpu(struct pt_regs *);
+extern void machine_crash_shutdown_end(struct pt_regs *);
+#else
+extern void machine_crash_shutdown(struct pt_regs *);
+#endif /* !CONFIG_KDB_KDUMP */
 
 /* 
  * Architecture independent implemenations of sys_reboot commands.
index 5cae23b..c03dfb9 100644 (file)
@@ -163,6 +163,7 @@ enum
        KERN_MAX_LOCK_DEPTH=74,
        KERN_NMI_WATCHDOG=75, /* int: enable/disable nmi watchdog */
        KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
+       KERN_KDB=77,            /* int: kdb on/off */
 };
 
 
index f6f7042..bf00e12 100644 (file)
 #include <asm/smp.h>
 #endif
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
+
 /*
  * This is one of the first .c files built. Error out early if we have compiler
  * trouble.
@@ -193,6 +197,26 @@ static const char *panic_later, *panic_param;
 
 extern struct obs_kernel_param __setup_start[], __setup_end[];
 
+#ifdef CONFIG_KDB
+static int __init kdb_setup(char *str)
+{
+       if (strcmp(str, "on") == 0) {
+               kdb_on = 1;
+       } else if (strcmp(str, "on-nokey") == 0) {
+               kdb_on = 2;
+       } else if (strcmp(str, "off") == 0) {
+               kdb_on = 0;
+       } else if (strcmp(str, "early") == 0) {
+               kdb_on = 1;
+               kdb_flags |= KDB_FLAG_EARLYKDB;
+       } else
+               printk("kdb flag %s not recognised\n", str);
+       return 0;
+}
+
+__setup("kdb=", kdb_setup);
+#endif /* CONFIG_KDB */
+
 static int __init obsolete_checksetup(char *line)
 {
        struct obs_kernel_param *p;
@@ -659,6 +683,14 @@ asmlinkage void __init start_kernel(void)
        pgtable_cache_init();
        prio_tree_init();
        anon_vma_init();
+
+#ifdef CONFIG_KDB
+       kdb_init();
+       if (KDB_FLAG(EARLYKDB)) {
+               KDB_ENTER();
+       }
+#endif /* CONFIG_KDB */
+
 #ifdef CONFIG_X86
        if (efi_enabled)
                efi_enter_virtual_mode();
diff --git a/kdb/ChangeLog b/kdb/ChangeLog
new file mode 100644 (file)
index 0000000..c3d10f3
--- /dev/null
@@ -0,0 +1,1989 @@
+2008-08-14 Jay Lan  <jlan@sgi.com>
+
+       * Support 'kdump' command to take a kdump vmcore from KDB,
+           Dan Aloni (da-x@monatomic.org),
+           Jason Xiao (jidong.xiao@gmail.com),
+           Jay Lan (jlan@sgi.com)
+       * kdb-v4.4-2.6.27-rc2-common-2.
+
+2008-08-06 Jay Lan  <jlan@sgi.com>
+
+       * Fix up the NULL pointer deference issue in ohci_kdb_poll_char,
+         Jason Xiao <jidong.xiao@gmail.com>
+       * kdb-v4.4-2.6.27-rc2-common-1.
+
+2008-07-18 Jay Lan  <jlan@sgi.com>
+
+       * support Hardware Breakpoint (bph/bpha) commands
+         IA64: Greg Banks <gnb@sgi.com>
+         X86:  Konstantin Baydarov <kbaidarov@ru.mvista.com>
+       * kdb-v4.4-2.6.26-common-2.
+
+2008-07-14 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-common-1.
+
+2008-07-11 Jay Lan  <jlan@sgi.com>
+
+       * New commands and some fixups and enhancements,
+         Joe Korty <joe.korty@ccur.com>
+         John Blackwood <john.blackwood@ccur.com>
+         Jim Houston <jim.houston@ccur.com>
+         - Use the non-sleeping copy_from_user_atomic.
+         - Enhance kdb_cmderror diagnostic output.
+         - Expand the KDB 'duplicate command' error message.
+         - Touch NMI watchdog in various KDB busy-loops.
+         - Support IMB HS20 Blade 8843 platform.
+         - Display exactly which cpus needed an NMI to get them into kdb.
+         - Better document that kdb's 'ps A' command can be used to show
+           _all_ processes and threads
+         - Suppress KDB boottime INFO messages if quiet boot.
+         - Add a KDB breakpoint to the OOPs path.
+         - Add CONFIG_DISCONTIGMEM support to kdbm_memmap.
+         - Extend the KDB task command to handle CONFIG_NUMA fields.
+         - Extend the KDB vm command to support NUMA stuff.
+         - Create the KDB mempolicy command.
+         - Create a pgdat command for KDB.
+         - Fix a hang on boot on some i386 systems.
+       * kdb-v4.4-2.6.26-rc9-common-1.
+
+2008-06-30 Jay Lan  <jlan@sgi.com>
+
+       * compilation warning cleanup, Cliff Wickman <cpw@sgi.com>
+       * kdb-v4.4-2.6.26-rc8-common-1.
+
+2008-06-25 Jay Lan  <jlan@sgi.com>
+
+       * Added John Blackwood <john.blackwood@ccur.com> to the authors of
+         kdb-v4.4-2.6.26-rc4-common-2.
+       * kdb-v4.4-2.6.26-rc7-common-1.
+
+2008-06-24 Jay Lan  <jlan@sgi.com>
+
+       * support lcrash style debug_info file: Cliff Wickman <cpw@sgi.com>
+         - It adds to kdb the ability to symbolically dereference structure
+           pointers through a lcrash-style debug_info file.
+         - Implements "print", "px", and "pd" print commands.
+         - Implements "walk" command to follow linked lists.
+         - Implements "whatis" to display a structure (with offsets).
+         - Implements "sizeof" for types (structures, typedefs, etc.).
+       * kdb-v4.4-2.6.26-rc5-common-2.
+
+2008-06-06 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc5-common-1.
+
+2008-06-05 Jay Lan  <jlan@sgi.com>
+
+       * fixed 'rq/rqa' command runs off the end of runqueue's rt.active
+          priority bitmap array, John Blackwood <john.blackwood@ccur.com> &
+         Lachlan McIlroy <lachlan@sgi.com>
+       * kdb-v4.4-2.6.26-rc4-common-2.
+
+2008-05-30 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc4-common-1.
+
+2008-05-20 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.26-rc3-common-1.
+
+2008-05-13 Jay Lan  <jlan@sgi.com>
+
+       * XPC support is removed from KDB due to XPC changes in 2.6.26-rc1.
+       * kdb-v4.4-2.6.26-rc1-common-1.
+
+2008-04-17 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.25-common-1.
+
+2008-03-16 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.25-rc6-common-1.
+
+2008-03-03 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.25-rc3-common-1.
+
+2008-02-26 Jay Lan  <jlan@sgi.com>
+
+       * remove 'fastcall' from kdb code.
+       * kdb-v4.4-2.6.25-rc2-common-1.
+
+2008-02-19 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.25-rc1-common-1.
+
+2008-02-06 Jay Lan  <jlan@sgi.com>
+
+       * Backed out USB UHCI support since it caused dropped characters and
+          broke OHCI.
+       * Restored "archkdbcommon" commands for x86. It was lost at the x86
+         merge.
+       * Detecting if the HC was "busy", Aaron Young <ayoung@sgi.com>
+       * kdb-v4.4-2.6.24-common-2.
+
+2008-01-29 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.24-common-1.
+
+2008-01-22 Jay Lan  <jlan@sgi.com>
+
+       * USB UHCI kdb support, Konstantin Baydarov <kbaidarov@ru.mvista.com>
+       * kdb-v4.4-2.6.24-rc8-common-3.
+
+2008-01-18 Jay Lan  <jlan@sgi.com>
+
+       * USB EHCI kdb support,  Aaron Young <ayoung@sgi.com>
+       * kdb-v4.4-2.6.24-rc8-common-2.
+
+2008-01-18 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.24-rc8-common-1.
+
+2008-01-07 Jay Lan  <jlan@sgi.com>
+
+       * kdb-v4.4-2.6.24-rc7-common-1.
+
+2007-12-21 Jay Lan  <jlan@sgi.com>
+
+       * Renamed kdb/kdba_bt_x86.c to arch/x86/kdba_bt.c. And thus, the x86
+         backtrace code is now moved into the kdb x86 patch.
+       * kdb v4.4-2.6.24-rc6-common-1.
+
+2007-12-12 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.24-rc5-common-1.
+
+2007-12-05 Jay Lan  <jlan@sgi.com>
+
+       * Fixed a 'sysctl table check failed' problem.
+       * kdb v4.4-2.6.24-rc4-common-1.
+
+2007-11-26 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.24-rc3-common-1.
+
+2007-11-13 Jay Lan  <jlan@sgi.com>
+
+       * Back ported "New KDB USB interface" from Aaron Young in
+         v4.4-2.6.23-common-2 to 2.6.24 kdb patchset.
+       * kdb v4.4-2.6.24-rc2-common-2.
+
+2007-11-12 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.24-rc2-common-1.
+
+2007-11-09 Jay Lan  <jlan@sgi.com>
+
+       * Rebase to 2.6.24-rc1 kernel
+       *   - merged kdb-v4.4-2.6.23-i386-1 and kdb-v4.4-2.6.23-x86_64-1
+       *     into kdb-v4.4-2.6.24-rc1-x86-1
+       *   - Fields "done", "sglist_len", and "pid" are removed from
+       *     struct scsi_cmnd. Thus, these fields are no longer displayed
+       *     on "sc" command.
+       * kdb v4.4-2.6.24-rc1-common-1.
+
+2007-11-08 Jay Lan  <jlan@sgi.com>
+
+       * New KDB USB interface,  Aaron Young <ayoung@sgi.com>
+       *  1. This patch allows KDB to work with any Host Contoller driver
+       *     and call the correct HC driver poll routine (as long as the
+       *     HC driver provides a .kdb_poll_char routine via it's
+       *     associated hc_driver struct).
+       *  2. Hotplugged keyboards are now recognized by KDB.
+       *  3. Currently KDB can only make use of 1 USB type keyboard.
+       *     New code can handle up to 8 attached keyboards - input is
+       *     multiplexed from all of them while in kdb.
+       * kdb v4.4-2.6.23-common-2.
+
+2007-10-24 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-common-1.
+
+2007-09-26 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc8-common-1.
+
+2007-09-21 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc7-common-1.
+
+2007-09-12 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc6-common-1.
+
+2007-09-06 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc5-common-1.
+
+2007-08-30 Keith Owens  <kaos@sgi.com>
+
+       * New i386/x86_64 backtrace requires that kdb_save_running() does not
+         exit until after kdb_main_loop() has completed.
+       * List more noret functions in i386/x86_64 backtrace code.
+       * Call to a noret function ends a basic block.
+       * After a call to a noret function, eip/rip may be pointing at the next
+         function or not, depending on function alignment.  Jay Lan.
+       * kdb v4.4-2.6.23-rc4-common-2.
+
+2007-08-30 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc4-common-1.
+
+2007-08-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb/kdba_bt_x86.c:
+       *   Handle the variable amount of stack data that is pushed by x86_64
+       *   hardware on an interrupt.
+       *   Add instruction vmsave.
+       *   Handle pop to %rsp.
+       *   Cope with return address for functions defined as ATTRIB_NORET.
+       *   Include CONFIG_DEBUG_INFO in the summary line of bb_all.
+       *   Check for an interrupt that was delivered while user space was in
+       *   control.
+       *   A return to child_rip ends a backtrace.
+       *   Ignore level2_kernel_pgt and level3_kernel_pgt data areas if they
+       *   occur within the text segment.
+       * kdb v4.4-2.6.23-rc3-common-2.
+
+2007-08-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.23-rc3-common-1.
+
+2007-08-24 Jay Lan  <jlan@sgi.com>
+
+       * kdb/kdba_bt_x86.c:
+       *   retint_kernel is only defined for CONFIG_PREEMPT.
+       *   Handle assembler code for CONFIG_HIBERNATION=y.
+       *   Handle assembler code for CONFIG_MATH_EMULATION=y.
+       *   Handle assembler code for CONFIG_XEN=y.
+       *   Handle assembler code for CONFIG_KPROBES=y.
+       *   Add CC version to the bb_all header.
+       *   Handle spurious label in jprobe_return.
+       *   Handle stack switch in jprobe_return.
+       *   Prefix register name with '%' in xadd/xchg temporary variable.
+       *   Require bb_usage_mov() to handle all the special cases internally.
+       *   Handle stack manipulation for kexec.
+       *   Handle spurious label in kretprobe_trampoline_holder.
+       *   Add instructions clgi, invlpga, rcl, rdpmc, stgi, vmclear,
+       *   vmlaunch, vmload, vmptrld, vmread, vmresume, vmrun, vmwrite,
+       *   xstore-rng.
+       *   Exclude more 16 bit and/or real mode acpi functions from bb_all.
+       *   Handle assembler stack switching code in i386 do_softirq.
+       * kdb/kdbmain.c:
+       *   Add CC version to the summary output.
+       *   Bump debug_kmalloc pool from 128K to 256K, some of the kernel
+       *   functions have huge numbers of basic blocks and jumps between them.
+       *   Correct reinstallation of breakpoints when exiting KDB.
+       * Keith Owens.
+       * kdb v4.4-2.6.23-rc2-common-2.
+
+2007-08-07 Jay Lan  <jlan@sgi.com>
+
+       * kdb v4.4-2.6.23-rc2-common-1.
+
+2007-08-03 Keith Owens  <kaos@sgi.com>
+
+       * kdba_bt_x86.c: Rename some variables to make the code more readable.
+         Print more debug information when merging register states and when
+         calculating the new stack pointer.
+       * kdb v4.4-2.6.23-rc1-common-2.
+
+2007-07-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.23-rc1-common-1.
+
+2007-07-26 Keith Owens  <kaos@sgi.com>
+
+       * New x86 backtrace code.
+       * kdb v4.4-2.6.22-common-4.
+
+2007-07-17 Keith Owens  <kaos@sgi.com>
+
+       * Make kdb_printf_lock an irq lock to keep lockdep happy.
+       * kdb v4.4-2.6.22-common-3.
+
+2007-07-13 Keith Owens  <kaos@sgi.com>
+
+       * Increase the size of the debug_alloc pool.
+       * Add the caller that obtained each entry in the debug_alloc pool.
+       * Poison entries in the debug_alloc pool.
+       * Track current and maximum usage in debug_alloc pool.
+       * Print the debug_alloc entries that are still in use when kdb exits
+         (memory leaks).
+       * Increase the default value of BTARGS to 9.
+       * kdb v4.4-2.6.22-common-2.
+
+2007-07-09 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-common-1.
+
+2007-07-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc7-common-1.
+
+2007-06-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc5-common-1.
+
+2007-06-15 Keith Owens  <kaos@sgi.com>
+
+       * Do not include asm/kdb.h unless CONFIG_KDB is on.  Dave Jiang.
+       * kdb v4.4-2.6.22-rc4-common-2.
+
+2007-06-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc4-common-1.
+
+2007-05-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc3-common-1.
+
+2007-05-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc2-common-1.
+
+2007-05-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.22-rc1-common-1.
+
+2007-05-17 Keith Owens  <kaos@sgi.com>
+
+       * Add rdmsr and wrmsr commands for i386 and x86_64.  Original patch by
+         Bernardo Innocenti for i386, reworked by Keith Owens to make it safe
+         on all cpu models and to handle both i386 and x86_64.
+       * kdb v4.4-2.6.21-common-3.
+
+2007-05-15 Keith Owens  <kaos@sgi.com>
+
+       * Correct alignment of debug_alloc_header.
+       * kdb v4.4-2.6.21-common-2.
+
+2007-04-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-common-1.
+
+2007-04-16 Keith Owens  <kaos@sgi.com>
+
+       * Remove dead symbol declarations.
+       * kdb v4.4-2.6.21-rc7-common-2.
+
+2007-04-16 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc7-common-1.
+
+2007-04-10 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc6-common-1.
+
+2007-04-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc5-common-1.
+
+2007-03-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc4-common-1.
+
+2007-03-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc3-common-1.
+
+2007-03-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc2-common-1.
+
+2007-03-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.21-rc1-common-1.
+
+2007-03-01 Keith Owens  <kaos@sgi.com>
+
+       * Remove sparse warnings.
+       * kdb v4.4-2.6.20-common-6.
+
+2007-02-27 Keith Owens  <kaos@sgi.com>
+
+       * set_irq_regs() on entry to kdb() if they are not already set.
+       * kdb v4.4-2.6.20-common-5.
+
+2007-02-22 Keith Owens  <kaos@sgi.com>
+
+       * Initialise struct disassemble_info in kdb_id1().
+       * kdb v4.4-2.6.20-common-4.
+
+2007-02-16 Keith Owens  <kaos@sgi.com>
+
+       * Clean up debug_alloc_pool code.
+       * kdb v4.4-2.6.20-common-3.
+
+2007-02-16 Keith Owens  <kaos@sgi.com>
+
+       * Initialise variable bits of struct disassemble_info each time.
+       * kdb v4.4-2.6.20-common-2.
+
+2007-02-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-common-1.
+
+2007-02-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc7-common-1.
+
+2007-01-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc4-common-1.
+
+2007-01-02 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc3-common-1.
+
+2006-12-21 Keith Owens  <kaos@sgi.com>
+
+       * Initialize the debug_kmalloc pool on the first call, so it can be
+         used at any time.
+       * kdb v4.4-2.6.20-rc1-common-2.
+
+2006-12-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.20-rc1-common-1.
+
+2006-11-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-common-1.
+
+2006-11-30 Keith Owens  <kaos@sgi.com>
+
+       * Do not access registers if kdb_current_regs is NULL.
+       * kdb v4.4-2.6.19-rc6-common-3.
+
+2006-11-27 Keith Owens  <kaos@sgi.com>
+
+       * Only use VT keyboard if the command line allows it and ACPI indicates
+         that there is an i8042.
+       * Optimize kdb_read() to reduce the risk of dropping input characters.
+       * Print cpumasks as lists instead of hex, also cope with long lists.
+       * kdb v4.4-2.6.19-rc6-common-2.
+
+2006-11-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc6-common-1.
+
+2006-11-09 Keith Owens  <kaos@sgi.com>
+
+       * Change kdb() to fastcall.
+       * Correct loop in kdb_help().  Georg Nikodym.
+       * Only use VT console if the command line allows it.
+       * kdb v4.4-2.6.19-rc5-common-2.
+
+2006-11-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc5-common-1.
+
+2006-11-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc4-common-1.
+
+2006-10-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc3-common-1.
+
+2006-10-24 Keith Owens  <kaos@sgi.com>
+
+       * Remove redundant regs and envp parameters.
+       * kdb v4.4-2.6.19-rc2-common-2.
+
+2006-10-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc2-common-1.
+
+2006-10-11 Keith Owens  <kaos@sgi.com>
+
+       * Move kdbm_x86.c from the i386 to the common KDB patch.
+       * Expand kdbm_x86.c to work on x86_64 as well as i386.
+       * kdb v4.4-2.6.19-rc1-common-2.
+
+2006-10-09 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.19-rc1-common-1.
+
+2006-10-06 Keith Owens  <kaos@sgi.com>
+
+       * Remove #include <linux/config.h>
+       * kdb v4.4-2.6.18-common-2.
+
+2006-09-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-common-1.
+
+2006-09-15 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc7-common-1.
+
+2006-08-29 Keith Owens  <kaos@sgi.com>
+
+       * Rewrite all backtrace code.
+       * kdb v4.4-2.6.18-rc5-common-2.
+
+2006-08-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc5-common-1.
+
+2006-08-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc4-common-1.
+
+2006-08-04 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc3-common-1.
+
+2006-07-18 Keith Owens  <kaos@sgi.com>
+
+       * 8250.c locking has been fixed so there is no need to break spinlocks
+         for keyboard entry.
+       * kdb v4.4-2.6.18-rc2-common-2.
+
+2006-07-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc2-common-1.
+
+2006-07-12 Keith Owens  <kaos@sgi.com>
+
+       * Remove dead KDB_REASON codes.
+       * The main kdb() function is now always entered with interrupts
+         disabled, so there is no need to disable bottom halves.
+       * sparse cleanups.
+       * kdb v4.4-2.6.18-rc1-common-2.
+
+2006-07-07 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.18-rc1-common-1.
+
+2006-07-04 Keith Owens  <kaos@sgi.com>
+
+       * Add KDB_REASON_CPU_UP and callbacks for cpus coming online.
+       * Relegate KDB_REASON_SILENT to KDB internal use only.
+       * Backout the v4.4-2.6.15-common-3 change that made KDB_REASON_SILENT
+         wait for cpus, the Dell Xeon problem has been fixed.
+       * notify_die() is not called for KDB_REASON_SILENT nor
+         KDB_REASON_CPU_UP, these events do not stay in KDB.
+       * Export kdb_current_task for kdbm_x86.  SuSE patch
+         kdb-missing-export.diff
+       * Scale kdb_wait_for_cpus_secs by the number of online cpus.
+       * Delete kdb_enablehwfault, architectures now do their own setup.
+       * Delete kdba_enable_mce, architectures now do their own setup.
+       * Delete kdba_enable_lbr, kdba_disable_lbr, kdba_print_lbr,
+         page_fault_mca.  Only ever implemented on x86, difficult to maintain
+         and rarely used in the field.
+       * Replace #ifdef KDB_HAVE_LONGJMP with #ifdef kdba_setjmp.
+       * kdb v4.4-2.6.17-common-2.
+
+2006-06-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-common-1.
+
+2006-05-31 Keith Owens  <kaos@sgi.com>
+
+       * Break spinlocks for keyboard entry.  Hopefully a temporary hack while
+         I track down why keyboard entry to KDB is hanging.
+       * kdb v4.4-2.6.17-rc5-common-2.
+
+2006-05-25 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc5-common-1.
+
+2006-05-15 Keith Owens  <kaos@sgi.com>
+
+       * Refresh bfd related files from binutils 2.16.91.0.2.
+       * kdb v4.4-2.6.17-rc4-common-2.
+
+2006-05-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc4-common-1.
+
+2006-04-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc3-common-1.
+
+2006-04-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc2-common-1.
+
+2006-04-11 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.17-rc1-common-1.
+
+2006-04-05 Keith Owens  <kaos@sgi.com>
+
+       * More fixes for the timing race with KDB_ENTER_SLAVE.
+       * kdb v4.4-2.6.16-common-5.
+
+2006-03-30 Keith Owens  <kaos@sgi.com>
+
+       * Some code was testing KDB_IS_RUNNING() twice, which left it open to
+         races.  Cache the result instead.
+       * kdb v4.4-2.6.16-common-4.
+
+2006-03-30 Keith Owens  <kaos@sgi.com>
+
+       * Change CONFIG_LKCD to CONFIG_LKCD_DUMP.
+       * kdb v4.4-2.6.16-common-3.
+
+2006-03-22 Keith Owens  <kaos@sgi.com>
+
+       * Add some more xpc flags.  Dean Nelson, SGI.
+       * Replace open coded counter references with atomic_read().
+       * Pass early_uart_console to early_uart_setup().  Francois
+         Wellenreiter, Bull.
+       * Replace open code with for_each_online_cpu().
+       * If cpus do not come into kdb after a few seconds then let
+         architectures send a more forceful interrupt.
+       * Close a timing race with KDB_ENTER_SLAVE.
+       * kdb v4.4-2.6.16-common-2.
+
+2006-03-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.16-common-1.
+
+2006-03-14 Nathan Scott  <nathans@sgi.com>
+
+       * kdb v4.4-2.6.16-rc6-common-1.
+
+2006-02-28 Nathan Scott  <nathans@sgi.com>
+
+       * kdb v4.4-2.6.16-rc5-common-1.
+
+2006-02-20 Nathan Scott  <nathans@sgi.com>
+
+       * kdb v4.4-2.6.16-rc4-common-1.
+
+2006-02-06 Keith Owens  <kaos@sgi.com>
+
+       * Change CONFIG_CRASH_DUMP to CONFIG_LKCD.
+       * Remove obsolete kdb_notifier_list.
+       * kdb v4.4-2.6.16-rc2-common-2.
+
+2006-02-06 Keith Owens  <kaos@sgi.com>
+
+       * Add xpcusers command.  Dean Nelson, SGI.
+       * kdb v4.4-2.6.16-rc2-common-1.
+
+2006-02-02 Keith Owens  <kaos@sgi.com>
+
+       * Check if we have a console before using it for KDB.
+       * kdb v4.4-2.6.16-rc1-common-3.
+
+2006-02-01 Keith Owens  <kaos@sgi.com>
+
+       * Add option 'R' to the pid command to reset to the original task.
+       * Include 'pid R' in archkdb* commands to reset up the original failing
+         task.  Users may have switched to other cpus and/or tasks before
+         issuing archkdb.
+       * Compile fix for kdbm_pg.c on i386.
+       * kdb v4.4-2.6.16-rc1-common-2.
+
+2006-01-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.16-rc1-common-1.
+
+2006-01-11 Keith Owens  <kaos@sgi.com>
+
+       * Plug a timing race between KDB_ENTER_SLAVE and KDB_ENTER, and allow
+         the cpu command to switch to a slave cpu.
+       * KDB_REASON_SILENT now waits for other cpus, to avoid spurious NMI
+         events that were seen on some Xeon systems.
+       * kdb v4.4-2.6.15-common-3.
+
+2006-01-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb mainline invokes DIE_KDEBUG_ENTER and DIE_KDEBUG_LEAVE via
+         notify_die.
+       * Move xpc debug support from xpc to mainline kdb.
+       * kdbm_cm.c: check if file_lock_operations or lock_manager_operations
+         are set before dereferencing them.  Felix Blyakher, SGI.
+       * kdb v4.4-2.6.15-common-2.
+
+2006-01-04 Keith Owens  <kaos@sgi.com>
+
+       * Print all buffers on a page in inode pages and update formatting to be
+         legible, too.  David Chinner, SGI.
+       * Update page flags in kdbm_pg.
+       * Remove inline from *.c files.
+       * kdb v4.4-2.6.15-common-1.
+
+2005-12-25 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc7-common-1.
+
+2005-12-20 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc6-common-1.
+
+2005-12-10 Keith Owens  <kaos@sgi.com>
+
+       * Update mapping of flags to strings in kdbm_pg.c and kdbm_vm.c.
+       * kdb v4.4-2.6.15-rc5-common-3.
+
+2005-12-06 Keith Owens  <kaos@sgi.com>
+
+       * Add RECOVERY flag to global KDB flags.
+       * Add kdb_{save,restore}_flags.
+       * kdb v4.4-2.6.15-rc5-common-2.
+
+2005-12-05 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc5-common-1.
+
+2005-12-02 Keith Owens  <kaos@sgi.com>
+
+       * kdbm_vm.c: offsets of page macros should be unsigned long.  Reported
+         by Dean Nelson, SGI.
+       * kdb v4.4-2.6.15-rc4-common-1.
+
+2005-11-30 Keith Owens  <kaos@sgi.com>
+
+       * New follow_page() API.
+       * kdb v4.4-2.6.15-rc3-common-1.
+
+2005-11-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc2-common-1.
+
+2005-11-15 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.15-rc1-common-1.
+
+2005-11-15 Keith Owens  <kaos@sgi.com>
+
+       * Allow kdb_printf() to be used outside kdb, in preemptible context.
+       * Build with CONFIG_SWAP=n.  Reported by Leo Yuriev.
+       * kdb v4.4-2.6.14-common-2.
+
+2005-10-28 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.14-common-1.
+
+2005-10-21 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.14-rc5-common-1.
+
+2005-10-11 Keith Owens  <kaos@sgi.com>
+
+       * Handle removal of USB keyboard.  Aaron Young, SGI.
+       * kdb v4.4-2.6.14-rc4-common-1.
+
+2005-10-05 Keith Owens  <kaos@sgi.com>
+
+       * Extend kdb_notifier_list() codes to include dumping.
+       * Use emergency_restart() for reboot, it can be called from interrupt
+         context, unlike machine_restart().
+       * kdb v4.4-2.6.14-rc3-common-1.
+
+2005-09-21 Keith Owens  <kaos@sgi.com>
+
+       * Support kdb_current_task in register display and modify commands.
+       * Document what changes kdb's notion of the current task.
+       * Update rd documentation for IA64.
+       * Move some definictions to kdbprivate.h and remove some unused symbol
+         exports.
+       * kdb v4.4-2.6.14-rc2-common-1.
+
+2005-09-20 Keith Owens  <kaos@sgi.com>
+
+       * Document IA64 handlers command.
+       * Add more fields to the task command.
+       * Cope with MCA/INIT handlers in the ps command.
+       * Namespace cleanup, delete unused exports, make some functions static.
+       * Add a kdb_notifier_list callback when kdb is about to reboot the
+         system.
+       * kdb v4.4-2.6.14-rc1-common-1.
+
+2005-08-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-common-1.
+
+2005-08-24 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc7-common-1.
+
+2005-08-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc6-common-1.
+
+2005-08-02 Keith Owens  <kaos@sgi.com>
+
+       * Print more fields from filp, dentry.
+       * Add kdb=on-nokey to suppress kdb entry from the keyboard.
+       * kdb v4.4-2.6.13-rc5-common-1.
+
+2005-07-30 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc4-common-1.
+
+2005-07-26 Keith Owens  <kaos@sgi.com>
+
+       * Fix compile problem with CONFIG_USB_KBD.
+       * kdb v4.4-2.6.13-rc3-common-3.
+
+2005-07-22 Keith Owens  <kaos@sgi.com>
+
+       * The asmlinkage kdb() patch was lost during packaging.  Reinstate it.
+       * kdb v4.4-2.6.13-rc3-common-2.
+
+2005-07-19 Keith Owens  <kaos@sgi.com>
+
+       * Add support for USB keyboard (OHCI only).  Aaron Young, SGI.
+       * kdb v4.4-2.6.13-rc3-common-1.
+
+2005-07-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.13-rc2-common-1.
+
+2005-07-01 Keith Owens  <kaos@sgi.com>
+
+       * Make kdb() asmlinkage to avoid problems with CONFIG_REGPARM.
+       * Change some uses of smp_processor_id() to be preempt safe.
+       * Use DEFINE_SPINLOCK().
+       * kdb v4.4-2.6.13-rc1-common-1.
+
+2005-06-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-common-1.
+
+2005-06-08 Keith Owens  <kaos@sgi.com>
+
+       * Correct early exit from bd *.
+       * kdb v4.4-2.6.12-rc6-common-1.
+
+2005-05-25 Keith Owens  <kaos@sgi.com>
+
+       * Delete Documentation/kdb/dump.txt.  lkcd now has reasonable
+         integration with kdb.
+       * kdb v4.4-2.6.12-rc5-common-1.
+
+2005-05-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.12-rc4-common-1.
+
+2005-04-21 Keith Owens  <kaos@sgi.com>
+
+       * Add rpte command (find the pte for a physical page).
+       * kdb v4.4-2.6.12-rc3-common-1.
+
+2005-04-06 Keith Owens  <kaos@sgi.com>
+
+       * Add rq and rqa commands.  John Hawkes, SGI.
+       * kdb v4.4-2.6.12-rc2-common-1.
+
+2005-03-29 Keith Owens  <kaos@sgi.com>
+
+       * Use register_sysctl_table() instead of patching kernel/sysctl.c.
+       * Non-ASCII characters are not printable.
+       * kdb v4.4-2.6.12-rc1-common-1.
+
+2005-03-15 Keith Owens  <kaos@sgi.com>
+
+       * More coexistence patches for lkcd.  Jason Uhlenkott, SGI.
+       * kdb v4.4-2.6.11-common-3.
+
+2005-03-08 Keith Owens  <kaos@sgi.com>
+
+       * Coexistence patches for lkcd.  Jason Uhlenkott, SGI.
+       * kdb v4.4-2.6.11-common-2.
+
+2005-03-03 Keith Owens  <kaos@sgi.com>
+
+       * Add kdb to drivers/serial/8250_early.c.  Francois Wellenreiter, Bull.
+       * kdb v4.4-2.6.11-common-1.
+
+2005-02-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.11-rc4-common-1.
+
+2005-02-08 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.11-rc3-bk4-common-1.
+
+2005-02-03 Keith Owens  <kaos@sgi.com>
+
+       * Print more superblock fields.  Nathan Scott, SGI.
+       * Remove kallsyms correction for modules, Linus took it.
+       * kdb v4.4-2.6.11-rc3-common-1.
+
+2005-01-27 Keith Owens  <kaos@sgi.com>
+
+       * Add bio command.  Nathan Scott, SGI.
+       * kdb v4.4-2.6.11-rc2-common-1.
+
+2005-01-20 Keith Owens  <kaos@sgi.com>
+
+       * Include kallsyms correction for modules until Linus takes it.
+       * kdb v4.4-2.6.11-rc1-bk7-common-1.
+
+2005-01-12 Keith Owens  <kaos@sgi.com>
+
+       * kallsyms now supports all symbols properly, remove kdb patch.
+       * Add last ditch allocator for debugging.
+       * Update kdb_meminfo_read_proc() for vmalloc changes.
+       * Update kdbm_vm.c for 4 level page tables.
+       * kdb v4.4-2.6.11-rc1-common-1.
+
+2004-12-25 Keith Owens  <kaos@sgi.com>
+
+       * Add kobject command.
+       * Ignore low addresses and large offsets in kdbnearsym().
+       * Console updates for sn2 simulator.
+       * kdb v4.4-2.6.10-common-1.
+
+2004-12-07 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.10-rc3-common-1.
+
+2004-11-23 Keith Owens  <kaos@sgi.com>
+
+       * Remove warning message from kdb_get_one_user_page(), it was too noisy.
+       * kdb v4.4-2.6.10-rc2-common-1.
+
+2004-11-02 Keith Owens  <kaos@sgi.com>
+
+       * Build with kdb patch applied but CONFIG_KDB=n.
+       * kdb v4.4-2.6.10-rc1-common-2.
+
+2004-10-29 Keith Owens  <kaos@sgi.com>
+
+       * Handle new compression scheme for kallsyms.
+       * Handle move of DEAD and ZOMBIE for task->state to task->exit_state.
+       * Tweak the concept of a valid kernel address to get all symbols,
+         including the symbols in the ia64 gate page.
+       * kdb v4.4-2.6.10-rc1-common-1.
+
+2004-10-21 Keith Owens  <kaos@sgi.com>
+
+       * Handle variable size for the kernel log buffer.
+       * kdb v4.4-2.6.9-common-2.
+
+2004-10-19 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.9-common-1.
+
+2004-10-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.9-rc4-common-1.
+
+2004-10-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.9-rc3-common-1.
+
+2004-09-30 Keith Owens  <kaos@sgi.com>
+
+       * Add stackdepth command to Documentation/kdb/kdb.mm.  stackdepth is
+         only supported on i386 and ia64 at the moment.
+       * Skip kdbm_pg memmap build on x86_64.  Scott Lurndal, 3leafnetworks.
+       * Export kdb_serial_str for modular I/O.  Bryan Cardillo, UPenn.
+       * Reinstate tab completion for symbols.
+       * kdb v4.4-2.6.9-rc2-common-2.
+
+2004-09-14 Keith Owens  <kaos@sgi.com>
+
+       * Add task states C (traCed) and E (dEad).
+       * kdb v4.4-2.6.9-rc2-common-1.
+
+2004-08-27 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.9-rc1-common-1.
+
+2004-08-14 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.8-common-1.
+
+2004-08-12 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.8-rc4-common-1.
+
+2004-08-05 Keith Owens  <kaos@sgi.com>
+
+       * Mark kdb_initcall as __attribute_used__ for newer gcc.
+       * kdb v4.4-2.6.8-rc3-common-2.
+
+2004-08-04 Keith Owens  <kaos@sgi.com>
+
+       * Add mdp (memory display physical) comnmand.
+         Ananth N Mavinakayanahalli, IBM.
+       * kdb v4.4-2.6.8-rc3-common-1.
+
+2004-07-18 Keith Owens  <kaos@sgi.com>
+
+       * Patch for new sn_console.  Erik Jacobson. SGI.
+       * kdb v4.4-2.6.8-rc2-common-1.
+
+2004-07-12 Keith Owens  <kaos@sgi.com>
+
+       * Convert kdbm_task to standard cpumask_t.
+       * Document '*' (all breakpoints) option on bd/be/bc commands.
+       * kdb v4.4-2.6.8-rc1-common-1.
+
+2004-06-30 Keith Owens  <kaos@sgi.com>
+
+       * Common changes to help the x86-64 port.
+       * kdb v4.4-2.6.7-common-3.
+
+2004-06-20 Keith Owens  <kaos@sgi.com>
+
+       * Move kdb includes in mm/swapfile.c to reduce conflicts with other
+         SGI patches.
+       * kdb v4.4-2.6.7-common-2.
+
+2004-06-16 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.7-common-1.
+
+2004-06-09 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.7-rc3-common-1.
+
+2004-06-09 Keith Owens  <kaos@sgi.com>
+
+       * Namespace clean up.  Mark code/variables as static when it is only
+         used in one file, delete dead code/variables.
+       * Saved interrupt state requires long, not int.
+       * kdb v4.4-2.6.7-rc2-common-3.
+
+2004-06-08 Keith Owens  <kaos@sgi.com>
+
+       * Whitespace clean up, no code changes.
+       * kdb v4.4-2.6.7-rc2-common-2.
+
+2004-06-07 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.4-2.6.7-rc2-common-1.
+
+2004-06-06 Keith Owens  <kaos@sgi.com>
+
+       * Avoid recursion problems in kdb_init().
+       * Add standard archkdb commands.
+       * Add per_cpu command.
+       * Move kdb_{get,put}userarea_size definitions to linux/kdb.h.
+       * kdb v4.4-2.6.6-common-2.
+
+2004-05-23 Keith Owens  <kaos@sgi.com>
+
+       * Shrink the output from the cpu command.
+       * Add cpu state 'I', the cpu is idle.
+       * Add cpu state '+', some kdb data is available but the cpu is not
+         responding.
+       * Do not print tasks in state I or M by default in ps and bta commands.
+       * Add states I (idle task) and M (sleeping system daemon) to ps and
+         bta commands.
+       * Delete unused variables.
+       * Move private kdb fields from kdb.h to kdbprivate.h.
+       * Print 'for keyboard entry' for the special cases when KDB_ENTER() is
+         used to get registers.
+       * Move bfd.h and ansidecl.h from arch/$(ARCH)/kdb to include/asm-$(ARCH)
+         and remove -I arch/$(ARCH)/kdb.
+       * dmesg command now prints from either the start or end of dmesg, or at
+         an arbitrary point in the middle of the kernel log buffer.
+       * Sensible string dump for multi byte md commands.
+       * 'page' command handles ia64 correctly.
+       * Show some activity when waiting for cpus to enter kdb.
+       * Change the KDB entry code to <esc>KDB.
+       * Allow comment commands, starting with '#'.
+       * Commands defined using defcmd from kdb_cmds are not printed as they
+         are entered, use defcmd with no parameters to print all the defined
+         commands.
+       * Add summary command.
+       * Update copyright notices.
+       * Zero suppression on md command.
+       * Make set NOSECT=1 the default.
+       * PPC64 uses OF-stdout instead of console.  Ananth N Mavinakayanahalli.
+       * kdb v4.4-2.6.6-common-1.
+
+2004-05-10 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.6-common-1.
+
+2004-05-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.6-rc3-common-1.
+
+2004-05-06 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.6-rc2-common-1.
+
+2004-04-30 Keith Owens  <kaos@sgi.com>
+
+       * Rewrite inode_pages command for new radix code in struct page.
+       * kdb v4.3-2.6.6-rc1-common-1.
+
+2004-04-11 Keith Owens  <kaos@sgi.com>
+
+       * Unlock sn_sal_lock before entering kdb from sn_serial.
+       * kdb v4.3-2.6.5-common-2.
+
+2004-04-05 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.5-common-1.
+
+2004-03-22 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.5-rc2-common-1.
+
+2004-03-12 Keith Owens  <kaos@sgi.com>
+
+       * More work to avoid spurious messages from WARN_CONSOLE_UNLOCKED().
+       * bh command bug fixes.  Nathan Scott.
+       * kdb v4.3-2.6.4-common-1.
+
+2004-03-06 Keith Owens  <kaos@sgi.com>
+
+       * Set KDB_IS_RUNNING() during kdb_init to avoid spurious messages from
+         WARN_CONSOLE_UNLOCKED().
+       * Correct loss of symbol names in kdbnearsym.
+       * kdb v4.3-2.6.4-rc2-common-1.
+
+2004-02-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.4-rc1-common-1.
+
+2004-02-21 Keith Owens  <kaos@sgi.com>
+
+       * Correct build of kdb_cmds when using a separate object directory and
+         make it quiet.  j-nomura (NEC), Keith Owens.
+       * kdb v4.3-2.6.3-common-2.
+
+2004-02-18 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.6.3-common-1.
+
+2004-02-17 Keith Owens  <kaos@sgi.com>
+
+       * Remove WAR for incorrect console registration patch.
+       * kdb v4.3-2.6.3-rc4-common-1.
+
+2004-02-17 Keith Owens  <kaos@sgi.com>
+
+       * Convert longjmp buffers from static to dynamic allocation, for large
+         cpu counts.
+       * Tweak kdbm_task for SMP/UP.
+       * Reconcile with kdb-v4.3 2.4.25-rc1-common-1.
+       * Simplify coexistence with NPTL patches.
+       * Support kill command on new scheduler.
+       * Do not refetch data when printing a value as characters.
+       * Document the pid command.
+       * Work around 2.6 kallsyms 'feature'.
+       * Upgrade to 2.6.3-rc3.
+       * WAR for incorrect console registration patch.
+       * kdb v4.3-2.6.3-rc3-common-1.
+
+2003-12-03 Keith Owens  <kaos@sgi.com>
+
+       * Reconcile 2.6-test versions from Xavier Bru (Bull), Greg Banks (SGI),
+         Jim Houston (Concurrent Computer Corp).
+       * Reconcile with kdb v4.3-2.4.23-common-2.
+       * Clean up CONFIG_KDB changes to {scripts,kernel}/kallsyms.c.
+       * Correct handling of kdb command line arguments.
+       * Make hooks into module code less intrusive.
+       * Delete kdb_active_task, not required with O(1) scheduler.
+       * Port kdbm_task.c from 2.4.
+       * Disable debug check in exit.c::next_thread() when kdb is running.
+       * Remove "only bh_disable when interrupts are set".  BH must be disabled
+         in kdb to prevent deadlock on breakpoints in interrupt handlers.
+       * Add kdb to drivers/char/sn_serial.c.
+       * kdb v4.3-2.6.0-test11-common-1.
+
+2003-11-11 Xavier Bru   <xavier.bru@bull.net>
+       * Merge to 2.6.0-test9
+2003-10-17 Xavier Bru   <xavier.bru@bull.net>
+       * fix NUll ptr in kdb_ps at early prompt.
+2003-10-14 Xavier Bru   <xavier.bru@bull.net>
+       * fix NUll ptr in kdb_ps when cpu not present.
+2003-10-06 Xavier Bru   <xavier.bru@bull.net>
+       * Merge to 2.6.0-test5
+       * fix compile error with CONFIG_MODULES not set.
+
+2003-09-08 Xavier Bru   <xavier.bru@bull.net>
+       * Merge to 2.6.0-test4
+
+2003-07-10 Xavier Bru   <xavier.bru@bull.net>
+
+       * Merge kdb v4.3 to 2.5.72 ia64
+       * don't call local_bh_enable() with interrupts masked.
+
+2003-04-07 Xavier Bru   <xavier.bru@bull.net>
+
+       * Merge kdb v4.1 to 2.5.64 ia64
+       * new kernel parameters support
+       * new module format
+       * new kallsyms support
+
+2003-12-02 Keith Owens  <kaos@sgi.com>
+
+       * Use correct page alignment in kdb_get_one_user_page().
+         Prasanna S Panchamukhi, IBM.
+       * Split pte command into pte -m and pte -p.  Dean Roe, SGI.
+       * kdb v4.3-2.4.23-common-2.
+
+2003-12-01 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.4.23-common-1.
+
+2003-11-11 Keith Owens  <kaos@sgi.com>
+
+       * Make KDB for USB keyboards build.  Peter T. Breuer.
+       * Do not use USB keyboard if it has not been probed.
+       * kdb v4.3-2.4.23-rc1-common-1.
+
+2003-10-10 Keith Owens  <kaos@sgi.com>
+
+       * Sync with XFS 2.4.22 tree.
+       * kdb v4.3-2.4.22-common-2.
+
+2003-08-29 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.4.22-common-1.
+
+2003-07-27 Keith Owens  <kaos@sgi.com>
+
+       * kdb v4.3-2.4.22-pre8-common-8.
+
+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 --git a/kdb/Makefile b/kdb/Makefile
new file mode 100644 (file)
index 0000000..03cd4fb
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+#
+
+CCVERSION      := $(shell $(CC) -v 2>&1 | sed -ne '$$p')
+obj-y          := kdb_bt.o kdb_bp.o kdb_id.o kdbsupport.o gen-kdb_cmds.o kdbmain.o kdb_io.o kdbdereference.o
+CFLAGS_kdbmain.o += -DCCVERSION="$(CCVERSION)"
+
+subdir-$(CONFIG_KDB_MODULES) := modules
+obj-y += $(addsuffix /built-in.o, $(subdir-y))
+
+clean-files := gen-kdb_cmds.c
+
+override CFLAGS := $(CFLAGS:%-pg=% )
+
+# define architecture dependent kdb_cmds
+ifeq ($(CONFIG_IA64),y)
+       KDB_CMDS = ia64/kdb/kdb_cmds
+else
+       ifeq ($(CONFIG_X86_64),y)
+               KDB_CMDS = x86/kdb/kdb_cmds_64
+       else
+               ifeq ($(CONFIG_X86_32),y)
+                       KDB_CMDS = x86/kdb/kdb_cmds_32
+               endif
+       endif
+endif
+
+quiet_cmd_gen-kdb = GENKDB  $@
+      cmd_gen-kdb = $(AWK) 'BEGIN {print "\#include <linux/stddef.h>"; print "\#include <linux/init.h>"} \
+               /^\#/{next} \
+               /^[ \t]*$$/{next} \
+               {gsub(/"/, "\\\"", $$0); \
+                 print "static __initdata char kdb_cmd" cmds++ "[] = \"" $$0 "\\n\";"} \
+               END {print "extern char *kdb_cmds[]; char __initdata *kdb_cmds[] = {"; for (i = 0; i < cmds; ++i) {print "  kdb_cmd" i ","}; print("  NULL\n};");}' \
+               $(filter-out %/Makefile,$^) > $@
+
+$(obj)/gen-kdb_cmds.c: $(src)/kdb_cmds $(wildcard $(TOPDIR)/arch/$(KDB_CMDS)) $(src)/Makefile
+       $(call cmd,gen-kdb)
diff --git a/kdb/kdb_bp.c b/kdb/kdb_bp.c
new file mode 100644 (file)
index 0000000..e438aa2
--- /dev/null
@@ -0,0 +1,658 @@
+/*
+ * Kernel Debugger Architecture Independent Breakpoint Handler
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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 <linux/interrupt.h>
+#include <asm/system.h>
+
+/*
+ * Table of kdb_breakpoints
+ */
+kdb_bp_t kdb_breakpoints[KDB_MAXBPT];
+
+/*
+ *     Predicate to test whether a breakpoint should be installed
+ *     on this CPU.
+ *
+ *     Note that for purposes of installation, hardware breakpoints
+ *     are treated as local (even if the global flag is set), on
+ *     the assumption that the require per-cpu registers to be set.
+ */
+
+static inline int kdb_is_installable_global_bp(const kdb_bp_t *bp)
+{
+       return (bp->bp_enabled &&
+               bp->bp_global &&
+               !bp->bp_forcehw);
+}
+
+static int kdb_is_installable_local_bp(const kdb_bp_t *bp)
+{
+       if (!bp->bp_enabled)
+               return 0;
+
+       if (bp->bp_forcehw) {
+               if (bp->bp_cpu == smp_processor_id() || bp->bp_global)
+                       return 1;
+       } else {
+               if (bp->bp_cpu == smp_processor_id() && !bp->bp_global)
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ * 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++) {
+               kdb_bp_t *bp = &kdb_breakpoints[i];
+
+               if (KDB_DEBUG(BP)) {
+                       kdb_printf("kdb_bp_install_global bp %d bp_enabled %d bp_global %d\n",
+                               i, bp->bp_enabled, bp->bp_global);
+               }
+               /* HW BP local or global are installed in kdb_bp_install_local*/
+               if (kdb_is_installable_global_bp(bp))
+                       kdba_installbp(regs, bp);
+       }
+}
+
+/*
+ * 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++) {
+               kdb_bp_t *bp = &kdb_breakpoints[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, bp->bp_enabled, bp->bp_global,
+                               smp_processor_id(), bp->bp_cpu);
+               }
+               if (kdb_is_installable_local_bp(bp))
+                       kdba_installbp(regs, bp);
+       }
+}
+
+/*
+ * 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--) {
+               kdb_bp_t *bp = &kdb_breakpoints[i];
+
+               if (KDB_DEBUG(BP)) {
+                       kdb_printf("kdb_bp_remove_global bp %d bp_enabled %d bp_global %d\n",
+                               i, bp->bp_enabled, bp->bp_global);
+               }
+               if (kdb_is_installable_global_bp(bp))
+                       kdba_removebp(bp);
+       }
+}
+
+
+/*
+ * 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--) {
+               kdb_bp_t *bp = &kdb_breakpoints[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, bp->bp_enabled, bp->bp_global,
+                               smp_processor_id(), bp->bp_cpu);
+               }
+               if (kdb_is_installable_local_bp(bp))
+                       kdba_removebp(bp);
+       }
+}
+
+/*
+ * 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("\taddr at %016lx, hardtype=%d, forcehw=%d, installed=%d, hard=%p\n",
+               bp->bp_addr, bp->bp_hardtype, bp->bp_forcehw,
+               bp->bp_installed, bp->bp_hard);
+
+       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
+ * 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
+ */
+
+static int
+kdb_bp(int argc, const char **argv)
+{
+       int i, bpno;
+       kdb_bp_t *bp, *bp_check;
+       int diag;
+       int free;
+       char *symname = NULL;
+       long offset = 0ul;
+       int nextarg;
+       kdb_bp_t template = {0};
+
+       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;
+       }
+
+       template.bp_global = ((strcmp(argv[0], "bpa") == 0)
+                          || (strcmp(argv[0], "bpha") == 0));
+       template.bp_forcehw = ((strcmp(argv[0], "bph") == 0)
+                          || (strcmp(argv[0], "bpha") == 0));
+
+       /* Fix me: "bp" is treated as "bpa" to avoid system freeze. -jlan */
+       if (strcmp(argv[0], "bp") == 0)
+               template.bp_global = 1;
+
+       nextarg = 1;
+       diag = kdbgetaddrarg(argc, argv, &nextarg, &template.bp_addr,
+                            &offset, &symname);
+       if (diag)
+               return diag;
+       if (!template.bp_addr)
+               return KDB_BADINT;
+
+       /*
+        * Find an empty bp structure, to allocate
+        */
+       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;
+
+       /*
+        * Handle architecture dependent parsing
+        */
+       diag = kdba_parsebp(argc, argv, &nextarg, &template);
+       if (diag) {
+               return diag;
+       }
+
+
+       /*
+        * Check for clashing breakpoints.
+        *
+        * Note, in this design we can't have hardware breakpoints
+        * enabled for both read and write on the same address, even
+        * though ia64 allows this.
+        */
+       for(i=0,bp_check=kdb_breakpoints; i<KDB_MAXBPT; i++,bp_check++) {
+               if (!bp_check->bp_free &&
+                   bp_check->bp_addr == template.bp_addr &&
+                   (bp_check->bp_global ||
+                    bp_check->bp_cpu == template.bp_cpu)) {
+                       kdb_printf("You already have a breakpoint at " kdb_bfd_vma_fmt0 "\n", template.bp_addr);
+                       return KDB_DUPBPT;
+               }
+       }
+
+       template.bp_enabled = 1;
+
+       /*
+        * Actually allocate the breakpoint found earlier
+        */
+       *bp = template;
+       bp->bp_free = 0;
+
+       if (!bp->bp_global) {
+               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) {
+               kdba_alloc_hwbp(bp, &diag);
+               if (diag) {
+                       bp->bp_enabled = 0;
+                       bp->bp_hardtype = 0;
+                       kdba_free_hwbp(bp);
+                       return diag;
+               }
+       }
+
+       kdb_printbp(bp, bpno);
+
+       return 0;
+}
+
+/*
+ * kdb_bc
+ *
+ *     Handles the 'bc', 'be', and 'bd' commands
+ *
+ *     [bd|bc|be] <breakpoint-number>
+ *     [bd|bc|be] *
+ *
+ * Parameters:
+ *     argc    Count of arguments in argv
+ *     argv    Space delimited command line arguments
+ * 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
+
+static int
+kdb_bc(int argc, const char **argv)
+{
+       kdb_machreg_t addr;
+       kdb_bp_t *bp = NULL;
+       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_free_hwbp(bp);
+
+                       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) {
+                               kdba_alloc_hwbp(bp, &diag);
+                               if (diag) {
+                                       bp->bp_enabled = 0;
+                                       bp->bp_hardtype = 0;
+                                       kdba_free_hwbp(bp);
+                                       return diag;
+                               }
+                       }
+
+                       bp->bp_enabled = 1;
+
+                       kdb_printf("Breakpoint %d at " kdb_bfd_vma_fmt " enabled",
+                               i, bp->bp_addr);
+
+                       kdb_printf("\n");
+                       break;
+               case KDBCMD_BD:
+                       if (!bp->bp_enabled)
+                               break;
+
+                       /*
+                        * Since this breakpoint is now disabled, we can
+                        * give up the hardware register which is allocated
+                        * to it.
+                        */
+                       if (bp->bp_hardtype)
+                               kdba_free_hwbp(bp);
+
+                       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
+ * 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.
+ */
+
+static int
+kdb_ss(int argc, const char **argv)
+{
+       int ssb = 0;
+       struct pt_regs *regs = get_irq_regs();
+
+       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 --git a/kdb/kdb_bt.c b/kdb/kdb_bt.c
new file mode 100644 (file)
index 0000000..0793ab8
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Kernel Debugger Architecture Independent Stack Traceback
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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 [DRSTCZEUIMA]               All useful processes, optionally filtered by state
+ *     btc [<cpu>]                     The current process on one cpu, default is all cpus
+ *
+ *     bt <address-expression> refers to a address on the stack, that location
+ *     is assumed to contain a return address.
+ *
+ *     btt <address-expression> refers to the address of a struct task.
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * 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 or
+ *     to get a starting point for bt <address-expression>.
+ */
+
+static int
+kdb_bt1(const 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)
+{
+       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 *g, *p;
+               unsigned long cpu;
+               unsigned long mask = kdb_task_state_string(argc ? argv[1] : NULL);
+               if (argc == 0)
+                       kdb_ps_suppressed();
+               /* Run the active tasks first */
+               for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+                       if (!cpu_online(cpu))
+                               continue;
+                       p = kdb_curr_task(cpu);
+                       if (kdb_bt1(p, mask, argcount, btaprompt))
+                               return 0;
+               }
+               /* Now the inactive tasks */
+               kdb_do_each_thread(g, p) {
+                       if (task_curr(p))
+                               continue;
+                       if (kdb_bt1(p, mask, argcount, btaprompt))
+                               return 0;
+               } kdb_while_each_thread(g, p);
+       } else if (strcmp(argv[0], "btp") == 0) {
+               struct task_struct *p;
+               unsigned long pid;
+               if (argc != 1)
+                       return KDB_ARGCOUNT;
+               if ((diag = kdbgetularg((char *)argv[1], &pid)))
+                       return diag;
+               if ((p = find_task_by_pid_type_ns(PIDTYPE_PID, pid, &init_pid_ns))) {
+                       kdba_set_current_task(p);
+                       return kdb_bt1(p, ~0UL, argcount, 0);
+               }
+               kdb_printf("No process with pid == %ld found\n", pid);
+               return 0;
+       } else if (strcmp(argv[0], "btt") == 0) {
+               if (argc != 1)
+                       return KDB_ARGCOUNT;
+               if ((diag = kdbgetularg((char *)argv[1], &addr)))
+                       return diag;
+               kdba_set_current_task((struct task_struct *)addr);
+               return kdb_bt1((struct task_struct *)addr, ~0UL, argcount, 0);
+       } else if (strcmp(argv[0], "btc") == 0) {
+               unsigned long cpu = ~0;
+               struct kdb_running_process *krp;
+               const struct task_struct *save_current_task = kdb_current_task;
+               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 >= NR_CPUS || !krp->seqno || !cpu_online(cpu)) {
+                               kdb_printf("no process for cpu %ld\n", cpu);
+                               return 0;
+                       }
+                       sprintf(buf, "btt 0x%p\n", krp->p);
+                       kdb_parse(buf);
+                       return 0;
+               }
+               kdb_printf("btc: cpu status: ");
+               kdb_parse("cpu\n");
+               for (cpu = 0, krp = kdb_running_process; cpu < NR_CPUS; ++cpu, ++krp) {
+                       if (!cpu_online(cpu) || !krp->seqno)
+                               continue;
+                       sprintf(buf, "btt 0x%p\n", krp->p);
+                       kdb_parse(buf);
+                       touch_nmi_watchdog();
+               }
+               kdba_set_current_task(save_current_task);
+               return 0;
+       } else {
+               if (argc) {
+                       nextarg = 1;
+                       diag = kdbgetaddrarg(argc, argv, &nextarg, &addr,
+                                            &offset, NULL);
+                       if (diag)
+                               return diag;
+                       return kdba_bt_address(addr, argcount);
+               } else {
+                       return kdb_bt1(kdb_current_task, ~0UL, argcount, 0);
+               }
+       }
+
+       /* NOTREACHED */
+       return 0;
+}
diff --git a/kdb/kdb_cmds b/kdb/kdb_cmds
new file mode 100644 (file)
index 0000000..343955c
--- /dev/null
@@ -0,0 +1,32 @@
+# 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.
+
+# Standard debugging information for first level support, just type archkdb
+# or archkdbcpu or archkdbshort at the kdb prompt.
+
+defcmd archkdb "" "First line arch debugging"
+  set BTSYMARG 1
+  set BTARGS 9
+  pid R
+  -archkdbcommon
+  -bta
+endefcmd
+
+defcmd archkdbcpu "" "archkdb with only tasks on cpus"
+  set BTSYMARG 1
+  set BTARGS 9
+  pid R
+  -archkdbcommon
+  -btc
+endefcmd
+
+defcmd archkdbshort "" "archkdb with less detailed backtrace"
+  set BTSYMARG 0
+  set BTARGS 0
+  pid R
+  -archkdbcommon
+  -bta
+endefcmd
diff --git a/kdb/kdb_id.c b/kdb/kdb_id.c
new file mode 100644 (file)
index 0000000..fcf6400
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Kernel Debugger Architecture Independent Instruction Disassembly
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     Zero for success, a kdb diagnostic if failure.
+ * Locking:
+ *     None.
+ * Remarks:
+ */
+
+int
+kdb_id(int argc, const char **argv)
+{
+       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;
+
+       kdb_di.fprintf_func = kdb_dis_fprintf;
+       kdba_id_init(&kdb_di);
+
+       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);
+       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;
+
+       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;
+
+       kdb_di.fprintf_func = kdb_dis_fprintf;
+       kdba_id_init(&kdb_di);
+
+       /*
+        * Allow the user to specify that this instruction
+        * should be treated differently.
+        */
+
+       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;
+}
diff --git a/kdb/kdb_io.c b/kdb/kdb_io.c
new file mode 100644 (file)
index 0000000..027824a
--- /dev/null
@@ -0,0 +1,856 @@
+/*
+ * Kernel Debugger Architecture Independent Console I/O handler
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2006 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ctype.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>
+
+static struct console *kdbcons;
+
+#ifdef CONFIG_PPC64
+#include <asm/udbg.h>
+#endif
+
+#define CMD_BUFLEN 256
+char kdb_prompt_str[CMD_BUFLEN];
+
+extern int kdb_grepping_flag;
+extern char kdb_grep_string[];
+extern int kdb_grep_leading;
+extern int kdb_grep_trailing;
+
+/*
+ * 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);
+                               count = kallsyms_symbol_complete(p_tmp, sizeof(tmpbuffer) - (p_tmp - tmpbuffer));
+                               if (tab == 2) {
+                                       if (count > 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 (count > 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;
+                               } else {
+                                       *++lastchar = '\0';
+                                       *cp++ = key;
+                                       kdb_printf("%c", key);
+                               }
+                       }
+                       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.
+ *
+ *  If the user is doing a cmd args | grep srch
+ *  then kdb_grepping_flag is set.
+ *  In that case we need to accumulate full lines (ending in \n) before
+ *  searching for the pattern.
+ */
+
+static char kdb_buffer[256];   /* A bit too big to go on stack */
+static char *next_avail=kdb_buffer;
+static int  size_avail;
+static int  suspend_grep=0;
+
+/*
+ * search arg1 to see if it contains arg2
+ * (kdmain.c provides flags for ^pat and pat$)
+ *
+ * return 1 for found, 0 for not found
+ */
+int
+kdb_search_string(char *searched, char *searchfor)
+{
+       char firstchar, *cp;
+       int len1, len2;
+
+       /* not counting the newline at the end of "searched" */
+       len1 = strlen(searched)-1;
+       len2 = strlen(searchfor);
+       if (len1 < len2) return 0;
+       if (kdb_grep_leading && kdb_grep_trailing && len1 != len2) return 0;
+
+       if (kdb_grep_leading) {
+               if (!strncmp(searched, searchfor, len2)) {
+                       return 1;
+               }
+       } else if (kdb_grep_trailing) {
+               if (!strncmp(searched+len1-len2, searchfor, len2)) {
+                       return 1;
+               }
+       } else {
+               firstchar = *searchfor;
+               cp = searched;
+               while ((cp = strchr(cp,firstchar))) {
+                       if (!strncmp(cp, searchfor, len2)) {
+                               return 1;
+                       }
+                       cp++;
+               }
+       }
+       return 0;
+}
+
+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;
+       int fnd, len;
+       char *cp, *cp2, *cphold = NULL, replaced_byte = ' ';
+       char *moreprompt = "more> ";
+       struct console *c = console_drivers;
+       static DEFINE_SPINLOCK(kdb_printf_lock);
+       unsigned long uninitialized_var(flags);
+
+       preempt_disable();
+       /* 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_irqsave(&kdb_printf_lock, flags);
+               got_printf_lock = 1;
+               atomic_inc(&kdb_event);
+       } else {
+               __acquire(kdb_printf_lock);
+       }
+
+       diag = kdbgetintenv("LINES", &linecount);
+       if (diag || linecount <= 1)
+               linecount = 22;
+
+       diag = kdbgetintenv("LOGGING", &logging);
+       if (diag)
+               logging = 0;
+
+       if (!kdb_grepping_flag || suspend_grep) {
+               /* normally, every vsnprintf starts a new buffer */
+               next_avail = kdb_buffer;
+               size_avail = sizeof(kdb_buffer);
+       }
+       va_start(ap, fmt);
+       vsnprintf(next_avail, size_avail, fmt, ap);
+       va_end(ap);
+
+       /*
+        * If kdb_parse() found that the command was cmd xxx | grep yyy
+        * then kdb_grepping_flag is set, and kdb_grep_string contains yyy
+        *
+        * Accumulate the print data up to a newline before searching it.
+        * (vsnprintf does null-terminate the string that it generates)
+        */
+
+       /* skip the search if prints are temporarily unconditional */
+       if (! suspend_grep) {
+
+               if (kdb_grepping_flag) {
+                       cp = strchr(kdb_buffer, '\n');
+                       if (!cp) {
+                               /*
+                                * Special cases that don't end with newlines
+                                * but should be written without one:
+                                *   The "[nn]kdb> " prompt should
+                                *   appear at the front of the buffer.
+                                *
+                                *   The "[nn]more " prompt should also be
+                                *     (MOREPROMPT -> moreprompt)
+                                *   written *   but we print that ourselves,
+                                *   we set the suspend_grep flag to make
+                                *   it unconditional.
+                                *
+                                */
+                               if (next_avail == kdb_buffer) {
+                                       /*
+                                        * these should occur after a newline,
+                                        * so they will be at the front of
+                                        * the buffer
+                                        */
+                                       cp2 = kdb_buffer;
+                                       len = strlen(kdb_prompt_str);
+                                       if (!strncmp(cp2,kdb_prompt_str, len)) {
+                                               /*
+                                                * We're about to start a new
+                                                * command, so we can go back
+                                                * to normal mode.
+                                                */
+                                               kdb_grepping_flag = 0;
+                                               goto kdb_printit;
+                                       }
+                               }
+                               /* no newline; don't search/write the buffer
+                                  until one is there */
+                               len = strlen(kdb_buffer);
+                               next_avail = kdb_buffer + len;
+                               size_avail = sizeof(kdb_buffer) - len;
+                               goto kdb_print_out;
+                       }
+
+                       /*
+                        * The newline is present; print through it or discard
+                        * it, depending on the results of the search.
+                        */
+                       cp++;                /* to byte after the newline */
+                       replaced_byte = *cp; /* remember what/where it was */
+                       cphold = cp;
+                       *cp = '\0';          /* end the string for our search */
+
+                       /*
+                        * We now have a newline at the end of the string
+                        * Only continue with this output if it contains the
+                        * search string.
+                        */
+                       fnd = kdb_search_string(kdb_buffer, kdb_grep_string);
+                       if (!fnd) {
+                               /*
+                                * At this point the complete line at the start
+                                * of kdb_buffer can be discarded, as it does
+                                * not contain what the user is looking for.
+                                * Shift the buffer left.
+                                */
+                               *cphold = replaced_byte;
+                               strcpy(kdb_buffer, cphold);
+                               len = strlen(kdb_buffer);
+                               next_avail = kdb_buffer + len;
+                               size_avail = sizeof(kdb_buffer) - len;
+                               goto kdb_print_out;
+                       }
+                       /*
+                        * at this point the string is a full line and
+                        * should be printed, up to the null.
+                        */
+               }
+       }
+kdb_printit:
+
+       /*
+        * Write to all consoles.
+        */
+#ifdef CONFIG_SPARC64
+       if (c == NULL)
+               prom_printf("%s", kdb_buffer);
+       else
+#endif
+
+#ifdef CONFIG_PPC64
+       if (udbg_write)
+               udbg_write(kdb_buffer, strlen(kdb_buffer));
+       else
+#endif
+
+       while (c) {
+               c->write(c, kdb_buffer, strlen(kdb_buffer));
+               touch_nmi_watchdog();
+               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++;
+
+       /* check for having reached the LINES number of printed lines */
+       if (kdb_nextline == linecount) {
+               char buf1[16]="";
+#if defined(CONFIG_SMP)
+               char buf2[32];
+#endif
+
+               /* 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, get_cpu());
+                       put_cpu();
+                       moreprompt = buf2;
+               }
+#endif
+
+               kdb_input_flush();
+               c = console_drivers;
+#ifdef CONFIG_SPARC64
+               if (c == NULL)
+                       prom_printf("%s", moreprompt);
+               else
+#endif
+
+#ifdef CONFIG_PPC64
+               if (udbg_write)
+                       udbg_write(moreprompt, strlen(moreprompt));
+               else
+#endif
+
+               while (c) {
+                       c->write(c, moreprompt, strlen(moreprompt));
+                       touch_nmi_watchdog();
+                       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 */
+
+               /* empty and reset the buffer: */
+               kdb_buffer[0] = '\0';
+               next_avail = kdb_buffer;
+               size_avail = sizeof(kdb_buffer);
+               if ((buf1[0] == 'q') || (buf1[0] == 'Q')) {
+                       /* user hit q or Q */
+                       do_longjmp = 1;
+                       KDB_FLAG_SET(CMD_INTERRUPT);    /* command was interrupted */
+                       /* end of command output; back to normal mode */
+                       kdb_grepping_flag = 0;
+                       kdb_printf("\n");
+               } else if (buf1[0] && buf1[0] != '\n') {
+                       /* user hit something other than enter */
+                       suspend_grep = 1; /* for this recursion */
+                       kdb_printf("\nOnly 'q' or 'Q' are processed at more prompt, input ignored\n");
+               } else if (kdb_grepping_flag) {
+                       /* user hit enter */
+                       suspend_grep = 1; /* for this recursion */
+                       kdb_printf("\n");
+               }
+               kdb_input_flush();
+       }
+
+       /*
+        * For grep searches, shift the printed string left.
+        *  replaced_byte contains the character that was overwritten with
+        *  the terminating null, and cphold points to the null.
+        * Then adjust the notion of available space in the buffer.
+        */
+       if (kdb_grepping_flag && !suspend_grep) {
+               *cphold = replaced_byte;
+               strcpy(kdb_buffer, cphold);
+               len = strlen(kdb_buffer);
+               next_avail = kdb_buffer + len;
+               size_avail = sizeof(kdb_buffer) - len;
+       }
+
+kdb_print_out:
+       suspend_grep = 0; /* end of what may have been a recursive call */
+       if (logging) {
+               console_loglevel = saved_loglevel;
+       }
+       if (KDB_STATE(PRINTF_LOCK) && got_printf_lock) {
+               got_printf_lock = 0;
+               spin_unlock_irqrestore(&kdb_printf_lock, flags);
+               KDB_STATE_CLEAR(PRINTF_LOCK);
+               atomic_dec(&kdb_event);
+       } else {
+               __release(kdb_printf_lock);
+       }
+       preempt_enable();
+       if (do_longjmp)
+#ifdef kdba_setjmp
+               kdba_longjmp(&kdbjmpbuf[smp_processor_id()], 1)
+#endif /* kdba_setjmp */
+               ;
+}
+
+/*
+ * kdb_io_init
+ *
+ *     Initialize kernel debugger output environment.
+ *
+ * Parameters:
+ *     None.
+ * Returns:
+ *     None.
+ * Locking:
+ *     None.
+ * Remarks:
+ *     Select a console device.  Only use a VT console if the user specified
+ *     or defaulted console= /^tty[0-9]*$/
+ */
+
+void __init
+kdb_io_init(void)
+{
+       /*
+        * Select a console.
+        */
+       struct console *c = console_drivers;
+       int vt_console = 0;
+
+       while (c) {
+               if ((c->flags & CON_CONSDEV) && !kdbcons)
+                       kdbcons = c;
+               if ((c->flags & CON_ENABLED) &&
+                   strncmp(c->name, "tty", 3) == 0) {
+                       char *p = c->name + 3;
+                       while (isdigit(*p))
+                               ++p;
+                       if (*p == '\0')
+                               vt_console = 1;
+               }
+               c = c->next;
+       }
+
+       if (kdbcons == NULL) {
+               printk(KERN_ERR "kdb: Initialization failed - no console.  kdb is disabled.\n");
+               KDB_FLAG_SET(NO_CONSOLE);
+               kdb_on = 0;
+       }
+       if (!vt_console)
+               KDB_FLAG_SET(NO_VT_CONSOLE);
+       kdb_input_flush();
+       return;
+}
+
+#ifdef CONFIG_KDB_USB
+
+int kdb_no_usb = 0;
+
+static int __init opt_kdbnousb(char *str)
+{
+       kdb_no_usb = 1;
+       return 0;
+}
+
+early_param("kdbnousb", opt_kdbnousb);
+
+#endif
+
+EXPORT_SYMBOL(kdb_read);
diff --git a/kdb/kdbdereference.c b/kdb/kdbdereference.c
new file mode 100644 (file)
index 0000000..8c6b8fe
--- /dev/null
@@ -0,0 +1,7257 @@
+/*
+ *
+ * Most of this code is borrowed and adapted from the lkcd command "lcrash"
+ * and its supporting libarary.
+ *
+ * This kdb commands for casting memory structures.
+ * It provides
+ *  "print" "px", "pd" *
+ *
+ * Careful of porting the klib KL_XXX functions (they call thru a jump table
+ * that we don't use here)
+ *
+ * The kernel type information is added be insmod'g the kdb debuginfo module
+ * It loads symbolic debugging info (provided from lcrash -o),
+ * (this information originally comes from the lcrash "kerntypes" file)
+ *
+ */
+
+#define VMALLOC_START_IA64 0xa000000200000000
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/fs.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/fcntl.h>
+#include <linux/vmalloc.h>
+#include <linux/ctype.h>
+#include <linux/file.h>
+#include <linux/err.h>
+#include "modules/lcrash/klib.h"
+#include "modules/lcrash/kl_stringtab.h"
+#include "modules/lcrash/kl_btnode.h"
+#include "modules/lcrash/lc_eval.h"
+
+#undef next_node /* collision with nodemask.h */
+int            have_debug_file = 0;
+dbg_sym_t *types_tree_head;
+dbg_sym_t *typedefs_tree_head;
+kltype_t       *kltype_array;
+dbg_sym_t      *dsym_types_array;
+
+
+EXPORT_SYMBOL(types_tree_head);
+EXPORT_SYMBOL(typedefs_tree_head);
+EXPORT_SYMBOL(kltype_array);
+EXPORT_SYMBOL(dsym_types_array);
+
+#define C_HEX          0x0002
+#define C_WHATIS       0x0004
+#define C_NOVARS       0x0008
+#define C_SIZEOF       0x0010
+#define C_SHOWOFFSET   0x0020
+#define        C_LISTHEAD      0x0040
+#define C_LISTHEAD_N    0x0080 /* walk using list_head.next */
+#define C_LISTHEAD_P    0x0100 /* walk using list_head.prev */
+#define C_BINARY       0x0200
+#define MAX_LONG_LONG  0xffffffffffffffffULL
+klib_t   kdb_klib;
+klib_t   *KLP = &kdb_klib;
+k_error_t klib_error = 0;
+dbg_sym_t *type_tree = (dbg_sym_t *)NULL;
+dbg_sym_t *typedef_tree = (dbg_sym_t *)NULL;
+dbg_sym_t *func_tree = (dbg_sym_t *)NULL;
+dbg_sym_t *srcfile_tree = (dbg_sym_t *)NULL;
+dbg_sym_t *var_tree = (dbg_sym_t *)NULL;
+dbg_sym_t *xtype_tree = (dbg_sym_t *)NULL;
+dbg_hashrec_t *dbg_hash[TYPE_NUM_SLOTS];
+int all_count, deall_count;
+void single_type(char *str);
+void sizeof_type(char *str);
+typedef struct chunk_s {
+       struct chunk_s  *next;  /* Must be first */
+       struct chunk_s  *prev;  /* Must be second */
+       void            *addr;
+       struct bucket_s *bucketp;
+       uint32_t        chunksz;  /* size of memory chunk (via malloc()) */
+       uint32_t        blksz;  /* Not including header */
+       short           blkcount; /* Number of blksz blocks in chunk */
+} chunk_t;
+
+typedef struct blkhdr_s {
+       struct blkhdr_s *next;
+       union {
+               struct blkhdr_s *prev;
+       chunk_t *chunkp;
+       } b_un;
+       int     flg;
+       int     size;
+} blkhdr_t;
+
+int ptrsz64 = ((int)sizeof(void *) == 8);
+alloc_functions_t alloc_functions;
+
+/*
+ * return 1 if addr is invalid
+ */
+static int
+invalid_address(kaddr_t addr, int count)
+{
+       unsigned char c;
+       unsigned long lcount;
+       /* FIXME: untested? */
+       lcount = count;
+       /* FIXME: use kdb_verify_area */
+       while (count--) {
+               if (kdb_getarea(c, addr))
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ * wrappers for calls to kernel-style allocation/deallocation
+ */
+static void *
+kl_alloc_block(int size)
+{
+       void    *vp;
+
+       vp = kmalloc(size, GFP_KERNEL);
+       if (!vp) {
+               kdb_printf ("kmalloc of %d bytes failed\n", size);
+       }
+       /* important: the lcrash code sometimes assumes that the
+        *            allocation is zeroed out
+        */
+       memset(vp, 0, size);
+       all_count++;
+       return vp;
+}
+static void
+kl_free_block(void *vp)
+{
+       kfree(vp);
+       deall_count++;
+       return;
+}
+
+int
+get_value(char *s, uint64_t *value)
+{
+       return kl_get_value(s, NULL, 0, value);
+}
+
+/*
+ * kl_get_block()
+ *
+ *   Read a size block from virtual address addr in the system memory image.
+ */
+k_error_t
+kl_get_block(kaddr_t addr, unsigned size, void *bp, void *mmap)
+{
+       if (!bp) {
+               return(KLE_NULL_BUFF);
+       } else if (!size) {
+               return(KLE_ZERO_SIZE);
+       }
+
+       memcpy(bp, (void *)addr, size);
+
+       return(0);
+}
+
+/*
+ * print_value()
+ */
+void
+print_value(char *ldstr, uint64_t value, int width)
+{
+       int w = 0;
+       char fmtstr[12], f, s[2]="\000\000";
+
+       if (ldstr) {
+               kdb_printf("%s", ldstr);
+       }
+        s[0] = '#';
+       f = 'x';
+       if (width) {
+               if (ptrsz64) {
+                       w = 18; /* due to leading "0x" */
+               } else {
+                       w = 10; /* due to leading "0x" */
+               }
+       }
+       if (w) {
+               sprintf(fmtstr, "%%%s%d"FMT64"%c", s, w, f);
+       } else {
+               sprintf(fmtstr, "%%%s"FMT64"%c", s, f);
+       }
+       kdb_printf(fmtstr, value);
+}
+
+/*
+ * print_list_head()
+ */
+void
+print_list_head(kaddr_t saddr)
+{
+       print_value("STRUCT ADDR: ", (uint64_t)saddr, 8);
+       kdb_printf("\n");
+}
+
+/*
+ * check_prev_ptr()
+ */
+void
+check_prev_ptr(kaddr_t ptr, kaddr_t prev)
+{
+       if(ptr != prev) {
+               kdb_printf("\nWARNING: Pointer broken. %#"FMTPTR"x,"
+                       " SHOULD BE: %#"FMTPTR"x\n", prev, ptr);
+       }
+}
+
+/*
+ * kl_kaddr() -- Return a kernel virtual address stored in a structure
+ *
+ *   Pointer 'p' points to a kernel structure
+ *   of type 's.' Get the kernel address located in member 'm.'
+ */
+kaddr_t
+kl_kaddr(void *p, char *s, char *m)
+{
+       uint64_t *u64p;
+       int     offset;
+
+       offset = kl_member_offset(s, m);
+       u64p = (uint64_t *)(p + offset);
+       return((kaddr_t)*u64p);
+}
+
+/*
+ * walk_structs() -- walk linked lists of kernel data structures
+ */
+int
+walk_structs(char *s, char *f, char *member, kaddr_t addr, int flags)
+{
+       int size, offset, mem_offset=0;
+       kaddr_t last = 0, next;
+       kltype_t *klt = (kltype_t *)NULL, *memklt=(kltype_t *)NULL;
+       unsigned long long iter_threshold = 10000;
+
+       int counter = 0;
+       kaddr_t head=0, head_next=0, head_prev=0, entry=0;
+       kaddr_t entry_next=0, entry_prev;
+
+       /* field name of link pointer, determine its offset in the struct.  */
+       if ((offset = kl_member_offset(s, f)) == -1) {
+               kdb_printf("Could not determine offset for member %s of %s.\n",
+                       f, s);
+               return 0;
+       }
+
+       /* Get the type of the enclosing structure */
+       if (!(klt = kl_find_type(s, (KLT_STRUCT|KLT_UNION)))) {
+               kdb_printf("Could not find the type of %s\n", s);
+               return(1);
+       }
+
+       /* Get the struct size */
+       if ((size = kl_struct_len(s)) == 0) {
+               kdb_printf ("could not get the length of %s\n", s);
+               return(1);
+       }
+
+       /* test for a named member of the structure that should be displayed */
+       if (member) {
+               memklt = kl_get_member(klt, member);
+               if (!memklt) {
+                       kdb_printf ("%s has no member %s\n", s, member);
+                       return 1;
+               }
+               mem_offset = kl_get_member_offset(klt, member);
+       }
+
+       if ((next = addr)) {
+               /* get head of list (anchor) when struct list_head is used */
+               if (flags & C_LISTHEAD) {
+                       head = next;
+                       if (invalid_address(head, sizeof(head))) {
+                               kdb_printf ("invalid address %#lx\n",
+                                       head);
+                               return 1;
+                       }
+                       /* get contents of addr  struct member */
+                       head_next = kl_kaddr((void *)head, "list_head", "next");
+                       if (invalid_address(head, sizeof(head_next))) {
+                               kdb_printf ("invalid address %#lx\n",
+                                       head_next);
+                               return 1;
+                       }
+                       /* get prev field of anchor */
+                       head_prev = kl_kaddr((void *)head, "list_head", "prev");
+                       if (invalid_address(head, sizeof(head_prev))) {
+                               kdb_printf ("invalid address %#lx\n",
+                                       head_prev);
+                               return 1;
+                       }
+                       entry = 0;
+               }
+       }
+
+       while(next && counter < iter_threshold) {
+               counter++;
+               if (counter > iter_threshold) {
+                       kdb_printf("\nWARNING: Iteration threshold reached.\n");
+                        kdb_printf("Current threshold: %lld\n", iter_threshold);
+                       break;
+               }
+               if(flags & C_LISTHEAD) {
+                       if(!(entry)){
+                               if(flags & C_LISTHEAD_N){
+                                       entry = head_next;
+                               } else {
+                                       entry = head_prev;
+                               }
+                               last = head;
+                       }
+
+                       if(head == entry) {
+                               if(flags & C_LISTHEAD_N){
+                                       check_prev_ptr(last, head_prev);
+                               } else {
+                                       check_prev_ptr(last, head_next);
+                               }
+                               break;
+                       }
+
+                       next = entry - offset; /* next structure */
+                       /* check that the whole structure can be addressed */
+                       if (invalid_address(next, size)) {
+                               kdb_printf(
+                               "invalid struct address %#lx\n", next);
+                               return 1;
+                       }
+                       /* and validate that it points to valid addresses */
+                       entry_next = kl_kaddr((void *)entry,"list_head","next");
+                       if (invalid_address(entry_next, sizeof(entry_next))) {
+                               kdb_printf("invalid address %#lx\n",
+                                       entry_next);
+                               return 1;
+                       }
+                       entry_prev = kl_kaddr((void *)entry,"list_head","prev");
+                       if (invalid_address(entry_prev, sizeof(entry_prev))) {
+                               kdb_printf("invalid address %#lx\n",
+                                       entry_prev);
+                               return 1;
+                       }
+                       if(flags & C_LISTHEAD_N){
+                               check_prev_ptr(last, entry_prev);
+                       } else {
+                               check_prev_ptr(last, entry_next);
+                       }
+                       print_list_head(next);
+                       last = entry;
+                       if(flags & C_LISTHEAD_N){
+                               entry = entry_next; /* next list_head */
+                       } else {
+                               entry = entry_prev; /* next list_head */
+                       }
+               }
+
+               if (memklt) {
+                       /* print named sub-structure in C-like struct format. */
+                       kl_print_member(
+                               (void *)((unsigned long)next+mem_offset),
+                               memklt, 0, C_HEX);
+               } else {
+                       /* print entire structure in C-like struct format. */
+                       kl_print_type((void *)next, klt, 0, C_HEX);
+               }
+
+               if(!(flags & C_LISTHEAD)) {
+                       last = next;
+                       next = (kaddr_t) (*(uint64_t*)(next + offset));
+               }
+       }
+
+       return(0);
+}
+
+/*
+ * Implement the lcrash walk -s command
+ *  see lcrash cmd_walk.c
+ */
+int
+kdb_walk(int argc, const char **argv)
+{
+       int     i, nonoptc=0, optc=0, flags=0, init_len=0;
+       char    *cmd, *arg, *structp=NULL, *forwp=NULL, *memberp=NULL;
+       char    *addrp=NULL;
+       uint64_t value;
+       kaddr_t start_addr;
+
+       all_count=0;
+       deall_count=0;
+       if (!have_debug_file) {
+               kdb_printf("no debuginfo file\n");
+               return 0;
+       }
+       /* If there is nothing to evaluate, just return */
+       if (argc == 0) {
+               return 0;
+       }
+       cmd = (char *)*argv; /* s/b "walk" */
+       if (strcmp(cmd,"walk")) {
+               kdb_printf("got %s, not \"walk\"\n", cmd);
+               return 0;
+       }
+
+       for (i=1; i<=argc; i++) {
+               arg = (char *)*(argv+i);
+               if (*arg == '-') {
+                       optc++;
+                       if (optc > 2) {
+                               kdb_printf("too many options\n");
+                               kdb_printf("see 'walkhelp'\n");
+                               return 0;
+                       }
+                       if (*(arg+1) == 's') {
+                               continue; /* ignore -s */
+                       } else if (*(arg+1) == 'h') {
+                               if ((init_len=kl_struct_len("list_head"))
+                                                               == 0) {
+                                       kdb_printf(
+                                               "could not find list_head\n");
+                                       return 0;
+                               }
+                               if (*(arg+2) == 'p') {
+                                       flags = C_LISTHEAD;
+                                       flags |= C_LISTHEAD_P;
+                               } else if (*(arg+2) == 'n') {
+                                       flags = C_LISTHEAD;
+                                       flags |= C_LISTHEAD_N;
+                               } else {
+                                       kdb_printf("invalid -h option <%s>\n",
+                                               arg);
+                                       kdb_printf("see 'walkhelp'\n");
+                                       return 0;
+                               }
+                       } else {
+                               kdb_printf("invalid option <%s>\n", arg);
+                               kdb_printf("see 'walkhelp'\n");
+                               return 0;
+                       }
+               }  else {
+                       nonoptc++;
+                       if (nonoptc > 4) {
+                               kdb_printf("too many arguments\n");
+                               kdb_printf("see 'walkhelp'\n");
+                               return 0;
+                       }
+                       if (nonoptc == 1) {
+                               structp = arg;
+                       } else if (nonoptc == 2) {
+                               forwp = arg;
+                       } else if (nonoptc == 3) {
+                               addrp = arg;
+                       } else if (nonoptc == 4) {
+                               /* the member is optional; if we get
+                                  a fourth, the previous was the member */
+                               memberp = addrp;
+                               addrp = arg;
+                       } else {
+                               kdb_printf("invalid argument <%s>\n", arg);
+                               kdb_printf("see 'walkhelp'\n");
+                               return 0;
+                       }
+               }
+       }
+       if (nonoptc < 3) {
+               kdb_printf("too few arguments\n");
+               kdb_printf("see 'walkhelp'\n");
+               return 0;
+       }
+       if (!(flags & C_LISTHEAD)) {
+               if ((init_len=kl_struct_len(structp)) == 0) {
+                       kdb_printf("could not find %s\n", structp);
+                       return 0;
+               }
+       }
+
+       /* Get the start address of the structure */
+       if (get_value(addrp, &value)) {
+               kdb_printf ("address %s invalid\n", addrp);
+               return 0;
+       }
+       start_addr = (kaddr_t)value;
+       if (invalid_address(start_addr, init_len)) {
+               kdb_printf ("address %#lx invalid\n", start_addr);
+               return 0;
+       }
+
+       if (memberp) {
+       }
+
+       if (walk_structs(structp, forwp, memberp, start_addr, flags)) {
+               kdb_printf ("walk_structs failed\n");
+               return 0;
+       }
+       /* kdb_printf("ptc allocated:%d deallocated:%d\n",
+                all_count, deall_count); */
+       return 0;
+}
+
+/*
+ * Implement the lcrash px (print, pd) command
+ *  see lcrash cmd_print.c
+ *
+ *     px <expression>
+ *       e.g. px *(task_struct *) <address>
+ */
+int
+kdb_debuginfo_print(int argc, const char **argv)
+{
+       /* argc does not count the command itself, which is argv[0] */
+       char            *cmd, *next, *end, *exp, *cp;
+       unsigned char   *buf;
+       int             i, j, iflags;
+       node_t          *np;
+       uint64_t        flags = 0;
+
+       /* If there is nothing to evaluate, just return */
+       if (argc == 0) {
+               return 0;
+       }
+       all_count=0;
+       deall_count=0;
+
+       cmd = (char *)*argv;
+
+       /* Set up the flags value. If this command was invoked via
+        * "pd" or "px", then make sure the appropriate flag is set.
+        */
+       flags = 0;
+       if (!strcmp(cmd, "pd") || !strcmp(cmd, "print")) {
+               flags = 0;
+       } else if (!strcmp(cmd, "px")) {
+               flags |= C_HEX;
+       } else if (!strcmp(cmd, "whatis")) {
+               if (argc != 1) {
+                       kdb_printf("usage: whatis <symbol | type>\n");
+                       return 0;
+               }
+               cp = (char *)*(argv+1);
+               single_type(cp);
+               /* kdb_printf("allocated:%d deallocated:%d\n",
+                        all_count, deall_count); */
+               return 0;
+       } else if (!strcmp(cmd, "sizeof")) {
+               if (!have_debug_file) {
+                       kdb_printf("no debuginfo file\n");
+                       return 0;
+               }
+               if (argc != 1) {
+                       kdb_printf("usage: sizeof type\n");
+                       return 0;
+               }
+               cp = (char *)*(argv+1);
+               sizeof_type(cp);
+               return 0;
+       } else {
+               kdb_printf("command error: %s\n", cmd);
+               return 0;
+       }
+
+       /*
+        * Count the number of bytes necessary to hold the entire expression
+        * string.
+        */
+       for (i=1, j=0; i <= argc; i++) {
+               j += (strlen(*(argv+i)) + 1);
+       }
+
+       /*
+        * Allocate space for the expression string and copy the individual
+        * arguments into it.
+        */
+       buf = kl_alloc_block(j);
+       if (!buf) {
+               return 0;
+       }
+
+       for (i=1; i <= argc; i++) {
+               strcat(buf, *(argv+i));
+               /* put spaces between arguments */
+               if (i < argc) {
+                       strcat(buf, " ");
+               }
+       }
+
+       /* Walk through the expression string, expression by expression.
+        * Note that a comma (',') is the delimiting character between
+        * expressions.
+        */
+       next = buf;
+       while (next) {
+               if ((end = strchr(next, ','))) {
+                       *end = (char)0;
+               }
+
+               /* Copy the next expression to a separate expression string.
+                * A separate expresison string is necessary because it is
+                * likely to get freed up in eval() when variables get expanded.
+                */
+               i = strlen(next)+1;
+               exp = (char *)kl_alloc_block(i);
+               if (!exp) {
+                       return 0;
+               }
+               strcpy(exp, next);
+
+               /* Evaluate the expression */
+               np = eval(&exp, 0);
+               if (!np || eval_error) {
+                       print_eval_error(cmd, exp,
+                               (error_token ? error_token : (char*)NULL),
+                               eval_error, CMD_NAME_FLG);
+                       if (np) {
+                               free_nodes(np);
+                       }
+                       kl_free_block(buf);
+                       kl_free_block(exp);
+                       free_eval_memory();
+                       return 0;
+               }
+               iflags = flags;
+               if (print_eval_results(np, iflags)) {
+                       free_nodes(np);
+                       kl_free_block(buf);
+                       free_eval_memory();
+                       return 0;
+               }
+               kl_free_block(exp);
+
+               if (end) {
+                       next = end + 1;
+                       kdb_printf(" ");
+               } else {
+                       next = (char*)NULL;
+                       kdb_printf("\n");
+               }
+               free_nodes(np);
+       }
+       free_eval_memory();
+       kl_free_block(buf);
+       /* kdb_printf("allocated:%d deallocated:%d\n",
+                        all_count, deall_count); */
+       return 0;
+}
+
+/*
+ * Display help for the px command
+ */
+int
+kdb_pxhelp(int argc, const char **argv)
+{
+       if (have_debug_file) {
+ kdb_printf ("Some examples of using the px command:\n");
+ kdb_printf (" the whole structure:\n");
+ kdb_printf ("  px *(task_struct *)0xe0000...\n");
+ kdb_printf (" one member:\n");
+ kdb_printf ("  px (*(task_struct *)0xe0000...)->comm\n");
+ kdb_printf (" the address of a member\n");
+ kdb_printf ("  px &((task_struct *)0xe0000...)->children\n");
+ kdb_printf (" a structure pointed to by a member:\n");
+ kdb_printf ("  px ((*(class_device *)0xe0000...)->class)->name\n");
+ kdb_printf (" array element:\n");
+ kdb_printf ("  px (cache_sizes *)0xa0000...[0]\n");
+ kdb_printf ("  px (task_struct *)(0xe0000...)->cpus_allowed.bits[0]\n");
+       } else {
+               kdb_printf ("There is no debug info file.\n");
+               kdb_printf ("The px/pd/print commands can only evaluate ");
+               kdb_printf ("arithmetic expressions.\n");
+       }
+ return 0;
+}
+
+/*
+ * Display help for the walk command
+ */
+int
+kdb_walkhelp(int argc, const char **argv)
+{
+       if (!have_debug_file) {
+               kdb_printf("no debuginfo file\n");
+               return 0;
+       }
+ kdb_printf ("Using the walk command:\n");
+ kdb_printf (" (only the -s (symbolic) form is supported, so -s is ignored)\n");
+ kdb_printf ("\n");
+ kdb_printf (" If the list is not linked with list_head structures:\n");
+ kdb_printf ("  walk [-s] struct name-of-forward-pointer address\n");
+ kdb_printf ("  example: walk xyz_struct next 0xe00....\n");
+ kdb_printf ("\n");
+ kdb_printf (" If the list is linked with list_head structures, use -hn\n");
+ kdb_printf (" to walk the 'next' list, -hp for the 'prev' list\n");
+ kdb_printf ("  walk -h[n|p] struct name-of-forward-pointer [member-to-show] address-of-list-head\n");
+ kdb_printf ("  example, to show the entire task_struct:\n");
+ kdb_printf ("   walk -hn task_struct tasks 0xe000....\n");
+ kdb_printf ("  example, to show the task_struct member comm:\n");
+ kdb_printf ("   walk -hn task_struct tasks comm 0xe000....\n");
+ kdb_printf ("  (address is not the address of first member's list_head, ");
+ kdb_printf     ("but of the anchoring list_head\n");
+ return 0;
+}
+
+/*
+ * dup_block()
+ */
+void *
+dup_block(void *b, int len)
+{
+       void *b2;
+
+       if ((b2 = kl_alloc_block(len))) {
+               memcpy(b2, b, len); /* dst, src, sz */
+       }
+       return(b2);
+}
+
+/*
+ * kl_reset_error()
+ */
+void
+kl_reset_error(void)
+{
+        klib_error = 0;
+}
+
+/*
+ * given a symbol name, look up its address
+ *
+ * in lcrash, this would return a pointer to the syment_t in
+ * a binary tree of them
+ *
+ * In this one, look up the symbol in the standard kdb way,
+ * which fills in the kdb_symtab_t.
+ * Then fill in the  global syment_t "lkup_syment" -- assuming
+ * we'll only need one at a time!
+ *
+ * kl_lkup_symname returns the address of syment_t if the symbol is
+ * found, else null.
+ *
+ * Note: we allocate a syment_t   the caller should kfree it
+ */
+syment_t *
+kl_lkup_symname (char *cp)
+{
+       syment_t  *sp;
+       kdb_symtab_t kdb_symtab;
+
+       if (kdbgetsymval(cp, &kdb_symtab)) {
+               sp = (syment_t *)kl_alloc_block(sizeof(syment_t));
+               sp->s_addr = (kaddr_t)kdb_symtab.sym_start;
+               KL_ERROR = 0;
+               return (sp);
+       } else {
+               /* returns 0 if the symbol is not found */
+               KL_ERROR = KLE_INVALID_VALUE;
+               return ((syment_t *)0);
+       }
+}
+
+/*
+ * kl_get_ra()
+ *
+ * This function returns its own return address.
+ * Usefule when trying to capture where we came from.
+ */
+void*
+kl_get_ra(void)
+{
+       return (__builtin_return_address(0));
+}
+
+/* start kl_util.c */
+/*
+ * Definitions for the do_math() routine.
+ */
+#define M_ADD      '+'
+#define M_SUBTRACT '-'
+#define M_MULTIPLY '*'
+#define M_DIVIDE   '/'
+
+/*
+ * do_math() -- Calculate some math values based on a string argument
+ *              passed into the function.  For example, if you use:
+ *
+ *              0xffffc000*2+6/5-3*19-8
+ *
+ *              And you will get the value 0xffff7fc0 back.  I could
+ *              probably optimize this a bit more, but right now, it
+ *              works, which is good enough for me.
+ */
+static uint64_t
+do_math(char *str)
+{
+       int i = 0;
+       char *buf, *loc;
+       uint64_t value1, value2;
+       syment_t *sp;
+
+       buf = (char *)kl_alloc_block((strlen(str) + 1));
+       sprintf(buf, "%s", str);
+       for (i = strlen(str); i >= 0; i--) {
+               if ((str[i] == M_ADD) || (str[i] == M_SUBTRACT)) {
+                       buf[i] = '\0';
+                       value1 = do_math(buf);
+                       value2 = do_math(&str[i+1]);
+                       kl_free_block((void *)buf);
+                       if (str[i] == M_SUBTRACT) {
+                               return value1 - value2;
+                       } else {
+                               return value1 + value2;
+                       }
+               }
+       }
+
+       for (i = strlen(str); i >= 0; i--) {
+               if ((str[i] == M_MULTIPLY) || (str[i] == M_DIVIDE)) {
+                       buf[i] = '\0';
+                       value1 = do_math(buf);
+                       value2 = do_math(&str[i+1]);
+                       kl_free_block((void *)buf);
+                       if (str[i] == M_MULTIPLY) {
+                               return (value1 * value2);
+                       } else {
+                               if (value2 == 0) {
+                                       /* handle divide by zero */
+                                       /* XXX -- set proper error code */
+                                       klib_error = 1;
+                                       return (0);
+                               } else {
+                                       return (value1 / value2);
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Otherwise, just process the value, and return it.
+        */
+       sp = kl_lkup_symname(buf);
+       if (KL_ERROR) {
+               KL_ERROR = 0;
+               value2 = kl_strtoull(buf, &loc, 10);
+               if (((!value2) && (buf[0] != '0')) || (*loc) ||
+                       (!strncmp(buf, "0x", 2)) || (!strncmp(buf, "0X", 2))) {
+                       value1 = (kaddr_t)kl_strtoull(buf, (char**)NULL, 16);
+               } else {
+                       value1 = (unsigned)kl_strtoull(buf, (char**)NULL, 10);
+               }
+       } else {
+               value1 = (kaddr_t)sp->s_addr;
+               kl_free_block((void *)sp);
+       }
+       kl_free_block((void *)buf);
+       return (value1);
+}
+/*
+ * kl_get_value() -- Translate numeric input strings
+ *
+ *   A generic routine for translating an input string (param) in a
+ *   number of dfferent ways. If the input string is an equation
+ *   (contains the characters '+', '-', '/', and '*'), then perform
+ *   the math evaluation and return one of the following modes (if
+ *   mode is passed):
+ *
+ *   0 -- if the resulting value is <= elements, if elements (number
+ *        of elements in a table) is passed.
+ *
+ *   1 -- if the first character in param is a pound sign ('#').
+ *
+ *   3 -- the numeric result of an equation.
+ *
+ *   If the input string is NOT an equation, mode (if passed) will be
+ *   set in one of the following ways (depending on the contents of
+ *   param and elements).
+ *
+ *   o When the first character of param is a pound sign ('#'), mode
+ *     is set equal to one and the trailing numeric value (assumed to
+ *     be decimal) is returned.
+ *
+ *   o When the first two characters in param are "0x" or "0X," or
+ *     when when param contains one of the characers "abcdef," or when
+ *     the length of the input value is eight characters. mode is set
+ *     equal to two and the numeric value contained in param is
+ *     translated as hexadecimal and returned.
+ *
+ *   o The value contained in param is translated as decimal and mode
+ *     is set equal to zero. The resulting value is then tested to see
+ *     if it exceeds elements (if passed). If it does, then value is
+ *     translated as hexadecimal and mode is set equal to two.
+ *
+ *   Note that mode is only set when a pointer is passed in the mode
+ *   paramater. Also note that when elements is set equal to zero, any
+ *   non-hex (as determined above) value not starting with a pound sign
+ *   will be translated as hexadecimal (mode will be set equal to two) --
+ *   IF the length of the string of characters is less than 16 (kaddr_t).
+ *
+ */
+int
+kl_get_value(char *param, int *mode, int elements, uint64_t *value)
+{
+       char *loc;
+       uint64_t v;
+
+       kl_reset_error();
+
+       /* Check to see if we are going to need to do any math
+        */
+       if (strpbrk(param, "+-/*")) {
+               if (!strncmp(param, "#", 1)) {
+                       v = do_math(&param[1]);
+                       if (mode) {
+                               *mode = 1;
+                       }
+               } else {
+                       v = do_math(param);
+                       if (mode) {
+                               if (elements && (*value <= elements)) {
+                                       *mode = 0;
+                               } else {
+                                       *mode = 3;
+                               }
+                       }
+               }
+       } else {
+               if (!strncmp(param, "#", 1)) {
+                       if (!strncmp(param, "0x", 2)
+                                       || !strncmp(param, "0X", 2)
+                                       || strpbrk(param, "abcdef")) {
+                               v = kl_strtoull(&param[1], &loc, 16);
+                       } else {
+                               v = kl_strtoull(&param[1], &loc, 10);
+                       }
+                       if (loc) {
+                               KL_ERROR = KLE_INVALID_VALUE;
+                               return (1);
+                       }
+                       if (mode) {
+                               *mode = 1;
+                       }
+               } else if (!strncmp(param, "0x", 2) || !strncmp(param, "0X", 2)
+                                       || strpbrk(param, "abcdef")) {
+                       v = kl_strtoull(param, &loc, 16);
+                       if (loc) {
+                               KL_ERROR = KLE_INVALID_VALUE;
+                               return (1);
+                       }
+                       if (mode) {
+                               *mode = 2; /* HEX VALUE */
+                       }
+               } else if (elements || (strlen(param) < 16) ||
+                               (strlen(param) > 16)) {
+                       v = kl_strtoull(param, &loc, 10);
+                       if (loc) {
+                               KL_ERROR = KLE_INVALID_VALUE;
+                               return (1);
+                       }
+                       if (elements && (v >= elements)) {
+                               v = (kaddr_t)kl_strtoull(param,
+                                               (char**)NULL, 16);
+                               if (mode) {
+                                       *mode = 2; /* HEX VALUE */
+                               }
+                       } else if (mode) {
+                               *mode = 0;
+                       }
+               } else {
+                       v = kl_strtoull(param, &loc, 16);
+                       if (loc) {
+                               KL_ERROR = KLE_INVALID_VALUE;
+                               return (1);
+                       }
+                       if (mode) {
+                               *mode = 2; /* ASSUME HEX VALUE */
+                       }
+               }
+       }
+       *value = v;
+       return (0);
+}
+/* end kl_util.c */
+
+/* start kl_libutil.c */
+static int
+valid_digit(char c, int base)
+{
+       switch(base) {
+               case 2:
+                       if ((c >= '0') && (c <= '1')) {
+                               return(1);
+                       } else {
+                               return(0);
+                       }
+               case 8:
+                       if ((c >= '0') && (c <= '7')) {
+                               return(1);
+                       } else {
+                               return(0);
+                       }
+               case 10:
+                       if ((c >= '0') && (c <= '9')) {
+                               return(1);
+                       } else {
+                               return(0);
+                       }
+               case 16:
+                       if (((c >= '0') && (c <= '9'))
+                                       || ((c >= 'a') && (c <= 'f'))
+                                       || ((c >= 'A') && (c <= 'F'))) {
+                               return(1);
+                       } else {
+                               return(0);
+                       }
+       }
+       return(0);
+}
+
+static int
+digit_value(char c, int base, int *val)
+{
+       if (!valid_digit(c, base)) {
+               return(1);
+       }
+       switch (base) {
+               case 2:
+               case 8:
+               case 10:
+                       *val = (int)((int)(c - 48));
+                       break;
+               case 16:
+                       if ((c >= 'a') && (c <= 'f')) {
+                               *val = ((int)(c - 87));
+                       } else if ((c >= 'A') && (c <= 'F')) {
+                               *val = ((int)(c - 55));
+                       } else {
+                               *val = ((int)(c - 48));
+                       }
+       }
+       return(0);
+}
+
+uint64_t
+kl_strtoull(char *str, char **loc, int base)
+{
+       int dval;
+       uint64_t i = 1, v, value = 0;
+       char *c, *cp = str;
+
+       *loc = (char *)NULL;
+       if (base == 0) {
+               if (!strncmp(cp, "0x", 2) || !strncmp(cp, "0X", 2)) {
+                       base = 16;
+               } else if (cp[0] == '0') {
+                       if (cp[1] == 'b') {
+                               base = 2;
+                       } else {
+                               base = 8;
+                       }
+               } else if (strpbrk(cp, "abcdefABCDEF")) {
+                       base = 16;
+               } else {
+                       base = 10;
+               }
+       }
+       if ((base == 8) && (*cp == '0')) {
+               cp += 1;
+       } else if ((base == 2) && !strncmp(cp, "0b", 2)) {
+               cp += 2;
+       } else if ((base == 16) &&
+                       (!strncmp(cp, "0x", 2) || !strncmp(cp, "0X", 2))) {
+               cp += 2;
+       }
+       c = &cp[strlen(cp) - 1];
+       while (c >= cp) {
+
+               if (digit_value(*c, base, &dval)) {
+                       if (loc) {
+                               *loc = c;
+                       }
+                       return(value);
+               }
+               v = dval * i;
+               if ((MAX_LONG_LONG - value) < v) {
+                       return(MAX_LONG_LONG);
+               }
+               value += v;
+               i *= (uint64_t)base;
+               c--;
+       }
+       return(value);
+}
+/* end kl_libutil.c */
+
+/*
+ * dbg_hash_sym()
+ */
+void
+dbg_hash_sym(uint64_t typenum, dbg_sym_t *stp)
+{
+       dbg_hashrec_t *shp, *hshp;
+
+       if ((typenum == 0) || (!stp)) {
+               return;
+       }
+       shp = (dbg_hashrec_t *)kl_alloc_block(sizeof(dbg_hashrec_t));
+       shp->h_typenum = typenum;
+       shp->h_ptr = stp;
+       shp->h_next = (dbg_hashrec_t *)NULL;
+       if ((hshp = dbg_hash[TYPE_NUM_HASH(typenum)])) {
+               while (hshp->h_next) {
+                       hshp = hshp->h_next;
+               }
+               hshp->h_next = shp;
+       } else {
+               dbg_hash[TYPE_NUM_HASH(typenum)] = shp;
+       }
+}
+
+/*
+ * dbg_find_sym()
+ */
+dbg_sym_t *
+dbg_find_sym(char *name, int type, uint64_t typenum)
+{
+       dbg_sym_t *stp = (dbg_sym_t *)NULL;
+
+       if (name && strlen(name)) {
+               /* Cycle through the type flags and see if any records are
+                * present. Note that if multiple type flags or DBG_ALL is
+                * passed in, only the first occurance of 'name' will be
+                * found and returned. If name exists in multiple trees,
+                * then multiple searches are necessary to find them.
+                */
+               if (type & DBG_TYPE) {
+                       if ((stp = (dbg_sym_t *)kl_find_btnode((btnode_t *)
+                                       type_tree, name, (int *)NULL))) {
+                               goto found_sym;
+                       }
+               }
+               if (type & DBG_TYPEDEF) {
+                       if ((stp = (dbg_sym_t *)kl_find_btnode((btnode_t *)
+                                       typedef_tree, name, (int *)NULL))) {
+                               goto found_sym;
+                       }
+               }
+               if (!stp) {
+                       return((dbg_sym_t*)NULL);
+               }
+       }
+found_sym:
+       if (typenum) {
+               dbg_hashrec_t *hshp;
+
+               if (stp) {
+                       if (stp->sym_typenum == typenum) {
+                               return(stp);
+                       }
+               } else if ((hshp = dbg_hash[TYPE_NUM_HASH(typenum)])) {
+                       while (hshp) {
+                               if (hshp->h_typenum == typenum) {
+                                       return(hshp->h_ptr);
+                               }
+                               hshp = hshp->h_next;
+                       }
+               }
+       }
+       return(stp);
+}
+
+/*
+ * kl_find_type() -- find a KLT type by name.
+ */
+kltype_t *
+kl_find_type(char *name, int tnum)
+{
+       dbg_sym_t *stp;
+       kltype_t *kltp = (kltype_t *)NULL;
+
+       if (!have_debug_file) {
+               kdb_printf("no debuginfo file\n");
+               return kltp;
+       }
+
+       if (!tnum || IS_TYPE(tnum)) {
+               if ((stp = dbg_find_sym(name, DBG_TYPE, 0))) {
+                       kltp = (kltype_t *)stp->sym_kltype;
+                       if (tnum && !(kltp->kl_type & tnum)) {
+                               /* We have found a type by this name
+                                * but it does not have the right
+                                * type number (e.g., we're looking
+                                * for a struct and we don't find
+                                * a KLT_STRUCT type by this name).
+                                */
+                               return((kltype_t *)NULL);
+                       }
+               }
+       }
+       if (!tnum || IS_TYPEDEF(tnum)) {
+               if ((stp = dbg_find_sym(name, DBG_TYPEDEF, 0))) {
+                       kltp = (kltype_t *)stp->sym_kltype;
+               }
+       }
+       return(kltp);
+}
+
+/*
+ * kl_first_btnode() -- non-recursive implementation.
+ */
+btnode_t *
+kl_first_btnode(btnode_t *np)
+{
+       if (!np) {
+               return((btnode_t *)NULL);
+       }
+
+       /* Walk down the left side 'til the end...
+        */
+       while (np->bt_left) {
+               np = np->bt_left;
+       }
+       return(np);
+}
+
+/*
+ * kl_next_btnode() -- non-recursive implementation.
+ */
+btnode_t *
+kl_next_btnode(btnode_t *node)
+{
+       btnode_t *np = node, *parent;
+
+       if (np) {
+               if (np->bt_right) {
+                       return(kl_first_btnode(np->bt_right));
+               } else {
+                       parent = np->bt_parent;
+next:
+                       if (parent) {
+                               if (parent->bt_left == np) {
+                                       return(parent);
+                               }
+                               np = parent;
+                               parent = parent->bt_parent;
+                               goto next;
+                       }
+               }
+       }
+       return((btnode_t *)NULL);
+}
+
+/*
+ * dbg_next_sym()
+ */
+dbg_sym_t *
+dbg_next_sym(dbg_sym_t *stp)
+{
+       dbg_sym_t *next_stp;
+
+       next_stp = (dbg_sym_t *)kl_next_btnode((btnode_t *)stp);
+       return(next_stp);
+}
+
+/*
+ * kl_prev_btnode() -- non-recursive implementation.
+ */
+btnode_t *
+kl_prev_btnode(btnode_t *node)
+{
+       btnode_t *np = node, *parent;
+
+       if (np) {
+               if (np->bt_left) {
+                       np = np->bt_left;
+                       while (np->bt_right) {
+                               np = np->bt_right;
+                       }
+                       return(np);
+               }
+               parent = np->bt_parent;
+next:
+               if (parent) {
+                       if (parent->bt_right == np) {
+                               return(parent);
+                       }
+                       np = parent;
+                       parent = parent->bt_parent;
+                       goto next;
+               }
+       }
+       return((btnode_t *)NULL);
+}
+
+/*
+ * dbg_prev_sym()
+ */
+dbg_sym_t *
+dbg_prev_sym(dbg_sym_t *stp)
+{
+       dbg_sym_t *prev_stp;
+
+       prev_stp = (dbg_sym_t *)kl_prev_btnode((btnode_t *)stp);
+       return(prev_stp);
+}
+
+/*
+ * kl_find_next_type() -- find next KLT type
+ */
+kltype_t *
+kl_find_next_type(kltype_t *kltp, int type)
+{
+       kltype_t *nkltp = NULL;
+       dbg_sym_t *nstp;
+
+       if (kltp && kltp->kl_ptr) {
+               nstp = (dbg_sym_t *)kltp->kl_ptr;
+               nkltp = (kltype_t *)nstp->sym_kltype;
+               if (type) {
+                       while(nkltp && !(nkltp->kl_type & type)) {
+                               if ((nstp = dbg_next_sym(nstp))) {
+                                       nkltp = (kltype_t *)nstp->sym_kltype;
+                               } else {
+                                       nkltp = (kltype_t *)NULL;
+                               }
+                       }
+               }
+       }
+       return(nkltp);
+}
+
+/*
+ * dbg_first_sym()
+ */
+dbg_sym_t *
+dbg_first_sym(int type)
+{
+       dbg_sym_t *stp = (dbg_sym_t *)NULL;
+
+       switch(type) {
+               case DBG_TYPE:
+                       stp = (dbg_sym_t *)
+                               kl_first_btnode((btnode_t *)type_tree);
+                       break;
+               case DBG_TYPEDEF:
+                       stp = (dbg_sym_t *)
+                               kl_first_btnode((btnode_t *)typedef_tree);
+                       break;
+       }
+       return(stp);
+}
+
+/*
+ * kl_first_type()
+ */
+kltype_t *
+kl_first_type(int tnum)
+{
+       kltype_t *kltp = NULL;
+       dbg_sym_t *stp;
+
+       if (IS_TYPE(tnum)) {
+               /* If (tnum == KLT_TYPE), then return the first type
+                * record, regardless of the type. Otherwise, search
+                * for the frst type that mapps into tnum.
+                */
+               if ((stp = dbg_first_sym(DBG_TYPE))) {
+                       kltp = (kltype_t *)stp->sym_kltype;
+                       if (tnum != KLT_TYPE) {
+                               while (kltp && !(kltp->kl_type & tnum)) {
+                                       if ((stp = dbg_next_sym(stp))) {
+                                               kltp = (kltype_t *)stp->sym_kltype;
+                                       } else {
+                                               kltp = (kltype_t *)NULL;
+                                       }
+                               }
+                       }
+               }
+       } else if (IS_TYPEDEF(tnum)) {
+               if ((stp = dbg_first_sym(DBG_TYPEDEF))) {
+                       kltp = (kltype_t *)stp->sym_kltype;
+               }
+       }
+       return(kltp);
+}
+
+/*
+ * kl_next_type()
+ */
+kltype_t *
+kl_next_type(kltype_t *kltp)
+{
+       dbg_sym_t *stp, *nstp;
+       kltype_t *nkltp = (kltype_t *)NULL;
+
+       if (!kltp) {
+               return((kltype_t *)NULL);
+       }
+       stp = (dbg_sym_t *)kltp->kl_ptr;
+       if ((nstp = dbg_next_sym(stp))) {
+               nkltp = (kltype_t *)nstp->sym_kltype;
+       }
+       return(nkltp);
+}
+
+/*
+ * kl_prev_type()
+ */
+kltype_t *
+kl_prev_type(kltype_t *kltp)
+{
+       dbg_sym_t *stp, *pstp;
+       kltype_t *pkltp = (kltype_t *)NULL;
+
+       if (!kltp) {
+               return((kltype_t *)NULL);
+       }
+       stp = (dbg_sym_t *)kltp->kl_ptr;
+       if ((pstp = dbg_prev_sym(stp))) {
+               pkltp = (kltype_t *)pstp->sym_kltype;
+       }
+       return(pkltp);
+}
+
+/*
+ * kl_realtype()
+ */
+kltype_t *
+kl_realtype(kltype_t *kltp, int tnum)
+{
+       kltype_t *rkltp = kltp;
+
+       while (rkltp) {
+               if (tnum && (rkltp->kl_type == tnum)) {
+                       break;
+               }
+               if (!rkltp->kl_realtype) {
+                       break;
+               }
+               if (rkltp->kl_realtype == rkltp) {
+                       break;
+               }
+               rkltp = rkltp->kl_realtype;
+               if (rkltp == kltp) {
+                       break;
+               }
+       }
+       return(rkltp);
+}
+
+/*
+ * dbg_find_typenum()
+ */
+dbg_type_t *
+dbg_find_typenum(uint64_t typenum)
+{
+        dbg_sym_t *stp;
+        dbg_type_t *sp = (dbg_type_t *)NULL;
+
+        if ((stp = dbg_find_sym(0, DBG_TYPE, typenum))) {
+                sp = (dbg_type_t *)stp->sym_kltype;
+        }
+        return(sp);
+}
+
+/*
+ * find type by typenum
+ */
+kltype_t *
+kl_find_typenum(uint64_t typenum)
+{
+       kltype_t *kltp;
+
+       kltp = (kltype_t *)dbg_find_typenum(typenum);
+       return(kltp);
+}
+
+/*
+ * kl_find_btnode() -- non-recursive implementation.
+ */
+btnode_t *
+_kl_find_btnode(btnode_t *np, char *key, int *max_depth, size_t len)
+{
+       int ret;
+        btnode_t *next, *prev;
+
+       if (np) {
+               if (max_depth) {
+                       (*max_depth)++;
+               }
+               next = np;
+again:
+               if (len) {
+                       ret = strncmp(key, next->bt_key, len);
+               } else {
+                       ret = strcmp(key, next->bt_key);
+               }
+               if (ret == 0) {
+                       if ((prev = kl_prev_btnode(next))) {
+                               if (len) {
+                                       ret = strncmp(key, prev->bt_key, len);
+                               } else {
+                                       ret = strcmp(key, prev->bt_key);
+                               }
+                               if (ret == 0) {
+                                       next = prev;
+                                       goto again;
+                               }
+                       }
+                       return(next);
+               } else if (ret < 0) {
+                       if ((next = next->bt_left)) {
+                               goto again;
+                       }
+               } else {
+                       if ((next = next->bt_right)) {
+                               goto again;
+                       }
+               }
+       }
+       return((btnode_t *)NULL);
+}
+
+/*
+ * kl_type_size()
+ */
+int
+kl_type_size(kltype_t *kltp)
+{
+       kltype_t *rkltp;
+
+       if (!kltp) {
+               return(0);
+       }
+       if (!(rkltp = kl_realtype(kltp, 0))) {
+               return(0);
+       }
+       return(rkltp->kl_size);
+}
+
+/*
+ * kl_struct_len()
+ */
+int
+kl_struct_len(char *s)
+{
+       kltype_t *kltp;
+
+       if ((kltp = kl_find_type(s, (KLT_TYPES)))) {
+               return kl_type_size(kltp);
+       }
+       return(0);
+}
+
+/*
+ * kl_get_member()
+ */
+kltype_t *
+kl_get_member(kltype_t *kltp, char *f)
+{
+       kltype_t *mp;
+
+       if ((mp = kltp->kl_member)) {
+               while (mp) {
+                       if (mp->kl_flags & TYP_ANONYMOUS_FLG) {
+                               kltype_t *amp;
+
+                               if ((amp = kl_get_member(mp->kl_realtype, f))) {
+                                       return(amp);
+                               }
+                       } else if (!strcmp(mp->kl_name, f)) {
+                               break;
+                       }
+                       mp = mp->kl_member;
+               }
+       }
+       return(mp);
+}
+
+/*
+ * kl_member()
+ */
+kltype_t *
+kl_member(char *s, char *f)
+{
+       kltype_t *kltp, *mp = NULL;
+
+       if (!(kltp = kl_find_type(s, (KLT_STRUCT|KLT_UNION)))) {
+               if ((kltp = kl_find_type(s, KLT_TYPEDEF))) {
+                       kltp = kl_realtype(kltp, 0);
+               }
+       }
+       if (kltp) {
+               mp = kl_get_member(kltp, f);
+       }
+       return(mp);
+}
+
+
+/*
+ * kl_get_member_offset()
+ */
+int
+kl_get_member_offset(kltype_t *kltp, char *f)
+{
+       kltype_t *mp;
+
+       if ((mp = kltp->kl_member)) {
+               while (mp) {
+                       if (mp->kl_flags & TYP_ANONYMOUS_FLG) {
+                               int off;
+
+                               /* Drill down to see if the member we are looking for is in
+                                * an anonymous union or struct. Since this call is recursive,
+                                * the drill down may actually be multi-layer.
+                                */
+                               off = kl_get_member_offset(mp->kl_realtype, f);
+                               if (off >= 0) {
+                                       return(mp->kl_offset + off);
+                               }
+                       } else if (!strcmp(mp->kl_name, f)) {
+                               return(mp->kl_offset);
+                       }
+                       mp = mp->kl_member;
+               }
+       }
+       return(-1);
+}
+
+/*
+ * kl_member_offset()
+ */
+int
+kl_member_offset(char *s, char *f)
+{
+       int off = -1;
+       kltype_t *kltp;
+
+    if (!(kltp = kl_find_type(s, (KLT_STRUCT|KLT_UNION)))) {
+        if ((kltp = kl_find_type(s, KLT_TYPEDEF))) {
+            kltp = kl_realtype(kltp, 0);
+        }
+    }
+       if (kltp) {
+               off = kl_get_member_offset(kltp, f);
+       }
+       return(off);
+}
+
+/*
+ * kl_is_member()
+ */
+int
+kl_is_member(char *s, char *f)
+{
+       kltype_t *mp;
+
+       if ((mp = kl_member(s, f))) {
+               return(1);
+       }
+       return(0);
+}
+
+/*
+ * kl_member_size()
+ */
+int
+kl_member_size(char *s, char *f)
+{
+       kltype_t *mp;
+
+       if ((mp = kl_member(s, f))) {
+               return(mp->kl_size);
+       }
+       return(0);
+}
+
+#define TAB_SPACES                  8
+#define LEVEL_INDENT(level, flags) {\
+       int i, j; \
+       if (!(flags & NO_INDENT)) { \
+               for (i = 0; i < level; i++) { \
+                       for (j = 0; j < TAB_SPACES; j++) { \
+                               kdb_printf(" "); \
+                       } \
+               }\
+       } \
+}
+#define PRINT_NL(flags) \
+       if (!(flags & SUPPRESS_NL)) { \
+               kdb_printf("\n"); \
+       }
+#define PRINT_SEMI_COLON(level, flags) \
+       if (level && (!(flags & SUPPRESS_SEMI_COLON))) { \
+               kdb_printf(";"); \
+       }
+
+/*
+ * print_realtype()
+ */
+static void
+print_realtype(kltype_t *kltp)
+{
+       kltype_t *rkltp;
+
+       if ((rkltp = kltp->kl_realtype)) {
+               while (rkltp && rkltp->kl_realtype) {
+                       rkltp = rkltp->kl_realtype;
+               }
+               if (rkltp->kl_type == KLT_BASE) {
+                       kdb_printf(" (%s)", rkltp->kl_name);
+               }
+       }
+}
+
+int align_chk = 0;
+/*
+ *  kl_print_uint16()
+ *
+ */
+void
+kl_print_uint16(void *ptr, int flags)
+{
+       unsigned long long a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        *          * dump core)
+        *                   */
+       if (align_chk && (uaddr_t)ptr % 16) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(unsigned long long *) ptr;
+       if (flags & C_HEX) {
+               kdb_printf("%#llx", a);
+       } else if (flags & C_BINARY) {
+               kdb_printf("0b");
+               kl_binary_print(a);
+       } else {
+               kdb_printf("%llu", a);
+       }
+}
+
+#if 0
+/*
+ * kl_print_float16()
+ *
+ */
+void
+kl_print_float16(void *ptr, int flags)
+{
+       double a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        *          * dump core)
+        *                   */
+       if (align_chk && (uaddr_t)ptr % 16) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(double*) ptr;
+       kdb_printf("%f", a);
+}
+#endif
+
+/*
+ * kl_print_int16()
+ *
+ */
+void
+kl_print_int16(void *ptr, int flags)
+{
+       long long a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        *          * dump core)
+        *                   */
+       if (align_chk && (uaddr_t)ptr % 16) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(long long *) ptr;
+       if (flags & C_HEX) {
+               kdb_printf("%#llx", a);
+       } else if (flags & C_BINARY) {
+               kdb_printf("0b");
+               kl_binary_print(a);
+       } else {
+               kdb_printf("%lld", a);
+       }
+}
+
+/*
+ * kl_print_int8()
+ */
+void
+kl_print_int8(void *ptr, int flags)
+{
+       long long a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        * dump core)
+        */
+       if (align_chk && (uaddr_t)ptr % 8) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(long long *) ptr;
+       if (flags & C_HEX) {
+               kdb_printf("%#llx", a);
+       } else if (flags & C_BINARY) {
+               kdb_printf("0b");
+               kl_binary_print(a);
+       } else {
+               kdb_printf("%lld", a);
+       }
+}
+
+#if 0
+/*
+ * kl_print_float8()
+ */
+void
+kl_print_float8(void *ptr, int flags)
+{
+       double a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        * dump core)
+        */
+       if (align_chk && (uaddr_t)ptr % 8) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(double*) ptr;
+       kdb_printf("%f", a);
+}
+#endif
+
+/*
+ * kl_print_uint8()
+ */
+void
+kl_print_uint8(void *ptr, int flags)
+{
+       unsigned long long a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        * dump core)
+        */
+       if (align_chk && (uaddr_t)ptr % 8) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(unsigned long long *) ptr;
+       if (flags & C_HEX) {
+               kdb_printf("%#llx", a);
+       } else if (flags & C_BINARY) {
+               kdb_printf("0b");
+               kl_binary_print(a);
+       } else {
+               kdb_printf("%llu", a);
+       }
+}
+
+/*
+ * kl_print_int4()
+ */
+void
+kl_print_int4(void *ptr, int flags)
+{
+       int32_t a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        * dump core
+        */
+       if (align_chk && (uaddr_t)ptr % 4) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(int32_t*) ptr;
+       if (flags & C_HEX) {
+               kdb_printf("0x%x", a);
+       } else if (flags & C_BINARY) {
+               uint64_t value = a & 0xffffffff;
+               kdb_printf("0b");
+               kl_binary_print(value);
+       } else {
+               kdb_printf("%d", a);
+       }
+}
+
+#if 0
+/*
+ * kl_print_float4()
+ */
+void
+kl_print_float4(void *ptr, int flags)
+{
+       float a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        * dump core)
+        */
+       if (align_chk && (uaddr_t)ptr % 4) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(float*) ptr;
+       kdb_printf("%f", a);
+}
+#endif
+
+/*
+ * kl_print_uint4()
+ */
+void
+kl_print_uint4(void *ptr, int flags)
+{
+       uint32_t a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        * dump core)
+        */
+       if (align_chk && (uaddr_t)ptr % 4) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(uint32_t*) ptr;
+       if (flags & C_HEX) {
+               kdb_printf("0x%x", a);
+       } else if (flags & C_BINARY) {
+               uint64_t value = a & 0xffffffff;
+               kdb_printf("0b");
+               kl_binary_print(value);
+       } else {
+               kdb_printf("%u", a);
+       }
+}
+
+/*
+ * kl_print_int2()
+ */
+void
+kl_print_int2(void *ptr, int flags)
+{
+       int16_t a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        * dump core
+        */
+       if (align_chk && (uaddr_t)ptr % 2) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(int16_t*) ptr;
+       if (flags & C_HEX) {
+               kdb_printf("0x%hx", a);
+       } else if (flags & C_BINARY) {
+               uint64_t value = a & 0xffff;
+               kdb_printf("0b");
+               kl_binary_print(value);
+       } else {
+               kdb_printf("%hd", a);
+       }
+}
+
+/*
+ * kl_print_uint2()
+ */
+void
+kl_print_uint2(void *ptr, int flags)
+{
+       uint16_t a;
+
+       /* Make sure the pointer is properly aligned (or we will
+        * dump core
+        */
+       if (align_chk && (uaddr_t)ptr % 2) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       a = *(uint16_t*) ptr;
+       if (flags & C_HEX) {
+               kdb_printf("0x%hx", a);
+       } else if (flags & C_BINARY) {
+               uint64_t value = a & 0xffff;
+               kdb_printf("0b");
+               kl_binary_print(value);
+       } else {
+               kdb_printf("%hu", a);
+       }
+}
+
+/*
+ * kl_print_char()
+ */
+void
+kl_print_char(void *ptr, int flags)
+{
+       char c;
+
+       if (flags & C_HEX) {
+               kdb_printf("0x%x", (*(char *)ptr) & 0xff);
+       } else if (flags & C_BINARY) {
+               uint64_t value = (*(char *)ptr) & 0xff;
+               kdb_printf("0b");
+               kl_binary_print(value);
+       } else {
+               c = *(char *)ptr;
+
+               kdb_printf("\'\\%03o\'", (unsigned char)c);
+               switch (c) {
+                       case '\a' :
+                               kdb_printf(" = \'\\a\'");
+                               break;
+                       case '\b' :
+                               kdb_printf(" = \'\\b\'");
+                               break;
+                       case '\t' :
+                               kdb_printf(" = \'\\t\'");
+                               break;
+                       case '\n' :
+                               kdb_printf(" = \'\\n\'");
+                               break;
+                       case '\f' :
+                               kdb_printf(" = \'\\f\'");
+                               break;
+                       case '\r' :
+                               kdb_printf(" = \'\\r\'");
+                               break;
+                       case '\e' :
+                               kdb_printf(" = \'\\e\'");
+                               break;
+                       default :
+                               if( !iscntrl((unsigned char) c) ) {
+                                       kdb_printf(" = \'%c\'", c);
+                               }
+                               break;
+               }
+       }
+}
+
+/*
+ * kl_print_uchar()
+ */
+void
+kl_print_uchar(void *ptr, int flags)
+{
+       if (flags & C_HEX) {
+               kdb_printf("0x%x", *(unsigned char *)ptr);
+       } else if (flags & C_BINARY) {
+               uint64_t value = (*(unsigned char *)ptr) & 0xff;
+               kdb_printf("0b");
+               kl_binary_print(value);
+       } else {
+               kdb_printf("%u", *(unsigned char *)ptr);
+       }
+}
+
+/*
+ * kl_print_base()
+ */
+void
+kl_print_base(void *ptr, int size, int encoding, int flags)
+{
+       /* FIXME: untested */
+       if (invalid_address((kaddr_t)ptr, size)) {
+               kdb_printf("ILLEGAL ADDRESS (%lx)", (uaddr_t)ptr);
+               return;
+       }
+       switch (size) {
+
+               case 1:
+                       if (encoding == ENC_UNSIGNED) {
+                               kl_print_uchar(ptr, flags);
+                       } else {
+                               kl_print_char(ptr, flags);
+                       }
+                       break;
+
+               case 2:
+                       if (encoding == ENC_UNSIGNED) {
+                               kl_print_uint2(ptr, flags);
+                       } else {
+                               kl_print_int2(ptr, flags);
+                       }
+                       break;
+
+               case 4:
+                       if (encoding == ENC_UNSIGNED) {
+                               kl_print_uint4(ptr, flags);
+                       } else if (encoding == ENC_FLOAT) {
+                               printk("error: print of 4-byte float\n");
+                               /* kl_print_float4(ptr, flags); */
+                       } else {
+                               kl_print_int4(ptr, flags);
+                       }
+                       break;
+
+               case 8:
+                       if (encoding == ENC_UNSIGNED) {
+                               kl_print_uint8(ptr, flags);
+                       } else if (encoding == ENC_FLOAT) {
+                               printk("error: print of 8-byte float\n");
+                               /* kl_print_float8(ptr, flags); */
+                       } else {
+                               kl_print_int8(ptr, flags);
+                       }
+                       break;
+
+               case 16:
+                       if (encoding == ENC_UNSIGNED) {
+                               /* Ex: unsigned long long */
+                               kl_print_uint16(ptr, flags);
+                       } else if (encoding == ENC_FLOAT) {
+                               printk("error: print of 16-byte float\n");
+                               /* Ex: long double */
+                               /* kl_print_float16(ptr, flags); */
+                       } else {
+                               /* Ex: long long */
+                               kl_print_int16(ptr, flags);
+                       }
+                       break;
+
+               default:
+                       break;
+       }
+}
+
+/*
+ * kl_print_base_value()
+ */
+void
+kl_print_base_value(void *ptr, kltype_t *kltp, int flags)
+{
+       kltype_t *rkltp=NULL;
+
+       if (kltp->kl_type != KLT_BASE) {
+               if (!(rkltp = kltp->kl_realtype)) {
+                       return;
+               }
+               if (rkltp->kl_type != KLT_BASE) {
+                       return;
+               }
+       } else {
+               rkltp = kltp;
+       }
+       kl_print_base(ptr, rkltp->kl_size, rkltp->kl_encoding, flags);
+}
+
+/*
+ * kl_print_typedef_type()
+ */
+void
+kl_print_typedef_type(
+       void *ptr,
+       kltype_t *kltp,
+       int level,
+       int flags)
+{
+       char *name;
+       kltype_t *rkltp;
+
+       if (ptr) {
+               rkltp = kltp->kl_realtype;
+               while (rkltp->kl_type == KLT_TYPEDEF) {
+                       if (rkltp->kl_realtype) {
+                               rkltp = rkltp->kl_realtype;
+                       }
+               }
+               if (rkltp->kl_type == KLT_POINTER) {
+                       kl_print_pointer_type(ptr, kltp, level, flags);
+                       return;
+               }
+               switch (rkltp->kl_type) {
+                       case KLT_BASE:
+                               kl_print_base_type(ptr, kltp,
+                                       level, flags);
+                               break;
+
+                       case KLT_UNION:
+                       case KLT_STRUCT:
+                               kl_print_struct_type(ptr, kltp,
+                                       level, flags);
+                               break;
+
+                       case KLT_ARRAY:
+                               kl_print_array_type(ptr, kltp,
+                                       level, flags);
+                               break;
+
+                       case KLT_ENUMERATION:
+                               kl_print_enumeration_type(ptr,
+                                       kltp, level, flags);
+                               break;
+
+                       default:
+                               kl_print_base_type(ptr, kltp,
+                                       level, flags);
+                               break;
+               }
+       } else {
+               LEVEL_INDENT(level, flags);
+               if (flags & NO_REALTYPE) {
+                       rkltp = kltp;
+               } else {
+                       rkltp = kltp->kl_realtype;
+                       while (rkltp && rkltp->kl_type == KLT_POINTER) {
+                               rkltp = rkltp->kl_realtype;
+                       }
+               }
+               if (!rkltp) {
+                       if (SUPPRESS_NAME) {
+                               kdb_printf("<UNKNOWN>");
+                       } else {
+                               kdb_printf( "typedef <UNKNOWN>%s;",
+                                       kltp->kl_name);
+                       }
+                       return;
+               }
+               if (rkltp->kl_type == KLT_FUNCTION) {
+                       if (kltp->kl_realtype->kl_type == KLT_POINTER) {
+                               kdb_printf("typedef %s(*%s)();",
+                                       kltp->kl_typestr, kltp->kl_name);
+                       } else {
+                               kdb_printf( "typedef %s(%s)();",
+                                       kltp->kl_typestr, kltp->kl_name);
+                       }
+               } else if (rkltp->kl_type == KLT_ARRAY) {
+                       kl_print_array_type(ptr, rkltp, level, flags);
+               } else if (rkltp->kl_type == KLT_TYPEDEF) {
+                       if (!(name = rkltp->kl_name)) {
+                               name = rkltp->kl_typestr;
+                       }
+
+                       if (SUPPRESS_NAME) {
+                               kdb_printf("%s", name);
+                       } else {
+                               kdb_printf("typedef %s%s;",
+                                       name, kltp->kl_name);
+                       }
+                       print_realtype(rkltp);
+               } else {
+                       kl_print_type(ptr, rkltp, level, flags);
+               }
+               PRINT_NL(flags);
+       }
+}
+
+/*
+ * kl_print_pointer_type()
+ */
+void
+kl_print_pointer_type(
+       void *ptr,
+       kltype_t *kltp,
+       int level,
+       int flags)
+{
+       kltype_t *itp;
+
+       if (kltp->kl_type == KLT_MEMBER) {
+               itp = kltp->kl_realtype;
+       } else {
+               itp = kltp;
+       }
+
+       /* See if this is a pointer to a function. If it is, then it
+        * has to be handled differently...
+        */
+       while (itp->kl_type == KLT_POINTER) {
+               if ((itp = itp->kl_realtype)) {
+                       if (itp->kl_type == KLT_FUNCTION) {
+                               kl_print_function_type(ptr,
+                                       kltp, level, flags);
+                               return;
+                       }
+               } else {
+                       LEVEL_INDENT(level, flags);
+                       kdb_printf("%s%s;\n",
+                               kltp->kl_typestr, kltp->kl_name);
+                       return;
+               }
+       }
+
+       LEVEL_INDENT(level, flags);
+       if (ptr) {
+               kaddr_t tmp;
+               tmp = *(kaddr_t *)ptr;
+               flags |= SUPPRESS_SEMI_COLON;
+               if(kltp->kl_name){
+                       if (*(kaddr_t *)ptr) {
+                               kdb_printf("%s = 0x%"FMTPTR"x",
+                                       kltp->kl_name, tmp);
+                       } else {
+                               kdb_printf("%s = (nil)", kltp->kl_name);
+                       }
+               } else {
+                       if (tmp != 0) {
+                               kdb_printf("0x%"FMTPTR"x", tmp);
+                       } else {
+                               kdb_printf( "(nil)");
+                       }
+               }
+       } else {
+               if (kltp->kl_typestr) {
+                       if (kltp->kl_name && !(flags & SUPPRESS_NAME)) {
+                               kdb_printf("%s%s",
+                                       kltp->kl_typestr, kltp->kl_name);
+                       } else {
+                               kdb_printf("%s", kltp->kl_typestr);
+                       }
+               } else {
+                       kdb_printf("<UNKNOWN>");
+               }
+       }
+       PRINT_SEMI_COLON(level, flags);
+       PRINT_NL(flags);
+}
+
+/*
+ * kl_print_function_type()
+ */
+void
+kl_print_function_type(
+       void *ptr,
+       kltype_t *kltp,
+       int level,
+       int flags)
+{
+       LEVEL_INDENT(level, flags);
+       if (ptr) {
+               kaddr_t a;
+
+               a = *(kaddr_t *)ptr;
+               kdb_printf("%s = 0x%"FMTPTR"x", kltp->kl_name, a);
+       } else {
+               if (flags & SUPPRESS_NAME) {
+                       kdb_printf("%s(*)()", kltp->kl_typestr);
+               } else {
+                       kdb_printf("%s(*%s)();",
+                               kltp->kl_typestr, kltp->kl_name);
+               }
+       }
+       PRINT_NL(flags);
+}
+
+/*
+ * kl_print_array_type()
+ */
+void
+kl_print_array_type(void *ptr, kltype_t *kltp, int level, int flags)
+{
+       int i, count = 0, anon = 0, size, low, high, multi = 0;
+       char typestr[128], *name, *p;
+       kltype_t *rkltp, *etp, *retp;
+
+       if (kltp->kl_type != KLT_ARRAY) {
+               if ((rkltp = kltp->kl_realtype)) {
+                       while (rkltp->kl_type != KLT_ARRAY) {
+                               if (!(rkltp = rkltp->kl_realtype)) {
+                                       break;
+                               }
+                       }
+               }
+               if (!rkltp) {
+                       LEVEL_INDENT(level, flags);
+                       kdb_printf("<ARRAY_TYPE>");
+                       PRINT_SEMI_COLON(level, flags);
+                       PRINT_NL(flags);
+                       return;
+               }
+       } else {
+               rkltp = kltp;
+       }
+
+       etp = rkltp->kl_elementtype;
+       if (!etp) {
+               LEVEL_INDENT(level, flags);
+               kdb_printf("<BAD_ELEMENT_TYPE> %s", rkltp->kl_name);
+               PRINT_SEMI_COLON(level, flags);
+               PRINT_NL(flags);
+               return;
+       }
+
+       /* Set retp to point to the actual element type. This is necessary
+        * for multi-dimensional arrays, which link using the kl_elementtype
+        * member.
+        */
+       retp = etp;
+       while (retp->kl_type == KLT_ARRAY) {
+               retp = retp->kl_elementtype;
+       }
+       low = rkltp->kl_low_bounds + 1;
+       high = rkltp->kl_high_bounds;
+
+       if (ptr) {
+
+               p = ptr;
+
+               if ((retp->kl_size == 1) && (retp->kl_encoding == ENC_CHAR)) {
+                       if (kltp->kl_type == KLT_MEMBER) {
+                               LEVEL_INDENT(level, flags);
+                       }
+                       if (flags & SUPPRESS_NAME) {
+                               kdb_printf("\"");
+                               flags &= ~SUPPRESS_NAME;
+                       } else {
+                               kdb_printf("%s = \"", kltp->kl_name);
+                       }
+                       for (i = 0; i < high; i++) {
+                               if (*(char*)p == 0) {
+                                       break;
+                               }
+                               kdb_printf("%c", *(char *)p);
+                               p++;
+                       }
+                       kdb_printf("\"");
+                       PRINT_NL(flags);
+               } else {
+                       if (kltp->kl_type == KLT_MEMBER) {
+                               LEVEL_INDENT(level, flags);
+                       }
+
+                       if (flags & SUPPRESS_NAME) {
+                               kdb_printf("{\n");
+                               flags &= ~SUPPRESS_NAME;
+                       } else {
+                               kdb_printf("%s = {\n", kltp->kl_name);
+                       }
+
+                       if (retp->kl_type == KLT_POINTER) {
+                               size = sizeof(void *);
+                       } else {
+                               while (retp->kl_realtype) {
+                                       retp = retp->kl_realtype;
+                               }
+                               size = retp->kl_size;
+                       }
+                       if ((retp->kl_type != KLT_STRUCT) &&
+                                       (retp->kl_type != KLT_UNION)) {
+                               /* Turn off the printing of names for all
+                                * but structs and unions.
+                                */
+                               flags |= SUPPRESS_NAME;
+                       }
+                       for (i = low; i <= high; i++) {
+
+                               LEVEL_INDENT(level + 1, flags);
+                               kdb_printf("[%d] ", i);
+
+                               switch (retp->kl_type) {
+                                       case KLT_POINTER :
+                                               kl_print_pointer_type(
+                                                       p, retp, level,
+                                                       flags|NO_INDENT);
+                                               break;
+
+                                       case KLT_TYPEDEF:
+                                               kl_print_typedef_type(
+                                                       p, retp, level,
+                                                       flags|NO_INDENT);
+                                               break;
+
+                                       case KLT_BASE:
+                                               kl_print_base_value(p,
+                                                       retp, flags|NO_INDENT);
+                                               kdb_printf("\n");
+                                               break;
+
+                                       case KLT_ARRAY:
+                                               kl_print_array_type(p, retp,
+                                                       level + 1,
+                                                       flags|SUPPRESS_NAME);
+                                               break;
+
+                                       case KLT_STRUCT:
+                                       case KLT_UNION:
+                                               kl_print_struct_type(p,
+                                                       retp, level + 1,
+                                                       flags|NO_INDENT);
+                                               break;
+
+                                       default:
+                                               kl_print_base_value(
+                                                       p, retp,
+                                                       flags|NO_INDENT);
+                                               kdb_printf("\n");
+                                               break;
+                               }
+                               p = (void *)((uaddr_t)p + size);
+                       }
+                       LEVEL_INDENT(level, flags);
+                       kdb_printf("}");
+                       PRINT_SEMI_COLON(level, flags);
+                       PRINT_NL(flags);
+               }
+       } else {
+               if (rkltp) {
+                       count = (rkltp->kl_high_bounds -
+                                       rkltp->kl_low_bounds) + 1;
+               } else {
+                       count = 1;
+               }
+
+               if (!strcmp(retp->kl_typestr, "struct ") ||
+                               !strcmp(retp->kl_typestr, "union ")) {
+                       anon = 1;
+               }
+next_dimension:
+               switch (retp->kl_type) {
+
+                        case KLT_UNION:
+                        case KLT_STRUCT:
+                               if (anon) {
+                                       if (multi) {
+                                               kdb_printf("[%d]", count);
+                                               break;
+                                       }
+                                       kl_print_struct_type(ptr, retp, level,
+                                               flags|
+                                               SUPPRESS_NL|
+                                               SUPPRESS_SEMI_COLON);
+                                       if (kltp->kl_type == KLT_MEMBER) {
+                                               kdb_printf(" %s[%d]",
+                                                       kltp->kl_name, count);
+                                       } else {
+                                               kdb_printf(" [%d]", count);
+                                       }
+                                       break;
+                               }
+                               /* else drop through */
+
+                       default:
+                               LEVEL_INDENT(level, flags);
+                               if (multi) {
+                                       kdb_printf("[%d]", count);
+                                       break;
+                               }
+                               name = kltp->kl_name;
+                               if (retp->kl_type == KLT_TYPEDEF) {
+                                       strcpy(typestr, retp->kl_name);
+                                       strcat(typestr, " ");
+                               } else {
+                                       strcpy(typestr, retp->kl_typestr);
+                               }
+                               if (!name || (flags & SUPPRESS_NAME)) {
+                                       kdb_printf("%s[%d]", typestr, count);
+                               } else {
+                                       kdb_printf("%s%s[%d]",
+                                               typestr, name, count);
+                               }
+               }
+               if (etp->kl_type == KLT_ARRAY) {
+                       count = etp->kl_high_bounds - etp->kl_low_bounds + 1;
+                       etp = etp->kl_elementtype;
+                       multi++;
+                       goto next_dimension;
+               }
+               PRINT_SEMI_COLON(level, flags);
+               PRINT_NL(flags);
+       }
+}
+
+/*
+ * kl_print_enumeration_type()
+ */
+void
+kl_print_enumeration_type(
+       void *ptr,
+       kltype_t *kltp,
+       int level,
+       int flags)
+{
+       unsigned long long val = 0;
+       kltype_t *mp, *rkltp;
+
+       rkltp = kl_realtype(kltp, KLT_ENUMERATION);
+       if (ptr) {
+               switch (kltp->kl_size) {
+                       case 1:
+                               val = *(unsigned long long *)ptr;
+                               break;
+
+                       case 2:
+                               val = *(uint16_t *)ptr;
+                               break;
+
+                       case 4:
+                               val = *(uint32_t *)ptr;
+                               break;
+
+                       case 8:
+                               val = *(uint64_t *)ptr;
+                               break;
+               }
+               mp = rkltp->kl_member;
+               while (mp) {
+                       if (mp->kl_value == val) {
+                               break;
+                       }
+                       mp = mp->kl_member;
+               }
+               LEVEL_INDENT(level, flags);
+               if (mp) {
+                       kdb_printf("%s = (%s=%lld)",
+                               kltp->kl_name, mp->kl_name, val);
+               } else {
+                       kdb_printf("%s = %lld", kltp->kl_name, val);
+               }
+               PRINT_NL(flags);
+       } else {
+               LEVEL_INDENT(level, flags);
+               kdb_printf ("%s {", kltp->kl_typestr);
+               mp = rkltp->kl_member;
+               while (mp) {
+                       kdb_printf("%s = %d", mp->kl_name, mp->kl_value);
+                       if ((mp = mp->kl_member)) {
+                               kdb_printf(", ");
+                       }
+               }
+               mp = kltp;
+               if (level) {
+                       kdb_printf("} %s;", mp->kl_name);
+               } else {
+                       kdb_printf("};");
+               }
+               PRINT_NL(flags);
+       }
+}
+
+/*
+ * kl_binary_print()
+ */
+void
+kl_binary_print(uint64_t num)
+{
+       int i, pre = 1;
+
+       for (i = 63; i >= 0; i--) {
+               if (num & ((uint64_t)1 << i)) {
+                       kdb_printf("1");
+                       if (pre) {
+                               pre = 0;
+                       }
+               } else {
+                       if (!pre) {
+                               kdb_printf("0");
+                       }
+               }
+       }
+       if (pre) {
+               kdb_printf("0");
+       }
+}
+
+/*
+ * kl_get_bit_value()
+ *
+ * x = byte_size, y = bit_size, z = bit_offset
+ */
+uint64_t
+kl_get_bit_value(void *ptr, unsigned int x, unsigned int y, unsigned int z)
+{
+       uint64_t value=0, mask;
+
+       /* handle x bytes of buffer -- doing just memcpy won't work
+        * on big endian architectures
+        */
+        switch (x) {
+       case 5:
+       case 6:
+       case 7:
+       case 8:
+               x = 8;
+               value = *(uint64_t*) ptr;
+               break;
+       case 3:
+       case 4:
+               x = 4;
+               value = *(uint32_t*) ptr;
+               break;
+       case 2:
+               value = *(uint16_t*) ptr;
+               break;
+       case 1:
+               value = *(uint8_t *)ptr;
+               break;
+       default:
+               /* FIXME: set KL_ERROR */
+               return(0);
+        }
+       /*
+           o FIXME: correct handling of overlapping fields
+       */
+
+       /* goto bit offset */
+       value = value >> z;
+
+       /* mask bit size bits */
+       mask = (((uint64_t)1 << y) - 1);
+       return (value & mask);
+}
+
+/*
+ * kl_print_bit_value()
+ *
+ * x = byte_size, y = bit_size, z = bit_offset
+ */
+void
+kl_print_bit_value(void *ptr, int x, int y, int z, int flags)
+{
+       unsigned long long value;
+
+       value = kl_get_bit_value(ptr, x, y, z);
+       if (flags & C_HEX) {
+               kdb_printf("%#llx", value);
+       } else if (flags & C_BINARY) {
+               kdb_printf("0b");
+               kl_binary_print(value);
+       } else {
+               kdb_printf("%lld", value);
+       }
+}
+
+/*
+ * kl_print_base_type()
+ */
+void
+kl_print_base_type(void *ptr, kltype_t *kltp, int level, int flags)
+{
+       LEVEL_INDENT(level, flags);
+       if (ptr) {
+               if (!(flags & SUPPRESS_NAME))  {
+                       kdb_printf ("%s = ", kltp->kl_name);
+               }
+       }
+       if (kltp->kl_type == KLT_MEMBER) {
+               if (kltp->kl_bit_size < (kltp->kl_size * 8)) {
+                       if (ptr) {
+                               kl_print_bit_value(ptr, kltp->kl_size,
+                                       kltp->kl_bit_size,
+                                       kltp->kl_bit_offset, flags);
+                       } else {
+                               if (kltp->kl_name) {
+                                       kdb_printf ("%s%s :%d;",
+                                               kltp->kl_typestr,
+                                               kltp->kl_name,
+                                               kltp->kl_bit_size);
+                               } else {
+                                       kdb_printf ("%s :%d;",
+                                               kltp->kl_typestr,
+                                               kltp->kl_bit_size);
+                               }
+                       }
+                       PRINT_NL(flags);
+                       return;
+               }
+       }
+       if (ptr) {
+               kltype_t *rkltp;
+
+               rkltp = kl_realtype(kltp, 0);
+               if (rkltp->kl_encoding == ENC_UNDEFINED) {
+                       /* This is a void value
+                        */
+                       kdb_printf("<VOID>");
+               } else {
+                       kl_print_base(ptr, kltp->kl_size,
+                               rkltp->kl_encoding, flags);
+               }
+       } else {
+               if (kltp->kl_type == KLT_MEMBER) {
+                       if (flags & SUPPRESS_NAME) {
+                               kdb_printf ("%s", kltp->kl_typestr);
+                       } else {
+                               if (kltp->kl_name) {
+                                       kdb_printf("%s%s;", kltp->kl_typestr,
+                                               kltp->kl_name);
+                               } else {
+                                       kdb_printf ("%s :%d;",
+                                               kltp->kl_typestr,
+                                               kltp->kl_bit_size);
+                               }
+                       }
+               } else {
+                       if (SUPPRESS_NAME) {
+                               kdb_printf("%s", kltp->kl_name);
+                       } else {
+                               kdb_printf("%s;", kltp->kl_name);
+                       }
+               }
+       }
+       PRINT_NL(flags);
+}
+
+/*
+ * kl_print_member()
+ */
+void
+kl_print_member(void *ptr, kltype_t *mp, int level, int flags)
+{
+       int kl_type = 0;
+       kltype_t *rkltp;
+
+       if (flags & C_SHOWOFFSET) {
+               kdb_printf("%#x ", mp->kl_offset);
+       }
+
+       if ((rkltp = mp->kl_realtype)) {
+               kl_type = rkltp->kl_type;
+       } else
+               kl_type = mp->kl_type;
+       switch (kl_type) {
+               case KLT_STRUCT:
+               case KLT_UNION:
+                       kl_print_struct_type(ptr, mp, level, flags);
+                       break;
+               case KLT_ARRAY:
+                       kl_print_array_type(ptr, mp, level, flags);
+                       break;
+               case KLT_POINTER:
+                       kl_print_pointer_type(ptr, mp, level, flags);
+                       break;
+               case KLT_FUNCTION:
+                       kl_print_function_type(ptr, mp, level, flags);
+                       break;
+               case KLT_BASE:
+                       kl_print_base_type(ptr, mp, level, flags);
+                       break;
+               case KLT_ENUMERATION:
+                       kl_print_enumeration_type(ptr, mp, level, flags);
+                       break;
+               case KLT_TYPEDEF:
+                       while (rkltp && rkltp->kl_realtype) {
+                               if (rkltp->kl_realtype == rkltp) {
+                                       break;
+                               }
+                               rkltp = rkltp->kl_realtype;
+                       }
+                       if (ptr) {
+                               kl_print_typedef_type(ptr, mp,
+                                       level, flags);
+                               break;
+                       }
+                       LEVEL_INDENT(level, flags);
+                       if (flags & SUPPRESS_NAME) {
+                               if (rkltp && (mp->kl_bit_size <
+                                               (rkltp->kl_size * 8))) {
+                                       kdb_printf ("%s :%d",
+                                               mp->kl_typestr,
+                                               mp->kl_bit_size);
+                               } else {
+                                       kdb_printf("%s",
+                                               mp->kl_realtype->kl_name);
+                               }
+                               print_realtype(mp->kl_realtype);
+                       } else {
+                               if (rkltp && (mp->kl_bit_size <
+                                               (rkltp->kl_size * 8))) {
+                                       if (mp->kl_name) {
+                                               kdb_printf ("%s%s :%d;",
+                                                       mp->kl_typestr,
+                                                       mp->kl_name,
+                                                       mp->kl_bit_size);
+                                       } else {
+                                               kdb_printf ("%s :%d;",
+                                                       mp->kl_typestr,
+                                                       mp->kl_bit_size);
+                                       }
+                               } else {
+                                       kdb_printf("%s %s;",
+                                               mp->kl_realtype->kl_name,
+                                               mp->kl_name);
+                               }
+                       }
+                       PRINT_NL(flags);
+                       break;
+
+               default:
+                       LEVEL_INDENT(level, flags);
+                       if (mp->kl_typestr) {
+                               kdb_printf("%s%s;",
+                                       mp->kl_typestr, mp->kl_name);
+                       } else {
+                               kdb_printf("<\?\?\? kl_type:%d> %s;",
+                                       kl_type, mp->kl_name);
+                       }
+                       PRINT_NL(flags);
+                       break;
+       }
+}
+
+/*
+ * kl_print_struct_type()
+ */
+void
+kl_print_struct_type(void *buf, kltype_t *kltp, int level, int flags)
+{
+       int orig_flags = flags;
+       void *ptr = NULL;
+       kltype_t *mp, *rkltp;
+
+       /* If we are printing out an actual struct, then don't print any
+        * semi colons.
+        */
+       if (buf) {
+               flags |= SUPPRESS_SEMI_COLON;
+       }
+
+       LEVEL_INDENT(level, flags);
+       if ((level == 0) || (flags & NO_INDENT)) {
+               kdb_printf("%s{\n", kltp->kl_typestr);
+       } else {
+               if (buf) {
+                       if (level && !(kltp->kl_flags & TYP_ANONYMOUS_FLG)) {
+                               kdb_printf("%s = %s{\n",
+                                       kltp->kl_name, kltp->kl_typestr);
+                       } else {
+                               kdb_printf("%s{\n", kltp->kl_typestr);
+                       }
+                       flags &= (~SUPPRESS_NL);
+               } else {
+                       if (kltp->kl_typestr) {
+                               kdb_printf("%s{\n", kltp->kl_typestr);
+                       } else {
+                               kdb_printf("<UNKNOWN> {\n");
+                       }
+               }
+       }
+
+       /* If the SUPPRESS_NL, SUPPRESS_SEMI_COLON, and SUPPRESS_NAME flags
+        * are set and buf is NULL, then turn them off as they only apply
+        * at the end of the struct. We save the original flags for that
+        * purpose.
+        */
+       if (!buf) {
+               flags &= ~(SUPPRESS_NL|SUPPRESS_SEMI_COLON|SUPPRESS_NAME);
+       }
+
+       /* If the NO_INDENT is set, we need to turn it off at this
+        * point -- just in case we come across a member of this struct
+        * that is also a struct.
+        */
+       if (flags & NO_INDENT) {
+               flags &= ~(NO_INDENT);
+       }
+
+       if (kltp->kl_type == KLT_MEMBER) {
+               rkltp = kl_realtype(kltp, 0);
+       } else {
+               rkltp = kltp;
+       }
+       level++;
+       if ((mp = rkltp->kl_member)) {
+               while (mp) {
+                       if (buf) {
+                               ptr = buf + mp->kl_offset;
+                       }
+                       kl_print_member(ptr, mp, level, flags);
+                       mp = mp->kl_member;
+               }
+       } else {
+               if (kltp->kl_flags & TYP_INCOMPLETE_FLG) {
+                       LEVEL_INDENT(level, flags);
+                       kdb_printf("<INCOMPLETE TYPE>\n");
+               }
+       }
+       level--;
+       LEVEL_INDENT(level, flags);
+
+       /* kl_size = 0 for empty structs */
+       if (ptr || ((kltp->kl_size == 0) && buf)) {
+               kdb_printf("}");
+       } else if ((kltp->kl_type == KLT_MEMBER) &&
+                       !(orig_flags & SUPPRESS_NAME) &&
+                       !(kltp->kl_flags & TYP_ANONYMOUS_FLG)) {
+               kdb_printf("} %s", kltp->kl_name);
+       } else {
+               kdb_printf("}");
+       }
+       PRINT_SEMI_COLON(level, orig_flags);
+       PRINT_NL(orig_flags);
+}
+
+/*
+ * kl_print_type()
+ */
+void
+kl_print_type(void *buf, kltype_t *kltp, int level, int flags)
+{
+       void *ptr;
+
+       if (buf) {
+               if (kltp->kl_offset) {
+                       ptr = (void *)((uaddr_t)buf + kltp->kl_offset);
+               } else {
+                       ptr = buf;
+               }
+       } else {
+               ptr = 0;
+       }
+
+       /* Only allow binary printing for base types
+        */
+       if (kltp->kl_type != KLT_BASE) {
+               flags &= (~C_BINARY);
+       }
+       switch (kltp->kl_type) {
+
+               case KLT_TYPEDEF:
+                       kl_print_typedef_type(ptr, kltp, level, flags);
+                       break;
+
+               case KLT_STRUCT:
+               case KLT_UNION:
+                       kl_print_struct_type(ptr, kltp, level, flags);
+                       break;
+
+               case KLT_MEMBER:
+                       kl_print_member(ptr, kltp, level, flags);
+                       break;
+
+               case KLT_POINTER:
+                       kl_print_pointer_type(ptr, kltp, level, flags);
+                       break;
+
+               case KLT_FUNCTION:
+                       LEVEL_INDENT(level, flags);
+                       kl_print_function_type(ptr, kltp, level, flags);
+                       break;
+
+               case KLT_ARRAY:
+                       kl_print_array_type(ptr, kltp, level, flags);
+                       break;
+
+               case KLT_ENUMERATION:
+                       kl_print_enumeration_type(ptr,
+                               kltp, level, flags);
+                       break;
+
+               case KLT_BASE:
+                       kl_print_base_type(ptr, kltp, level, flags);
+                       break;
+
+               default:
+                       LEVEL_INDENT(level, flags);
+                       if (flags & SUPPRESS_NAME) {
+                               kdb_printf ("%s", kltp->kl_name);
+                       } else {
+                               kdb_printf ("%s %s;",
+                                       kltp->kl_name, kltp->kl_name);
+                       }
+                       PRINT_NL(flags);
+       }
+}
+
+/*
+ * eval is from lcrash eval.c
+ */
+
+/* Forward declarations */
+static void free_node(node_t *);
+static node_t *make_node(token_t *, int);
+static node_t *get_node_list(token_t *, int);
+static node_t *do_eval(int);
+static int is_unary(int);
+static int is_binary(int);
+static int precedence(int);
+static node_t *get_sizeof(void);
+static int replace_cast(node_t *, int);
+static int replace_unary(node_t *, int);
+static node_t *replace(node_t *, int);
+static void array_to_element(node_t*, node_t*);
+static int type_to_number(node_t *);
+kltype_t *number_to_type(node_t *);
+static type_t *eval_type(node_t *);
+static type_t *get_type(char *, int);
+static int add_rchild(node_t *, node_t *);
+static void free_nodelist(node_t *);
+
+/* Global variables
+ */
+static int logical_flag;
+static node_t *node_list = (node_t *)NULL;
+uint64_t eval_error;
+char *error_token;
+
+/*
+ * set_eval_error()
+ */
+static void
+set_eval_error(uint64_t ecode)
+{
+       eval_error = ecode;
+}
+
+/*
+ * is_typestr()
+ *
+ * We check for "struct", "union", etc. separately because they
+ * would not be an actual part of the type name. We also assume
+ * that the string passed in
+ *
+ * - does not have any leading blanks or tabs
+ * - is NULL terminated
+ * - contains only one type name to check
+ * - does not contain any '*' characters
+ */
+static int
+is_typestr(char *str)
+{
+       int len;
+
+       len = strlen(str);
+       if ((len >= 6) && !strncmp(str, "struct", 6)) {
+               return(1);
+       } else if ((len >= 5) &&!strncmp(str, "union", 5)) {
+               return(1);
+       } else if ((len >= 5) &&!strncmp(str, "short", 5)) {
+               return(1);
+       } else if ((len >= 8) &&!strncmp(str, "unsigned", 8)) {
+               return(1);
+       } else if ((len >= 6) &&!strncmp(str, "signed", 6)) {
+               return(1);
+       } else if ((len >= 4) &&!strncmp(str, "long", 4)) {
+               return(1);
+       }
+       /* Strip off any trailing blanks
+        */
+       while(*str && ((str[strlen(str) - 1] == ' ')
+                       || (str[strlen(str) - 1] == '\t'))) {
+               str[strlen(str) - 1] = 0;
+       }
+       if (kl_find_type(str, KLT_TYPES)) {
+               return (1);
+       }
+       return(0);
+}
+
+/*
+ * free_tokens()
+ */
+static void
+free_tokens(token_t *tp)
+{
+       token_t *t, *tnext;
+
+       t = tp;
+       while (t) {
+               tnext = t->next;
+               if (t->string) {
+                       kl_free_block((void *)t->string);
+               }
+               kl_free_block((void *)t);
+               t = tnext;
+       }
+}
+
+/*
+ * process_text()
+ */
+static int
+process_text(char **str, token_t *tok)
+{
+       char *cp = *str;
+       char *s = NULL;
+       int len = 0;
+
+       /* Check and see if this token is a STRING or CHARACTER
+        * type (beginning with a single or double quote).
+        */
+       if (*cp == '\'') {
+               /* make sure that only a single character is between
+                * the single quotes (it can be an escaped character
+                * too).
+                */
+               s = strpbrk((cp + 1), "\'");
+               if (!s) {
+                       set_eval_error(E_SINGLE_QUOTE);
+                       error_token = tok->ptr;
+                       return(1);
+               }
+               len = (uaddr_t)s - (uaddr_t)cp;
+               if ((*(cp+1) == '\\')) {
+                       if (*(cp+2) == '0') {
+                               long int val;
+                               unsigned long uval;
+                               char *ep;
+
+                               uval = kl_strtoull((char*)(cp+2),
+                                               (char **)&ep, 8);
+                               val = uval;
+                               if ((val > 255) || (*ep != '\'')) {
+                                       set_eval_error(E_BAD_CHAR);
+                                       error_token = tok->ptr;
+                                       return(1);
+                               }
+                       } else if (*(cp+3) != '\'') {
+                               set_eval_error(E_BAD_CHAR);
+                               error_token = tok->ptr;
+                               return(1);
+                       }
+                       tok->type = CHARACTER;
+               } else if (len == 2) {
+                       tok->type = CHARACTER;
+               } else {
+
+                       /* Treat as a single token entry. It's possible
+                        * that what's between the single quotes is a
+                        * type name. That will be determined later on.
+                        */
+                       tok->type = STRING;
+               }
+               *str = cp + len;
+       } else if (*cp == '\"') {
+               s = strpbrk((cp + 1), "\"");
+               if (!s) {
+                       set_eval_error(E_BAD_STRING);
+                       error_token = tok->ptr;
+                       return(1);
+               }
+               len = (uaddr_t)s - (uaddr_t)cp;
+               tok->type = TEXT;
+               *str = cp + len;
+       }
+       if ((tok->type == STRING) || (tok->type == TEXT)) {
+
+               if ((tok->type == TEXT) && (strlen(cp) > (len + 1))) {
+
+                       /* Check to see if there is a comma or semi-colon
+                        * directly following the string. If there is,
+                        * then the string is OK (the following characters
+                        * are part of the next expression). Also, it's OK
+                        * to have trailing blanks as long as that's all
+                        * threre is.
+                        */
+                       char *c;
+
+                       c = s + 1;
+                       while (*c) {
+                               if ((*c == ',') || (*c == ';')) {
+                                       break;
+                               } else if (*c != ' ') {
+                                       set_eval_error(E_END_EXPECTED);
+                                       tok->ptr = c;
+                                       error_token = tok->ptr;
+                                       return(1);
+                               }
+                               c++;
+                       }
+                       /* Truncate the trailing blanks (they are not
+                        * part of the string).
+                        */
+                       if (c != (s + 1)) {
+                               *(s + 1) = 0;
+                       }
+               }
+               tok->string = (char *)kl_alloc_block(len);
+               memcpy(tok->string, (cp + 1), len - 1);
+               tok->string[len - 1] = 0;
+       }
+       return(0);
+}
+
+/*
+ * get_token_list()
+ */
+static token_t *
+get_token_list(char *str)
+{
+       int paren_count = 0;
+       char *cp;
+       token_t *tok = (token_t*)NULL, *tok_head = (token_t*)NULL;
+       token_t *tok_last = (token_t*)NULL;
+
+       cp = str;
+       eval_error = 0;
+
+       while (*cp) {
+
+               /* Skip past any "white space" (spaces and tabs).
+                */
+               switch (*cp) {
+                       case ' ' :
+                       case '\t' :
+                       case '`' :
+                               cp++;
+                               continue;
+                       default :
+                               break;
+               }
+
+               /* Allocate space for the next token */
+               tok = (token_t *)kl_alloc_block(sizeof(token_t));
+               tok->ptr = cp;
+
+               switch(*cp) {
+
+                       /* Check for operators
+                        */
+                       case '+' :
+                               if (*((char*)cp + 1) == '+') {
+
+                                       /* We aren't doing asignment here,
+                                        * so the ++ operator is not
+                                        * considered valid.
+                                        */
+                                       set_eval_error(E_BAD_OPERATOR);
+                                       error_token = tok_last->ptr;
+                                       free_tokens(tok_head);
+                                       free_tokens(tok);
+                                       return ((token_t*)NULL);
+                               } else if (!tok_last ||
+                                       (tok_last->operator &&
+                                       (tok_last->operator != CLOSE_PAREN))) {
+                                       tok->operator = UNARY_PLUS;
+                               } else {
+                                       tok->operator = ADD;
+                               }
+                               break;
+
+                       case '-' :
+                               if (*((char*)cp + 1) == '-') {
+
+                                       /* We aren't doing asignment here, so
+                                        * the -- operator is not considered
+                                        * valid.
+                                        */
+                                       set_eval_error(E_BAD_OPERATOR);
+                                       error_token = tok_last->ptr;
+                                       free_tokens(tok_head);
+                                       free_tokens(tok);
+                                       return ((token_t*)NULL);
+                               } else if (*((char*)cp + 1) == '>') {
+                                       tok->operator = RIGHT_ARROW;
+                                       cp++;
+                               } else if (!tok_last || (tok_last->operator &&
+                                       (tok_last->operator != CLOSE_PAREN))) {
+                                       tok->operator = UNARY_MINUS;
+                               } else {
+                                       tok->operator = SUBTRACT;
+                               }
+                               break;
+
+                       case '.' :
+                               /* XXX - need to check to see if this is a
+                                * decimal point in the middle fo a floating
+                                * point value.
+                                */
+                               tok->operator = DOT;
+                               break;
+
+                       case '*' :
+                               /* XXX - need a better way to tell if this is
+                                * an INDIRECTION. perhaps check the next
+                                * token?
+                                */
+                               if (!tok_last || (tok_last->operator &&
+                                       ((tok_last->operator != CLOSE_PAREN) &&
+                                       (tok_last->operator != CAST)))) {
+                                       tok->operator = INDIRECTION;
+                               } else {
+                                       tok->operator = MULTIPLY;
+                               }
+                               break;
+
+                       case '/' :
+                               tok->operator = DIVIDE;
+                               break;
+
+                       case '%' :
+                               tok->operator = MODULUS;
+                               break;
+
+                       case '(' : {
+                               char *s, *s1, *s2;
+                               int len;
+
+                               /* Make sure the previous token is an operator
+                                */
+                               if (tok_last && !tok_last->operator) {
+                                       set_eval_error(E_SYNTAX_ERROR);
+                                       error_token = tok_last->ptr;
+                                       free_tokens(tok_head);
+                                       free_tokens(tok);
+                                       return ((token_t*)NULL);
+                               }
+
+                               if (tok_last &&
+                                       ((tok_last->operator == RIGHT_ARROW) ||
+                                               (tok_last->operator == DOT))) {
+                                       set_eval_error(E_SYNTAX_ERROR);
+                                       error_token = tok_last->ptr;
+                                       free_tokens(tok_head);
+                                       free_tokens(tok);
+                                       return ((token_t*)NULL);
+                               }
+
+                               /* Check here to see if following tokens
+                                * constitute a cast.
+                                */
+
+                               /* Skip past any "white space" (spaces
+                                * and tabs)
+                                */
+                               while ((*(cp+1) == ' ') || (*(cp+1) == '\t')) {
+                                       cp++;
+                               }
+                               if ((*(cp+1) == '(') || isdigit(*(cp+1)) ||
+                                       (*(cp+1) == '+') || (*(cp+1) == '-') ||
+                                       (*(cp+1) == '*') || (*(cp+1) == '&') ||
+                                               (*(cp+1) == ')')){
+                                       tok->operator = OPEN_PAREN;
+                                       paren_count++;
+                                       break;
+                               }
+
+                               /* Make sure we have a CLOSE_PAREN.
+                                */
+                               if (!(s1 = strchr(cp+1, ')'))) {
+                                       set_eval_error(E_OPEN_PAREN);
+                                       error_token = tok->ptr;
+                                       free_tokens(tok_head);
+                                       free_tokens(tok);
+                                       return ((token_t*)NULL);
+                               }
+                               /* Check to see if this is NOT a simple
+                                * typecast.
+                                */
+                               if (!(s2 = strchr(cp+1, '.'))) {
+                                       s2 = strstr(cp+1, "->");
+                               }
+                               if (s2 && (s2 < s1)) {
+                                       tok->operator = OPEN_PAREN;
+                                       paren_count++;
+                                       break;
+                               }
+
+                               if ((s = strpbrk(cp+1, "*)"))) {
+                                       char str[128];
+
+                                       len = (uaddr_t)s - (uaddr_t)(cp+1);
+                                       strncpy(str, cp+1, len);
+                                       str[len] = 0;
+                                       if (!is_typestr(str)) {
+                                               set_eval_error(E_BAD_TYPE);
+                                               error_token = tok->ptr;
+                                               free_tokens(tok_head);
+                                               free_tokens(tok);
+                                               return ((token_t*)NULL);
+                                       }
+                                       if (!(s = strpbrk((cp+1), ")"))) {
+                                               set_eval_error(E_OPEN_PAREN);
+                                               error_token = tok->ptr;
+                                               free_tokens(tok_head);
+                                               free_tokens(tok);
+                                               return ((token_t*)NULL);
+                                       }
+                                       len = (uaddr_t)s - (uaddr_t)(cp+1);
+                                       tok->string = (char *)
+                                               kl_alloc_block(len + 1);
+                                       memcpy(tok->string, (cp+1), len);
+                                       tok->string[len] = 0;
+                                       tok->operator = CAST;
+                                       cp = (char *)((uaddr_t)(cp+1) + len);
+                                       break;
+                               }
+                               tok->operator = OPEN_PAREN;
+                               paren_count++;
+                               break;
+                       }
+
+                       case ')' :
+                               if (tok_last && ((tok_last->operator ==
+                                               RIGHT_ARROW) ||
+                                               (tok_last->operator == DOT))) {
+                                       set_eval_error(E_SYNTAX_ERROR);
+                                       error_token = tok_last->ptr;
+                                       free_tokens(tok_head);
+                                       free_tokens(tok);
+                                       return ((token_t*)NULL);
+                               }
+                               tok->operator = CLOSE_PAREN;
+                               paren_count--;
+                               break;
+
+                       case '&' :
+                               if (*((char*)cp + 1) == '&') {
+                                       tok->operator = LOGICAL_AND;
+                                       cp++;
+                               } else if (!tok_last || (tok_last &&
+                                       (tok_last->operator &&
+                                               tok_last->operator !=
+                                               CLOSE_PAREN))) {
+                                       tok->operator = ADDRESS;
+                               } else {
+                                       tok->operator = BITWISE_AND;
+                               }
+                               break;
+
+                       case '|' :
+                               if (*((char*)cp + 1) == '|') {
+                                       tok->operator = LOGICAL_OR;
+                                       cp++;
+                               } else {
+                                       tok->operator = BITWISE_OR;
+                               }
+                               break;
+
+                       case '=' :
+                               if (*((char*)cp + 1) == '=') {
+                                       tok->operator = EQUAL;
+                                       cp++;
+                               } else {
+                                       /* ASIGNMENT -- NOT IMPLEMENTED
+                                        */
+                                       tok->operator = NOT_YET;
+                               }
+                               break;
+
+                       case '<' :
+                               if (*((char*)cp + 1) == '<') {
+                                       tok->operator = LEFT_SHIFT;
+                                       cp++;
+                               } else if (*((char*)cp + 1) == '=') {
+                                       tok->operator = LESS_THAN_OR_EQUAL;
+                                       cp++;
+                               } else {
+                                       tok->operator = LESS_THAN;
+                               }
+                               break;
+
+                       case '>' :
+                               if (*((char*)(cp + 1)) == '>') {
+                                       tok->operator = RIGHT_SHIFT;
+                                       cp++;
+                               } else if (*((char*)cp + 1) == '=') {
+                                       tok->operator = GREATER_THAN_OR_EQUAL;
+                                       cp++;
+                               } else {
+                                       tok->operator = GREATER_THAN;
+                               }
+                               break;
+
+                       case '!' :
+                               if (*((char*)cp + 1) == '=') {
+                                       tok->operator = NOT_EQUAL;
+                                       cp++;
+                               } else {
+                                       tok->operator = LOGICAL_NEGATION;
+                               }
+                               break;
+
+                       case '$' :
+                               set_eval_error(E_NOT_IMPLEMENTED);
+                               error_token = tok->ptr;
+                               free_tokens(tok_head);
+                               free_tokens(tok);
+                               return((token_t*)NULL);
+                       case '~' :
+                               tok->operator = ONES_COMPLEMENT;
+                               break;
+
+                       case '^' :
+                               tok->operator = BITWISE_EXCLUSIVE_OR;
+                               break;
+
+                       case '?' :
+                               set_eval_error(E_NOT_IMPLEMENTED);
+                               error_token = tok->ptr;
+                               free_tokens(tok_head);
+                               free_tokens(tok);
+                               return((token_t*)NULL);
+                       case ':' :
+                               set_eval_error(E_NOT_IMPLEMENTED);
+                               error_token = tok->ptr;
+                               free_tokens(tok_head);
+                               free_tokens(tok);
+                               return((token_t*)NULL);
+                       case '[' :
+                               tok->operator = OPEN_SQUARE_BRACKET;;
+                               break;
+
+                       case ']' :
+                               tok->operator = CLOSE_SQUARE_BRACKET;;
+                               break;
+
+                       default: {
+
+                               char *s;
+                               int len;
+
+                               /* See if the last token is a RIGHT_ARROW
+                                * or a DOT. If it is, then this token must
+                                * be the name of a struct/union member.
+                                */
+                               if (tok_last &&
+                                       ((tok_last->operator == RIGHT_ARROW) ||
+                                                (tok_last->operator == DOT))) {
+                                       tok->type = MEMBER;
+                               } else if (process_text(&cp, tok)) {
+                                       free_tokens(tok_head);
+                                       free_tokens(tok);
+                                       return((token_t*)NULL);
+                               }
+                               if (tok->type == TEXT) {
+                                       return(tok);
+                               } else if (tok->type == STRING) {
+                                       if (is_typestr(tok->string)) {
+                                               tok->type = TYPE_DEF;
+                                       } else {
+                                               tok->operator = TEXT;
+                                               return(tok);
+                                       }
+                                       break;
+                               } else if (tok->type == CHARACTER) {
+                                       break;
+                               }
+
+                               /* Check and See if the entire string is
+                                * a typename (valid only for whatis case).
+                                */
+                               s = strpbrk(cp,
+                                       ".\t+-*/()[]|~!$&%^<>?:&=^\"\'");
+                               if (!s && !tok->type && is_typestr(cp)) {
+                                       tok->type = TYPE_DEF;
+                                       len = strlen(cp) + 1;
+                                       tok->string = (char *)
+                                               kl_alloc_block(len);
+                                       memcpy(tok->string, cp, len - 1);
+                                       tok->string[len - 1] = 0;
+                                       cp = (char *)((uaddr_t)cp + len - 2);
+                                       break;
+                               }
+
+                               /* Now check for everything else
+                                */
+                               if ((s = strpbrk(cp,
+                                       " .\t+-*/()[]|~!$&%^<>?:&=^\"\'"))) {
+                                       len = (uaddr_t)s - (uaddr_t)cp + 1;
+                               } else {
+                                       len = strlen(cp) + 1;
+                               }
+
+                               tok->string =
+                                       (char *)kl_alloc_block(len);
+                               memcpy(tok->string, cp, len - 1);
+                               tok->string[len - 1] = 0;
+
+                               cp = (char *)((uaddr_t)cp + len - 2);
+
+                               /* Check to see if this is the keyword
+                                * "sizeof". If not, then check to see if
+                                * the string is a member name.
+                                */
+                               if (!strcmp(tok->string, "sizeof")) {
+                                       tok->operator = SIZEOF;
+                                       kl_free_block((void *)tok->string);
+                                       tok->string = 0;
+                               } else if (tok_last &&
+                                       ((tok_last->operator == RIGHT_ARROW) ||
+                                        (tok_last->operator == DOT))) {
+                                       tok->type = MEMBER;
+                               } else {
+                                       tok->type = STRING;
+                               }
+                               break;
+                       }
+               }
+               if (!(tok->type)) {
+                       tok->type = OPERATOR;
+               }
+               if (!tok_head) {
+                       tok_head = tok_last = tok;
+               } else {
+                       tok_last->next = tok;
+                       tok_last = tok;
+               }
+               cp++;
+       }
+       if (paren_count < 0) {
+               set_eval_error(E_CLOSE_PAREN);
+               error_token = tok->ptr;
+               free_tokens(tok_head);
+               return((token_t*)NULL);
+       } else if (paren_count > 0) {
+               set_eval_error(E_OPEN_PAREN);
+               error_token = tok->ptr;
+               free_tokens(tok_head);
+               return((token_t*)NULL);
+       }
+       return(tok_head);
+}
+
+/*
+ * valid_binary_args()
+ */
+int
+valid_binary_args(node_t *np, node_t *left, node_t *right)
+{
+       int op = np->operator;
+
+       if ((op == RIGHT_ARROW) || (op == DOT)) {
+               if (!left) {
+                       set_eval_error(E_MISSING_STRUCTURE);
+                       error_token = np->tok_ptr;
+                       return(0);
+               } else if (!(left->node_type == TYPE_DEF) &&
+                               !(left->node_type == MEMBER) &&
+                               !(left->operator == CLOSE_PAREN) &&
+                               !(left->operator == CLOSE_SQUARE_BRACKET)) {
+                       set_eval_error(E_BAD_STRUCTURE);
+                       error_token = left->tok_ptr;
+                       return(0);
+               }
+               if (!right || (!(right->node_type == MEMBER))) {
+                       set_eval_error(E_BAD_MEMBER);
+                       error_token = np->tok_ptr;
+                       return(0);
+               }
+               return(1);
+       }
+       if (!left || !right) {
+               set_eval_error(E_MISSING_OPERAND);
+               error_token = np->tok_ptr;
+               return(0);
+       }
+       switch (left->operator) {
+               case CLOSE_PAREN:
+               case CLOSE_SQUARE_BRACKET:
+                       break;
+               default:
+                       switch(left->node_type) {
+                               case NUMBER:
+                               case STRING:
+                               case TEXT:
+                               case CHARACTER:
+                               case EVAL_VAR:
+                               case MEMBER:
+                                       break;
+                               default:
+                                       set_eval_error(E_BAD_OPERAND);
+                                       error_token = np->tok_ptr;
+                                       return(0);
+                       }
+       }
+       switch (right->operator) {
+               case OPEN_PAREN:
+                       break;
+               default:
+                       switch(right->node_type) {
+                               case NUMBER:
+                               case STRING:
+                               case TEXT:
+                               case CHARACTER:
+                               case EVAL_VAR:
+                               case MEMBER:
+                                       break;
+                               default:
+                                       set_eval_error(E_BAD_OPERAND);
+                                       error_token = np->tok_ptr;
+                                       return(0);
+                       }
+       }
+       return(1);
+}
+
+/*
+ * get_node_list()
+ */
+static node_t *
+get_node_list(token_t *tp, int flags)
+{
+       node_t *root = (node_t *)NULL;
+       node_t *np = (node_t *)NULL;
+       node_t *last = (node_t *)NULL;
+
+       /* Loop through the tokens and convert them to nodes.
+        */
+       while (tp) {
+               np = make_node(tp, flags);
+               if (eval_error) {
+                       return((node_t *)NULL);
+               }
+               if (root) {
+                       last->next = np;
+                       last = np;
+               } else {
+                       root = last = np;
+               }
+               tp = tp->next;
+       }
+       last->next = (node_t *)NULL; /* cpw patch */
+       last = (node_t *)NULL;
+       for (np = root; np; np = np->next) {
+               if (is_binary(np->operator)) {
+                       if (!valid_binary_args(np, last, np->next)) {
+                               free_nodelist(root);
+                               return((node_t *)NULL);
+                       }
+               }
+               last = np;
+       }
+       return(root);
+}
+
+/*
+ * next_node()
+ */
+static node_t *
+next_node(void)
+{
+       node_t *np;
+       if ((np = node_list)) {
+               node_list = node_list->next;
+               np->next = (node_t*)NULL;
+       }
+       return(np);
+}
+
+/*
+ * eval_unary()
+ */
+static node_t *
+eval_unary(node_t *curnp, int flags)
+{
+       node_t *n0, *n1;
+
+       n0 = curnp;
+
+       /* Peek ahead and make sure there is a next node.
+        * Also check to see if the next node requires
+        * a recursive call to do_eval(). If it does, we'll
+        * let the do_eval() call take care of pulling it
+        * off the list.
+        */
+       if (!node_list) {
+               set_eval_error(E_SYNTAX_ERROR);
+               error_token = n0->tok_ptr;
+               free_nodes(n0);
+               return((node_t*)NULL);
+       }
+       if (n0->operator == CAST) {
+               if (node_list->operator == CLOSE_PAREN) {
+
+                       /* Free the CLOSE_PAREN and return
+                        */
+                       free_node(next_node());
+                       return(n0);
+               }
+               if (!(node_list->node_type == NUMBER) &&
+                               !(node_list->node_type == VADDR) &&
+                               !((node_list->operator == ADDRESS) ||
+                               (node_list->operator == CAST) ||
+                               (node_list->operator == UNARY_MINUS) ||
+                               (node_list->operator == UNARY_PLUS) ||
+                               (node_list->operator == INDIRECTION) ||
+                               (node_list->operator == OPEN_PAREN))) {
+                       set_eval_error(E_SYNTAX_ERROR);
+                       error_token = node_list->tok_ptr;
+                       free_nodes(n0);
+                       return((node_t*)NULL);
+               }
+       }
+       if ((n0->operator == INDIRECTION) ||
+                       (n0->operator == ADDRESS) ||
+                       (n0->operator == OPEN_PAREN) ||
+                       is_unary(node_list->operator)) {
+               n1 = do_eval(flags);
+               if (eval_error) {
+                       free_nodes(n0);
+                       free_nodes(n1);
+                       return((node_t*)NULL);
+               }
+       } else {
+               n1 = next_node();
+       }
+
+       if (n1->operator == OPEN_PAREN) {
+               /* Get the value contained within the parenthesis.
+                * If there was an error, just return.
+                */
+               free_node(n1);
+               n1 = do_eval(flags);
+               if (eval_error) {
+                       free_nodes(n1);
+                       free_nodes(n0);
+                       return((node_t*)NULL);
+               }
+       }
+
+       n0->right = n1;
+       if (replace_unary(n0, flags) == -1) {
+               if (!eval_error) {
+                       set_eval_error(E_SYNTAX_ERROR);
+                       error_token = n0->tok_ptr;
+               }
+               free_nodes(n0);
+               return((node_t*)NULL);
+       }
+       return(n0);
+}
+
+/*
+ * do_eval() -- Reduces an equation to a single value.
+ *
+ *   Any parenthesis (and nested parenthesis) within the equation will
+ *   be solved first via recursive calls to do_eval().
+ */
+static node_t *
+do_eval(int flags)
+{
+       node_t *root = (node_t*)NULL, *curnp, *n0, *n1;
+
+       /* Loop through the list of nodes until we run out of nodes
+        * or we hit a CLOSE_PAREN. If we hit an OPEN_PAREN, make a
+        * recursive call to do_eval().
+        */
+       curnp = next_node();
+       while (curnp) {
+               n0 = n1 = (node_t *)NULL;
+
+               if (curnp->operator == OPEN_PAREN) {
+                       /* Get the value contained within the parenthesis.
+                        * If there was an error, just return.
+                        */
+                       free_node(curnp);
+                       n0 = do_eval(flags);
+                       if (eval_error) {
+                               free_nodes(n0);
+                               free_nodes(root);
+                               return((node_t *)NULL);
+                       }
+
+               } else if (curnp->operator == SIZEOF) {
+                       /* Free the SIZEOF node and then make a call
+                        * to the get_sizeof() function (which will
+                        * get the next node off the list).
+                        */
+                       n0 = get_sizeof();
+                       if (eval_error) {
+                               if (!error_token) {
+                                       error_token = curnp->tok_ptr;
+                               }
+                               free_node(curnp);
+                               free_nodes(root);
+                               return((node_t *)NULL);
+                       }
+                       free_node(curnp);
+                       curnp = (node_t *)NULL;
+               } else if (is_unary(curnp->operator)) {
+                       n0 = eval_unary(curnp, flags);
+               } else {
+                       n0 = curnp;
+                       curnp = (node_t *)NULL;
+               }
+               if (eval_error) {
+                       free_nodes(n0);
+                       free_nodes(root);
+                       return((node_t *)NULL);
+               }
+
+               /* n0 should now contain a non-operator node. Check to see if
+                * there is a next token. If there isn't, just add the last
+                * rchild and return.
+                */
+               if (!node_list) {
+                       if (root) {
+                               add_rchild(root, n0);
+                       } else {
+                               root = n0;
+                       }
+                       replace(root, flags);
+                       if (eval_error) {
+                               free_nodes(root);
+                               return((node_t *)NULL);
+                       }
+                       return(root);
+               }
+
+               /* Make sure the next token is an operator.
+                */
+               if (!node_list->operator) {
+                       free_nodes(root);
+                       free_node(n0);
+                       set_eval_error(E_SYNTAX_ERROR);
+                       error_token = node_list->tok_ptr;
+                       return((node_t *)NULL);
+               } else if ((node_list->operator == CLOSE_PAREN) ||
+                       (node_list->operator == CLOSE_SQUARE_BRACKET)) {
+
+                       if (root) {
+                               add_rchild(root, n0);
+                       } else {
+                               root = n0;
+                       }
+
+                       /* Reduce the resulting tree to a single value
+                        */
+                       replace(root, flags);
+                       if (eval_error) {
+                               free_nodes(root);
+                               return((node_t *)NULL);
+                       }
+
+                       /* Step over the CLOSE_PAREN or CLOSE_SQUARE_BRACKET
+                        * and then return.
+                        */
+                       free_node(next_node());
+                       return(root);
+               } else if (node_list->operator == OPEN_SQUARE_BRACKET) {
+next_dimension1:
+                       /* skip over the OPEN_SQUARE_BRACKET token
+                        */
+                       free_node(next_node());
+
+                       /* Get the value contained within the brackets. This
+                        * value must represent an array index (value or
+                        * equation).
+                        */
+                       n1 = do_eval(0);
+                       if (eval_error) {
+                               free_nodes(root);
+                               free_node(n0);
+                               free_node(n1);
+                               return((node_t *)NULL);
+                       }
+
+                       /* Convert the array (or pointer type) to an
+                        * element type using the index value obtained
+                        * above. Make sure that n0 contains some sort
+                        * of type definition first, however.
+                        */
+                       if (n0->node_type != TYPE_DEF) {
+                               set_eval_error(E_BAD_TYPE);
+                               error_token = n0->tok_ptr;
+                               free_nodes(n0);
+                               free_nodes(n1);
+                               free_nodes(root);
+                               return((node_t *)NULL);
+                       }
+                       array_to_element(n0, n1);
+                       free_node(n1);
+                       if (eval_error) {
+                               free_nodes(root);
+                               free_nodes(n0);
+                               return((node_t *)NULL);
+                       }
+
+                       /* If there aren't any more nodes, just
+                        * return.
+                        */
+                       if (!node_list) {
+                               return(n0);
+                       }
+                       if (node_list->operator == OPEN_SQUARE_BRACKET) {
+                               goto next_dimension1;
+                       }
+               } else if (!is_binary(node_list->operator)) {
+                       set_eval_error(E_BAD_OPERATOR);
+                       error_token = node_list->tok_ptr;
+                       free_nodes(root);
+                       free_nodes(n0);
+                       return((node_t *)NULL);
+               }
+
+               /* Now get the operator node
+                */
+               if (!(n1 = next_node())) {
+                       set_eval_error(E_SYNTAX_ERROR);
+                       error_token = n0->tok_ptr;
+                       free_nodes(n0);
+                       free_nodes(root);
+                       return((node_t *)NULL);
+               }
+
+               /* Check to see if this binary operator is RIGHT_ARROW or DOT.
+                * If it is, we need to reduce it to a single value node now.
+                */
+               while ((n1->operator == RIGHT_ARROW) || (n1->operator == DOT)) {
+
+                       /* The next node must contain the name of the
+                        * struct|union member.
+                        */
+                       if (!node_list || (node_list->node_type != MEMBER)) {
+                               set_eval_error(E_BAD_MEMBER);
+                               error_token = n1->tok_ptr;
+                               free_nodes(n0);
+                               free_nodes(n1);
+                               free_nodes(root);
+                               return((node_t *)NULL);
+                       }
+                       n1->left = n0;
+
+                       /* Now get the next node and link it as the
+                        * right child.
+                        */
+                       if (!(n0 = next_node())) {
+                               set_eval_error(E_SYNTAX_ERROR);
+                               error_token = n1->tok_ptr;
+                               free_nodes(n1);
+                               free_nodes(root);
+                               return((node_t *)NULL);
+                       }
+                       n1->right = n0;
+                       if (!(n0 = replace(n1, flags))) {
+                               if (!(eval_error)) {
+                                       set_eval_error(E_SYNTAX_ERROR);
+                                       error_token = n1->tok_ptr;
+                               }
+                               free_nodes(n1);
+                               free_nodes(root);
+                               return((node_t *)NULL);
+                       }
+                       n1 = (node_t *)NULL;
+
+                       /* Check to see if there is a next node. If there
+                        * is, check to see if it is the operator CLOSE_PAREN.
+                        * If it is, then return (skipping over the
+                        * CLOSE_PAREN first).
+                        */
+                       if (node_list && ((node_list->operator == CLOSE_PAREN)
+                                               || (node_list->operator ==
+                                               CLOSE_SQUARE_BRACKET))) {
+                               if (root) {
+                                       add_rchild(root, n0);
+                               } else {
+                                       root = n0;
+                               }
+
+                               /* Reduce the resulting tree to a single
+                                * value
+                                */
+                               replace(root, flags);
+                               if (eval_error) {
+                                       free_nodes(root);
+                                       return((node_t *)NULL);
+                               }
+
+                               /* Advance the token pointer past the
+                                * CLOSE_PAREN and then return.
+                                */
+                               free_node(next_node());
+                               return(root);
+                       }
+
+                       /* Check to see if the next node is an
+                        * OPEN_SQUARE_BRACKET. If it is, then we have to
+                        * reduce the contents of the square brackets to
+                        * an index array.
+                        */
+                       if (node_list && (node_list->operator
+                                               == OPEN_SQUARE_BRACKET)) {
+
+                               /* Advance the token pointer and call
+                                * do_eval() again.
+                                */
+                               free_node(next_node());
+next_dimension2:
+                               n1 = do_eval(0);
+                               if (eval_error) {
+                                       free_node(n0);
+                                       free_node(n1);
+                                       free_nodes(root);
+                                       return((node_t *)NULL);
+                               }
+
+                               /* Convert the array (or pointer type) to
+                                * an element type using the index value
+                                * obtained above. Make sure that n0
+                                * contains some sort of type definition
+                                * first, however.
+                                */
+                               if (n0->node_type != TYPE_DEF) {
+                                       set_eval_error(E_BAD_TYPE);
+                                       error_token = n0->tok_ptr;
+                                       free_node(n0);
+                                       free_node(n1);
+                                       free_node(root);
+                                       return((node_t *)NULL);
+                               }
+                               array_to_element(n0, n1);
+                               free_node(n1);
+                               if (eval_error) {
+                                       free_node(n0);
+                                       free_node(root);
+                                       return((node_t *)NULL);
+                               }
+                       }
+
+                       /* Now get the next operator node (if there is one).
+                        */
+                       if (!node_list) {
+                               if (root) {
+                                       add_rchild(root, n0);
+                               } else {
+                                       root = n0;
+                               }
+                               return(root);
+                       }
+                       n1 = next_node();
+                       if (n1->operator == OPEN_SQUARE_BRACKET) {
+                               goto next_dimension2;
+                       }
+               }
+
+               if (n1 && ((n1->operator == CLOSE_PAREN) ||
+                               (n1->operator == CLOSE_SQUARE_BRACKET))) {
+                       free_node(n1);
+                       if (root) {
+                               add_rchild(root, n0);
+                       } else {
+                               root = n0;
+                       }
+                       replace(root, flags);
+                       if (eval_error) {
+                               free_nodes(root);
+                               return((node_t *)NULL);
+                       }
+                       return(root);
+               }
+
+               if (!root) {
+                       root = n1;
+                       n1->left = n0;
+               } else if (precedence(root->operator)
+                               >= precedence(n1->operator)) {
+                       add_rchild(root, n0);
+                       n1->left = root;
+                       root = n1;
+               } else {
+                       if (!root->right) {
+                               n1->left = n0;
+                               root->right = n1;
+                       } else {
+                               add_rchild(root, n0);
+                               n1->left = root->right;
+                               root->right = n1;
+                       }
+               }
+               curnp = next_node();
+       } /* while(curnp) */
+       return(root);
+}
+
+/*
+ * is_unary()
+ */
+static int
+is_unary(int op)
+{
+       switch (op) {
+               case LOGICAL_NEGATION :
+               case ADDRESS :
+               case INDIRECTION :
+               case UNARY_MINUS :
+               case UNARY_PLUS :
+               case ONES_COMPLEMENT :
+               case CAST :
+                       return(1);
+
+               default :
+                       return(0);
+       }
+}
+
+
+/*
+ * is_binary()
+ */
+static int
+is_binary(int op)
+{
+       switch (op) {
+
+               case BITWISE_OR :
+               case BITWISE_EXCLUSIVE_OR :
+               case BITWISE_AND :
+               case RIGHT_SHIFT :
+               case LEFT_SHIFT :
+               case ADD :
+               case SUBTRACT :
+               case MULTIPLY :
+               case DIVIDE :
+               case MODULUS :
+               case LOGICAL_OR :
+               case LOGICAL_AND :
+               case EQUAL :
+               case NOT_EQUAL :
+               case LESS_THAN :
+               case GREATER_THAN :
+               case LESS_THAN_OR_EQUAL :
+               case GREATER_THAN_OR_EQUAL :
+               case RIGHT_ARROW :
+               case DOT :
+                       return(1);
+
+               default :
+                       return(0);
+       }
+}
+
+/*
+ * precedence()
+ */
+static int
+precedence(int a)
+{
+       if ((a >= CONDITIONAL) && (a <= CONDITIONAL_ELSE)) {
+               return(1);
+       } else if (a == LOGICAL_OR) {
+               return(2);
+       } else if (a == LOGICAL_AND) {
+               return(3);
+       } else if (a == BITWISE_OR) {
+               return(4);
+       } else if (a == BITWISE_EXCLUSIVE_OR) {
+               return(5);
+       } else if (a == BITWISE_AND) {
+               return(6);
+       } else if ((a >= EQUAL) && (a <= NOT_EQUAL)) {
+               return(7);
+       } else if ((a >= LESS_THAN) && (a <= GREATER_THAN_OR_EQUAL)) {
+               return(8);
+       } else if ((a >= RIGHT_SHIFT) && (a <= LEFT_SHIFT)) {
+               return(9);
+       } else if ((a >= ADD) && (a <= SUBTRACT)) {
+               return(10);
+       } else if ((a >= MULTIPLY) && (a <= MODULUS)) {
+               return(11);
+       } else if ((a >= LOGICAL_NEGATION) && (a <= SIZEOF)) {
+               return(12);
+       } else if ((a >= RIGHT_ARROW) && (a <= DOT)) {
+               return(13);
+       } else {
+               return(0);
+       }
+}
+
+/*
+ * esc_char()
+ */
+char
+esc_char(char *str)
+{
+       long int val;
+       unsigned long uval;
+       char ch;
+
+       if (strlen(str) > 1) {
+               uval = kl_strtoull(str, (char **)NULL, 8);
+               val = uval;
+               ch = (char)val;
+       } else {
+               ch = str[0];
+       }
+       switch (ch) {
+               case 'a' :
+                       return((char)7);
+               case 'b' :
+                       return((char)8);
+               case 't' :
+                       return((char)9);
+               case 'n' :
+                       return((char)10);
+               case 'f' :
+                       return((char)12);
+               case 'r' :
+                       return((char)13);
+               case 'e' :
+                       return((char)27);
+               default:
+                       return(ch);
+       }
+}
+
+/*
+ * make_node()
+ */
+static node_t *
+make_node(token_t *t, int flags)
+{
+       node_t *np;
+
+       set_eval_error(0);
+       np = (node_t*)kl_alloc_block(sizeof(*np));
+
+       if (t->type == OPERATOR) {
+
+               /* Check to see if this token represents a typecast
+                */
+               if (t->operator == CAST) {
+                       type_t *tp;
+
+                       if (!(np->type = get_type(t->string, flags))) {
+                               set_eval_error(E_BAD_CAST);
+                               error_token = t->ptr;
+                               free_nodes(np);
+                               return((node_t*)NULL);
+                       }
+
+                       /* Determin if this is a pointer to a type
+                        */
+                       tp = np->type;
+                       if (tp->flag == POINTER_FLAG) {
+                               np->flags = POINTER_FLAG;
+                               tp = tp->t_next;
+                               while (tp->flag == POINTER_FLAG) {
+                                       tp = tp->t_next;
+                               }
+                       }
+                       switch(tp->flag) {
+                               case KLTYPE_FLAG:
+                                       np->flags |= KLTYPE_FLAG;
+                                       break;
+
+                               default:
+                                       free_nodes(np);
+                                       set_eval_error(E_BAD_CAST);
+                                       error_token = t->ptr;
+                                       return((node_t*)NULL);
+                       }
+                       if (!t->next) {
+                               if (flags & C_WHATIS) {
+                                       np->node_type = TYPE_DEF;
+                               } else {
+                                       set_eval_error(E_BAD_CAST);
+                                       error_token = t->ptr;
+                                       return((node_t*)NULL);
+                               }
+                       } else {
+                               np->node_type = OPERATOR;
+                               np->operator = CAST;
+                       }
+               } else {
+                       np->node_type = OPERATOR;
+                       np->operator = t->operator;
+               }
+       } else if (t->type == MEMBER) {
+               np->name = (char *)dup_block((void *)t->string, strlen(t->string)+1);
+               np->node_type = MEMBER;
+       } else if ((t->type == STRING) || (t->type == TYPE_DEF)) {
+               syment_t *sp;
+               dbg_sym_t *stp;
+               dbg_type_t *sttp;
+
+               if ((sp = kl_lkup_symname(t->string))) {
+                   if (!(flags & C_NOVARS)) {
+                       int has_type = 0;
+
+                       /* The string is a symbol name. We'll treat it as
+                        * a global kernel variable and, at least, gather in
+                        * the address of the symbol and the value it points
+                        * to.
+                        */
+                       np->address = sp->s_addr;
+                       np->flags |= ADDRESS_FLAG;
+                       np->name = t->string;
+                       t->string = (char*)NULL;
+
+                       /* Need to see if there is type information available
+                        * for this variable. Since this mapping is not
+                        * available yet, we will just attach a type struct
+                        * for either uint32_t or uint64_t (depending on the
+                        * size of a kernel pointer).  That will at least let
+                        * us do something and will prevent the scenario where
+                        * we have a type node with out a pointer to a type
+                        * struct!
+                        */
+                       np->node_type = TYPE_DEF;
+                       np->flags |= KLTYPE_FLAG;
+                       np->value = *((kaddr_t *)np->address);
+                       /* try to get the actual type info for the variable */
+                       if(((stp = dbg_find_sym(sp->s_name, DBG_VAR,
+                                               (uint64_t)0)) != NULL)){
+                               if((sttp = (dbg_type_t *)
+                                       kl_find_typenum(stp->sym_typenum))
+                                               != NULL){
+                                       /* kl_get_typestring(sttp); */
+                                       has_type = 1;
+                                       if(sttp->st_klt.kl_type == KLT_POINTER){
+                                               np->flags ^= KLTYPE_FLAG;
+                                               np->flags |= POINTER_FLAG;
+                                               np->type =
+                                                 get_type(sttp->st_typestr,
+                                                               flags);
+                                       } else {
+                                               np->type =
+                                                kl_alloc_block(sizeof(type_t));
+                                               np->type->un.kltp =
+                                                       &sttp->st_klt;
+                                       }
+                               }
+                       }
+                       /* no type info for the variable found */
+                       if(!has_type){
+                               if (ptrsz64) {
+                                       np->type = get_type("uint64_t", flags);
+                               } else {
+                                       np->type = get_type("uint32_t", flags);
+                               }
+                       }
+                   }
+                   kl_free_block((void *)sp);
+               } else if (flags & (C_WHATIS|C_SIZEOF)) {
+
+                       kltype_t *kltp;
+
+                       if ((kltp = kl_find_type(t->string, KLT_TYPES))) {
+
+                               np->node_type = TYPE_DEF;
+                               np->flags = KLTYPE_FLAG;
+                               np->type = (type_t*)
+                                       kl_alloc_block(sizeof(type_t));
+                               np->type->flag = KLTYPE_FLAG;
+                               np->type->t_kltp = kltp;
+                       } else {
+                               if (get_value(t->string,
+                                       (uint64_t *)&np->value)) {
+                                       set_eval_error(E_BAD_VALUE);
+                                       error_token = t->ptr;
+                                       free_nodes(np);
+                                       return((node_t*)NULL);
+                               }
+                               if (!strncmp(t->string, "0x", 2) ||
+                                               !strncmp(t->string, "0X", 2)) {
+                                       np->flags |= UNSIGNED_FLAG;
+                               }
+                               np->node_type = NUMBER;
+                       }
+                       np->tok_ptr = t->ptr;
+                       return(np);
+               } else {
+                       if (get_value(t->string, (uint64_t *)&np->value)) {
+                               set_eval_error(E_BAD_VALUE);
+                               error_token = t->ptr;
+                               free_nodes(np);
+                               return((node_t*)NULL);
+                       }
+                       if (np->value > 0xffffffff) {
+                               np->byte_size = 8;
+                       } else {
+                               np->byte_size = 4;
+                       }
+                       if (!strncmp(t->string, "0x", 2) ||
+                                       !strncmp(t->string, "0X", 2)) {
+                               np->flags |= UNSIGNED_FLAG;
+                       }
+                       np->node_type = NUMBER;
+               }
+       } else if (t->type == CHARACTER) {
+               char *cp;
+
+               /* Step over the single quote
+                */
+               cp = (t->ptr + 1);
+               if (*cp == '\\') {
+                       int i = 0;
+                       char str[16];
+
+                       /* Step over the back slash
+                        */
+                       cp++;
+                       while (*cp != '\'') {
+                               str[i++] = *cp++;
+                       }
+                       str[i] = 0;
+                       np->value = esc_char(str);
+               } else {
+                       np->value = *cp;
+               }
+               np->type = get_type("char", flags);
+               np->node_type = TYPE_DEF;
+               np->flags |= KLTYPE_FLAG;
+       } else if (t->type == TEXT) {
+               np->node_type = TEXT;
+               np->name = t->string;
+               /* So the block doesn't get freed twice */
+               t->string = (char*)NULL;
+       } else {
+               set_eval_error(E_SYNTAX_ERROR);
+               error_token = t->ptr;
+               return((node_t*)NULL);
+       }
+       np->tok_ptr = t->ptr;
+       return(np);
+}
+
+/*
+ * add_node()
+ */
+static int
+add_node(node_t *root, node_t *new_node)
+{
+       node_t *n = root;
+
+       /* Find the most lower-right node
+        */
+       while (n->right) {
+               n = n->right;
+       }
+
+       /* If the node we found is a leaf node, return an error (we will
+        * have to insert the node instead).
+        */
+       if (n->node_type == NUMBER) {
+               return(-1);
+       } else {
+               n->right = new_node;
+       }
+       return(0);
+}
+
+/*
+ * add_rchild()
+ */
+static int
+add_rchild(node_t *root, node_t *new_node)
+{
+       if (add_node(root, new_node) == -1) {
+               return(-1);
+       }
+       return(0);
+}
+
+/*
+ * free_type()
+ */
+static void
+free_type(type_t *head)
+{
+       type_t *t0, *t1;
+
+       t0 = head;
+       while(t0) {
+               if (t0->flag == POINTER_FLAG) {
+                       t1 = t0->t_next;
+                       kl_free_block((void *)t0);
+                       t0 = t1;
+               } else {
+                       if (t0->flag != KLTYPE_FLAG) {
+                               kl_free_block((void *)t0->t_kltp);
+                       }
+                       kl_free_block((void *)t0);
+                       t0 = (type_t *)NULL;
+               }
+       }
+       return;
+}
+
+/*
+ * get_type() -- Convert a typecast string into a type.
+ *
+ *   Returns a pointer to a struct containing type information.
+ *   The type of struct returned is indicated by the contents
+ *   of type. If the typecast contains an asterisk, set ptr_type
+ *   equal to one, otherwise set it equal to zero.
+ */
+static type_t *
+get_type(char *s, int flags)
+{
+       int len, type = 0;
+       char *cp, typename[128];
+       type_t *t, *head, *last;
+       kltype_t *kltp;
+
+       head = last = (type_t *)NULL;
+
+       /* Get the type string
+        */
+       if (!strncmp(s, "struct", 6)) {
+               if ((cp = strpbrk(s + 7, " \t*"))) {
+                       len = cp - (s + 7);
+               } else {
+                       len = strlen(s + 7);
+               }
+               memcpy(typename, s + 7, len);
+       } else if (!strncmp(s, "union", 5)) {
+               if ((cp = strpbrk(s + 6, " \t*"))) {
+                       len = cp - (s + 6);
+               } else {
+                       len = strlen(s + 6);
+               }
+               memcpy(typename, s + 6, len);
+       } else {
+               if ((cp = strpbrk(s, "*)"))) {
+                       len = cp - s;
+               } else {
+                       len = strlen(s);
+               }
+               memcpy(typename, s, len);
+       }
+
+       /* Strip off any trailing spaces
+        */
+       while (len && ((typename[len - 1] == ' ') ||
+                       (typename[len - 1] == '\t'))) {
+               len--;
+       }
+       typename[len] = 0;
+
+       if (!(kltp = kl_find_type(typename, KLT_TYPES))) {
+               return ((type_t *)NULL);
+       }
+       type = KLTYPE_FLAG;
+
+       /* check to see if this cast is a pointer to a type, a pointer
+        * to a pointer to a type, etc.
+        */
+       cp = s;
+       while ((cp = strpbrk(cp, "*"))) {
+               t = (type_t *)kl_alloc_block(sizeof(type_t));
+               t->flag = POINTER_FLAG;
+               if (last) {
+                       last->t_next = t;
+                       last = t;
+               } else {
+                       head = last = t;
+               }
+               cp++;
+       }
+
+       /* Allocate a type block that will point to the type specific
+        * record.
+        */
+       t = (type_t *)kl_alloc_block(sizeof(type_t));
+       t->flag = type;
+
+       switch (t->flag) {
+
+               case KLTYPE_FLAG:
+                       t->t_kltp = kltp;
+                       break;
+
+               default:
+                       free_type(head);
+                       return((type_t*)NULL);
+       }
+       if (last) {
+               last->t_next = t;
+       } else {
+               head = t;
+       }
+       return(head);
+}
+
+/*
+ * free_node()
+ */
+static void
+free_node(node_t *np)
+{
+       /* If there is nothing to free, just return.
+        */
+       if (!np) {
+               return;
+       }
+       if (np->name) {
+               kl_free_block((void *)np->name);
+       }
+       free_type(np->type);
+       kl_free_block((void *)np);
+}
+
+/*
+ * free_nodes()
+ */
+void
+free_nodes(node_t *np)
+{
+       node_t *q;
+
+       /* If there is nothing to free, just return.
+        */
+       if (!np) {
+               return;
+       }
+       if ((q = np->left)) {
+               free_nodes(q);
+       }
+       if ((q = np->right)) {
+               free_nodes(q);
+       }
+       if (np->name) {
+               kl_free_block((void *)np->name);
+       }
+       free_type(np->type);
+       kl_free_block((void *)np);
+}
+
+/*
+ * free_nodelist()
+ */
+static void
+free_nodelist(node_t *np)
+{
+       node_t *nnp;
+
+       while(np) {
+               nnp = np->next;
+               free_node(np);
+               np = nnp;
+       }
+}
+
+extern int alloc_debug;
+
+/*
+ * free_eval_memory()
+ */
+void
+free_eval_memory(void)
+{
+       free_nodelist(node_list);
+       node_list = (node_t*)NULL;
+}
+
+/*
+ * get_sizeof()
+ */
+static node_t *
+get_sizeof()
+{
+       node_t *curnp, *n0 = NULL;
+
+       if (!(curnp = next_node())) {
+               set_eval_error(E_SYNTAX_ERROR);
+               return((node_t*)NULL);
+       }
+
+       /* The next token should be a CAST or an open paren.
+        * If it's something else, then return an error.
+        */
+       if (curnp->operator == OPEN_PAREN) {
+               free_nodes(curnp);
+               n0 = do_eval(C_SIZEOF);
+               if (eval_error) {
+                       error_token = n0->tok_ptr;
+                       free_nodes(n0);
+                       return((node_t*)NULL);
+               }
+       } else if (curnp->operator == CAST) {
+               n0 = curnp;
+       } else {
+               set_eval_error(E_BAD_TYPE);
+               error_token = n0->tok_ptr;
+               free_nodes(n0);
+               return((node_t*)NULL);
+       }
+
+       if (!n0->type) {
+               set_eval_error(E_NOTYPE);
+               error_token = n0->tok_ptr;
+               free_nodes(n0);
+               return((node_t*)NULL);
+       }
+
+       if (n0->type->flag & POINTER_FLAG) {
+               n0->value = sizeof(void *);
+       } else if (n0->type->flag & KLTYPE_FLAG) {
+               kltype_t *kltp;
+
+               kltp = kl_realtype(n0->type->t_kltp, 0);
+
+               if (kltp->kl_bit_size) {
+                       n0->value = kltp->kl_bit_size / 8;
+                       if (kltp->kl_bit_size % 8) {
+                               n0->value += 1;
+                       }
+               } else {
+                       n0->value = kltp->kl_size;
+               }
+       } else {
+               set_eval_error(E_BAD_TYPE);
+               error_token = n0->tok_ptr;
+               free_nodes(n0);
+               return((node_t*)NULL);
+       }
+       n0->node_type = NUMBER;
+       n0->flags = 0;
+       n0->operator = 0;
+       n0->byte_size = 0;
+       n0->address = 0;
+       if (n0->type) {
+               free_type(n0->type);
+               n0->type = 0;
+       }
+       return(n0);
+}
+
+/*
+ * apply_unary()
+ */
+static int
+apply_unary(node_t *n, uint64_t *value)
+{
+       if (!n || !n->right) {
+               return(-1);
+       }
+
+       switch (n->operator) {
+
+               case UNARY_MINUS :
+                       *value = (0 - n->right->value);
+                       break;
+
+               case UNARY_PLUS :
+                       *value = (n->right->value);
+                       break;
+
+               case ONES_COMPLEMENT :
+                       *value = ~(n->right->value);
+                       break;
+
+               case LOGICAL_NEGATION :
+                       if (n->right->value) {
+                               *value = 0;
+                       } else {
+                               *value = 1;
+                       }
+                       logical_flag++;
+                       break;
+
+               default :
+                       break;
+       }
+       return(0);
+}
+
+/*
+ * pointer_math()
+ */
+static int
+pointer_math(node_t *np, uint64_t *value, int type, int flags)
+{
+       int size;
+       uint64_t lvalue, rvalue;
+       type_t *tp = NULL, *tp1;
+
+       if (type < 0) {
+               if (np->left->flags & POINTER_FLAG) {
+
+                       /* Since we only allow pointer math,
+                        * anything other than a pointer causes
+                        * failure.
+                        */
+                       tp = (type_t*)np->left->type;
+                       if (tp->flag != POINTER_FLAG) {
+                               set_eval_error(E_SYNTAX_ERROR);
+                               error_token = np->left->tok_ptr;
+                               return(-1);
+                       }
+
+                       tp = tp->t_next;
+
+                       switch (tp->flag) {
+
+                               case POINTER_FLAG :
+                                       size = sizeof(void *);
+                                       break;
+
+                               case KLTYPE_FLAG : {
+                                       /* Get the size of the real type,
+                                        * not just the size of a pointer
+                                        * If there isn't any type info,
+                                        * then just set size equal to the
+                                        * size of a pointer.
+                                        */
+                                       kltype_t *kltp, *rkltp;
+
+                                       kltp = tp->t_kltp;
+                                       rkltp = kl_realtype(kltp, 0);
+                                       if (!(size = rkltp->kl_size)) {
+                                               if (kltp != rkltp) {
+                                                       size = kltp->kl_size;
+                                               } else {
+                                                       size = sizeof(void *);
+                                               }
+                                       }
+                                       break;
+                               }
+
+                               default :
+                                       set_eval_error(E_SYNTAX_ERROR);
+                                       error_token = np->left->tok_ptr;
+                                       return(-1);
+                       }
+                       lvalue = np->left->value;
+               } else {
+                       size = sizeof(void *);
+                       lvalue = np->left->address;
+               }
+               switch (np->operator) {
+                       case ADD :
+                               *value = lvalue + (np->right->value * size);
+                               break;
+
+                       case SUBTRACT :
+                               *value = lvalue - (np->right->value * size);
+                               break;
+
+                       default :
+                               set_eval_error(E_BAD_OPERATOR);
+                               error_token = np->tok_ptr;
+                               return(-1);
+               }
+       } else if (type > 0) {
+               if (np->right->flags & POINTER_FLAG) {
+
+                       /* Since we only allow pointer math,
+                        * anything other than a pointer causes
+                        * failure.
+                        */
+                       tp = (type_t*)np->right->type;
+                       if (tp->flag != POINTER_FLAG) {
+                               set_eval_error(E_SYNTAX_ERROR);
+                               error_token = np->right->tok_ptr;
+                               return(-1);
+                       }
+
+                       tp = tp->t_next;
+
+                       switch (tp->flag) {
+
+                               case POINTER_FLAG :
+                                       size = sizeof(void *);
+                                       break;
+
+                               case KLTYPE_FLAG :
+                                       size = tp->t_kltp->kl_size;
+                                       break;
+
+                               default :
+                                       set_eval_error(E_SYNTAX_ERROR);
+                                       error_token = np->right->tok_ptr;
+                                       return(-1);
+                       }
+                       rvalue = np->right->value;
+               } else {
+                       size = sizeof(void *);
+                       rvalue = np->right->address;
+               }
+               switch (np->operator) {
+                       case ADD :
+                               *value = rvalue + (np->left->value * size);
+                               break;
+
+                       case SUBTRACT :
+                               *value = rvalue - (np->left->value * size);
+                               break;
+
+                       default :
+                               set_eval_error(E_BAD_OPERATOR);
+                               error_token = np->tok_ptr;
+                               return(-1);
+               }
+       } else {
+               return(-1);
+       }
+       tp1 = (type_t *)kl_alloc_block(sizeof(type_t));
+       tp1->flag = POINTER_FLAG;
+       np->type = tp1;
+       while (tp->flag == POINTER_FLAG) {
+               tp1->t_next = (type_t *)kl_alloc_block(sizeof(type_t));
+               tp1->flag = POINTER_FLAG;
+               tp1 = tp1->t_next;
+               tp = tp->t_next;
+       }
+       if (tp) {
+               tp1->t_next = (type_t *)kl_alloc_block(sizeof(type_t));
+               tp1 = tp1->t_next;
+               tp1->flag = KLTYPE_FLAG;
+               tp1->t_kltp = tp->t_kltp;
+               if (type < 0) {
+                       if (np->left->flags & POINTER_FLAG) {
+                               np->flags |= POINTER_FLAG;
+                       } else {
+                               np->flags |= VADDR;
+                       }
+               } else {
+                       if (np->right->flags & POINTER_FLAG) {
+                               np->flags |= POINTER_FLAG;
+                       } else {
+                               np->flags |= VADDR;
+                       }
+               }
+       }
+       return(0);
+}
+
+/*
+ * check_unsigned()
+ */
+int
+check_unsigned(node_t *np)
+{
+       kltype_t *kltp, *rkltp;
+
+       if (np->flags & UNSIGNED_FLAG) {
+               return(1);
+       }
+       if (!np->type) {
+               return(0);
+       }
+       if (np->type->flag == POINTER_FLAG) {
+               return(0);
+       }
+       kltp = np->type->t_kltp;
+       if ((rkltp = kl_realtype(kltp, 0))) {
+               if (rkltp->kl_encoding == ENC_UNSIGNED) {
+                       np->flags |= UNSIGNED_FLAG;
+                       return(1);
+               }
+       }
+       return(0);
+}
+
+/*
+ * apply()
+ */
+static int
+apply(node_t *np, uint64_t *value, int flags)
+{
+       int ltype, rtype, do_signed = 0;
+
+       /* There must be two operands
+        */
+       if (!np->right || !np->left) {
+               set_eval_error(E_MISSING_OPERAND);
+               error_token = np->tok_ptr;
+               return(-1);
+       }
+
+       if (np->right->node_type == OPERATOR) {
+               replace(np->right, flags);
+               if (eval_error) {
+                       return(-1);
+               }
+       }
+
+       ltype = np->left->node_type;
+       rtype = np->right->node_type;
+       if ((ltype == TYPE_DEF) || (ltype == VADDR)) {
+               if ((rtype == TYPE_DEF) || (rtype == VADDR)) {
+                       set_eval_error(E_NO_VALUE);
+                       error_token = np->tok_ptr;
+                       return(-1);
+               }
+               if (check_unsigned(np->left)) {
+                       np->flags |= UNSIGNED_FLAG;
+               } else {
+                       do_signed++;
+               }
+               if (!type_to_number(np->left)) {
+                       return(pointer_math(np, value, -1, flags));
+               }
+               np->byte_size = np->left->byte_size;
+       } else if ((rtype == TYPE_DEF) || (rtype == VADDR)) {
+               if ((ltype == TYPE_DEF) || (ltype == VADDR)) {
+                       error_token = np->tok_ptr;
+                       set_eval_error(E_NO_VALUE);
+                       return(-1);
+               }
+               if (check_unsigned(np->right)) {
+                       np->flags |= UNSIGNED_FLAG;
+               } else {
+                       do_signed++;
+               }
+               if (!type_to_number(np->right)) {
+                       return(pointer_math(np, value, 1, flags));
+               }
+               np->byte_size = np->right->byte_size;
+       } else if ((np->left->flags & UNSIGNED_FLAG) ||
+                       (np->right->flags & UNSIGNED_FLAG)) {
+               np->flags |= UNSIGNED_FLAG;
+       } else {
+               do_signed++;
+       }
+
+       if (do_signed) {
+               switch (np->operator) {
+                       case ADD :
+                               *value = (int64_t)np->left->value +
+                                       (int64_t)np->right->value;
+                               break;
+
+                       case SUBTRACT :
+                               *value = (int64_t)np->left->value -
+                                       (int64_t)np->right->value;
+                               break;
+
+                       case MULTIPLY :
+                               *value = (int64_t)np->left->value *
+                                       (int64_t)np->right->value;
+                               break;
+
+                       case DIVIDE :
+                               if ((int64_t)np->right->value == 0) {
+                                       set_eval_error(E_DIVIDE_BY_ZERO);
+                                       error_token = np->right->tok_ptr;
+                                       return(-1);
+                               }
+                               *value = (int64_t)np->left->value /
+                                       (int64_t)np->right->value;
+                               break;
+
+                       case BITWISE_OR :
+                               *value = (int64_t)np->left->value |
+                                       (int64_t)np->right->value;
+                               break;
+
+                       case BITWISE_AND :
+                               *value = (int64_t)np->left->value &
+                                       (int64_t)np->right->value;
+                               break;
+
+                       case MODULUS :
+                               if ((int64_t)np->right->value == 0) {
+                                       set_eval_error(E_DIVIDE_BY_ZERO);
+                                       error_token = np->right->tok_ptr;
+                                       return(-1);
+                               }
+                               *value = (int64_t)np->left->value %
+                                       (int64_t)np->right->value;
+                               break;
+
+                       case RIGHT_SHIFT :
+                               *value =
+                                       (int64_t)np->left->value >>
+                                               (int64_t)np->right->value;
+                               break;
+
+                       case LEFT_SHIFT :
+                               *value =
+                                       (int64_t)np->left->value <<
+                                               (int64_t)np->right->value;
+                               break;
+
+                       case LOGICAL_OR :
+                               if ((int64_t)np->left->value ||
+                                               (int64_t)np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case LOGICAL_AND :
+                               if ((int64_t)np->left->value &&
+                                               (int64_t)np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case EQUAL :
+                               if ((int64_t)np->left->value ==
+                                               (int64_t)np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case NOT_EQUAL :
+                               if ((int64_t)np->left->value !=
+                                               (int64_t)np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case LESS_THAN :
+                               if ((int64_t)np->left->value <
+                                               (int64_t)np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case GREATER_THAN :
+                               if ((int64_t)np->left->value >
+                                               (int64_t)np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case LESS_THAN_OR_EQUAL :
+                               if ((int64_t)np->left->value <=
+                                               (int64_t)np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case GREATER_THAN_OR_EQUAL :
+                               if ((int64_t)np->left->value >=
+                                               (int64_t)np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       default :
+                               break;
+               }
+       } else {
+               switch (np->operator) {
+                       case ADD :
+                               *value = np->left->value + np->right->value;
+                               break;
+
+                       case SUBTRACT :
+                               *value = np->left->value - np->right->value;
+                               break;
+
+                       case MULTIPLY :
+                               *value = np->left->value * np->right->value;
+                               break;
+
+                       case DIVIDE :
+                               *value = np->left->value / np->right->value;
+                               break;
+
+                       case BITWISE_OR :
+                               *value = np->left->value | np->right->value;
+                               break;
+
+                       case BITWISE_AND :
+                               *value = np->left->value & np->right->value;
+                               break;
+
+                       case MODULUS :
+                               *value = np->left->value % np->right->value;
+                               break;
+
+                       case RIGHT_SHIFT :
+                               *value = np->left->value >> np->right->value;
+                               break;
+
+                       case LEFT_SHIFT :
+                               *value = np->left->value << np->right->value;
+                               break;
+
+                       case LOGICAL_OR :
+                               if (np->left->value || np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case LOGICAL_AND :
+                               if (np->left->value && np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case EQUAL :
+                               if (np->left->value == np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case NOT_EQUAL :
+                               if (np->left->value != np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case LESS_THAN :
+                               if (np->left->value < np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case GREATER_THAN :
+                               if (np->left->value > np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case LESS_THAN_OR_EQUAL :
+                               if (np->left->value <= np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       case GREATER_THAN_OR_EQUAL :
+                               if (np->left->value >= np->right->value) {
+                                       *value = 1;
+                               } else {
+                                       *value = 0;
+                               }
+                               logical_flag++;
+                               break;
+
+                       default :
+                               break;
+               }
+       }
+       return(0);
+}
+
+/*
+ * member_to_type()
+ */
+static type_t *
+member_to_type(kltype_t *kltp, int flags)
+{
+       kltype_t *rkltp;
+       type_t *tp, *head = (type_t *)NULL, *last = (type_t *)NULL;
+
+       /* Make sure this is a member
+        */
+       if (kltp->kl_type != KLT_MEMBER) {
+               return((type_t *)NULL);
+       }
+
+       rkltp = kltp->kl_realtype;
+       while (rkltp && rkltp->kl_type == KLT_POINTER) {
+               tp = (type_t *)kl_alloc_block(sizeof(type_t));
+               tp->flag = POINTER_FLAG;
+               if (last) {
+                       last->t_next = tp;
+                       last = tp;
+               } else {
+                       head = last = tp;
+               }
+               rkltp = rkltp->kl_realtype;
+       }
+
+       /* If We step past all the pointer records and don't point
+        * at anything, this must be a void pointer. Setup a VOID
+        * type struct so that we can maintain a pointer to some
+        * type info.
+        */
+       if (!rkltp) {
+               tp = (type_t *)kl_alloc_block(sizeof(type_t));
+               tp->flag = VOID_FLAG;
+               tp->t_kltp = kltp;
+               if (last) {
+                       last->t_next = tp;
+                       last = tp;
+               } else {
+                       head = last = tp;
+               }
+               return(head);
+       }
+
+       tp = (type_t *)kl_alloc_block(sizeof(type_t));
+       tp->flag = KLTYPE_FLAG;
+       tp->t_kltp = kltp;
+       if (last) {
+               last->t_next = tp;
+       } else {
+               head = tp;
+       }
+       return(head);
+}
+
+/*
+ * replace() --
+ *
+ * Replace the tree with a node containing the numerical result of
+ * the equation. If pointer math is performed, the result will have
+ * the same type as the pointer.
+ */
+static node_t *
+replace(node_t *np, int flags)
+{
+       int offset;
+       uint64_t value;
+       node_t *q;
+
+       if (!np) {
+               return((node_t *)NULL);
+       }
+
+       if (np->node_type == OPERATOR) {
+               if (!(q = np->left)) {
+                       return((node_t *)NULL);
+               }
+               while (q) {
+                       if (!replace(q, flags)) {
+                               return((node_t *)NULL);
+                       }
+                       q = q->right;
+               }
+
+               if ((np->operator == RIGHT_ARROW) || (np->operator == DOT)) {
+                       kaddr_t addr = 0;
+                       type_t *tp;
+
+                       if (!have_debug_file) {
+                               kdb_printf("no debuginfo file\n");
+                               return 0;
+                       }
+
+                       /* The left node must point to a TYPE_DEF
+                        */
+                       if (np->left->node_type != TYPE_DEF) {
+                               if (np->left->flags & NOTYPE_FLAG) {
+                                       set_eval_error(E_NOTYPE);
+                                       error_token = np->left->tok_ptr;
+                               } else {
+                                       set_eval_error(E_BAD_TYPE);
+                                       error_token = np->left->tok_ptr;
+                               }
+                               return((node_t *)NULL);
+                       }
+
+                       /* Get the type information.  Check to see if we
+                        * have a pointer to a type. If we do, we need
+                        * to strip off the pointer and get the type info.
+                        */
+                       if (np->left->type->flag == POINTER_FLAG) {
+                               tp = np->left->type->t_next;
+                               kl_free_block((void *)np->left->type);
+                       } else {
+                               tp = np->left->type;
+                       }
+
+                       /* We need to zero out the left child's type pointer
+                        * to prevent the type structs from being prematurely
+                        * freed (upon success). We have to remember, however,
+                        * to the free the type information before we return.
+                        */
+                       np->left->type = (type_t*)NULL;
+
+                       /* tp should now point at a type_t struct that
+                        * references a kltype_t struct. If it points
+                        * to anything else, return failure.
+                        *
+                        */
+                       if (tp->flag != KLTYPE_FLAG) {
+                               set_eval_error(E_BAD_TYPE);
+                               error_token = np->left->tok_ptr;
+                               free_type(tp);
+                               return((node_t *)NULL);
+                       }
+
+                       switch (tp->flag) {
+                               case KLTYPE_FLAG: {
+                                       /* Make sure that the type referenced
+                                        * is a struct, union, or pointer to
+                                        * a struct or union. If it isn't one
+                                        * of these, then return failure.
+                                        */
+                                       kltype_t *kltp, *kltmp;
+
+                                       kltp = kl_realtype(tp->t_kltp, 0);
+                                       if ((kltp->kl_type != KLT_STRUCT) &&
+                                               (kltp->kl_type != KLT_UNION)) {
+                                               error_token =
+                                                       np->left->tok_ptr;
+                                               set_eval_error(E_BAD_TYPE);
+                                               free_type(tp);
+                                               return((node_t *)NULL);
+                                       }
+
+                                       /* Get type information for member.
+                                        * If member is a pointer to a type,
+                                        * get the pointer address and load
+                                        * it into value. In any event, load
+                                        * the struct/union address plus the
+                                        * offset of the member.
+                                        */
+                                       kltmp = kl_get_member(kltp,
+                                                       np->right->name);
+                                       if (!kltmp) {
+                                               set_eval_error(E_BAD_MEMBER);
+                                               error_token =
+                                                       np->right->tok_ptr;
+                                               free_type(tp);
+                                               return((node_t *)NULL);
+                                       }
+
+                                       /* We can't just use the offset value
+                                        * for the member. That's because it
+                                        * may be from an anonymous struct or
+                                        * union within another struct
+                                        * definition.
+                                        */
+                                       offset = kl_get_member_offset(kltp,
+                                               np->right->name);
+                                       np->type = member_to_type(kltmp, flags);
+                                       if (!np->type) {
+                                               set_eval_error(E_BAD_MEMBER);
+                                               error_token =
+                                                       np->right->tok_ptr;
+                                               free_type(tp);
+                                               return((node_t *)NULL);
+                                       }
+
+                                       /* Now free the struct type information
+                                        */
+                                       free_type(tp);
+                                       np->node_type = TYPE_DEF;
+                                       np->flags |= KLTYPE_FLAG;
+                                       np->operator = 0;
+                                       addr = 0;
+                                       if (np->left->flags & POINTER_FLAG) {
+                                               addr =  np->left->value +
+                                                       offset;
+                                       } else if (np->left->flags &
+                                                       ADDRESS_FLAG) {
+                                               addr =  np->left->address +
+                                                       offset;
+                                       }
+                                       if (addr) {
+                                               np->address = addr;
+                                               np->flags |= ADDRESS_FLAG;
+                                       }
+
+                                       if (np->type->flag == POINTER_FLAG) {
+                                               np->flags |= POINTER_FLAG;
+                                               np->value = *((kaddr_t *)addr);
+                                       } else {
+                                               np->value = addr;
+                                       }
+                                       break;
+                               }
+                       }
+                       free_nodes(np->left);
+                       free_nodes(np->right);
+                       np->left = np->right = (node_t*)NULL;
+                       return(np);
+               } else {
+                       if (!np->left || !np->right) {
+                               set_eval_error(E_MISSING_OPERAND);
+                               error_token = np->tok_ptr;
+                               return((node_t *)NULL);
+                       }
+                       if (np->left->byte_size && np->right->byte_size) {
+                               if (np->left->byte_size >
+                                               np->right->byte_size) {
+
+                                       /* Left byte_size is greater than right
+                                        */
+                                       np->byte_size = np->left->byte_size;
+                                       np->type = np->left->type;
+                                       np->flags = np->left->flags;
+                                       free_type(np->right->type);
+                               } else if (np->left->byte_size <
+                                               np->right->byte_size) {
+
+                                       /* Right byte_size is greater than left
+                                        */
+                                       np->byte_size = np->right->byte_size;
+                                       np->type = np->right->type;
+                                       np->flags = np->right->flags;
+                                       free_type(np->left->type);
+                               } else {
+
+                                       /* Left and right byte_size is equal
+                                        */
+                                       if (np->left->flags & UNSIGNED_FLAG) {
+                                               np->byte_size =
+                                                       np->left->byte_size;
+                                               np->type = np->left->type;
+                                               np->flags = np->left->flags;
+                                               free_type(np->right->type);
+                                       } else if (np->right->flags &
+                                                       UNSIGNED_FLAG) {
+                                               np->byte_size =
+                                                       np->right->byte_size;
+                                               np->type = np->right->type;
+                                               np->flags = np->right->flags;
+                                               free_type(np->left->type);
+                                       } else {
+                                               np->byte_size =
+                                                       np->left->byte_size;
+                                               np->type = np->left->type;
+                                               np->flags = np->left->flags;
+                                               free_type(np->right->type);
+                                       }
+                               }
+                       } else if (np->left->byte_size) {
+                               np->byte_size = np->left->byte_size;
+                               np->type = np->left->type;
+                               np->flags = np->left->flags;
+                               free_type(np->right->type);
+                       } else if (np->right->byte_size) {
+                               np->byte_size = np->right->byte_size;
+                               np->type = np->right->type;
+                               np->flags = np->right->flags;
+                       } else {
+                               /* XXX - No byte sizes
+                                */
+                       }
+
+                       if (apply(np, &value, flags)) {
+                               return((node_t *)NULL);
+                       }
+               }
+               np->right->type = np->left->type = (type_t*)NULL;
+
+               /* Flesh out the rest of the node struct.
+                */
+               if (np->type) {
+                       np->node_type = TYPE_DEF;
+                       np->flags |= KLTYPE_FLAG;
+               } else {
+                       np->node_type = NUMBER;
+                       np->flags &= ~(KLTYPE_FLAG);
+               }
+               np->operator = 0;
+               np->value = value;
+               kl_free_block((void *)np->left);
+               kl_free_block((void *)np->right);
+               np->left = np->right = (node_t*)NULL;
+       }
+       return(np);
+}
+
+/*
+ * replace_cast()
+ */
+static int
+replace_cast(node_t *n, int flags)
+{
+       type_t *t;
+
+       if (!n) {
+               set_eval_error(E_SYNTAX_ERROR);
+               return(-1);
+       } else if (!n->right) {
+               set_eval_error(E_SYNTAX_ERROR);
+               error_token = n->tok_ptr;
+               return(-1);
+       }
+       if (n->flags & POINTER_FLAG) {
+               if (n->right->node_type == VADDR) {
+                       if (n->right->flags & ADDRESS_FLAG) {
+                               n->value = n->right->address;
+                       } else {
+                               set_eval_error(E_SYNTAX_ERROR);
+                               error_token = n->right->tok_ptr;
+                               return(-1);
+                       }
+
+               } else {
+                       n->value = n->right->value;
+                       n->address = 0;
+               }
+       } else if (n->right->flags & ADDRESS_FLAG) {
+               n->flags |= ADDRESS_FLAG;
+               n->address = n->right->address;
+               n->value = n->right->value;
+       } else {
+               kltype_t *kltp;
+
+               if (!(t = eval_type(n))) {
+                       set_eval_error(E_BAD_TYPE);
+                       error_token = n->tok_ptr;
+                       return(-1);
+               }
+               if (t->t_kltp->kl_type != KLT_BASE) {
+
+                       kltp = kl_realtype(t->t_kltp, 0);
+                       if (kltp->kl_type != KLT_BASE) {
+                               set_eval_error(E_BAD_CAST);
+                               error_token = n->tok_ptr;
+                               return(-1);
+                       }
+               }
+               n->value = n->right->value;
+               n->type = t;
+       }
+       n->node_type = TYPE_DEF;
+       n->operator = 0;
+       free_node(n->right);
+       n->right = (node_t *)NULL;
+       return(0);
+}
+
+/*
+ * replace_indirection()
+ */
+static int
+replace_indirection(node_t *n, int flags)
+{
+       kaddr_t addr;
+       type_t *t, *tp, *rtp;
+
+       /* Make sure there is a right child and that it is a TYPE_DEF.
+        */
+       if (!n->right) {
+               set_eval_error(E_BAD_TYPE);
+               error_token = n->tok_ptr;
+               return(-1);
+       } else if (n->right->node_type != TYPE_DEF) {
+               set_eval_error(E_BAD_TYPE);
+               error_token = n->right->tok_ptr;
+               return(-1);
+       }
+
+       /* Make sure the right node contains a pointer or address value.
+        * Note that it's possible for the whatis command to generate
+        * this case without any actual pointer/address value.
+        */
+       if (!(n->right->flags & (POINTER_FLAG|ADDRESS_FLAG))) {
+               set_eval_error(E_BAD_POINTER);
+               error_token = n->right->tok_ptr;
+               return(-1);
+       }
+
+       /* Get the pointer to the first type struct and make sure
+        * it's a pointer.
+        */
+       if (!(tp = n->right->type) || (tp->flag != POINTER_FLAG)) {
+               set_eval_error(E_BAD_TYPE);
+               error_token = n->right->tok_ptr;
+               return(-1);
+       }
+
+       /* Make sure we have a pointer to a type structure.
+        */
+       if (!(n->right->flags & KLTYPE_FLAG)) {
+               set_eval_error(E_BAD_TYPE);
+               error_token = n->right->tok_ptr;
+               return(-1);
+       }
+
+       n->node_type = TYPE_DEF;
+       n->flags = KLTYPE_FLAG;
+       n->operator = 0;
+
+       if (!(t = tp->t_next)) {
+               set_eval_error(E_BAD_TYPE);
+               error_token = n->right->tok_ptr;
+               return(-1);
+       }
+
+       if (!(rtp = eval_type(n->right))) {
+               set_eval_error(E_BAD_TYPE);
+               error_token = n->right->tok_ptr;
+               return(-1);
+       }
+
+       /* Zero out the type field in the right child so
+        * it wont accidently be freed when the right child
+        * is freed (upon success).
+        */
+       n->right->type = (type_t*)NULL;
+
+       n->type = t;
+
+       /* Free the pointer struct
+        */
+       kl_free_block((void *)tp);
+
+       /* Get the pointer address
+        */
+       addr = n->address = n->right->value;
+       n->flags |= ADDRESS_FLAG;
+
+       if (rtp->t_kltp->kl_type == KLT_MEMBER) {
+               /* If this is a member, we have to step over the KLT_MEMBER
+                * struct and then make sure we have a KLT_POINTER struct.
+                * If we do, we step over it too...otherwise return an
+                * error.
+                */
+               if (rtp->t_kltp->kl_realtype->kl_type != KLT_POINTER) {
+                       set_eval_error(E_BAD_TYPE);
+                       error_token = n->right->tok_ptr;
+                       return(-1);
+               }
+               rtp->t_kltp = rtp->t_kltp->kl_realtype;
+       }
+
+       if (rtp->t_kltp->kl_type == KLT_POINTER) {
+               /* Strip off the pointer type record so that
+                * we pick up the actual type definition with
+                * our indirection.
+                */
+               rtp->t_kltp = rtp->t_kltp->kl_realtype;
+               if (rtp->t_kltp->kl_name &&
+                               !strcmp(rtp->t_kltp->kl_name, "char")) {
+                       n->flags |= STRING_FLAG;
+               }
+       }
+
+
+       /* If this is a pointer to a pointer, get the next
+        * pointer value.
+        */
+       if (n->type->flag == POINTER_FLAG) {
+               n->value = *((kaddr_t *)addr);
+
+               /* Set the appropriate node flag values
+                */
+               n->flags |= POINTER_FLAG;
+               free_node(n->right);
+               n->left = n->right = (node_t *)NULL;
+               return(0);
+       }
+       /* Zero out the type field in the right child so it doesn't
+        * accidently get freed up when the right child is freed
+        * (upon success).
+        */
+       n->right->type = (type_t*)NULL;
+       free_node(n->right);
+       n->left = n->right = (node_t *)NULL;
+       return(0);
+}
+
+/*
+ * replace_unary()
+ *
+ * Convert a unary operator node that contains a pointer to a value
+ * with a node containing the numerical result. Free the node that
+ * originally contained the value.
+ */
+static int
+replace_unary(node_t *n, int flags)
+{
+       uint64_t value;
+
+       if (!n->right) {
+               set_eval_error(E_MISSING_OPERAND);
+               error_token = n->tok_ptr;
+               return(-1);
+       }
+       if (is_unary(n->right->operator)) {
+               if (replace_unary(n->right, flags) == -1) {
+                       return(-1);
+               }
+       }
+       if (n->operator == CAST) {
+               return(replace_cast(n, flags));
+       } else if (n->operator == INDIRECTION) {
+               return(replace_indirection(n, flags));
+       } else if (n->operator == ADDRESS) {
+               type_t *t;
+
+               if (n->right->node_type == TYPE_DEF) {
+                       if (!(n->right->flags & ADDRESS_FLAG)) {
+                               set_eval_error(E_NO_ADDRESS);
+                               error_token = n->right->tok_ptr;
+                               return(-1);
+                       }
+                       t = n->right->type;
+               } else {
+                       set_eval_error(E_BAD_TYPE);
+                       error_token = n->right->tok_ptr;
+                       return(-1);
+               }
+               n->type = (type_t*)kl_alloc_block(sizeof(type_t));
+               n->type->flag = POINTER_FLAG;
+               n->type->t_next = t;
+               n->node_type = TYPE_DEF;
+               n->operator = 0;
+               n->value = n->right->address;
+               n->flags = POINTER_FLAG;
+               if (!(t = eval_type(n))) {
+                       set_eval_error(E_BAD_TYPE);
+                       error_token = n->tok_ptr;
+                       return(-1);
+               }
+               n->flags |= t->flag;
+               n->right->type = 0;
+               free_nodes(n->right);
+               n->left = n->right = (node_t *)NULL;
+               return(0);
+       } else if (apply_unary(n, &value) == -1) {
+               return(-1);
+       }
+       free_nodes(n->right);
+       n->node_type = NUMBER;
+       n->operator = 0;
+       n->left = n->right = (node_t *)NULL;
+       memcpy(&n->value, &value, sizeof(uint64_t));
+       return(0);
+}
+
+/*
+ * pointer_to_element()
+ */
+static void
+pointer_to_element(node_t *n0, node_t *n1)
+{
+       int size;
+       kltype_t *kltp, *rkltp;
+       type_t *tp;
+
+       if (!(tp = n0->type)) {
+               set_eval_error(E_BAD_INDEX);
+               error_token = n0->tok_ptr;
+               return;
+       }
+       if (tp->t_next->flag == POINTER_FLAG) {
+               size = sizeof(void *);
+       } else {
+               kltp = tp->t_next->t_kltp;
+               if (!(rkltp = kl_realtype(kltp, 0))) {
+                       set_eval_error(E_BAD_INDEX);
+                       error_token = n0->tok_ptr;
+                       return;
+               }
+               size = rkltp->kl_size;
+       }
+
+       /* Get the details on the array element
+        */
+       n0->flags |= ADDRESS_FLAG;
+       n0->address = n0->value + (n1->value * size);
+       n0->type = tp->t_next;
+       kl_free_block((char *)tp);
+       if (tp->t_next->flag == POINTER_FLAG) {
+               n0->flags |= POINTER_FLAG;
+               n0->value = *((kaddr_t *)n0->address);
+       } else {
+               n0->flags &= (~POINTER_FLAG);
+               n0->value = 0;
+       }
+}
+
+/*
+ * array_to_element()
+ */
+static void
+array_to_element(node_t *n0, node_t *n1)
+{
+       kltype_t *kltp, *rkltp, *ip, *ep;
+       type_t *tp, *troot = (type_t *)NULL;
+
+       if (!(tp = n0->type)) {
+               set_eval_error(E_BAD_INDEX);
+               error_token = n0->tok_ptr;
+               return;
+       }
+
+       /* If we are indexing a pointer, then make a call to the
+        * pointer_to_element() and return.
+        */
+       if (tp->flag == POINTER_FLAG) {
+               return(pointer_to_element(n0, n1));
+       }
+
+       if (!(kltp = n0->type->t_kltp)) {
+               set_eval_error(E_BAD_INDEX);
+               error_token = n0->tok_ptr;
+               return;
+       }
+       if (!(rkltp = kl_realtype(kltp, KLT_ARRAY))) {
+               set_eval_error(E_BAD_INDEX);
+               error_token = n0->tok_ptr;
+               return;
+       }
+       ip = rkltp->kl_indextype;
+       ep = rkltp->kl_elementtype;
+       if (!ip || !ep) {
+               set_eval_error(E_BAD_INDEX);
+               error_token = n1->tok_ptr;
+               return;
+       }
+       /* Get the details on the array element
+        */
+       n0->address = n0->address + (n1->value * ep->kl_size);
+       if (ep->kl_type == KLT_POINTER) {
+               n0->flags |= POINTER_FLAG;
+               n0->value = *((kaddr_t *)n0->address);
+       } else {
+               n0->value = 0;
+       }
+       n0->flags |= ADDRESS_FLAG;
+       kltp = ep;
+       while (kltp->kl_type == KLT_POINTER) {
+               if (troot) {
+                       tp->t_next = (type_t*)kl_alloc_block(sizeof(type_t));
+                       tp = tp->t_next;
+               } else {
+                       tp = (type_t*)kl_alloc_block(sizeof(type_t));
+                       troot = tp;
+               }
+               tp->flag = POINTER_FLAG;
+               kltp = kltp->kl_realtype;
+       }
+       if (troot) {
+               tp->t_next = (type_t*)kl_alloc_block(sizeof(type_t));
+               tp = tp->t_next;
+               n0->type = troot;
+       } else {
+               tp = (type_t*)kl_alloc_block(sizeof(type_t));
+               n0->type = tp;
+       }
+       tp->flag = KLTYPE_FLAG;
+       tp->t_kltp = ep;
+}
+
+/*
+ * number_to_size()
+ */
+int
+number_to_size(node_t *np)
+{
+       int unsigned_flag = 0;
+
+       if (np->node_type != NUMBER) {
+               set_eval_error(E_BAD_TYPE);
+               error_token = np->tok_ptr;
+               return(0);
+       }
+       if (np->flags & UNSIGNED_FLAG) {
+               unsigned_flag = 1;
+       }
+       if ((np->value >= 0) && (np->value <= 0xffffffff)) {
+               return(4);
+       } else if (((np->value >> 32) & 0xffffffff) == 0xffffffff) {
+               if (unsigned_flag) {
+                       return(8);
+               } else if (sizeof(void *) == 4) {
+                       return(4);
+               } else {
+                       return(8);
+               }
+       }
+       return(8);
+}
+
+/*
+ * number_to_type()
+ */
+kltype_t *
+number_to_type(node_t *np)
+{
+       int unsigned_flag = 0;
+       kltype_t *kltp, *rkltp = (kltype_t *)NULL;
+
+       if (np->node_type != NUMBER) {
+               set_eval_error(E_BAD_TYPE);
+               error_token = np->tok_ptr;
+               return((kltype_t *)NULL);
+       }
+       if (np->flags & UNSIGNED_FLAG) {
+               unsigned_flag = 1;
+       }
+       if ((np->value >= 0) && (np->value <= 0xffffffff)) {
+               if (unsigned_flag) {
+                       kltp = kl_find_type("uint32_t", KLT_TYPEDEF);
+               } else {
+                       kltp = kl_find_type("int32_t", KLT_TYPEDEF);
+               }
+       } else if (((np->value >> 32) & 0xffffffff) == 0xffffffff) {
+               if (unsigned_flag) {
+                       kltp = kl_find_type("uint64_t", KLT_TYPEDEF);
+               } else if (sizeof(void *) == 4) {
+                       kltp = kl_find_type("int32_t", KLT_TYPEDEF);
+               } else {
+                       kltp = kl_find_type("int64_t", KLT_TYPEDEF);
+               }
+       } else {
+               if (unsigned_flag) {
+                       kltp = kl_find_type("uint64_t", KLT_TYPEDEF);
+               } else {
+                       kltp = kl_find_type("int64_t", KLT_TYPEDEF);
+               }
+       }
+       if (kltp) {
+               if (!(rkltp = kl_realtype(kltp, 0))) {
+                       rkltp = kltp;
+               }
+       } else {
+               set_eval_error(E_BAD_TYPE);
+               error_token = np->tok_ptr;
+       }
+       return(rkltp);
+}
+
+/*
+ * type_to_number()
+ *
+ * Convert a base type to a numeric value. Return 1 on successful
+ * conversion, 0 if nothing was done.
+ */
+static int
+type_to_number(node_t *np)
+{
+       int byte_size, bit_offset, bit_size, encoding;
+       uint64_t value, value1;
+       kltype_t *kltp, *rkltp;
+
+       /* Sanity check...
+        */
+       if (np->node_type != TYPE_DEF) {
+               set_eval_error(E_NOTYPE);
+               error_token = np->tok_ptr;
+               return(0);
+       }
+       if (!np->type) {
+               set_eval_error(E_NOTYPE);
+               error_token = np->tok_ptr;
+               return(0);
+       }
+       if (np->type->flag == POINTER_FLAG) {
+               return(0);
+       }
+
+       /* Get the real type record and make sure that it is
+        * for a base type.
+        */
+       kltp = np->type->t_kltp;
+       rkltp = kl_realtype(kltp, 0);
+       if (rkltp->kl_type != KLT_BASE) {
+               set_eval_error(E_NOTYPE);
+               error_token = np->tok_ptr;
+               return(0);
+       }
+
+       byte_size = rkltp->kl_size;
+       bit_offset = rkltp->kl_bit_offset;
+       if (!(bit_size = rkltp->kl_bit_size)) {
+               bit_size = byte_size * 8;
+       }
+       encoding = rkltp->kl_encoding;
+       if (np->flags & ADDRESS_FLAG) {
+               /* FIXME: untested */
+               if (invalid_address(np->address, byte_size)) {
+                       kdb_printf("ILLEGAL ADDRESS (%lx)",
+                                               (uaddr_t)np->address);
+                       return (0);
+               }
+               kl_get_block(np->address, byte_size,(void *)&value1,(void *)0);
+       } else {
+               value1 = np->value;
+       }
+       value = kl_get_bit_value(&value1, byte_size, bit_size, bit_offset);
+       switch (byte_size) {
+
+               case 1 :
+                       if (encoding == ENC_UNSIGNED) {
+                               np->value = (unsigned char)value;
+                               np->flags |= UNSIGNED_FLAG;
+                       } else if (encoding == ENC_SIGNED) {
+                               np->value = (signed char)value;
+                       } else {
+                               np->value = (char)value;
+                       }
+                       break;
+
+               case 2 :
+                       if (encoding == ENC_UNSIGNED) {
+                               np->value = (uint16_t)value;
+                               np->flags |= UNSIGNED_FLAG;
+                       } else {
+                               np->value = (int16_t)value;
+                       }
+                       break;
+
+               case 4 :
+                       if (encoding == ENC_UNSIGNED) {
+                               np->value = (uint32_t)value;
+                               np->flags |= UNSIGNED_FLAG;
+                       } else {
+                               np->value = (int32_t)value;
+                       }
+                       break;
+
+               case 8 :
+                       if (encoding == ENC_UNSIGNED) {
+                               np->value = (uint64_t)value;
+                               np->flags |= UNSIGNED_FLAG;
+                       } else {
+                               np->value = (int64_t)value;
+                       }
+                       break;
+
+               default :
+                       set_eval_error(E_BAD_TYPE);
+                       error_token = np->tok_ptr;
+                       return(0);
+       }
+       np->byte_size = byte_size;
+       np->node_type = NUMBER;
+       return(1);
+}
+
+/*
+ * eval_type()
+ */
+static type_t *
+eval_type(node_t *n)
+{
+       type_t *t;
+
+       if (!(t = n->type)) {
+               return((type_t*)NULL);
+       }
+       while (t->flag == POINTER_FLAG) {
+               t = t->t_next;
+
+               /* If for some reason, there is no type pointer (this shouldn't
+                * happen but...), we have to make sure that we don't try to
+                * reference a NULL pointer and get a SEGV. Return an error if
+                * 't' is NULL.
+                */
+                if (!t) {
+                       return((type_t*)NULL);
+                }
+       }
+       if (t->flag == KLTYPE_FLAG) {
+               return (t);
+       }
+       return((type_t*)NULL);
+}
+
+/*
+ * expand_variables()
+ */
+static char *
+expand_variables(char *exp, int flags)
+{
+       return((char *)NULL);
+}
+
+/*
+ * eval()
+ */
+node_t *
+eval(char **exp, int flags)
+{
+       token_t *tok;
+       node_t *n, *root;
+       char *e, *s;
+
+       eval_error = 0;
+       logical_flag = 0;
+
+       /* Make sure there is an expression to evaluate
+        */
+       if (!(*exp)) {
+               return ((node_t*)NULL);
+       }
+
+       /* Expand any variables that are in the expression string. If
+        * a new string is allocated by the expand_variables() function,
+        * we need to make sure the original expression string gets
+        * freed. In any event, point s at the current expression string
+        * so that it gets freed up when we are done.
+        */
+       if ((e = expand_variables(*exp, 0))) {
+               kl_free_block((void *)*exp);
+               *exp = e;
+       } else if (eval_error) {
+               eval_error |= E_BAD_EVAR;
+               error_token = *exp;
+       }
+       s = *exp;
+       tok = get_token_list(s);
+       if (eval_error) {
+               return((node_t*)NULL);
+       }
+
+       /* Get the node_list and evaluate the expression.
+        */
+       node_list = get_node_list(tok, flags);
+       if (eval_error) {
+               free_nodelist(node_list);
+               node_list = (node_t*)NULL;
+               free_tokens(tok);
+               return((node_t*)NULL);
+       }
+       if (!(n = do_eval(flags))) {
+               if (!eval_error) {
+                       set_eval_error(E_SYNTAX_ERROR);
+                       error_token = s + strlen(s) - 1;
+               }
+               free_nodes(n);
+               free_tokens(tok);
+               return((node_t*)NULL);
+       }
+
+       if (!(root = replace(n, flags))) {
+               if (eval_error) {
+                       free_nodes(n);
+                       free_tokens(tok);
+                       return((node_t*)NULL);
+               }
+               root = n;
+       }
+
+       /* Check to see if the the result should
+        * be interpreted as 'true' or 'false'
+        */
+       if (logical_flag && ((root->value == 0) || (root->value == 1))) {
+               root->flags |= BOOLIAN_FLAG;
+       }
+       free_tokens(tok);
+       return(root);
+}
+
+/*
+ * print_number()
+ */
+void
+print_number(node_t *np, int flags)
+{
+       int size;
+       unsigned long long value;
+
+       if ((size = number_to_size(np)) && (size != sizeof(uint64_t))) {
+               value = np->value & (((uint64_t)1 << (uint64_t)(size*8))-1);
+       } else {
+               value = np->value;
+       }
+       if (flags & C_HEX) {
+               kdb_printf("0x%llx", value);
+       } else if (flags & C_BINARY) {
+               kdb_printf("0b");
+               kl_binary_print(value);
+       } else {
+               if (np->flags & UNSIGNED_FLAG) {
+                       kdb_printf("%llu", value);
+               } else {
+                       kdb_printf("%lld", np->value);
+               }
+       }
+}
+
+/*
+ * print_string()
+ */
+void
+print_string(kaddr_t addr, int size)
+{
+       int i;
+       char *str;
+
+       if (!size) {
+               size = 255;
+       }
+       /* FIXME: untested */
+       if (invalid_address(addr, size)) {
+               klib_error = KLE_INVALID_PADDR;
+               return;
+       }
+       str = (char*)kl_alloc_block(size);
+       kl_get_block(addr, size, (void *)str, (void *)0);
+       kdb_printf("\"%s", str);
+       for (i = 0; i < size; i++) {
+               if (!str[i]) {
+                       break;
+               }
+       }
+       if (KL_ERROR || (i == size)) {
+               kdb_printf("...");
+       }
+       kdb_printf("\"");
+       kl_free_block(str);
+}
+
+/*
+ * kl_print_error()
+ */
+void
+kl_print_error(void)
+{
+       int ecode;
+
+       ecode = klib_error & 0xffffffff;
+       switch(ecode) {
+
+               /** General klib error codes
+                **/
+               case KLE_NO_MEMORY:
+                       kdb_printf("insufficient memory");
+                       break;
+               case KLE_OPEN_ERROR:
+                       kdb_printf("unable to open file");
+                       break;
+               case KLE_ZERO_BLOCK:
+                       kdb_printf("tried to allocate a zero-sized block");
+                       break;
+               case KLE_INVALID_VALUE:
+                       kdb_printf("invalid input value");
+                       break;
+               case KLE_NULL_BUFF:
+                       kdb_printf( "NULL buffer pointer");
+                       break;
+               case KLE_ZERO_SIZE:
+                       kdb_printf("zero sized block requested");
+                       break;
+               case KLE_ACTIVE:
+                       kdb_printf("operation not supported on a live system");
+                       break;
+               case KLE_UNSUPPORTED_ARCH:
+                       kdb_printf("unsupported architecture");
+                       break;
+               case KLE_MISC_ERROR:
+                       kdb_printf("KLIB error");
+                       break;
+               case KLE_NOT_SUPPORTED:
+                       kdb_printf("operation not supported");
+                       break;
+               case KLE_UNKNOWN_ERROR:
+                       kdb_printf("unknown error");
+                       break;
+
+               /** memory error codes
+                **/
+               case KLE_BAD_MAP_FILE:
+                       kdb_printf("bad map file");
+                       break;
+               case KLE_BAD_DUMP:
+                       kdb_printf("bad dump file");
+                       break;
+               case KLE_BAD_DUMPTYPE:
+                       kdb_printf("bad dumptype");
+                       break;
+               case KLE_INVALID_LSEEK:
+                       kdb_printf("lseek error");
+                       break;
+               case KLE_INVALID_READ:
+                       kdb_printf("not found in dump file");
+                       break;
+               case KLE_BAD_KERNINFO:
+                       kdb_printf("bad kerninfo struct");
+                       break;
+               case KLE_INVALID_PADDR:
+                       kdb_printf("invalid physical address");
+                       break;
+               case KLE_INVALID_VADDR:
+                       kdb_printf("invalid virtual address");
+                       break;
+               case KLE_INVALID_VADDR_ALIGN:
+                       kdb_printf("invalid vaddr alignment");
+                       break;
+               case KLE_INVALID_MAPPING:
+                       kdb_printf("invalid address mapping");
+                       break;
+               case KLE_PAGE_NOT_PRESENT:
+                       kdb_printf("page not present");
+                       break;
+               case KLE_BAD_ELF_FILE:
+                       kdb_printf("bad elf file");
+                       break;
+               case KLE_ARCHIVE_FILE:
+                       kdb_printf("archive file");
+                       break;
+               case KLE_MAP_FILE_PRESENT:
+                       kdb_printf("map file present");
+                       break;
+               case KLE_BAD_MAP_FILENAME:
+                       kdb_printf("bad map filename");
+                       break;
+               case KLE_BAD_DUMP_FILENAME:
+                       kdb_printf("bad dump filename");
+                       break;
+               case KLE_BAD_NAMELIST_FILE:
+                       kdb_printf("bad namelist file");
+                       break;
+               case KLE_BAD_NAMELIST_FILENAME:
+                       kdb_printf("bad namelist filename");
+                       break;
+
+               /** symbol error codes
+                **/
+               case KLE_NO_SYMTAB:
+                       kdb_printf("no symtab");
+                       break;
+               case KLE_NO_SYMBOLS:
+                       kdb_printf("no symbol information");
+                       break;
+               case KLE_NO_MODULE_LIST:
+                       kdb_printf("kernel without module support");
+                       break;
+
+               /** kernel data error codes
+                **/
+               case KLE_INVALID_KERNELSTACK:
+                       kdb_printf("invalid kernel stack");
+                       break;
+               case KLE_INVALID_STRUCT_SIZE:
+                       kdb_printf("invalid struct size");
+                       break;
+               case KLE_BEFORE_RAM_OFFSET:
+                       kdb_printf("physical address proceeds start of RAM");
+                       break;
+               case KLE_AFTER_MAXPFN:
+                       kdb_printf("PFN exceeds maximum PFN");
+                       break;
+               case KLE_AFTER_PHYSMEM:
+                       kdb_printf("address exceeds physical memory");
+                       break;
+               case KLE_AFTER_MAXMEM:
+                       kdb_printf("address exceeds maximum physical address");
+                       break;
+               case KLE_PHYSMEM_NOT_INSTALLED:
+                       kdb_printf("physical memory not installed");
+                       break;
+               case KLE_NO_DEFTASK:
+                       kdb_printf("default task not set");
+                       break;
+               case KLE_PID_NOT_FOUND:
+                       kdb_printf("PID not found");
+                       break;
+               case KLE_DEFTASK_NOT_ON_CPU:
+                       kdb_printf("default task not running on a cpu");
+                       break;
+               case KLE_NO_CURCPU:
+                       kdb_printf("current cpu could not be determined");
+                       break;
+
+               case KLE_KERNEL_MAGIC_MISMATCH:
+                       kdb_printf("kernel_magic mismatch "
+                               "of map and memory image");
+                       break;
+
+               case KLE_INVALID_DUMP_HEADER:
+                       kdb_printf("invalid dump header in dump");
+                       break;
+
+               case KLE_DUMP_INDEX_CREATION:
+                       kdb_printf("cannot create index file");
+                       break;
+
+               case KLE_DUMP_HEADER_ONLY:
+                       kdb_printf("dump only has a dump header");
+                       break;
+
+               case KLE_NO_END_SYMBOL:
+                       kdb_printf("no _end symbol in kernel");
+                       break;
+
+               case KLE_NO_CPU:
+                       kdb_printf("CPU not installed");
+                       break;
+
+               default:
+                       break;
+       }
+       kdb_printf("\n");
+}
+
+/*
+ * kl_print_string()
+ *
+ *   print out a string, translating all embeded control characters
+ *   (e.g., '\n' for newline, '\t' for tab, etc.)
+ */
+void
+kl_print_string(char *s)
+{
+       char *sp, *cp;
+
+       kl_reset_error();
+
+       if (!(sp = s)) {
+               klib_error = KLE_BAD_STRING;
+               return;
+       }
+       /* FIXME: untested */
+       if (invalid_address((kaddr_t)sp, 1)) {
+               klib_error = KLE_INVALID_PADDR;
+               return;
+       }
+
+       while (sp) {
+               if ((cp = strchr(sp, '\\'))) {
+                       switch (*(cp + 1)) {
+
+                               case 'n' :
+                                       *cp++ = '\n';
+                                       *cp++ = 0;
+                                       break;
+
+                               case 't' :
+                                       *cp++ = '\t';
+                                       *cp++ = 0;
+                                       break;
+
+                               default :
+                                       if (*(cp + 1) == 0) {
+                                               klib_error = KLE_BAD_STRING;
+                                               return;
+                                       }
+                                       /* Change the '\' character to a zero
+                                        * and then print the string (the rest
+                                        * of the string will be picked
+                                        * up on the next pass).
+                                        */
+                                       *cp++ = 0;
+                                       break;
+                       }
+                       kdb_printf("%s", sp);
+                       sp = cp;
+               } else {
+                       kdb_printf("%s", sp);
+                       sp = 0;
+               }
+       }
+}
+
+/*
+ * print_eval_results()
+ */
+int
+print_eval_results(node_t *np, int flags)
+{
+       int size, i, count, ptr_cnt = 0;
+       kaddr_t addr;
+       char *typestr;
+       kltype_t *kltp, *rkltp = NULL, *nkltp;
+       type_t *tp;
+
+       /* Print the results
+        */
+       switch (np->node_type) {
+
+               case NUMBER:
+                       print_number(np, flags);
+                       break;
+
+               case TYPE_DEF: {
+
+                       /* First, determine the number of levels of indirection
+                        * by determining the number of pointer type records.
+                        */
+                       if ((tp = np->type)) {
+                               while (tp && (tp->flag == POINTER_FLAG)) {
+                                       ptr_cnt++;
+                                       tp = tp->t_next;
+                               }
+                               if (tp) {
+                                       rkltp = tp->t_kltp;
+                               }
+                       }
+                       if (!rkltp) {
+                               kdb_printf("Type information not available\n");
+                               return(1);
+                       }
+
+                       if (ptr_cnt) {
+
+                               /* If this is a member, we need to get the
+                                * first type record.
+                                */
+                               if (rkltp->kl_type == KLT_MEMBER) {
+                                       /* We need to get down to the first
+                                        * real type record...
+                                        */
+                                       rkltp = rkltp->kl_realtype;
+                               }
+
+                               /* step over any KLT_POINTER type records.
+                                */
+                               while (rkltp && rkltp->kl_type == KLT_POINTER) {
+                                       rkltp = rkltp->kl_realtype;
+                               }
+                               if (!rkltp) {
+                                       kdb_printf("Bad type information\n");
+                                       return(1);
+                               }
+                               typestr = rkltp->kl_typestr;
+                               if (rkltp->kl_type == KLT_FUNCTION) {
+                                       kdb_printf("%s(", typestr);
+                               } else if (rkltp->kl_type == KLT_ARRAY) {
+                                       kdb_printf("(%s(", typestr);
+                               } else {
+                                       kdb_printf("(%s", typestr);
+                               }
+                               for (i = 0; i < ptr_cnt; i++) {
+                                       kdb_printf("*");
+                               }
+                               if (rkltp->kl_type == KLT_FUNCTION) {
+                                       kdb_printf(")(");
+                               } else if (rkltp->kl_type == KLT_ARRAY) {
+                                       kdb_printf(")");
+
+                                       nkltp = rkltp;
+                                       while (nkltp->kl_type == KLT_ARRAY) {
+                                               count = nkltp->kl_high_bounds -
+                                                 nkltp->kl_low_bounds + 1;
+                                               kdb_printf("[%d]", count);
+                                               nkltp = nkltp->kl_elementtype;
+                                       }
+                               }
+                               kdb_printf(") ");
+                               kdb_printf("0x%llx", np->value);
+
+                               if (ptr_cnt > 1) {
+                                       break;
+                               }
+
+                               if ((rkltp->kl_type == KLT_BASE) &&
+                                       rkltp->kl_encoding == ENC_CHAR) {
+                                       kdb_printf(" = ");
+                                       print_string(np->value, 0);
+                               }
+                               break;
+                       }
+                       if (np->flags & KLTYPE_FLAG) {
+                               void * ptr;
+
+                               /* Get the type information. It's possible
+                                * that the type is a member. In which case,
+                                * the size may only be from this record
+                                * (which would be the casse if this is an
+                                * array). We must check the original type
+                                * record first, and try the realtype record
+                                * if the value is zero.
+                                */
+                               kltp = np->type->t_kltp;
+
+                               if (kltp->kl_type == KLT_MEMBER) {
+                                       rkltp = kltp->kl_realtype;
+                               } else {
+                                       rkltp = kltp;
+                               }
+
+                               /* Check to see if this is a typedef. If
+                                * it is, then it might be a typedef for
+                                * a pointer type. Don't walk to the last
+                                * type record.
+                                */
+                               while (rkltp->kl_type == KLT_TYPEDEF) {
+                                       rkltp = rkltp->kl_realtype;
+                               }
+
+                               if (rkltp->kl_type == KLT_POINTER) {
+                                       kdb_printf("0x%llx", np->value);
+                                       break;
+                               }
+                               if((rkltp->kl_name != 0) &&
+                                       !(strcmp(rkltp->kl_name, "void"))) {
+                                       /* we are about to dereference
+                                        * a void pointer.
+                                        */
+                                       kdb_printf("Can't dereference a "
+                                               "generic pointer.\n");
+                                       return(1);
+                               }
+
+                               size = rkltp->kl_size;
+                               if (!size || (size < 0)) {
+                                       size = kltp->kl_size;
+                               }
+
+                               if(rkltp->kl_type==KLT_ARRAY) {
+                                       size = rkltp->kl_high_bounds -
+                                               rkltp->kl_low_bounds + 1;
+                                       if(rkltp->kl_elementtype == NULL){
+                                               kdb_printf("Incomplete array"
+                                                       " type.\n");
+                                                       return(1);
+                                       }
+                                       if(rkltp->kl_elementtype->kl_type ==
+                                                       KLT_POINTER){
+                                               size *= sizeof(void *);
+                                       } else {
+                                               size *= rkltp->kl_elementtype->kl_size;
+                                       }
+                               }
+                               if(size){
+                                       ptr = kl_alloc_block(size);
+                               } else {
+                                       ptr = NULL;
+                               }
+                               if ((rkltp->kl_type == KLT_BASE) &&
+                                               !(np->flags & ADDRESS_FLAG)) {
+                                       switch (size) {
+                                               case 1:
+                                                       *(unsigned char *)ptr =
+                                                               np->value;
+                                                       break;
+
+                                               case 2:
+                                                       *(unsigned short *)ptr =
+                                                               np->value;
+                                                       break;
+
+                                               case 4:
+                                                       *(unsigned int *)ptr =
+                                                               np->value;
+                                                       break;
+
+                                               case 8:
+                                                       *(unsigned long long *)
+                                                               ptr = np->value;
+                                                       break;
+                                       }
+                                       kl_print_type(ptr, rkltp, 0,
+                                               flags|SUPPRESS_NAME);
+                                       kl_free_block(ptr);
+                                       return(1);
+                               }
+
+                               if(size){
+                                       addr = np->address;
+                                       if (invalid_address(addr, size)) {
+                                               kdb_printf (
+                                                "invalid address %#lx\n",
+                                                        addr);
+                                               return 1;
+                                       }
+                                       kl_get_block(addr, size, (void *)ptr,
+                                                       (void *)0);
+                                       if (KL_ERROR) {
+                                               kl_print_error();
+                                               kl_free_block(ptr);
+                                               return(1);
+                                       }
+                               }
+                               /* Print out the actual type
+                                */
+                               switch (rkltp->kl_type) {
+                                       case KLT_STRUCT:
+                                       case KLT_UNION:
+                                               kl_print_type(ptr, rkltp, 0,
+                                                       flags);
+                                               break;
+
+                                       case KLT_ARRAY:
+                                               kl_print_type(ptr, rkltp, 0,
+                                                       flags| SUPPRESS_NAME);
+                                               break;
+
+                                       default:
+                                               kl_print_type(ptr, rkltp, 0,
+                                                       (flags|
+                                                       SUPPRESS_NAME|
+                                                       SUPPRESS_NL));
+                                               break;
+                               }
+                               if(ptr){
+                                       kl_free_block(ptr);
+                               }
+                       }
+                       break;
+               }
+
+               case VADDR:
+                       /* If we get here, there was no type info available.
+                        * The ADDRESS_FLAG should be set (otherwise we
+                        * would have returned an error). So, print out
+                        * the address.
+                        */
+                       kdb_printf("0x%lx", np->address);
+                       break;
+
+               default:
+                       if (np->node_type == TEXT) {
+                               kl_print_string(np->name);
+                               if (KL_ERROR) {
+                                       kl_print_error();
+                                       return(1);
+                               }
+                       } else if (np->node_type == CHARACTER) {
+                               kdb_printf("\'%c\'", (char)np->value);
+                       }
+                       break;
+       }
+       return(0);
+}
+
+/*
+ * print_eval_error()
+ */
+void
+print_eval_error(
+       char *cmdname,
+       char *s,
+       char *bad_ptr,
+       uint64_t error,
+       int flags)
+{
+       int i, cmd_len;
+
+       kdb_printf("%s %s\n", cmdname, s);
+       cmd_len = strlen(cmdname);
+
+       if (!bad_ptr) {
+               for (i = 0; i < (strlen(s) + cmd_len); i++) {
+                       kdb_printf(" ");
+               }
+       } else {
+               for (i = 0; i < (bad_ptr - s + 1 + cmd_len); i++) {
+                       kdb_printf(" ");
+               }
+       }
+       kdb_printf("^ ");
+       switch (error) {
+               case E_OPEN_PAREN :
+                       kdb_printf("Too many open parenthesis\n");
+                       break;
+
+               case E_CLOSE_PAREN :
+                       kdb_printf("Too many close parenthesis\n");
+                       break;
+
+               case E_BAD_STRUCTURE :
+                       kdb_printf("Invalid structure\n");
+                       break;
+
+               case E_MISSING_STRUCTURE :
+                       kdb_printf("Missing structure\n");
+                       break;
+
+               case E_BAD_MEMBER :
+                       kdb_printf("No such member\n");
+                       break;
+
+               case E_BAD_OPERATOR :
+                       kdb_printf("Invalid operator\n");
+                       break;
+
+               case E_MISSING_OPERAND :
+                       kdb_printf("Missing operand\n");
+                       break;
+
+               case E_BAD_OPERAND :
+                       kdb_printf("Invalid operand\n");
+                       break;
+
+               case E_BAD_TYPE :
+                       kdb_printf("Invalid type\n");
+                       if (!have_debug_file) {
+                               kdb_printf("no debuginfo file\n");
+                               return;
+                       }
+                       break;
+
+               case E_NOTYPE :
+                       kdb_printf("Could not find type information\n");
+                       break;
+
+               case E_BAD_POINTER :
+                       kdb_printf("Invalid pointer\n");
+                       break;
+
+               case E_BAD_INDEX :
+                       kdb_printf("Invalid array index\n");
+                       break;
+
+               case E_BAD_CHAR :
+                       kdb_printf("Invalid character value\n");
+                       break;
+
+               case E_BAD_STRING :
+                       kdb_printf("Non-termining string\n");
+                       break;
+
+               case E_END_EXPECTED :
+                       kdb_printf(
+                               "Expected end of print statement\n");
+                       break;
+
+               case E_BAD_EVAR :
+                       kdb_printf("Invalid eval variable\n");
+                       break;
+
+               case E_BAD_VALUE :
+                       kdb_printf("Invalid value\n");
+                       break;
+
+               case E_NO_VALUE :
+                       kdb_printf("No value supplied\n");
+                       break;
+
+               case E_DIVIDE_BY_ZERO :
+                       kdb_printf("Divide by zero\n");
+                       break;
+
+               case E_BAD_CAST :
+                       kdb_printf("Invalid cast\n");
+                       break;
+
+               case E_NO_ADDRESS :
+                       kdb_printf("Not an address\n");
+                       break;
+
+               case E_SINGLE_QUOTE :
+                       kdb_printf("Missing single quote\n");
+                       break;
+
+               case E_BAD_WHATIS :
+                       kdb_printf("Invalid whatis Operation\n");
+                       break;
+
+               case E_NOT_IMPLEMENTED :
+                       kdb_printf("Not implemented\n");
+                       break;
+
+               default :
+                       kdb_printf("Syntax error\n");
+                       break;
+       }
+}
+
+/*
+ * single_type()
+ */
+void
+single_type(char *str)
+{
+       char            buffer[256], *type_name;
+       kltype_t        *kltp;
+       syment_t        *sp;
+
+       type_name = buffer;
+       strcpy(type_name, str);
+
+       if (have_debug_file) {
+               if ((kltp = kl_find_type(type_name, KLT_TYPE))) {
+                       kl_print_type((void *)NULL, kltp, 0, C_SHOWOFFSET);
+                       return;
+               }
+               if ((kltp = kl_find_type(type_name, KLT_TYPEDEF))) {
+                       kdb_printf ("typedef %s:\n", type_name);
+                       kl_print_type((void *)NULL, kltp, 0, C_SHOWOFFSET);
+                       return;
+               }
+       }
+       if ((sp = kl_lkup_symname(type_name))) {
+               kdb_printf ("symbol %s value: %#lx\n", str, sp->s_addr);
+               kl_free_block((void *)sp);
+               return;
+       }
+       kdb_printf("could not find type or symbol information for %s\n",
+               type_name);
+       return;
+}
+
+/*
+ * sizeof_type()
+ */
+void
+sizeof_type(char *str)
+{
+       char            buffer[256], *type_name;
+       kltype_t        *kltp;
+
+       type_name = buffer;
+       strcpy(type_name, str);
+
+       if ((kltp = kl_find_type(type_name, KLT_TYPE))) {
+               kdb_printf ("%s %d %#x\n", kltp->kl_typestr,
+                               kltp->kl_size, kltp->kl_size);
+               return;
+       }
+       if ((kltp = kl_find_type(type_name, KLT_TYPEDEF))) {
+               kdb_printf ("%s %d %#x\n", kltp->kl_typestr,
+                               kltp->kl_size, kltp->kl_size);
+               return;
+       }
+       kdb_printf("could not find type information for %s\n", type_name);
+}
+
+EXPORT_SYMBOL(have_debug_file);
+EXPORT_SYMBOL(type_tree);
+EXPORT_SYMBOL(typedef_tree);
+
+#if defined(CONFIG_X86_32)
+/* needed for i386: */
+#include <linux/types.h>
+#include <asm/div64.h>
+/*
+ * Generic C version of full 64 bit by 64 bit division
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * Code generated for this function might be very inefficient
+ * for some CPUs, can be overridden by linking arch-specific
+ * assembly versions such as arch/sparc/lib/udivdi.S
+ */
+uint64_t
+__udivdi3(uint64_t dividend, uint64_t divisor)
+{
+       uint32_t d = divisor;
+       /* Scale divisor to 32 bits */
+       if (divisor > 0xffffffffULL) {
+               unsigned int shift = fls(divisor >> 32);
+               d = divisor >> shift;
+               dividend >>= shift;
+       }
+       /* avoid 64 bit division if possible */
+       if (dividend >> 32)
+               do_div(dividend, d);
+       else
+               dividend = (uint32_t) dividend / d;
+       return dividend;
+}
+
+int64_t
+__divdi3(int64_t dividend, int64_t divisor)
+{
+       int32_t d = divisor;
+       /* Scale divisor to 32 bits */
+       if (divisor > 0xffffffffLL) {
+               unsigned int shift = fls(divisor >> 32);
+               d = divisor >> shift;
+               dividend >>= shift;
+       }
+       /* avoid 64 bit division if possible */
+       if (dividend >> 32)
+               do_div(dividend, d);
+       else
+               dividend = (int32_t) dividend / d;
+       return dividend;
+}
+
+uint64_t
+__umoddi3(uint64_t dividend, uint64_t divisor)
+{
+       return dividend - (__udivdi3(dividend, divisor) * divisor);
+}
+
+int64_t
+__moddi3(int64_t dividend, int64_t divisor)
+{
+       return dividend - (__divdi3(dividend, divisor) * divisor);
+}
+#endif /* CONFIG_x86_32 */
diff --git a/kdb/kdbmain.c b/kdb/kdbmain.c
new file mode 100644 (file)
index 0000000..5f50dc4
--- /dev/null
@@ -0,0 +1,4340 @@
+/*
+ * Kernel Debugger Architecture Independent Main Code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
+ */
+
+/*
+ * Updated for Xscale (R) architecture support
+ * Eddie Dong <eddie.dong@intel.com> 8 Jan 03
+ */
+
+#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/utsname.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/mm.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>
+#include <linux/ptrace.h>
+#include <linux/sysctl.h>
+#if defined(CONFIG_LKCD_DUMP) || defined(CONFIG_LKCD_DUMP_MODULE)
+#include <linux/dump.h>
+#endif
+#include <linux/cpu.h>
+#include <linux/kdebug.h>
+#ifdef CONFIG_KDB_KDUMP
+#include <linux/kexec.h>
+#endif
+
+#include <acpi/acpi_bus.h>
+
+#include <asm/system.h>
+#include <asm/kdebug.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+char kdb_debug_info_filename[256] = {""};
+EXPORT_SYMBOL(kdb_debug_info_filename);
+#define GREP_LEN 256
+char kdb_grep_string[GREP_LEN];
+int kdb_grepping_flag;
+EXPORT_SYMBOL(kdb_grepping_flag);
+int kdb_grep_leading;
+int kdb_grep_trailing;
+
+/*
+ * Kernel debugger state flags
+ */
+volatile int kdb_flags;
+atomic_t kdb_event;
+atomic_t kdb_8250;
+
+/*
+ * kdb_lock protects updates to kdb_initial_cpu.  Used to
+ * single thread processors through the kernel debugger.
+ */
+static DEFINE_SPINLOCK(kdb_lock);
+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 */
+
+volatile int kdb_state[NR_CPUS];               /* Per cpu state */
+
+const struct task_struct *kdb_current_task;
+EXPORT_SYMBOL(kdb_current_task);
+struct pt_regs *kdb_current_regs;
+
+#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;
+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 kdba_setjmp
+       /*
+        * 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;
+#endif /* kdba_setjmp */
+
+       /*
+        * 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=9",                   /* 9 possible args in bt */
+ KDB_PLATFORM_ENV,
+ "DTABCOUNT=30",
+ "NOSECT=1",
+ (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 *));
+
+/* external commands: */
+int kdb_debuginfo_print(int argc, const char **argv);
+int kdb_pxhelp(int argc, const char **argv);
+int kdb_walkhelp(int argc, const char **argv);
+int kdb_walk(int argc, const char **argv);
+
+/*
+ * 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[] = "\eKDB";
+EXPORT_SYMBOL(kdb_serial_str);
+
+struct task_struct *
+kdb_curr_task(int cpu)
+{
+       struct task_struct *p = curr_task(cpu);
+#ifdef _TIF_MCA_INIT
+       struct kdb_running_process *krp = kdb_running_process + cpu;
+       if ((task_thread_info(p)->flags & _TIF_MCA_INIT) && krp->p)
+               p = krp->p;
+#endif
+       return p;
+}
+
+/*
+ * 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 NULL;
+}
+
+/*
+ * 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 = NULL;
+
+       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:
+ */
+
+static 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, NULL, 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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_set(int argc, const char **argv)
+{
+       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;
+}
+
+static int
+kdb_check_regs(void)
+{
+       if (!kdb_current_regs) {
+               kdb_printf("No current kdb registers."
+                          "  You may need to select another task\n");
+               return KDB_BADREG;
+       }
+       return 0;
+}
+
+/*
+ * 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)
+{
+       kdb_machreg_t addr;
+       unsigned 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] == '%') {
+               if ((diag = kdb_check_regs()))
+                       return diag;
+               diag = kdba_getregcontents(&symname[1], kdb_current_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 (diagnostic is %d)\n", diag);
+               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
+ * 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);
+
+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_KDB);
+       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_KDB);
+       kfree(save_command);
+       return 0;
+}
+
+static int
+kdb_defcmd(int argc, const char **argv)
+{
+       struct defcmd_set *save_defcmd_set = defcmd_set, *s;
+       if (defcmd_in_progress) {
+               kdb_printf("kdb: nested defcmd detected, assuming missing endefcmd\n");
+               kdb_defcmd2("endefcmd", "endefcmd");
+       }
+       if (argc == 0) {
+               int i;
+               for (s = defcmd_set; s < defcmd_set + defcmd_set_count; ++s) {
+                       kdb_printf("defcmd %s \"%s\" \"%s\"\n", s->name, s->usage, s->help);
+                       for (i = 0; i < s->count; ++i)
+                               kdb_printf("%s", s->command[i]);
+                       kdb_printf("endefcmd\n");
+               }
+               return 0;
+       }
+       if (argc != 3)
+               return KDB_ARGCOUNT;
+       defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set), GFP_KDB);
+       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_KDB);
+       s->usage = kdb_strdup(argv[2], GFP_KDB);
+       s->help = kdb_strdup(argv[3], GFP_KDB);
+       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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_exec_defcmd(int argc, const char **argv)
+{
+       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])))
+                       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];
+
+/*
+ * The "str" argument may point to something like  | grep xyz
+ *
+ */
+static void
+parse_grep(const char *str)
+{
+       int     len;
+       char    *cp = (char *)str, *cp2;
+
+       /* sanity check: we should have been called with the \ first */
+       if (*cp != '|')
+               return;
+       cp++;
+       while (isspace(*cp)) cp++;
+       if (strncmp(cp,"grep ",5)) {
+               kdb_printf ("invalid 'pipe', see grephelp\n");
+               return;
+       }
+       cp += 5;
+       while (isspace(*cp)) cp++;
+       cp2 = strchr(cp, '\n');
+       if (cp2)
+               *cp2 = '\0'; /* remove the trailing newline */
+       len = strlen(cp);
+       if (len == 0) {
+               kdb_printf ("invalid 'pipe', see grephelp\n");
+               return;
+       }
+       /* now cp points to a nonzero length search string */
+       if (*cp == '"') {
+               /* allow it be "x y z" by removing the "'s - there must
+                  be two of them */
+               cp++;
+               cp2 = strchr(cp, '"');
+               if (!cp2) {
+                       kdb_printf ("invalid quoted string, see grephelp\n");
+                       return;
+               }
+               *cp2 = '\0'; /* end the string where the 2nd " was */
+       }
+       kdb_grep_leading = 0;
+       if (*cp == '^') {
+               kdb_grep_leading = 1;
+               cp++;
+       }
+       len = strlen(cp);
+       kdb_grep_trailing = 0;
+       if (*(cp+len-1) == '$') {
+               kdb_grep_trailing = 1;
+               *(cp+len-1) = '\0';
+       }
+       len = strlen(cp);
+       if (!len) return;
+       if (len >= GREP_LEN) {
+               kdb_printf ("search string too long\n");
+               return;
+       }
+       strcpy(kdb_grep_string, cp);
+       kdb_grepping_flag++;
+       return;
+}
+
+/*
+ * 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)
+{
+       static char *argv[MAXARGC];
+       static int argc = 0;
+       static char cbuf[CMD_BUFLEN+2];
+       char *cp;
+       char *cpp, quoted;
+       kdbtab_t *tp;
+       int i, escaped, ignore_errors = 0, check_grep;
+
+       /*
+        * First tokenize the command string.
+        */
+       cp = (char *)cmdstr;
+       kdb_grepping_flag = check_grep = 0;
+
+       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') || (*cp == '#' && !defcmd_in_progress))
+                               break;
+                       /* special case: check for | grep pattern */
+                       if (*cp == '|') {
+                               check_grep++;
+                               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 (check_grep)
+               parse_grep(cp);
+       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);
+               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)) {
+                       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(void)
+{
+#if defined(CONFIG_LKCD_DUMP) || defined(CONFIG_LKCD_DUMP_MODULE)
+       kdb_printf("Forcing dump (if configured)\n");
+       console_loglevel = 8;   /* to see the dump messages */
+       dump("kdb_do_dump");
+#endif
+}
+
+/*
+ * kdb_reboot
+ *
+ *     This function implements the 'reboot' command.  Reboot the system
+ *     immediately.
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     Shouldn't return from this function.
+ */
+
+static int
+kdb_reboot(int argc, const char **argv)
+{
+       emergency_restart();
+       kdb_printf("Hmm, kdb_reboot did not reboot, spinning here\n");
+       while (1) {};
+       /* NOTREACHED */
+       return 0;
+}
+
+#ifdef CONFIG_KDB_KDUMP
+
+int kdb_kdump_state = KDB_KDUMP_RESET; /* KDB kdump state */
+int kdb_kdump_reason = 0;      /* values as defined KDB entry reasons */
+
+static int kdb_cpu(int argc, const char **argv);
+
+/*
+ * kdb_kdump_check
+ *
+ *     This is where the kdump on monarch cpu is handled.
+ *
+ */
+void kdb_kdump_check(struct pt_regs *regs)
+{
+       if (kdb_kdump_state != KDB_KDUMP_RESET) {
+               crash_kexec(regs);
+
+               /* If the call above returned then something
+                  didn't work */
+               kdb_printf("kdb_kdump_check: crash_kexec failed!\n");
+               kdb_printf("  Please check if the kdump kernel has been properly loaded\n");
+               kdb_kdump_state = KDB_KDUMP_RESET;
+       }
+}
+
+
+/*
+ * kdb_kdump
+ *
+ *     This function implements the 'kdump' command.
+ *
+ * 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.
+ */
+
+static int
+kdb_kdump(int argc, const char **argv)
+{
+       char cpu_id[6];         /* up to 99,999 cpus */
+       const char *cpu_argv[] = {NULL, cpu_id, NULL};
+       int ret;
+
+       kdb_kdump_state = KDB_KDUMP_KDUMP;
+       /* Switch back to the initial cpu before process kdump command */
+       if (smp_processor_id() != kdb_initial_cpu) {
+               sprintf(cpu_id, "%d", kdb_initial_cpu);
+               ret = kdb_cpu(1, cpu_argv);
+               if (ret != KDB_CMD_CPU) {
+                       kdb_printf("kdump: Failed to switch to initial cpu %d;"
+                               " aborted\n", kdb_initial_cpu);
+                       kdb_kdump_state = KDB_KDUMP_RESET;
+               }
+       } else
+               ret = KDB_CMD_CPU;
+
+       return ret;
+}
+
+#endif /* CONFIG_KDB_KDUMP */
+
+static int
+kdb_quiet(int reason)
+{
+       return (reason == KDB_REASON_CPU_UP || reason == KDB_REASON_SILENT);
+}
+
+/*
+ * 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 or CPU_UP, 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
+ */
+
+static int
+kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, kdb_dbtrap_t db_result)
+{
+       char *cmdbuf;
+       int diag;
+       struct task_struct *kdb_current = kdb_curr_task(smp_processor_id());
+
+#ifdef CONFIG_KDB_KDUMP
+       kdb_kdump_check(regs);
+#endif
+
+       /* If kdb has been entered for an event which has been/will be
+        * recovered then silently return.  We have to get this far into kdb in
+        * order to synchronize all the cpus, typically only one cpu (monarch)
+        * knows that the event is recoverable but the other cpus (slaves) may
+        * also be driven into kdb before that decision is made by the monarch.
+        *
+        * To pause in kdb even for recoverable events, 'set RECOVERY_PAUSE 1'
+        */
+       KDB_DEBUG_STATE("kdb_local 1", reason);
+       if (reason == KDB_REASON_ENTER
+           && KDB_FLAG(RECOVERY)
+           && !KDB_FLAG(CATASTROPHIC)) {
+               int recovery_pause = 0;
+               kdbgetintenv("RECOVERY_PAUSE", &recovery_pause);
+               if (recovery_pause == 0)
+                       reason = KDB_REASON_SILENT;
+               else
+                       kdb_printf("%s: Recoverable error detected but"
+                                  " RECOVERY_PAUSE is set, staying in KDB\n",
+                                  __FUNCTION__);
+       }
+
+       KDB_DEBUG_STATE("kdb_local 2", reason);
+       kdb_go_count = 0;
+       if (kdb_quiet(reason)) {
+               /* no message */
+       } else if (reason == KDB_REASON_DEBUG) {
+               /* special case below */
+       } else {
+               kdb_printf("\nEntering kdb (current=0x%p, pid %d) ", kdb_current, kdb_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, pid %d) ", kdb_current, kdb_current->pid);
+#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.
+                        */
+                       KDB_DEBUG_STATE("kdb_local 3", reason);
+                       return KDB_CMD_SSB;     /* Continue with SSB command */
+
+                       break;
+               case KDB_DB_SS:
+                       break;
+               case KDB_DB_SSBPT:
+                       KDB_DEBUG_STATE("kdb_local 4", reason);
+                       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_ENTER:
+               if (KDB_STATE(KEYBOARD))
+                       kdb_printf("due to Keyboard Entry\n");
+               else {
+                       if (!kdb_kdump_reason)
+                               kdb_kdump_reason = reason;
+                       kdb_printf("due to KDB_ENTER()\n");
+               }
+               break;
+       case KDB_REASON_KEYBOARD:
+               KDB_STATE_SET(KEYBOARD);
+               kdb_printf("due to Keyboard Entry\n");
+               break;
+       case KDB_REASON_ENTER_SLAVE:    /* drop through, slaves only get released via cpu switch */
+       case KDB_REASON_SWITCH:
+               kdb_printf("due to cpu switch\n");
+               if (KDB_STATE(GO_SWITCH)) {
+                       KDB_STATE_CLEAR(GO_SWITCH);
+                       KDB_DEBUG_STATE("kdb_local 5", reason);
+                       return KDB_CMD_GO;
+               }
+               break;
+       case KDB_REASON_OOPS:
+               if (!kdb_kdump_reason)
+                       kdb_kdump_reason = reason;
+               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:
+               if (!kdb_kdump_reason)
+                       kdb_kdump_reason = reason;
+               kdb_printf("due to NonMaskable 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);
+                       KDB_DEBUG_STATE("kdb_local 6", reason);
+                       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_CPU_UP:
+       case KDB_REASON_SILENT:
+               KDB_DEBUG_STATE("kdb_local 7", reason);
+               if (reason == KDB_REASON_CPU_UP)
+                       kdba_cpu_up();
+               return KDB_CMD_GO;      /* Silent entry, silent exit */
+               break;
+       default:
+               kdb_printf("kdb: unexpected reason code: %d\n", reason);
+               KDB_DEBUG_STATE("kdb_local 8", reason);
+               return 0;       /* Not for us, dismiss it */
+       }
+
+       kdba_local_arch_setup();
+
+       kdba_set_current_task(kdb_current);
+
+       while (1) {
+               /*
+                * Initialize pager context.
+                */
+               kdb_nextline = 1;
+               KDB_STATE_CLEAR(SUPPRESS);
+#ifdef kdba_setjmp
+               /*
+                * 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 (kdbjmpbuf) {
+                       if (kdba_setjmp(&kdbjmpbuf[smp_processor_id()])) {
+                               /* Command aborted (usually in pager) */
+                               continue;
+                       }
+                       else
+                               KDB_STATE_SET(LONGJMP);
+               }
+#endif /* kdba_setjmp */
+
+               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);
+                       kdb_do_dump();
+                       kdb_reboot(0, NULL);
+                       /*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);
+               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();
+
+       KDB_DEBUG_STATE("kdb_local 9", diag);
+       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;
+
+static void
+kdb_wait_for_cpus(void)
+{
+#ifdef CONFIG_SMP
+       int online = 0, kdb_data = 0, prev_kdb_data = 0, c, time;
+       mdelay(100);
+       for (time = 0; time < kdb_wait_for_cpus_secs; ++time) {
+               online = 0;
+               kdb_data = 0;
+               for_each_online_cpu(c) {
+                       ++online;
+                       if (kdb_running_process[c].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, timeout in %d second(s)\n",
+                               kdb_data, online, kdb_wait_for_cpus_secs - time);
+                       prev_kdb_data = kdb_data;
+               }
+               touch_nmi_watchdog();
+               mdelay(1000);
+               /* Architectures may want to send a more forceful interrupt */
+               if (time == min(kdb_wait_for_cpus_secs / 2, 5))
+                       kdba_wait_for_cpus();
+               if (time % 4 == 0)
+                       kdb_printf(".");
+       }
+       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 SILENT or CPU_UP 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;
+       /* 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);
+                       }
+
+#if defined(CONFIG_KDB_KDUMP)
+                       if (KDB_STATE(KEXEC)) {
+                               struct pt_regs r;
+                               if (regs == NULL)
+                                       regs = &r;
+
+                               kdba_kdump_shutdown_slave(regs);
+                               return 0;
+                       }
+#endif
+               }
+
+               KDB_STATE_CLEAR(SUPPRESS);
+               KDB_DEBUG_STATE("kdb_main_loop 2", reason);
+               if (KDB_STATE(LEAVING))
+                       break;  /* Another cpu said 'go' */
+
+               if (!kdb_quiet(reason))
+                       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;
+}
+
+/* iapc_boot_arch was defined in ACPI 2.0, FADT revision 3 onwards.  For any
+ * FADT prior to revision 3, we have to assume that we have an i8042 I/O
+ * device.  ACPI initialises after KDB initialises but before using KDB, so
+ * check iapc_boot_arch on each entry to KDB.
+ */
+static void
+kdb_check_i8042(void)
+{
+       KDB_FLAG_CLEAR(NO_I8042);
+#ifdef CONFIG_ACPI
+       if (acpi_gbl_FADT.header.revision >= 3 &&
+           (acpi_gbl_FADT.boot_flags & BAF_8042_KEYBOARD_CONTROLLER) == 0)
+               KDB_FLAG_SET(NO_I8042);
+#endif /* CONFIG_ACPI */
+}
+
+/*
+ * 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.
+ *
+ *     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.
+ *
+ *     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 SILENT or CPU_UP 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 = 0; /* Default is kdb did not handle it */
+       int ss_event, old_regs_saved = 0;
+       struct pt_regs *old_regs = NULL;
+       kdb_dbtrap_t db_result=KDB_DB_NOBPT;
+       preempt_disable();
+       atomic_inc(&kdb_event);
+
+       switch(reason) {
+       case KDB_REASON_OOPS:
+       case KDB_REASON_NMI:
+               KDB_FLAG_SET(CATASTROPHIC);     /* kernel state is dubious now */
+               break;
+       default:
+               break;
+       }
+       switch(reason) {
+       case KDB_REASON_ENTER:
+       case KDB_REASON_ENTER_SLAVE:
+       case KDB_REASON_BREAK:
+       case KDB_REASON_DEBUG:
+       case KDB_REASON_OOPS:
+       case KDB_REASON_SWITCH:
+       case KDB_REASON_KEYBOARD:
+       case KDB_REASON_NMI:
+               if (regs && regs != get_irq_regs()) {
+                       old_regs = set_irq_regs(regs);
+                       old_regs_saved = 1;
+               }
+               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))
+               goto out;
+
+       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);
+               goto out;       /* 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 &&
+           reason != KDB_REASON_ENTER_SLAVE) {
+               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 kdba_setjmp
+                               kdba_longjmp(&kdbjmpbuf[smp_processor_id()], 0);
+#endif /* kdba_setjmp */
+                       }
+                       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");
+                               /*temp*/
+                               while (KDB_IS_RUNNING())
+                                       cpu_relax();
+                               goto out;
+                       }
+               }
+       } else if (reason == KDB_REASON_SWITCH && !KDB_IS_RUNNING()) {
+               kdb_printf("kdb: CPU switch without kdb running, I'm confused\n");
+               goto out;
+       }
+
+       /*
+        * Disable interrupts, breakpoints etc. on this processor
+        * during kdb command processing
+        */
+       KDB_STATE_SET(KDB);
+       kdba_disableint(&int_state);
+       if (!KDB_STATE(KDB_CONTROL)) {
+               kdb_bp_remove_local();
+               KDB_STATE_SET(KDB_CONTROL);
+       }
+
+       /*
+        * 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.
+        *
+        * The above describes the normal state of affairs, where two or more
+        * cpus that are entering kdb at the "same" time are assumed to be for
+        * separate events.  However some processes such as ia64 MCA/INIT will
+        * drive all the cpus into error processing at the same time.  For that
+        * case, all of the cpus entering kdb at the "same" time are really a
+        * single event.
+        *
+        * That case is handled by the use of KDB_ENTER by one cpu (the
+        * monarch) and KDB_ENTER_SLAVE on the other cpus (the slaves).
+        * KDB_ENTER_SLAVE maps to KDB_REASON_ENTER_SLAVE.  The slave events
+        * will be treated as if they had just responded to the kdb IPI, i.e.
+        * as if they were KDB_REASON_SWITCH.
+        *
+        * Because of races across multiple cpus, ENTER_SLAVE can occur before
+        * the main ENTER.   Hold up ENTER_SLAVE here until the main ENTER
+        * arrives.
+        */
+
+       if (reason == KDB_REASON_ENTER_SLAVE) {
+               spin_lock(&kdb_lock);
+               while (!KDB_IS_RUNNING()) {
+                       spin_unlock(&kdb_lock);
+                       while (!KDB_IS_RUNNING())
+                               cpu_relax();
+                       spin_lock(&kdb_lock);
+               }
+               reason = KDB_REASON_SWITCH;
+               KDB_STATE_SET(HOLD_CPU);
+               spin_unlock(&kdb_lock);
+       }
+
+       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())
+                               cpu_relax();
+                       spin_lock(&kdb_lock);
+               }
+               KDB_DEBUG_STATE("kdb 5", reason);
+
+               kdb_initial_cpu = smp_processor_id();
+               ++kdb_seqno;
+               spin_unlock(&kdb_lock);
+               if (!kdb_quiet(reason))
+                       notify_die(DIE_KDEBUG_ENTER, "KDEBUG ENTER", regs, error, 0, 0);
+       }
+
+       if (smp_processor_id() == kdb_initial_cpu
+        && !KDB_STATE(REENTRY)) {
+               KDB_STATE_CLEAR(HOLD_CPU);
+               KDB_STATE_CLEAR(WAIT_IPI);
+               kdb_check_i8042();
+               /*
+                * Remove the global breakpoints.  This is only done
+                * once from the initial processor on initial entry.
+                */
+               if (!kdb_quiet(reason) || smp_processor_id() == 0)
+                       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 (NR_CPUS > 1 && !kdb_quiet(reason)) {
+                       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);
+       reason = reason2;       /* back to original event type */
+
+       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 and cleanup the cached
+                * symbol table.  This is only done once from the initial
+                * processor on go.
+                */
+               KDB_DEBUG_STATE("kdb 12", reason);
+               if (!kdb_quiet(reason) || smp_processor_id() == 0) {
+                       kdb_bp_install_global(regs);
+                       kdbnearsym_cleanup();
+                       debug_kusage();
+               }
+               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)
+                               ;
+                       if (!kdb_quiet(reason))
+                               notify_die(DIE_KDEBUG_LEAVE, "KDEBUG LEAVE", regs, error, 0, 0);
+                       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);
+               if (old_regs_saved)
+                       set_irq_regs(old_regs);
+               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(KEYBOARD);
+       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);
+out:
+       atomic_dec(&kdb_event);
+       preempt_enable();
+       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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static void
+kdb_md_line(const char *fmtstr, kdb_machreg_t addr,
+           int symbolic, int nosect, int bytesperword,
+           int num, int repeat, int phys)
+{
+       /* print just one line of data */
+       kdb_symtab_t symtab;
+       char cbuf[32];
+       char *c = cbuf;
+       int i;
+       unsigned long word;
+
+       memset(cbuf, '\0', sizeof(cbuf));
+       if (phys)
+               kdb_printf("phys " kdb_machreg_fmt0 " ", addr);
+       else
+               kdb_printf(kdb_machreg_fmt0 " ", addr);
+
+       for (i = 0; i < num && repeat--; i++) {
+               if (phys) {
+                       if (kdb_getphysword(&word, addr, bytesperword))
+                               break;
+               } else if (kdb_getword(&word, addr, bytesperword))
+                       break;
+               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 {
+                       union {
+                               u64 word;
+                               unsigned char c[8];
+                       } wc;
+                       unsigned char *cp;
+#ifdef __BIG_ENDIAN
+                       cp = wc.c + 8 - bytesperword;
+#else
+                       cp = wc.c;
+#endif
+                       wc.word = word;
+#define printable_char(c) ({unsigned char __c = c; isascii(__c) && isprint(__c) ? __c : '.';})
+                       switch (bytesperword) {
+                       case 8:
+                               *c++ = printable_char(*cp++);
+                               *c++ = printable_char(*cp++);
+                               *c++ = printable_char(*cp++);
+                               *c++ = printable_char(*cp++);
+                               addr += 4;
+                       case 4:
+                               *c++ = printable_char(*cp++);
+                               *c++ = printable_char(*cp++);
+                               addr += 2;
+                       case 2:
+                               *c++ = printable_char(*cp++);
+                               addr++;
+                       case 1:
+                               *c++ = printable_char(*cp++);
+                               addr++;
+                               break;
+                       }
+#undef printable_char
+               }
+       }
+       kdb_printf("%*s %s\n", (int)((num-i)*(2*bytesperword + 1)+1), " ", cbuf);
+}
+
+static int
+kdb_md(int argc, const char **argv)
+{
+       static kdb_machreg_t last_addr;
+       static int last_radix, last_bytesperword, last_repeat;
+       int radix = 16, mdcount = 8, bytesperword = KDB_WORD_SIZE, repeat;
+       int nosect = 0;
+       char fmtchar, fmtstr[64];
+       kdb_machreg_t addr;
+       unsigned long word;
+       long offset = 0;
+       int symbolic = 0;
+       int valid = 0;
+       int phys = 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;
+       else if (strcmp(argv[0], "mdp") == 0) {
+               phys = 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);
+               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 > KDB_WORD_SIZE)
+               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 = KDB_WORD_SIZE;
+               repeat = mdcount;
+               kdbgetintenv("NOSECT", &nosect);
+       }
+
+       /* Round address down modulo BYTESPERWORD */
+
+       addr &= ~(bytesperword-1);
+
+       while (repeat > 0) {
+               unsigned long a;
+               int n, z, num = (symbolic ? 1 : (16 / bytesperword));
+
+               for (a = addr, z = 0; z < repeat; a += bytesperword, ++z) {
+                       if (phys) {
+                               if (kdb_getphysword(&word, a, bytesperword)
+                                               || word)
+                                       break;
+                       } else if (kdb_getword(&word, a, bytesperword) || word)
+                               break;
+               }
+               n = min(num, repeat);
+               kdb_md_line(fmtstr, addr, symbolic, nosect, bytesperword, num, repeat, phys);
+               addr += bytesperword * n;
+               repeat -= n;
+               z = (z + num - 1) / num;
+               if (z > 2) {
+                       int s = num * (z-2);
+                       kdb_printf(kdb_machreg_fmt0 "-" kdb_machreg_fmt0 " zero suppressed\n",
+                               addr, addr + bytesperword * s - 1);
+                       addr += bytesperword * s;
+                       repeat -= s;
+               }
+       }
+       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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     mm works on machine words, mmW works on bytes.
+ */
+
+static int
+kdb_mm(int argc, const char **argv)
+{
+       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)))
+               return diag;
+
+       if (nextarg > argc)
+               return KDB_ARGCOUNT;
+
+       if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &contents, NULL, NULL)))
+               return diag;
+
+       if (nextarg != argc + 1)
+               return KDB_ARGCOUNT;
+
+       width = argv[0][2] ? (argv[0][2] - '0') : (KDB_WORD_SIZE);
+       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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     KDB_CMD_GO for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_go(int argc, const char **argv)
+{
+       kdb_machreg_t addr;
+       int diag;
+       int nextarg;
+       long offset;
+       struct pt_regs *regs = get_irq_regs();
+
+       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);
+               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();
+                       kdb_printf("forcing reboot\n");
+                       kdb_reboot(0, NULL);
+               }
+               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);
+               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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_rd(int argc, const char **argv)
+{
+       int diag;
+       if (argc == 0) {
+               if ((diag = kdb_check_regs()))
+                       return diag;
+               return kdba_dumpregs(kdb_current_regs, NULL, NULL);
+       }
+
+       if (argc > 2) {
+               return KDB_ARGCOUNT;
+       }
+
+       if ((diag = kdb_check_regs()))
+               return diag;
+       return kdba_dumpregs(kdb_current_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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     Currently doesn't allow modification of control or
+ *     debug registers.
+ */
+
+static int
+kdb_rm(int argc, const char **argv)
+{
+       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;
+
+       if ((diag = kdb_check_regs()))
+               return diag;
+       diag = kdba_setregcontents(&argv[1][ind], kdb_current_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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     None.
+ */
+static int
+kdb_sr(int argc, const char **argv)
+{
+       extern int __sysrq_enabled;
+       if (argc != 1) {
+               return KDB_ARGCOUNT;
+       }
+       if (!__sysrq_enabled) {
+               kdb_printf("Auto activating sysrq\n");
+               __sysrq_enabled = 1;
+       }
+
+       handle_sysrq(*argv[1], NULL);
+
+       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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     Not done yet.
+ */
+
+static int
+kdb_ef(int argc, const char **argv)
+{
+       int diag;
+       kdb_machreg_t addr;
+       long offset;
+       int nextarg;
+
+       if (argc == 1) {
+               nextarg = 1;
+               diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
+               if (diag)
+                       return diag;
+
+               return kdba_dumpregs((struct pt_regs *)addr, NULL, NULL);
+       }
+
+       return KDB_ARGCOUNT;
+}
+
+#if defined(CONFIG_MODULES)
+extern struct list_head *kdb_modules;
+extern void free_module(struct module *);
+
+/* modules using other modules */
+struct module_use
+{
+       struct list_head list;
+       struct module *module_which_uses;
+};
+
+/*
+ * 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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *
+ */
+
+static int
+kdb_lsmod(int argc, const char **argv)
+{
+       struct module *mod;
+
+       if (argc != 0)
+               return KDB_ARGCOUNT;
+
+       kdb_printf("Module                  Size  modstruct     Used by\n");
+       list_for_each_entry(mod, kdb_modules, list) {
+
+               kdb_printf("%-20s%8u  0x%p ", mod->name,
+                          mod->core_size, (void *)mod);
+#ifdef CONFIG_MODULE_UNLOAD
+               kdb_printf("%4d ", module_refcount(mod));
+#endif
+               if (mod->state == MODULE_STATE_GOING)
+                       kdb_printf(" (Unloading)");
+               else if (mod->state == MODULE_STATE_COMING)
+                       kdb_printf(" (Loading)");
+               else
+                       kdb_printf(" (Live)");
+
+#ifdef CONFIG_MODULE_UNLOAD
+               {
+                       struct module_use *use;
+                       kdb_printf(" [ ");
+                       list_for_each_entry(use, &mod->modules_which_use_me, list)
+                               kdb_printf("%s ", use->module_which_uses->name);
+                       kdb_printf("]\n");
+               }
+#endif
+       }
+
+       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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_env(int argc, const char **argv)
+{
+       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] [adjust]
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ *     None.
+ */
+
+static int
+kdb_dmesg(int argc, const char **argv)
+{
+       char *syslog_data[4], *start, *end, c = '\0', *p;
+       int diag, logging, logsize, lines = 0, adjust = 0, n;
+
+       if (argc > 2)
+               return KDB_ARGCOUNT;
+       if (argc) {
+               char *cp;
+               lines = simple_strtol(argv[1], &cp, 0);
+               if (*cp)
+                       lines = 0;
+               if (argc > 1) {
+                       adjust = simple_strtoul(argv[2], &cp, 0);
+                       if (*cp || adjust < 0)
+                               adjust = 0;
+               }
+       }
+
+       /* disable LOGGING if set */
+       diag = kdbgetintenv("LOGGING", &logging);
+       if (!diag && logging) {
+               const char *setargs[] = { "set", "LOGGING", "0" };
+               kdb_set(2, setargs);
+       }
+
+       /* 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[2];
+       end = syslog_data[3];
+#define KDB_WRAP(p) (((p - syslog_data[0]) % logsize) + syslog_data[0])
+       for (n = 0, p = start; p < end; ++p) {
+               if ((c = *KDB_WRAP(p)) == '\n')
+                       ++n;
+       }
+       if (c != '\n')
+               ++n;
+       if (lines < 0) {
+               if (adjust >= n)
+                       kdb_printf("buffer only contains %d lines, nothing printed\n", n);
+               else if (adjust - lines >= n)
+                       kdb_printf("buffer only contains %d lines, last %d lines printed\n",
+                               n, n - adjust);
+               if (adjust) {
+                       for (; start < end && adjust; ++start) {
+                               if (*KDB_WRAP(start) == '\n')
+                                       --adjust;
+                       }
+                       if (start < end)
+                               ++start;
+               }
+               for (p = start; p < end && lines; ++p) {
+                       if (*KDB_WRAP(p) == '\n')
+                               ++lines;
+               }
+               end = p;
+       } else if (lines > 0) {
+               int skip = n - (adjust + lines);
+               if (adjust >= n) {
+                       kdb_printf("buffer only contains %d lines, nothing printed\n", n);
+                       skip = n;
+               } else if (skip < 0) {
+                       lines += skip;
+                       skip = 0;
+                       kdb_printf("buffer only contains %d lines, first %d lines printed\n",
+                               n, lines);
+               }
+               for (; start < end && skip; ++start) {
+                       if (*KDB_WRAP(start) == '\n')
+                               --skip;
+               }
+               for (p = start; p < end && lines; ++p) {
+                       if (*KDB_WRAP(p) == '\n')
+                               --lines;
+               }
+               end = p;
+       }
+       /* Do a line at a time (max 200 chars) to reduce protocol overhead */
+       c = '\n';
+       while (start != end) {
+               char buf[201];
+               p = buf;
+               while (start < end && (c = *KDB_WRAP(start)) && (p - buf) < sizeof(buf)-1) {
+                       ++start;
+                       *p++ = c;
+                       if (c == '\n')
+                               break;
+               }
+               *p = '\0';
+               kdb_printf("%s", buf);
+       }
+       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
+ * 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.
+ */
+
+static void
+kdb_cpu_status(void)
+{
+       int i, start_cpu, first_print = 1;
+       char state, prev_state = '?';
+
+       kdb_printf("Currently on cpu %d\n", smp_processor_id());
+       kdb_printf("Available cpus: ");
+       for (start_cpu = -1, i = 0; i < NR_CPUS; i++) {
+               if (!cpu_online(i))
+                       state = 'F';    /* cpu is offline */
+               else {
+                       struct kdb_running_process *krp = kdb_running_process+i;
+                       if (KDB_STATE_CPU(KDB, i)) {
+                               state = ' ';    /* cpu is responding to kdb */
+                               if (kdb_task_state_char(krp->p) == 'I')
+                                       state = 'I';    /* running the idle task */
+                       } else if (krp->seqno && krp->p && krp->seqno >= kdb_seqno - 1)
+                               state = '+';    /* some kdb data, but not responding */
+                       else
+                               state = '*';    /* no kdb data */
+               }
+               if (state != prev_state) {
+                       if (prev_state != '?') {
+                               if (!first_print)
+                                       kdb_printf(", ");
+                               first_print = 0;
+                               kdb_printf("%d", start_cpu);
+                               if (start_cpu < i-1)
+                                       kdb_printf("-%d", i-1);
+                               if (prev_state != ' ')
+                                       kdb_printf("(%c)", prev_state);
+                       }
+                       prev_state = state;
+                       start_cpu = i;
+               }
+       }
+       /* print the trailing cpus, ignoring them if they are all offline */
+       if (prev_state != 'F') {
+               if (!first_print)
+                       kdb_printf(", ");
+               kdb_printf("%d", start_cpu);
+               if (start_cpu < i-1)
+                       kdb_printf("-%d", i-1);
+               if (prev_state != ' ')
+                       kdb_printf("(%c)", prev_state);
+       }
+       kdb_printf("\n");
+}
+
+static int
+kdb_cpu(int argc, const char **argv)
+{
+       unsigned long cpunum;
+       int diag, 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) {
+               kdb_cpu_status();
+               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;
+}
+
+/* The user may not realize that ps/bta with no parameters does not print idle
+ * or sleeping system daemon processes, so tell them how many were suppressed.
+ */
+void
+kdb_ps_suppressed(void)
+{
+       int idle = 0, daemon = 0;
+       unsigned long mask_I = kdb_task_state_string("I"),
+                     mask_M = kdb_task_state_string("M");
+       unsigned long cpu;
+       const struct task_struct *p, *g;
+       for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+               if (!cpu_online(cpu))
+                       continue;
+               p = kdb_curr_task(cpu);
+               if (kdb_task_state(p, mask_I))
+                       ++idle;
+       }
+       kdb_do_each_thread(g, p) {
+               if (kdb_task_state(p, mask_M))
+                       ++daemon;
+       } kdb_while_each_thread(g, p);
+       if (idle || daemon) {
+               if (idle)
+                       kdb_printf("%d idle process%s (state I)%s\n",
+                                  idle, idle == 1 ? "" : "es",
+                                  daemon ? " and " : "");
+               if (daemon)
+                       kdb_printf("%d sleeping system daemon (state M) process%s",
+                                  daemon, daemon == 1 ? "" : "es");
+               kdb_printf(" suppressed,\nuse 'ps A' to see all.\n");
+       }
+}
+
+/*
+ * kdb_ps
+ *
+ *     This function implements the 'ps' command which shows
+ *     a list of the active processes.
+ *
+ *     ps [DRSTCZEUIMA]                All processes, optionally filtered by state
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+void
+kdb_ps1(const struct task_struct *p)
+{
+       struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(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),
+                  kdb_task_state_char(p),
+                  (void *)(&p->thread),
+                  p == kdb_curr_task(smp_processor_id()) ? '*': ' ',
+                  p->comm);
+       if (kdb_task_has_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);
+               }
+       }
+}
+
+static int
+kdb_ps(int argc, const char **argv)
+{
+       struct task_struct *g, *p;
+       unsigned long mask, cpu;
+
+       if (argc == 0)
+               kdb_ps_suppressed();
+       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[1] : NULL);
+       /* Run the active tasks first */
+       for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+               if (!cpu_online(cpu))
+                       continue;
+               p = kdb_curr_task(cpu);
+               if (kdb_task_state(p, mask))
+                       kdb_ps1(p);
+       }
+       kdb_printf("\n");
+       /* Now the real tasks */
+       kdb_do_each_thread(g, p) {
+               if (kdb_task_state(p, mask))
+                       kdb_ps1(p);
+       } kdb_while_each_thread(g, p);
+
+       return 0;
+}
+
+/*
+ * kdb_pid
+ *
+ *     This function implements the 'pid' command which switches
+ *     the currently active process.
+ *
+ *     pid [<pid> | R]
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+
+static int
+kdb_pid(int argc, const char **argv)
+{
+       struct task_struct *p;
+       unsigned long val;
+       int diag;
+
+       if (argc > 1)
+               return KDB_ARGCOUNT;
+
+       if (argc) {
+               if (strcmp(argv[1], "R") == 0) {
+                       p = KDB_RUNNING_PROCESS_ORIGINAL[kdb_initial_cpu].p;
+               } else {
+                       diag = kdbgetularg(argv[1], &val);
+                       if (diag)
+                               return KDB_BADINT;
+
+                       p = find_task_by_pid_type_ns(PIDTYPE_PID, (pid_t)val,
+                               &init_pid_ns);
+                       if (!p) {
+                               kdb_printf("No task with pid=%d\n", (pid_t)val);
+                               return 0;
+                       }
+               }
+
+               kdba_set_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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_ll(int argc, const char **argv)
+{
+       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);
+       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_KDB))) {
+               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);
+               if (diag)
+                       return diag;
+
+               addr = va + linkoffset;
+               if (kdb_getword(&va, addr, sizeof(va)))
+                       return 0;
+       }
+       kfree(command);
+
+       return 0;
+}
+
+/*
+ * kdb_help
+ *
+ *     This function implements the 'help' and '?' commands.
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_help(int argc, const char **argv)
+{
+       kdbtab_t *kt;
+       int i;
+
+       kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");
+       kdb_printf("----------------------------------------------------------\n");
+       for(i=0, kt=kdb_commands; i<kdb_max_commands; i++, kt++) {
+               if (kt->cmd_name)
+                       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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_kill(int argc, const char **argv)
+{
+       long sig, pid;
+       char *endp;
+       struct task_struct *p;
+       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. */
+       if (!(p = find_task_by_pid_type_ns(PIDTYPE_PID, pid, &init_pid_ns))) {
+               kdb_printf("The specified process isn't found.\n");
+               return 0;
+       }
+       p = p->group_leader;
+       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 */
+       kdb_send_sig_info(p, &info, kdb_seqno);
+       return 0;
+}
+
+struct kdb_tm {
+       int tm_sec;     /* seconds */
+       int tm_min;     /* minutes */
+       int tm_hour;    /* hours */
+       int tm_mday;    /* day of the month */
+       int tm_mon;     /* month */
+       int tm_year;    /* year */
+};
+
+static void
+kdb_gmtime(struct timespec *tv, struct kdb_tm *tm)
+{
+       /* This will work from 1970-2099, 2100 is not a leap year */
+       static int mon_day[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+       memset(tm, 0, sizeof(*tm));
+       tm->tm_sec  = tv->tv_sec % (24 * 60 * 60);
+       tm->tm_mday = tv->tv_sec / (24 * 60 * 60) + (2 * 365 + 1); /* shift base from 1970 to 1968 */
+       tm->tm_min =  tm->tm_sec / 60 % 60;
+       tm->tm_hour = tm->tm_sec / 60 / 60;
+       tm->tm_sec =  tm->tm_sec % 60;
+       tm->tm_year = 68 + 4*(tm->tm_mday / (4*365+1));
+       tm->tm_mday %= (4*365+1);
+       mon_day[1] = 29;
+       while (tm->tm_mday >= mon_day[tm->tm_mon]) {
+               tm->tm_mday -= mon_day[tm->tm_mon];
+               if (++tm->tm_mon == 12) {
+                       tm->tm_mon = 0;
+                       ++tm->tm_year;
+                       mon_day[1] = 28;
+               }
+       }
+       ++tm->tm_mday;
+}
+
+/*
+ * Most of this code has been lifted from kernel/timer.c::sys_sysinfo().
+ * I cannot call that code directly from kdb, it has an unconditional
+ * cli()/sti() and calls routines that take locks which can stop the debugger.
+ */
+
+static void
+kdb_sysinfo(struct sysinfo *val)
+{
+       struct timespec uptime;
+       do_posix_clock_monotonic_gettime(&uptime);
+       memset(val, 0, sizeof(*val));
+       val->uptime = uptime.tv_sec;
+       val->loads[0] = avenrun[0];
+       val->loads[1] = avenrun[1];
+       val->loads[2] = avenrun[2];
+       val->procs = nr_threads-1;
+       si_meminfo(val);
+       kdb_si_swapinfo(val);
+
+       return;
+}
+
+/*
+ * kdb_summary
+ *
+ *     This function implements the 'summary' command.
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_summary(int argc, const char **argv)
+{
+       extern struct timespec xtime;
+       extern struct timezone sys_tz;
+       struct kdb_tm tm;
+       struct sysinfo val;
+
+       if (argc)
+               return KDB_ARGCOUNT;
+
+       kdb_printf("sysname    %s\n", init_uts_ns.name.sysname);
+       kdb_printf("release    %s\n", init_uts_ns.name.release);
+       kdb_printf("version    %s\n", init_uts_ns.name.version);
+       kdb_printf("machine    %s\n", init_uts_ns.name.machine);
+       kdb_printf("nodename   %s\n", init_uts_ns.name.nodename);
+       kdb_printf("domainname %s\n", init_uts_ns.name.domainname);
+       kdb_printf("ccversion  %s\n", __stringify(CCVERSION));
+
+       kdb_gmtime(&xtime, &tm);
+       kdb_printf("date       %04d-%02d-%02d %02d:%02d:%02d tz_minuteswest %d\n",
+               1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday,
+               tm.tm_hour, tm.tm_min, tm.tm_sec,
+               sys_tz.tz_minuteswest);
+
+       kdb_sysinfo(&val);
+       kdb_printf("uptime     ");
+       if (val.uptime > (24*60*60)) {
+               int days = val.uptime / (24*60*60);
+               val.uptime %= (24*60*60);
+               kdb_printf("%d day%s ", days, days == 1 ? "" : "s");
+       }
+       kdb_printf("%02ld:%02ld\n", val.uptime/(60*60), (val.uptime/60)%60);
+
+       /* lifted from fs/proc/proc_misc.c::loadavg_read_proc() */
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+       kdb_printf("load avg   %ld.%02ld %ld.%02ld %ld.%02ld\n",
+               LOAD_INT(val.loads[0]), LOAD_FRAC(val.loads[0]),
+               LOAD_INT(val.loads[1]), LOAD_FRAC(val.loads[1]),
+               LOAD_INT(val.loads[2]), LOAD_FRAC(val.loads[2]));
+       kdb_printf("\n");
+#undef LOAD_INT
+#undef LOAD_FRAC
+
+       kdb_meminfo_read_proc();        /* in fs/proc/proc_misc.c */
+
+       return 0;
+}
+
+/*
+ * kdb_per_cpu
+ *
+ *     This function implements the 'per_cpu' command.
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_per_cpu(int argc, const char **argv)
+{
+       char buf[256], fmtstr[64];
+       kdb_symtab_t symtab;
+       cpumask_t suppress = CPU_MASK_NONE;
+       int cpu, diag;
+       unsigned long addr, val, bytesperword = 0, whichcpu = ~0UL;
+
+       if (argc < 1 || argc > 3)
+               return KDB_ARGCOUNT;
+
+       snprintf(buf, sizeof(buf), "per_cpu__%s", argv[1]);
+       if (!kdbgetsymval(buf, &symtab)) {
+               kdb_printf("%s is not a per_cpu variable\n", argv[1]);
+               return KDB_BADADDR;
+       }
+       if (argc >=2 && (diag = kdbgetularg(argv[2], &bytesperword)))
+               return diag;
+       if (!bytesperword)
+               bytesperword = KDB_WORD_SIZE;
+       else if (bytesperword > KDB_WORD_SIZE)
+               return KDB_BADWIDTH;
+       sprintf(fmtstr, "%%0%dlx ", (int)(2*bytesperword));
+       if (argc >= 3) {
+               if ((diag = kdbgetularg(argv[3], &whichcpu)))
+                       return diag;
+               if (!cpu_online(whichcpu)) {
+                       kdb_printf("cpu %ld is not online\n", whichcpu);
+                       return KDB_BADCPUNUM;
+               }
+       }
+
+       /* Most architectures use __per_cpu_offset[cpu], some use
+        * __per_cpu_offset(cpu), smp has no __per_cpu_offset.
+        */
+#ifdef __per_cpu_offset
+#define KDB_PCU(cpu) __per_cpu_offset(cpu)
+#else
+#ifdef CONFIG_SMP
+#define KDB_PCU(cpu) __per_cpu_offset[cpu]
+#else
+#define KDB_PCU(cpu) 0
+#endif
+#endif
+
+       for_each_online_cpu(cpu) {
+               if (whichcpu != ~0UL && whichcpu != cpu)
+                       continue;
+               addr = symtab.sym_start + KDB_PCU(cpu);
+               if ((diag = kdb_getword(&val, addr, bytesperword))) {
+                       kdb_printf("%5d " kdb_bfd_vma_fmt0 " - unable to read, diag=%d\n",
+                               cpu, addr, diag);
+                       continue;
+               }
+#ifdef CONFIG_SMP
+               if (!val) {
+                       cpu_set(cpu, suppress);
+                       continue;
+               }
+#endif /* CONFIG_SMP */
+               kdb_printf("%5d ", cpu);
+               kdb_md_line(fmtstr, addr,
+                       bytesperword == KDB_WORD_SIZE,
+                       1, bytesperword, 1, 1, 0);
+       }
+       if (cpus_weight(suppress) == 0)
+               return 0;
+       kdb_printf("Zero suppressed cpu(s):");
+       for (cpu = first_cpu(suppress); cpu < NR_CPUS; cpu = next_cpu(cpu, suppress)) {
+               kdb_printf(" %d", cpu);
+               if (cpu == NR_CPUS-1 || next_cpu(cpu, suppress) != cpu + 1)
+                       continue;
+               while (cpu < NR_CPUS && next_cpu(cpu, suppress) == cpu + 1)
+                       ++cpu;
+               kdb_printf("-%d", cpu);
+       }
+       kdb_printf("\n");
+
+#undef KDB_PCU
+
+       return 0;
+}
+
+/*
+ * display help for the use of cmd | grep pattern
+ */
+static int
+kdb_grep_help(int argc, const char **argv)
+{
+       kdb_printf ("Usage of  cmd args | grep pattern:\n");
+       kdb_printf ("  Any command's output may be filtered through an ");
+       kdb_printf ("emulated 'pipe'.\n");
+       kdb_printf ("  'grep' is just a key word.\n");
+       kdb_printf
+       ("  The pattern may include a very limited set of metacharacters:\n");
+       kdb_printf ("   pattern or ^pattern or pattern$ or ^pattern$\n");
+       kdb_printf
+       ("  And if there are spaces in the pattern, you may quote it:\n");
+       kdb_printf
+       ("   \"pat tern\" or \"^pat tern\" or \"pat tern$\" or \"^pat tern$\"\n");
+       return 0;
+}
+
+/*
+ * 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, func %p help %s\n", cmd, func, help);
+                       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_KDB);
+               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;
+
+       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("mdp", kdb_md, "<paddr> <bytes>",   "Display Physical 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, "[DRSTCZEUIMA]",     "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, "[<flags>|A]", "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);
+#if defined(CONFIG_KDB_KDUMP)
+       kdb_register_repeat("kdump", kdb_kdump, "",    "Calls kdump mode", 0, KDB_REPEAT_NONE);
+#endif
+#if defined(CONFIG_MODULES)
+       kdb_register_repeat("lsmod", kdb_lsmod, "",     "List loaded kernel modules", 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);
+       kdb_register_repeat("summary", kdb_summary, "", "Summarize the system", 4, KDB_REPEAT_NONE);
+       kdb_register_repeat("per_cpu", kdb_per_cpu, "", "Display per_cpu variables", 3, KDB_REPEAT_NONE);
+       kdb_register_repeat("grephelp", kdb_grep_help, "",
+               "Display help on | grep", 0, KDB_REPEAT_NONE);
+       kdb_register_repeat("print", kdb_debuginfo_print, "<expression>",
+               "Type casting, as in lcrash",  0, KDB_REPEAT_NONE);
+       kdb_register_repeat("px", kdb_debuginfo_print, "<expression>",
+          "Print in hex (type casting) (see 'pxhelp')",  0, KDB_REPEAT_NONE);
+       kdb_register_repeat("pxhelp", kdb_pxhelp, "",
+               "Display help for the px command", 0, KDB_REPEAT_NONE);
+       kdb_register_repeat("pd", kdb_debuginfo_print, "<expression>",
+               "Print in decimal (type casting)", 0, KDB_REPEAT_NONE);
+       kdb_register_repeat("whatis", kdb_debuginfo_print,"<type or symbol>",
+       "Display the type, or the address for a symbol", 0, KDB_REPEAT_NONE);
+       kdb_register_repeat("sizeof", kdb_debuginfo_print, "<type>",
+       "Display the size of a structure, typedef, etc.", 0, KDB_REPEAT_NONE);
+        kdb_register_repeat("walk", kdb_walk, "",
+               "Walk a linked list (see 'walkhelp')", 0, KDB_REPEAT_NONE);
+       kdb_register_repeat("walkhelp", kdb_walkhelp, "",
+               "Display help for the walk command", 0, KDB_REPEAT_NONE);
+}
+
+/*
+ * The user has written to our "file"
+ * file: the /proc file
+ * buffer: user address of the data he is writing
+ * count:  number of bytes in the user's buffer
+ */
+static int
+kdb_write_proc_filename(struct file *file, const char __user *buffer,
+               unsigned long count, void *data)
+{
+       int     ret_count;
+
+       /* our buffer is kdb_debug_info_filename[256] */
+       if (count > 256) {
+               return 0;
+       }
+       if (copy_from_user(kdb_debug_info_filename, buffer, count)) {
+               return 0;
+       }
+       ret_count = count; /* actual count */
+       /* remove any newline from the end of the file name */
+       if (kdb_debug_info_filename[count-1] == '\n') count--;
+        kdb_debug_info_filename[count] = '\0';
+
+       return ret_count;
+}
+
+/*
+ * The user is reading from our "file"
+ * page:  the beginning of the user's buffer
+ * start: pointer to the user's pointer (tells him where we put the data)
+ * off:   offset into the resource to be read
+ * count: length of the read
+ */
+static int
+kdb_read_proc_filename(char *page, char **start, off_t off,
+               int count, int *eof, void *data)
+{
+       /* give him kdb_debug_info_filename[]; */
+       return snprintf(page, count, "%s\n", kdb_debug_info_filename);
+}
+
+/*
+ * kdb_proc_filename
+ *
+ * create /proc/kdb/debug_info_name
+ */
+static void
+kdb_proc_filename(void)
+{
+       struct proc_dir_entry *kdb_dir_entry, *kdb_file_entry;
+
+       /* create /proc/kdb */
+       kdb_dir_entry = proc_mkdir("kdb", NULL);
+       if (!kdb_dir_entry) {
+               printk ("kdb could not create /proc/kdb\n");
+               return;
+       }
+
+       /* read/write by owner (root) only */
+       kdb_file_entry = create_proc_entry("debug_info_name",
+                                       S_IRUSR | S_IWUSR, kdb_dir_entry);
+       if (!kdb_file_entry) {
+               printk ("kdb could not create /proc/kdb/kdb_dir_entry\n");
+               return;
+       }
+       kdb_file_entry->nlink = 1;
+       kdb_file_entry->data = (void *)NULL;
+       kdb_file_entry->read_proc = kdb_read_proc_filename;
+       kdb_file_entry->write_proc = kdb_write_proc_filename;
+       return;
+}
+
+/*
+ * 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) {
+               if (!defcmd_in_progress)
+                       if (console_loglevel >= 6 /* KERN_INFO */)
+                               kdb_printf("kdb_cmd[%d]: %s", i, kdb_cmds[i]);
+               diag = kdb_parse(kdb_cmds[i]);
+               if (diag)
+                       kdb_printf("kdb command %s failed, kdb diag %d\n",
+                               kdb_cmds[i], diag);
+       }
+       if (defcmd_in_progress) {
+               kdb_printf("Incomplete 'defcmd' set, forcing endefcmd\n");
+               kdb_parse("endefcmd");
+       }
+}
+
+/*
+ * 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 };
+
+#ifdef CONFIG_SYSCTL
+static int proc_do_kdb(ctl_table *table, int write, struct file *filp,
+                      void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       if (KDB_FLAG(NO_CONSOLE) && write) {
+               printk(KERN_ERR "kdb has no working console and has switched itself off\n");
+               return -EINVAL;
+       }
+       return proc_dointvec(table, write, filp, buffer, lenp, ppos);
+}
+
+static ctl_table kdb_kern_table[] = {
+       {
+               .ctl_name       = KERN_KDB,
+               .procname       = "kdb",
+               .data           = &kdb_on,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_do_kdb,
+               .strategy       = &sysctl_intvec,
+       },
+       {}
+};
+
+static ctl_table kdb_root_table[] = {
+       {
+               .ctl_name       = CTL_KERN,
+               .procname       = "kernel",
+               .mode           = 0555,
+               .child          = kdb_kern_table,
+       },
+       {}
+};
+#endif /* CONFIG_SYSCTL */
+
+static int
+kdb_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+       if (action == CPU_ONLINE) {
+               int cpu =(unsigned long)hcpu;
+               cpumask_t save_cpus_allowed = current->cpus_allowed;
+               cpumask_t new_cpus_allowed = cpumask_of_cpu(cpu);
+               set_cpus_allowed(current, new_cpus_allowed);
+               kdb(KDB_REASON_CPU_UP, 0, NULL);        /* do kdb setup on this cpu */
+               set_cpus_allowed(current, save_cpus_allowed);
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block kdb_cpu_nfb = {
+       .notifier_call = kdb_cpu_callback
+};
+
+/*
+ * kdb_init
+ *
+ *     Initialize the kernel debugger environment.
+ *
+ * Parameters:
+ *     None.
+ * Returns:
+ *     None.
+ * Locking:
+ *     None.
+ * Remarks:
+ *     None.
+ */
+
+void __init
+kdb_init(void)
+{
+       kdb_initial_cpu = smp_processor_id();
+       /*
+        * 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_initial_cpu = -1;   /* Avoid recursion problems */
+       kdb(KDB_REASON_CPU_UP, 0, NULL);        /* do kdb setup on boot cpu */
+       kdb_initial_cpu = smp_processor_id();
+       atomic_notifier_chain_register(&panic_notifier_list, &kdb_block);
+       register_cpu_notifier(&kdb_cpu_nfb);
+
+#ifdef kdba_setjmp
+       kdbjmpbuf = vmalloc(NR_CPUS * sizeof(*kdbjmpbuf));
+       if (!kdbjmpbuf)
+               printk(KERN_ERR "Cannot allocate kdbjmpbuf, no kdb recovery will be possible\n");
+#endif /* kdba_setjmp */
+
+       kdb_initial_cpu = -1;
+       kdb_wait_for_cpus_secs = max(10, 2*num_online_cpus());
+}
+
+#ifdef CONFIG_SYSCTL
+static int __init
+kdb_late_init(void)
+{
+       register_sysctl_table(kdb_root_table);
+       /* seems that we cannot allocate with kmalloc until now */
+        kdb_proc_filename();
+       return 0;
+}
+
+__initcall(kdb_late_init);
+#endif
+
+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(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(kdbnearsym);
+EXPORT_SYMBOL(kdb_printf);
+EXPORT_SYMBOL(kdb_symbol_print);
+EXPORT_SYMBOL(kdb_running_process);
diff --git a/kdb/kdbsupport.c b/kdb/kdbsupport.c
new file mode 100644 (file)
index 0000000..0cdceb5
--- /dev/null
@@ -0,0 +1,1154 @@
+/*
+ * Kernel Debugger Architecture Independent Support Functions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * 03/02/13    added new 2.5 kallsyms <xavier.bru@bull.net>
+ */
+
+#include <stdarg.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/ptrace.h>
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/hardirq.h>
+#include <linux/delay.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)
+{
+       if (KDB_DEBUG(AR))
+               kdb_printf("kdbgetsymval: symname=%s, symtab=%p\n", symname, symtab);
+       memset(symtab, 0, sizeof(*symtab));
+
+       if ((symtab->sym_start = kallsyms_lookup_name(symname))) {
+               if (KDB_DEBUG(AR))
+                       kdb_printf("kdbgetsymval: returns 1, symtab->sym_start=0x%lx\n", symtab->sym_start);
+               return 1;
+       }
+       if (KDB_DEBUG(AR))
+               kdb_printf("kdbgetsymval: returns 0\n");
+       return 0;
+}
+EXPORT_SYMBOL(kdbgetsymval);
+
+/*
+ * 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:
+ *     2.6 kallsyms has a "feature" where it unpacks the name into a string.
+ *     If that string is reused before the caller expects it then the caller
+ *     sees its string change without warning.  To avoid cluttering up the
+ *     main kdb code with lots of kdb_strdup, tests and kfree calls, kdbnearsym
+ *     maintains an LRU list of the last few unique strings.  The list is sized
+ *     large enough to hold active strings, no kdb caller of kdbnearsym makes
+ *     more than ~20 later calls before using a saved value.
+ */
+
+static char *kdb_name_table[100];      /* arbitrary size */
+
+int
+kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
+{
+       int ret = 0;
+       unsigned long symbolsize;
+       unsigned long offset;
+#define knt1_size 128          /* must be >= kallsyms table size */
+       char *knt1 = NULL;
+
+       if (KDB_DEBUG(AR))
+               kdb_printf("kdbnearsym: addr=0x%lx, symtab=%p\n", addr, symtab);
+       memset(symtab, 0, sizeof(*symtab));
+
+       if (addr < 4096)
+               goto out;
+       knt1 = debug_kmalloc(knt1_size, GFP_ATOMIC);
+       if (!knt1) {
+               kdb_printf("kdbnearsym: addr=0x%lx cannot kmalloc knt1\n", addr);
+               goto out;
+       }
+       symtab->sym_name = kallsyms_lookup(addr, &symbolsize , &offset, (char **)(&symtab->mod_name), knt1);
+       if (offset > 8*1024*1024) {
+               symtab->sym_name = NULL;
+               addr = offset = symbolsize = 0;
+       }
+       symtab->sym_start = addr - offset;
+       symtab->sym_end = symtab->sym_start + symbolsize;
+       ret = symtab->sym_name != NULL && *(symtab->sym_name) != '\0';
+
+       if (ret) {
+               int i;
+               /* Another 2.6 kallsyms "feature".  Sometimes the sym_name is
+                * set but the buffer passed into kallsyms_lookup is not used,
+                * so it contains garbage.  The caller has to work out which
+                * buffer needs to be saved.
+                *
+                * What was Rusty smoking when he wrote that code?
+                */
+               if (symtab->sym_name != knt1) {
+                       strncpy(knt1, symtab->sym_name, knt1_size);
+                       knt1[knt1_size-1] = '\0';
+               }
+               for (i = 0; i < ARRAY_SIZE(kdb_name_table); ++i) {
+                       if (kdb_name_table[i] && strcmp(kdb_name_table[i], knt1) == 0)
+                               break;
+               }
+               if (i >= ARRAY_SIZE(kdb_name_table)) {
+                       debug_kfree(kdb_name_table[0]);
+                       memcpy(kdb_name_table, kdb_name_table+1,
+                              sizeof(kdb_name_table[0])*(ARRAY_SIZE(kdb_name_table)-1));
+               } else {
+                       debug_kfree(knt1);
+                       knt1 = kdb_name_table[i];
+                       memcpy(kdb_name_table+i, kdb_name_table+i+1,
+                              sizeof(kdb_name_table[0])*(ARRAY_SIZE(kdb_name_table)-i-1));
+               }
+               i = ARRAY_SIZE(kdb_name_table) - 1;
+               kdb_name_table[i] = knt1;
+               symtab->sym_name = kdb_name_table[i];
+               knt1 = NULL;
+       }
+
+       if (symtab->mod_name == NULL)
+               symtab->mod_name = "kernel";
+       if (KDB_DEBUG(AR))
+               kdb_printf("kdbnearsym: returns %d symtab->sym_start=0x%lx, symtab->mod_name=%p, symtab->sym_name=%p (%s)\n", ret, symtab->sym_start, symtab->mod_name, symtab->sym_name, symtab->sym_name);
+
+out:
+       debug_kfree(knt1);
+       return ret;
+}
+
+void
+kdbnearsym_cleanup(void)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(kdb_name_table); ++i) {
+               if (kdb_name_table[i]) {
+                       debug_kfree(kdb_name_table[i]);
+                       kdb_name_table[i] = NULL;
+               }
+       }
+}
+
+/*
+ * kallsyms_symbol_complete
+ *
+ * Parameters:
+ *     prefix_name     prefix of a symbol name to lookup
+ *     max_len         maximum length that can be returned
+ * Returns:
+ *     Number of symbols which match the given prefix.
+ * Notes:
+ *     prefix_name is changed to contain the longest unique prefix that
+ *     starts with this prefix (tab completion).
+ */
+
+static char ks_namebuf[KSYM_NAME_LEN+1], ks_namebuf_prev[KSYM_NAME_LEN+1];
+
+int kallsyms_symbol_complete(char *prefix_name, int max_len)
+{
+       loff_t pos = 0;
+       int prefix_len = strlen(prefix_name), prev_len = 0;
+       int i, number = 0;
+       const char *name;
+
+       while ((name = kdb_walk_kallsyms(&pos))) {
+               if (strncmp(name, prefix_name, prefix_len) == 0) {
+                       strcpy(ks_namebuf, name);
+                       /* Work out the longest name that matches the prefix */
+                       if (++number == 1) {
+                               prev_len = min_t(int, max_len-1, strlen(ks_namebuf));
+                               memcpy(ks_namebuf_prev, ks_namebuf, prev_len);
+                               ks_namebuf_prev[prev_len] = '\0';
+                       } else for (i = 0; i < prev_len; ++i) {
+                               if (ks_namebuf[i] != ks_namebuf_prev[i]) {
+                                       prev_len = i;
+                                       ks_namebuf_prev[i] = '\0';
+                                       break;
+                               }
+                       }
+               }
+       }
+       if (prev_len > prefix_len)
+               memcpy(prefix_name, ks_namebuf_prev, prev_len+1);
+       return number;
+}
+
+/*
+ * kallsyms_symbol_next
+ *
+ * Parameters:
+ *     prefix_name     prefix of a symbol name to lookup
+ *     flag    0 means search from the head, 1 means continue search.
+ * Returns:
+ *     1 if a symbol matches the given prefix.
+ *     0 if no string found
+ */
+
+int kallsyms_symbol_next(char *prefix_name, int flag)
+{
+       int prefix_len = strlen(prefix_name);
+       static loff_t pos;
+       const char *name;
+
+       if (!flag)
+               pos = 0;
+
+       while ((name = kdb_walk_kallsyms(&pos))) {
+               if (strncmp(name, prefix_name, prefix_len) == 0) {
+                       strncpy(prefix_name, name, strlen(name)+1);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+#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 */
+
+/*
+ * 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, gfp_t 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_getphys
+ *
+ * Read data from a physical address. Validate the address is in range,
+ * use kmap_atomic() to get data
+ *
+ * Similar to kdb_getarea() - but for phys addresses
+ *
+ * Inputs:
+ *     res     Pointer to the word to receive the result
+ *     addr    Physical address of the area to copy
+ *     size    Size of the area
+ * Outputs:
+ *     none.
+ * Returns:
+ *     0 for success, < 0 for error.
+ * Locking:
+ *     none.
+ */
+static int kdb_getphys(void *res, unsigned long addr, size_t size)
+{
+       unsigned long pfn;
+       void *vaddr;
+       struct page *page;
+
+       pfn = (addr >> PAGE_SHIFT);
+       if (!pfn_valid(pfn))
+               return 1;
+       page = pfn_to_page(pfn);
+       vaddr = kmap_atomic(page, KM_KDB);
+       memcpy(res, vaddr + (addr & (PAGE_SIZE -1)), size);
+       kunmap_atomic(vaddr, KM_KDB);
+
+       return 0;
+}
+
+/*
+ * kdb_getphysword
+ *
+ * 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_getphysword(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_getphys(&w1, addr, sizeof(w1))))
+                       *word = w1;
+               break;
+       case 2:
+               if (!(diag = kdb_getphys(&w2, addr, sizeof(w2))))
+                       *word = w2;
+               break;
+       case 4:
+               if (!(diag = kdb_getphys(&w4, addr, sizeof(w4))))
+                       *word = w4;
+               break;
+       case 8:
+               if (size <= sizeof(*word)) {
+                       if (!(diag = kdb_getphys(&w8, addr, sizeof(w8))))
+                               *word = w8;
+                       break;
+               }
+               /* drop through */
+       default:
+               diag = KDB_BADWIDTH;
+               kdb_printf("kdb_getphysword: bad width %ld\n", (long) size);
+       }
+       return(diag);
+}
+
+/*
+ * 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 DRSTCZEUIMA to a mask
+ *     for the process state field and return the value.  If no argument is
+ *     supplied, return the mask that corresponds to environment variable PS,
+ *     DRSTCZEU by default.
+ * Inputs:
+ *     s       String to convert
+ * Outputs:
+ *     none.
+ * Returns:
+ *     Mask for process state.
+ * Locking:
+ *     none.
+ * Notes:
+ *     The mask folds data from several sources into a single long value, so
+ *     be carefull not to overlap the bits.  TASK_* bits are in the LSB,
+ *     special cases like UNRUNNABLE are in the MSB.  As of 2.6.10-rc1 there
+ *     is no overlap between TASK_* and EXIT_* but that may not always be
+ *     true, so EXIT_* bits are shifted left 16 bits before being stored in
+ *     the mask.
+ */
+
+#define UNRUNNABLE     (1UL << (8*sizeof(unsigned long) - 1))  /* unrunnable is < 0 */
+#define RUNNING                (1UL << (8*sizeof(unsigned long) - 2))
+#define IDLE           (1UL << (8*sizeof(unsigned long) - 3))
+#define DAEMON         (1UL << (8*sizeof(unsigned long) - 4))
+
+unsigned long
+kdb_task_state_string(const char *s)
+{
+       long res = 0;
+       if (!s && !(s = kdbgetenv("PS"))) {
+               s = "DRSTCZEU"; /* default value for ps */
+       }
+       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; break;
+               case 'C': res |= TASK_TRACED; break;
+               case 'Z': res |= EXIT_ZOMBIE << 16; break;
+               case 'E': res |= EXIT_DEAD << 16; break;
+               case 'U': res |= UNRUNNABLE; break;
+               case 'I': res |= IDLE; break;
+               case 'M': res |= DAEMON; break;
+               case 'A': res = ~0UL; break;
+               default:
+                         kdb_printf("%s: unknown flag '%c' ignored\n", __FUNCTION__, *s);
+                         break;
+               }
+               ++s;
+       }
+       return res;
+}
+
+/*
+ * kdb_task_state_char
+ *
+ *     Return the character that represents the task state.
+ * Inputs:
+ *     p       struct task for the process
+ * Outputs:
+ *     none.
+ * Returns:
+ *     One character to represent the task state.
+ * Locking:
+ *     none.
+ */
+
+char
+kdb_task_state_char (const struct task_struct *p)
+{
+       int cpu = kdb_process_cpu(p);
+       struct kdb_running_process *krp = kdb_running_process + cpu;
+       char state = (p->state == 0) ? 'R' :
+                    (p->state < 0) ? 'U' :
+                    (p->state & TASK_UNINTERRUPTIBLE) ? 'D' :
+                    (p->state & TASK_STOPPED) ? 'T' :
+                    (p->state & TASK_TRACED) ? 'C' :
+                    (p->exit_state & EXIT_ZOMBIE) ? 'Z' :
+                    (p->exit_state & EXIT_DEAD) ? 'E' :
+                    (p->state & TASK_INTERRUPTIBLE) ? 'S' : '?';
+       if (p->pid == 0) {
+               /* Idle task.  Is it really idle, apart from the kdb interrupt? */
+               if (!kdb_task_has_cpu(p) || krp->irq_depth == 1) {
+                       /* There is a corner case when the idle task takes an
+                        * interrupt and dies in the interrupt code.  It has an
+                        * interrupt count of 1 but that did not come from kdb.
+                        * This corner case can only occur on the initial cpu,
+                        * all the others were entered via the kdb IPI.
+                        */
+                       if (cpu != kdb_initial_cpu || KDB_STATE_CPU(KEYBOARD, cpu))
+                               state = 'I';    /* idle task */
+               }
+       }
+       else if (!p->mm && state == 'S') {
+               state = 'M';    /* sleeping system daemon */
+       }
+       return state;
+}
+
+/*
+ * 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)
+{
+       char state[] = { kdb_task_state_char(p), '\0' };
+       return (mask & kdb_task_state_string(state)) != 0;
+}
+
+struct kdb_running_process kdb_running_process[NR_CPUS];
+
+/* Save the state of a running process and invoke kdb_main_loop.  This is
+ * invoked on the current process on each cpu (assuming the cpu is responding).
+ */
+
+int
+kdb_save_running(struct pt_regs *regs, kdb_reason_t reason,
+                kdb_reason_t reason2, int error, kdb_dbtrap_t db_result)
+{
+       struct kdb_running_process *krp = kdb_running_process + smp_processor_id();
+       krp->p = current;
+       krp->regs = regs;
+       krp->seqno = kdb_seqno;
+       krp->irq_depth = hardirq_count() >> HARDIRQ_SHIFT;
+       kdba_save_running(&(krp->arch), regs);
+       return kdb_main_loop(reason, reason2, error, db_result, 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(const 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. */
+       if ((start & PAGE_MASK) != ((start+len) & PAGE_MASK))
+               return NULL;
+
+       /* we need to align start address to the current page boundy, PAGE_ALIGN
+        * aligns to next page boundry.
+        * FIXME: What about hugetlb?
+        */
+       start = start & PAGE_MASK;
+       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 follow_page(vma, start, write ? FOLL_WRITE : 0);
+}
+
+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;
+}
+
+/* Last ditch allocator for debugging, so we can still debug even when the
+ * GFP_ATOMIC pool has been exhausted.  The algorithms are tuned for space
+ * usage, not for speed.  One smallish memory pool, the free chain is always in
+ * ascending address order to allow coalescing, allocations are done in brute
+ * force best fit.
+ */
+
+struct debug_alloc_header {
+       u32 next;       /* offset of next header from start of pool */
+       u32 size;
+       void *caller;
+};
+
+/* The memory returned by this allocator must be aligned, which means so must
+ * the header size.  Do not assume that sizeof(struct debug_alloc_header) is a
+ * multiple of the alignment, explicitly calculate the overhead of this header,
+ * including the alignment.  The rest of this code must not use sizeof() on any
+ * header or pointer to a header.
+ */
+#define dah_align 8
+#define dah_overhead ALIGN(sizeof(struct debug_alloc_header), dah_align)
+
+static u64 debug_alloc_pool_aligned[256*1024/dah_align];       /* 256K pool */
+static char *debug_alloc_pool = (char *)debug_alloc_pool_aligned;
+static u32 dah_first, dah_first_call = 1, dah_used = 0, dah_used_max = 0;
+
+/* Locking is awkward.  The debug code is called from all contexts, including
+ * non maskable interrupts.  A normal spinlock is not safe in NMI context.  Try
+ * to get the debug allocator lock, if it cannot be obtained after a second
+ * then give up.  If the lock could not be previously obtained on this cpu then
+ * only try once.
+ *
+ * sparse has no annotation for "this function _sometimes_ acquires a lock", so
+ * fudge the acquire/release notation.
+ */
+static DEFINE_SPINLOCK(dap_lock);
+static int
+get_dap_lock(void)
+       __acquires(dap_lock)
+{
+       static int dap_locked = -1;
+       int count;
+       if (dap_locked == smp_processor_id())
+               count = 1;
+       else
+               count = 1000;
+       while (1) {
+               if (spin_trylock(&dap_lock)) {
+                       dap_locked = -1;
+                       return 1;
+               }
+               if (!count--)
+                       break;
+               udelay(1000);
+       }
+       dap_locked = smp_processor_id();
+       __acquire(dap_lock);
+       return 0;
+}
+
+void
+*debug_kmalloc(size_t size, gfp_t flags)
+{
+       unsigned int rem, h_offset;
+       struct debug_alloc_header *best, *bestprev, *prev, *h;
+       void *p = NULL;
+       if (!get_dap_lock()) {
+               __release(dap_lock);    /* we never actually got it */
+               return NULL;
+       }
+       h = (struct debug_alloc_header *)(debug_alloc_pool + dah_first);
+       if (dah_first_call) {
+               h->size = sizeof(debug_alloc_pool_aligned) - dah_overhead;
+               dah_first_call = 0;
+       }
+       size = ALIGN(size, dah_align);
+       prev = best = bestprev = NULL;
+       while (1) {
+               if (h->size >= size && (!best || h->size < best->size)) {
+                       best = h;
+                       bestprev = prev;
+                       if (h->size == size)
+                               break;
+               }
+               if (!h->next)
+                       break;
+               prev = h;
+               h = (struct debug_alloc_header *)(debug_alloc_pool + h->next);
+       }
+       if (!best)
+               goto out;
+       rem = best->size - size;
+       /* The pool must always contain at least one header */
+       if (best->next == 0 && bestprev == NULL && rem < dah_overhead)
+               goto out;
+       if (rem >= dah_overhead) {
+               best->size = size;
+               h_offset = ((char *)best - debug_alloc_pool) +
+                          dah_overhead + best->size;
+               h = (struct debug_alloc_header *)(debug_alloc_pool + h_offset);
+               h->size = rem - dah_overhead;
+               h->next = best->next;
+       } else
+               h_offset = best->next;
+       best->caller = __builtin_return_address(0);
+       dah_used += best->size;
+       dah_used_max = max(dah_used, dah_used_max);
+       if (bestprev)
+               bestprev->next = h_offset;
+       else
+               dah_first = h_offset;
+       p = (char *)best + dah_overhead;
+       memset(p, POISON_INUSE, best->size - 1);
+       *((char *)p + best->size - 1) = POISON_END;
+out:
+       spin_unlock(&dap_lock);
+       return p;
+}
+
+void
+debug_kfree(void *p)
+{
+       struct debug_alloc_header *h;
+       unsigned int h_offset;
+       if (!p)
+               return;
+       if ((char *)p < debug_alloc_pool ||
+           (char *)p >= debug_alloc_pool + sizeof(debug_alloc_pool_aligned)) {
+               kfree(p);
+               return;
+       }
+       if (!get_dap_lock()) {
+               __release(dap_lock);    /* we never actually got it */
+               return;         /* memory leak, cannot be helped */
+       }
+       h = (struct debug_alloc_header *)((char *)p - dah_overhead);
+       memset(p, POISON_FREE, h->size - 1);
+       *((char *)p + h->size - 1) = POISON_END;
+       h->caller = NULL;
+       dah_used -= h->size;
+       h_offset = (char *)h - debug_alloc_pool;
+       if (h_offset < dah_first) {
+               h->next = dah_first;
+               dah_first = h_offset;
+       } else {
+               struct debug_alloc_header *prev;
+               unsigned int prev_offset;
+               prev = (struct debug_alloc_header *)(debug_alloc_pool + dah_first);
+               while (1) {
+                       if (!prev->next || prev->next > h_offset)
+                               break;
+                       prev = (struct debug_alloc_header *)
+                               (debug_alloc_pool + prev->next);
+               }
+               prev_offset = (char *)prev - debug_alloc_pool;
+               if (prev_offset + dah_overhead + prev->size == h_offset) {
+                       prev->size += dah_overhead + h->size;
+                       memset(h, POISON_FREE, dah_overhead - 1);
+                       *((char *)h + dah_overhead - 1) = POISON_END;
+                       h = prev;
+                       h_offset = prev_offset;
+               } else {
+                       h->next = prev->next;
+                       prev->next = h_offset;
+               }
+       }
+       if (h_offset + dah_overhead + h->size == h->next) {
+               struct debug_alloc_header *next;
+               next = (struct debug_alloc_header *)
+                       (debug_alloc_pool + h->next);
+               h->size += dah_overhead + next->size;
+               h->next = next->next;
+               memset(next, POISON_FREE, dah_overhead - 1);
+               *((char *)next + dah_overhead - 1) = POISON_END;
+       }
+       spin_unlock(&dap_lock);
+}
+
+void
+debug_kusage(void)
+{
+       struct debug_alloc_header *h_free, *h_used;
+#ifdef CONFIG_IA64
+       /* FIXME: using dah for ia64 unwind always results in a memory leak.
+        * Fix that memory leak first, then set debug_kusage_one_time = 1 for
+        * all architectures.
+        */
+       static int debug_kusage_one_time = 0;
+#else
+       static int debug_kusage_one_time = 1;
+#endif
+       if (!get_dap_lock()) {
+               __release(dap_lock);    /* we never actually got it */
+               return;
+       }
+       h_free = (struct debug_alloc_header *)(debug_alloc_pool + dah_first);
+       if (dah_first == 0 &&
+           (h_free->size == sizeof(debug_alloc_pool_aligned) - dah_overhead ||
+            dah_first_call))
+               goto out;
+       if (!debug_kusage_one_time)
+               goto out;
+       debug_kusage_one_time = 0;
+       kdb_printf("%s: debug_kmalloc memory leak dah_first %d\n",
+                  __FUNCTION__, dah_first);
+       if (dah_first) {
+               h_used = (struct debug_alloc_header *)debug_alloc_pool;
+               kdb_printf("%s: h_used %p size %d\n", __FUNCTION__, h_used, h_used->size);
+       }
+       do {
+               h_used = (struct debug_alloc_header *)
+                         ((char *)h_free + dah_overhead + h_free->size);
+               kdb_printf("%s: h_used %p size %d caller %p\n",
+                          __FUNCTION__, h_used, h_used->size, h_used->caller);
+               h_free = (struct debug_alloc_header *)
+                         (debug_alloc_pool + h_free->next);
+       } while (h_free->next);
+       h_used = (struct debug_alloc_header *)
+                 ((char *)h_free + dah_overhead + h_free->size);
+       if ((char *)h_used - debug_alloc_pool !=
+           sizeof(debug_alloc_pool_aligned))
+               kdb_printf("%s: h_used %p size %d caller %p\n",
+                          __FUNCTION__, h_used, h_used->size, h_used->caller);
+out:
+       spin_unlock(&dap_lock);
+}
+
+/* Maintain a small stack of kdb_flags to allow recursion without disturbing
+ * the global kdb state.
+ */
+
+static int kdb_flags_stack[4], kdb_flags_index;
+
+void
+kdb_save_flags(void)
+{
+       BUG_ON(kdb_flags_index >= ARRAY_SIZE(kdb_flags_stack));
+       kdb_flags_stack[kdb_flags_index++] = kdb_flags;
+}
+
+void
+kdb_restore_flags(void)
+{
+       BUG_ON(kdb_flags_index <= 0);
+       kdb_flags = kdb_flags_stack[--kdb_flags_index];
+}
diff --git a/kdb/modules/Makefile b/kdb/modules/Makefile
new file mode 100644 (file)
index 0000000..11524d1
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (c) 1999-2006 Silicon Graphics, Inc.  All Rights Reserved.
+#
+
+obj-$(CONFIG_KDB_MODULES) += kdbm_pg.o kdbm_task.o kdbm_vm.o kdbm_sched.o
+obj-m += kdbm_debugtypes.o
+ifdef CONFIG_X86
+obj-$(CONFIG_KDB_MODULES) += kdbm_x86.o
+endif
+CFLAGS_kdbm_vm.o       += -I $(srctree)/drivers/scsi
diff --git a/kdb/modules/kdbm_debugtypes.c b/kdb/modules/kdbm_debugtypes.c
new file mode 100644 (file)
index 0000000..5141300
--- /dev/null
@@ -0,0 +1,388 @@
+/* this one has some additional address validation - untested */
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+/*
+ *
+ * Most of this code is borrowed and adapted from the lkcd command "lcrash"
+ * and its supporting libarary.
+ *
+ * This module provides kdb commands for casting memory structures.
+ * It loads symbolic debugging info (provided from lcrash -o), and provides
+ *  "print" "px", "pd"
+ * (this information originally comes from the lcrash "kerntypes" file)
+ *
+ * A key here is tacking a file of debug info onto this module, for
+ * load with it at insmod time.
+ *
+ * Careful of porting the klib KL_XXX functions (they call thru a jump table
+ * that we don't use here)
+ *
+ * Usage:
+ *  in order for the insmod kdbm_debugtypes.ko to succeed in loading types
+ *  you must first use  lcrash -t kerntypes.xxxx -o debug_info
+ *  and echo debug_info > /proc/kdb/debug_info_name
+ */
+
+#define VMALLOC_START_IA64 0xa000000200000000
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/fs.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/fcntl.h>
+#include <linux/vmalloc.h>
+#include <linux/ctype.h>
+#include <linux/file.h>
+#include <linux/err.h>
+#include "lcrash/klib.h"
+#include "lcrash/kl_stringtab.h"
+#include "lcrash/kl_btnode.h"
+#include "lcrash/lc_eval.h"
+
+MODULE_AUTHOR("SGI");
+MODULE_DESCRIPTION("Load symbolic debugging information");
+MODULE_LICENSE("GPL");
+
+#undef next_node /* collision with nodemask.h */
+static char    *stringstorage, **stringp_array;
+static void    *filestorage;
+static long    num_strings, num_kltypes, num_dsyms, stringstorage_size;
+extern int     have_debug_file;
+extern dbg_sym_t *types_tree_head;
+extern dbg_sym_t *typedefs_tree_head;
+extern kltype_t         *kltype_array;
+extern dbg_sym_t *dsym_types_array;
+extern dbg_sym_t *type_tree;
+extern dbg_sym_t *typedef_tree;
+
+/*
+ * use a pointer's value as an index in the stringp_array (num_strings) and
+ * translate it to string address
+ *
+ * Return 0 for success, 1 for failure
+ */
+static int
+index_to_char_ptr(char **ptrp)
+{
+       long    i;
+
+       i = (long)*ptrp;
+       /* we use a value of -1 to mean this was a null pointer */
+       if (i == -1) {
+               *ptrp = NULL;
+               return 0;
+       }
+       if (i > num_strings-1) {
+               printk("Could not translate character string index %#lx\n", i);
+               return 1;
+       }
+       *ptrp = *(stringp_array+i);
+       return 0;
+}
+
+/*
+ * use a pointer's value as an index in the kltype_array (num_kltypes) and
+ * translate it to the kltype_t address
+ *
+ * return 0 for success, 1 for failure
+ */
+static int
+index_to_kltype_ptr(kltype_t **ptrp)
+{
+       long    i;
+
+       i = (long)*ptrp;
+       /* we use a value of -1 to mean this was a null pointer */
+       if (i == -1) {
+               *ptrp = NULL;
+               return 0;
+       }
+       if (i > num_kltypes-1) {
+               printk("Could not translate kl_type string index %#lx\n", i);
+               return 1;
+       }
+       *ptrp = kltype_array+i;
+       return 0;
+}
+
+/*
+ * look up a pointer in the dsym_types_array (num_dsyms) and
+ * translate it to the index in the array
+ *
+ * return 0 for success, 1 for failure
+ */
+static int
+index_to_dbg_ptr(dbg_sym_t **ptrp)
+{
+       long    i;
+
+       i = (long)*ptrp;
+       /* we use a value of -1 to mean this was a null pointer */
+       if (i == -1) {
+               *ptrp = NULL;
+               return 0;
+       }
+       if (i > num_dsyms-1) {
+               printk("Could not translate dbg_sym_t index %#lx\n", i);
+               return 1;
+       }
+       *ptrp = dsym_types_array+i;
+       return 0;
+}
+
+
+/*
+ * Work on the image of the file built by lcrash.
+ * Unpack the strings, and resolve the pointers in the arrays of kltype_t's
+ * and dbg_sym_t's to pointers.
+ *
+ * see lcrash's lib/libklib/kl_debug.c, which generates this file
+ *
+ * Return the pointers to the heads of the two binary trees by means of
+ * pointer arguments.
+ *
+ * Return 0 for sucess, 1 for any error.
+ */
+static int
+trans_file_image(void *file_storage, long file_size,  dbg_sym_t **type_treepp,
+               dbg_sym_t **typedef_treepp)
+{
+       int             len;
+       long            i, section_size, *lp, element_size;
+       long            head_types_tree, head_typedefs_tree;
+       char            *ptr, *stringsection, *kltypesection, *dbgsection;
+       void            *kltypestorage, *dbgstorage;
+       kltype_t        *klp;
+       dbg_sym_t       *dbgp;
+
+       /* 1) the strings */
+       lp = (long *)file_storage;
+       stringsection = (char *)lp;
+       section_size = *lp++;
+       num_strings = *lp++;
+       lp++; /* element size does not apply the strings section */
+
+       stringstorage_size = section_size - (3*sizeof(long));
+       stringstorage = (char *)lp;
+
+       stringp_array = (char **)vmalloc(num_strings * sizeof(char *));
+       if (! stringp_array) {
+               printk("vmalloc of %ld string pointers failed\n", num_strings);
+               return 1;
+       }
+       ptr = stringstorage;
+       for (i=0; i<num_strings; i++) {
+               *(stringp_array+i) = ptr;
+               len = strlen(ptr) + 1;
+               ptr += len;
+       }
+
+       /* 2) the kltypes */
+       kltypesection = (char *)(stringsection + section_size);
+       lp = (long *)kltypesection;
+       section_size = *lp++;
+       num_kltypes = *lp++;
+       element_size = *lp++;
+       /* sanity check: */
+       if (element_size != sizeof(kltype_t)) {
+               printk("size of kltype_t:%ld does not match\n", element_size);
+               goto bad;
+       }
+       kltypestorage = (void *)lp;
+       kltype_array = (kltype_t *)kltypestorage;
+
+       /* 3) the dbg_sym_t's */
+       dbgsection = (char *)kltypesection + section_size;
+       lp = (long *)dbgsection;
+       section_size = *lp++;
+       /* sanity check: */
+       if ((dbgsection + section_size) != ((char *)file_storage+file_size)) {
+               printk("dbg_sym_ts do not end at end of file\n");
+               goto bad;
+       }
+       num_dsyms = *lp++;
+       element_size = *lp++;
+       /* sanity check: */
+       if (element_size != sizeof(dbg_sym_t)) {
+               printk("kdb: size of dbg_sym_t does not match lkcd\'s\n");
+               goto bad;
+       }
+
+       /* two special words ahead of the structures themselves */
+       head_types_tree = *lp++;
+       head_typedefs_tree = *lp++;
+
+       dbgstorage = (void *)lp;
+       dsym_types_array = (dbg_sym_t *)dbgstorage;
+
+       /* return the heads of the two binary trees */
+       *type_treepp = dsym_types_array+head_types_tree;
+       *typedef_treepp = dsym_types_array+head_typedefs_tree;
+
+       /* translate the indices in our our array of kltype_t's to pointers */
+       /*  (see write_kltype() for the fields that can be translated) */
+       klp = kltype_array;
+       for (i=0; i<num_kltypes; i++, klp++) {
+               if (index_to_char_ptr(&klp->kl_name))
+                       goto bad;
+               if (index_to_char_ptr(&klp->kl_typestr))
+                       goto bad;
+               if (index_to_kltype_ptr(&klp->kl_member))
+                       goto bad;
+               if (index_to_kltype_ptr(&klp->kl_next))
+                       goto bad;
+               if (index_to_kltype_ptr(&klp->kl_realtype))
+                       goto bad;
+               if (index_to_kltype_ptr(&klp->kl_indextype))
+                       goto bad;
+               if (index_to_kltype_ptr(&klp->kl_elementtype))
+                       goto bad;
+               if (index_to_dbg_ptr((dbg_sym_t **)&klp->kl_ptr))
+                       goto bad;
+       }
+
+       /* translate the indices in our our array of dbg_sym_t's to pointers */
+       /*  (see write_dbgtype() for the fields that can be translated) */
+       dbgp = dsym_types_array;
+       for (i=0; i<num_dsyms; i++, dbgp++) {
+               if (index_to_char_ptr(&dbgp->sym_bt.bt_key))
+                       goto bad;
+               if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_bt.bt_left))
+                       goto bad;
+               if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_bt.bt_right))
+                       goto bad;
+               if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_bt.bt_parent))
+                       goto bad;
+               if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_next))
+                       goto bad;
+               if (index_to_dbg_ptr((dbg_sym_t **)&dbgp->sym_link))
+                       goto bad;
+               if (index_to_kltype_ptr(&dbgp->sym_kltype))
+                       goto bad;
+       }
+
+       vfree(stringp_array);
+       return 0;
+bad:
+       printk("trans_file_image() returning an error\n");
+       vfree(stringp_array);
+       return 1;
+}
+
+/* there is /proc interface to this string */
+extern char kdb_debug_info_filename[];
+/*
+ * This is the module initialization function.
+ */
+static int __init
+kdbm_debuginfo_init(void)
+{
+       int             len;
+       long            ret, file_size;
+       ssize_t         sizeread;
+       mm_segment_t    fs;
+       struct file     *file;
+       loff_t          inode_size, pos;
+
+       len = strlen(kdb_debug_info_filename);
+       if (!len) {
+               printk("kdb: no file name in /proc/kdb/debug_info_name\n");
+               return -ENODEV;
+       }
+
+       fs = get_fs();     /* save previous value of address limits */
+       set_fs (get_ds()); /* use kernel limit */
+
+        file = filp_open(kdb_debug_info_filename, O_RDONLY, 0);
+       if (IS_ERR(file)) {
+               set_fs(fs);
+               printk (
+                 "kdb: open of %s (from /proc/kdb/debug_info_name) failed\n",
+                       kdb_debug_info_filename);
+               return -ENODEV;
+       }
+       if (!file->f_op || (!file->f_op->read && !file->f_op->llseek)) {
+               printk ("file has no operation for read or seek\n");
+               set_fs(fs);
+               return -ENODEV;
+       }
+       inode_size = file->f_dentry->d_inode->i_size;
+
+       /*
+        * File has a header word on it that contains the size of the
+        * file.  We don't need it, but can use it as a sanity check.
+        */
+       pos = 0;
+       sizeread = file->f_op->read(file, (char *)&file_size,
+                                       sizeof(file_size), &pos);
+       if (sizeread != sizeof(file_size)) {
+               printk("could not read %d bytes from %s\n",
+                       (int)sizeof(file_size), kdb_debug_info_filename);
+               ret = filp_close(file, NULL);
+               set_fs(fs);
+               return -ENODEV;
+       }
+       if (inode_size != file_size) {
+               printk("file says %ld, inode says %lld\n",
+                               file_size, inode_size);
+               ret = filp_close(file, NULL);
+               set_fs(fs);
+               return -ENODEV;
+       }
+
+       /* space for the rest of the file: */
+       file_size -= sizeof(long);
+       filestorage = (void *)vmalloc(file_size);
+
+       pos = sizeof(file_size); /* position after the header word */
+       sizeread = file->f_op->read(file, (char *)filestorage,
+                                        file_size, &pos);
+       if (sizeread != file_size) {
+               printk("could not read %ld bytes from %s\n",
+                       file_size, kdb_debug_info_filename);
+               ret = filp_close(file, NULL);
+               set_fs(fs);
+               vfree (filestorage);
+               return -ENODEV;
+       }
+
+       ret = filp_close(file, NULL);
+       set_fs(fs); /* restore address limits before returning to user space */
+
+       if (trans_file_image(filestorage, file_size, &types_tree_head,
+                                                    &typedefs_tree_head)){
+               vfree (filestorage);
+               return -ENODEV;
+       }
+       printk("kdbm_debuginfo loaded %s\n", kdb_debug_info_filename);
+       /* set the lcrash code's binary tree head nodes */
+       type_tree = types_tree_head;
+       typedef_tree = typedefs_tree_head;
+
+       have_debug_file = 1;
+
+       return 0;
+}
+
+/*
+ * This is the module exit function.
+ */
+static void __exit
+kdbm_debuginfo_exit(void)
+{
+       printk("kdbm_debuginfo unloaded %s\n", kdb_debug_info_filename);
+       vfree (filestorage);
+       have_debug_file = 0;
+       return;
+}
+
+module_init(kdbm_debuginfo_init);
+module_exit(kdbm_debuginfo_exit);
diff --git a/kdb/modules/kdbm_pg.c b/kdb/modules/kdbm_pg.c
new file mode 100644 (file)
index 0000000..fa7a6a2
--- /dev/null
@@ -0,0 +1,689 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/fs.h>
+#include <linux/bio.h>
+#include <linux/buffer_head.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 */
+
+#if !defined(CONFIG_DISCONTIGMEM) && !defined(CONFIG_NUMA)
+/* From include/linux/page-flags.h */
+static char *pg_flag_vals[] = {
+       "PG_locked", "PG_error", "PG_referenced", "PG_uptodate",
+       "PG_dirty", "PG_lru", "PG_active", "PG_slab",
+       "PG_owner_priv_1", "PG_arch_1", "PG_reserved", "PG_private",
+       "PG_writeback",
+#ifdef CONFIG_PAGEFLAGS_EXTENDED
+       "PG_head", "PG_tail",
+#else
+       "PG_compound",
+#endif
+       "PG_swapcache", "PG_mappedtodisk", "PG_reclaim", "PG_buddy",
+#ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
+       "PG_uncached",
+#endif
+       NULL };
+#endif
+
+/* From include/linux/buffer_head.h */
+static char *bh_state_vals[] = {
+       "Uptodate", "Dirty", "Lock", "Req",
+       "Uptodate_Lock", "Mapped", "New", "Async_read",
+       "Async_write", "Delay", "Boundary", "Write_EIO",
+       "Ordered", "Eopnotsupp", "Unwritten", "PriavateStart",
+       NULL };
+
+/* From include/linux/bio.h */
+static char *bio_flag_vals[] = {
+       "Uptodate", "RW_block", "EOF", "Seg_valid",
+       "Cloned", "Bounced", "User_mapped", "Eopnotsupp",
+       NULL };
+
+/* From include/linux/fs.h */
+static char *inode_flag_vals[] = {
+       "I_DIRTY_SYNC", "I_DIRTY_DATASYNC", "I_DIRTY_PAGES", "I_NEW",
+       "I_WILL_FREE", "I_FREEING", "I_CLEAR", "I_LOCK",
+       "I_SYNC", 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 int
+kdbm_buffers(int argc, const char **argv)
+{
+       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)) ||
+           (diag = kdb_getarea(bh, addr)))
+               return(diag);
+
+       kdb_printf("buffer_head at 0x%lx\n", addr);
+       kdb_printf("  bno %llu size %llu dev 0x%x\n",
+               (unsigned long long)bh.b_blocknr,
+               (unsigned long long)bh.b_size,
+               bh.b_bdev ? bh.b_bdev->bd_dev : 0);
+       kdb_printf("  count %d state 0x%lx [%s]\n",
+               bh.b_count.counter, bh.b_state,
+               map_flags(bh.b_state, bh_state_vals));
+       kdb_printf("  b_data 0x%p\n",
+               bh.b_data);
+       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
+print_biovec(struct bio_vec *vec, int vcount)
+{
+       struct bio_vec bvec;
+       unsigned long addr;
+       int diag;
+       int i;
+
+       if (vcount < 1 || vcount > BIO_MAX_PAGES) {
+               kdb_printf("  [skipped iovecs, vcnt is %d]\n", vcount);
+               return 0;
+       }
+
+       addr = (unsigned long)vec;
+       for (i = 0; i < vcount; i++) {
+               if ((diag = kdb_getarea(bvec, addr)))
+                       return(diag);
+               addr += sizeof(bvec);
+               kdb_printf("  [%d] page 0x%p length=%u offset=%u\n",
+                       i, bvec.bv_page, bvec.bv_len, bvec.bv_offset);
+       }
+       return 0;
+}
+
+static int
+kdbm_bio(int argc, const char **argv)
+{
+       struct bio bio;
+       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)) ||
+           (diag = kdb_getarea(bio, addr)))
+               return(diag);
+
+       kdb_printf("bio at 0x%lx\n", addr);
+       kdb_printf("  bno %llu  next 0x%p  dev 0x%x\n",
+               (unsigned long long)bio.bi_sector,
+               bio.bi_next, bio.bi_bdev ? bio.bi_bdev->bd_dev : 0);
+       kdb_printf("  vcnt %u vec 0x%p  rw 0x%lx flags 0x%lx [%s]\n",
+               bio.bi_vcnt, bio.bi_io_vec, bio.bi_rw, bio.bi_flags,
+               map_flags(bio.bi_flags, bio_flag_vals));
+       print_biovec(bio.bi_io_vec, bio.bi_vcnt);
+       kdb_printf("  count %d  private 0x%p\n",
+               atomic_read(&bio.bi_cnt), bio.bi_private);
+       kdb_printf("  bi_end_io ");
+       if (bio.bi_end_io)
+               kdb_symbol_print(kdba_funcptr_value(bio.bi_end_io), NULL, KDB_SP_VALUE);
+       else
+               kdb_printf("(NULL)");
+       kdb_printf("\n");
+
+       return 0;
+}
+
+#if !defined(CONFIG_DISCONTIGMEM) && !defined(CONFIG_NUMA)
+static char *page_flags(unsigned long flags)
+{
+       return(map_flags(flags, pg_flag_vals));
+}
+
+static int
+kdbm_page(int argc, const char **argv)
+{
+       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);
+       if (diag)
+               return diag;
+
+#ifdef __ia64__
+       if (rgn_index(addr) == 0)
+               addr = (unsigned long) &mem_map[addr];  /* assume region 0 is a page index, not an address */
+#else
+       if (addr < PAGE_OFFSET)
+               addr = (unsigned long) &mem_map[addr];
+#endif
+
+       if ((diag = kdb_getarea(page, addr)))
+               return(diag);
+
+       kdb_printf("struct page at 0x%lx\n", addr);
+       kdb_printf("  addr space 0x%p index %lu (offset 0x%llx)\n",
+                  page.mapping, page.index,
+                  (unsigned long long)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_has_buffers(&page))
+               kdb_printf("  buffers 0x%p\n", page_buffers(&page));
+       else
+               kdb_printf("  private 0x%lx\n", page_private(&page));
+
+       return 0;
+}
+#endif /* !CONFIG_DISCONTIGMEM && !NUMA */
+
+static 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("  errors %d sector %llu nr_sectors %lu\n",
+                       rq.errors,
+                       (unsigned long long)rq.sector, rq.nr_sectors);
+
+       kdb_printf("  hsect %llu hnrsect %lu nrseg %u nrhwseg %u currnrsect %u\n",
+                       (unsigned long long)rq.hard_sector, rq.hard_nr_sectors,
+                       rq.nr_phys_segments, rq.nr_hw_segments,
+                       rq.current_nr_sectors);
+
+       return (unsigned long) rq.queuelist.next;
+}
+
+static int
+kdbm_request(int argc, const char **argv)
+{
+       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);
+       if (diag)
+               return diag;
+
+       print_request(addr);
+       return 0;
+}
+
+
+static int
+kdbm_rqueue(int argc, const char **argv)
+{
+       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)) ||
+           (diag = kdb_getarea(rq, addr)))
+               return(diag);
+
+       kdb_printf("struct request_queue at 0x%lx\n", addr);
+       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("\tbh 0x%lx bno %8llu [%s]\n", addr,
+                (unsigned long long)bh.b_blocknr,
+                map_flags(bh.b_state, bh_state_vals));
+}
+
+static void
+kdbm_show_page(struct page *page, int first)
+{
+       if (first)
+               kdb_printf("page_struct       index   cnt zone nid flags\n");
+       kdb_printf("%p%s %6lu %5d %3d %3d 0x%lx",
+               page_address(page), sizeof(void *) == 4 ? "        " : "",
+               page->index, atomic_read(&(page->_count)),
+               page_zonenum(page), page_to_nid(page),
+               page->flags & (~0UL >> ZONES_SHIFT));
+#define kdb_page_flags(page, type) if (Page ## type(page)) kdb_printf(" " #type);
+       kdb_page_flags(page, Locked);
+       kdb_page_flags(page, Error);
+       kdb_page_flags(page, Referenced);
+       kdb_page_flags(page, Uptodate);
+       kdb_page_flags(page, Dirty);
+       kdb_page_flags(page, LRU);
+       kdb_page_flags(page, Active);
+       kdb_page_flags(page, Slab);
+       kdb_page_flags(page, Checked);
+       if (page->flags & (1UL << PG_arch_1))
+               kdb_printf(" arch_1");
+       kdb_page_flags(page, Reserved);
+       kdb_page_flags(page, Private);
+       kdb_page_flags(page, Writeback);
+       kdb_page_flags(page, Compound);
+       kdb_page_flags(page, SwapCache);
+       kdb_page_flags(page, MappedToDisk);
+       kdb_page_flags(page, Reclaim);
+       kdb_page_flags(page, Buddy);
+
+       /* PageHighMem is not a flag any more, but treat it as one */
+       kdb_page_flags(page, HighMem);
+
+       if (page_has_buffers(page)) {
+               struct buffer_head *head, *bh;
+               kdb_printf("\n");
+               head = bh = page_buffers(page);
+               do {
+                       do_buffer((unsigned long) bh);
+               } while ((bh = bh->b_this_page) != head);
+       } else if (page_private(page)) {
+               kdb_printf(" private= 0x%lx", page_private(page));
+       }
+       /* Cannot use page_mapping(page) here, it needs swapper_space which is
+        * not exported.
+        */
+       if (page->mapping)
+               kdb_printf(" mapping= %p", page->mapping);
+       kdb_printf("\n");
+#undef kdb_page_flags
+}
+
+static int
+kdbm_inode_pages(int argc, const char **argv)
+{
+       struct inode *inode = NULL;
+       struct address_space *ap = NULL;
+       unsigned long addr, addr1 = 0;
+       long offset = 0;
+       int nextarg;
+       int diag;
+       pgoff_t next = 0;
+       struct page *page;
+       int first;
+
+       nextarg = 1;
+       diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
+       if (diag)
+               goto out;
+
+       if (argc == 2) {
+               nextarg = 2;
+               diag = kdbgetaddrarg(argc, argv, &nextarg, &addr1,
+                                       &offset, NULL);
+               if (diag)
+                       goto out;
+               kdb_printf("Looking for page index 0x%lx ... \n", addr1);
+               next = 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;
+
+       /* Run the pages in the radix tree, printing the state of each page */
+       first = 1;
+       while (radix_tree_gang_lookup(&ap->page_tree, (void **)&page, next, 1)) {
+               kdbm_show_page(page, first);
+               if (addr1)
+                       break;
+               first = 0;
+               next = page->index + 1;
+       }
+
+out:
+       if (inode)
+               kfree(inode);
+       if (ap)
+               kfree(ap);
+       return diag;
+}
+
+static int
+kdbm_inode(int argc, const char **argv)
+{
+       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)))
+               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_size %Ld\n",
+                                       inode->i_ino, atomic_read(&inode->i_count),
+                                       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.pprev = 0x%p\n",
+               inode->i_hash.next,
+               inode->i_hash.pprev);
+
+       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_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, i_private);
+
+       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)
+{
+       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)))
+               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_frozen %d s_id [%s]\n", sb->s_frozen, sb->s_id);
+out:
+       if (sb)
+               kfree(sb);
+       return diag;
+}
+
+
+#if !defined(CONFIG_DISCONTIGMEM) && !defined(CONFIG_NUMA)
+/* 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)
+{
+       struct page page;
+       int i, page_count;
+       int slab_count = 0;
+       int dirty_count = 0;
+       int locked_count = 0;
+       int page_counts[10];    /* [8] = large counts, [9] = -1 counts */
+       int buffered_count = 0;
+#ifdef buffer_delay
+       int delay_count = 0;
+#endif
+       int diag;
+       unsigned long addr;
+#ifdef CONFIG_DISCONTIGMEM
+       int node_id = -1, found_node = 0;
+       int tot_page_count = 0;
+       unsigned long unode_id;
+       pg_data_t *pgdat;
+
+       if (argc == 1) {                /* node_id was specified */
+           diag = kdbgetularg(argv[argc], &unode_id);
+           if (diag)
+               return diag;
+           node_id = (int)unode_id;
+       }
+       else if (argc)
+           return KDB_ARGCOUNT;
+
+       tot_page_count = 0;
+       memset(page_counts, 0, sizeof(page_counts));
+
+       for_each_online_pgdat(pgdat) {
+           if ((node_id != -1) && (pgdat->node_id != node_id))
+               continue;
+           found_node = 1;
+           addr = (unsigned long)pgdat->node_mem_map;
+           page_count = pgdat->node_spanned_pages;
+           tot_page_count += page_count;
+#else
+       addr = (unsigned long)mem_map;
+       page_count = max_mapnr;
+       memset(page_counts, 0, sizeof(page_counts));
+#endif
+       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 == -1)
+                        page_counts[9]++;
+               else if (page._count.counter < 8)
+                       page_counts[page._count.counter]++;
+               else
+                       page_counts[8]++;
+               if (page_has_buffers(&page)) {
+                       buffered_count++;
+#ifdef buffer_delay
+                       if (buffer_delay(page.buffers))
+                               delay_count++;
+#endif
+               }
+       }
+#ifdef CONFIG_DISCONTIGMEM
+       }
+       page_count = tot_page_count;
+       if (node_id != -1) {
+           if (!found_node) {
+               kdb_printf("Node %d does not exist.\n", node_id);
+               return 0;
+           }
+           kdb_printf("Node %d pages:\n", node_id);
+       }
+#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
+       kdb_printf(" -1 page count:     %6d\n", page_counts[9]);
+       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_DISCONTIGMEM && !NUMA */
+
+static int __init kdbm_pg_init(void)
+{
+#if !defined(CONFIG_DISCONTIGMEM) && !defined(CONFIG_NUMA)
+       kdb_register("page", kdbm_page, "<vaddr>", "Display page", 0);
+#endif
+       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("bio", kdbm_bio, "<bio address>", "Display bio", 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);
+#if !defined(CONFIG_DISCONTIGMEM) && !defined(CONFIG_NUMA)
+       kdb_register("memmap", kdbm_memmap, "", "page table summary", 0);
+#endif
+
+       return 0;
+}
+
+
+static void __exit kdbm_pg_exit(void)
+{
+#if !defined(CONFIG_DISCONTIGMEM) && !defined(CONFIG_NUMA)
+       kdb_unregister("page");
+#endif
+       kdb_unregister("inode");
+       kdb_unregister("sb");
+       kdb_unregister("bh");
+       kdb_unregister("bio");
+       kdb_unregister("inode_pages");
+       kdb_unregister("req");
+       kdb_unregister("rqueue");
+#if !defined(CONFIG_DISCONTIGMEM) && !defined(CONFIG_NUMA)
+       kdb_unregister("memmap");
+#endif
+}
+
+module_init(kdbm_pg_init)
+module_exit(kdbm_pg_exit)
diff --git a/kdb/modules/kdbm_sched.c b/kdb/modules/kdbm_sched.c
new file mode 100644 (file)
index 0000000..a0e9e28
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+MODULE_AUTHOR("SGI");
+MODULE_DESCRIPTION("Debug scheduler information");
+MODULE_LICENSE("GPL");
+
+static int
+kdbm_runqueues(int argc, const char **argv)
+{
+       unsigned long cpu;
+       int ret = 0;
+
+       if (argc == 1) {
+               ret = kdbgetularg((char *)argv[1], &cpu);
+               if (!ret) {
+                       if (!cpu_online(cpu)) {
+                               kdb_printf("Invalid cpu number\n");
+                       } else
+                               kdb_runqueue(cpu, kdb_printf);
+               }
+       } else if (argc == 0) {
+               for_each_online_cpu(cpu)
+                       kdb_runqueue(cpu, kdb_printf);
+       } else {
+               /* More than one arg */
+               kdb_printf("Specify one cpu number\n");
+       }
+       return ret;
+}
+
+static int __init kdbm_sched_init(void)
+{
+       kdb_register("rq",  kdbm_runqueues, "<cpunum>", "Display runqueue for <cpunum>", 0);
+       kdb_register("rqa", kdbm_runqueues, "", "Display all runqueues", 0);
+       return 0;
+}
+
+static void __exit kdbm_sched_exit(void)
+{
+       kdb_unregister("rq");
+       kdb_unregister("rqa");
+}
+
+module_init(kdbm_sched_init)
+module_exit(kdbm_sched_exit)
diff --git a/kdb/modules/kdbm_task.c b/kdb/modules/kdbm_task.c
new file mode 100644 (file)
index 0000000..2e5b7d6
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2006 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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");
+
+static char *
+kdb_cpus_allowed_string(struct task_struct *tp)
+{
+       static char maskbuf[NR_CPUS * 8];
+       if (cpus_equal(tp->cpus_allowed, cpu_online_map))
+               strcpy(maskbuf, "ALL");
+       else if (cpus_full(tp->cpus_allowed))
+               strcpy(maskbuf, "ALL(NR_CPUS)");
+       else if (cpus_empty(tp->cpus_allowed))
+               strcpy(maskbuf, "NONE");
+       else if (cpus_weight(tp->cpus_allowed) == 1)
+               snprintf(maskbuf, sizeof(maskbuf), "ONLY(%d)", first_cpu(tp->cpus_allowed));
+       else
+               cpulist_scnprintf(maskbuf, sizeof(maskbuf), tp->cpus_allowed);
+       return maskbuf;
+}
+
+static int
+kdbm_task(int argc, const char **argv)
+{
+       unsigned long addr;
+       long offset=0;
+       int nextarg;
+       int e = 0;
+       struct task_struct *tp = NULL, *tp1;
+
+       if (argc != 1)
+               return KDB_ARGCOUNT;
+
+       nextarg = 1;
+       if ((e = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL)) != 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;
+       }
+
+       tp1 = (struct task_struct *)addr;
+       kdb_printf(
+           "struct task at 0x%lx, pid=%d flags=0x%x state=%ld comm=\"%s\"\n",
+           addr, tp->pid, tp->flags, tp->state, tp->comm);
+
+       kdb_printf("  cpu=%d policy=%u ", kdb_process_cpu(tp), tp->policy);
+       kdb_printf(
+           "prio=%d static_prio=%d cpus_allowed=",
+           tp->prio, tp->static_prio);
+       {
+               /* The cpus allowed string may be longer than kdb_printf() can
+                * handle.  Print it in chunks.
+                */
+               char c, *p;
+               p = kdb_cpus_allowed_string(tp);
+               while (1) {
+                       if (strlen(p) < 100) {
+                               kdb_printf("%s", p);
+                               break;
+                       }
+                       c = p[100];
+                       p[100] = '\0';
+                       kdb_printf("%s", p);
+                       p[100] = c;
+                       p += 100;
+               }
+       }
+       kdb_printf(" &thread=0x%p\n", &tp1->thread);
+
+       kdb_printf("  need_resched=%d ",
+               test_tsk_thread_flag(tp, TIF_NEED_RESCHED));
+       kdb_printf(
+           "time_slice=%u",
+           tp->rt.time_slice);
+       kdb_printf(" lock_depth=%d\n", tp->lock_depth);
+
+       kdb_printf(
+           "  fs=0x%p files=0x%p mm=0x%p\n",
+           tp->fs, tp->files, tp->mm);
+
+       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\n",
+           tp->user);
+
+       if (tp->sysvsem.undo_list)
+               kdb_printf(
+                   "  sysvsem.sem_undo refcnt %d list_proc=0x%p\n",
+                   atomic_read(&tp->sysvsem.undo_list->refcnt),
+                   &tp->sysvsem.undo_list->list_proc);
+
+       kdb_printf(
+           "  signal=0x%p &blocked=0x%p &pending=0x%p\n",
+           tp->signal, &tp1->blocked, &tp1->pending);
+
+       kdb_printf(
+           "  utime=%ld stime=%ld cutime=%ld cstime=%ld\n",
+           tp->utime, tp->stime,
+           tp->signal ? tp->signal->cutime : 0L,
+           tp->signal ? tp->signal->cstime : 0L);
+
+       kdb_printf("  thread_info=0x%p\n", task_thread_info(tp));
+       kdb_printf("  ti flags=0x%lx\n", (unsigned long)task_thread_info(tp)->flags);
+
+#ifdef CONFIG_NUMA
+       kdb_printf(
+           "  mempolicy=0x%p il_next=%d\n",
+           tp->mempolicy, tp->il_next);
+#endif
+
+out:
+       if (tp)
+           kfree(tp);
+       return e;
+}
+
+static int
+kdbm_sigset(int argc, const char **argv)
+{
+       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)) != 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");
+}
+
+module_init(kdbm_task_init)
+module_exit(kdbm_task_exit)
diff --git a/kdb/modules/kdbm_vm.c b/kdb/modules/kdbm_vm.c
new file mode 100644 (file)
index 0000000..53b37a1
--- /dev/null
@@ -0,0 +1,1036 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2006 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#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/swap.h>
+#include <linux/swapops.h>
+
+#include <scsi.h>
+#include <scsi/scsi_host.h>
+#include <asm/pgtable.h>
+
+MODULE_AUTHOR("SGI");
+MODULE_DESCRIPTION("Debug VM information");
+MODULE_LICENSE("GPL");
+
+struct __vmflags {
+       unsigned long mask;
+       char *name;
+};
+
+static struct __vmflags vmflags[] = {
+       { VM_READ, "VM_READ " },
+       { VM_WRITE, "VM_WRITE " },
+       { VM_EXEC, "VM_EXEC " },
+       { VM_SHARED, "VM_SHARED " },
+       { VM_MAYREAD, "VM_MAYREAD " },
+       { VM_MAYWRITE, "VM_MAYWRITE " },
+       { VM_MAYEXEC, "VM_MAYEXEC " },
+       { VM_MAYSHARE, "VM_MAYSHARE " },
+       { VM_GROWSDOWN, "VM_GROWSDOWN " },
+       { VM_GROWSUP, "VM_GROWSUP " },
+       { VM_PFNMAP, "VM_PFNMAP " },
+       { VM_DENYWRITE, "VM_DENYWRITE " },
+       { VM_EXECUTABLE, "VM_EXECUTABLE " },
+       { VM_LOCKED, "VM_LOCKED " },
+       { VM_IO, "VM_IO " },
+       { VM_SEQ_READ, "VM_SEQ_READ " },
+       { VM_RAND_READ, "VM_RAND_READ " },
+       { VM_DONTCOPY, "VM_DONTCOPY " },
+       { VM_DONTEXPAND, "VM_DONTEXPAND " },
+       { VM_RESERVED, "VM_RESERVED " },
+       { VM_ACCOUNT, "VM_ACCOUNT " },
+       { VM_HUGETLB, "VM_HUGETLB " },
+       { VM_NONLINEAR, "VM_NONLINEAR " },
+       { VM_MAPPED_COPY, "VM_MAPPED_COPY " },
+       { VM_INSERTPAGE, "VM_INSERTPAGE " },
+       { 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%llx\n",
+               (unsigned long long)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("shared.vm_set.list.next = 0x%p\n", (void *) vp->shared.vm_set.list.next);
+       kdb_printf("shared.vm_set.list.prev = 0x%p\n", (void *) vp->shared.vm_set.list.prev);
+       kdb_printf("shared.vm_set.parent = 0x%p\n", (void *) vp->shared.vm_set.parent);
+       kdb_printf("shared.vm_set.head = 0x%p\n", (void *) vp->shared.vm_set.head);
+       kdb_printf("anon_vma_node.next = 0x%p\n", (void *) vp->anon_vma_node.next);
+       kdb_printf("anon_vma_node.prev = 0x%p\n", (void *) vp->anon_vma_node.prev);
+       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->fault = 0x%p\n", vp->vm_ops->fault);
+#ifdef HAVE_VMOP_MPROTECT
+               kdb_printf("vm_ops->mprotect = 0x%p\n", vp->vm_ops->mprotect);
+#endif
+#ifdef CONFIG_NUMA
+               kdb_printf("vm_ops->set_policy = 0x%p\n", vp->vm_ops->set_policy);
+               kdb_printf("vm_ops->get_policy = 0x%p\n", vp->vm_ops->get_policy);
+#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);
+#ifdef CONFIG_NUMA
+       kdb_printf("vm_policy = 0x%p\n", vp->vm_policy);
+#endif
+
+       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;
+}
+
+
+#ifdef CONFIG_NUMA
+#include <linux/mempolicy.h>
+
+/*
+ * kdbm_mpol
+ *
+ *     This function implements the 'mempolicy' command.
+ *     Print a struct mempolicy.
+ *
+ *     mempolicy <address>     Print struct mempolicy at <address>
+ */
+static int
+kdbm_mpol(int argc, const char **argv)
+{
+       unsigned long addr;
+       long offset = 0;
+       int nextarg;
+       int err = 0;
+       struct mempolicy *mp = NULL;
+
+       if (argc != 1)
+               return KDB_ARGCOUNT;
+
+       nextarg = 1;
+       if ((err = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset,
+                               NULL)) != 0)
+               return(err);
+
+       if (!(mp = kmalloc(sizeof(*mp), GFP_ATOMIC))) {
+               kdb_printf("%s: cannot kmalloc mp\n", __FUNCTION__);
+               goto out;
+       }
+
+       if ((err = kdb_getarea(*mp, addr))) {
+               kdb_printf("%s: invalid mempolicy address\n", __FUNCTION__);
+               goto out;
+       }
+
+       kdb_printf("struct mempolicy at 0x%p\n", (struct mempolicy *)addr);
+       kdb_printf("  refcnt %d\n", atomic_read(&mp->refcnt));
+
+       switch (mp->mode) {
+         case MPOL_DEFAULT:
+               kdb_printf("  mode %d (MPOL_DEFAULT)\n", mp->mode);
+               break;
+
+         case MPOL_PREFERRED:
+               kdb_printf("  mode %d (MPOL_PREFERRED)\n", mp->mode);
+               kdb_printf("  preferred_node %d\n", mp->v.preferred_node);
+               break;
+
+         case MPOL_BIND:
+         case MPOL_INTERLEAVE:
+         {
+               int i, nlongs;
+               unsigned long *longp;
+
+               kdb_printf("  mode %d (%s)\n", mp->mode,
+                       mp->mode == MPOL_INTERLEAVE
+                               ? "MPOL_INTERLEAVE"
+                               : "MPOL_BIND");
+               nlongs = (int)BITS_TO_LONGS(MAX_NUMNODES);
+               kdb_printf("  nodes:");
+               longp = mp->v.nodes.bits;
+               for (i = 0; i < nlongs; i++, longp++)
+                       kdb_printf("  0x%lx ", *longp);
+               kdb_printf("\n");
+               break;
+         }
+
+         default:
+               kdb_printf("  mode %d (unknown)\n", mp->mode);
+               break;
+       }
+out:
+       if (mp)
+               kfree(mp);
+       return err;
+}
+
+#endif /* CONFIG_NUMA */
+
+/*
+ * kdbm_pgdat
+ *
+ *     This function implements the 'pgdat' command.
+ *     Print a struct pglist_data (pg_dat_t).
+ *
+ *     pgdat <node_id>         Print struct pglist_data for node <node_id>.
+ *
+ *     Print pglist_data for node 0 if node_id not specified,
+ *     or print the one pglist_data structure if !CONFIG_NUMA.
+ */
+static int
+kdbm_pgdat(int argc, const char **argv)
+{
+       int err = 0, node_id = 0, i;
+       pg_data_t *pgdatp = NULL;
+
+#ifdef CONFIG_NUMA
+       if (argc > 1)
+               return KDB_ARGCOUNT;
+       if (argc == 1) {
+               int nextarg;
+               long offset = 0;
+               unsigned long node_id_ul;
+
+               nextarg = 1;
+               if ((err = kdbgetaddrarg(argc, argv, &nextarg, &node_id_ul,
+                                        &offset, NULL)) != 0) {
+                       return(err);
+               }
+               node_id = (int)node_id_ul;
+       }
+#endif
+       for_each_online_pgdat(pgdatp) {
+               if (pgdatp->node_id == node_id)
+                       break;
+       }
+       if (!pgdatp) {
+               kdb_printf("%s: specified node not found\n", __FUNCTION__);
+               return 0;
+       }
+       kdb_printf("struct pglist_data at 0x%p  node_id = %d\n",
+                  pgdatp, pgdatp->node_id);
+
+       for (i = 0; i < MAX_ZONELISTS; i++) {
+               int zr;
+               struct zoneref *zonerefp;
+               struct zone *zonep;
+
+               zonerefp = pgdatp->node_zonelists[i]._zonerefs;
+               kdb_printf("  _zonerefs[%d] at 0x%p\n", i, zonerefp);
+
+               for (zr = 0; zr <= MAX_ZONES_PER_ZONELIST; zr++, zonerefp++) {
+                       int z;
+                       pg_data_t *tmp_pgdatp;
+
+                       zonep = zonelist_zone(zonerefp);
+                       if (!zonep)
+                               break;
+
+                       kdb_printf("    0x%p", zonep);
+
+                       for_each_online_pgdat(tmp_pgdatp) {
+                               for (z = 0; z < MAX_NR_ZONES; z++) {
+                                       if (zonep == &tmp_pgdatp->node_zones[z]) {
+                                               kdb_printf ("  (node %d node_zones[%d])",
+                                                    tmp_pgdatp->node_id, z);
+                                               break;
+                                       }
+                               }
+                               if (z != MAX_NR_ZONES)
+                                       break;  /* found it */
+                       }
+                       kdb_printf("\n");
+               }
+       }
+
+       kdb_printf("  nr_zones = %d", pgdatp->nr_zones);
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
+       kdb_printf("  node_mem_map = 0x%p\n", pgdatp->node_mem_map);
+#endif
+       kdb_printf("  bdata = 0x%p", pgdatp->bdata);
+       kdb_printf("  node_start_pfn = 0x%lx\n", pgdatp->node_start_pfn);
+       kdb_printf("  node_present_pages = %ld (0x%lx)\n",
+                  pgdatp->node_present_pages, pgdatp->node_present_pages);
+       kdb_printf("  node_spanned_pages = %ld (0x%lx)\n",
+                  pgdatp->node_spanned_pages, pgdatp->node_spanned_pages);
+       kdb_printf("  kswapd = 0x%p\n", pgdatp->kswapd);
+
+       return err;
+}
+
+/*
+ * 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)
+{
+       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 *g, *tp;
+               struct vm_area_struct *vp;
+               pid_t pid;
+
+               if ((diag = kdbgetularg(argv[argc], (unsigned long *) &pid)))
+                       return diag;
+
+               kdb_do_each_thread(g, 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_while_each_thread(g, tp);
+
+               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))
+                   || (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)) {
+#ifdef pte_exec
+               if (pte_exec(*pte))
+                       kdb_printf("X");
+#endif
+               if (pte_write(*pte))
+                       kdb_printf("W");
+#ifdef pte_read
+               if (pte_read(*pte))
+                       kdb_printf("R");
+#endif
+               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%ulx", 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 (<address> through <address>
+ *     plus <nbytes>) for the given process. The default value for nbytes is
+ *     one.
+ *
+ *     pte -m <mm> <address> [<nbytes>]    Print all pte_t structures for
+ *                                        virtual <address> in address space
+ *                                        of <mm> which is a pointer to a
+ *                                        mm_struct
+ *     pte -p <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)
+{
+       unsigned long addr;
+       long offset = 0;
+       int nextarg;
+       unsigned long nbytes = 1;
+       long npgs;
+       int diag;
+       int found;
+       pid_t pid;
+       struct task_struct *tp;
+       struct mm_struct *mm, copy_of_mm;
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+
+       if (argc < 3 || argc > 4) {
+               return KDB_ARGCOUNT;
+       }
+
+        if (strcmp(argv[1], "-p") == 0) {
+               if ((diag = kdbgetularg(argv[2], (unsigned long *) &pid))) {
+                       return diag;
+               }
+
+               found = 0;
+               for_each_process(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;
+               }
+               mm = tp->mm;
+       } else if (strcmp(argv[1], "-m") == 0) {
+
+
+               nextarg = 2;
+               if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset,
+                                         NULL))
+                   || (diag = kdb_getarea(copy_of_mm, addr)))
+                       return (diag);
+               mm = &copy_of_mm;
+       } else {
+               return KDB_ARGCOUNT;
+       }
+
+       if ((diag = kdbgetularg(argv[3], &addr))) {
+               return diag;
+       }
+
+       if (argc == 4) {
+               if ((diag = kdbgetularg(argv[4], &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(mm, addr);
+               if (pgd_present(*pgd)) {
+                       pud = pud_offset(pgd, addr);
+                       if (pud_present(*pud)) {
+                               pmd = pmd_offset(pud, addr);
+                               if (pmd_present(*pmd)) {
+                                       pte = pte_offset_map(pmd, addr);
+                                       if (pte_present(*pte)) {
+                                               kdbm_print_pte(pte);
+                                       }
+                               }
+                       }
+               }
+
+               kdb_printf("\n");
+               addr += PAGE_SIZE;
+       }
+
+       return 0;
+}
+
+/*
+ * kdbm_rpte
+ *
+ *     This function implements the 'rpte' command.  Print all pte_t structures
+ *     that contain the given physical page range (<pfn> through <pfn>
+ *     plus <npages>) for the given process. The default value for npages is
+ *     one.
+ *
+ *     rpte -m <mm> <pfn> [<npages>]      Print all pte_t structures for
+ *                                        physical page <pfn> in address space
+ *                                        of <mm> which is a pointer to a
+ *                                        mm_struct
+ *     rpte -p <pid> <pfn> [<npages>]     Print all pte_t structures for
+ *                                        physical page <pfn> in address space
+ *                                        of <pid>
+ */
+
+static int
+kdbm_rpte(int argc, const char **argv)
+{
+       unsigned long addr;
+       unsigned long pfn;
+       long offset = 0;
+       int nextarg;
+       unsigned long npages = 1;
+       int diag;
+       int found;
+       pid_t pid;
+       struct task_struct *tp;
+       struct mm_struct *mm, copy_of_mm;
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       unsigned long g, u, m, t;
+
+       if (argc < 3 || argc > 4) {
+               return KDB_ARGCOUNT;
+       }
+
+        if (strcmp(argv[1], "-p") == 0) {
+               if ((diag = kdbgetularg(argv[2], (unsigned long *) &pid))) {
+                       return diag;
+               }
+
+               found = 0;
+               for_each_process(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;
+               }
+               mm = tp->mm;
+       } else if (strcmp(argv[1], "-m") == 0) {
+
+
+               nextarg = 2;
+               if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset,
+                                         NULL))
+                   || (diag = kdb_getarea(copy_of_mm, addr)))
+                       return (diag);
+               mm = &copy_of_mm;
+       } else {
+               return KDB_ARGCOUNT;
+       }
+
+       if ((diag = kdbgetularg(argv[3], &pfn))) {
+               return diag;
+       }
+
+       if (argc == 4) {
+               if ((diag = kdbgetularg(argv[4], &npages))) {
+                       return diag;
+               }
+       }
+
+       /* spaces after vaddr depends on sizeof(unsigned long) */
+       kdb_printf("pfn              vaddr%*s pte\n",
+                  (int)(2*sizeof(unsigned long) + 2 - 5), " ");
+
+       for (g = 0, pgd = pgd_offset(mm, 0UL); g < PTRS_PER_PGD; ++g, ++pgd) {
+               if (pgd_none(*pgd) || pgd_bad(*pgd))
+                       continue;
+               for (u = 0, pud = pud_offset(pgd, 0UL); u < PTRS_PER_PUD; ++u, ++pud) {
+                       if (pud_none(*pud) || pud_bad(*pud))
+                               continue;
+                       for (m = 0, pmd = pmd_offset(pud, 0UL); m < PTRS_PER_PMD; ++m, ++pmd) {
+                               if (pmd_none(*pmd) || pmd_bad(*pmd))
+                                       continue;
+                               for (t = 0, pte = pte_offset_map(pmd, 0UL); t < PTRS_PER_PTE; ++t, ++pte) {
+                                       if (pte_none(*pte))
+                                               continue;
+                                       if (pte_pfn(*pte) < pfn || pte_pfn(*pte) >= (pfn + npages))
+                                               continue;
+                                       addr = g << PGDIR_SHIFT;
+#ifdef __ia64__
+                                       /* IA64 plays tricks with the pgd mapping to save space.
+                                        * This reverses pgd_index().
+                                        */
+                                       {
+                                               unsigned long region = g >> (PAGE_SHIFT - 6);
+                                               unsigned long l1index = g - (region << (PAGE_SHIFT - 6));
+                                               addr = (region << 61) + (l1index << PGDIR_SHIFT);
+                                       }
+#endif
+                                       addr += (m << PMD_SHIFT) + (t << PAGE_SHIFT);
+                                       kdb_printf("0x%-14lx " kdb_bfd_vma_fmt0 " ",
+                                                  pte_pfn(*pte), addr);
+                                       kdbm_print_pte(pte);
+                                       kdb_printf("\n");
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int
+kdbm_print_dentry(unsigned long daddr)
+{
+       struct dentry d;
+       int diag;
+       char buf[256];
+
+       kdb_printf("Dentry at 0x%lx\n", daddr);
+       if ((diag = kdb_getarea(d, (unsigned long)daddr)))
+               return diag;
+
+       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.pprev);
+
+       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_u.d_child.next, d.d_u.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 d_fsdata = 0x%p\n",
+                                       d.d_op, d.d_sb, d.d_fsdata);
+
+       kdb_printf(" d_iname = %s\n",
+                                       d.d_iname);
+
+       if (d.d_inode) {
+               struct inode i;
+               kdb_printf("\nInode Entry at 0x%p\n", d.d_inode);
+               if ((diag = kdb_getarea(i, (unsigned long)d.d_inode)))
+                       return diag;
+               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\n",
+                                               i.i_ino, atomic_read(&i.i_count));
+
+               kdb_printf(" i_hash.nxt = 0x%p i_hash.prv = 0x%p\n",
+                                               i.i_hash.next, i.i_hash.pprev);
+
+               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);
+
+       }
+       kdb_printf("\n");
+       return 0;
+}
+
+static int
+kdbm_filp(int argc, const char **argv)
+{
+       struct file   f;
+       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)) ||
+           (diag = kdb_getarea(f, addr)))
+               return diag;
+
+       kdb_printf("File Pointer at 0x%lx\n", addr);
+
+       kdb_printf(" fu_list.nxt = 0x%p fu_list.prv = 0x%p\n",
+                                       f.f_u.fu_list.next, f.f_u.fu_list.prev);
+
+       kdb_printf(" f_dentry = 0x%p f_vfsmnt = 0x%p f_op = 0x%p\n",
+                                       f.f_dentry, f.f_vfsmnt, f.f_op);
+
+       kdb_printf(" f_count = %lld f_flags = 0x%x f_mode = 0x%x\n",
+                                       atomic_read(&f.f_count), f.f_flags, f.f_mode);
+
+       kdb_printf(" f_pos = %Ld\n", f.f_pos);
+#ifdef CONFIG_SECURITY
+       kdb_printf(" security = 0x%p\n", f.f_security);
+#endif
+
+       kdb_printf(" private_data = 0x%p f_mapping = 0x%p\n\n",
+                                       f.private_data, f.f_mapping);
+
+       return kdbm_print_dentry((unsigned long)f.f_dentry);
+}
+
+static int
+kdbm_fl(int argc, const char **argv)
+{
+       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)) ||
+               (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(" file_lock_operations");
+       if (fl.fl_ops)
+               kdb_printf("\n   fl_copy_lock = 0x%p fl_release_private = 0x%p\n",
+                       fl.fl_ops->fl_copy_lock, fl.fl_ops->fl_release_private);
+       else
+               kdb_printf("   empty\n");
+
+       kdb_printf(" lock_manager_operations");
+       if (fl.fl_lmops)
+               kdb_printf("\n   fl_compare_owner = 0x%p fl_notify = 0x%p\n",
+                       fl.fl_lmops->fl_compare_owner, fl.fl_lmops->fl_notify);
+       else
+               kdb_printf("   empty\n");
+
+       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)
+{
+       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)))
+               return diag;
+
+       return kdbm_print_dentry(addr);
+}
+
+static int
+kdbm_kobject(int argc, const char **argv)
+{
+       struct kobject k;
+       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)) ||
+           (diag = kdb_getarea(k, addr)))
+               return diag;
+
+
+       kdb_printf("kobject at 0x%lx\n", addr);
+
+       if (k.name) {
+               char c;
+               kdb_printf(" name 0x%p", k.name);
+               if (kdb_getarea(c, (unsigned long)k.name) == 0)
+                       kdb_printf(" '%s'", k.name);
+               kdb_printf("\n");
+       }
+
+       if (k.name != kobject_name((struct kobject *)addr))
+               kdb_printf(" name '%.20s'\n", k.name);
+
+       kdb_printf(" kref.refcount %d'\n", atomic_read(&k.kref.refcount));
+
+       kdb_printf(" entry.next = 0x%p entry.prev = 0x%p\n",
+                                       k.entry.next, k.entry.prev);
+
+       kdb_printf(" parent = 0x%p kset = 0x%p ktype = 0x%p sd = 0x%p\n",
+                                       k.parent, k.kset, k.ktype, k.sd);
+
+       return 0;
+}
+
+static int
+kdbm_sh(int argc, const char **argv)
+{
+       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)) ||
+           (diag = kdb_getarea(sh, addr)))
+               return diag;
+
+       kdb_printf("Scsi_Host at 0x%lx\n", addr);
+       kdb_printf("host_queue = 0x%p\n", sh.__devices.next);
+       kdb_printf("ehandler = 0x%p eh_action = 0x%p\n",
+                  sh.ehandler, sh.eh_action);
+       kdb_printf("host_wait = 0x%p hostt = 0x%p\n",
+                  &sh.host_wait, sh.hostt);
+       kdb_printf("host_failed = %d  host_no = %d resetting = %d\n",
+                  sh.host_failed, 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)
+{
+       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)))
+               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->siblings.next, sd->siblings.prev, sd->host);
+       kdb_printf("device_busy = %d   current_cmnd 0x%p\n",
+                  sd->device_busy, sd->current_cmnd);
+       kdb_printf("id/lun/chan = [%d/%d/%d]  single_lun = %d  device_blocked = %d\n",
+                  sd->id, sd->lun, sd->channel, sd->sdev_target->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 int
+kdbm_sc(int argc, const char **argv)
+{
+       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)))
+               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("device = 0x%p  next = 0x%p\n",
+                  sc->device, sc->list.next);
+       kdb_printf("serial_number = %ld  retries = %d\n",
+                  sc->serial_number, sc->retries);
+       kdb_printf("cmd_len = %d\n", sc->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("request_buffer = 0x%p  request_bufflen = %d\n",
+                  scsi_sglist(sc), scsi_bufflen(sc));
+       kdb_printf("use_sg = %d\n", scsi_sg_count(sc));
+       kdb_printf("underflow = %d transfersize = %d\n",
+                  sc->underflow, sc->transfersize);
+       kdb_printf("tag = %d\n", sc->tag);
+
+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);
+#ifdef CONFIG_NUMA
+       kdb_register("mempolicy", kdbm_mpol, "<vaddr>", "Display mempolicy structure", 0);
+       kdb_register("pgdat", kdbm_pgdat, "<node_id>", "Display pglist_data node structure", 0);
+#else
+       kdb_register("pgdat", kdbm_pgdat, "", "Display pglist_data node structure", 0);
+#endif
+       kdb_register("pte", kdbm_pte, "( -m <mm> | -p <pid> ) <vaddr> [<nbytes>]", "Display pte_t for mm_struct or pid", 0);
+       kdb_register("rpte", kdbm_rpte, "( -m <mm> | -p <pid> ) <pfn> [<npages>]", "Find pte_t containing pfn for mm_struct or pid", 0);
+       kdb_register("dentry", kdbm_dentry, "<dentry>", "Display interesting dentry stuff", 0);
+       kdb_register("kobject", kdbm_kobject, "<kobject>", "Display interesting kobject stuff", 0);
+       kdb_register("filp", kdbm_filp, "<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");
+#ifdef CONFIG_NUMA
+       kdb_unregister("mempolicy");
+#endif
+       kdb_unregister("pgdat");
+       kdb_unregister("pte");
+       kdb_unregister("rpte");
+       kdb_unregister("dentry");
+       kdb_unregister("kobject");
+       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 --git a/kdb/modules/kdbm_x86.c b/kdb/modules/kdbm_x86.c
new file mode 100644 (file)
index 0000000..1080a25
--- /dev/null
@@ -0,0 +1,1093 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Author: Vamsi Krishna S. <vamsi_krishna@in.ibm.com>
+ * (C) 2003 IBM Corporation.
+ * 2006-10-10 Keith Owens
+ *   Reworked to include x86_64 support
+ * Copyright (c) 2006 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/interrupt.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 <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/desc.h>
+#include <asm/debugreg.h>
+#if 0
+#include <asm/pgtable.h>
+#endif
+
+MODULE_AUTHOR("Vamsi Krishna S./IBM");
+MODULE_DESCRIPTION("x86 specific information (gdt/idt/ldt/page tables)");
+MODULE_LICENSE("GPL");
+
+/* Isolate as many of the i386/x86_64 differences as possible in one spot */
+
+#ifdef CONFIG_X86_64
+
+#define KDB_X86_64 1
+#define        MOVLQ "movq"
+
+typedef struct desc_struct kdb_desc_t;
+typedef struct gate_struct64 kdb_gate_desc_t;
+
+#define KDB_SYS_DESC_OFFSET(d) ((unsigned long)d->offset_high << 32 | d->offset_middle << 16 | d->offset_low)
+#define KDB_SYS_DESC_CALLG_COUNT(d) 0
+
+#else  /* !CONFIG_X86_64 */
+
+#define KDB_X86_64 0
+#define        MOVLQ "movl"
+
+/* i386 has no detailed mapping for the 8 byte segment descriptor, copy the
+ * x86_64 one and merge the l and avl bits.
+ */
+struct kdb_desc {
+       u16 limit0;
+       u16 base0;
+       unsigned base1 : 8, type : 4, s : 1, dpl : 2, p : 1;
+       unsigned limit : 4, avl : 2, d : 1, g : 1, base2 : 8;
+} __attribute__((packed));
+typedef struct kdb_desc kdb_desc_t;
+
+/* i386 has no detailed mapping for the 8 byte gate descriptor, base it on the
+ * x86_64 one.
+ */
+struct kdb_gate_desc {
+       u16 offset_low;
+       u16 segment;
+       unsigned res : 8, type : 4, s : 1, dpl : 2, p : 1;
+       u16 offset_middle;
+} __attribute__((packed));
+typedef struct kdb_gate_desc kdb_gate_desc_t;
+
+#define KDB_SYS_DESC_OFFSET(d) ((unsigned long)(d->offset_middle << 16 | d->offset_low))
+#define KDB_SYS_DESC_CALLG_COUNT(d) ((unsigned int)(d->res & 0x0F))
+
+#endif /* CONFIG_X86_64 */
+
+#define KDB_SEL_MAX                    0x2000
+#define KDB_IDT_MAX                    0x100
+#define KDB_SYS_DESC_TYPE_TSS16                0x01
+#define KDB_SYS_DESC_TYPE_LDT          0x02
+#define KDB_SYS_DESC_TYPE_TSSB16       0x03
+#define KDB_SYS_DESC_TYPE_CALLG16      0x04
+#define KDB_SYS_DESC_TYPE_TASKG                0x05
+#define KDB_SYS_DESC_TYPE_INTG16       0x06
+#define KDB_SYS_DESC_TYPE_TRAP16       0x07
+
+#define KDB_SYS_DESC_TYPE_TSS          0x09
+#define KDB_SYS_DESC_TYPE_TSSB         0x0b
+#define KDB_SYS_DESC_TYPE_CALLG                0x0c
+#define KDB_SYS_DESC_TYPE_INTG         0x0e
+#define KDB_SYS_DESC_TYPE_TRAPG                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 _LIMIT(d) ((unsigned long)((d)->limit << 16 | (d)->limit0))
+#define KDB_SEG_DESC_LIMIT(d) ((d)->g ? ((_LIMIT(d)+1) << 12) -1 : _LIMIT(d))
+
+static unsigned long kdb_seg_desc_base(kdb_desc_t *d)
+{
+       unsigned long base = d->base2 << 24 | d->base1 << 16 | d->base0;
+#ifdef CONFIG_X86_64
+       switch (d->type) {
+       case KDB_SYS_DESC_TYPE_TSS:
+       case KDB_SYS_DESC_TYPE_TSSB:
+       case KDB_SYS_DESC_TYPE_LDT:
+               base += (unsigned long)(((struct ldttss_desc64 *)d)->base3) << 32;
+               break;
+       }
+#endif
+       return base;
+}
+
+/* helper functions to display system registers in verbose mode */
+static void display_gdtr(void)
+{
+       struct desc_ptr gdtr;
+
+       __asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+       kdb_printf("gdtr.address = " kdb_machreg_fmt0 ", gdtr.size = 0x%x\n",
+                  gdtr.address, gdtr.size);
+
+       return;
+}
+
+static void display_ldtr(void)
+{
+       struct desc_ptr gdtr;
+       unsigned long ldtr;
+
+       __asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+       __asm__ __volatile__ ("sldt %0\n\t" : "=m"(ldtr));
+       ldtr &= 0xfff8;         /* extract the index */
+
+       kdb_printf("ldtr = " kdb_machreg_fmt0 " ", ldtr);
+
+       if (ldtr < gdtr.size) {
+               kdb_desc_t *ldt_desc =
+                       (kdb_desc_t *)(gdtr.address + ldtr);
+               kdb_printf("base=" kdb_machreg_fmt0
+                          ", limit=" kdb_machreg_fmt "\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 desc_ptr idtr;
+       __asm__ __volatile__ ("sidt %0\n\t" : "=m"(idtr));
+       kdb_printf("idtr.address = " kdb_machreg_fmt0 ", idtr.size = 0x%x\n",
+                  idtr.address, idtr.size);
+       return;
+}
+
+static const 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__ (MOVLQ " %%cr0,%0\n\t":"=r"(cr0));
+       kdb_printf("cr0 = " kdb_machreg_fmt0, cr0);
+       for (i = 0; i < ARRAY_SIZE(cr0_flags); 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__ (MOVLQ " %%cr3,%0\n\t":"=r"(cr3));
+       kdb_printf("cr3 = " kdb_machreg_fmt0 " ", cr3);
+       if (cr3 & 0x08)
+               kdb_printf("pwt ");
+       if (cr3 & 0x10)
+               kdb_printf("pcd ");
+       kdb_printf("%s=" kdb_machreg_fmt0 "\n",
+                  KDB_X86_64 ? "pml4" : "pgdir", cr3 & PAGE_MASK);
+       return;
+}
+
+static const char *cr4_flags[] = {
+       "vme", "pvi", "tsd", "de",
+       "pse", "pae", "mce", "pge",
+       "pce", "osfxsr" "osxmmexcpt"};
+
+static void display_cr4(void)
+{
+       kdb_machreg_t cr4;
+       int i;
+       __asm__ (MOVLQ " %%cr4,%0\n\t":"=r"(cr4));
+       kdb_printf("cr4 = " kdb_machreg_fmt0, cr4);
+       for (i = 0; i < ARRAY_SIZE(cr4_flags); i++) {
+               if (test_bit(i, &cr4))
+                       kdb_printf(" %s", cr4_flags[i]);
+       }
+       kdb_printf("\n");
+       return;
+}
+
+static void display_cr8(void)
+{
+#ifdef CONFIG_X86_64
+       kdb_machreg_t cr8;
+       __asm__ (MOVLQ " %%cr8,%0\n\t":"=r"(cr8));
+       kdb_printf("cr8 = " kdb_machreg_fmt0 "\n", cr8);
+       return;
+#endif /* CONFIG_X86_64 */
+}
+
+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("    debug 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__ (MOVLQ " %%db0,%0\n\t":"=r"(dr0));
+       __asm__ (MOVLQ " %%db1,%0\n\t":"=r"(dr1));
+       __asm__ (MOVLQ " %%db2,%0\n\t":"=r"(dr2));
+       __asm__ (MOVLQ " %%db3,%0\n\t":"=r"(dr3));
+       __asm__ (MOVLQ " %%db6,%0\n\t":"=r"(dr6));
+       __asm__ (MOVLQ " %%db7,%0\n\t":"=r"(dr7));
+
+       kdb_printf("dr0 = " kdb_machreg_fmt0 " dr1 = " kdb_machreg_fmt0
+                  " dr2 = " kdb_machreg_fmt0 " dr3 = " kdb_machreg_fmt0 "\n",
+                  dr0, dr1, dr2, dr3);
+       kdb_printf("dr6 = " kdb_machreg_fmt0 " ", 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 = " kdb_machreg_fmt0 "\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"};
+
+static void display_eflags(unsigned long ef)
+{
+       int i, iopl;
+       kdb_printf("eflags = " kdb_machreg_fmt0 " ", ef);
+       for (i = 0; i < ARRAY_SIZE(set_eflags); i++) {
+               if (test_bit(i, &ef) && set_eflags[i])
+                       kdb_printf("%s ", set_eflags[i]);
+       }
+
+       iopl = (ef & 0x00003000) >> 12;
+       kdb_printf("iopl=%d\n", iopl);
+       return;
+}
+
+static void display_tss(struct tss_struct *t)
+{
+#ifdef CONFIG_X86_64
+       int i;
+       kdb_printf("    sp0 = 0x%016Lx,  sp1 = 0x%016Lx\n",
+                  t->x86_tss.sp0, t->x86_tss.sp1);
+       kdb_printf("    sp2 = 0x%016Lx\n", t->x86_tss.sp2);
+       for (i = 0; i < ARRAY_SIZE(t->x86_tss.ist); ++i)
+               kdb_printf("    ist[%d] = 0x%016Lx\n",
+                         i, t->x86_tss.ist[i]);
+       kdb_printf("   iomap = 0x%04x\n", t->x86_tss.io_bitmap_base);
+#else  /* !CONFIG_X86_64 */
+       kdb_printf("    cs = %04x,  ip = " kdb_machreg_fmt0 "\n",
+                  t->x86_tss.es, t->x86_tss.ip);
+       kdb_printf("    ss = %04x,  sp = " kdb_machreg_fmt0 "\n",
+                  t->x86_tss.ss, t->x86_tss.sp);
+       kdb_printf("   ss0 = %04x, sp0 = " kdb_machreg_fmt0 "\n",
+                  t->x86_tss.ss0, t->x86_tss.sp0);
+       kdb_printf("   ss1 = %04x, sp1 = " kdb_machreg_fmt0 "\n",
+                  t->x86_tss.ss1, t->x86_tss.sp1);
+       kdb_printf("   ss2 = %04x, sp2 = " kdb_machreg_fmt0 "\n",
+                  t->x86_tss.ss2, t->x86_tss.sp2);
+       kdb_printf("   ldt = %04x, cr3 = " kdb_machreg_fmt0 "\n",
+                  t->x86_tss.ldt, t->x86_tss.__cr3);
+       kdb_printf("    ds = %04x, es = %04x fs = %04x gs = %04x\n",
+                       t->x86_tss.ds, t->x86_tss.es, t->x86_tss.fs, t->x86_tss.gs);
+       kdb_printf("   ax = " kdb_machreg_fmt0 ", bx = " kdb_machreg_fmt0
+                  " cx = " kdb_machreg_fmt0 " dx = " kdb_machreg_fmt0 "\n",
+                  t->x86_tss.ax, t->x86_tss.bx, t->x86_tss.cx, t->x86_tss.dx);
+       kdb_printf("   si = " kdb_machreg_fmt0 ", di = " kdb_machreg_fmt0
+                  " bp = " kdb_machreg_fmt0 "\n",
+                  t->x86_tss.si, t->x86_tss.di, t->x86_tss.bp);
+       kdb_printf("   trace = %d, iomap = 0x%04x\n", t->x86_tss.trace, t->x86_tss.io_bitmap_base);
+#endif /* CONFIG_X86_64 */
+}
+
+static char *gate_desc_types[] = {
+#ifdef CONFIG_X86_64
+       "reserved-0", "reserved-1", "ldt", "reserved-3",
+       "reserved-4", "reserved-5", "reserved-6", "reserved-7",
+       "reserved-8", "tss-avlb", "reserved-10", "tss-busy",
+       "callgate", "reserved-13", "intgate", "trapgate",
+#else  /* CONFIG_X86_64 */
+       "reserved-0", "tss16-avlb", "ldt", "tss16-busy",
+       "callgate16", "taskgate", "intgate16", "trapgate16",
+       "reserved-8", "tss-avlb", "reserved-10", "tss-busy",
+       "callgate", "reserved-13", "intgate", "trapgate",
+#endif /* CONFIG_X86_64 */
+};
+
+static void
+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=");
+               kdb_symbol_print(kdb_seg_desc_base((kdb_desc_t *)d), NULL,
+                                KDB_SP_DEFAULT);
+               kdb_printf(" limit=" kdb_machreg_fmt " dpl=%d\n",
+                          KDB_SEG_DESC_LIMIT((kdb_desc_t *)d), d->dpl);
+               break;
+       case KDB_SYS_DESC_TYPE_TSS:
+       case KDB_SYS_DESC_TYPE_TSS16:
+       case KDB_SYS_DESC_TYPE_TSSB:
+       case KDB_SYS_DESC_TYPE_TSSB16:
+       {
+               struct tss_struct *tss =
+                       (struct tss_struct *)
+                       kdb_seg_desc_base((kdb_desc_t *)d);
+               kdb_printf("base=");
+               kdb_symbol_print((unsigned long)tss, NULL, KDB_SP_DEFAULT);
+               kdb_printf(" limit=" kdb_machreg_fmt " dpl=%d\n",
+                          KDB_SEG_DESC_LIMIT((kdb_desc_t *)d), d->dpl);
+               display_tss(tss);
+               break;
+       }
+       case KDB_SYS_DESC_TYPE_CALLG16:
+               kdb_printf("segment=0x%4.4x off=", d->segment);
+               kdb_symbol_print(KDB_SYS_DESC_OFFSET(d), NULL, KDB_SP_DEFAULT);
+               kdb_printf(" dpl=%d wc=%d\n",
+                          d->dpl, KDB_SYS_DESC_CALLG_COUNT(d));
+               break;
+       case KDB_SYS_DESC_TYPE_CALLG:
+               kdb_printf("segment=0x%4.4x off=", d->segment);
+               kdb_symbol_print(KDB_SYS_DESC_OFFSET(d), NULL, KDB_SP_DEFAULT);
+               kdb_printf(" dpl=%d\n", d->dpl);
+               break;
+       default:
+               kdb_printf("segment=0x%4.4x off=", d->segment);
+               if (KDB_SYS_DESC_OFFSET(d))
+                       kdb_symbol_print(KDB_SYS_DESC_OFFSET(d), NULL,
+                                        KDB_SP_DEFAULT);
+               else
+                       kdb_printf(kdb_machreg_fmt0, KDB_SYS_DESC_OFFSET(d));
+               kdb_printf(" dpl=%d", d->dpl);
+#ifdef CONFIG_X86_64
+               if (d->ist)
+                       kdb_printf(" ist=%d", d->ist);
+#endif /* CONFIG_X86_64 */
+               kdb_printf("\n");
+               break;
+       }
+}
+
+static void
+display_seg_desc(kdb_desc_t *d)
+{
+       unsigned char type = d->type;
+
+       if (type & KDB_SEG_DESC_TYPE_CODE) {
+               kdb_printf("%-11s base=" kdb_machreg_fmt0 " limit="
+                          kdb_machreg_fmt " 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',
+#ifdef CONFIG_X86_64
+                          d->l ? "64b" : d->d ? "32b" : "16b",
+#else  /* !CONFIG_X86_64 */
+                          d->d ? "32b" : "16b",
+#endif /* CONFIG_X86_64 */
+                          (type & KDB_SEG_DESC_TYPE_A)?"ac":"",
+                          (type & KDB_SEG_DESC_TYPE_CODE_C)?"conf":"");
+       } else {
+               kdb_printf("%-11s base=" kdb_machreg_fmt0 " limit="
+                          kdb_machreg_fmt " 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->d ? "32b" : "16b",
+                          (type & KDB_SEG_DESC_TYPE_A)?"ac":"",
+                          (type & KDB_SEG_DESC_TYPE_DATA_D)?"down":"");
+       }
+}
+
+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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+static int
+kdb_gdt(int argc, const char **argv)
+{
+       int sel = 0;
+       struct desc_ptr 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) {
+               kdb_printf("Maximum selector (%d) reached\n", max_sel);
+               return 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->p) {
+                       kdb_printf("not present\n");
+                       continue;
+               }
+               if (d->s) {
+                       display_seg_desc(d);
+               } else {
+                       display_gate_desc((kdb_gate_desc_t *)d);
+                       if (KDB_X86_64 && count) {
+                               ++sel;  /* this descriptor occupies two slots */
+                               --count;
+                       }
+               }
+       }
+
+       last_sel = sel;
+       return 0;
+}
+
+/*
+ * kdb_ldt
+ *
+ *     This function implements the 'ldt' command.
+ *
+ *     ldt [<selector> [<line count>]]
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+static int
+kdb_ldt(int argc, const char **argv)
+{
+       int sel = 0;
+       struct desc_ptr 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.ldt) {
+                       kdb_printf("no special LDT for this process\n");
+                       return 0;
+               }
+               ldt = kdb_current_task->mm->context.ldt;
+               max_sel = kdb_current_task->mm->context.size;
+       } 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));
+               ldtr &= 0xfff8;         /* extract the index */
+
+               if (ldtr > gdtr.size+1) {
+                       kdb_printf("invalid ldtr\n");
+                       return 0;
+               }
+
+               ldt_desc = (kdb_desc_t *)(gdtr.address + ldtr);
+               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) {
+               kdb_printf("Maximum selector (%d) reached\n", max_sel);
+               return 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->p) {
+                       kdb_printf("not present\n");
+                       continue;
+               }
+               if (d->s) {
+                       display_seg_desc(d);
+               } else {
+                       display_gate_desc((kdb_gate_desc_t *)d);
+                       if (KDB_X86_64 && count) {
+                               ++sel;  /* this descriptor occupies two slots */
+                               --count;
+                       }
+               }
+       }
+
+       last_sel = sel;
+       return 0;
+}
+
+/*
+ * kdb_idt
+ *
+ *     This function implements the 'idt' command.
+ *
+ *     idt [<vector> [<line count>]]
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+static int
+kdb_idt(int argc, const char **argv)
+{
+       int vec = 0;
+       struct desc_ptr 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) {
+               kdb_printf("Maximum vector (%d) reached\n", max_entries);
+               return 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->p) {
+                       kdb_printf("not present\n");
+                       continue;
+               }
+#ifndef        CONFIG_X86_64
+               if (d->s) {
+                       kdb_printf("invalid\n");
+                       continue;
+               }
+#endif /* CONFIG_X86_64 */
+               display_gate_desc(d);
+       }
+
+       last_vec = vec;
+
+       return 0;
+}
+
+#if 0
+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;
+}
+#endif
+
+#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":"  ");
+#if 0
+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;
+}
+#endif
+
+#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
+
+#if 0
+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
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+static int
+kdb_pte(int argc, const char **argv)
+{
+       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);
+               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;
+}
+#else
+/*
+ * Todo - In 2.5 the pte_offset macro in asm/pgtable.h seems to be
+ * renamed to pte_offset_kernel.
+ */
+static int
+kdb_pte(int argc, const char **argv)
+{
+       kdb_printf("not supported.");
+       return KDB_NOTIMP;
+}
+#endif
+
+/*
+ * 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
+ * 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)
+{
+       struct pt_regs *regs = get_irq_regs();
+       kdba_dumpregs(regs, NULL, NULL);
+       kdb_printf("\n");
+       display_eflags(regs->flags);
+       kdb_printf("\n");
+       display_gdtr();
+       display_idtr();
+       display_ldtr();
+       kdb_printf("\n");
+       display_cr0();
+       display_cr3();
+       display_cr4();
+       display_cr8();
+       kdb_printf("\n");
+       display_dr();
+       return 0;
+}
+
+static int
+kdb_rdmsr(int argc, const char **argv)
+{
+       unsigned long addr;
+       uint32_t l, h;
+       int diag;
+       struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
+
+       if (argc != 1)
+               return KDB_ARGCOUNT;
+
+       if ((diag = kdbgetularg(argv[1], &addr)))
+               return diag;
+
+       if (!cpu_has(c, X86_FEATURE_MSR))
+               return KDB_NOTIMP;
+
+       kdb_printf("msr(0x%lx) = ", addr);
+       if ((diag = rdmsr_safe(addr, &l, &h))) {
+               kdb_printf("error %d\n", diag);
+               return KDB_BADINT;
+       } else {
+               kdb_printf("0x%08x_%08x\n", h, l);
+       }
+
+       return 0;
+}
+
+static int
+kdb_wrmsr(int argc, const char **argv)
+{
+       unsigned long addr;
+       unsigned long l, h;
+       int diag;
+       struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
+
+       if (argc != 3)
+               return KDB_ARGCOUNT;
+
+       if ((diag = kdbgetularg(argv[1], &addr))
+                       || (diag = kdbgetularg(argv[2], &h))
+                       || (diag = kdbgetularg(argv[3], &l)))
+               return diag;
+
+       if (!cpu_has(c, X86_FEATURE_MSR))
+               return KDB_NOTIMP;
+
+       if ((diag = wrmsr_safe(addr, l, h))) {
+               kdb_printf("error %d\n", diag);
+               return KDB_BADINT;
+       }
+
+       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);
+       kdb_register("rdmsr", kdb_rdmsr, "<maddr>", "Display Model Specific Register", 0);
+       kdb_register("wrmsr", kdb_wrmsr, "<maddr> <h> <l>", "Modify Model Specific Register", 0);
+       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");
+       kdb_unregister("rdmsr");
+       kdb_unregister("wrmsr");
+}
+
+module_init(kdbm_x86_init)
+module_exit(kdbm_x86_exit)
diff --git a/kdb/modules/lcrash/README b/kdb/modules/lcrash/README
new file mode 100644 (file)
index 0000000..53f9181
--- /dev/null
@@ -0,0 +1,3 @@
+
+ These files are copied from lcrash.
+  The only changes are flagged with "cpw".
diff --git a/kdb/modules/lcrash/asm/README b/kdb/modules/lcrash/asm/README
new file mode 100644 (file)
index 0000000..7b9ef97
--- /dev/null
@@ -0,0 +1 @@
+This kl_types.h is asm-ia64 version.
diff --git a/kdb/modules/lcrash/asm/kl_dump_ia64.h b/kdb/modules/lcrash/asm/kl_dump_ia64.h
new file mode 100644 (file)
index 0000000..5c3f8d8
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * $Id: kl_dump_ia64.h 1151 2005-02-23 01:09:12Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+/* This header file holds the architecture specific crash dump header */
+#ifndef __KL_DUMP_IA64_H
+#define __KL_DUMP_IA64_H
+
+/* definitions */
+#ifndef KL_NR_CPUS
+# define KL_NR_CPUS  128    /* max number CPUs */
+#endif
+
+#define KL_DUMP_MAGIC_NUMBER_IA64   0xdeaddeadULL  /* magic number            */
+#define KL_DUMP_VERSION_NUMBER_IA64 0x4            /* version number          */
+
+
+/*
+ * mkswap.c calls getpagesize() to get the system page size,
+ * which is not  necessarily the same as the hardware page size.
+ *
+ * For ia64 the kernel PAGE_SIZE can be configured from 4KB ... 16KB.
+ *
+ * The physical memory is layed out out in the hardware/minimal pages.
+ * This is the size we need to use for dumping physical pages.
+ *
+ * Note ths hardware/minimal page size being use in;
+ *      arch/ia64/kernel/efi.c`efi_memmap_walk():
+ *         curr.end   = curr.start + (md->num_pages << 12);
+ *
+ * Since the system page size could change between the kernel we boot
+ * on the the kernel that cause the core dume we may want to have something
+ * more constant like the maximum system page size (See include/asm-ia64/page.h).
+ */
+#define DUMP_MIN_PAGE_SHIFT                    12
+#define DUMP_MIN_PAGE_SIZE                     (1UL << DUMP_MIN_PAGE_SHIFT)
+#define DUMP_MIN_PAGE_MASK                     (~(DUMP_MIN_PAGE_SIZE - 1))
+#define DUMP_MIN_PAGE_ALIGN(addr)              (((addr) + DUMP_MIN_PAGE_SIZE - 1) & DUMP_MIN_PAGE_MASK)
+
+#define DUMP_MAX_PAGE_SHIFT                    16
+#define DUMP_MAX_PAGE_SIZE                     (1UL << DUMP_MAX_PAGE_SHIFT)
+#define DUMP_MAX_PAGE_MASK                     (~(DUMP_MAX_PAGE_SIZE - 1))
+#define DUMP_MAX_PAGE_ALIGN(addr)              (((addr) + DUMP_MAX_PAGE_SIZE - 1) & DUMP_MAX_PAGE_MASK)
+
+#define DUMP_HEADER_OFFSET                     DUMP_MAX_PAGE_SIZE
+
+#define DUMP_EF_PAGE_SHIFT                     DUMP_MIN_PAGE_SHIFT
+
+#define DUMP_PAGE_SHIFT                                DUMP_MIN_PAGE_SHIFT
+#define DUMP_PAGE_SIZE                         DUMP_MIN_PAGE_SIZE
+#define DUMP_PAGE_MASK                         DUMP_MIN_PAGE_MASK
+#define DUMP_PAGE_ALIGN(addr)                  DUMP_MIN_PAGE_ALIGN(addr)
+
+struct kl_ia64_fpreg {
+       union {
+               unsigned long bits[2];
+               long double __dummy;    /* force 16-byte alignment */
+       } u;
+};
+
+struct kl_pt_regs_ia64 {
+       /* for 2.6 kernels only. This structure was totally different in 2.4 kernels */
+       unsigned long b6;               /* scratch */
+       unsigned long b7;               /* scratch */
+
+       unsigned long ar_csd;           /* used by cmp8xchg16 (scratch) */
+       unsigned long ar_ssd;           /* reserved for future use (scratch) */
+
+       unsigned long r8;               /* scratch (return value register 0) */
+       unsigned long r9;               /* scratch (return value register 1) */
+       unsigned long r10;              /* scratch (return value register 2) */
+       unsigned long r11;              /* scratch (return value register 3) */
+
+       unsigned long cr_ipsr;          /* interrupted task's psr */
+       unsigned long cr_iip;           /* interrupted task's instruction pointer */
+       unsigned long cr_ifs;           /* interrupted task's function state */
+
+       unsigned long ar_unat;          /* interrupted task's NaT register (preserved) */
+       unsigned long ar_pfs;           /* prev function state  */
+       unsigned long ar_rsc;           /* RSE configuration */
+       /* The following two are valid only if cr_ipsr.cpl > 0: */
+       unsigned long ar_rnat;          /* RSE NaT */
+       unsigned long ar_bspstore;      /* RSE bspstore */
+
+       unsigned long pr;               /* 64 predicate registers (1 bit each) */
+       unsigned long b0;               /* return pointer (bp) */
+       unsigned long loadrs;           /* size of dirty partition << 16 */
+
+       unsigned long r1;               /* the gp pointer */
+       unsigned long r12;              /* interrupted task's memory stack pointer */
+       unsigned long r13;              /* thread pointer */
+
+       unsigned long ar_fpsr;          /* floating point status (preserved) */
+       unsigned long r15;              /* scratch */
+
+       /* The remaining registers are NOT saved for system calls.  */
+
+       unsigned long r14;              /* scratch */
+       unsigned long r2;               /* scratch */
+       unsigned long r3;               /* scratch */
+
+       /* The following registers are saved by SAVE_REST: */
+       unsigned long r16;              /* scratch */
+       unsigned long r17;              /* scratch */
+       unsigned long r18;              /* scratch */
+       unsigned long r19;              /* scratch */
+       unsigned long r20;              /* scratch */
+       unsigned long r21;              /* scratch */
+       unsigned long r22;              /* scratch */
+       unsigned long r23;              /* scratch */
+       unsigned long r24;              /* scratch */
+       unsigned long r25;              /* scratch */
+       unsigned long r26;              /* scratch */
+       unsigned long r27;              /* scratch */
+       unsigned long r28;              /* scratch */
+       unsigned long r29;              /* scratch */
+       unsigned long r30;              /* scratch */
+       unsigned long r31;              /* scratch */
+
+       unsigned long ar_ccv;           /* compare/exchange value (scratch) */
+
+       /*
+        *          * Floating point registers that the kernel considers scratch:
+        *                   */
+       struct kl_ia64_fpreg f6;           /* scratch */
+       struct kl_ia64_fpreg f7;           /* scratch */
+       struct kl_ia64_fpreg f8;           /* scratch */
+       struct kl_ia64_fpreg f9;           /* scratch */
+       struct kl_ia64_fpreg f10;          /* scratch */
+       struct kl_ia64_fpreg f11;          /* scratch */
+} __attribute__((packed));
+
+/*
+ * Structure: dump_header_asm_t
+ *  Function: This is the header for architecture-specific stuff.  It
+ *            follows right after the dump header.
+ */
+typedef struct kl_dump_header_ia64_s {
+        /* the dump magic number -- unique to verify dump is valid */
+        uint64_t             magic_number;
+        /* the version number of this dump */
+        uint32_t             version;
+        /* the size of this header (in case we can't read it) */
+        uint32_t             header_size;
+        /* pointer to pt_regs */
+       uint64_t             pt_regs;
+       /* the dump registers */
+       struct kl_pt_regs_ia64 regs;
+        /* the rnat register saved after flushrs */
+        uint64_t             rnat;
+       /* the pfs register saved after flushrs */
+       uint64_t             pfs;
+       /* the bspstore register saved after flushrs */
+       uint64_t             bspstore;
+
+       /* smp specific */
+       uint32_t               smp_num_cpus;
+       uint32_t               dumping_cpu;
+       struct kl_pt_regs_ia64 smp_regs[KL_NR_CPUS];
+       uint64_t               smp_current_task[KL_NR_CPUS];
+       uint64_t               stack[KL_NR_CPUS];
+} __attribute__((packed)) kl_dump_header_ia64_t;
+
+/* The following struct is used just to calculate the size needed
+ * to store per CPU info. (Make sure it is sync with the above struct)
+ */
+struct kl_dump_CPU_info_ia64 {
+       struct kl_pt_regs_ia64          smp_regs;
+       uint64_t                        smp_current_task;
+       uint64_t                        stack;
+} __attribute__((packed));
+
+/* function declarations
+ */
+int kl_set_dumparch_ia64(void);
+uint32_t dha_num_cpus_ia64(void);
+kaddr_t dha_current_task_ia64(int cpuid);
+int dha_cpuid_ia64(kaddr_t);
+kaddr_t dha_stack_ia64(int);
+kaddr_t dha_stack_ptr_ia64(int);
+int kl_read_dump_header_ia64(void);
+
+#endif /* __KL_DUMP_IA64_H */
diff --git a/kdb/modules/lcrash/asm/kl_types.h b/kdb/modules/lcrash/asm/kl_types.h
new file mode 100644 (file)
index 0000000..5f31269
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * $Id: kl_types.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __ASMIA64_KL_TYPES_H
+#define __ASMIA64_KL_TYPES_H
+
+/* cpw */
+/* was #include <kl_dump_ia64.h> */
+#include "kl_dump_ia64.h"
+
+#define HOST_ARCH_IA64
+/* cpw: add this, as otherwise comes from makefile */
+#define DUMP_ARCH_IA64
+
+/* Format string that allows a single fprintf() call to work for both
+ * 32-bit and 64-bit pointer values (architecture specific).
+ */
+#ifdef CONFIG_X86_32
+#define FMT64  "ll"
+#else
+#define FMT64  "l"
+#endif
+#define FMTPTR  "l"
+
+/* for usage in common code where host architecture
+ * specific type/macro is needed
+ */
+typedef kl_dump_header_ia64_t kl_dump_header_asm_t;
+#define KL_DUMP_ASM_MAGIC_NUMBER KL_DUMP_MAGIC_NUMBER_IA64
+
+#endif /* __ASMIA64_KL_TYPES_H */
diff --git a/kdb/modules/lcrash/kl_alloc.h b/kdb/modules/lcrash/kl_alloc.h
new file mode 100644 (file)
index 0000000..6a5bcac
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * $Id: kl_alloc.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libutil.
+ * A library which provides auxiliary functions.
+ * libutil is part of lkcdutils -- utilities for Linux kernel crash dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_ALLOC_H
+#define __KL_ALLOC_H
+
+/**
+ ** Header file for kl_alloc.c module
+ **
+ **/
+
+#define K_TEMP 1
+#define K_PERM 2
+
+/** function prototypes for register functions
+ **/
+
+/* Memory block allocator. Returns a pointer to an allocated block
+ * of size bytes. In case of error, a NULL pointer will be returned
+ * and errno will be set to indicate exactly what error occurred.
+ * Note that the flag value will determine if the block allocated is
+ * temporary (can be freed via a call to kl_free_temp_blks()) or
+ * permenant (must be freed with a call to kl_free_block())..
+ */
+typedef void * (*klib_block_alloc_func) (
+       int             /* size of block required */,
+       int             /* flag value */,
+       void *          /* return address */);
+
+/* Memory block reallocator. Returns a pointer to a block of new_size
+ * bytes. In case of error, a NULL pointer will be returned and
+ * errno will be set to indicate exactly what error occurred.
+ * Note that the flag value will determine if the block allocated is
+ * temporary (can be free via a call to kl_free_temp_blks()) or
+ * permenant.
+ */
+typedef void * (*klib_block_realloc_func) (
+       void *          /* pointer to block to realloc */,
+       int             /* size of new block required */,
+       int             /* flag value */,
+       void *          /* return address */);
+
+/* Memory block duplicator. Returns a pointer to a block that is
+ * a copy of the block passed in via pointer. In case of error, a
+ * NULL pointer will be returned and errno will be set to indicate
+ * exactly what error occurred. Note that the flag value will
+ * determine if the block allocated is temporary (will be freed
+ * via a call to kl_free_temp_blks()) or permenant. Note that this
+ * function is only supported when liballoc is used (there is no
+ * way to tell the size of a malloced block.
+ */
+typedef void * (*klib_block_dup_func) (
+       void *          /* pointer to block to dup */,
+       int             /* flag value */,
+       void *          /* return address */);
+
+/* Allocates a block large enough to hold a string (plus the terminating
+ * NULL character).
+ */
+typedef void * (*klib_str_to_block_func) (
+       char *          /* pointer to character string */,
+       int             /* flag value */,
+       void *          /* return address */);
+
+/* Frees blocks that were previously allocated.
+ */
+typedef void (*klib_block_free_func) (
+       void *     /* pointer to block */);
+
+/* alloc block wrapper function table structure
+ */
+typedef struct alloc_functions_s {
+       int                     flag;          /* Functions initialized? */
+       klib_block_alloc_func   block_alloc;   /* Returns ptr to block   */
+       klib_block_realloc_func block_realloc; /* Returns ptr to new blk */
+       klib_block_dup_func     block_dup;     /* Returns ptr to new blk */
+       klib_str_to_block_func  str_to_block;  /* Returns ptr to new blk */
+       klib_block_free_func    block_free;    /* Frees memory block     */
+} alloc_functions_t;
+
+extern alloc_functions_t alloc_functions;
+
+/* Macros for accessing functions in alloc_functions table
+ */
+#define KL_BLOCK_ALLOC()       (alloc_functions.block_alloc)
+#define KL_BLOCK_REALLOC()     (alloc_functions.block_realloc)
+#define KL_BLOCK_DUP()         (alloc_functions.block_dup)
+#define KL_STR_TO_BLOCK()      (alloc_functions.str_to_block)
+#define KL_BLOCK_FREE()                (alloc_functions.block_free)
+
+void *_kl_alloc_block(int, int, void *);
+void *_kl_realloc_block(void *, int, int, void *);
+void *_kl_dup_block(void *, int, void *);
+void *_kl_str_to_block(char *, int, void *);
+#if 0
+cpw: we create a new wrappers for these:
+void kl_free_block(void *);
+
+#define kl_alloc_block(size, flags) _kl_alloc_block(size, flags, kl_get_ra())
+#endif
+#define kl_realloc_block(b, new_size, flags) \
+       _kl_realloc_block(b, new_size, flags, kl_get_ra())
+#define kl_dup_block(b, flags) _kl_dup_block(b, flags, kl_get_ra())
+#define kl_str_to_block(s, flags) _kl_str_to_block(s, flags, kl_get_ra())
+
+#endif /* __KL_ALLOC_H */
diff --git a/kdb/modules/lcrash/kl_bfd.h b/kdb/modules/lcrash/kl_bfd.h
new file mode 100644 (file)
index 0000000..9cfee7f
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * $Id: kl_bfd.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_BFD_H
+#define __KL_BFD_H
+
+/* cpw:  " " form: */
+#include "klib.h"
+
+int kl_check_bfd_error(bfd_error_type);
+int kl_open_elf(char*, bfd**, bfd**);
+int kl_read_bfd_syminfo(maplist_t*);
+
+#endif /*  __KL_BFD_H */
diff --git a/kdb/modules/lcrash/kl_btnode.h b/kdb/modules/lcrash/kl_btnode.h
new file mode 100644 (file)
index 0000000..b042993
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * $Id: kl_btnode.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libutil.
+ * A library which provides auxiliary functions.
+ * libutil is part of lkcdutils -- utilities for Linux kernel crash dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_BTNODE_H
+#define __KL_BTNODE_H
+
+/*
+ * Node header struct for use in binary search tree routines
+ */
+typedef struct btnode_s {
+       struct btnode_s     *bt_left;
+       struct btnode_s     *bt_right;
+       struct btnode_s     *bt_parent;
+       char                *bt_key;
+       int                  bt_height;
+} btnode_t;
+
+#define DUPLICATES_OK   1
+
+/**
+ ** btnode operation function prototypes
+ **/
+
+/* Return the hight of a given btnode_s struct in a tree. In the
+ * event of an error (a NULL btnode_s pointer was passed in), a
+ * value of -1 will be returned.
+ */
+int kl_btnode_height(
+       btnode_t*       /* pointer to btnode_s struct */);
+
+/* Insert a btnode_s struct into a tree. After the insertion, the
+ * tree will be left in a reasonibly ballanced state. Note that, if
+ * the DUPLICATES_OK flag is set, duplicate keys will be inserted
+ * into the tree (otherwise return an error). In the event of an
+ * error, a value of -1 will be returned.
+ */
+int kl_insert_btnode(
+       btnode_t**      /* pointer to root of tree */,
+       btnode_t*       /* pointer to btnode_s struct to insert */,
+       int             /* flags (DUPLICATES_OK) */);
+
+/* Finds a btnode in a tree and removes it, making sure to keep
+ * the tree in a reasonably balanced state. As part of the
+ * delete_btnode() operation, a call will be made to the free
+ * function (passed in as a parameter) to free any application
+ * specific data.
+ */
+int kl_delete_btnode(
+       btnode_t**      /* pointer to the root of the btree */,
+       btnode_t*       /* pointer to btnode_s struct to delete */,
+       void(*)(void*)  /* pointer to function to actually free the node */,
+       int             /* flags */);
+
+/* Traverse a tree looking for a particular key. In the event that
+ * duplicate keys are allowed in the tree, returns the first occurance
+ * of the search key found. A pointer to an int should be passed in
+ * to hold the maximum depth reached in the search. Upon success,
+ * returns a pointer to a btnode_s struct. Otherwise, a NULL pointer
+ * will be returned.
+ */
+btnode_t *_kl_find_btnode(
+       btnode_t*       /* pointer to btnode_s struct to start search with */,
+       char*           /* key we are looking for */,
+       int*            /* pointer to where max depth vlaue will be placed */,
+       size_t          /* if nonzero compare only first n chars of key */);
+#define kl_find_btnode(A, B, C) _kl_find_btnode(A, B, C, 0)
+
+btnode_t *kl_first_btnode(
+       btnode_t *      /* pointer to any btnode in a btree */);
+
+btnode_t *kl_next_btnode(
+       btnode_t *      /* pointer to current btnode */);
+
+btnode_t *kl_prev_btnode(
+       btnode_t *      /* Pointer to current btnode */);
+
+#endif /* __KL_BTNODE_H */
diff --git a/kdb/modules/lcrash/kl_cmp.h b/kdb/modules/lcrash/kl_cmp.h
new file mode 100644 (file)
index 0000000..abbd633
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * $Id: kl_cmp.h 1216 2005-07-06 10:03:13Z holzheu $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_CMP_H
+#define __KL_CMP_H
+
+#define DUMP_INDEX_MAGIC    0xdeadbeef
+#define DUMP_INDEX_VERSION  31900
+#define NUM_BUCKETS         65535
+
+/*
+ * Definitions for compressed cached reads.  I've recently lowered
+ * these ... If they need to be increased later, I'll do so.
+ */
+#define CMP_HIGH_WATER_MARK 25
+#define CMP_LOW_WATER_MARK  10
+
+#define CMP_VM_CACHED   0x01
+#define CMP_VM_UNCACHED 0x02
+
+
+/*
+ * This structure defines a page table entry, what each value will
+ * contain.  Since these can be cached or uncached, we have a flags
+ * variable to specify this.
+ */
+typedef struct _ptableentry {
+       int          flags;                /* flags for page in cache   */
+       int          length;               /* length of page            */
+       int          cached;               /* cached (1 = yes, cached)  */
+       kaddr_t      addr;                 /* addr of page              */
+       char         *data;                /* data in page              */
+       struct _ptableentry *next;         /* ptr to next dump page     */
+       struct _ptableentry *prev;         /* ptr to prev dump page     */
+       struct _ptableentry *nextcache;    /* ptr to next cached page   */
+       struct _ptableentry *prevcache;    /* ptr to prev cached page   */
+} ptableentry;
+
+/*
+ * This is for the page table index from the compressed core dump.
+ * This is separate from the page table entries because these are
+ * simply addresses off of the compressed core dump, and not the
+ * actual data from the core dump.  If we hash these values, we gain
+ * a lot of performance because we only have 1 to search for the
+ * page data, 1 to search for the index, and return if both searches
+ * failed.
+ */
+typedef struct _ptableindex {
+       kl_dump_page_t dir;          /* directory entry of page         */
+       kaddr_t addr;                /* address of page offset          */
+       kaddr_t coreaddr;            /* address of page in core         */
+       unsigned int hash;           /* hash value for this index item  */
+       struct _ptableindex *next;   /* next pointer                    */
+} ptableindex;
+
+typedef struct dump_index_s {
+       unsigned int magic_number;   /* dump index magic number         */
+       unsigned int version_number; /* dump index version number       */
+       /* struct timeval depends on machine, use two long values here */
+       struct {uint64_t tv_sec;
+               uint64_t tv_usec;
+       } timebuf; /* the time of the dump */
+} __attribute__((packed)) dump_index_t;
+
+/* Compression function */
+typedef int (*kl_compress_fn_t)(const unsigned char *old, uint32_t old_size, unsigned char *new, uint32_t size);
+
+/* function declarations
+ */
+int  kl_cmpreadmem(int, kaddr_t, char*, unsigned int, unsigned int);
+int  kl_cmpinit(
+       int                     /* fd */,
+       char *                  /* indexname */,
+       int                     /* flags */);
+
+/* Compression routine: No compression */
+int kl_compress_none(const char *old, uint32_t old_size, char *new, uint32_t new_size);
+
+/* Compression routine: Run length encoding */
+int kl_compress_rle(const char *old, uint32_t old_size, char *new, uint32_t new_size);
+
+/* Compression routine: GZIP */
+int kl_compress_gzip(const unsigned char *old, uint32_t old_size, unsigned char *new, uint32_t new_size);
+
+#endif /* __KL_CMP_H */
diff --git a/kdb/modules/lcrash/kl_copt.h b/kdb/modules/lcrash/kl_copt.h
new file mode 100644 (file)
index 0000000..abd96e8
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * $Id: kl_copt.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libutil.
+ * A library which provides auxiliary functions.
+ * libutil is part of lkcdutils -- utilities for Linux kernel crash dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ *
+ * Copyright (C) 2003, 2004 Silicon Graphics, Inc. All rights reserved.
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+#ifndef __KL_COPT_H
+#define __KL_COPT_H
+
+extern int copt_ind;
+extern char *copt_arg;
+extern int copt_error;
+
+void reset_copt(void);
+int is_copt(char *);
+int get_copt(int, char **, const char *, char **);
+
+#endif /* __KL_COPT_H */
diff --git a/kdb/modules/lcrash/kl_debug.h b/kdb/modules/lcrash/kl_debug.h
new file mode 100644 (file)
index 0000000..8faf87e
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * $Id: kl_debug.h 1196 2005-05-17 18:34:12Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_DEBUG_H
+#define __KL_DEBUG_H
+
+/* generic functions for reading kerntypes in stabs and dwarf2 formats */
+
+#define DBG_NONE       0
+#define DBG_STABS      1
+#define DBG_DWARF2     2
+
+extern int debug_format;
+
+#define TYPE_NUM(X)     ((uint64_t)(X) & 0xffffffff)
+#define SRC_FILE(X)     (((uint64_t)(X) >> 48) & 0xfff)
+#define TYPE_NUM_SLOTS (255)
+#define TYPE_NUM_HASH(X) \
+        (((SRC_FILE(X)<<1)+TYPE_NUM(X)) % (TYPE_NUM_SLOTS - 1))
+
+typedef struct dbg_type_s {
+        kltype_t        st_klt;          /* must be first */
+
+        int             st_bit_offset;   /* from start of struct/union */
+        uint64_t       st_type_num;     /* DBG type_num */
+        uint64_t       st_real_type;    /* real type type_num */
+        uint64_t       st_index_type;   /* type_num of array index */
+        uint64_t       st_element_type; /* type_num of array element */
+} dbg_type_t;
+
+#define st_name st_klt.kl_name
+#define st_type st_klt.kl_type
+#define st_ptr st_klt.kl_ptr
+#define st_flags st_klt.kl_flags
+#define st_typestr st_klt.kl_typestr
+#define st_size st_klt.kl_size
+#define st_offset st_klt.kl_offset
+#define st_low_bounds st_klt.kl_low_bounds
+#define st_high_bounds st_klt.kl_high_bounds
+#define st_value st_klt.kl_value
+#define st_bit_size st_klt.kl_bit_size
+#define st_next st_klt.kl_next
+#define st_member st_klt.kl_member
+#define st_realtype st_klt.kl_realtype
+#define st_indextype st_klt.kl_indextype
+#define st_elementtype st_klt.kl_elementtype
+#define st_encoding st_klt.kl_encoding
+
+/* Structure containing information about a symbol entry
+ */
+/* this must match the definition in lkcd's libklib/include/kl_debug.h */
+typedef struct dbg_sym_s {
+       btnode_t                sym_bt; /* must be first */
+       short                   sym_dbgtyp;     /* STABS, DWARF2, ... */
+       short                   sym_state;      /* current state */
+       short                   sym_flag;       /* current flag value */
+       short                   sym_type;       /* symbol type */
+       short                   sym_pvttype;    /* private type */
+       short                   sym_nmlist;     /* namelist index */
+       short                   sym_srcfile;    /* source file index */
+       short                   sym_incfile;    /* include file index */
+       int                     sym_num;        /* symbol number */
+       int                     sym_off;        /* symbol table offset */
+       int                     sym_stroff;  /* symbol offset in string table */
+       uint64_t                sym_typenum;    /* arbitrary type number */
+       kltype_t                *sym_kltype;    /* Full type information */
+       struct dbg_sym_s        *sym_next;      /* next pointer for chaining */
+       struct dbg_sym_s        *sym_link;      /* another pointer for chaining */
+       int                     sym_dup;        /* duplicate symbol */
+} dbg_sym_t;
+#define sym_name sym_bt.bt_key
+
+extern dbg_sym_t *type_tree;
+extern dbg_sym_t *typedef_tree;
+extern dbg_sym_t *func_tree;
+extern dbg_sym_t *srcfile_tree;
+extern dbg_sym_t *var_tree;
+extern dbg_sym_t *xtype_tree;
+extern dbg_sym_t *symlist;
+extern dbg_sym_t *symlist_end;
+
+/* State flags
+ */
+#define DBG_SETUP              0x1
+#define DBG_SETUP_DONE         0x2
+#define DBG_SETUP_FAILED       0x4
+
+/* Flags for identifying individual symbol types
+ */
+#define DBG_SRCFILE    0x0001
+#define DBG_TYPE       0x0002
+#define DBG_TYPEDEF    0x0004
+#define DBG_FUNC       0x0008
+#define DBG_PARAM      0x0010
+#define DBG_LINE       0x0020
+#define DBG_VAR                0x0040
+#define DBG_XTYPE      0x0100
+#define DBG_ALL                0xffff
+
+/* Structure for cross referencing one type number to another
+ */
+typedef struct dbg_hashrec_s {
+       uint64_t                 h_typenum;     /* type number */
+       dbg_sym_t               *h_ptr;         /* pointer to actual type */
+       struct dbg_hashrec_s    *h_next;        /* next pointer (for hashing) */
+} dbg_hashrec_t;
+
+extern dbg_hashrec_t *dbg_hash[];
+
+#define HASH_SYM       1
+#define HASH_XREF      2
+
+/* DBG function prototypes
+ */
+dbg_sym_t *dbg_alloc_sym(
+       int             /* format */);
+
+void dbg_free_sym(
+       dbg_sym_t *     /* dbg_sym_s pointer */);
+
+int dbg_setup_typeinfo(
+       dbg_sym_t *     /* dbg_sym_s pointer */);
+
+int dbg_insert_sym(
+       dbg_sym_t *     /* dbg_sym_s pointer */);
+
+void dbg_hash_sym(
+       uint64_t        /* typenum */,
+       dbg_sym_t *     /* dbg_sym_s pointer */);
+
+dbg_type_t *dbg_walk_hash(
+       int *           /* pointer to hash index */,
+       void **         /* pointer to hash record pointer */);
+
+dbg_sym_t *dbg_find_sym(
+       char *          /* name */,
+       int             /* type number */,
+       uint64_t        /* typenum */);
+
+dbg_sym_t *dbg_first_sym(
+       int             /* type number */);
+
+dbg_sym_t *dbg_next_sym(
+       dbg_sym_t *     /* dbg_sym_s pointer */);
+
+dbg_sym_t *dbg_prev_sym(
+       dbg_sym_t *     /* dbg_sym_s pointer */);
+
+dbg_type_t *dbg_find_typenum(
+       uint64_t        /* typenum */);
+
+#endif /* __KL_DEBUG_H */
diff --git a/kdb/modules/lcrash/kl_dump.h b/kdb/modules/lcrash/kl_dump.h
new file mode 100644 (file)
index 0000000..ba9f397
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * $Id: kl_dump.h 1336 2006-10-23 23:27:06Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_DUMP_H
+#define __KL_DUMP_H
+
+#if 0
+cpw: dont need:
+#include <klib.h>
+#include <asm/ioctl.h>
+#endif
+
+/*
+ * DUMP_DEBUG: a debug level for the kernel dump code and
+ *             the supporting lkcd libraries in user space.
+ *
+ * 0: FALSE: No Debug Added
+ * 1: TRUE:  Break Points
+ * .
+ * .
+ * .
+ * 6: Add Debug Data to Structures
+ * .
+ * .
+ * 9: Max
+ */
+#define DUMP_DEBUG FALSE
+
+#if DUMP_DEBUG
+void dump_bp(void);                     /* Called when something exceptional occures */
+# define DUMP_BP() dump_bp()            /* BreakPoint */
+#else
+# define DUMP_BP()
+#endif
+
+
+#define KL_UTS_LEN 65     /* do not change ... */
+
+extern int SN2_24X;
+
+/*
+ * Size of the buffer that's used to hold:
+ *
+ *     1. the dump header (paded to fill the complete buffer)
+ *     2. the possibly compressed page headers and data
+ */
+extern uint64_t KL_DUMP_BUFFER_SIZE;
+extern uint64_t KL_DUMP_HEADER_SIZE;
+
+#if 0
+/* Variables that contain page size, mask etc. used in dump format
+ * (this is not the system page size stored in the dump header)
+ */
+uint64_t KL_DUMP_PAGE_SIZE;
+uint64_t KL_DUMP_PAGE_MASK;
+uint64_t KL_DUMP_PAGE_SHIFT;
+#endif
+
+/* Dump header offset changed from 4k to 64k to support multiple page sizes */
+#define KL_DUMP_HEADER_OFFSET  (1ULL << 16)
+
+
+/* header definitions for dumps from s390 standalone dump tools */
+#define KL_DUMP_MAGIC_S390SA     0xa8190173618f23fdULL /* s390sa magic number */
+#define KL_DUMP_HEADER_SZ_S390SA 4096
+
+/* standard header definitions */
+#define KL_DUMP_MAGIC_NUMBER  0xa8190173618f23edULL  /* dump magic number  */
+#define KL_DUMP_MAGIC_LIVE    0xa8190173618f23cdULL  /* live magic number  */
+#define KL_DUMP_MAGIC_ASM     0xdeaddeadULL  /* generic arch magic number  */
+#define KL_DUMP_VERSION_NUMBER 0x8      /* dump version number             */
+#define KL_DUMP_PANIC_LEN      0x100    /* dump panic string length        */
+
+/* dump levels - type specific stuff added later -- add as necessary */
+#define KL_DUMP_LEVEL_NONE        0x0   /* no dumping at all -- just bail   */
+#define KL_DUMP_LEVEL_HEADER      0x1   /* kernel dump header only          */
+#define KL_DUMP_LEVEL_KERN        0x2   /* dump header and kernel pages     */
+#define KL_DUMP_LEVEL_USED        0x4   /* dump header, kernel/user pages   */
+#define KL_DUMP_LEVEL_ALL_RAM     0x8   /* dump header, all RAM pages       */
+#define KL_DUMP_LEVEL_ALL         0x10  /* dump all memory RAM and firmware */
+
+/* dump compression options -- add as necessary */
+#define KL_DUMP_COMPRESS_NONE     0x0      /* don't compress this dump      */
+#define KL_DUMP_COMPRESS_RLE      0x1      /* use RLE compression           */
+#define KL_DUMP_COMPRESS_GZIP     0x2      /* use GZIP compression          */
+
+/* dump flags - any dump-type specific flags -- add as necessary */
+#define KL_DUMP_FLAGS_NONE        0x0   /* no flags are set for this dump   */
+#define KL_DUMP_FLAGS_NONDISRUPT  0x1   /* try to keep running after dump   */
+#define KL_DUMP_FLAGS_DISKDUMP   0x80000000 /* dump to local disk          */
+#define KL_DUMP_FLAGS_NETDUMP    0x40000000 /* dump to network device      */
+
+/* dump header flags -- add as necessary */
+#define KL_DUMP_DH_FLAGS_NONE     0x0   /* no flags set (error condition!)  */
+#define KL_DUMP_DH_RAW            0x1   /* raw page (no compression)        */
+#define KL_DUMP_DH_COMPRESSED     0x2   /* page is compressed               */
+#define KL_DUMP_DH_END            0x4   /* end marker on a full dump        */
+#define KL_DUMP_DH_TRUNCATED      0x8   /* dump is incomplete               */
+#define KL_DUMP_DH_TEST_PATTERN   0x10  /* dump page is a test pattern      */
+#define KL_DUMP_DH_NOT_USED       0x20  /* 1st bit not used in flags        */
+
+/*  dump ioctl() control options */
+#ifdef IOCTL26
+#define DIOSDUMPDEV     _IOW('p', 0xA0, unsigned int)  /* set the dump device              */
+#define DIOGDUMPDEV     _IOR('p', 0xA1, unsigned int)  /* get the dump device              */
+#define DIOSDUMPLEVEL   _IOW('p', 0xA2, unsigned int)  /* set the dump level               */
+#define DIOGDUMPLEVEL   _IOR('p', 0xA3, unsigned int)  /* get the dump level               */
+#define DIOSDUMPFLAGS   _IOW('p', 0xA4, unsigned int)  /* set the dump flag parameters     */
+#define DIOGDUMPFLAGS   _IOR('p', 0xA5, unsigned int)  /* get the dump flag parameters     */
+#define DIOSDUMPCOMPRESS _IOW('p', 0xA6, unsigned int) /* set the dump compress level      */
+#define DIOGDUMPCOMPRESS _IOR('p', 0xA7, unsigned int) /* get the dump compress level      */
+
+/* these ioctls are used only by netdump module */
+#define DIOSTARGETIP    _IOW('p', 0xA8, unsigned int)  /* set the target m/c's ip          */
+#define DIOGTARGETIP    _IOR('p', 0xA9, unsigned int)  /* get the target m/c's ip           */
+#define DIOSTARGETPORT  _IOW('p', 0xAA, unsigned int) /* set the target m/c's port          */
+#define DIOGTARGETPORT  _IOR('p', 0xAB, unsigned int) /* get the target m/c's port          */
+#define DIOSSOURCEPORT  _IOW('p', 0xAC, unsigned int) /* set the source m/c's port          */
+#define DIOGSOURCEPORT  _IOR('p', 0xAD, unsigned int) /* get the source m/c's port          */
+#define DIOSETHADDR     _IOW('p', 0xAE, unsigned int) /* set ethernet address       */
+#define DIOGETHADDR     _IOR('p', 0xAF, unsigned int) /* get ethernet address       */
+#define DIOGDUMPOKAY   _IOR('p', 0xB0, unsigned int) /* check if dump is configured      */
+#define DIOSDUMPTAKE   _IOW('p', 0xB1, unsigned int) /* take a manual dump               */
+#else
+#define DIOSDUMPDEV            1       /* set the dump device              */
+#define DIOGDUMPDEV            2       /* get the dump device              */
+#define DIOSDUMPLEVEL          3       /* set the dump level               */
+#define DIOGDUMPLEVEL          4       /* get the dump level               */
+#define DIOSDUMPFLAGS          5       /* set the dump flag parameters     */
+#define DIOGDUMPFLAGS          6       /* get the dump flag parameters     */
+#define DIOSDUMPCOMPRESS       7       /* set the dump compress level      */
+#define DIOGDUMPCOMPRESS       8       /* get the dump compress level      */
+#define DIOSTARGETIP           9       /* set the target m/c's ip          */
+#define DIOGTARGETIP           10      /* get the target m/c's ip          */
+#define DIOSTARGETPORT         11      /* set the target m/c's port        */
+#define DIOGTARGETPORT         12      /* get the target m/c's port        */
+#define DIOSSOURCEPORT         13      /* set the source m/c's port        */
+#define DIOGSOURCEPORT         14      /* get the source m/c's port        */
+#define DIOSETHADDR            15      /* set ethernet address             */
+#define DIOGETHADDR            16      /* get ethernet address             */
+#define DIOGDUMPOKAY           17      /* check if dump is configured      */
+#define DIOSDUMPTAKE           18      /* take a manual dump               */
+#endif
+
+/*
+ * structures
+ */
+
+/* This is the header dumped at the top of every valid crash dump.
+ */
+typedef struct kl_dump_header_s {
+       uint64_t magic_number; /* dump magic number, unique to verify dump */
+       uint32_t version;      /* version number of this dump */
+       uint32_t header_size;  /* size of this header */
+       uint32_t dump_level;   /* level of this dump */
+       /* FIXME: rename page_size to dump_page_size
+        * The size of a hardware/physical memory page (DUMP_PAGE_SIZE).
+        * NB: Not the configurable system page (PAGE_SIZE) (4K, 8K, 16K, etc.)
+        */
+/*     uint32_t             dh_dump_page_size; */
+       uint32_t page_size;    /* page size (e.g. 4K, 8K, 16K, etc.) */
+       uint64_t memory_size;  /* size of entire physical memory */
+       uint64_t memory_start; /* start of physical memory */
+       uint64_t memory_end;      /* end of physical memory */
+#if DUMP_DEBUG >= 6
+        uint64_t num_bytes; /* number of bytes in this dump */
+#endif
+       /* the number of dump pages in this dump specifically */
+       uint32_t num_dump_pages;
+       char panic_string[KL_DUMP_PANIC_LEN]; /* panic string, if available*/
+
+       /* timeval depends on machine, two long values */
+       struct {uint64_t tv_sec;
+               uint64_t tv_usec;
+       } time; /* the time of the system crash */
+
+       /* the NEW utsname (uname) information -- in character form */
+       /* we do this so we don't have to include utsname.h         */
+       /* plus it helps us be more architecture independent        */
+       char utsname_sysname[KL_UTS_LEN];
+       char utsname_nodename[KL_UTS_LEN];
+       char utsname_release[KL_UTS_LEN];
+       char utsname_version[KL_UTS_LEN];
+       char utsname_machine[KL_UTS_LEN];
+       char utsname_domainname[KL_UTS_LEN];
+
+       uint64_t current_task; /* fixme: better use uint64_t here */
+       uint32_t dump_compress; /* compression type used in this dump */
+       uint32_t dump_flags;       /* any additional flags */
+       uint32_t dump_device;   /* any additional flags */
+       uint64_t dump_buffer_size; /* version >= 9 */
+} __attribute__((packed)) kl_dump_header_t;
+
+/* This is the header used by the s390 standalone dump tools
+ */
+typedef struct kl_dump_header_s390sa_s {
+       uint64_t magic_number; /* magic number for this dump (unique)*/
+       uint32_t version;      /* version number of this dump */
+       uint32_t header_size;  /* size of this header */
+       uint32_t dump_level;   /* the level of this dump (just a header?) */
+       uint32_t page_size;    /* page size of dumped Linux (4K,8K,16K etc.) */
+       uint64_t memory_size;  /* the size of all physical memory */
+       uint64_t memory_start; /* the start of physical memory */
+       uint64_t memory_end;   /* the end of physical memory */
+       uint32_t num_pages;    /* number of pages in this dump */
+       uint32_t pad;          /* ensure 8 byte alignment for tod and cpu_id */
+       uint64_t tod;          /* the time of the dump generation */
+       uint64_t cpu_id;       /* cpu id */
+       uint32_t arch_id;
+       uint32_t build_arch_id;
+#define KL_DH_ARCH_ID_S390X 2
+#define KL_DH_ARCH_ID_S390  1
+} __attribute__((packed))  kl_dump_header_s390sa_t;
+
+/* Header associated to each physical page of memory saved in the system
+ * crash dump.
+ */
+typedef struct kl_dump_page_s {
+#if DUMP_DEBUG >= 6
+       uint64_t byte_offset; /* byte offset */
+       uint64_t page_index;  /* page index */
+#endif
+       uint64_t address; /* the address of this dump page */
+       uint32_t size;  /* the size of this dump page */
+       uint32_t flags; /* flags (DUMP_COMPRESSED, DUMP_RAW or DUMP_END) */
+} __attribute__((packed)) kl_dump_page_t;
+
+/* CORE_TYPE indicating type of dump
+ */
+typedef enum {
+       dev_kmem,   /* image of /dev/kmem, a running kernel */
+       reg_core,   /* Regular (uncompressed) core file */
+       s390_core,  /* s390 core file */
+       cmp_core,   /* compressed core file */
+       unk_core    /* unknown core type */
+} CORE_TYPE;
+
+/* function to determine kernel stack for task */
+typedef kaddr_t(*kl_kernelstack_t) (kaddr_t);
+/* map virtual address to physical one */
+typedef int(*kl_virtop_t)(kaddr_t, void*, kaddr_t*);
+/* function to perform page-table traversal */
+typedef kaddr_t(*kl_mmap_virtop_t)(kaddr_t, void*);
+/* XXX description */
+typedef int(*kl_valid_physmem_t)(kaddr_t, int);
+/* XXX description */
+typedef kaddr_t(*kl_next_valid_physaddr_t)(kaddr_t);
+/* write a dump-header-asm, if analyzing a live system */
+typedef int(*kl_write_dump_header_asm_t)(void*);
+/* redirect addresses pointing into task_union areas for running tasks */
+typedef kaddr_t(*kl_fix_vaddr_t)(kaddr_t, size_t);
+/* initialize mapping of virtual to physical addresses */
+typedef int (*kl_init_virtop_t)(void);
+
+/* struct storing dump architecture specific values
+ */
+typedef struct kl_dumparch_s {
+       int             arch;           /* KL_ARCH_ */
+       int             ptrsz;          /* 32 or 64 bit */
+       int             byteorder;      /* KL_LITTLE_ENDIAN or KL_BIG_ENDIAN */
+       uint64_t        pageoffset;     /* PAGE_OFFSET */
+       uint64_t        kstacksize;     /* size of kernel stack */
+       uint64_t        pgdshift;       /* PGDIR_SHIFT */
+       uint64_t        pgdsize;        /* PGDIR_SIZE */
+       uint64_t        pgdmask;        /* PGDIR_MASK */
+       uint64_t        pmdshift;       /* PMD_SHIFT */
+       uint64_t        pmdsize;        /* PMD_SIZE */
+       uint64_t        pmdmask;        /* PMD_MASK */
+       uint64_t        pageshift;      /* PAGE_SHIFT */
+       uint64_t        pagesize;       /* PAGE_SIZE */
+       uint64_t        pagemask;       /* PAGE_MASK */
+       uint32_t        ptrsperpgd;     /* PTRS_PER_PGD */
+       uint32_t        ptrsperpmd;     /* PTRS_PER_PMD */
+       uint32_t        ptrsperpte;     /* PTRS_PER_PTE */
+       kl_kernelstack_t   kernelstack; /* determine kernel stack for task */
+       kl_virtop_t     virtop;         /* map virtual address to physical */
+       kl_mmap_virtop_t   mmap_virtop; /* traverse page table */
+       kl_valid_physmem_t valid_physmem; /* XXX description */
+       kl_next_valid_physaddr_t next_valid_physaddr; /* XXX description */
+       kl_fix_vaddr_t  fix_vaddr;      /* XXX description */
+       uint32_t        dha_size;       /* size of kl_dump_header_xxx_t */
+       kl_write_dump_header_asm_t write_dha; /* XXX description */
+       kl_init_virtop_t init_virtop;   /* init address translation */
+} kl_dumparch_t;
+
+/* function types for dumpaccess */
+typedef kaddr_t (*kl_get_ptr_t)   (void*);
+typedef uint8_t (*kl_get_uint8_t) (void*);
+typedef uint16_t(*kl_get_uint16_t)(void*);
+typedef uint32_t(*kl_get_uint32_t)(void*);
+typedef uint64_t(*kl_get_uint64_t)(void*);
+/* function types for dumpaccess */
+typedef        kaddr_t  (*kl_read_ptr_t)   (kaddr_t);
+typedef        uint8_t  (*kl_read_uint8_t) (kaddr_t);
+typedef        uint16_t (*kl_read_uint16_t)(kaddr_t);
+typedef        uint32_t (*kl_read_uint32_t)(kaddr_t);
+typedef        uint64_t (*kl_read_uint64_t)(kaddr_t);
+
+/* struct to store dump architecture specific functions
+ */
+typedef struct kl_dumpaccess_s {
+       /* get integer value from memory, previously read from dump */
+        kl_get_ptr_t    get_ptr;
+       kl_get_uint8_t  get_uint8;
+       kl_get_uint16_t get_uint16;
+       kl_get_uint32_t get_uint32;
+       kl_get_uint64_t get_uint64;
+       /* read integer value from dump (from physical address) */
+        kl_read_ptr_t    read_ptr;
+       kl_read_uint8_t  read_uint8;
+       kl_read_uint16_t read_uint16;
+       kl_read_uint32_t read_uint32;
+       kl_read_uint64_t read_uint64;
+       /* read integer value from dump (from virtual address) */
+        kl_read_ptr_t    vread_ptr;
+       kl_read_uint8_t  vread_uint8;
+       kl_read_uint16_t vread_uint16;
+       kl_read_uint32_t vread_uint32;
+       kl_read_uint64_t vread_uint64;
+} kl_dumpaccess_t;
+
+/* Struct containing sizes of frequently used kernel structures.
+ */
+typedef struct struct_sizes_s {
+       int     task_struct_sz;
+       int     mm_struct_sz;
+       int     page_sz;
+       int     module_sz;
+       int     new_utsname_sz;
+       int     switch_stack_sz;
+       int     pt_regs_sz;
+       int     pglist_data_sz;
+       int     runqueue_sz;
+} struct_sizes_t;
+
+/* struct storing memory specifc values of the dumped Linux system
+ */
+typedef struct kl_kerninfo_s{
+       kaddr_t         num_physpages;  /* number of physical pages */
+       kaddr_t         mem_map;        /* XXX description */
+       kaddr_t         high_memory;    /* physical memory size */
+       kaddr_t         init_mm;        /* address of mm_struct init_mm */
+       uint64_t        kernel_flags;   /* to indicate kernel features
+                                        * e.g. KL_IS_PAE_I386 on i386 */
+       int             num_cpus;       /* number of cpus */
+       kaddr_t         pgdat_list;     /* pgdat_list value. used as MEM_MAP */
+                                       /* not defined for DISCONTIG memory */
+       int             linux_release;  /* kernel release of dump */
+       struct_sizes_t  struct_sizes;   /* frequently needed struct sizes */
+} kl_kerninfo_t;
+
+/* various flags to indicate Linux kernel compile switches */
+#define KL_IS_PAE_I386  0x0020 /* i386 kernel with PAE support */
+
+/* struct where to keep whole information about the dump
+ */
+typedef struct kl_dumpinfo_s {
+       CORE_TYPE       core_type;      /* type of core file   */
+       char            *dump;          /* pathname for dump  */
+       char            *map;           /* pathname for map file */
+       int             core_fd;        /* file descriptor for dump file  */
+       int             rw_flag;        /* O_RDONLY/O_RDWR (/dev/kmem only) */
+       kl_dumparch_t   arch;           /* dump arch info */
+       kl_dumpaccess_t func;           /* dump access functions */
+       kl_kerninfo_t   mem;            /* mem info for dump */
+} kl_dumpinfo_t;
+
+/* External declarations
+ */
+extern char *dh_typename;
+extern char *dha_typename;
+extern void *G_dump_header;
+extern void *G_dump_header_asm;
+extern kl_dump_header_t *KL_DUMP_HEADER;
+extern void *KL_DUMP_HEADER_ASM;
+
+/* function declarations
+ */
+
+/* open dump */
+int  kl_open_dump(void);
+
+/* init sizes for some structures */
+void kl_init_struct_sizes(void);
+
+/* init host architecture information */
+int  kl_setup_hostinfo(void);
+
+/* init dumpinfo structure */
+int  kl_setup_dumpinfo(char *          /* map file */,
+                     char *            /* dump */,
+                     int               /* rwflag */);
+
+
+/* init dumpinfo structure */
+int  kl_set_dumpinfo(char *            /* map file */,
+                    char *             /* dump */,
+                    int                /* arch of dump */,
+                    int                /* rwflag */);
+
+/* free dumpinfo structure */
+void kl_free_dumpinfo(kl_dumpinfo_t *);
+
+/* set memory related characteristics of dump */
+int  kl_set_kerninfo(void);
+
+/* set function pointers for dump access (depends on host and dump arch) */
+int  kl_set_dumpaccess(void);
+
+/* print contents of kl_dumpinfo_t etc. */
+int  kl_print_dumpinfo(int);
+#define KL_INFO_ALL      0
+#define KL_INFO_ENDIAN   1
+#define KL_INFO_ARCH     2
+#define KL_INFO_PTRSZ    3
+#define KL_INFO_KRELEASE 4
+#define KL_INFO_MEMSIZE  5
+#define KL_INFO_NUMCPUS  6
+
+/* Functions that read data from generic dump_header */
+int kl_valid_dump_magic(uint64_t);
+int kl_header_swap(void *);
+uint64_t kl_header_magic(void *);
+int kl_valid_header(void *);
+uint32_t kl_header_version(void *);
+int kl_header_size(void *);
+void *kl_read_header(int fd, void *);
+
+/* init common lkcd dump header from dump */
+void kl_init_dump_header(int);
+
+/* try to evalutate arch from lkcd 4.1 (version <= 7) dump header */
+int kl_dump_arch_4_1(void *);
+
+/* swap dump header values if necessary */
+void kl_swap_dump_header_reg(kl_dump_header_t* dh);
+void kl_swap_dump_header_s390sa(kl_dump_header_s390sa_t* dh);
+
+/* Read dump header in from dump */
+int kl_read_dump_header(void);
+int kl_read_dump_header_asm(void);
+
+/* Determine the architecure of dump */
+int kl_set_dumparch(int);
+
+/* Finish setting up for access to dump */
+int kl_setup_dumpaccess(int);
+
+/* get the raw dump header */
+int kl_get_raw_dh(int);
+int kl_get_raw_asm_dh(int);
+
+/* get common lkcd dump header */
+int kl_get_dump_header(kl_dump_header_t*);
+
+/* get older style dump headers */
+kl_dump_header_t *get_dump_header_4_1(void *);
+kl_dump_header_t *get_dump_header_SN2_24X(void *);
+
+/* get task that was running when dump was started */
+kaddr_t kl_dumptask(void);
+
+/* Print dump header */
+int kl_print_dump_header(const char* dump);
+
+/* Print dump regular header */
+void kl_print_dump_header_reg(kl_dump_header_t *);
+
+/* Print s390 dump header */
+void kl_print_dump_header_s390(char*);
+
+/* Convert s390 to reg header */
+void kl_s390sa_to_reg_header(kl_dump_header_s390sa_t*, kl_dump_header_t*);
+
+/* Byte swapping functions needed for Xclrash */
+/* get integer value from buffer and swap bytes */
+kaddr_t  kl_get_swap_ptr(void*);
+uint16_t kl_get_swap_uint16(void*);
+uint32_t kl_get_swap_uint32(void*);
+uint64_t kl_get_swap_uint64(void*);
+
+/* read integer value from dump (physical address) and swap bytes */
+kaddr_t  kl_read_swap_ptr(kaddr_t);
+uint16_t kl_read_swap_uint16(kaddr_t);
+uint32_t kl_read_swap_uint32(kaddr_t);
+uint64_t kl_read_swap_uint64(kaddr_t);
+
+/* read integer value from dump (virtual address) and swap bytes */
+kaddr_t  kl_vread_swap_ptr(kaddr_t);
+uint16_t kl_vread_swap_uint16(kaddr_t);
+uint32_t kl_vread_swap_uint32(kaddr_t);
+uint64_t kl_vread_swap_uint64(kaddr_t);
+
+#endif /* __KL_DUMP_H */
diff --git a/kdb/modules/lcrash/kl_dump_arch.h b/kdb/modules/lcrash/kl_dump_arch.h
new file mode 100644 (file)
index 0000000..2d7d8f9
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * $Id: kl_dump_arch.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_DUMP_ARCH_H
+#define __KL_DUMP_ARCH_H
+
+/* check for valid configuration
+ */
+#if !(defined(HOST_ARCH_ALPHA) || defined(HOST_ARCH_I386) || \
+      defined(HOST_ARCH_IA64)  || defined(HOST_ARCH_S390) || \
+      defined(HOST_ARCH_S390X) || defined(HOST_ARCH_ARM)  || \
+      defined(HOST_ARCH_PPC64) || defined(HOST_ARCH_X86_64))
+# error "No valid host architecture defined."
+#endif
+#if ((defined(HOST_ARCH_ALPHA) && \
+      (defined(HOST_ARCH_I386) || defined(HOST_ARCH_IA64) || \
+       defined(HOST_ARCH_S390) || defined(HOST_ARCH_S390X) || \
+       defined(HOST_ARCH_ARM) || defined(HOST_ARCH_PPC64) || \
+       defined(HOST_ARCH_X86_64))) || \
+     (defined(HOST_ARCH_I386) && \
+      (defined(HOST_ARCH_IA64) || defined(HOST_ARCH_S390) || \
+       defined(HOST_ARCH_S390X)|| defined(HOST_ARCH_ARM) || \
+       defined(HOST_ARCH_PPC64)|| defined(HOST_ARCH_X86_64))) || \
+     (defined(HOST_ARCH_IA64) && \
+      (defined(HOST_ARCH_S390)|| defined(HOST_ARCH_S390X) || \
+       defined(HOST_ARCH_ARM) || defined(HOST_ARCH_PPC64) || \
+       defined(HOST_ARCH_X86_64))) || \
+     (defined(HOST_ARCH_S390) && \
+      (defined(HOST_ARCH_S390X) || defined(HOST_ARCH_ARM) || \
+       defined(HOST_ARCH_PPC64) || defined(HOST_ARCH_X86_64))) || \
+     (defined(HOST_ARCH_S390X) && \
+       (defined(HOST_ARCH_ARM) || defined(HOST_ARCH_PPC64) || \
+       defined(HOST_ARCH_X86_64))) || \
+     (defined(HOST_ARCH_ARM) && \
+      (defined(HOST_ARCH_PPC64) || defined(HOST_ARCH_X86_64))) || \
+     (defined(HOST_ARCH_PPC64) && defined(HOST_ARCH_X86_64)))
+# error "More than one valid host architectures defined."
+#endif
+#if !(defined(DUMP_ARCH_ALPHA) || defined(DUMP_ARCH_I386) || \
+      defined(DUMP_ARCH_IA64)  || defined(DUMP_ARCH_S390) || \
+      defined(DUMP_ARCH_S390X) || defined(DUMP_ARCH_ARM) || \
+      defined(DUMP_ARCH_PPC64) || defined(DUMP_ARCH_X86_64))
+# error "No valid dump architecture defined."
+#endif
+
+/* optional: check that host arch equals one supported dump arch
+ */
+#ifdef SUPPORT_HOST_ARCH
+# if (defined(HOST_ARCH_ALPHA) && !defined(DUMP_ARCH_ALPHA)) || \
+     (defined(HOST_ARCH_I386) && !defined(DUMP_ARCH_I386)) || \
+     (defined(HOST_ARCH_IA64) && !defined(DUMP_ARCH_IA64)) || \
+     (defined(HOST_ARCH_S390) && !defined(DUMP_ARCH_S390)) || \
+     (defined(HOST_ARCH_S390X) && !defined(DUMP_ARCH_S390X)) || \
+     (defined(HOST_ARCH_ARM) && !defined(DUMP_ARCH_ARM)) || \
+     (defined(HOST_ARCH_PPC64) && !defined(DUMP_ARCH_PPC64)) || \
+     (defined(HOST_ARCH_X86_64) && !defined(DUMP_ARCH_X86_64))
+#  error "Host architecture not supported as dump architecture."
+# endif
+#endif
+
+/* include dump architecture specific stuff
+ */
+#ifdef DUMP_ARCH_ALPHA
+# include <kl_mem_alpha.h>
+# include <kl_dump_alpha.h>
+#endif
+/* cpw: use the " " form: */
+#ifdef DUMP_ARCH_IA64
+# include "kl_mem_ia64.h"
+# include "kl_dump_ia64.h"
+#endif
+#ifdef DUMP_ARCH_I386
+# include <kl_mem_i386.h>
+# include <kl_dump_i386.h>
+#endif
+#ifdef DUMP_ARCH_S390
+# include <kl_mem_s390.h>
+# include <kl_dump_s390.h>
+#endif
+#ifdef DUMP_ARCH_S390X
+# include <kl_mem_s390x.h>
+# include <kl_dump_s390.h>
+#endif
+#ifdef DUMP_ARCH_ARM
+# include <kl_mem_arm.h>
+# include <kl_dump_arm.h>
+#endif
+#ifdef DUMP_ARCH_PPC64
+#include <kl_mem_ppc64.h>
+#include <kl_dump_ppc64.h>
+#endif
+#ifdef DUMP_ARCH_X86_64
+#include <kl_mem_x86_64.h>
+#include <kl_dump_x86_64.h>
+#endif
+
+/** Function prototypes
+ **/
+int kl_init_kern_info(void);
+
+int kl_get_struct(
+       kaddr_t         /* address */,
+       int             /* size of struct */,
+       void *          /* ptr to buffer */,
+       char *          /* name of struct */);
+
+#endif /* __KL_DUMP_ARCH_H */
diff --git a/kdb/modules/lcrash/kl_dump_ia64.h b/kdb/modules/lcrash/kl_dump_ia64.h
new file mode 100644 (file)
index 0000000..5c3f8d8
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * $Id: kl_dump_ia64.h 1151 2005-02-23 01:09:12Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+/* This header file holds the architecture specific crash dump header */
+#ifndef __KL_DUMP_IA64_H
+#define __KL_DUMP_IA64_H
+
+/* definitions */
+#ifndef KL_NR_CPUS
+# define KL_NR_CPUS  128    /* max number CPUs */
+#endif
+
+#define KL_DUMP_MAGIC_NUMBER_IA64   0xdeaddeadULL  /* magic number            */
+#define KL_DUMP_VERSION_NUMBER_IA64 0x4            /* version number          */
+
+
+/*
+ * mkswap.c calls getpagesize() to get the system page size,
+ * which is not  necessarily the same as the hardware page size.
+ *
+ * For ia64 the kernel PAGE_SIZE can be configured from 4KB ... 16KB.
+ *
+ * The physical memory is layed out out in the hardware/minimal pages.
+ * This is the size we need to use for dumping physical pages.
+ *
+ * Note ths hardware/minimal page size being use in;
+ *      arch/ia64/kernel/efi.c`efi_memmap_walk():
+ *         curr.end   = curr.start + (md->num_pages << 12);
+ *
+ * Since the system page size could change between the kernel we boot
+ * on the the kernel that cause the core dume we may want to have something
+ * more constant like the maximum system page size (See include/asm-ia64/page.h).
+ */
+#define DUMP_MIN_PAGE_SHIFT                    12
+#define DUMP_MIN_PAGE_SIZE                     (1UL << DUMP_MIN_PAGE_SHIFT)
+#define DUMP_MIN_PAGE_MASK                     (~(DUMP_MIN_PAGE_SIZE - 1))
+#define DUMP_MIN_PAGE_ALIGN(addr)              (((addr) + DUMP_MIN_PAGE_SIZE - 1) & DUMP_MIN_PAGE_MASK)
+
+#define DUMP_MAX_PAGE_SHIFT                    16
+#define DUMP_MAX_PAGE_SIZE                     (1UL << DUMP_MAX_PAGE_SHIFT)
+#define DUMP_MAX_PAGE_MASK                     (~(DUMP_MAX_PAGE_SIZE - 1))
+#define DUMP_MAX_PAGE_ALIGN(addr)              (((addr) + DUMP_MAX_PAGE_SIZE - 1) & DUMP_MAX_PAGE_MASK)
+
+#define DUMP_HEADER_OFFSET                     DUMP_MAX_PAGE_SIZE
+
+#define DUMP_EF_PAGE_SHIFT                     DUMP_MIN_PAGE_SHIFT
+
+#define DUMP_PAGE_SHIFT                                DUMP_MIN_PAGE_SHIFT
+#define DUMP_PAGE_SIZE                         DUMP_MIN_PAGE_SIZE
+#define DUMP_PAGE_MASK                         DUMP_MIN_PAGE_MASK
+#define DUMP_PAGE_ALIGN(addr)                  DUMP_MIN_PAGE_ALIGN(addr)
+
+struct kl_ia64_fpreg {
+       union {
+               unsigned long bits[2];
+               long double __dummy;    /* force 16-byte alignment */
+       } u;
+};
+
+struct kl_pt_regs_ia64 {
+       /* for 2.6 kernels only. This structure was totally different in 2.4 kernels */
+       unsigned long b6;               /* scratch */
+       unsigned long b7;               /* scratch */
+
+       unsigned long ar_csd;           /* used by cmp8xchg16 (scratch) */
+       unsigned long ar_ssd;           /* reserved for future use (scratch) */
+
+       unsigned long r8;               /* scratch (return value register 0) */
+       unsigned long r9;               /* scratch (return value register 1) */
+       unsigned long r10;              /* scratch (return value register 2) */
+       unsigned long r11;              /* scratch (return value register 3) */
+
+       unsigned long cr_ipsr;          /* interrupted task's psr */
+       unsigned long cr_iip;           /* interrupted task's instruction pointer */
+       unsigned long cr_ifs;           /* interrupted task's function state */
+
+       unsigned long ar_unat;          /* interrupted task's NaT register (preserved) */
+       unsigned long ar_pfs;           /* prev function state  */
+       unsigned long ar_rsc;           /* RSE configuration */
+       /* The following two are valid only if cr_ipsr.cpl > 0: */
+       unsigned long ar_rnat;          /* RSE NaT */
+       unsigned long ar_bspstore;      /* RSE bspstore */
+
+       unsigned long pr;               /* 64 predicate registers (1 bit each) */
+       unsigned long b0;               /* return pointer (bp) */
+       unsigned long loadrs;           /* size of dirty partition << 16 */
+
+       unsigned long r1;               /* the gp pointer */
+       unsigned long r12;              /* interrupted task's memory stack pointer */
+       unsigned long r13;              /* thread pointer */
+
+       unsigned long ar_fpsr;          /* floating point status (preserved) */
+       unsigned long r15;              /* scratch */
+
+       /* The remaining registers are NOT saved for system calls.  */
+
+       unsigned long r14;              /* scratch */
+       unsigned long r2;               /* scratch */
+       unsigned long r3;               /* scratch */
+
+       /* The following registers are saved by SAVE_REST: */
+       unsigned long r16;              /* scratch */
+       unsigned long r17;              /* scratch */
+       unsigned long r18;              /* scratch */
+       unsigned long r19;              /* scratch */
+       unsigned long r20;              /* scratch */
+       unsigned long r21;              /* scratch */
+       unsigned long r22;              /* scratch */
+       unsigned long r23;              /* scratch */
+       unsigned long r24;              /* scratch */
+       unsigned long r25;              /* scratch */
+       unsigned long r26;              /* scratch */
+       unsigned long r27;              /* scratch */
+       unsigned long r28;              /* scratch */
+       unsigned long r29;              /* scratch */
+       unsigned long r30;              /* scratch */
+       unsigned long r31;              /* scratch */
+
+       unsigned long ar_ccv;           /* compare/exchange value (scratch) */
+
+       /*
+        *          * Floating point registers that the kernel considers scratch:
+        *                   */
+       struct kl_ia64_fpreg f6;           /* scratch */
+       struct kl_ia64_fpreg f7;           /* scratch */
+       struct kl_ia64_fpreg f8;           /* scratch */
+       struct kl_ia64_fpreg f9;           /* scratch */
+       struct kl_ia64_fpreg f10;          /* scratch */
+       struct kl_ia64_fpreg f11;          /* scratch */
+} __attribute__((packed));
+
+/*
+ * Structure: dump_header_asm_t
+ *  Function: This is the header for architecture-specific stuff.  It
+ *            follows right after the dump header.
+ */
+typedef struct kl_dump_header_ia64_s {
+        /* the dump magic number -- unique to verify dump is valid */
+        uint64_t             magic_number;
+        /* the version number of this dump */
+        uint32_t             version;
+        /* the size of this header (in case we can't read it) */
+        uint32_t             header_size;
+        /* pointer to pt_regs */
+       uint64_t             pt_regs;
+       /* the dump registers */
+       struct kl_pt_regs_ia64 regs;
+        /* the rnat register saved after flushrs */
+        uint64_t             rnat;
+       /* the pfs register saved after flushrs */
+       uint64_t             pfs;
+       /* the bspstore register saved after flushrs */
+       uint64_t             bspstore;
+
+       /* smp specific */
+       uint32_t               smp_num_cpus;
+       uint32_t               dumping_cpu;
+       struct kl_pt_regs_ia64 smp_regs[KL_NR_CPUS];
+       uint64_t               smp_current_task[KL_NR_CPUS];
+       uint64_t               stack[KL_NR_CPUS];
+} __attribute__((packed)) kl_dump_header_ia64_t;
+
+/* The following struct is used just to calculate the size needed
+ * to store per CPU info. (Make sure it is sync with the above struct)
+ */
+struct kl_dump_CPU_info_ia64 {
+       struct kl_pt_regs_ia64          smp_regs;
+       uint64_t                        smp_current_task;
+       uint64_t                        stack;
+} __attribute__((packed));
+
+/* function declarations
+ */
+int kl_set_dumparch_ia64(void);
+uint32_t dha_num_cpus_ia64(void);
+kaddr_t dha_current_task_ia64(int cpuid);
+int dha_cpuid_ia64(kaddr_t);
+kaddr_t dha_stack_ia64(int);
+kaddr_t dha_stack_ptr_ia64(int);
+int kl_read_dump_header_ia64(void);
+
+#endif /* __KL_DUMP_IA64_H */
diff --git a/kdb/modules/lcrash/kl_dwarfs.h b/kdb/modules/lcrash/kl_dwarfs.h
new file mode 100644 (file)
index 0000000..e34a929
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * $Id: kl_dwarfs.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by: Prashanth Tamraparni (prasht@in.ibm.com)
+ * Contributions by SGI
+ *
+ * Copyright (C) 2004 International Business Machines Corp.
+ * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+#ifndef __KL_DWARFS_H
+#define __KL_DWARFS_H
+
+/* Dwarf function declarations */
+
+int dw_open_namelist(char*, int);
+int dw_setup_typeinfo(void);
+
+#endif /*  __KL_DWARFS_H */
diff --git a/kdb/modules/lcrash/kl_error.h b/kdb/modules/lcrash/kl_error.h
new file mode 100644 (file)
index 0000000..2594c17
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * $Id: kl_error.h 1169 2005-03-02 21:38:01Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_ERROR_H
+#define __KL_ERROR_H
+
+extern uint64_t klib_error;
+extern FILE *kl_stdout;
+extern FILE *kl_stderr;
+
+/* Error Classes
+ */
+#define KLEC_APP        0
+#define KLEC_KLIB       1
+#define KLEC_MEM       2
+#define KLEC_SYM       3
+#define KLEC_KERN      4
+
+#define KLEC_CLASS_MASK 0x00000000ff000000ULL
+#define KLEC_CLASS_SHIFT 24
+#define KLEC_ECODE_MASK 0x0000000000ffffffULL
+#define KLEC_TYPE_MASK  0xffffffff00000000ULL
+#define KLEC_TYPE_SHIFT 32
+#define KLEC_CLASS(e) ((e & KLEC_CLASS_MASK) >> KLEC_CLASS_SHIFT)
+#define KLEC_ECODE(e) (e & KLEC_ECODE_MASK)
+#define KLEC_TYPE(e) ((e & KLEC_TYPE_MASK) >> KLEC_TYPE_SHIFT)
+
+void kl_reset_error(void);  /* reset klib_error */
+void kl_print_error(void);  /* print warning/error messages */
+void kl_check_error(char*); /* check for/handle errors, generate messages */
+
+/* FIXME: not used yet -- for changes in future, improve error handling
+ */
+typedef struct klib_error_s{
+       uint32_t code;      /* error code */
+       uint16_t class;     /* error class */
+       uint16_t severity;  /* severity of error: e.g. warning or fatal error */
+       uint32_t datadesc;  /* description of data which caused the error */
+       FILE     *fp;       /* fp where to place warning and error messages */
+} klib_error_t;
+
+/*
+ * Some macros for accessing data in klib_error
+ */
+#define KL_ERROR               klib_error
+#define KL_ERRORFP             kl_stderr
+
+/* Error codes
+ *
+ * There are basically two types of error codes -- with each type
+ * residing in a single word in a two word error code value. The lower
+ * 32-bits contains an error class and code that represents exactly
+ * WHAT error occurred (e.g., non-numeric text in a numeric value
+ * entered by a user, bad virtual address, etc.).
+ *
+ * The upper 32-bits represents what type of data was being referenced
+ * when the error occurred (e.g., bad proc struct). Having two tiers of
+ * error codes makes it easier to generate useful and specific error
+ * messages. Note that is possible to have situations where one or the
+ * other type of error codes is not set. This is OK as long as at least
+ * one type s set.
+ */
+
+/* General klib error codes
+ */
+#define KLE_KLIB (KLEC_KLIB << KLEC_CLASS_SHIFT)
+#define KLE_NO_MEMORY                          (KLE_KLIB|1)
+#define KLE_OPEN_ERROR                         (KLE_KLIB|2)
+#define KLE_ZERO_BLOCK                                 (KLE_KLIB|3)
+#define KLE_INVALID_VALUE                      (KLE_KLIB|4)
+#define KLE_NULL_BUFF                          (KLE_KLIB|5)
+#define KLE_ZERO_SIZE                          (KLE_KLIB|6)
+#define KLE_ACTIVE                             (KLE_KLIB|7)
+#define KLE_NULL_POINTER                       (KLE_KLIB|8)
+#define KLE_UNSUPPORTED_ARCH                   (KLE_KLIB|9)
+
+#define KLE_MISC_ERROR                                 (KLE_KLIB|97)
+#define KLE_NOT_SUPPORTED                      (KLE_KLIB|98)
+#define KLE_UNKNOWN_ERROR                      (KLE_KLIB|99)
+
+/* memory error codes
+ */
+#define KLE_MEM (KLEC_MEM << KLEC_CLASS_SHIFT)
+#define KLE_BAD_MAP_FILE                       (KLE_MEM|1)
+#define KLE_BAD_DUMP                           (KLE_MEM|2)
+#define KLE_BAD_DUMPTYPE                       (KLE_MEM|3)
+#define KLE_INVALID_LSEEK                      (KLE_MEM|4)
+#define KLE_INVALID_READ                       (KLE_MEM|5)
+#define KLE_BAD_KERNINFO                       (KLE_MEM|6)
+#define KLE_INVALID_PADDR                      (KLE_MEM|7)
+#define KLE_INVALID_VADDR                      (KLE_MEM|8)
+#define KLE_INVALID_VADDR_ALIGN                (KLE_MEM|9)
+#define KLE_INVALID_MAPPING                    (KLE_MEM|10)
+#define KLE_CMP_ERROR                          (KLE_MEM|11)
+#define KLE_INVALID_DUMP_MAGIC                         (KLE_MEM|12)
+#define KLE_KERNEL_MAGIC_MISMATCH               (KLE_MEM|13)
+#define KLE_NO_END_SYMBOL                       (KLE_MEM|14)
+#define KLE_INVALID_DUMP_HEADER                        (KLE_MEM|15)
+#define KLE_DUMP_INDEX_CREATION                        (KLE_MEM|16)
+#define KLE_DUMP_HEADER_ONLY                   (KLE_MEM|17)
+#define KLE_PAGE_NOT_PRESENT                   (KLE_MEM|18)
+#define KLE_BAD_ELF_FILE                       (KLE_MEM|19)
+#define KLE_ARCHIVE_FILE                       (KLE_MEM|20)
+#define KLE_MAP_FILE_PRESENT                   (KLE_MEM|21)
+#define KLE_BAD_MAP_FILENAME                   (KLE_MEM|22)
+#define KLE_BAD_DUMP_FILENAME                  (KLE_MEM|23)
+#define KLE_BAD_NAMELIST_FILE                  (KLE_MEM|24)
+#define KLE_BAD_NAMELIST_FILENAME              (KLE_MEM|25)
+#define KLE_LIVE_SYSTEM                                (KLE_MEM|26)
+#define KLE_NOT_INITIALIZED                    (KLE_MEM|27)
+
+/* symbol error codes
+ */
+#define KLE_SYM (KLEC_SYM << KLEC_CLASS_SHIFT)
+#define KLE_NO_SYMTAB                          (KLE_SYM|1)
+#define KLE_NO_SYMBOLS                         (KLE_SYM|2)
+#define KLE_INVALID_TYPE                        (KLE_SYM|3)
+#define KLE_NO_MODULE_LIST                      (KLE_SYM|4)
+
+/* kernel data error codes
+ */
+#define KLE_KERN (KLEC_KERN << KLEC_CLASS_SHIFT)
+#define KLE_INVALID_KERNELSTACK                (KLE_KERN|1)
+#define KLE_INVALID_STRUCT_SIZE                (KLE_KERN|2)
+#define KLE_BEFORE_RAM_OFFSET                  (KLE_KERN|3)
+#define KLE_AFTER_MAXPFN                       (KLE_KERN|4)
+#define KLE_AFTER_PHYSMEM                      (KLE_KERN|5)
+#define KLE_AFTER_MAXMEM                       (KLE_KERN|6)
+#define KLE_PHYSMEM_NOT_INSTALLED              (KLE_KERN|7)
+#define KLE_NO_DEFTASK                         (KLE_KERN|8)
+#define KLE_PID_NOT_FOUND                      (KLE_KERN|9)
+#define KLE_DEFTASK_NOT_ON_CPU                         (KLE_KERN|10)
+#define KLE_NO_CURCPU                          (KLE_KERN|11)
+#define KLE_NO_CPU                             (KLE_KERN|12)
+#define KLE_SIG_ERROR                          (KLE_KERN|13)
+#define KLE_TASK_RUNNING                        (KLE_KERN|14)
+#define KLE_NO_SWITCH_STACK                     (KLE_KERN|15)
+
+/* Error codes that indicate what type of data was bad. These are
+ * placed in the upper 32-bits of klib_error.
+ */
+#define KLE_BAD_TASK_STRUCT            (((uint64_t)1)<<32)
+#define KLE_BAD_SYMNAME         (((uint64_t)2)<<32)
+#define KLE_BAD_SYMADDR         (((uint64_t)3)<<32)
+#define KLE_BAD_FUNCADDR        (((uint64_t)4)<<32)
+#define KLE_BAD_STRUCT          (((uint64_t)5)<<32)
+#define KLE_BAD_FIELD           (((uint64_t)6)<<32)
+#define KLE_BAD_PC              (((uint64_t)7)<<32)
+#define KLE_BAD_RA              (((uint64_t)8)<<32)
+#define KLE_BAD_SP              (((uint64_t)9)<<32)
+#define KLE_BAD_EP              (((uint64_t)10)<<32)
+#define KLE_BAD_SADDR           (((uint64_t)11)<<32)
+#define KLE_BAD_KERNELSTACK     (((uint64_t)12)<<32)
+#define KLE_BAD_LINENO          (((uint64_t)13)<<32)
+#define KLE_MAP_FILE           (((uint64_t)14)<<32)
+#define KLE_DUMP               (((uint64_t)15)<<32)
+#define KLE_BAD_STRING          (((uint64_t)16)<<32)
+#define KLE_ELF_FILE           (((uint64_t)17)<<32)
+
+/* flags for function kl_msg()
+ * First 3 bits define trace levels. Minimum trace threshold is trace level 1.
+ * So maximal 7 trace levels are possible. We are using only KLE_TRACELEVEL_MAX.
+ * If no trace level bits are set, it is normal output.
+ */
+#define _KLE_TRACEBIT1       0x00000001  /* trace bit 1 */
+#define _KLE_TRACEBIT2       0x00000002  /* trace bit 2 */
+#define _KLE_TRACEBIT3       0x00000004  /* trace bit 3 */
+#define _KLE_TRACENUM        8           /* used in _KLE_TRACENUM */
+#define _KLE_TRACEMASK       (_KLE_TRACENUM-1) /* mask for trace bits */
+/* further flags */
+#define KLE_F_NOORIGIN       0x00001000 /* do not print origin for this msg */
+#define KLE_F_ERRORMSG       0x00002000 /* treat message as error message */
+/* trace levels := predefined combinations of trace bits */
+#define KLE_F_TRACELEVEL1      (_KLE_TRACEBIT1)
+#define KLE_F_TRACELEVEL2      (_KLE_TRACEBIT2)
+#define KLE_F_TRACELEVEL3      (_KLE_TRACEBIT1|_KLE_TRACEBIT2)
+#define KLE_F_TRACELEVEL4      (_KLE_TRACEBIT3)
+#define KLE_TRACELEVELMAX      4
+#define KLE_TRACELEVEL(flg)    (flg & _KLE_TRACEMASK)
+#define KLE_GETTRACELEVEL(flg) \
+ ((KLE_TRACELEVEL(flg) > KLE_TRACELEVELMAX) ? KLE_TRACELEVELMAX : \
+  KLE_TRACELEVEL(flg))
+
+/* define debug components of libklib (64 components possible)
+ * used by kl_msg()
+ */
+#define KL_DBGCOMP_ALLOC    0x0000000001  /* liballoc */
+#define KL_DBGCOMP_BFD      0x0000000002  /* general bfd support */
+#define KL_DBGCOMP_BTREE    0x0000000004  /* btree implementation */
+#define KL_DBGCOMP_COMPRESS 0x0000000008  /* gzip/rle (de)compression */
+#define KL_DBGCOMP_INIT     0x0000000010  /* klib initialization */
+#define KL_DBGCOMP_MEMMAP   0x0000000020  /* memory mapping */
+#define KL_DBGCOMP_MODULE   0x0000000040  /* kernel module handling */
+#define KL_DBGCOMP_SIGNAL   0x0000000080  /* signal handling */
+#define KL_DBGCOMP_STABS    0x0000000100  /* stabs format support */
+#define KL_DBGCOMP_SYMBOL   0x0000000200  /* symbol handling */
+#define KL_DBGCOMP_TYPE     0x0000000400  /* type information handling */
+#define KL_DBGCOMP_ALL      ((uint64_t) -1)  /* all components */
+
+/* central output routine, shouldn't be used directly, but
+ * by following macros
+ */
+void kl_msg(uint64_t, uint32_t, const char*, const char*, int,
+           const char*, ...);
+
+/* vararg macros that should be used instead of kl_msg()
+ */
+/* used within libklib to print non-error messages (e.g. progress indication)
+ */
+#define KL_MSG(fmt, args...) \
+kl_msg(0, 0, NULL, NULL, 0, fmt, ## args)
+/* Can be used by application to print error messages;
+ * not used by libklib itself.
+ */
+#define kl_error(fmt, args...)  \
+kl_msg(0, KLE_F_ERRORMSG, __FUNCTION__, __FILE__, __LINE__, fmt, ## args)
+/* Generate trace messages. Used for libklib debugging. Might be used
+ * by an application, too.
+ * A macro _DBG_COMPONENT has to be defined locally in the module where
+ * any trace macro is used. See above debug components.
+ * Trace messages are only printed iff _DBG_COMPONENT was set before with a
+ * call to kl_set_dbg_component().
+ */
+#define kl_trace1(flg, fmt, args...) \
+kl_msg(_DBG_COMPONENT,  KLE_F_TRACELEVEL1|(flg), \
+       __FUNCTION__, __FILE__, __LINE__, fmt, ## args)
+#define kl_trace2(flg, fmt, args...) \
+kl_msg(_DBG_COMPONENT,  KLE_F_TRACELEVEL2|(flg), \
+       __FUNCTION__, __FILE__, __LINE__, fmt, ## args)
+#define kl_trace3(flg, fmt, args...) \
+kl_msg(_DBG_COMPONENT,  KLE_F_TRACELEVEL3|(flg), \
+       __FUNCTION__, __FILE__, __LINE__, fmt, ## args)
+#define kl_trace4(flg, fmt, args...) \
+kl_msg(_DBG_COMPONENT,  KLE_F_TRACELEVEL4|(flg), \
+       __FUNCTION__, __FILE__, __LINE__, fmt, ## args)
+
+/* functions to set some global variables for libklib debugging
+ */
+int  kl_set_trace_threshold(uint32_t);
+void kl_set_dbg_component(uint64_t);
+void kl_set_stdout(FILE *);
+void kl_set_stderr(FILE *);
+
+/* functions to get contents of global variables for libklib debugging
+ */
+uint32_t kl_get_trace_threshold(void);
+uint64_t kl_get_dbg_component(void);
+
+#endif /* __KL_ERROR_H */
diff --git a/kdb/modules/lcrash/kl_htnode.h b/kdb/modules/lcrash/kl_htnode.h
new file mode 100644 (file)
index 0000000..44ebd7a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * $Id: kl_htnode.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libutil.
+ * A library which provides auxiliary functions.
+ * libutil is part of lkcdutils -- utilities for Linux kernel crash dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_HTNODE_H
+#define __KL_HTNODE_H
+
+/* Node structure for use in hierarchical trees (htrees).
+ */
+typedef struct htnode_s {
+       struct htnode_s *next;
+       struct htnode_s *prev;
+       struct htnode_s *parent;
+       struct htnode_s *children;
+       int                              seq;
+       int                              level;
+       int                              key;
+} htnode_t;
+
+/* Flag values
+ */
+#define HT_BEFORE      0x1
+#define HT_AFTER       0x2
+#define HT_CHILD       0x4
+#define HT_PEER                0x8
+
+/* Function prototypes
+ */
+htnode_t *kl_next_htnode(
+       htnode_t *              /* htnode pointer */);
+
+htnode_t *kl_prev_htnode(
+       htnode_t *              /* htnode pointer */);
+
+void ht_insert_peer(
+       htnode_t *              /* htnode pointer */,
+       htnode_t *              /* new htnode pointer*/,
+       int                     /* flags */);
+
+void ht_insert_child(
+       htnode_t *              /* htnode pointer */,
+       htnode_t *              /* new htnode pointer*/,
+       int                     /* flags */);
+
+int ht_insert(
+       htnode_t *              /* htnode pointer */,
+       htnode_t *              /* new htnode pointer*/,
+       int                     /* flags */);
+
+void ht_insert_next_htnode(
+       htnode_t *      /* htnode pointer */,
+       htnode_t *      /* new htnode pointer*/);
+
+#endif /* __KL_HTNODE_H */
diff --git a/kdb/modules/lcrash/kl_lib.h b/kdb/modules/lcrash/kl_lib.h
new file mode 100644 (file)
index 0000000..f5216ad
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * $Id: kl_lib.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libutil.
+ * A library which provides auxiliary functions.
+ * libutil is part of lkcdutils -- utilities for Linux kernel crash dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_LIB_H
+#define __KL_LIB_H
+
+/* Include system header files
+ */
+
+#if 0
+/* cpw: we don't need this userland stuff: */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <sys/utsname.h>
+#include <fcntl.h>
+#include <string.h>
+#include <setjmp.h>
+#include <strings.h>
+#include <errno.h>
+#include <assert.h>
+#include <ctype.h>
+#endif
+
+/* Include lkcd library header files
+ */
+/* cpw: change these from the < > form to the " " form: */
+#include "kl_types.h"
+#include "kl_alloc.h"
+#include "kl_libutil.h"
+#include "kl_btnode.h"
+#include "kl_htnode.h"
+#include "kl_queue.h"
+#include "kl_stringtab.h"
+
+#endif /* __KL_LIB_H */
diff --git a/kdb/modules/lcrash/kl_libutil.h b/kdb/modules/lcrash/kl_libutil.h
new file mode 100644 (file)
index 0000000..90fdd9b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * $Id: kl_libutil.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libutil.
+ * A library which provides auxiliary functions.
+ * libutil is part of lkcdutils -- utilities for Linux kernel crash dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_LIBUTIL_H
+#define __KL_LIBUTIL_H
+
+/* cpw: change all these from the < > form to the " " form: */
+#include "kl_alloc.h"
+#include "kl_btnode.h"
+#include "kl_copt.h"
+#include "kl_htnode.h"
+#include "kl_queue.h"
+#include "kl_stringtab.h"
+
+int kl_shift_value(uint64_t );
+int kl_string_compare(char *, char *);
+int kl_string_match(char *, char *);
+uint64_t kl_strtoull(char *, char **, int);
+time_t kl_str_to_ctime(char *);
+void *kl_get_ra(void);
+
+#endif /* __KL_LIBUTIL_H */
diff --git a/kdb/modules/lcrash/kl_mem.h b/kdb/modules/lcrash/kl_mem.h
new file mode 100644 (file)
index 0000000..6760918
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * $Id: kl_mem.h 1157 2005-02-25 22:04:05Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_MEM_H
+#define __KL_MEM_H
+
+#if 0
+cpw: skip:
+extern kaddr_t VMALLOC_START;
+extern kaddr_t VMALLOC_END;
+#endif
+
+/*
+ * Function prototypes
+ */
+
+int kl_linux_release(void);
+
+k_error_t kl_readmem(
+       kaddr_t         /* physical address to start reading from */,
+       unsigned        /* number of bytes to read */,
+       void *          /* pointer to buffer */);
+
+k_error_t kl_readkmem(
+       kaddr_t         /* virtual address to start reading from */,
+       unsigned        /* number of bytes to read */,
+       void *          /* pointer to buffer */);
+
+int kl_virtop(
+       kaddr_t         /* virtual address to translate */,
+       void *          /* pointer to mem_map for address translation */,
+       kaddr_t *       /* pointer to physical address to return */);
+
+k_error_t kl_get_block(
+       kaddr_t         /* virtual address */,
+       unsigned        /* size of block to read in */,
+       void *          /* pointer to buffer */,
+       void *          /* pointer to mmap */);
+
+/* Wrapper that eliminates the mmap parameter
+ */
+#define GET_BLOCK(a, s, b) kl_get_block(a, s, (void *)b, (void *)0)
+
+uint64_t kl_uint(
+       void *          /* pointer to buffer containing struct */,
+       char *          /* name of struct */,
+       char *          /* name of member */,
+       unsigned        /* offset */);
+
+int64_t kl_int(
+       void *          /* pointer to buffer containing struct */,
+       char *          /* name of struct */,
+       char *          /* name of member */,
+       unsigned        /* offset */);
+
+kaddr_t kl_kaddr(
+       void *          /* pointer to buffer containing struct */,
+       char *          /* name of struct */,
+       char *          /* name of member */);
+
+/* XXX deprecated use KL_READ_PTR() instead */
+kaddr_t kl_kaddr_to_ptr(
+       kaddr_t                 /* Address to dereference */);
+
+int     kl_is_valid_kaddr(
+       kaddr_t                 /* Address to test */,
+       void *                  /* pointer to mmap */,
+       int                     /* flags */);
+
+/* REMIND:
+ *    Likely not right for ia64
+ */
+#define KL_KADDR_IS_PHYSICAL(vaddr) ((vaddr >= KL_PAGE_OFFSET) && \
+                                     (vaddr <= KL_HIGH_MEMORY))
+
+#define PGNO_TO_PADDR(pgno) (pgno << KL_PAGE_SHIFT)
+
+/*
+ * declaration of some defaults that are used in kl_set_dumparch()
+ */
+int    kl_valid_physaddr(kaddr_t);
+int     kl_valid_physmem(kaddr_t, int);
+kaddr_t kl_next_valid_physaddr(kaddr_t);
+kaddr_t kl_fix_vaddr(kaddr_t, size_t);
+int     kl_init_virtop(void);
+
+#endif /* __KL_MEM_H */
diff --git a/kdb/modules/lcrash/kl_mem_ia64.h b/kdb/modules/lcrash/kl_mem_ia64.h
new file mode 100644 (file)
index 0000000..62b4de3
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * $Id: kl_mem_ia64.h 1250 2006-04-18 18:23:44Z cliffpwickman $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_MEM_IA64_H
+#define __KL_MEM_IA64_H
+
+/* XXX - the following macros are used by functions in kl_page.c and in */
+/*       function kl_virtop, they still have to be defined properly, */
+/*       all the following macros have first to be set with correct values. */
+/*       I don't have a clue what values to use for ia64 architecture!!! */
+
+/* KSTACK_SIZE depends on page size (see kernel headers ptrace.h and page.h)
+ * #define IA64_STK_OFFSET   ((1 << IA64_TASK_STRUCT_LOG_NUM_PAGES)*PAGE_SIZE)
+ * and
+ * #define PAGE_SIZE 1UL<<PAGE_SHIFT
+ * and
+ * #if defined(CONFIG_IA64_PAGE_SIZE_4KB)
+ * # define PAGE_SHIFT     12
+ * #elif defined(CONFIG_IA64_PAGE_SIZE_8KB)
+ * # define PAGE_SHIFT     13
+ * #elif defined(CONFIG_IA64_PAGE_SIZE_16KB)
+ * # define PAGE_SHIFT     14
+ * #elif defined(CONFIG_IA64_PAGE_SIZE_64KB)
+ * # define PAGE_SHIFT     16
+ * #else
+ * # error Unsupported page size!
+ * #endif
+ * and
+ * #if defined(CONFIG_IA64_PAGE_SIZE_4KB)
+ * # define IA64_TASK_STRUCT_LOG_NUM_PAGES         3
+ * #elif defined(CONFIG_IA64_PAGE_SIZE_8KB)
+ * # define IA64_TASK_STRUCT_LOG_NUM_PAGES         2
+ * #elif defined(CONFIG_IA64_PAGE_SIZE_16KB)
+ * # define IA64_TASK_STRUCT_LOG_NUM_PAGES         1
+ * #else
+ * # define IA64_TASK_STRUCT_LOG_NUM_PAGES         0
+ * #endif
+ * Finally we have for page sizes 4KB, 8K, 16K IA64_STK_OFFSET=32K, and
+ * for page size 64K IA64_STK_OFFSET=64K.
+ * FIXME: !!!Don't know how to handle 64K page size case!!!
+ */
+#define KL_KSTACK_SIZE_IA64        0x8000ULL
+/* 64KB page size case:
+ * #define KL_KSTACK_SIZE_IA64        0x10000ULL
+ */
+
+#define KL_PAGE_OFFSET_IA64        0xe000000000000000
+
+#define KL_PAGE_SHIFT_IA64         KL_PAGE_SHIFT
+#define KL_PAGE_SIZE_IA64          (1ULL << KL_PAGE_SHIFT_IA64)
+#define KL_PAGE_MASK_IA64          (~(KL_PAGE_SIZE_IA64-1))
+
+/* for 3-level page tables: */
+#define KL_PGDIR_SHIFT_IA64      (KL_PAGE_SHIFT_IA64+(KL_PAGE_SHIFT_IA64-3)*2)
+#define KL_PGDIR_SIZE_IA64       (1ULL<<KL_PGDIR_SHIFT_IA64)
+#define KL_PGDIR_MASK_IA64       (~(KL_PGDIR_SIZE_IA64-1))
+
+/* for 4-level page tables: */
+#define KL_PGDIR4_SHIFT_IA64      (KL_PAGE_SHIFT_IA64+(KL_PAGE_SHIFT_IA64-3)*3)
+#define KL_PGDIR4_SIZE_IA64       (1ULL<<KL_PGDIR4_SHIFT_IA64)
+#define KL_PGDIR4_MASK_IA64       (~(KL_PGDIR_SIZE4_IA64-1))
+#define KL_PUD_SHIFT_IA64        (KL_PAGE_SHIFT_IA64+(KL_PAGE_SHIFT_IA64-3)*2)
+#define KL_PUD_SIZE_IA64         (1ULL<<KL_PUD_SHIFT_IA64)
+#define KL_PUD_MASK_IA64         (~(KL_PUD_SIZE_IA64-1))
+
+#define KL_PMD_SHIFT_IA64        (KL_PAGE_SHIFT_IA64+(KL_PAGE_SHIFT_IA64-3)*1)
+#define KL_PMD_SIZE_IA64         (1ULL<<KL_PMD_SHIFT_IA64)
+#define KL_PMD_MASK_IA64         (~(KL_PMD_SIZE_IA64-1))
+
+#define KL_PTRS_PER_PGD_IA64     (1ULL<<(KL_PAGE_SHIFT_IA64-3))
+#define KL_PTRS_PER_PUD_IA64     (1ULL<<(KL_PAGE_SHIFT_IA64-3))
+#define KL_PTRS_PER_PMD_IA64     (1ULL<<(KL_PAGE_SHIFT_IA64-3))
+#define KL_PTRS_PER_PTE_IA64     (1ULL<<(KL_PAGE_SHIFT_IA64-3))
+
+/* These values describe the bits of pgd/pmd/pte entries that are
+ * status bits and therefor have to be masked in order to get valid
+ * addresses
+ */
+#define KL_PMD_BASE_MASK_IA64    (((1ULL<<50)-1)&(~0xfffULL))
+#define KL_PT_BASE_MASK_IA64     KL_PMD_BASE_MASK_IA64
+#define KL_PAGE_BASE_MASK_IA64   KL_PMD_BASE_MASK_IA64
+
+#define KL_KADDR_IS_HIGHMEM(vaddr) ((KL_HIGH_MEMORY && (vaddr >= KL_HIGH_MEMORY)))
+
+uint32_t dha_num_cpus_ia64(void);
+kaddr_t dha_current_task_ia64(int);
+int dha_cpuid_ia64(kaddr_t);
+kaddr_t dha_stack_ia64(int);
+kaddr_t dha_stack_ptr_ia64(int);
+kaddr_t kl_kernelstack_ia64(kaddr_t);
+kaddr_t kl_mmap_virtop_ia64(kaddr_t, void*);
+int     kl_init_virtop_ia64(void);
+int     kl_virtop_ia64(kaddr_t, void*, kaddr_t*);
+int     kl_vtop_ia64(kaddr_t, kaddr_t*);
+int    kl_valid_physmem_ia64(kaddr_t, int);
+kaddr_t kl_next_valid_physaddr_ia64(kaddr_t);
+kaddr_t kl_fix_vaddr_ia64(kaddr_t, size_t);
+
+/* Structure containing key data for ia64 virtual memory mapping.
+ * Note that a number of fields are SN system specific.
+ */
+typedef struct ia64_vminfo_s {
+        int             flags;
+        kaddr_t         vpernode_base;
+        kaddr_t         vglobal_base;
+        kaddr_t         to_phys_mask;
+        kaddr_t         kernphysbase;
+        int             nasid_shift;    /* SN specific */
+        int             nasid_mask;     /* SN specific */
+} ia64_vminfo_t;
+
+extern ia64_vminfo_t ia64_vminfo;
+
+/* Some vminfo flags
+ */
+#define MAPPED_KERN_FLAG        0x1
+#define SN2_FLAG                0x2
+
+/* Some vminfo macros
+ */
+#define IS_MAPPED_KERN (ia64_vminfo.flags & MAPPED_KERN_FLAG)
+#define IS_SN2 (ia64_vminfo.flags & SN2_FLAG)
+#define KL_VPERNODE_BASE ia64_vminfo.vpernode_base
+#define KL_VGLOBAL_BASE ia64_vminfo.vglobal_base
+#define KL_TO_PHYS_MASK ia64_vminfo.to_phys_mask
+#define KL_KERNPHYSBASE ia64_vminfo.kernphysbase
+#define KL_NASID_SHIFT ia64_vminfo.nasid_shift
+#define KL_NASID_MASK ia64_vminfo.nasid_mask
+
+#define ADDR_TO_NASID(A) (((A) >> (long)(KL_NASID_SHIFT)) & KL_NASID_MASK)
+
+#endif /* __KL_MEM_IA64_H */
diff --git a/kdb/modules/lcrash/kl_module.h b/kdb/modules/lcrash/kl_module.h
new file mode 100644 (file)
index 0000000..a3cd05f
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * $Id: kl_module.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_MODULE_H
+#define __KL_MODULE_H
+
+/*
+ * insmod generates ksymoops
+ *
+ */
+
+typedef struct kl_modinfo_s {
+       char *modname;         /* name of module as loaded in dump */
+       /* store ksym info for all modules in a linked list */
+       struct kl_modinfo_s *next;
+       char *object_file;     /* name of file that module was loaded from*/
+                              /* ? possibly store modtime and version here ? */
+       uint64_t header;       /* address of module header */
+       uint64_t mtime;        /* time of last modification of object_file */
+       uint32_t version;      /* kernel version that module was compiled for */
+       uint64_t text_sec;     /* address of text section */
+       uint64_t text_len;     /* length of text section */
+       uint64_t data_sec;     /* address of data section */
+       uint64_t data_len;     /* length of data section */
+       uint64_t rodata_sec;   /* address of rodata section */
+       uint64_t rodata_len;   /* length of rodata section */
+       uint64_t bss_sec;      /* address of rodata section */
+       uint64_t bss_len;      /* length of rodata section */
+       char *ksym_object;     /* ksym for object */
+       char *ksym_text_sec;   /* ksym for its text section */
+       char *ksym_data_sec;   /* ksym for its data section */
+       char *ksym_rodata_sec; /* ksym for its rodata section */
+       char *ksym_bss_sec;    /* ksym for its bss sectio */
+} kl_modinfo_t;
+
+int  kl_get_module(char*, kaddr_t*, void**);
+int  kl_get_module_2_6(char*, kaddr_t*, void**);
+int  kl_get_modname(char**, void*);
+int  kl_new_get_modname(char**, void*);
+void kl_free_modinfo(kl_modinfo_t**);
+int  kl_new_modinfo(kl_modinfo_t**, void*);
+int  kl_set_modinfo(kaddr_t, char*, kl_modinfo_t*);
+int  kl_complete_modinfo(kl_modinfo_t*);
+int  kl_load_ksyms(int);
+int  kl_load_ksyms_2_6(int);
+int  kl_unload_ksyms(void);
+int  kl_load_module_sym(char*, char*, char*);
+int  kl_unload_module_sym(char*);
+int  kl_autoload_module_info(char*);
+kl_modinfo_t * kl_lkup_modinfo(char*);
+
+#endif /* __KL_MODULE_H */
diff --git a/kdb/modules/lcrash/kl_queue.h b/kdb/modules/lcrash/kl_queue.h
new file mode 100644 (file)
index 0000000..3d5d2a5
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * $Id: kl_queue.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libutil.
+ * A library which provides auxiliary functions.
+ * libutil is part of lkcdutils -- utilities for Linux kernel crash dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_QUEUE_H
+#define __KL_QUEUE_H
+
+/* List element header
+ */
+typedef struct element_s {
+       struct element_s    *next;
+       struct element_s    *prev;
+} element_t;
+
+/* Some useful macros
+ */
+#define ENQUEUE(list, elem) \
+       kl_enqueue((element_t **)list, (element_t *)elem)
+#define DEQUEUE(list) kl_dequeue((element_t **)list)
+#define FINDQUEUE(list, elem) \
+       kl_findqueue((element_t **)list, (element_t *)elem)
+#define REMQUEUE(list, elem) kl_remqueue((element_t **)list, (element_t *)elem)
+
+typedef struct list_of_ptrs {
+       element_t               elem;
+       unsigned long long      val64;
+} list_of_ptrs_t;
+
+#define FINDLIST_QUEUE(list, elem, compare) \
+       kl_findlist_queue((list_of_ptrs_t **)list, \
+               (list_of_ptrs_t *)elem, compare)
+
+/**
+ ** Function prototypes
+ **/
+
+/* Add a new element to the tail of a doubly linked list.
+ */
+void kl_enqueue(
+       element_t**     /* ptr to head of list */,
+       element_t*      /* ptr to element to add to the list */);
+
+/* Remove an element from the head of a doubly linked list. A pointer
+ * to the element will be returned. In the event that the list is
+ * empty, a NULL pointer will be returned.
+ */
+element_t *kl_dequeue(
+       element_t**     /* ptr to list head (first item removed) */);
+
+/* Checks to see if a particular element is in a list. If it is, a
+ * value of one (1) will be returned. Otherwise, a value of zero (0)
+ * will be returned.
+ */
+int kl_findqueue(
+       element_t**     /* ptr to head of list */,
+       element_t*      /* ptr to element to find on list */);
+
+/* Walks through a list of pointers to queues and looks for a
+ * particular list.
+ */
+int kl_findlist_queue(
+       list_of_ptrs_t**        /* ptr to list of lists */,
+       list_of_ptrs_t*         /* ptr to list to look for */,
+       int(*)(void *, void *)  /* ptr to compare function */);
+
+/* Remove specified element from doubly linked list.
+ */
+void kl_remqueue(
+       element_t**             /* ptr to head of list */,
+       element_t*              /* ptr to element to remove from list */);
+
+#endif /* __KL_QUEUE_H */
diff --git a/kdb/modules/lcrash/kl_stabs.h b/kdb/modules/lcrash/kl_stabs.h
new file mode 100644 (file)
index 0000000..6d0e072
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * $Id: kl_stabs.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_STABS_H
+#define __KL_STABS_H
+
+/* STABS specific types
+ */
+#define STAB_XSTRUCT   100     /* Cross referense to STAB_STRUCT */
+#define STAB_XUNION    101     /* Cross referense to STAB_UNIONB */
+#define STAB_XENUM     102     /* Cross referense to STAB_ENUM */
+
+/* Structure allocated for every namelist. A namelist can be either an
+ * object file (.o or executible), or it can be an archive (.a).
+ */
+typedef struct st_nmlist_s {
+       char            *sts_filename;  /* disk file name */
+       short            sts_type;      /* ST_OBJ or ST_AR */
+       short            sts_nfiles;    /* number of source/object files */
+} st_nmlist_t;
+
+/* Values for type field
+ */
+#define ST_OBJ 1       /* object file (.o or executible) */
+#define ST_AR  2       /* archive */
+
+/* Stab entry type Flags. For determining which stab entries to
+ * capture from the symbol table.
+ */
+#define ST_UNDF                0x0001
+#define ST_SO          0x0002
+#define ST_LSYM                0x0004
+#define ST_GSYM                0x0008
+#define ST_PSYM                0x0010
+#define ST_STSYM       0x0020
+#define ST_LCSYM       0x0040
+#define ST_FUN         0x0080
+#define ST_BINCL       0x0100
+#define ST_EINCL       0x0200
+#define ST_EXCL                0x0400
+#define ST_SLINE       0x0800
+#define ST_RSYM         0x2000
+#define ST_ALL         0xffff
+#define ST_DEFAULT     (ST_LSYM|ST_GSYM|ST_FUN)
+
+#define N_UNDF                 0
+
+/* Structures that allow us to selectively cycle through only those BFD
+ * sections containing STAB data.
+ */
+typedef struct stab_sect_s {
+       char *stabsect_name;
+       char *strsect_name;
+} stab_sect_t;
+
+/* Local structure that contains the current type string (which may be
+ * just a part of the complete type defenition string) and the character
+ * index (current) pointer.
+ */
+typedef struct stab_str_s {
+        char            *str;
+        char            *ptr;
+} stab_str_t;
+
+/* Local structure containing global values that allow us to cycle
+ * through multiple object files without reinitializing.
+ */
+typedef struct st_global_s {
+       bfd             *abfd;          /* current bfd pointer */
+       int              type;          /* symbol entry type */
+       int              flags;         /* want flags */
+       int              flag;          /* current ST flag */
+       int              nmlist;        /* current namelist index */
+       int              srcfile;       /* current source file number */
+       int              incfile;       /* current include file */
+       int              symnum;        /* symbol entry number */
+       bfd_byte        *stabp;         /* beg of current string table */
+       bfd_byte        *stabs_end;     /* end of current string table */
+       int              staboff;       /* current stab table offset */
+       unsigned int     value;         /* value (e.g., function addr) */
+       int              stroffset;     /* offset in stab string table */
+       short            desc;          /* desc value (e.g, line number) */
+       stab_str_t       stab_str;      /* current stab string */
+} st_global_t;
+
+/* Macros for accessing the current global values
+ */
+#define G_abfd         G_values.abfd
+#define G_type                 G_values.type
+#define G_flags        G_values.flags
+#define G_flag         G_values.flag
+#define G_nmlist       G_values.nmlist
+#define G_srcfile      G_values.srcfile
+#define G_incfile      G_values.incfile
+#define G_symnum       G_values.symnum
+#define G_stabp         G_values.stabp
+#define G_stabs_end     G_values.stabs_end
+#define G_staboff      G_values.staboff
+#define G_value        G_values.value
+#define G_stroffset    G_values.stroffset
+#define G_desc         G_values.desc
+#define G_stab_str             G_values.stab_str
+#define CUR_CHAR       G_stab_str.ptr
+
+#endif /* __KL_STABS_H */
diff --git a/kdb/modules/lcrash/kl_stringtab.h b/kdb/modules/lcrash/kl_stringtab.h
new file mode 100644 (file)
index 0000000..c9b6437
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * $Id: kl_stringtab.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libutil.
+ * A library which provides auxiliary functions.
+ * libutil is part of lkcdutils -- utilities for Linux kernel crash dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_STRINGTAB_H
+#define __KL_STRINGTAB_H
+
+/* The string table structure
+ *
+ * String space is allocated from 4K blocks which are allocated
+ * as needed. The first four bytes of each block are reserved so
+ * that the blocks can be chained together (to make it easy to free
+ * them when the string table is no longer necessary).
+ */
+typedef struct string_table_s {
+       int             num_strings;
+       void           *block_list;
+} string_table_t;
+
+#define NO_STRINGTAB    0
+#define USE_STRINGTAB   1
+
+/**
+ ** Function prototypes
+ **/
+
+/* Initialize a string table. Depending on the value of the flag
+ * parameter, either temporary or permenent blocks will be used.
+ * Upon success, a pointer to a string table will be returned.
+ * Otherwise, a NULL pointer will be returned.
+ */
+string_table_t *kl_init_string_table(
+       int                             /* flag (K_TEMP/K_PERM)*/);
+
+/* Free all memory blocks allocated for a particular string table
+ * and then free the table itself.
+ */
+void kl_free_string_table(
+       string_table_t* /* pointer to string table */);
+
+/* Search for a string in a string table. If the string does not
+ * exist, allocate space from the string table and add the string.
+ * In either event, a pointer to the string (from the table) will
+ * be returned.
+ */
+char *kl_get_string(
+       string_table_t* /* pointer to string table */,
+       char*           /* string to get/add from/to string table */,
+       int             /* flag (K_TEMP/K_PERM)*/);
+
+#endif /* __KL_STRINGTAB_H */
diff --git a/kdb/modules/lcrash/kl_sym.h b/kdb/modules/lcrash/kl_sym.h
new file mode 100644 (file)
index 0000000..be93ba7
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * $Id: kl_sym.h 1233 2005-09-10 08:01:11Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_SYM_H
+#define __KL_SYM_H
+
+/* The syment struct contains information about kernel symbols (text,
+ * data, etc.). The first field in syment_t is a btnode_s sruct. This
+ * allows the generic binary search tree routines, insert_tnode() and
+ * find_tnode(), to be used.
+ */
+typedef struct syment_s {
+       btnode_t                s_bt;      /* Must be first */
+       struct syment_s        *s_next;    /* For linked lists */
+       struct syment_s        *s_prev;    /* For linked lists */
+       kaddr_t                 s_addr;    /* vaddr of symbol */
+       kaddr_t                 s_end;     /* end address of symbol */
+       int                     s_type;    /* text, data */
+       struct syment_s        *s_forward; /* For linked lists */
+} syment_t;
+
+#define s_name s_bt.bt_key
+
+#define SYM_GLOBAL_TEXT        1
+#define SYM_LOCAL_TEXT 2
+#define SYM_LOCORE_TEXT        3
+#define SYM_GLOBAL_DATA        4
+#define SYM_LOCAL_DATA 5
+#define SYM_ABS        6
+#define SYM_UNK        9
+#define SYM_KSYM       10
+#define SYM_KSYM_TEXT   11
+#define SYM_KALLSYMS    12
+
+#define SYM_MAP_ANY            0
+#define SYM_MAP_FILE           1
+#define SYM_MAP_KSYM           2
+#define SYM_MAP_MODULE                 3
+#define SYM_MAP_KALLSYMS       4
+
+#define KL_KERNEL_MODULE  "kernel_module"
+#define KL_S_BSS          ".bss.start"
+#define KL_E_BSS          ".bss.end"
+#define KL_S_DATA         ".data.start"
+#define KL_E_DATA         ".data.end"
+#define KL_S_RODATA       ".rodata.start"
+#define KL_E_RODATA       ".rodata.end"
+#define KL_S_TEXT         ".text.start"
+#define KL_E_TEXT         ".text.end"
+#define KL_SYM_END        "__end__"
+
+
+#define KL_SYMBOL_NAME_LEN 256
+
+/*
+ * Struct containing symbol table information
+ */
+typedef struct symtab_s {
+       int               symcnt;       /* Number of symbols */
+       int               symaddrcnt;   /* Number of symbol addrs to track */
+       syment_t        **symaddrs;     /* Table of symbols by address */
+       btnode_t         *symnames;     /* tree of symbols by name */
+       syment_t         *text_list;    /* Linked list of text symbols */
+       syment_t         *data_list;    /* Linked list of data symbols */
+} symtab_t;
+
+
+/* support of further mapfiles besides System.map */
+typedef struct maplist_s {
+       struct maplist_s   *next;
+       int                maplist_type;  /* type of maplist */
+       char               *mapfile;      /* name of mapfile */
+       char              *modname;      /* set if map belongs to a module */
+       symtab_t           *syminfo;
+} maplist_t;
+
+
+/* API Function prototypes
+ */
+int  kl_read_syminfo(maplist_t*);
+int  kl_free_syminfo(char*);
+void kl_free_symtab(symtab_t*);
+void kl_free_syment_list(syment_t*);
+void kl_free_maplist(maplist_t*);
+syment_t *kl_get_similar_name(char*, char*, int*, int*);
+syment_t *kl_lkup_symname(char*);
+syment_t *_kl_lkup_symname(char*, int, size_t len);
+#define KL_LKUP_SYMNAME(NAME, TYPE, LEN) _kl_lkup_symname(NAME, TYPE, LEN)
+syment_t *kl_lkup_funcaddr(kaddr_t);
+syment_t *kl_lkup_symaddr(kaddr_t);
+syment_t *kl_lkup_symaddr_text(kaddr_t);
+syment_t *_kl_lkup_symaddr(kaddr_t, int);
+#define KL_LKUP_SYMADDR(KADDR, TYPE) _kl_lkup_symaddr(KADDR, TYPE)
+kaddr_t kl_symaddr(char *      /* symbol name */);
+kaddr_t kl_symptr(char *       /* symbol name */);
+kaddr_t kl_funcaddr(kaddr_t     /* pc value */);
+char *kl_funcname(kaddr_t      /* pc value */);
+int kl_funcsize(kaddr_t         /* pc value */);
+int kl_symsize(syment_t*);
+syment_t *kl_alloc_syment(kaddr_t, kaddr_t, int, const char*);
+void kl_insert_symbols(symtab_t*, syment_t*);
+int  kl_insert_artificial_symbols(symtab_t*, syment_t**, kl_modinfo_t*);
+int  kl_convert_symbol(kaddr_t*, int*, char, kl_modinfo_t*);
+int  kl_load_sym(char*);
+int  kl_print_symtables(char*, char*, int, int);
+void kl_print_symbol(kaddr_t, syment_t*, int);
+
+/* flag for use by kl_print_symbol() and kl_print_syminfo()
+ */
+#define KL_SYMWOFFSET    (0x01)  /* with offset field */
+#define KL_SYMFULL       (0x02)  /* print detailed syminfo */
+#define KL_SYMBYNAME     (0x04)  /* print symbol sorted by name */
+
+#endif /* __KL_SYM_H */
diff --git a/kdb/modules/lcrash/kl_task.h b/kdb/modules/lcrash/kl_task.h
new file mode 100644 (file)
index 0000000..3aa2a1a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * $Id: kl_task.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002, 2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_TASK_H
+#define __KL_TASK_H
+
+extern kaddr_t deftask;
+
+/* Function prototypes
+ */
+k_error_t kl_set_deftask(kaddr_t);
+int kl_parent_pid(void *);
+kaddr_t kl_pid_to_task(kaddr_t);
+k_error_t kl_get_task_struct(kaddr_t, int, void *);
+kaddr_t kl_kernelstack(kaddr_t);
+kaddr_t kl_first_task(void);
+kaddr_t kl_next_task(void *);
+kaddr_t kl_prev_task(void *);
+kaddr_t kl_pid_to_task(kaddr_t);
+int kl_task_size(kaddr_t);
+
+#endif /* __KL_TASK_H */
diff --git a/kdb/modules/lcrash/kl_typeinfo.h b/kdb/modules/lcrash/kl_typeinfo.h
new file mode 100644 (file)
index 0000000..601eb68
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * $Id: kl_typeinfo.h 1259 2006-04-25 18:33:20Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2006 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_TYPEINFO_H
+#define __KL_TYPEINFO_H
+
+#define KLT_BASE         0x001
+#define KLT_STRUCT       0x002
+#define KLT_UNION        0x004
+#define KLT_ENUMERATION  0x008
+#define KLT_MEMBER       0x010
+#define KLT_ARRAY        0x020
+#define KLT_POINTER      0x040
+#define KLT_TYPEDEF      0x080
+#define KLT_FUNCTION     0x100
+#define KLT_VARIABLE     0x200
+#define KLT_SRCFILE      0x400
+#define KLT_SUBRANGE     0x800
+#define KLT_INCOMPLETE   0x4000
+#define KLT_UNKNOWN      0x8000
+#define KLT_TYPE       (KLT_BASE|KLT_STRUCT|KLT_UNION|KLT_ENUMERATION)
+#define KLT_TYPES      (KLT_BASE|KLT_STRUCT|KLT_UNION|KLT_ENUMERATION|KLT_TYPEDEF)
+
+#define IS_TYPE(T)      ((T) & KLT_TYPE)
+#define IS_STRUCT(T)    ((T) & KLT_STRUCT)
+#define IS_UNION(T)     ((T) & KLT_UNION)
+#define IS_ENUM(T)      ((T) & KLT_ENUM)
+#define IS_MEMBER(T)    ((T) & KLT_MEMBER)
+#define IS_POINTER(T)   ((T) & KLT_POINTER)
+#define IS_TYPEDEF(T)   ((T) & KLT_TYPEDEF)
+
+#define TYP_SETUP_FLG                  0x01
+#define TYP_TYPESTRING_FLG     0x02
+#define TYP_INCOMPLETE_FLG     0x04
+#define TYP_XREFERENCE_FLG     0x08
+#define TYP_ANONYMOUS_FLG      0x10 /* Denotes anonymous union or struct */
+
+#define NO_INDENT           0x01000000
+#define SUPPRESS_NAME       0x02000000
+#define SUPPRESS_NL         0x04000000
+#define SUPPRESS_SEMI_COLON 0x08000000
+#define NO_REALTYPE         0x10000000
+
+extern int numnmlist;
+
+#define KL_TYPEINFO()  (numnmlist)
+
+typedef struct kltype_s {
+       char                    *kl_name;         /* type name */
+        char                    *kl_typestr;      /* 'typecast' string */
+       void                    *kl_ptr;          /* ptr to arch typeinfo */
+        int                      kl_flags;        /* (e.g., STAB_FLG) */
+        int                      kl_type;         /* (e.g., KLT_TYPEDEF) */
+        int                      kl_offset;       /* offset to 1st byte */
+        int                      kl_size;         /* number of bytes */
+        int                      kl_bit_offset;   /* offset to 1st data bit */
+        int                      kl_bit_size;     /* total num of data bits */
+        int                      kl_encoding;     /* for base value types */
+        int                      kl_low_bounds;   /* for arrays */
+        int                      kl_high_bounds;  /* for arrays */
+        unsigned int             kl_value;        /* enum value, etc. */
+        struct kltype_s         *kl_member;       /* struct/union member list */
+       struct kltype_s         *kl_next;         /* hash lists, etc. */
+       struct kltype_s         *kl_realtype;     /* pointer to real type */
+       struct kltype_s         *kl_indextype;    /* pointer to index_type */
+       struct kltype_s         *kl_elementtype;  /* pointer to element_type */
+} kltype_t;
+
+/* Flag values
+ */
+#define K_HEX            0x1
+#define K_OCTAL          0x2
+#define K_BINARY         0x4
+#define K_NO_SWAP        0x8
+
+/* Base type encoding values
+ */
+#define ENC_CHAR       0x01
+#define ENC_SIGNED     0x02
+#define ENC_UNSIGNED   0x04
+#define ENC_FLOAT      0x08
+#define ENC_ADDRESS    0x10
+#define ENC_UNDEFINED  0x20
+
+/* Maximum number of open namelists
+ */
+#define MAXNMLIST 10
+
+typedef struct nmlist_s {
+       int              index;
+       char            *namelist;
+       void            *private;       /* pointer to private control struct */
+       string_table_t  *stringtab;
+} nmlist_t;
+
+extern nmlist_t nmlist[];
+extern int numnmlist;
+extern int curnmlist;
+
+#define KL_TYPESTR_STRUCT "struct"
+#define KL_TYPESTR_UNION  "union"
+#define KL_TYPESTR_ENUM   "enum"
+#define KL_TYPESTR_VOID   "void"
+
+/* Function prototypes
+ */
+kltype_t *kl_find_type(
+       char *          /* type name */,
+       int             /* type number */);
+
+kltype_t *kl_find_next_type(
+       kltype_t *      /* kltype_t pointer */,
+       int             /* type number */);
+
+kltype_t *kl_first_type(
+       int             /* type number */);
+
+kltype_t *kl_next_type(
+       kltype_t *      /* kltype_t pointer */);
+
+kltype_t *kl_prev_type(
+       kltype_t *      /* kltype_t pointer */);
+
+kltype_t *kl_realtype(
+       kltype_t *      /* kltype_t pointer */,
+       int             /* type number */);
+
+kltype_t *kl_find_typenum(
+       uint64_t        /* private typenumber */);
+
+int kl_get_first_similar_typedef(
+       char *          /* type name */,
+       char *          /* fullname */);
+
+int kl_type_size(
+       kltype_t *      /* kltype_t pointer */);
+
+int kl_struct_len(
+       char *          /* struct name */);
+
+kltype_t *kl_get_member(
+       kltype_t *      /* kltype_t pointer */,
+       char *          /* member name */);
+
+int kl_get_member_offset(
+       kltype_t *  /* kltype_t pointer */,
+       char *          /* member name */);
+
+int kl_is_member(
+       char *          /* struct name */,
+       char *          /* member name */);
+
+kltype_t *kl_member(
+       char *          /* struct name */,
+       char *          /* member name */);
+
+int kl_member_offset(
+       char *          /* struct name */,
+       char *          /* member name */);
+
+int kl_member_size(
+       char *          /* struct name */,
+       char *          /* member name */);
+
+/* cpw: get rid of last arguent FILE * */
+void kl_print_member(void *, kltype_t *, int, int);
+void kl_print_pointer_type(void *, kltype_t *, int, int);
+void kl_print_function_type(void *, kltype_t *, int, int);
+void kl_print_array_type(void *, kltype_t *, int, int);
+void kl_print_enumeration_type(void *, kltype_t *, int, int);
+void kl_print_base_type(void *, kltype_t *, int, int);
+void kl_print_type(void *, kltype_t *, int, int);
+void kl_print_struct_type(void *, kltype_t *, int, int);
+void kl_print_base_value(void *, kltype_t *, int);
+
+void kl_print_type(
+       void *          /* pointer to data */,
+       kltype_t *      /* pointer to type information */,
+       int             /* indent level */,
+       int             /* flags */);
+
+#endif /* __KL_TYPEINFO_H */
diff --git a/kdb/modules/lcrash/kl_types.h b/kdb/modules/lcrash/kl_types.h
new file mode 100644 (file)
index 0000000..3213a3f
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * $Id: kl_types.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __KL_TYPES_H
+#define __KL_TYPES_H
+
+/* The following typedef should be used for variables or return values
+ * that contain kernel virtual or physical addresses. It should be sized
+ * such that it can hold both pointers of 64 bit architectures as well as
+ * pointers from 32 bit architectures.
+ */
+typedef unsigned long kaddr_t;
+
+/* The following typedef should be used when converting a pointer value
+ * (either kernel or application) to an unsigned value for pointer
+ * calculations.
+ */
+typedef unsigned long  uaddr_t;
+
+/* KLIB error type
+ */
+typedef uint64_t       k_error_t;
+
+/* Typedef that allows a single fprintf() call to work for both
+ * 32-bit and 64-bit pointer values.
+ */
+#define UADDR(X) ((kaddr_t)X)
+#define UADDR64(X) ((kaddr_t)X))
+/* #define UADDR(X) ((uaddr_t)X) */
+/* #define UADDR64(X) ((uint64_t)((uaddr_t)X)) */
+
+
+/* cpw */
+/* was: #include <asm/kl_types.h> */
+#include "asm/kl_types.h"
+
+#endif /* __KL_TYPES_H */
diff --git a/kdb/modules/lcrash/klib.h b/kdb/modules/lcrash/klib.h
new file mode 100644 (file)
index 0000000..70d930e
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * $Id: klib.h 1336 2006-10-23 23:27:06Z tjm $
+ *
+ * This file is part of libklib.
+ * A library which provides access to Linux system kernel dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, NEC, and others
+ *
+ * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+/*
+ * klib.h -- Interface of the klib library, a library for access to
+ *           Linux system memory dumps.
+ */
+
+#ifndef __KLIB_H
+#define __KLIB_H
+
+/* Include header files
+ */
+#if 0
+ /* cpw: don't include all this: */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <setjmp.h>
+#include <strings.h>
+#include <errno.h>
+#include <ctype.h>
+#include <bfd.h>
+#include <assert.h>
+#endif
+
+/* cpw: change all the below includes form the < > form to " " */
+
+/* Include libutil header
+ */
+#include "kl_lib.h"
+
+/* Include libklib header files
+ */
+#include "kl_types.h"
+#include "kl_error.h"
+#include "kl_dump.h"
+#include "kl_mem.h"
+#include "kl_cmp.h"
+#include "kl_typeinfo.h"
+#include "kl_module.h"
+#include "kl_sym.h"
+#include "kl_bfd.h"
+#include "kl_debug.h"
+#include "kl_stabs.h"
+#include "kl_dwarfs.h"
+#include "kl_task.h"
+#include "kl_dump_arch.h"
+
+
+#ifndef TRUE
+# define TRUE  1
+#endif
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#ifndef MIN
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#endif
+#ifndef MAX
+#define MAX(x,y) (((x)>(y))?(x):(y))
+#endif
+
+#define KL_NR_CPUS 128
+
+/* We have to distinc between HOST_ARCH_* and DUMP_ARCH_*. These two classes of
+ * macros are used througout the code for conditional compilation.
+ * Additional we have following macros for comparison and switch statements.
+ */
+#define KL_ARCH_UNKNOWN          0
+#define KL_ARCH_ALPHA            1
+#define KL_ARCH_ARM              2
+#define KL_ARCH_I386             3
+#define KL_ARCH_IA64             4
+#define KL_ARCH_M68K             5
+#define KL_ARCH_MIPS             6
+#define KL_ARCH_MIPS64           7
+#define KL_ARCH_PPC              8
+#define KL_ARCH_S390             9
+#define KL_ARCH_SH              10
+#define KL_ARCH_SPARK           11
+#define KL_ARCH_SPARK64         12
+#define KL_ARCH_S390X           13
+#define KL_ARCH_PPC64           14
+#define KL_ARCH_X86_64          15
+#define KL_ARCH_IA64_SN2        16
+#define KL_ARCH_IA64_DIG        17
+#define KL_ARCH_IA64_HPSIM      18
+#define KL_ARCH_IA64_HPZX1      19
+#define KL_ARCH_S390SA          20
+
+#define KL_LIVE_SYSTEM        1000
+
+#define ARCH_IS_IA64(A) \
+       ((A==KL_ARCH_IA64)|| \
+        (A==KL_ARCH_IA64_SN2)|| \
+        (A==KL_ARCH_IA64_DIG)|| \
+        (A==KL_ARCH_IA64_HPSIM)|| \
+        (A==KL_ARCH_IA64_HPZX1))
+
+#ifdef HOST_ARCH_ALPHA
+# define KL_HOST_ARCH KL_ARCH_ALPHA
+#endif
+#ifdef HOST_ARCH_ARM
+# define KL_HOST_ARCH KL_ARCH_ARM
+#endif
+#ifdef HOST_ARCH_I386
+# define KL_HOST_ARCH KL_ARCH_I386
+#endif
+#ifdef HOST_ARCH_IA64
+# define KL_HOST_ARCH KL_ARCH_IA64
+#endif
+#ifdef HOST_ARCH_S390
+# define KL_HOST_ARCH KL_ARCH_S390
+#endif
+#ifdef HOST_ARCH_S390X
+# define KL_HOST_ARCH KL_ARCH_S390X
+#endif
+#ifdef HOST_ARCH_PPC64
+#define KL_HOST_ARCH KL_ARCH_PPC64
+#endif
+#ifdef HOST_ARCH_X86_64
+#define KL_HOST_ARCH KL_ARCH_X86_64
+#endif
+
+#define KL_ARCH_STR_ALPHA      "alpha"
+#define KL_ARCH_STR_ARM                "arm"
+#define KL_ARCH_STR_I386       "i386"
+#define KL_ARCH_STR_IA64       "ia64"
+#define KL_ARCH_STR_S390       "s390"
+#define KL_ARCH_STR_S390X      "s390x"
+#define KL_ARCH_STR_PPC64      "ppc64"
+#define KL_ARCH_STR_X86_64     "x86_64"
+#define KL_ARCH_STR_IA64_SN2   "sn2"
+#define KL_ARCH_STR_UNKNOWN    "unknown"
+
+/* for endianess of dump and host arch
+ */
+#define KL_UNKNOWN_ENDIAN  0x00
+#define KL_LITTLE_ENDIAN   0x01
+#define KL_BIG_ENDIAN      0x02
+
+/* macros for handling of different Kernel versions
+ */
+#define LINUX_2_2_X(R) (((R) & 0xffff00) == 0x020200)
+#define LINUX_2_2_16    0x020210
+#define LINUX_2_2_17    0x020211
+#define LINUX_2_4_X(R) (((R) & 0xffff00) == 0x020400)
+#define LINUX_2_4_0    0x020400
+#define LINUX_2_4_4     0x020404
+#define LINUX_2_4_15    0x02040f
+#define LINUX_2_6_X(R) (((R) & 0xffff00) == 0x020600)
+#define LINUX_2_6_0     0x020600
+
+/* libklib flags
+ */
+#define KL_FAILSAFE_FLG     0x0001
+#define KL_NOVERIFY_FLG     0x0002
+#define KL_SILENT_FLG      0x0004
+#define KL_SAVETYPES_FLG    0x0008
+#define KL_USETYPES_FLG            0x0010
+
+/* macros for backward compatibility
+ */
+#define NUM_PHYSPAGES  KLP->dump->mem.num_physpages
+#define MEM_MAP        KLP->dump->mem.mem_map
+#define KL_HIGH_MEMORY KLP->dump->mem.high_memory
+#define KL_INIT_MM     KLP->dump->mem.init_mm
+#define KL_NUM_CPUS    KLP->dump->mem.num_cpus
+#define KL_PGDAT_LIST  KLP->dump->mem.pgdat_list
+
+/* macros for better use of dump architecture dependent functions
+ */
+
+/* read integer value from buffer */
+#define KL_GET_PTR(ptr)    (*KLP->dump->func.get_ptr)(ptr)
+#define KL_GET_LONG(ptr)   ((int64_t) KL_GET_PTR(ptr))
+#define KL_GET_ULONG(ptr)  KL_GET_PTR(ptr)
+#define KL_GET_UINT8(ptr)  (*KLP->dump->func.get_uint8)(ptr)
+#define KL_GET_UINT16(ptr) (*KLP->dump->func.get_uint16)(ptr)
+#define KL_GET_UINT32(ptr) (*KLP->dump->func.get_uint32)(ptr)
+#define KL_GET_UINT64(ptr) (*KLP->dump->func.get_uint64)(ptr)
+#define KL_GET_INT8(ptr)   ((int8_t) KL_GET_UINT8(ptr))
+#define KL_GET_INT16(ptr)  ((int16_t) KL_GET_UINT16(ptr))
+#define KL_GET_INT32(ptr)  ((int32_t) KL_GET_UINT32(ptr))
+#define KL_GET_INT64(ptr)  ((int64_t) KL_GET_UINT64(ptr))
+
+/* read integer value from dump (without address mapping)
+ * Use these functions sparsely, e.g. before address translation
+ * is properly set up.
+ */
+#define KL_READ_PTR(addr)    (*KLP->dump->func.read_ptr)(addr)
+#define KL_READ_LONG(addr)   ((int64_t) KL_READ_PTR(addr))
+#define KL_READ_ULONG(addr)  KL_READ_PTR(addr)
+#define KL_READ_UINT8(addr)  (*KLP->dump->func.read_uint8)(addr)
+#define KL_READ_UINT16(addr) (*KLP->dump->func.read_uint16)(addr)
+#define KL_READ_UINT32(addr) (*KLP->dump->func.read_uint32)(addr)
+#define KL_READ_UINT64(addr) (*KLP->dump->func.read_uint64)(addr)
+#define KL_READ_INT8(addr)   ((int8_t) KL_READ_UINT8(addr))
+#define KL_READ_INT16(addr)  ((int16_t) KL_READ_UINT16(addr))
+#define KL_READ_INT32(addr)  ((int32_t) KL_READ_UINT32(addr))
+#define KL_READ_INT64(addr)  ((int64_t) KL_READ_UINT64(addr))
+
+/* read integer value from dump (from virtual address) doing address mapping */
+#define KL_VREAD_PTR(addr)    (*KLP->dump->func.vread_ptr)(addr)
+#define KL_VREAD_LONG(addr)   ((int64_t) KL_VREAD_PTR(addr))
+#define KL_VREAD_ULONG(addr)  KL_VREAD_PTR(addr)
+#define KL_VREAD_UINT8(addr)  (*KLP->dump->func.vread_uint8)(addr)
+#define KL_VREAD_UINT16(addr) (*KLP->dump->func.vread_uint16)(addr)
+#define KL_VREAD_UINT32(addr) (*KLP->dump->func.vread_uint32)(addr)
+#define KL_VREAD_UINT64(addr) (*KLP->dump->func.vread_uint64)(addr)
+#define KL_VREAD_INT8(addr)   ((int8_t) KL_VREAD_UINT8(addr))
+#define KL_VREAD_INT16(addr)  ((int16_t) KL_VREAD_UINT16(addr))
+#define KL_VREAD_INT32(addr)  ((int32_t) KL_VREAD_UINT32(addr))
+#define KL_VREAD_INT64(addr)  ((int64_t) KL_VREAD_UINT64(addr))
+
+/* determine start of stack */
+#define KL_KERNELSTACK_UINT64 (*KLP->dump->arch.kernelstack)
+/* map virtual adress to physical one */
+#define KL_VIRTOP (*KLP->dump->arch.virtop)
+/* travers page table */
+#define KL_MMAP_VIRTOP (*KLP->dump->arch.mmap_virtop)
+/* check whether address points to valid physical memory */
+#define KL_VALID_PHYSMEM (*KLP->dump->arch.valid_physmem)
+/* determine next valid physical address */
+#define KL_NEXT_VALID_PHYSADDR (*KLP->dump->arch.next_valid_physaddr)
+/* XXX */
+#define KL_FIX_VADDR (*KLP->dump->arch.fix_vaddr)
+/* write dump_header_asm_t */
+#define KL_WRITE_DHA (*KLP->dump->arch.write_dha)
+/* size of dump_header_asm_t */
+#define KL_DHA_SIZE (KLP->dump->arch.dha_size)
+/* init virtual to physical address mapping */
+#define KL_INIT_VIRTOP (KLP->dump->arch.init_virtop)
+
+
+/* macros for easier access to dump specific values */
+#define KL_CORE_TYPE            KLP->dump->core_type
+#define KL_CORE_FD              KLP->dump->core_fd
+#define KL_ARCH                 KLP->dump->arch.arch
+#define KL_PTRSZ                KLP->dump->arch.ptrsz
+#define KL_NBPW                 (KL_PTRSZ/8)
+#define KL_BYTE_ORDER           KLP->dump->arch.byteorder
+#define KL_PAGE_SHIFT           KLP->dump->arch.pageshift
+#define KL_PAGE_SIZE            KLP->dump->arch.pagesize
+#define KL_PAGE_MASK            KLP->dump->arch.pagemask
+#define KL_PAGE_OFFSET          KLP->dump->arch.pageoffset
+#define KL_STACK_OFFSET         KLP->dump->arch.kstacksize
+#define IS_BIG_ENDIAN()         (KL_BYTE_ORDER == KL_BIG_ENDIAN)
+#define IS_LITTLE_ENDIAN()      (KL_BYTE_ORDER == KL_LITTLE_ENDIAN)
+#define KL_LINUX_RELEASE        KLP->dump->mem.linux_release
+#define KL_KERNEL_FLAGS         KLP->dump->mem.kernel_flags
+
+#if 0
+/* cpw: don't need all this dump file stuff: */
+/* macros to access input files */
+#define KL_MAP_FILE       KLP->dump->map
+#define KL_DUMP_FILE      KLP->dump->dump
+#define KL_KERNTYPES_FILE KLP->kerntypes
+
+#define CORE_IS_KMEM (KL_CORE_TYPE == dev_kmem)
+#define CORE_IS_DUMP ((KL_CORE_TYPE > dev_kmem) && (KL_CORE_TYPE <= unk_core))
+
+
+/* Generic dump header structure (the first three members of
+ * dump_header and dump_header_asm are the same).
+ */
+typedef struct generic_dump_header_s {
+        uint64_t        magic_number;
+        uint32_t        version;
+        uint32_t        header_size;
+} generic_dump_header_t;
+
+/* Some macros for making it easier to access the generic header
+ * information in a dump_header or dump_header_asm stuct.
+ */
+#define DHP(dh)                 ((generic_dump_header_t*)(dh))
+#define DH_MAGIC(dh)            DHP(dh)->magic_number
+#define DH_VERSION(dh)          DHP(dh)->version
+#define DH_HEADER_SIZE(dh)      DHP(dh)->header_size
+
+extern kl_dump_header_t *DUMP_HEADER;
+extern void *DUMP_HEADER_ASM;
+#endif
+
+/* Struct to store some host architecture specific values
+ */
+typedef struct kl_hostarch_s {
+       int             arch;          /* KL_ARCH_ */
+       int             ptrsz;         /* 32 or 64 bit */
+       int             byteorder;     /* KL_LITTLE_ENDIAN or KL_BIG_ENDIAN */
+} kl_hostarch_t;
+
+/* Struct klib_s, contains all the information necessary for accessing
+ * information in the kernel. A pointer to a klib_t struct will be
+ * returned from libkern_init() if core dump analysis (or live system
+ * analysis) is possible.
+ *
+ */
+typedef struct klib_s {
+       int             k_flags;     /* Flags pertaining to klib_s struct */
+       kl_hostarch_t  *host;        /* host arch info */
+       kl_dumpinfo_t  *dump;        /* dump information */
+       maplist_t      *k_symmap;    /* symbol information */
+       kltype_t       *k_typeinfo;  /* type information */
+       char            *kerntypes;     /* pathname for kerntypes file */
+} klib_t;
+
+/* Structure to accomodate all debug formats */
+struct namelist_format_opns {
+       /* to open/setup the namelist file */
+       int (*open_namelist) (char *filename , int flags);
+       int (*setup_typeinfo)(void);
+};
+
+/*
+ * global variables
+ */
+
+/* Here we store almost everything, we need to know about a dump. */
+extern klib_t *KLP;
+
+/* macros to make live easier */
+#define MIP               KLP->dump
+#define STP               KLP->k_symmap
+#define TASK_STRUCT_SZ    (KLP->dump->mem.struct_sizes.task_struct_sz)
+#define MM_STRUCT_SZ      (KLP->dump->mem.struct_sizes.mm_struct_sz)
+#define PAGE_SZ           (KLP->dump->mem.struct_sizes.page_sz)
+#define MODULE_SZ         (KLP->dump->mem.struct_sizes.module_sz)
+#define NEW_UTSNAME_SZ    (KLP->dump->mem.struct_sizes.new_utsname_sz)
+#define SWITCH_STACK_SZ   (KLP->dump->mem.struct_sizes.switch_stack_sz)
+#define PT_REGS_SZ       (KLP->dump->mem.struct_sizes.pt_regs_sz)
+#define PGLIST_DATA_SZ    (KLP->dump->mem.struct_sizes.pglist_data_sz)
+#define RUNQUEUE_SZ       (KLP->dump->mem.struct_sizes.runqueue_sz)
+
+#if 0
+cpw: used for sial?
+/* klib_jbuf has to be defined outside libklib.
+ * Make sure to call setjmp(klib_jbuf) BEFORE kl_sig_setup() is called! */
+extern jmp_buf klib_jbuf;
+#endif
+
+/* Macros that eliminate the offset paramaters to the kl_uint() and kl_int()
+ * functions (just makes things cleaner looking)
+ */
+#define KL_UINT(p, s, m) kl_uint(p, s, m, 0)
+#define KL_INT(p, s, m) kl_int(p, s, m, 0)
+
+/* Macros for translating strings into long numeric values depending
+ * on the base of 's'.
+ */
+#define GET_VALUE(s, value) kl_get_value(s, NULL, 0, value)
+#define GET_HEX_VALUE(s) (kaddr_t)strtoull(s, (char**)NULL, 16)
+#define GET_DEC_VALUE(s) (unsigned)strtoull(s, (char**)NULL, 10)
+#define GET_OCT_VALUE(s) (unsigned)strtoull(s, (char**)NULL, 8)
+
+#define KL_SIGFLG_CORE          0x1
+#define KL_SIGFLG_SILENT        0x2
+#define KL_SIGFLG_LNGJMP        0x4
+
+/* Flag that tells kl_is_valid_kaddr() to perform a word aligned check
+ */
+#define WORD_ALIGN_FLAG         1
+
+#define ADDR_TO_PGNO(addr) ((addr - KL_PAGE_OFFSET) >> KL_PAGE_SHIFT);
+
+/* Generalized macros for pointing at different data types at particular
+ * offsets in kernel structs.
+ */
+/* #define K_ADDR(p, s, f)   ((uaddr_t)(p) + kl_member_offset(s, f)) */
+#define K_ADDR(p, s, f)   ((p) + kl_member_offset(s, f))
+#define K_PTR(p, s, f)    (K_ADDR((void*)p, s, f))
+#define CHAR(p, s, f)     (K_ADDR((char*)p, s, f))
+
+#define PTRSZ32 ((KL_PTRSZ == 32) ? 1 : 0)
+#define PTRSZ64 ((KL_PTRSZ == 64) ? 1 : 0)
+
+/* Function prototypes
+ */
+/* cpw: remove the last argument   FILE * */
+void kl_binary_print(uint64_t);
+void kl_print_bit_value(void *, int, int, int, int);
+void kl_print_char(void *, int);
+void kl_print_uchar(void *, int);
+void kl_print_int2(void *, int);
+void kl_print_uint2(void *, int);
+void kl_print_int4(void *, int);
+void kl_print_uint4(void *, int);
+void kl_print_float4(void *, int);
+void kl_print_int8(void *, int);
+void kl_print_uint8(void *, int);
+void kl_print_float8(void *, int);
+void kl_print_base(void *, int, int, int);
+void kl_print_string(char *);
+
+int kl_get_live_filenames(
+       char *                  /* pointer to buffer for map filename */,
+       char *                  /* pointer to buffer for dump filename */,
+       char *                  /* pointer to buffer for namelist filename */);
+
+int kl_init_klib(
+        char *                  /* map file name */,
+        char *                  /* dump file name */,
+        char *                  /* namelist file name */,
+        int                    /* system arch of memory in dump */,
+        int                    /* rwflag flag (/dev/mem only) */,
+       int                     /* Linux release */);
+
+void kl_free_klib(
+       klib_t *                /* Pointer to klib_s struct */);
+
+
+int kl_dump_retrieve(
+       char *                  /* dumpdev name */,
+       char *                  /* dumpdir name */,
+       int                     /* progress flag (zero or non-zero) */,
+       int                     /* debug flag (zero or non-zero) */);
+
+int kl_dump_erase(
+       char *                  /* dumpdev name */);
+
+uint64_t kl_strtoull(
+       char *                  /* string containing numeric value */,
+       char **                 /* pointer to pointer to bad char */,
+       int                     /* base */);
+
+int kl_get_value(
+       char *                  /* param */,
+       int *                   /* mode pointer */,
+       int                     /* number of elements */,
+       uint64_t *              /* pointer to value */);
+
+/* Functions for working with list_head structs
+ */
+kaddr_t kl_list_entry(kaddr_t, char *, char *);
+kaddr_t kl_list_next(kaddr_t);
+kaddr_t kl_list_prev(kaddr_t);
+
+int kl_sig_setup(int);
+
+void kl_set_curnmlist(
+       int                     /* index  of namelist */);
+
+int kl_open_namelist(
+       char *                  /* name of namelist */,
+       int                     /* flags */,
+       int                     /* kl_flags */);
+
+int   kl_get_structure(kaddr_t,  char*, size_t*, void**);
+uint64_t kl_get_bit_value(void*, unsigned int, unsigned int, unsigned int);
+void kl_s390tod_to_timeval(uint64_t, struct timeval*);
+
+#endif /* __KLIB_H */
diff --git a/kdb/modules/lcrash/lc_eval.h b/kdb/modules/lcrash/lc_eval.h
new file mode 100644 (file)
index 0000000..91a21b7
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * $Id: lc_eval.h 1122 2004-12-21 23:26:23Z tjm $
+ *
+ * This file is part of lcrash, an analysis tool for Linux memory dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, and others
+ *
+ * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *
+ * 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. See the file COPYING for more
+ * information.
+ */
+
+#ifndef __LC_EVAL_H
+#define __LC_EVAL_H
+
+typedef struct type_s {
+       int      flag;
+       union {
+               struct type_s   *next;
+               kltype_t        *kltp;
+       } un;
+} type_t;
+
+#define t_next un.next
+#define t_kltp un.kltp
+
+/* Structure to hold info on "tokens" extracted from eval and print
+ * command input strings.
+ */
+typedef struct token_s {
+       short           type;
+       short           operator;       /* if token is an operator */
+       char            *string;        /* string holding value or identifier */
+       char            *ptr;           /* pointer to start of token */
+       struct token_s  *next;          /* next token in the chain */
+} token_t;
+
+/* Structure returned by the eval() function containing the result
+ * of an expression evaluation. This struct is also used to build the
+ * parse tree for the expression.
+ */
+typedef struct node_s {
+       struct node_s   *next;          /* linked list pointer */
+       unsigned char    node_type;     /* type of node */
+       unsigned short   flags;         /* see below */
+       unsigned char    operator;      /* operator if node is type OPERATOR */
+       unsigned char    byte_size;     /* byte_size of base_type values */
+       char            *name;          /* name of variable or struct member */
+       /* value and address are uint64_t in lcrash, but for ia32 ... */
+       unsigned long long value;       /* numeric value or pointer */
+       unsigned long    address;       /* address (could be same as pointer) */
+       type_t          *type;          /* pointer to type related info */
+       char            *tok_ptr;       /* pointer to token in cmd string */
+       struct node_s   *left;          /* pointer to left child */
+       struct node_s   *right;         /* pointer to right child */
+} node_t;
+
+/* Token and Node types
+ */
+#define OPERATOR                         1
+#define NUMBER                   2
+#define INDEX                    3
+#define TYPE_DEF                 4
+#define VADDR                    5
+#define MEMBER                   6
+#define STRING                   7
+#define TEXT                     8
+#define CHARACTER                9
+#define EVAL_VAR                10
+
+/* Flag values
+ */
+#define STRING_FLAG           0x001
+#define ADDRESS_FLAG          0x002
+#define INDIRECTION_FLAG      0x004
+#define POINTER_FLAG          0x008
+#define MEMBER_FLAG           0x010
+#define BOOLIAN_FLAG          0x020
+#define KLTYPE_FLAG           0x040
+#define NOTYPE_FLAG           0x080
+#define UNSIGNED_FLAG         0x100
+#define VOID_FLAG             0x200
+
+/* Flag value for print_eval_error() function
+ */
+#define CMD_NAME_FLG             1  /* cmdname is not name of a command */
+#define CMD_STRING_FLG           2  /* cmdname is not name of a command */
+
+/* Expression operators in order of precedence.
+ */
+#define CONDITIONAL              1
+#define CONDITIONAL_ELSE          2
+#define LOGICAL_OR               3
+#define LOGICAL_AND              4
+#define BITWISE_OR               5
+#define BITWISE_EXCLUSIVE_OR      6
+#define BITWISE_AND              7
+#define EQUAL                    8
+#define NOT_EQUAL                9
+#define LESS_THAN               10
+#define GREATER_THAN            11
+#define LESS_THAN_OR_EQUAL      12
+#define GREATER_THAN_OR_EQUAL    13
+#define RIGHT_SHIFT             14
+#define LEFT_SHIFT              15
+#define ADD                     16
+#define SUBTRACT                17
+#define MULTIPLY                18
+#define DIVIDE                  19
+#define MODULUS                         20
+#define LOGICAL_NEGATION        21
+#define ONES_COMPLEMENT                 22
+#define PREFIX_INCREMENT        23
+#define PREFIX_DECREMENT        24
+#define POSTFIX_INCREMENT       25
+#define POSTFIX_DECREMENT       26
+#define CAST                    27
+#define UNARY_MINUS             28
+#define UNARY_PLUS              29
+#define INDIRECTION             30
+#define ADDRESS                         31
+#define SIZEOF                  32
+#define RIGHT_ARROW             33
+#define DOT                     34
+#define OPEN_PAREN             100
+#define CLOSE_PAREN            101
+#define OPEN_SQUARE_BRACKET    102
+#define CLOSE_SQUARE_BRACKET   103
+#define SEMI_COLON             104
+#define NOT_YET                 -1
+
+/* Errors codes primarily for use with eval (print) functions
+ */
+#define E_OPEN_PAREN           1100
+#define E_CLOSE_PAREN          1101
+#define E_BAD_STRUCTURE        1102
+#define E_MISSING_STRUCTURE    1103
+#define E_BAD_MEMBER           1104
+#define E_BAD_OPERATOR         1105
+#define E_BAD_OPERAND          1106
+#define E_MISSING_OPERAND      1107
+#define E_BAD_TYPE             1108
+#define E_NOTYPE               1109
+#define E_BAD_POINTER          1110
+#define E_BAD_INDEX            1111
+#define E_BAD_CHAR             1112
+#define E_BAD_STRING           1113
+#define E_END_EXPECTED         1114
+#define E_BAD_EVAR             1115  /* Bad eval variable */
+#define E_BAD_VALUE           1116
+#define E_NO_VALUE            1117
+#define E_DIVIDE_BY_ZERO       1118
+#define E_BAD_CAST             1119
+#define E_NO_ADDRESS           1120
+#define E_SINGLE_QUOTE         1121
+
+#define E_BAD_WHATIS           1197
+#define E_NOT_IMPLEMENTED      1198
+#define E_SYNTAX_ERROR         1199
+
+extern uint64_t eval_error;
+extern char *error_token;
+
+/* Function prototypes
+ */
+node_t *eval(char **, int);
+void print_eval_error(char *, char *, char *, uint64_t, int);
+void free_nodes(node_t *);
+
+/* Struct to hold information about eval variables
+ */
+typedef struct variable_s {
+       btnode_t         v_bt;      /* Must be first */
+       int              v_flags;
+       char            *v_exp;     /* What was entered on command line      */
+       char            *v_typestr; /* Actual type string after eval() call  */
+       node_t          *v_node;
+} variable_t;
+
+#define v_left v_bt.bt_left
+#define v_right v_bt.bt_right
+#define v_name v_bt.bt_key
+
+/* Flag values
+ */
+#define V_PERM          0x001  /* can't be unset - can be modified           */
+#define V_DEFAULT       0x002  /* set at startup                             */
+#define V_NOMOD         0x004  /* cannot be modified                         */
+#define V_TYPEDEF       0x008  /* contains typed data                        */
+#define V_REC_STRUCT    0x010  /* direct ref to struct/member (not pointer)  */
+#define V_STRING       0x020  /* contains ASCII string (no type)            */
+#define V_COMMAND      0x040  /* contains command string (no type)          */
+#define V_OPTION       0x080  /* contains option flag (e.g., $hexints)      */
+#define V_PERM_NODE     0x100  /* Don't free node after setting variable     */
+
+/* Variable table struct
+ */
+typedef struct vtab_s {
+       variable_t      *vt_root;
+       int              vt_count;
+} vtab_t;
+
+extern vtab_t *vtab;    /* Pointer to table of eval variable info    */
+
+/* Function Prototypes
+ */
+variable_t *make_variable(char *, char *, node_t *, int);
+void clean_variable(variable_t *);
+void free_variable(variable_t *);
+void init_variables(vtab_t *);
+int set_variable(vtab_t *, char *, char *, node_t *, int);
+int unset_variable(vtab_t *, variable_t *);
+variable_t *find_variable(vtab_t *, char *, int);
+kltype_t *number_to_type(node_t *);
+void free_eval_memory(void);
+/* cpw: was int print_eval_results(node_t *, FILE *, int); */
+int print_eval_results(node_t *, int);
+
+#endif /* __LC_EVAL_H */
index 38ec406..9e8930a 100644 (file)
@@ -4,6 +4,9 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
index 38fc10a..6c79d7c 100644 (file)
@@ -479,3 +479,25 @@ __initcall(kallsyms_init);
 
 EXPORT_SYMBOL(__print_symbol);
 EXPORT_SYMBOL_GPL(sprint_symbol);
+
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+
+const char *kdb_walk_kallsyms(loff_t *pos)
+{
+       static struct kallsym_iter kdb_walk_kallsyms_iter;
+       if (*pos == 0) {
+               memset(&kdb_walk_kallsyms_iter, 0, sizeof(kdb_walk_kallsyms_iter));
+               reset_iter(&kdb_walk_kallsyms_iter, 0);
+       }
+       while (1) {
+               if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
+                       return NULL;
+               ++*pos;
+               /* Some debugging symbols have no name.  Ignore them. */
+               if (kdb_walk_kallsyms_iter.name[0])
+                       return kdb_walk_kallsyms_iter.name;
+       }
+}
+#endif /* CONFIG_KDB */
index c8a4370..d23367e 100644 (file)
 #include <asm/system.h>
 #include <asm/sections.h>
 
+#ifdef CONFIG_KDB_KDUMP
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kdb.h>
+#endif
+
 /* Per cpu memory for storing cpu states in case of system crash. */
 note_buf_t* crash_notes;
 
@@ -1065,7 +1071,6 @@ void crash_kexec(struct pt_regs *regs)
 {
        int locked;
 
-
        /* Take the kexec_lock here to prevent sys_kexec_load
         * running on one cpu from replacing the crash kernel
         * we are using after a panic on a different cpu.
@@ -1078,9 +1083,19 @@ void crash_kexec(struct pt_regs *regs)
        if (!locked) {
                if (kexec_crash_image) {
                        struct pt_regs fixed_regs;
+
                        crash_setup_regs(&fixed_regs, regs);
                        crash_save_vmcoreinfo();
+                       /*
+                        * If we enabled KDB, we don't want to automatically
+                        * perform a kdump since KDB will be responsible for
+                        * executing kdb through a special 'kdump' command.
+                        */
+#ifdef CONFIG_KDB_KDUMP
+                       kdba_kdump_prepare(&fixed_regs);
+#else
                        machine_crash_shutdown(&fixed_regs);
+#endif
                        machine_kexec(kexec_crash_image);
                }
                locked = xchg(&kexec_lock, 0);
@@ -1088,6 +1103,7 @@ void crash_kexec(struct pt_regs *regs)
        }
 }
 
+
 static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
                            size_t data_len)
 {
index ca156e4..31cb920 100644 (file)
@@ -2505,12 +2505,23 @@ out:
        return -ERANGE;
 }
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+struct list_head *kdb_modules = &modules;      /* kdb needs the list of modules */
+#endif /* CONFIG_KDB */
+
 int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
                        char *name, char *module_name, int *exported)
 {
        struct module *mod;
+#ifdef CONFIG_KDB
+       int get_lock = !KDB_IS_RUNNING();
+#else
+#define        get_lock 1
+#endif
 
-       preempt_disable();
+       if (get_lock)
+               preempt_disable();
        list_for_each_entry(mod, &modules, list) {
                if (symnum < mod->num_symtab) {
                        *value = mod->symtab[symnum].st_value;
@@ -2519,12 +2530,14 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
                                KSYM_NAME_LEN);
                        strlcpy(module_name, mod->name, MODULE_NAME_LEN);
                        *exported = is_exported(name, mod);
-                       preempt_enable();
+                       if (get_lock)
+                               preempt_enable();
                        return 0;
                }
                symnum -= mod->num_symtab;
        }
-       preempt_enable();
+       if (get_lock)
+               preempt_enable();
        return -ERANGE;
 }
 
index db0290c..9dade3f 100644 (file)
@@ -21,6 +21,9 @@
 #include <linux/debug_locks.h>
 #include <linux/random.h>
 #include <linux/kallsyms.h>
+#ifdef CONFIG_KDB_KDUMP
+#include <linux/kdb.h>
+#endif
 
 int panic_on_oops;
 int tainted;
@@ -82,6 +85,11 @@ NORET_TYPE void panic(const char * fmt, ...)
        printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
        bust_spinlocks(0);
 
+#ifdef CONFIG_KDB_KDUMP
+       if (kdb_kdump_state == KDB_KDUMP_RESET) {
+               (void)kdb(KDB_REASON_OOPS, 999, get_irq_regs());
+       }
+#endif
        /*
         * If we have crashed and we have a crash kernel loaded let it handle
         * everything else.
index 25c8e5f..b6c071d 100644 (file)
@@ -441,6 +441,20 @@ void debugger_syslog_data(char *syslog_data[4])
 }
 #endif   /* CONFIG_DEBUG_KERNEL */
 
+#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 + log_buf_len;
+       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 /* CONFIG_KDB */
+
 /*
  * Call the console drivers on a range of log_buf
  */
index 8db15e0..03aae48 100644 (file)
@@ -8236,7 +8236,7 @@ void normalize_rt_tasks(void)
 
 #endif /* CONFIG_MAGIC_SYSRQ */
 
-#ifdef CONFIG_IA64
+#if    defined(CONFIG_IA64) || defined(CONFIG_KDB)
 /*
  * These functions are only useful for the IA64 MCA handling.
  *
@@ -9171,3 +9171,94 @@ struct cgroup_subsys cpuacct_subsys = {
        .subsys_id = cpuacct_subsys_id,
 };
 #endif /* CONFIG_CGROUP_CPUACCT */
+
+#ifdef CONFIG_KDB
+
+#include <linux/kdb.h>
+
+static void
+kdb_prio(char *name, struct rt_prio_array *array, kdb_printf_t xxx_printf,
+       unsigned int cpu)
+{
+       int pri, printed_header = 0;
+       struct task_struct *p;
+
+       xxx_printf("  %s rt bitmap: 0x%lx 0x%lx 0x%lx\n",
+               name,
+               array->bitmap[0], array->bitmap[1], array->bitmap[2]);
+
+       pri = sched_find_first_bit(array->bitmap);
+       if (pri < MAX_RT_PRIO) {
+               xxx_printf("   rt bitmap priorities:");
+               while (pri < MAX_RT_PRIO) {
+                       xxx_printf(" %d", pri);
+                       pri++;
+                       pri = find_next_bit(array->bitmap, MAX_RT_PRIO, pri);
+               }
+               xxx_printf("\n");
+       }
+
+       for (pri = 0; pri < MAX_RT_PRIO; pri++) {
+               int printed_hdr = 0;
+               struct list_head *head, *curr;
+
+               head = array->queue + pri;
+               curr = head->next;
+               while(curr != head) {
+                       struct task_struct *task;
+                       if (!printed_hdr) {
+                               xxx_printf("   queue at priority=%d\n", pri);
+                               printed_hdr = 1;
+                       }
+                       task = list_entry(curr, struct task_struct, rt.run_list);
+                       if (task)
+                               xxx_printf("    0x%p %d %s  time_slice:%d\n",
+                                  task, task->pid, task->comm,
+                                  task->rt.time_slice);
+                       curr = curr->next;
+               }
+       }
+       for_each_process(p) {
+               if (p->se.on_rq && (task_cpu(p) == cpu) &&
+                  (p->policy == SCHED_NORMAL)) {
+                       if (!printed_header) {
+                               xxx_printf("  sched_normal queue:\n");
+                               printed_header = 1;
+                       }
+                       xxx_printf("    0x%p %d %s pri:%d spri:%d npri:%d\n",
+                               p, p->pid, p->comm, p->prio,
+                               p->static_prio, p->normal_prio);
+               }
+       }
+}
+
+/* This code must be in sched.c because struct rq is only defined in this
+ * source.  To allow most of kdb to be modular, this code cannot call any kdb
+ * functions directly, any external functions that it needs must be passed in
+ * as parameters.
+ */
+
+void
+kdb_runqueue(unsigned long cpu, kdb_printf_t xxx_printf)
+{
+       struct rq *rq;
+
+       rq = cpu_rq(cpu);
+
+       xxx_printf("CPU%ld lock:%s curr:0x%p(%d)(%s)",
+                  cpu, (spin_is_locked(&rq->lock))?"LOCKED":"free",
+                  rq->curr, rq->curr->pid, rq->curr->comm);
+       if (rq->curr == rq->idle)
+               xxx_printf(" is idle");
+       xxx_printf("\n ");
+#ifdef CONFIG_SMP
+       xxx_printf(" cpu_load:%lu %lu %lu",
+                       rq->cpu_load[0], rq->cpu_load[1], rq->cpu_load[2]);
+#endif
+       xxx_printf(" nr_running:%lu nr_switches:%llu\n",
+                  rq->nr_running, (long long)rq->nr_switches);
+       kdb_prio("active", &rq->rt.active, xxx_printf, (unsigned int)cpu);
+}
+EXPORT_SYMBOL(kdb_runqueue);
+
+#endif /* CONFIG_KDB */
index c539f60..4bc78f4 100644 (file)
@@ -2596,3 +2596,52 @@ void __init signals_init(void)
 {
        sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC);
 }
+
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+/*
+ * kdb_send_sig_info
+ *
+ *     Allows kdb to send signals without exposing signal internals.
+ *
+ * Inputs:
+ *     t       task
+ *     siginfo signal information
+ *     seqno   current kdb sequence number (avoid including kdbprivate.h)
+ * Outputs:
+ *     None.
+ * Returns:
+ *     None.
+ * Locking:
+ *     Checks if the required locks are available before calling the main
+ *     signal code, to avoid kdb deadlocks.
+ * Remarks:
+ */
+void
+kdb_send_sig_info(struct task_struct *t, struct siginfo *info, int seqno)
+{
+       static struct task_struct *kdb_prev_t;
+       static int kdb_prev_seqno;
+       int sig, new_t;
+       if (!spin_trylock(&t->sighand->siglock)) {
+               kdb_printf("Can't do kill command now.\n"
+                       "The sigmask lock is held somewhere else in kernel, try again later\n");
+               return;
+       }
+       spin_unlock(&t->sighand->siglock);
+       new_t = kdb_prev_t != t || kdb_prev_seqno != seqno;
+       kdb_prev_t = t;
+       kdb_prev_seqno = seqno;
+       if (t->state != TASK_RUNNING && new_t) {
+               kdb_printf("Process is not RUNNING, sending a signal from kdb risks deadlock\n"
+                          "on the run queue locks.  The signal has _not_ been sent.\n"
+                          "Reissue the kill command if you want to risk the deadlock.\n");
+               return;
+       }
+       sig = info->si_signo;
+       if (send_sig_info(sig, info, t))
+               kdb_printf("Fail to deliver Signal %d to process %d.\n", sig, t->pid);
+       else
+               kdb_printf("Signal %d is sent to process %d.\n", sig, t->pid);
+}
+#endif /* CONFIG_KDB */
index e1f92ed..b190917 100644 (file)
@@ -105,6 +105,7 @@ static const struct trans_ctl_table trans_kern_table[] = {
        { KERN_NMI_WATCHDOG,            "nmi_watchdog" },
        { KERN_PANIC_ON_NMI,            "panic_on_unrecovered_nmi" },
        { KERN_SETUID_DUMPABLE,         "suid_dumpable" },
+       { KERN_KDB,                     "kdb" },
        {}
 };
 
index bfeafd6..c181d57 100644 (file)
--- a/lib/bug.c
+++ b/lib/bug.c
 #include <linux/bug.h>
 #include <linux/sched.h>
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif
+
 extern const struct bug_entry __start___bug_table[], __stop___bug_table[];
 
 #ifdef CONFIG_MODULES
@@ -162,5 +166,9 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
                       "[verbose debug info unavailable]\n",
                       (void *)bugaddr);
 
+#ifdef CONFIG_KDB
+       kdb(KDB_REASON_ENTER, 0, regs);
+#endif
+
        return BUG_TRAP_TYPE_BUG;
 }
index 67a7119..45ec9dd 100644 (file)
@@ -1455,6 +1455,28 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
 
 #endif /* CONFIG_SYSCTL */
 
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+/* Like hugetlb_report_meminfo() but using kdb_printf() */
+void
+kdb_hugetlb_report_meminfo(void)
+{
+       struct hstate *h = &default_hstate;
+       kdb_printf(
+               "HugePages_Total: %5lu\n"
+               "HugePages_Free:  %5lu\n"
+               "HugePages_Rsvd:  %5lu\n"
+               "HugePages_Surp:  %5lu\n"
+               "Hugepagesize:    %5lu kB\n",
+               h->nr_huge_pages,
+               h->free_huge_pages,
+               h->resv_huge_pages,
+               h->surplus_huge_pages,
+               1UL << (huge_page_order(h) + PAGE_SHIFT - 10));
+}
+#endif /* CONFIG_KDB */
+
 int hugetlb_report_meminfo(char *buf)
 {
        struct hstate *h = &default_hstate;
index 486ed59..4f0e40a 100644 (file)
@@ -22,6 +22,8 @@ struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
                return NULL;
        return NODE_DATA(nid);
 }
+EXPORT_SYMBOL_GPL(first_online_pgdat);
+EXPORT_SYMBOL_GPL(next_online_pgdat);
 
 /*
  * next_zone - helper magic for for_each_zone()
index 1e330f2..b8e75c9 100644 (file)
 #include <linux/swap.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#endif /* CONFIG_KDB */
 #include <linux/namei.h>
 #include <linux/shm.h>
 #include <linux/blkdev.h>
@@ -1750,6 +1754,24 @@ void si_swapinfo(struct sysinfo *val)
        spin_unlock(&swap_lock);
 }
 
+#ifdef CONFIG_KDB
+/* Like si_swapinfo() but without the locks */
+void kdb_si_swapinfo(struct sysinfo *val)
+{
+       unsigned int i;
+       unsigned long nr_to_be_unused = 0;
+
+       for (i = 0; i < nr_swapfiles; i++) {
+               if (!(swap_info[i].flags & SWP_USED) ||
+                    (swap_info[i].flags & SWP_WRITEOK))
+                       continue;
+               nr_to_be_unused += swap_info[i].inuse_pages;
+       }
+       val->freeswap = nr_swap_pages + nr_to_be_unused;
+       val->totalswap = total_swap_pages + nr_to_be_unused;
+}
+#endif /* CONFIG_KDB */
+
 /*
  * Verify that a swap entry is valid and increment its swap map count.
  *