%patch
Index: 2.6.x-xfs/arch/i386/Kconfig.debug
===================================================================
--- 2.6.x-xfs.orig/arch/i386/Kconfig.debug 2005-12-05 09:56:00.663373325 +1100
+++ 2.6.x-xfs/arch/i386/Kconfig.debug 2005-12-20 16:50:55.830227763 +1100
@@ -62,4 +62,82 @@
depends on X86_LOCAL_APIC && !X86_VISWS
default y
+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_CRASH_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 only)"
+ depends on KDB && USB_OHCI_HCD
+ help
+ If you want to use kdb from a OHCI USB keyboard then say Y here. If you
+ say N then kdb can only be used from a PC (AT) keyboard or a serial
+ console.
+
endmenu
Index: 2.6.x-xfs/arch/i386/Makefile
===================================================================
--- 2.6.x-xfs.orig/arch/i386/Makefile 2005-12-05 09:56:00.666302608 +1100
+++ 2.6.x-xfs/arch/i386/Makefile 2005-12-20 16:50:55.831204190 +1100
@@ -96,6 +96,7 @@
# must be linked after kernel/
drivers-$(CONFIG_OPROFILE) += arch/i386/oprofile/
drivers-$(CONFIG_PM) += arch/i386/power/
+drivers-$(CONFIG_KDB) += arch/i386/kdb/
CFLAGS += $(mflags-y)
AFLAGS += $(mflags-y)
Index: 2.6.x-xfs/arch/i386/kdb/ChangeLog
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kdb/ChangeLog 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/arch/i386/kdb/ChangeLog 2005-12-20 16:50:55.833157044 +1100
@@ -0,0 +1,487 @@
+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.
Index: 2.6.x-xfs/arch/i386/kdb/Makefile
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kdb/Makefile 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/arch/i386/kdb/Makefile 2005-12-20 16:50:55.833157044 +1100
@@ -0,0 +1,13 @@
+#
+# 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_bt.o kdba_bp.o kdba_id.o kdba_io.o kdbasupport.o i386-dis.o
+
+override CFLAGS := $(CFLAGS:%-pg=% )
+
+CFLAGS_kdba_io.o += -I $(TOPDIR)/arch/$(ARCH)/kdb
Index: 2.6.x-xfs/arch/i386/kdb/i386-dis.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kdb/i386-dis.c 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/arch/i386/kdb/i386-dis.c 2005-12-20 16:50:55.842921316 +1100
@@ -0,0 +1,3781 @@
+/* Print i386 instructions for GDB, the GNU debugger.
+ Copyright (C) 1988, 89, 91, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ * modified by John Hassey (hassey@dg-rtp.dg.com)
+ */
+
+/* Extracted from cygnus CVS and modified for kdb use.
+ * Keith Owens <kaos@sgi.com> 30 Oct 2000
+ */
+
+/*
+ * The main tables describing the instructions is essentially a copy
+ * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+ * Programmers Manual. Usually, there is a capital letter, followed
+ * by a small letter. The capital letter tell the addressing mode,
+ * and the small letter tells about the operand size. Refer to
+ * the Intel manual for details.
+ */
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/dis-asm.h>
+#include <linux/kdb.h>
+#else
+#include "dis-asm.h"
+#include "sysdep.h"
+#include "opintl.h"
+#endif
+
+#define MAXLEN 20
+
+#ifndef __KERNEL__
+#include <setjmp.h>
+#endif
+
+#ifndef UNIXWARE_COMPAT
+/* Set non-zero for broken, compatible instructions. Set to zero for
+ non-broken opcodes. */
+#define UNIXWARE_COMPAT 1
+#endif
+
+static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
+
+struct dis_private
+{
+ /* Points to first byte not fetched. */
+ bfd_byte *max_fetched;
+ bfd_byte the_buffer[MAXLEN];
+ bfd_vma insn_start;
+#ifndef __KERNEL__
+ jmp_buf bailout;
+#endif
+};
+
+/* The opcode for the fwait instruction, which we treat as a prefix
+ when we can. */
+#define FWAIT_OPCODE (0x9b)
+
+/* Flags for the prefixes for the current instruction. See below. */
+static int prefixes;
+
+/* Flags for prefixes which we somehow handled when printing the
+ current instruction. */
+static int used_prefixes;
+
+/* Flags stored in PREFIXES. */
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADDR 0x400
+#define PREFIX_FWAIT 0x800
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+ to ADDR (exclusive) are valid. Returns 1 for success, longjmps
+ on error. */
+#define FETCH_DATA(info, addr) \
+ ((addr) <= ((struct dis_private *)(info->private_data))->max_fetched \
+ ? 1 : fetch_data ((info), (addr)))
+
+static int
+fetch_data (info, addr)
+ struct disassemble_info *info;
+ bfd_byte *addr;
+{
+ int status;
+ struct dis_private *priv = (struct dis_private *)info->private_data;
+ bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
+
+ status = (*info->read_memory_func) (start,
+ priv->max_fetched,
+ addr - priv->max_fetched,
+ info);
+ if (status != 0)
+ {
+ /* If we did manage to read at least one byte, then
+ print_insn_i386 will do something sensible. Otherwise, print
+ an error. We do that here because this is where we know
+ STATUS. */
+ if (priv->max_fetched == priv->the_buffer)
+ (*info->memory_error_func) (status, start, info);
+#ifndef __KERNEL__
+ longjmp (priv->bailout, 1);
+#else
+ /* XXX - what to do? */
+ kdb_printf("Hmm. longjmp.\n");
+#endif
+ }
+ else
+ priv->max_fetched = addr;
+ return 1;
+}
+
+#define XX NULL, 0
+
+#define Eb OP_E, b_mode
+#define indirEb OP_indirE, b_mode
+#define Gb OP_G, b_mode
+#define Ev OP_E, v_mode
+#define Ed OP_E, d_mode
+#define indirEv OP_indirE, v_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_E, 0 /* lea */
+#define Mp OP_E, 0 /* 32 or 48 bit memory operand for LDS, LES etc */
+#define Gv OP_G, v_mode
+#define Gw OP_G, w_mode
+#define Rd OP_Rd, d_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode /* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iw OP_I, w_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#define Cd OP_C, d_mode
+#define Dd OP_D, d_mode
+#define Td OP_T, d_mode
+
+#define eAX OP_REG, eAX_reg
+#define eBX OP_REG, eBX_reg
+#define eCX OP_REG, eCX_reg
+#define eDX OP_REG, eDX_reg
+#define eSP OP_REG, eSP_reg
+#define eBP OP_REG, eBP_reg
+#define eSI OP_REG, eSI_reg
+#define eDI OP_REG, eDI_reg
+#define AL OP_REG, al_reg
+#define CL OP_REG, cl_reg
+#define DL OP_REG, dl_reg
+#define BL OP_REG, bl_reg
+#define AH OP_REG, ah_reg
+#define CH OP_REG, ch_reg
+#define DH OP_REG, dh_reg
+#define BH OP_REG, bh_reg
+#define AX OP_REG, ax_reg
+#define DX OP_REG, dx_reg
+#define indirDX OP_REG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, 0
+#define Ob OP_OFF, b_mode
+#define Ov OP_OFF, v_mode
+#define Xb OP_DSreg, eSI_reg
+#define Xv OP_DSreg, eSI_reg
+#define Yb OP_ESreg, eDI_reg
+#define Yv OP_ESreg, eDI_reg
+#define DSBX OP_DSreg, eBX_reg
+
+#define es OP_REG, es_reg
+#define ss OP_REG, ss_reg
+#define cs OP_REG, cs_reg
+#define ds OP_REG, ds_reg
+#define fs OP_REG, fs_reg
+#define gs OP_REG, gs_reg
+
+#define MX OP_MMX, 0
+#define XM OP_XMM, 0
+#define EM OP_EM, v_mode
+#define EX OP_EX, v_mode
+#define MS OP_MS, v_mode
+#define None OP_E, 0
+#define OPSUF OP_3DNowSuffix, 0
+#define OPSIMD OP_SIMD_Suffix, 0
+
+/* bits in sizeflag */
+#if 0 /* leave undefined until someone adds the extra flag to objdump */
+#define SUFFIX_ALWAYS 4
+#endif
+#define AFLAG 2
+#define DFLAG 1
+
+typedef void (*op_rtn) PARAMS ((int bytemode, int sizeflag));
+
+static void OP_E PARAMS ((int, int));
+static void OP_G PARAMS ((int, int));
+static void OP_I PARAMS ((int, int));
+static void OP_indirE PARAMS ((int, int));
+static void OP_sI PARAMS ((int, int));
+static void OP_REG PARAMS ((int, int));
+static void OP_J PARAMS ((int, int));
+static void OP_DIR PARAMS ((int, int));
+static void OP_OFF PARAMS ((int, int));
+static void OP_ESreg PARAMS ((int, int));
+static void OP_DSreg PARAMS ((int, int));
+static void OP_SEG PARAMS ((int, int));
+static void OP_C PARAMS ((int, int));
+static void OP_D PARAMS ((int, int));
+static void OP_T PARAMS ((int, int));
+static void OP_Rd PARAMS ((int, int));
+static void OP_ST PARAMS ((int, int));
+static void OP_STi PARAMS ((int, int));
+static void OP_MMX PARAMS ((int, int));
+static void OP_XMM PARAMS ((int, int));
+static void OP_EM PARAMS ((int, int));
+static void OP_EX PARAMS ((int, int));
+static void OP_MS PARAMS ((int, int));
+static void OP_3DNowSuffix PARAMS ((int, int));
+static void OP_SIMD_Suffix PARAMS ((int, int));
+static void SIMD_Fixup PARAMS ((int, int));
+
+static void append_seg PARAMS ((void));
+static void set_op PARAMS ((unsigned int op));
+static void putop PARAMS ((const char *template, int sizeflag));
+static void dofloat PARAMS ((int sizeflag));
+static int get16 PARAMS ((void));
+static int get32 PARAMS ((void));
+static void ckprefix PARAMS ((void));
+static const char *prefix_name PARAMS ((int, int));
+static void ptr_reg PARAMS ((int, int));
+static void BadOp PARAMS ((void));
+
+#define b_mode 1
+#define v_mode 2
+#define w_mode 3
+#define d_mode 4
+#define x_mode 5
+
+#define es_reg 100
+#define cs_reg 101
+#define ss_reg 102
+#define ds_reg 103
+#define fs_reg 104
+#define gs_reg 105
+
+#define eAX_reg 108
+#define eCX_reg 109
+#define eDX_reg 110
+#define eBX_reg 111
+#define eSP_reg 112
+#define eBP_reg 113
+#define eSI_reg 114
+#define eDI_reg 115
+
+#define al_reg 116
+#define cl_reg 117
+#define dl_reg 118
+#define bl_reg 119
+#define ah_reg 120
+#define ch_reg 121
+#define dh_reg 122
+#define bh_reg 123
+
+#define ax_reg 124
+#define cx_reg 125
+#define dx_reg 126
+#define bx_reg 127
+#define sp_reg 128
+#define bp_reg 129
+#define si_reg 130
+#define di_reg 131
+
+#define indir_dx_reg 150
+
+#define USE_GROUPS 1
+#define USE_PREFIX_USER_TABLE 2
+
+#define GRP1b NULL, NULL, 0, NULL, USE_GROUPS, NULL, 0
+#define GRP1S NULL, NULL, 1, NULL, USE_GROUPS, NULL, 0
+#define GRP1Ss NULL, NULL, 2, NULL, USE_GROUPS, NULL, 0
+#define GRP2b NULL, NULL, 3, NULL, USE_GROUPS, NULL, 0
+#define GRP2S NULL, NULL, 4, NULL, USE_GROUPS, NULL, 0
+#define GRP2b_one NULL, NULL, 5, NULL, USE_GROUPS, NULL, 0
+#define GRP2S_one NULL, NULL, 6, NULL, USE_GROUPS, NULL, 0
+#define GRP2b_cl NULL, NULL, 7, NULL, USE_GROUPS, NULL, 0
+#define GRP2S_cl NULL, NULL, 8, NULL, USE_GROUPS, NULL, 0
+#define GRP3b NULL, NULL, 9, NULL, USE_GROUPS, NULL, 0
+#define GRP3S NULL, NULL, 10, NULL, USE_GROUPS, NULL, 0
+#define GRP4 NULL, NULL, 11, NULL, USE_GROUPS, NULL, 0
+#define GRP5 NULL, NULL, 12, NULL, USE_GROUPS, NULL, 0
+#define GRP6 NULL, NULL, 13, NULL, USE_GROUPS, NULL, 0
+#define GRP7 NULL, NULL, 14, NULL, USE_GROUPS, NULL, 0
+#define GRP8 NULL, NULL, 15, NULL, USE_GROUPS, NULL, 0
+#define GRP9 NULL, NULL, 16, NULL, USE_GROUPS, NULL, 0
+#define GRP10 NULL, NULL, 17, NULL, USE_GROUPS, NULL, 0
+#define GRP11 NULL, NULL, 18, NULL, USE_GROUPS, NULL, 0
+#define GRP12 NULL, NULL, 19, NULL, USE_GROUPS, NULL, 0
+#define GRP13 NULL, NULL, 20, NULL, USE_GROUPS, NULL, 0
+#define GRP14 NULL, NULL, 21, NULL, USE_GROUPS, NULL, 0
+#define GRPAMD NULL, NULL, 22, NULL, USE_GROUPS, NULL, 0
+
+#define PREGRP0 NULL, NULL, 0, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP1 NULL, NULL, 1, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP2 NULL, NULL, 2, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP3 NULL, NULL, 3, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP4 NULL, NULL, 4, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP5 NULL, NULL, 5, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP6 NULL, NULL, 6, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP7 NULL, NULL, 7, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP8 NULL, NULL, 8, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP9 NULL, NULL, 9, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP10 NULL, NULL, 10, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP11 NULL, NULL, 11, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP12 NULL, NULL, 12, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP13 NULL, NULL, 13, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP14 NULL, NULL, 14, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+
+#define FLOATCODE 50
+#define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
+
+struct dis386 {
+ const char *name;
+ op_rtn op1;
+ int bytemode1;
+ op_rtn op2;
+ int bytemode2;
+ op_rtn op3;
+ int bytemode3;
+};
+
+/* Upper case letters in the instruction names here are macros.
+ 'A' => print 'b' if no register operands or suffix_always is true
+ 'B' => print 'b' if suffix_always is true
+ 'E' => print 'e' if 32-bit form of jcxz
+ 'L' => print 'l' if suffix_always is true
+ 'N' => print 'n' if instruction has no wait "prefix"
+ 'P' => print 'w' or 'l' if instruction has an operand size prefix,
+ or suffix_always is true
+ 'Q' => print 'w' or 'l' if no register operands or suffix_always is true
+ 'R' => print 'w' or 'l' ("wd" or "dq" in intel mode)
+ 'S' => print 'w' or 'l' if suffix_always is true
+ 'W' => print 'b' or 'w' ("w" or "de" in intel mode)
+*/
+
+static const struct dis386 dis386_att[] = {
+ /* 00 */
+ { "addB", Eb, Gb, XX },
+ { "addS", Ev, Gv, XX },
+ { "addB", Gb, Eb, XX },
+ { "addS", Gv, Ev, XX },
+ { "addB", AL, Ib, XX },
+ { "addS", eAX, Iv, XX },
+ { "pushP", es, XX, XX },
+ { "popP", es, XX, XX },
+ /* 08 */
+ { "orB", Eb, Gb, XX },
+ { "orS", Ev, Gv, XX },
+ { "orB", Gb, Eb, XX },
+ { "orS", Gv, Ev, XX },
+ { "orB", AL, Ib, XX },
+ { "orS", eAX, Iv, XX },
+ { "pushP", cs, XX, XX },
+ { "(bad)", XX, XX, XX }, /* 0x0f extended opcode escape */
+ /* 10 */
+ { "adcB", Eb, Gb, XX },
+ { "adcS", Ev, Gv, XX },
+ { "adcB", Gb, Eb, XX },
+ { "adcS", Gv, Ev, XX },
+ { "adcB", AL, Ib, XX },
+ { "adcS", eAX, Iv, XX },
+ { "pushP", ss, XX, XX },
+ { "popP", ss, XX, XX },
+ /* 18 */
+ { "sbbB", Eb, Gb, XX },
+ { "sbbS", Ev, Gv, XX },
+ { "sbbB", Gb, Eb, XX },
+ { "sbbS", Gv, Ev, XX },
+ { "sbbB", AL, Ib, XX },
+ { "sbbS", eAX, Iv, XX },
+ { "pushP", ds, XX, XX },
+ { "popP", ds, XX, XX },
+ /* 20 */
+ { "andB", Eb, Gb, XX },
+ { "andS", Ev, Gv, XX },
+ { "andB", Gb, Eb, XX },
+ { "andS", Gv, Ev, XX },
+ { "andB", AL, Ib, XX },
+ { "andS", eAX, Iv, XX },
+ { "(bad)", XX, XX, XX }, /* SEG ES prefix */
+ { "daa", XX, XX, XX },
+ /* 28 */
+ { "subB", Eb, Gb, XX },
+ { "subS", Ev, Gv, XX },
+ { "subB", Gb, Eb, XX },
+ { "subS", Gv, Ev, XX },
+ { "subB", AL, Ib, XX },
+ { "subS", eAX, Iv, XX },
+ { "(bad)", XX, XX, XX }, /* SEG CS prefix */
+ { "das", XX, XX, XX },
+ /* 30 */
+ { "xorB", Eb, Gb, XX },
+ { "xorS", Ev, Gv, XX },
+ { "xorB", Gb, Eb, XX },
+ { "xorS", Gv, Ev, XX },
+ { "xorB", AL, Ib, XX },
+ { "xorS", eAX, Iv, XX },
+ { "(bad)", XX, XX, XX }, /* SEG SS prefix */
+ { "aaa", XX, XX, XX },
+ /* 38 */
+ { "cmpB", Eb, Gb, XX },
+ { "cmpS", Ev, Gv, XX },
+ { "cmpB", Gb, Eb, XX },
+ { "cmpS", Gv, Ev, XX },
+ { "cmpB", AL, Ib, XX },
+ { "cmpS", eAX, Iv, XX },
+ { "(bad)", XX, XX, XX }, /* SEG DS prefix */
+ { "aas", XX, XX, XX },
+ /* 40 */
+ { "incS", eAX, XX, XX },
+ { "incS", eCX, XX, XX },
+ { "incS", eDX, XX, XX },
+ { "incS", eBX, XX, XX },
+ { "incS", eSP, XX, XX },
+ { "incS", eBP, XX, XX },
+ { "incS", eSI, XX, XX },
+ { "incS", eDI, XX, XX },
+ /* 48 */
+ { "decS", eAX, XX, XX },
+ { "decS", eCX, XX, XX },
+ { "decS", eDX, XX, XX },
+ { "decS", eBX, XX, XX },
+ { "decS", eSP, XX, XX },
+ { "decS", eBP, XX, XX },
+ { "decS", eSI, XX, XX },
+ { "decS", eDI, XX, XX },
+ /* 50 */
+ { "pushS", eAX, XX, XX },
+ { "pushS", eCX, XX, XX },
+ { "pushS", eDX, XX, XX },
+ { "pushS", eBX, XX, XX },
+ { "pushS", eSP, XX, XX },
+ { "pushS", eBP, XX, XX },
+ { "pushS", eSI, XX, XX },
+ { "pushS", eDI, XX, XX },
+ /* 58 */
+ { "popS", eAX, XX, XX },
+ { "popS", eCX, XX, XX },
+ { "popS", eDX, XX, XX },
+ { "popS", eBX, XX, XX },
+ { "popS", eSP, XX, XX },
+ { "popS", eBP, XX, XX },
+ { "popS", eSI, XX, XX },
+ { "popS", eDI, XX, XX },
+ /* 60 */
+ { "pushaP", XX, XX, XX },
+ { "popaP", XX, XX, XX },
+ { "boundS", Gv, Ma, XX },
+ { "arpl", Ew, Gw, XX },
+ { "(bad)", XX, XX, XX }, /* seg fs */
+ { "(bad)", XX, XX, XX }, /* seg gs */
+ { "(bad)", XX, XX, XX }, /* op size prefix */
+ { "(bad)", XX, XX, XX }, /* adr size prefix */
+ /* 68 */
+ { "pushP", Iv, XX, XX }, /* 386 book wrong */
+ { "imulS", Gv, Ev, Iv },
+ { "pushP", sIb, XX, XX }, /* push of byte really pushes 2 or 4 bytes */
+ { "imulS", Gv, Ev, sIb },
+ { "insb", Yb, indirDX, XX },
+ { "insR", Yv, indirDX, XX },
+ { "outsb", indirDX, Xb, XX },
+ { "outsR", indirDX, Xv, XX },
+ /* 70 */
+ { "jo", Jb, XX, XX },
+ { "jno", Jb, XX, XX },
+ { "jb", Jb, XX, XX },
+ { "jae", Jb, XX, XX },
+ { "je", Jb, XX, XX },
+ { "jne", Jb, XX, XX },
+ { "jbe", Jb, XX, XX },
+ { "ja", Jb, XX, XX },
+ /* 78 */
+ { "js", Jb, XX, XX },
+ { "jns", Jb, XX, XX },
+ { "jp", Jb, XX, XX },
+ { "jnp", Jb, XX, XX },
+ { "jl", Jb, XX, XX },
+ { "jge", Jb, XX, XX },
+ { "jle", Jb, XX, XX },
+ { "jg", Jb, XX, XX },
+ /* 80 */
+ { GRP1b },
+ { GRP1S },
+ { "(bad)", XX, XX, XX },
+ { GRP1Ss },
+ { "testB", Eb, Gb, XX },
+ { "testS", Ev, Gv, XX },
+ { "xchgB", Eb, Gb, XX },
+ { "xchgS", Ev, Gv, XX },
+ /* 88 */
+ { "movB", Eb, Gb, XX },
+ { "movS", Ev, Gv, XX },
+ { "movB", Gb, Eb, XX },
+ { "movS", Gv, Ev, XX },
+ { "movQ", Ev, Sw, XX },
+ { "leaS", Gv, M, XX },
+ { "movQ", Sw, Ev, XX },
+ { "popQ", Ev, XX, XX },
+ /* 90 */
+ { "nop", XX, XX, XX },
+ { "xchgS", eCX, eAX, XX },
+ { "xchgS", eDX, eAX, XX },
+ { "xchgS", eBX, eAX, XX },
+ { "xchgS", eSP, eAX, XX },
+ { "xchgS", eBP, eAX, XX },
+ { "xchgS", eSI, eAX, XX },
+ { "xchgS", eDI, eAX, XX },
+ /* 98 */
+ { "cWtR", XX, XX, XX },
+ { "cRtd", XX, XX, XX },
+ { "lcallP", Ap, XX, XX },
+ { "(bad)", XX, XX, XX }, /* fwait */
+ { "pushfP", XX, XX, XX },
+ { "popfP", XX, XX, XX },
+ { "sahf", XX, XX, XX },
+ { "lahf", XX, XX, XX },
+ /* a0 */
+ { "movB", AL, Ob, XX },
+ { "movS", eAX, Ov, XX },
+ { "movB", Ob, AL, XX },
+ { "movS", Ov, eAX, XX },
+ { "movsb", Yb, Xb, XX },
+ { "movsR", Yv, Xv, XX },
+ { "cmpsb", Xb, Yb, XX },
+ { "cmpsR", Xv, Yv, XX },
+ /* a8 */
+ { "testB", AL, Ib, XX },
+ { "testS", eAX, Iv, XX },
+ { "stosB", Yb, AL, XX },
+ { "stosS", Yv, eAX, XX },
+ { "lodsB", AL, Xb, XX },
+ { "lodsS", eAX, Xv, XX },
+ { "scasB", AL, Yb, XX },
+ { "scasS", eAX, Yv, XX },
+ /* b0 */
+ { "movB", AL, Ib, XX },
+ { "movB", CL, Ib, XX },
+ { "movB", DL, Ib, XX },
+ { "movB", BL, Ib, XX },
+ { "movB", AH, Ib, XX },
+ { "movB", CH, Ib, XX },
+ { "movB", DH, Ib, XX },
+ { "movB", BH, Ib, XX },
+ /* b8 */
+ { "movS", eAX, Iv, XX },
+ { "movS", eCX, Iv, XX },
+ { "movS", eDX, Iv, XX },
+ { "movS", eBX, Iv, XX },
+ { "movS", eSP, Iv, XX },
+ { "movS", eBP, Iv, XX },
+ { "movS", eSI, Iv, XX },
+ { "movS", eDI, Iv, XX },
+ /* c0 */
+ { GRP2b },
+ { GRP2S },
+ { "retP", Iw, XX, XX },
+ { "retP", XX, XX, XX },
+ { "lesS", Gv, Mp, XX },
+ { "ldsS", Gv, Mp, XX },
+ { "movA", Eb, Ib, XX },
+ { "movQ", Ev, Iv, XX },
+ /* c8 */
+ { "enterP", Iw, Ib, XX },
+ { "leaveP", XX, XX, XX },
+ { "lretP", Iw, XX, XX },
+ { "lretP", XX, XX, XX },
+ { "int3", XX, XX, XX },
+ { "int", Ib, XX, XX },
+ { "into", XX, XX, XX},
+ { "iretP", XX, XX, XX },
+ /* d0 */
+ { GRP2b_one },
+ { GRP2S_one },
+ { GRP2b_cl },
+ { GRP2S_cl },
+ { "aam", sIb, XX, XX },
+ { "aad", sIb, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "xlat", DSBX, XX, XX },
+ /* d8 */
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ /* e0 */
+ { "loopne", Jb, XX, XX },
+ { "loope", Jb, XX, XX },
+ { "loop", Jb, XX, XX },
+ { "jEcxz", Jb, XX, XX },
+ { "inB", AL, Ib, XX },
+ { "inS", eAX, Ib, XX },
+ { "outB", Ib, AL, XX },
+ { "outS", Ib, eAX, XX },
+ /* e8 */
+ { "callP", Jv, XX, XX },
+ { "jmpP", Jv, XX, XX },
+ { "ljmpP", Ap, XX, XX },
+ { "jmp", Jb, XX, XX },
+ { "inB", AL, indirDX, XX },
+ { "inS", eAX, indirDX, XX },
+ { "outB", indirDX, AL, XX },
+ { "outS", indirDX, eAX, XX },
+ /* f0 */
+ { "(bad)", XX, XX, XX }, /* lock prefix */
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX }, /* repne */
+ { "(bad)", XX, XX, XX }, /* repz */
+ { "hlt", XX, XX, XX },
+ { "cmc", XX, XX, XX },
+ { GRP3b },
+ { GRP3S },
+ /* f8 */
+ { "clc", XX, XX, XX },
+ { "stc", XX, XX, XX },
+ { "cli", XX, XX, XX },
+ { "sti", XX, XX, XX },
+ { "cld", XX, XX, XX },
+ { "std", XX, XX, XX },
+ { GRP4 },
+ { GRP5 },
+};
+
+static const struct dis386 dis386_intel[] = {
+ /* 00 */
+ { "add", Eb, Gb, XX },
+ { "add", Ev, Gv, XX },
+ { "add", Gb, Eb, XX },
+ { "add", Gv, Ev, XX },
+ { "add", AL, Ib, XX },
+ { "add", eAX, Iv, XX },
+ { "push", es, XX, XX },
+ { "pop", es, XX, XX },
+ /* 08 */
+ { "or", Eb, Gb, XX },
+ { "or", Ev, Gv, XX },
+ { "or", Gb, Eb, XX },
+ { "or", Gv, Ev, XX },
+ { "or", AL, Ib, XX },
+ { "or", eAX, Iv, XX },
+ { "push", cs, XX, XX },
+ { "(bad)", XX, XX, XX }, /* 0x0f extended opcode escape */
+ /* 10 */
+ { "adc", Eb, Gb, XX },
+ { "adc", Ev, Gv, XX },
+ { "adc", Gb, Eb, XX },
+ { "adc", Gv, Ev, XX },
+ { "adc", AL, Ib, XX },
+ { "adc", eAX, Iv, XX },
+ { "push", ss, XX, XX },
+ { "pop", ss, XX, XX },
+ /* 18 */
+ { "sbb", Eb, Gb, XX },
+ { "sbb", Ev, Gv, XX },
+ { "sbb", Gb, Eb, XX },
+ { "sbb", Gv, Ev, XX },
+ { "sbb", AL, Ib, XX },
+ { "sbb", eAX, Iv, XX },
+ { "push", ds, XX, XX },
+ { "pop", ds, XX, XX },
+ /* 20 */
+ { "and", Eb, Gb, XX },
+ { "and", Ev, Gv, XX },
+ { "and", Gb, Eb, XX },
+ { "and", Gv, Ev, XX },
+ { "and", AL, Ib, XX },
+ { "and", eAX, Iv, XX },
+ { "(bad)", XX, XX, XX }, /* SEG ES prefix */
+ { "daa", XX, XX, XX },
+ /* 28 */
+ { "sub", Eb, Gb, XX },
+ { "sub", Ev, Gv, XX },
+ { "sub", Gb, Eb, XX },
+ { "sub", Gv, Ev, XX },
+ { "sub", AL, Ib, XX },
+ { "sub", eAX, Iv, XX },
+ { "(bad)", XX, XX, XX }, /* SEG CS prefix */
+ { "das", XX, XX, XX },
+ /* 30 */
+ { "xor", Eb, Gb, XX },
+ { "xor", Ev, Gv, XX },
+ { "xor", Gb, Eb, XX },
+ { "xor", Gv, Ev, XX },
+ { "xor", AL, Ib, XX },
+ { "xor", eAX, Iv, XX },
+ { "(bad)", XX, XX, XX }, /* SEG SS prefix */
+ { "aaa", XX, XX, XX },
+ /* 38 */
+ { "cmp", Eb, Gb, XX },
+ { "cmp", Ev, Gv, XX },
+ { "cmp", Gb, Eb, XX },
+ { "cmp", Gv, Ev, XX },
+ { "cmp", AL, Ib, XX },
+ { "cmp", eAX, Iv, XX },
+ { "(bad)", XX, XX, XX }, /* SEG DS prefix */
+ { "aas", XX, XX, XX },
+ /* 40 */
+ { "inc", eAX, XX, XX },
+ { "inc", eCX, XX, XX },
+ { "inc", eDX, XX, XX },
+ { "inc", eBX, XX, XX },
+ { "inc", eSP, XX, XX },
+ { "inc", eBP, XX, XX },
+ { "inc", eSI, XX, XX },
+ { "inc", eDI, XX, XX },
+ /* 48 */
+ { "dec", eAX, XX, XX },
+ { "dec", eCX, XX, XX },
+ { "dec", eDX, XX, XX },
+ { "dec", eBX, XX, XX },
+ { "dec", eSP, XX, XX },
+ { "dec", eBP, XX, XX },
+ { "dec", eSI, XX, XX },
+ { "dec", eDI, XX, XX },
+ /* 50 */
+ { "push", eAX, XX, XX },
+ { "push", eCX, XX, XX },
+ { "push", eDX, XX, XX },
+ { "push", eBX, XX, XX },
+ { "push", eSP, XX, XX },
+ { "push", eBP, XX, XX },
+ { "push", eSI, XX, XX },
+ { "push", eDI, XX, XX },
+ /* 58 */
+ { "pop", eAX, XX, XX },
+ { "pop", eCX, XX, XX },
+ { "pop", eDX, XX, XX },
+ { "pop", eBX, XX, XX },
+ { "pop", eSP, XX, XX },
+ { "pop", eBP, XX, XX },
+ { "pop", eSI, XX, XX },
+ { "pop", eDI, XX, XX },
+ /* 60 */
+ { "pusha", XX, XX, XX },
+ { "popa", XX, XX, XX },
+ { "bound", Gv, Ma, XX },
+ { "arpl", Ew, Gw, XX },
+ { "(bad)", XX, XX, XX }, /* seg fs */
+ { "(bad)", XX, XX, XX }, /* seg gs */
+ { "(bad)", XX, XX, XX }, /* op size prefix */
+ { "(bad)", XX, XX, XX }, /* adr size prefix */
+ /* 68 */
+ { "push", Iv, XX, XX }, /* 386 book wrong */
+ { "imul", Gv, Ev, Iv },
+ { "push", sIb, XX, XX }, /* push of byte really pushes 2 or 4 bytes */
+ { "imul", Gv, Ev, sIb },
+ { "ins", Yb, indirDX, XX },
+ { "ins", Yv, indirDX, XX },
+ { "outs", indirDX, Xb, XX },
+ { "outs", indirDX, Xv, XX },
+ /* 70 */
+ { "jo", Jb, XX, XX },
+ { "jno", Jb, XX, XX },
+ { "jb", Jb, XX, XX },
+ { "jae", Jb, XX, XX },
+ { "je", Jb, XX, XX },
+ { "jne", Jb, XX, XX },
+ { "jbe", Jb, XX, XX },
+ { "ja", Jb, XX, XX },
+ /* 78 */
+ { "js", Jb, XX, XX },
+ { "jns", Jb, XX, XX },
+ { "jp", Jb, XX, XX },
+ { "jnp", Jb, XX, XX },
+ { "jl", Jb, XX, XX },
+ { "jge", Jb, XX, XX },
+ { "jle", Jb, XX, XX },
+ { "jg", Jb, XX, XX },
+ /* 80 */
+ { GRP1b },
+ { GRP1S },
+ { "(bad)", XX, XX, XX },
+ { GRP1Ss },
+ { "test", Eb, Gb, XX },
+ { "test", Ev, Gv, XX },
+ { "xchg", Eb, Gb, XX },
+ { "xchg", Ev, Gv, XX },
+ /* 88 */
+ { "mov", Eb, Gb, XX },
+ { "mov", Ev, Gv, XX },
+ { "mov", Gb, Eb, XX },
+ { "mov", Gv, Ev, XX },
+ { "mov", Ev, Sw, XX },
+ { "lea", Gv, M, XX },
+ { "mov", Sw, Ev, XX },
+ { "pop", Ev, XX, XX },
+ /* 90 */
+ { "nop", XX, XX, XX },
+ { "xchg", eCX, eAX, XX },
+ { "xchg", eDX, eAX, XX },
+ { "xchg", eBX, eAX, XX },
+ { "xchg", eSP, eAX, XX },
+ { "xchg", eBP, eAX, XX },
+ { "xchg", eSI, eAX, XX },
+ { "xchg", eDI, eAX, XX },
+ /* 98 */
+ { "cW", XX, XX, XX }, /* cwde and cbw */
+ { "cR", XX, XX, XX }, /* cdq and cwd */
+ { "lcall", Ap, XX, XX },
+ { "(bad)", XX, XX, XX }, /* fwait */
+ { "pushf", XX, XX, XX },
+ { "popf", XX, XX, XX },
+ { "sahf", XX, XX, XX },
+ { "lahf", XX, XX, XX },
+ /* a0 */
+ { "mov", AL, Ob, XX },
+ { "mov", eAX, Ov, XX },
+ { "mov", Ob, AL, XX },
+ { "mov", Ov, eAX, XX },
+ { "movs", Yb, Xb, XX },
+ { "movs", Yv, Xv, XX },
+ { "cmps", Xb, Yb, XX },
+ { "cmps", Xv, Yv, XX },
+ /* a8 */
+ { "test", AL, Ib, XX },
+ { "test", eAX, Iv, XX },
+ { "stos", Yb, AL, XX },
+ { "stos", Yv, eAX, XX },
+ { "lods", AL, Xb, XX },
+ { "lods", eAX, Xv, XX },
+ { "scas", AL, Yb, XX },
+ { "scas", eAX, Yv, XX },
+ /* b0 */
+ { "mov", AL, Ib, XX },
+ { "mov", CL, Ib, XX },
+ { "mov", DL, Ib, XX },
+ { "mov", BL, Ib, XX },
+ { "mov", AH, Ib, XX },
+ { "mov", CH, Ib, XX },
+ { "mov", DH, Ib, XX },
+ { "mov", BH, Ib, XX },
+ /* b8 */
+ { "mov", eAX, Iv, XX },
+ { "mov", eCX, Iv, XX },
+ { "mov", eDX, Iv, XX },
+ { "mov", eBX, Iv, XX },
+ { "mov", eSP, Iv, XX },
+ { "mov", eBP, Iv, XX },
+ { "mov", eSI, Iv, XX },
+ { "mov", eDI, Iv, XX },
+ /* c0 */
+ { GRP2b },
+ { GRP2S },
+ { "ret", Iw, XX, XX },
+ { "ret", XX, XX, XX },
+ { "les", Gv, Mp, XX },
+ { "lds", Gv, Mp, XX },
+ { "mov", Eb, Ib, XX },
+ { "mov", Ev, Iv, XX },
+ /* c8 */
+ { "enter", Iw, Ib, XX },
+ { "leave", XX, XX, XX },
+ { "lret", Iw, XX, XX },
+ { "lret", XX, XX, XX },
+ { "int3", XX, XX, XX },
+ { "int", Ib, XX, XX },
+ { "into", XX, XX, XX },
+ { "iret", XX, XX, XX },
+ /* d0 */
+ { GRP2b_one },
+ { GRP2S_one },
+ { GRP2b_cl },
+ { GRP2S_cl },
+ { "aam", sIb, XX, XX },
+ { "aad", sIb, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "xlat", DSBX, XX, XX },
+ /* d8 */
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ /* e0 */
+ { "loopne", Jb, XX, XX },
+ { "loope", Jb, XX, XX },
+ { "loop", Jb, XX, XX },
+ { "jEcxz", Jb, XX, XX },
+ { "in", AL, Ib, XX },
+ { "in", eAX, Ib, XX },
+ { "out", Ib, AL, XX },
+ { "out", Ib, eAX, XX },
+ /* e8 */
+ { "call", Jv, XX, XX },
+ { "jmp", Jv, XX, XX },
+ { "ljmp", Ap, XX, XX },
+ { "jmp", Jb, XX, XX },
+ { "in", AL, indirDX, XX },
+ { "in", eAX, indirDX, XX },
+ { "out", indirDX, AL, XX },
+ { "out", indirDX, eAX, XX },
+ /* f0 */
+ { "(bad)", XX, XX, XX }, /* lock prefix */
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX }, /* repne */
+ { "(bad)", XX, XX, XX }, /* repz */
+ { "hlt", XX, XX, XX },
+ { "cmc", XX, XX, XX },
+ { GRP3b },
+ { GRP3S },
+ /* f8 */
+ { "clc", XX, XX, XX },
+ { "stc", XX, XX, XX },
+ { "cli", XX, XX, XX },
+ { "sti", XX, XX, XX },
+ { "cld", XX, XX, XX },
+ { "std", XX, XX, XX },
+ { GRP4 },
+ { GRP5 },
+};
+
+static const struct dis386 dis386_twobyte_att[] = {
+ /* 00 */
+ { GRP6 },
+ { GRP7 },
+ { "larS", Gv, Ew, XX },
+ { "lslS", Gv, Ew, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "clts", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ /* 08 */
+ { "invd", XX, XX, XX },
+ { "wbinvd", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "ud2a", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { GRPAMD },
+ { "femms", XX, XX, XX },
+ { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix */
+ /* 10 */
+ { PREGRP8 },
+ { PREGRP9 },
+ { "movlps", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */
+ { "movlps", EX, XM, SIMD_Fixup, 'h' },
+ { "unpcklps", XM, EX, XX },
+ { "unpckhps", XM, EX, XX },
+ { "movhps", XM, EX, SIMD_Fixup, 'l' },
+ { "movhps", EX, XM, SIMD_Fixup, 'l' },
+ /* 18 */
+ { GRP14 },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ /* 20 */
+ /* these are all backward in appendix A of the intel book */
+ { "movL", Rd, Cd, XX },
+ { "movL", Rd, Dd, XX },
+ { "movL", Cd, Rd, XX },
+ { "movL", Dd, Rd, XX },
+ { "movL", Rd, Td, XX },
+ { "(bad)", XX, XX, XX },
+ { "movL", Td, Rd, XX },
+ { "(bad)", XX, XX, XX },
+ /* 28 */
+ { "movaps", XM, EX, XX },
+ { "movaps", EX, XM, XX },
+ { PREGRP2 },
+ { "movntps", Ev, XM, XX },
+ { PREGRP4 },
+ { PREGRP3 },
+ { "ucomiss", XM, EX, XX },
+ { "comiss", XM, EX, XX },
+ /* 30 */
+ { "wrmsr", XX, XX, XX },
+ { "rdtsc", XX, XX, XX },
+ { "rdmsr", XX, XX, XX },
+ { "rdpmc", XX, XX, XX },
+ { "sysenter", XX, XX, XX },
+ { "sysexit", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ /* 38 */
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ /* 40 */
+ { "cmovo", Gv, Ev, XX },
+ { "cmovno", Gv, Ev, XX },
+ { "cmovb", Gv, Ev, XX },
+ { "cmovae", Gv, Ev, XX },
+ { "cmove", Gv, Ev, XX },
+ { "cmovne", Gv, Ev, XX },
+ { "cmovbe", Gv, Ev, XX },
+ { "cmova", Gv, Ev, XX },
+ /* 48 */
+ { "cmovs", Gv, Ev, XX },
+ { "cmovns", Gv, Ev, XX },
+ { "cmovp", Gv, Ev, XX },
+ { "cmovnp", Gv, Ev, XX },
+ { "cmovl", Gv, Ev, XX },
+ { "cmovge", Gv, Ev, XX },
+ { "cmovle", Gv, Ev, XX },
+ { "cmovg", Gv, Ev, XX },
+ /* 50 */
+ { "movmskps", Gv, EX, XX },
+ { PREGRP13 },
+ { PREGRP12 },
+ { PREGRP11 },
+ { "andps", XM, EX, XX },
+ { "andnps", XM, EX, XX },
+ { "orps", XM, EX, XX },
+ { "xorps", XM, EX, XX },
+ /* 58 */
+ { PREGRP0 },
+ { PREGRP10 },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { PREGRP14 },
+ { PREGRP7 },
+ { PREGRP5 },
+ { PREGRP6 },
+ /* 60 */
+ { "punpcklbw", MX, EM, XX },
+ { "punpcklwd", MX, EM, XX },
+ { "punpckldq", MX, EM, XX },
+ { "packsswb", MX, EM, XX },
+ { "pcmpgtb", MX, EM, XX },
+ { "pcmpgtw", MX, EM, XX },
+ { "pcmpgtd", MX, EM, XX },
+ { "packuswb", MX, EM, XX },
+ /* 68 */
+ { "punpckhbw", MX, EM, XX },
+ { "punpckhwd", MX, EM, XX },
+ { "punpckhdq", MX, EM, XX },
+ { "packssdw", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "movd", MX, Ed, XX },
+ { "movq", MX, EM, XX },
+ /* 70 */
+ { "pshufw", MX, EM, Ib },
+ { GRP10 },
+ { GRP11 },
+ { GRP12 },
+ { "pcmpeqb", MX, EM, XX },
+ { "pcmpeqw", MX, EM, XX },
+ { "pcmpeqd", MX, EM, XX },
+ { "emms", XX, XX, XX },
+ /* 78 */
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "movd", Ed, MX, XX },
+ { "movq", EM, MX, XX },
+ /* 80 */
+ { "jo", Jv, XX, XX },
+ { "jno", Jv, XX, XX },
+ { "jb", Jv, XX, XX },
+ { "jae", Jv, XX, XX },
+ { "je", Jv, XX, XX },
+ { "jne", Jv, XX, XX },
+ { "jbe", Jv, XX, XX },
+ { "ja", Jv, XX, XX },
+ /* 88 */
+ { "js", Jv, XX, XX },
+ { "jns", Jv, XX, XX },
+ { "jp", Jv, XX, XX },
+ { "jnp", Jv, XX, XX },
+ { "jl", Jv, XX, XX },
+ { "jge", Jv, XX, XX },
+ { "jle", Jv, XX, XX },
+ { "jg", Jv, XX, XX },
+ /* 90 */
+ { "seto", Eb, XX, XX },
+ { "setno", Eb, XX, XX },
+ { "setb", Eb, XX, XX },
+ { "setae", Eb, XX, XX },
+ { "sete", Eb, XX, XX },
+ { "setne", Eb, XX, XX },
+ { "setbe", Eb, XX, XX },
+ { "seta", Eb, XX, XX },
+ /* 98 */
+ { "sets", Eb, XX, XX },
+ { "setns", Eb, XX, XX },
+ { "setp", Eb, XX, XX },
+ { "setnp", Eb, XX, XX },
+ { "setl", Eb, XX, XX },
+ { "setge", Eb, XX, XX },
+ { "setle", Eb, XX, XX },
+ { "setg", Eb, XX, XX },
+ /* a0 */
+ { "pushP", fs, XX, XX },
+ { "popP", fs, XX, XX },
+ { "cpuid", XX, XX, XX },
+ { "btS", Ev, Gv, XX },
+ { "shldS", Ev, Gv, Ib },
+ { "shldS", Ev, Gv, CL },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ /* a8 */
+ { "pushP", gs, XX, XX },
+ { "popP", gs, XX, XX },
+ { "rsm", XX, XX, XX },
+ { "btsS", Ev, Gv, XX },
+ { "shrdS", Ev, Gv, Ib },
+ { "shrdS", Ev, Gv, CL },
+ { GRP13 },
+ { "imulS", Gv, Ev, XX },
+ /* b0 */
+ { "cmpxchgB", Eb, Gb, XX },
+ { "cmpxchgS", Ev, Gv, XX },
+ { "lssS", Gv, Mp, XX },
+ { "btrS", Ev, Gv, XX },
+ { "lfsS", Gv, Mp, XX },
+ { "lgsS", Gv, Mp, XX },
+ { "movzbR", Gv, Eb, XX },
+ { "movzwR", Gv, Ew, XX }, /* yes, there really is movzww ! */
+ /* b8 */
+ { "(bad)", XX, XX, XX },
+ { "ud2b", XX, XX, XX },
+ { GRP8 },
+ { "btcS", Ev, Gv, XX },
+ { "bsfS", Gv, Ev, XX },
+ { "bsrS", Gv, Ev, XX },
+ { "movsbR", Gv, Eb, XX },
+ { "movswR", Gv, Ew, XX }, /* yes, there really is movsww ! */
+ /* c0 */
+ { "xaddB", Eb, Gb, XX },
+ { "xaddS", Ev, Gv, XX },
+ { PREGRP1 },
+ { "(bad)", XX, XX, XX },
+ { "pinsrw", MX, Ev, Ib },
+ { "pextrw", Ev, MX, Ib },
+ { "shufps", XM, EX, Ib },
+ { GRP9 },
+ /* c8 */
+ { "bswap", eAX, XX, XX }, /* bswap doesn't support 16 bit regs */
+ { "bswap", eCX, XX, XX },
+ { "bswap", eDX, XX, XX },
+ { "bswap", eBX, XX, XX },
+ { "bswap", eSP, XX, XX },
+ { "bswap", eBP, XX, XX },
+ { "bswap", eSI, XX, XX },
+ { "bswap", eDI, XX, XX },
+ /* d0 */
+ { "(bad)", XX, XX, XX },
+ { "psrlw", MX, EM, XX },
+ { "psrld", MX, EM, XX },
+ { "psrlq", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "pmullw", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "pmovmskb", Ev, MX, XX },
+ /* d8 */
+ { "psubusb", MX, EM, XX },
+ { "psubusw", MX, EM, XX },
+ { "pminub", MX, EM, XX },
+ { "pand", MX, EM, XX },
+ { "paddusb", MX, EM, XX },
+ { "paddusw", MX, EM, XX },
+ { "pmaxub", MX, EM, XX },
+ { "pandn", MX, EM, XX },
+ /* e0 */
+ { "pavgb", MX, EM, XX },
+ { "psraw", MX, EM, XX },
+ { "psrad", MX, EM, XX },
+ { "pavgw", MX, EM, XX },
+ { "pmulhuw", MX, EM, XX },
+ { "pmulhw", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "movntq", Ev, MX, XX },
+ /* e8 */
+ { "psubsb", MX, EM, XX },
+ { "psubsw", MX, EM, XX },
+ { "pminsw", MX, EM, XX },
+ { "por", MX, EM, XX },
+ { "paddsb", MX, EM, XX },
+ { "paddsw", MX, EM, XX },
+ { "pmaxsw", MX, EM, XX },
+ { "pxor", MX, EM, XX },
+ /* f0 */
+ { "(bad)", XX, XX, XX },
+ { "psllw", MX, EM, XX },
+ { "pslld", MX, EM, XX },
+ { "psllq", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "pmaddwd", MX, EM, XX },
+ { "psadbw", MX, EM, XX },
+ { "maskmovq", MX, EM, XX },
+ /* f8 */
+ { "psubb", MX, EM, XX },
+ { "psubw", MX, EM, XX },
+ { "psubd", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "paddb", MX, EM, XX },
+ { "paddw", MX, EM, XX },
+ { "paddd", MX, EM, XX },
+ { "(bad)", XX, XX, XX }
+};
+
+static const struct dis386 dis386_twobyte_intel[] = {
+ /* 00 */
+ { GRP6 },
+ { GRP7 },
+ { "lar", Gv, Ew, XX },
+ { "lsl", Gv, Ew, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "clts", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ /* 08 */
+ { "invd", XX, XX, XX },
+ { "wbinvd", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "ud2a", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { GRPAMD },
+ { "femms" , XX, XX, XX},
+ { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix */
+ /* 10 */
+ { PREGRP8 },
+ { PREGRP9 },
+ { "movlps", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */
+ { "movlps", EX, XM, SIMD_Fixup, 'h' },
+ { "unpcklps", XM, EX, XX },
+ { "unpckhps", XM, EX, XX },
+ { "movhps", XM, EX, SIMD_Fixup, 'l' },
+ { "movhps", EX, XM, SIMD_Fixup, 'l' },
+ /* 18 */
+ { GRP14 },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ /* 20 */
+ /* these are all backward in appendix A of the intel book */
+ { "mov", Rd, Cd, XX },
+ { "mov", Rd, Dd, XX },
+ { "mov", Cd, Rd, XX },
+ { "mov", Dd, Rd, XX },
+ { "mov", Rd, Td, XX },
+ { "(bad)", XX, XX, XX },
+ { "mov", Td, Rd, XX },
+ { "(bad)", XX, XX, XX },
+ /* 28 */
+ { "movaps", XM, EX, XX },
+ { "movaps", EX, XM, XX },
+ { PREGRP2 },
+ { "movntps", Ev, XM, XX },
+ { PREGRP4 },
+ { PREGRP3 },
+ { "ucomiss", XM, EX, XX },
+ { "comiss", XM, EX, XX },
+ /* 30 */
+ { "wrmsr", XX, XX, XX },
+ { "rdtsc", XX, XX, XX },
+ { "rdmsr", XX, XX, XX },
+ { "rdpmc", XX, XX, XX },
+ { "sysenter", XX, XX, XX },
+ { "sysexit", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ /* 38 */
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ /* 40 */
+ { "cmovo", Gv, Ev, XX },
+ { "cmovno", Gv, Ev, XX },
+ { "cmovb", Gv, Ev, XX },
+ { "cmovae", Gv, Ev, XX },
+ { "cmove", Gv, Ev, XX },
+ { "cmovne", Gv, Ev, XX },
+ { "cmovbe", Gv, Ev, XX },
+ { "cmova", Gv, Ev, XX },
+ /* 48 */
+ { "cmovs", Gv, Ev, XX },
+ { "cmovns", Gv, Ev, XX },
+ { "cmovp", Gv, Ev, XX },
+ { "cmovnp", Gv, Ev, XX },
+ { "cmovl", Gv, Ev, XX },
+ { "cmovge", Gv, Ev, XX },
+ { "cmovle", Gv, Ev, XX },
+ { "cmovg", Gv, Ev, XX },
+ /* 50 */
+ { "movmskps", Gv, EX, XX },
+ { PREGRP13 },
+ { PREGRP12 },
+ { PREGRP11 },
+ { "andps", XM, EX, XX },
+ { "andnps", XM, EX, XX },
+ { "orps", XM, EX, XX },
+ { "xorps", XM, EX, XX },
+ /* 58 */
+ { PREGRP0 },
+ { PREGRP10 },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { PREGRP14 },
+ { PREGRP7 },
+ { PREGRP5 },
+ { PREGRP6 },
+ /* 60 */
+ { "punpcklbw", MX, EM, XX },
+ { "punpcklwd", MX, EM, XX },
+ { "punpckldq", MX, EM, XX },
+ { "packsswb", MX, EM, XX },
+ { "pcmpgtb", MX, EM, XX },
+ { "pcmpgtw", MX, EM, XX },
+ { "pcmpgtd", MX, EM, XX },
+ { "packuswb", MX, EM, XX },
+ /* 68 */
+ { "punpckhbw", MX, EM, XX },
+ { "punpckhwd", MX, EM, XX },
+ { "punpckhdq", MX, EM, XX },
+ { "packssdw", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "movd", MX, Ed, XX },
+ { "movq", MX, EM, XX },
+ /* 70 */
+ { "pshufw", MX, EM, Ib },
+ { GRP10 },
+ { GRP11 },
+ { GRP12 },
+ { "pcmpeqb", MX, EM, XX },
+ { "pcmpeqw", MX, EM, XX },
+ { "pcmpeqd", MX, EM, XX },
+ { "emms", XX, XX, XX },
+ /* 78 */
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "movd", Ed, MX, XX },
+ { "movq", EM, MX, XX },
+ /* 80 */
+ { "jo", Jv, XX, XX },
+ { "jno", Jv, XX, XX },
+ { "jb", Jv, XX, XX },
+ { "jae", Jv, XX, XX },
+ { "je", Jv, XX, XX },
+ { "jne", Jv, XX, XX },
+ { "jbe", Jv, XX, XX },
+ { "ja", Jv, XX, XX },
+ /* 88 */
+ { "js", Jv, XX, XX },
+ { "jns", Jv, XX, XX },
+ { "jp", Jv, XX, XX },
+ { "jnp", Jv, XX, XX },
+ { "jl", Jv, XX, XX },
+ { "jge", Jv, XX, XX },
+ { "jle", Jv, XX, XX },
+ { "jg", Jv, XX, XX },
+ /* 90 */
+ { "seto", Eb, XX, XX },
+ { "setno", Eb, XX, XX },
+ { "setb", Eb, XX, XX },
+ { "setae", Eb, XX, XX },
+ { "sete", Eb, XX, XX },
+ { "setne", Eb, XX, XX },
+ { "setbe", Eb, XX, XX },
+ { "seta", Eb, XX, XX },
+ /* 98 */
+ { "sets", Eb, XX, XX },
+ { "setns", Eb, XX, XX },
+ { "setp", Eb, XX, XX },
+ { "setnp", Eb, XX, XX },
+ { "setl", Eb, XX, XX },
+ { "setge", Eb, XX, XX },
+ { "setle", Eb, XX, XX },
+ { "setg", Eb, XX, XX },
+ /* a0 */
+ { "push", fs, XX, XX },
+ { "pop", fs, XX, XX },
+ { "cpuid", XX, XX, XX },
+ { "bt", Ev, Gv, XX },
+ { "shld", Ev, Gv, Ib },
+ { "shld", Ev, Gv, CL },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ /* a8 */
+ { "push", gs, XX, XX },
+ { "pop", gs, XX, XX },
+ { "rsm" , XX, XX, XX},
+ { "bts", Ev, Gv, XX },
+ { "shrd", Ev, Gv, Ib },
+ { "shrd", Ev, Gv, CL },
+ { GRP13 },
+ { "imul", Gv, Ev, XX },
+ /* b0 */
+ { "cmpxchg", Eb, Gb, XX },
+ { "cmpxchg", Ev, Gv, XX },
+ { "lss", Gv, Mp, XX },
+ { "btr", Ev, Gv, XX },
+ { "lfs", Gv, Mp, XX },
+ { "lgs", Gv, Mp, XX },
+ { "movzx", Gv, Eb, XX },
+ { "movzx", Gv, Ew, XX },
+ /* b8 */
+ { "(bad)", XX, XX, XX },
+ { "ud2b", XX, XX, XX },
+ { GRP8 },
+ { "btc", Ev, Gv, XX },
+ { "bsf", Gv, Ev, XX },
+ { "bsr", Gv, Ev, XX },
+ { "movsx", Gv, Eb, XX },
+ { "movsx", Gv, Ew, XX },
+ /* c0 */
+ { "xadd", Eb, Gb, XX },
+ { "xadd", Ev, Gv, XX },
+ { PREGRP1 },
+ { "(bad)", XX, XX, XX },
+ { "pinsrw", MX, Ev, Ib },
+ { "pextrw", Ev, MX, Ib },
+ { "shufps", XM, EX, Ib },
+ { GRP9 },
+ /* c8 */
+ { "bswap", eAX, XX, XX }, /* bswap doesn't support 16 bit regs */
+ { "bswap", eCX, XX, XX },
+ { "bswap", eDX, XX, XX },
+ { "bswap", eBX, XX, XX },
+ { "bswap", eSP, XX, XX },
+ { "bswap", eBP, XX, XX },
+ { "bswap", eSI, XX, XX },
+ { "bswap", eDI, XX, XX },
+ /* d0 */
+ { "(bad)", XX, XX, XX },
+ { "psrlw", MX, EM, XX },
+ { "psrld", MX, EM, XX },
+ { "psrlq", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "pmullw", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "pmovmskb", Ev, MX, XX },
+ /* d8 */
+ { "psubusb", MX, EM, XX },
+ { "psubusw", MX, EM, XX },
+ { "pminub", MX, EM, XX },
+ { "pand", MX, EM, XX },
+ { "paddusb", MX, EM, XX },
+ { "paddusw", MX, EM, XX },
+ { "pmaxub", MX, EM, XX },
+ { "pandn", MX, EM, XX },
+ /* e0 */
+ { "pavgb", MX, EM, XX },
+ { "psraw", MX, EM, XX },
+ { "psrad", MX, EM, XX },
+ { "pavgw", MX, EM, XX },
+ { "pmulhuw", MX, EM, XX },
+ { "pmulhw", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "movntq", Ev, MX, XX },
+ /* e8 */
+ { "psubsb", MX, EM, XX },
+ { "psubsw", MX, EM, XX },
+ { "pminsw", MX, EM, XX },
+ { "por", MX, EM, XX },
+ { "paddsb", MX, EM, XX },
+ { "paddsw", MX, EM, XX },
+ { "pmaxsw", MX, EM, XX },
+ { "pxor", MX, EM, XX },
+ /* f0 */
+ { "(bad)", XX, XX, XX },
+ { "psllw", MX, EM, XX },
+ { "pslld", MX, EM, XX },
+ { "psllq", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "pmaddwd", MX, EM, XX },
+ { "psadbw", MX, EM, XX },
+ { "maskmovq", MX, EM, XX },
+ /* f8 */
+ { "psubb", MX, EM, XX },
+ { "psubw", MX, EM, XX },
+ { "psubd", MX, EM, XX },
+ { "(bad)", XX, XX, XX },
+ { "paddb", MX, EM, XX },
+ { "paddw", MX, EM, XX },
+ { "paddd", MX, EM, XX },
+ { "(bad)", XX, XX, XX }
+};
+
+static const unsigned char onebyte_has_modrm[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */
+ /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */
+ /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */
+ /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */
+ /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
+ /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */
+ /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */
+ /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */
+ /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */
+ /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */
+ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */
+ /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 /* f0 */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+static const unsigned char twobyte_has_modrm[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */
+ /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
+ /* 50 */ 1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1, /* 5f */
+ /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1, /* 6f */
+ /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
+ /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
+ /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
+ /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1, /* df */
+ /* e0 */ 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, /* ef */
+ /* f0 */ 0,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0 /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+static const unsigned char twobyte_uses_f3_prefix[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+ /* 10 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,1,1,1,0,0,0,0,1,1,0,0,1,1,1,1, /* 5f */
+ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+ /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+ /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+ /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+static char obuf[100];
+static char *obufp;
+static char scratchbuf[100];
+static unsigned char *start_codep;
+static unsigned char *insn_codep;
+static unsigned char *codep;
+static disassemble_info *the_info;
+static int mod;
+static int rm;
+static int reg;
+static void oappend PARAMS ((const char *s));
+
+static const char *names32[]={
+ "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
+};
+static const char *names16[] = {
+ "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
+};
+static const char *names8[] = {
+ "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
+};
+static const char *names_seg[] = {
+ "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+};
+static const char *index16[] = {
+ "%bx,%si","%bx,%di","%bp,%si","%bp,%di","%si","%di","%bp","%bx"
+};
+
+static const struct dis386 grps[][8] = {
+ /* GRP1b */
+ {
+ { "addA", Eb, Ib, XX },
+ { "orA", Eb, Ib, XX },
+ { "adcA", Eb, Ib, XX },
+ { "sbbA", Eb, Ib, XX },
+ { "andA", Eb, Ib, XX },
+ { "subA", Eb, Ib, XX },
+ { "xorA", Eb, Ib, XX },
+ { "cmpA", Eb, Ib, XX }
+ },
+ /* GRP1S */
+ {
+ { "addQ", Ev, Iv, XX },
+ { "orQ", Ev, Iv, XX },
+ { "adcQ", Ev, Iv, XX },
+ { "sbbQ", Ev, Iv, XX },
+ { "andQ", Ev, Iv, XX },
+ { "subQ", Ev, Iv, XX },
+ { "xorQ", Ev, Iv, XX },
+ { "cmpQ", Ev, Iv, XX }
+ },
+ /* GRP1Ss */
+ {
+ { "addQ", Ev, sIb, XX },
+ { "orQ", Ev, sIb, XX },
+ { "adcQ", Ev, sIb, XX },
+ { "sbbQ", Ev, sIb, XX },
+ { "andQ", Ev, sIb, XX },
+ { "subQ", Ev, sIb, XX },
+ { "xorQ", Ev, sIb, XX },
+ { "cmpQ", Ev, sIb, XX }
+ },
+ /* GRP2b */
+ {
+ { "rolA", Eb, Ib, XX },
+ { "rorA", Eb, Ib, XX },
+ { "rclA", Eb, Ib, XX },
+ { "rcrA", Eb, Ib, XX },
+ { "shlA", Eb, Ib, XX },
+ { "shrA", Eb, Ib, XX },
+ { "(bad)", XX, XX, XX },
+ { "sarA", Eb, Ib, XX },
+ },
+ /* GRP2S */
+ {
+ { "rolQ", Ev, Ib, XX },
+ { "rorQ", Ev, Ib, XX },
+ { "rclQ", Ev, Ib, XX },
+ { "rcrQ", Ev, Ib, XX },
+ { "shlQ", Ev, Ib, XX },
+ { "shrQ", Ev, Ib, XX },
+ { "(bad)", XX, XX, XX },
+ { "sarQ", Ev, Ib, XX },
+ },
+ /* GRP2b_one */
+ {
+ { "rolA", Eb, XX, XX },
+ { "rorA", Eb, XX, XX },
+ { "rclA", Eb, XX, XX },
+ { "rcrA", Eb, XX, XX },
+ { "shlA", Eb, XX, XX },
+ { "shrA", Eb, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "sarA", Eb, XX, XX },
+ },
+ /* GRP2S_one */
+ {
+ { "rolQ", Ev, XX, XX },
+ { "rorQ", Ev, XX, XX },
+ { "rclQ", Ev, XX, XX },
+ { "rcrQ", Ev, XX, XX },
+ { "shlQ", Ev, XX, XX },
+ { "shrQ", Ev, XX, XX },
+ { "(bad)", XX, XX, XX},
+ { "sarQ", Ev, XX, XX },
+ },
+ /* GRP2b_cl */
+ {
+ { "rolA", Eb, CL, XX },
+ { "rorA", Eb, CL, XX },
+ { "rclA", Eb, CL, XX },
+ { "rcrA", Eb, CL, XX },
+ { "shlA", Eb, CL, XX },
+ { "shrA", Eb, CL, XX },
+ { "(bad)", XX, XX, XX },
+ { "sarA", Eb, CL, XX },
+ },
+ /* GRP2S_cl */
+ {
+ { "rolQ", Ev, CL, XX },
+ { "rorQ", Ev, CL, XX },
+ { "rclQ", Ev, CL, XX },
+ { "rcrQ", Ev, CL, XX },
+ { "shlQ", Ev, CL, XX },
+ { "shrQ", Ev, CL, XX },
+ { "(bad)", XX, XX, XX },
+ { "sarQ", Ev, CL, XX }
+ },
+ /* GRP3b */
+ {
+ { "testA", Eb, Ib, XX },
+ { "(bad)", Eb, XX, XX },
+ { "notA", Eb, XX, XX },
+ { "negA", Eb, XX, XX },
+ { "mulB", AL, Eb, XX },
+ { "imulB", AL, Eb, XX },
+ { "divB", AL, Eb, XX },
+ { "idivB", AL, Eb, XX }
+ },
+ /* GRP3S */
+ {
+ { "testQ", Ev, Iv, XX },
+ { "(bad)", XX, XX, XX },
+ { "notQ", Ev, XX, XX },
+ { "negQ", Ev, XX, XX },
+ { "mulS", eAX, Ev, XX },
+ { "imulS", eAX, Ev, XX },
+ { "divS", eAX, Ev, XX },
+ { "idivS", eAX, Ev, XX },
+ },
+ /* GRP4 */
+ {
+ { "incA", Eb, XX, XX },
+ { "decA", Eb, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ },
+ /* GRP5 */
+ {
+ { "incQ", Ev, XX, XX },
+ { "decQ", Ev, XX, XX },
+ { "callP", indirEv, XX, XX },
+ { "lcallP", indirEv, XX, XX },
+ { "jmpP", indirEv, XX, XX },
+ { "ljmpP", indirEv, XX, XX },
+ { "pushQ", Ev, XX, XX },
+ { "(bad)", XX, XX, XX },
+ },
+ /* GRP6 */
+ {
+ { "sldt", Ew, XX, XX },
+ { "str", Ew, XX, XX },
+ { "lldt", Ew, XX, XX },
+ { "ltr", Ew, XX, XX },
+ { "verr", Ew, XX, XX },
+ { "verw", Ew, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX }
+ },
+ /* GRP7 */
+ {
+ { "sgdt", Ew, XX, XX },
+ { "sidt", Ew, XX, XX },
+ { "lgdt", Ew, XX, XX },
+ { "lidt", Ew, XX, XX },
+ { "smsw", Ew, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "lmsw", Ew, XX, XX },
+ { "invlpg", Ew, XX, XX },
+ },
+ /* GRP8 */
+ {
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "btQ", Ev, Ib, XX },
+ { "btsQ", Ev, Ib, XX },
+ { "btrQ", Ev, Ib, XX },
+ { "btcQ", Ev, Ib, XX },
+ },
+ /* GRP9 */
+ {
+ { "(bad)", XX, XX, XX },
+ { "cmpxchg8b", Ev, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ },
+ /* GRP10 */
+ {
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "psrlw", MS, Ib, XX },
+ { "(bad)", XX, XX, XX },
+ { "psraw", MS, Ib, XX },
+ { "(bad)", XX, XX, XX },
+ { "psllw", MS, Ib, XX },
+ { "(bad)", XX, XX, XX },
+ },
+ /* GRP11 */
+ {
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "psrld", MS, Ib, XX },
+ { "(bad)", XX, XX, XX },
+ { "psrad", MS, Ib, XX },
+ { "(bad)", XX, XX, XX },
+ { "pslld", MS, Ib, XX },
+ { "(bad)", XX, XX, XX },
+ },
+ /* GRP12 */
+ {
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "psrlq", MS, Ib, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "psllq", MS, Ib, XX },
+ { "(bad)", XX, XX, XX },
+ },
+ /* GRP13 */
+ {
+ { "fxsave", Ev, XX, XX },
+ { "fxrstor", Ev, XX, XX },
+ { "ldmxcsr", Ev, XX, XX },
+ { "stmxcsr", Ev, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "sfence", None, XX, XX },
+ },
+ /* GRP14 */
+ {
+ { "prefetchnta", Ev, XX, XX },
+ { "prefetcht0", Ev, XX, XX },
+ { "prefetcht1", Ev, XX, XX },
+ { "prefetcht2", Ev, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ },
+ /* GRPAMD */
+ {
+ { "prefetch", Eb, XX, XX },
+ { "prefetchw", Eb, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ }
+
+};
+
+static const struct dis386 prefix_user_table[][2] = {
+ /* PREGRP0 */
+ {
+ { "addps", XM, EX, XX },
+ { "addss", XM, EX, XX },
+ },
+ /* PREGRP1 */
+ {
+ { "", XM, EX, OPSIMD }, /* See OP_SIMD_SUFFIX */
+ { "", XM, EX, OPSIMD },
+ },
+ /* PREGRP2 */
+ {
+ { "cvtpi2ps", XM, EM, XX },
+ { "cvtsi2ss", XM, Ev, XX },
+ },
+ /* PREGRP3 */
+ {
+ { "cvtps2pi", MX, EX, XX },
+ { "cvtss2si", Gv, EX, XX },
+ },
+ /* PREGRP4 */
+ {
+ { "cvttps2pi", MX, EX, XX },
+ { "cvttss2si", Gv, EX, XX },
+ },
+ /* PREGRP5 */
+ {
+ { "divps", XM, EX, XX },
+ { "divss", XM, EX, XX },
+ },
+ /* PREGRP6 */
+ {
+ { "maxps", XM, EX, XX },
+ { "maxss", XM, EX, XX },
+ },
+ /* PREGRP7 */
+ {
+ { "minps", XM, EX, XX },
+ { "minss", XM, EX, XX },
+ },
+ /* PREGRP8 */
+ {
+ { "movups", XM, EX, XX },
+ { "movss", XM, EX, XX },
+ },
+ /* PREGRP9 */
+ {
+ { "movups", EX, XM, XX },
+ { "movss", EX, XM, XX },
+ },
+ /* PREGRP10 */
+ {
+ { "mulps", XM, EX, XX },
+ { "mulss", XM, EX, XX },
+ },
+ /* PREGRP11 */
+ {
+ { "rcpps", XM, EX, XX },
+ { "rcpss", XM, EX, XX },
+ },
+ /* PREGRP12 */
+ {
+ { "rsqrtps", XM, EX, XX },
+ { "rsqrtss", XM, EX, XX },
+ },
+ /* PREGRP13 */
+ {
+ { "sqrtps", XM, EX, XX },
+ { "sqrtss", XM, EX, XX },
+ },
+ /* PREGRP14 */
+ {
+ { "subps", XM, EX, XX },
+ { "subss", XM, EX, XX },
+ }
+};
+
+#define INTERNAL_DISASSEMBLER_ERROR "<internal disassembler error>"
+
+static void
+ckprefix ()
+{
+ prefixes = 0;
+ used_prefixes = 0;
+ while (1)
+ {
+ FETCH_DATA (the_info, codep + 1);
+ switch (*codep)
+ {
+ case 0xf3:
+ prefixes |= PREFIX_REPZ;
+ break;
+ case 0xf2:
+ prefixes |= PREFIX_REPNZ;
+ break;
+ case 0xf0:
+ prefixes |= PREFIX_LOCK;
+ break;
+ case 0x2e:
+ prefixes |= PREFIX_CS;
+ break;
+ case 0x36:
+ prefixes |= PREFIX_SS;
+ break;
+ case 0x3e:
+ prefixes |= PREFIX_DS;
+ break;
+ case 0x26:
+ prefixes |= PREFIX_ES;
+ break;
+ case 0x64:
+ prefixes |= PREFIX_FS;
+ break;
+ case 0x65:
+ prefixes |= PREFIX_GS;
+ break;
+ case 0x66:
+ prefixes |= PREFIX_DATA;
+ break;
+ case 0x67:
+ prefixes |= PREFIX_ADDR;
+ break;
+ case FWAIT_OPCODE:
+ /* fwait is really an instruction. If there are prefixes
+ before the fwait, they belong to the fwait, *not* to the
+ following instruction. */
+ if (prefixes)
+ {
+ prefixes |= PREFIX_FWAIT;
+ codep++;
+ return;
+ }
+ prefixes = PREFIX_FWAIT;
+ break;
+ default:
+ return;
+ }
+ codep++;
+ }
+}
+
+/* Return the name of the prefix byte PREF, or NULL if PREF is not a
+ prefix byte. */
+
+static const char *
+prefix_name (pref, sizeflag)
+ int pref;
+ int sizeflag;
+{
+ switch (pref)
+ {
+ case 0xf3:
+ return "repz";
+ case 0xf2:
+ return "repnz";
+ case 0xf0:
+ return "lock";
+ case 0x2e:
+ return "cs";
+ case 0x36:
+ return "ss";
+ case 0x3e:
+ return "ds";
+ case 0x26:
+ return "es";
+ case 0x64:
+ return "fs";
+ case 0x65:
+ return "gs";
+ case 0x66:
+ return (sizeflag & DFLAG) ? "data16" : "data32";
+ case 0x67:
+ return (sizeflag & AFLAG) ? "addr16" : "addr32";
+ case FWAIT_OPCODE:
+ return "fwait";
+ default:
+ return NULL;
+ }
+}
+
+static char op1out[100], op2out[100], op3out[100];
+static int op_ad, op_index[3];
+static unsigned int op_address[3];
+static unsigned int start_pc;
+
+
+/*
+ * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+ * (see topic "Redundant prefixes" in the "Differences from 8086"
+ * section of the "Virtual 8086 Mode" chapter.)
+ * 'pc' should be the address of this instruction, it will
+ * be used to print the target address if this is a relative jump or call
+ * The function returns the length of this instruction in bytes.
+ */
+
+static int print_insn_i386
+ PARAMS ((bfd_vma pc, disassemble_info *info));
+
+static char intel_syntax;
+static char open_char;
+static char close_char;
+static char separator_char;
+static char scale_char;
+
+int
+print_insn_i386_att (pc, info)
+ bfd_vma pc;
+ disassemble_info *info;
+{
+ intel_syntax = 0;
+ open_char = '(';
+ close_char = ')';
+ separator_char = ',';
+ scale_char = ',';
+
+ return print_insn_i386 (pc, info);
+}
+
+int
+print_insn_i386_intel (pc, info)
+ bfd_vma pc;
+ disassemble_info *info;
+{
+ intel_syntax = 1;
+ open_char = '[';
+ close_char = ']';
+ separator_char = '+';
+ scale_char = '*';
+
+ return print_insn_i386 (pc, info);
+}
+
+static int
+print_insn_i386 (pc, info)
+ bfd_vma pc;
+ disassemble_info *info;
+{
+ const struct dis386 *dp;
+ int i;
+ int two_source_ops;
+ char *first, *second, *third;
+ int needcomma;
+ unsigned char need_modrm;
+ unsigned char uses_f3_prefix;
+ VOLATILE int sizeflag;
+ VOLATILE int orig_sizeflag;
+
+ struct dis_private priv;
+ bfd_byte *inbuf = priv.the_buffer;
+
+ if (info->mach == bfd_mach_i386_i386
+ || info->mach == bfd_mach_i386_i386_intel_syntax)
+ sizeflag = AFLAG|DFLAG;
+ else if (info->mach == bfd_mach_i386_i8086)
+ sizeflag = 0;
+ else
+ abort ();
+ orig_sizeflag = sizeflag;
+
+ /* The output looks better if we put 7 bytes on a line, since that
+ puts most long word instructions on a single line. */
+ info->bytes_per_line = 7;
+
+ info->private_data = (PTR) &priv;
+ priv.max_fetched = priv.the_buffer;
+ priv.insn_start = pc;
+
+ obuf[0] = 0;
+ op1out[0] = 0;
+ op2out[0] = 0;
+ op3out[0] = 0;
+
+ op_index[0] = op_index[1] = op_index[2] = -1;
+
+ the_info = info;
+ start_pc = pc;
+ start_codep = inbuf;
+ codep = inbuf;
+
+#ifndef __KERNEL__
+ if (setjmp (priv.bailout) != 0)
+ {
+ const char *name;
+
+ /* Getting here means we tried for data but didn't get it. That
+ means we have an incomplete instruction of some sort. Just
+ print the first byte as a prefix or a .byte pseudo-op. */
+ if (codep > inbuf)
+ {
+ name = prefix_name (inbuf[0], orig_sizeflag);
+ if (name != NULL)
+ (*info->fprintf_func) (info->stream, "%s", name);
+ else
+ {
+ /* Just print the first byte as a .byte instruction. */
+ (*info->fprintf_func) (info->stream, ".byte 0x%x",
+ (unsigned int) inbuf[0]);
+ }
+
+ return 1;
+ }
+
+ return -1;
+ }
+#endif
+
+ ckprefix ();
+
+ insn_codep = codep;
+
+ FETCH_DATA (info, codep + 1);
+ two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
+
+ obufp = obuf;
+
+ if ((prefixes & PREFIX_FWAIT)
+ && ((*codep < 0xd8) || (*codep > 0xdf)))
+ {
+ const char *name;
+
+ /* fwait not followed by floating point instruction. Print the
+ first prefix, which is probably fwait itself. */
+ name = prefix_name (inbuf[0], orig_sizeflag);
+ if (name == NULL)
+ name = INTERNAL_DISASSEMBLER_ERROR;
+ (*info->fprintf_func) (info->stream, "%s", name);
+ return 1;
+ }
+
+ if (*codep == 0x0f)
+ {
+ FETCH_DATA (info, codep + 2);
+ if (intel_syntax)
+ dp = &dis386_twobyte_intel[*++codep];
+ else
+ dp = &dis386_twobyte_att[*++codep];
+ need_modrm = twobyte_has_modrm[*codep];
+ uses_f3_prefix = twobyte_uses_f3_prefix[*codep];
+ }
+ else
+ {
+ if (intel_syntax)
+ dp = &dis386_intel[*codep];
+ else
+ dp = &dis386_att[*codep];
+ need_modrm = onebyte_has_modrm[*codep];
+ uses_f3_prefix = 0;
+ }
+ codep++;
+
+ if (!uses_f3_prefix && (prefixes & PREFIX_REPZ))
+ {
+ oappend ("repz ");
+ used_prefixes |= PREFIX_REPZ;
+ }
+ if (prefixes & PREFIX_REPNZ)
+ {
+ oappend ("repnz ");
+ used_prefixes |= PREFIX_REPNZ;
+ }
+ if (prefixes & PREFIX_LOCK)
+ {
+ oappend ("lock ");
+ used_prefixes |= PREFIX_LOCK;
+ }
+
+ if (prefixes & PREFIX_DATA)
+ sizeflag ^= DFLAG;
+
+ if (prefixes & PREFIX_ADDR)
+ {
+ sizeflag ^= AFLAG;
+ if (sizeflag & AFLAG)
+ oappend ("addr32 ");
+ else
+ oappend ("addr16 ");
+ used_prefixes |= PREFIX_ADDR;
+ }
+
+ if (need_modrm)
+ {
+ FETCH_DATA (info, codep + 1);
+ mod = (*codep >> 6) & 3;
+ reg = (*codep >> 3) & 7;
+ rm = *codep & 7;
+ }
+
+ if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
+ {
+ dofloat (sizeflag);
+ }
+ else
+ {
+ if (dp->name == NULL)
+ {
+ switch(dp->bytemode2)
+ {
+ case USE_GROUPS:
+ dp = &grps[dp->bytemode1][reg];
+ break;
+ case USE_PREFIX_USER_TABLE:
+ dp = &prefix_user_table[dp->bytemode1][prefixes & PREFIX_REPZ ? 1 : 0];
+ used_prefixes |= (prefixes & PREFIX_REPZ);
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ break;
+ }
+ }
+
+ putop (dp->name, sizeflag);
+
+ obufp = op1out;
+ op_ad = 2;
+ if (dp->op1)
+ (*dp->op1)(dp->bytemode1, sizeflag);
+
+ obufp = op2out;
+ op_ad = 1;
+ if (dp->op2)
+ (*dp->op2)(dp->bytemode2, sizeflag);
+
+ obufp = op3out;
+ op_ad = 0;
+ if (dp->op3)
+ (*dp->op3)(dp->bytemode3, sizeflag);
+ }
+
+ /* See if any prefixes were not used. If so, print the first one
+ separately. If we don't do this, we'll wind up printing an
+ instruction stream which does not precisely correspond to the
+ bytes we are disassembling. */
+ if ((prefixes & ~used_prefixes) != 0)
+ {
+ const char *name;
+
+ name = prefix_name (inbuf[0], orig_sizeflag);
+ if (name == NULL)
+ name = INTERNAL_DISASSEMBLER_ERROR;
+ (*info->fprintf_func) (info->stream, "%s", name);
+ return 1;
+ }
+
+ obufp = obuf + strlen (obuf);
+ for (i = strlen (obuf); i < 6; i++)
+ oappend (" ");
+ oappend (" ");
+ (*info->fprintf_func) (info->stream, "%s", obuf);
+
+ /* The enter and bound instructions are printed with operands in the same
+ order as the intel book; everything else is printed in reverse order. */
+ if (intel_syntax || two_source_ops)
+ {
+ first = op1out;
+ second = op2out;
+ third = op3out;
+ op_ad = op_index[0];
+ op_index[0] = op_index[2];
+ op_index[2] = op_ad;
+ }
+ else
+ {
+ first = op3out;
+ second = op2out;
+ third = op1out;
+ }
+ needcomma = 0;
+ if (*first)
+ {
+ if (op_index[0] != -1)
+ (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", first);
+ needcomma = 1;
+ }
+ if (*second)
+ {
+ if (needcomma)
+ (*info->fprintf_func) (info->stream, ",");
+ if (op_index[1] != -1)
+ (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", second);
+ needcomma = 1;
+ }
+ if (*third)
+ {
+ if (needcomma)
+ (*info->fprintf_func) (info->stream, ",");
+ if (op_index[2] != -1)
+ (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", third);
+ }
+ return codep - inbuf;
+}
+
+static const char *float_mem_att[] = {
+ /* d8 */
+ "fadds",
+ "fmuls",
+ "fcoms",
+ "fcomps",
+ "fsubs",
+ "fsubrs",
+ "fdivs",
+ "fdivrs",
+ /* d9 */
+ "flds",
+ "(bad)",
+ "fsts",
+ "fstps",
+ "fldenv",
+ "fldcw",
+ "fNstenv",
+ "fNstcw",
+ /* da */
+ "fiaddl",
+ "fimull",
+ "ficoml",
+ "ficompl",
+ "fisubl",
+ "fisubrl",
+ "fidivl",
+ "fidivrl",
+ /* db */
+ "fildl",
+ "(bad)",
+ "fistl",
+ "fistpl",
+ "(bad)",
+ "fldt",
+ "(bad)",
+ "fstpt",
+ /* dc */
+ "faddl",
+ "fmull",
+ "fcoml",
+ "fcompl",
+ "fsubl",
+ "fsubrl",
+ "fdivl",
+ "fdivrl",
+ /* dd */
+ "fldl",
+ "(bad)",
+ "fstl",
+ "fstpl",
+ "frstor",
+ "(bad)",
+ "fNsave",
+ "fNstsw",
+ /* de */
+ "fiadd",
+ "fimul",
+ "ficom",
+ "ficomp",
+ "fisub",
+ "fisubr",
+ "fidiv",
+ "fidivr",
+ /* df */
+ "fild",
+ "(bad)",
+ "fist",
+ "fistp",
+ "fbld",
+ "fildll",
+ "fbstp",
+ "fistpll",
+};
+
+static const char *float_mem_intel[] = {
+ /* d8 */
+ "fadd",
+ "fmul",
+ "fcom",
+ "fcomp",
+ "fsub",
+ "fsubr",
+ "fdiv",
+ "fdivr",
+ /* d9 */
+ "fld",
+ "(bad)",
+ "fst",
+ "fstp",
+ "fldenv",
+ "fldcw",
+ "fNstenv",
+ "fNstcw",
+ /* da */
+ "fiadd",
+ "fimul",
+ "ficom",
+ "ficomp",
+ "fisub",
+ "fisubr",
+ "fidiv",
+ "fidivr",
+ /* db */
+ "fild",
+ "(bad)",
+ "fist",
+ "fistp",
+ "(bad)",
+ "fld",
+ "(bad)",
+ "fstp",
+ /* dc */
+ "fadd",
+ "fmul",
+ "fcom",
+ "fcomp",
+ "fsub",
+ "fsubr",
+ "fdiv",
+ "fdivr",
+ /* dd */
+ "fld",
+ "(bad)",
+ "fst",
+ "fstp",
+ "frstor",
+ "(bad)",
+ "fNsave",
+ "fNstsw",
+ /* de */
+ "fiadd",
+ "fimul",
+ "ficom",
+ "ficomp",
+ "fisub",
+ "fisubr",
+ "fidiv",
+ "fidivr",
+ /* df */
+ "fild",
+ "(bad)",
+ "fist",
+ "fistp",
+ "fbld",
+ "fild",
+ "fbstp",
+ "fistpll",
+};
+
+#define ST OP_ST, 0
+#define STi OP_STi, 0
+
+#define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0
+#define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0
+#define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0
+#define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0
+#define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0
+#define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0
+#define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0
+#define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0
+#define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0
+
+static const struct dis386 float_reg[][8] = {
+ /* d8 */
+ {
+ { "fadd", ST, STi, XX },
+ { "fmul", ST, STi, XX },
+ { "fcom", STi, XX, XX },
+ { "fcomp", STi, XX, XX },
+ { "fsub", ST, STi, XX },
+ { "fsubr", ST, STi, XX },
+ { "fdiv", ST, STi, XX },
+ { "fdivr", ST, STi, XX },
+ },
+ /* d9 */
+ {
+ { "fld", STi, XX, XX },
+ { "fxch", STi, XX, XX },
+ { FGRPd9_2 },
+ { "(bad)", XX, XX, XX },
+ { FGRPd9_4 },
+ { FGRPd9_5 },
+ { FGRPd9_6 },
+ { FGRPd9_7 },
+ },
+ /* da */
+ {
+ { "fcmovb", ST, STi, XX },
+ { "fcmove", ST, STi, XX },
+ { "fcmovbe",ST, STi, XX },
+ { "fcmovu", ST, STi, XX },
+ { "(bad)", XX, XX, XX },
+ { FGRPda_5 },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ },
+ /* db */
+ {
+ { "fcmovnb",ST, STi, XX },
+ { "fcmovne",ST, STi, XX },
+ { "fcmovnbe",ST, STi, XX },
+ { "fcmovnu",ST, STi, XX },
+ { FGRPdb_4 },
+ { "fucomi", ST, STi, XX },
+ { "fcomi", ST, STi, XX },
+ { "(bad)", XX, XX, XX },
+ },
+ /* dc */
+ {
+ { "fadd", STi, ST, XX },
+ { "fmul", STi, ST, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+#if UNIXWARE_COMPAT
+ { "fsub", STi, ST, XX },
+ { "fsubr", STi, ST, XX },
+ { "fdiv", STi, ST, XX },
+ { "fdivr", STi, ST, XX },
+#else
+ { "fsubr", STi, ST, XX },
+ { "fsub", STi, ST, XX },
+ { "fdivr", STi, ST, XX },
+ { "fdiv", STi, ST, XX },
+#endif
+ },
+ /* dd */
+ {
+ { "ffree", STi, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "fst", STi, XX, XX },
+ { "fstp", STi, XX, XX },
+ { "fucom", STi, XX, XX },
+ { "fucomp", STi, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ },
+ /* de */
+ {
+ { "faddp", STi, ST, XX },
+ { "fmulp", STi, ST, XX },
+ { "(bad)", XX, XX, XX },
+ { FGRPde_3 },
+#if UNIXWARE_COMPAT
+ { "fsubp", STi, ST, XX },
+ { "fsubrp", STi, ST, XX },
+ { "fdivp", STi, ST, XX },
+ { "fdivrp", STi, ST, XX },
+#else
+ { "fsubrp", STi, ST, XX },
+ { "fsubp", STi, ST, XX },
+ { "fdivrp", STi, ST, XX },
+ { "fdivp", STi, ST, XX },
+#endif
+ },
+ /* df */
+ {
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { FGRPdf_4 },
+ { "fucomip",ST, STi, XX },
+ { "fcomip", ST, STi, XX },
+ { "(bad)", XX, XX, XX },
+ },
+};
+
+
+static char *fgrps[][8] = {
+ /* d9_2 0 */
+ {
+ "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* d9_4 1 */
+ {
+ "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+ },
+
+ /* d9_5 2 */
+ {
+ "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+ },
+
+ /* d9_6 3 */
+ {
+ "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+ },
+
+ /* d9_7 4 */
+ {
+ "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+ },
+
+ /* da_5 5 */
+ {
+ "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* db_4 6 */
+ {
+ "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+ "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+ },
+
+ /* de_3 7 */
+ {
+ "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* df_4 8 */
+ {
+ "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+};
+
+static void
+dofloat (sizeflag)
+ int sizeflag;
+{
+ const struct dis386 *dp;
+ unsigned char floatop;
+
+ floatop = codep[-1];
+
+ if (mod != 3)
+ {
+ if (intel_syntax)
+ putop (float_mem_intel[(floatop - 0xd8 ) * 8 + reg], sizeflag);
+ else
+ putop (float_mem_att[(floatop - 0xd8 ) * 8 + reg], sizeflag);
+ obufp = op1out;
+ if (floatop == 0xdb)
+ OP_E (x_mode, sizeflag);
+ else if (floatop == 0xdd)
+ OP_E (d_mode, sizeflag);
+ else
+ OP_E (v_mode, sizeflag);
+ return;
+ }
+ codep++;
+
+ dp = &float_reg[floatop - 0xd8][reg];
+ if (dp->name == NULL)
+ {
+ putop (fgrps[dp->bytemode1][rm], sizeflag);
+
+ /* instruction fnstsw is only one with strange arg */
+ if (floatop == 0xdf && codep[-1] == 0xe0)
+ strcpy (op1out, names16[0]);
+ }
+ else
+ {
+ putop (dp->name, sizeflag);
+
+ obufp = op1out;
+ if (dp->op1)
+ (*dp->op1)(dp->bytemode1, sizeflag);
+ obufp = op2out;
+ if (dp->op2)
+ (*dp->op2)(dp->bytemode2, sizeflag);
+ }
+}
+
+/* ARGSUSED */
+static void
+OP_ST (ignore, sizeflag)
+ int ignore ATTRIBUTE_UNUSED;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ oappend ("%st");
+}
+
+/* ARGSUSED */
+static void
+OP_STi (ignore, sizeflag)
+ int ignore ATTRIBUTE_UNUSED;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ sprintf (scratchbuf, "%%st(%d)", rm);
+ oappend (scratchbuf);
+}
+
+
+/* capital letters in template are macros */
+static void
+putop (template, sizeflag)
+ const char *template;
+ int sizeflag;
+{
+ const char *p;
+
+ for (p = template; *p; p++)
+ {
+ switch (*p)
+ {
+ default:
+ *obufp++ = *p;
+ break;
+ case 'A':
+ if (intel_syntax)
+ break;
+ if (mod != 3
+#ifdef SUFFIX_ALWAYS
+ || (sizeflag & SUFFIX_ALWAYS)
+#endif
+ )
+ *obufp++ = 'b';
+ break;
+ case 'B':
+ if (intel_syntax)
+ break;
+#ifdef SUFFIX_ALWAYS
+ if (sizeflag & SUFFIX_ALWAYS)
+ *obufp++ = 'b';
+#endif
+ break;
+ case 'E': /* For jcxz/jecxz */
+ if (sizeflag & AFLAG)
+ *obufp++ = 'e';
+ break;
+ case 'L':
+ if (intel_syntax)
+ break;
+#ifdef SUFFIX_ALWAYS
+ if (sizeflag & SUFFIX_ALWAYS)
+ *obufp++ = 'l';
+#endif
+ break;
+ case 'N':
+ if ((prefixes & PREFIX_FWAIT) == 0)
+ *obufp++ = 'n';
+ else
+ used_prefixes |= PREFIX_FWAIT;
+ break;
+ case 'P':
+ if (intel_syntax)
+ break;
+ if ((prefixes & PREFIX_DATA)
+#ifdef SUFFIX_ALWAYS
+ || (sizeflag & SUFFIX_ALWAYS)
+#endif
+ )
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ }
+ break;
+ case 'Q':
+ if (intel_syntax)
+ break;
+ if (mod != 3
+#ifdef SUFFIX_ALWAYS
+ || (sizeflag & SUFFIX_ALWAYS)
+#endif
+ )
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ }
+ break;
+ case 'R':
+ if (intel_syntax)
+ {
+ if (sizeflag & DFLAG)
+ {
+ *obufp++ = 'd';
+ *obufp++ = 'q';
+ }
+ else
+ {
+ *obufp++ = 'w';
+ *obufp++ = 'd';
+ }
+ }
+ else
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case 'S':
+ if (intel_syntax)
+ break;
+#ifdef SUFFIX_ALWAYS
+ if (sizeflag & SUFFIX_ALWAYS)
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ }
+#endif
+ break;
+ case 'W':
+ /* operand size flag for cwtl, cbtw */
+ if (sizeflag & DFLAG)
+ *obufp++ = 'w';
+ else
+ *obufp++ = 'b';
+ if (intel_syntax)
+ {
+ if (sizeflag & DFLAG)
+ {
+ *obufp++ = 'd';
+ *obufp++ = 'e';
+ }
+ else
+ {
+ *obufp++ = 'w';
+ }
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ }
+ }
+ *obufp = 0;
+}
+
+static void
+oappend (s)
+ const char *s;
+{
+ strcpy (obufp, s);
+ obufp += strlen (s);
+}
+
+static void
+append_seg ()
+{
+ if (prefixes & PREFIX_CS)
+ {
+ oappend ("%cs:");
+ used_prefixes |= PREFIX_CS;
+ }
+ if (prefixes & PREFIX_DS)
+ {
+ oappend ("%ds:");
+ used_prefixes |= PREFIX_DS;
+ }
+ if (prefixes & PREFIX_SS)
+ {
+ oappend ("%ss:");
+ used_prefixes |= PREFIX_SS;
+ }
+ if (prefixes & PREFIX_ES)
+ {
+ oappend ("%es:");
+ used_prefixes |= PREFIX_ES;
+ }
+ if (prefixes & PREFIX_FS)
+ {
+ oappend ("%fs:");
+ used_prefixes |= PREFIX_FS;
+ }
+ if (prefixes & PREFIX_GS)
+ {
+ oappend ("%gs:");
+ used_prefixes |= PREFIX_GS;
+ }
+}
+
+static void
+OP_indirE (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ if (!intel_syntax)
+ oappend ("*");
+ OP_E (bytemode, sizeflag);
+}
+
+static void
+OP_E (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ int disp;
+
+ /* skip mod/rm byte */
+ codep++;
+
+ if (mod == 3)
+ {
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend (names8[rm]);
+ break;
+ case w_mode:
+ oappend (names16[rm]);
+ break;
+ case d_mode:
+ oappend (names32[rm]);
+ break;
+ case v_mode:
+ if (sizeflag & DFLAG)
+ oappend (names32[rm]);
+ else
+ oappend (names16[rm]);
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case 0:
+ if ( !(codep[-2] == 0xAE && codep[-1] == 0xF8 /* sfence */))
+ BadOp(); /* bad sfence,lea,lds,les,lfs,lgs,lss modrm */
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ break;
+ }
+ return;
+ }
+
+ disp = 0;
+ append_seg ();
+
+ if (sizeflag & AFLAG) /* 32 bit address mode */
+ {
+ int havesib;
+ int havebase;
+ int base;
+ int index = 0;
+ int scale = 0;
+
+ havesib = 0;
+ havebase = 1;
+ base = rm;
+
+ if (base == 4)
+ {
+ havesib = 1;
+ FETCH_DATA (the_info, codep + 1);
+ scale = (*codep >> 6) & 3;
+ index = (*codep >> 3) & 7;
+ base = *codep & 7;
+ codep++;
+ }
+
+ switch (mod)
+ {
+ case 0:
+ if (base == 5)
+ {
+ havebase = 0;
+ disp = get32 ();
+ }
+ break;
+ case 1:
+ FETCH_DATA (the_info, codep + 1);
+ disp = *codep++;
+ if ((disp & 0x80) != 0)
+ disp -= 0x100;
+ break;
+ case 2:
+ disp = get32 ();
+ break;
+ }
+
+ if (!intel_syntax)
+ if (mod != 0 || base == 5)
+ {
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
+ }
+
+ if (havebase || (havesib && (index != 4 || scale != 0)))
+ {
+ if (intel_syntax)
+ {
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend("BYTE PTR ");
+ break;
+ case w_mode:
+ oappend("WORD PTR ");
+ break;
+ case v_mode:
+ oappend("DWORD PTR ");
+ break;
+ case d_mode:
+ oappend("QWORD PTR ");
+ break;
+ case x_mode:
+ oappend("XWORD PTR ");
+ break;
+ default:
+ break;
+ }
+ }
+ *obufp++ = open_char;
+ *obufp = '\0';
+ if (havebase)
+ oappend (names32[base]);
+ if (havesib)
+ {
+ if (index != 4)
+ {
+ if (intel_syntax)
+ {
+ if (havebase)
+ {
+ *obufp++ = separator_char;
+ *obufp = '\0';
+ }
+ sprintf (scratchbuf, "%s", names32[index]);
+ }
+ else
+ sprintf (scratchbuf, ",%s", names32[index]);
+ oappend (scratchbuf);
+ }
+ if (!intel_syntax
+ || (intel_syntax
+ && bytemode != b_mode
+ && bytemode != w_mode
+ && bytemode != v_mode))
+ {
+ *obufp++ = scale_char;
+ *obufp = '\0';
+ sprintf (scratchbuf, "%d", 1 << scale);
+ oappend (scratchbuf);
+ }
+ }
+ if (intel_syntax)
+ if (mod != 0 || base == 5)
+ {
+ /* Don't print zero displacements */
+ if (disp > 0)
+ {
+ sprintf (scratchbuf, "+%d", disp);
+ oappend (scratchbuf);
+ }
+ else if (disp < 0)
+ {
+ sprintf (scratchbuf, "%d", disp);
+ oappend (scratchbuf);
+ }
+ }
+
+ *obufp++ = close_char;
+ *obufp = '\0';
+ }
+ else if (intel_syntax)
+ {
+ if (mod != 0 || base == 5)
+ {
+ if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+ | PREFIX_ES | PREFIX_FS | PREFIX_GS))
+ ;
+ else
+ {
+ oappend (names_seg[3]);
+ oappend (":");
+ }
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
+ }
+ }
+ }
+ else
+ { /* 16 bit address mode */
+ switch (mod)
+ {
+ case 0:
+ if (rm == 6)
+ {
+ disp = get16 ();
+ if ((disp & 0x8000) != 0)
+ disp -= 0x10000;
+ }
+ break;
+ case 1:
+ FETCH_DATA (the_info, codep + 1);
+ disp = *codep++;
+ if ((disp & 0x80) != 0)
+ disp -= 0x100;
+ break;
+ case 2:
+ disp = get16 ();
+ if ((disp & 0x8000) != 0)
+ disp -= 0x10000;
+ break;
+ }
+
+ if (!intel_syntax)
+ if (mod != 0 || rm == 6)
+ {
+ sprintf (scratchbuf, "%d", disp);
+ oappend (scratchbuf);
+ }
+
+ if (mod != 0 || rm != 6)
+ {
+ *obufp++ = open_char;
+ *obufp = '\0';
+ oappend (index16[rm]);
+ *obufp++ = close_char;
+ *obufp = '\0';
+ }
+ }
+}
+
+static void
+OP_G (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend (names8[reg]);
+ break;
+ case w_mode:
+ oappend (names16[reg]);
+ break;
+ case d_mode:
+ oappend (names32[reg]);
+ break;
+ case v_mode:
+ if (sizeflag & DFLAG)
+ oappend (names32[reg]);
+ else
+ oappend (names16[reg]);
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ break;
+ }
+}
+
+static int
+get32 ()
+{
+ int x = 0;
+
+ FETCH_DATA (the_info, codep + 4);
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ x |= (*codep++ & 0xff) << 16;
+ x |= (*codep++ & 0xff) << 24;
+ return x;
+}
+
+static int
+get16 ()
+{
+ int x = 0;
+
+ FETCH_DATA (the_info, codep + 2);
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ return x;
+}
+
+static void
+set_op (op)
+ unsigned int op;
+{
+ op_index[op_ad] = op_ad;
+ op_address[op_ad] = op;
+}
+
+static void
+OP_REG (code, sizeflag)
+ int code;
+ int sizeflag;
+{
+ const char *s;
+
+ switch (code)
+ {
+ case indir_dx_reg:
+ s = "(%dx)";
+ break;
+ case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+ case sp_reg: case bp_reg: case si_reg: case di_reg:
+ s = names16[code - ax_reg];
+ break;
+ case es_reg: case ss_reg: case cs_reg:
+ case ds_reg: case fs_reg: case gs_reg:
+ s = names_seg[code - es_reg];
+ break;
+ case al_reg: case ah_reg: case cl_reg: case ch_reg:
+ case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+ s = names8[code - al_reg];
+ break;
+ case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+ case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+ if (sizeflag & DFLAG)
+ s = names32[code - eAX_reg];
+ else
+ s = names16[code - eAX_reg];
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ default:
+ s = INTERNAL_DISASSEMBLER_ERROR;
+ break;
+ }
+ oappend (s);
+}
+
+static void
+OP_I (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ int op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ FETCH_DATA (the_info, codep + 1);
+ op = *codep++ & 0xff;
+ break;
+ case v_mode:
+ if (sizeflag & DFLAG)
+ op = get32 ();
+ else
+ op = get16 ();
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case w_mode:
+ op = get16 ();
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ return;
+ }
+
+ if (intel_syntax)
+ sprintf (scratchbuf, "0x%x", op);
+ else
+ sprintf (scratchbuf, "$0x%x", op);
+ oappend (scratchbuf);
+ scratchbuf[0] = '\0';
+}
+
+static void
+OP_sI (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ int op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ FETCH_DATA (the_info, codep + 1);
+ op = *codep++;
+ if ((op & 0x80) != 0)
+ op -= 0x100;
+ break;
+ case v_mode:
+ if (sizeflag & DFLAG)
+ op = get32 ();
+ else
+ {
+ op = get16();
+ if ((op & 0x8000) != 0)
+ op -= 0x10000;
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case w_mode:
+ op = get16 ();
+ if ((op & 0x8000) != 0)
+ op -= 0x10000;
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ return;
+ }
+ if (intel_syntax)
+ sprintf (scratchbuf, "%d", op);
+ else
+ sprintf (scratchbuf, "$0x%x", op);
+ oappend (scratchbuf);
+}
+
+static void
+OP_J (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ int disp;
+ int mask = -1;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ FETCH_DATA (the_info, codep + 1);
+ disp = *codep++;
+ if ((disp & 0x80) != 0)
+ disp -= 0x100;
+ break;
+ case v_mode:
+ if (sizeflag & DFLAG)
+ disp = get32 ();
+ else
+ {
+ disp = get16 ();
+ /* for some reason, a data16 prefix on a jump instruction
+ means that the pc is masked to 16 bits after the
+ displacement is added! */
+ mask = 0xffff;
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ return;
+ }
+ disp = (start_pc + codep - start_codep + disp) & mask;
+ set_op (disp);
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+static void
+OP_SEG (dummy, sizeflag)
+ int dummy ATTRIBUTE_UNUSED;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ static char *sreg[] = {
+ "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+ };
+
+ oappend (sreg[reg]);
+}
+
+/* ARGSUSED */
+static void
+OP_DIR (dummy, sizeflag)
+ int dummy ATTRIBUTE_UNUSED;
+ int sizeflag;
+{
+ int seg, offset;
+
+ if (sizeflag & DFLAG)
+ {
+ offset = get32 ();
+ seg = get16 ();
+ }
+ else
+ {
+ offset = get16 ();
+ seg = get16 ();
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+static void
+OP_OFF (ignore, sizeflag)
+ int ignore ATTRIBUTE_UNUSED;
+ int sizeflag;
+{
+ int off;
+
+ append_seg ();
+
+ if (sizeflag & AFLAG)
+ off = get32 ();
+ else
+ off = get16 ();
+
+ if (intel_syntax)
+ {
+ if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+ | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+ {
+ oappend (names_seg[3]);
+ oappend (":");
+ }
+ }
+ sprintf (scratchbuf, "0x%x", off);
+ oappend (scratchbuf);
+}
+
+static void
+ptr_reg (code, sizeflag)
+ int code;
+ int sizeflag;
+{
+ const char *s;
+ oappend ("(");
+ if (sizeflag & AFLAG)
+ s = names32[code - eAX_reg];
+ else
+ s = names16[code - eAX_reg];
+ oappend (s);
+ oappend (")");
+}
+
+static void
+OP_ESreg (code, sizeflag)
+ int code;
+ int sizeflag;
+{
+ oappend ("%es:");
+ ptr_reg (code, sizeflag);
+}
+
+static void
+OP_DSreg (code, sizeflag)
+ int code;
+ int sizeflag;
+{
+ if ((prefixes
+ & (PREFIX_CS
+ | PREFIX_DS
+ | PREFIX_SS
+ | PREFIX_ES
+ | PREFIX_FS
+ | PREFIX_GS)) == 0)
+ prefixes |= PREFIX_DS;
+ append_seg();
+ ptr_reg (code, sizeflag);
+}
+
+/* ARGSUSED */
+static void
+OP_C (dummy, sizeflag)
+ int dummy ATTRIBUTE_UNUSED;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ sprintf (scratchbuf, "%%cr%d", reg);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+static void
+OP_D (dummy, sizeflag)
+ int dummy ATTRIBUTE_UNUSED;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ sprintf (scratchbuf, "%%db%d", reg);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+static void
+OP_T (dummy, sizeflag)
+ int dummy ATTRIBUTE_UNUSED;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ sprintf (scratchbuf, "%%tr%d", reg);
+ oappend (scratchbuf);
+}
+
+static void
+OP_Rd (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ if (mod == 3)
+ OP_E (bytemode, sizeflag);
+ else
+ BadOp();
+}
+
+static void
+OP_MMX (ignore, sizeflag)
+ int ignore ATTRIBUTE_UNUSED;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ sprintf (scratchbuf, "%%mm%d", reg);
+ oappend (scratchbuf);
+}
+
+static void
+OP_XMM (bytemode, sizeflag)
+ int bytemode ATTRIBUTE_UNUSED;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ sprintf (scratchbuf, "%%xmm%d", reg);
+ oappend (scratchbuf);
+}
+
+static void
+OP_EM (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ if (mod != 3)
+ {
+ OP_E (bytemode, sizeflag);
+ return;
+ }
+
+ codep++;
+ sprintf (scratchbuf, "%%mm%d", rm);
+ oappend (scratchbuf);
+}
+
+static void
+OP_EX (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ if (mod != 3)
+ {
+ OP_E (bytemode, sizeflag);
+ return;
+ }
+
+ codep++;
+ sprintf (scratchbuf, "%%xmm%d", rm);
+ oappend (scratchbuf);
+}
+
+static void
+OP_MS (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ if (mod == 3)
+ OP_EM (bytemode, sizeflag);
+ else
+ BadOp();
+}
+
+static const char *Suffix3DNow[] = {
+/* 00 */ NULL, NULL, NULL, NULL,
+/* 04 */ NULL, NULL, NULL, NULL,
+/* 08 */ NULL, NULL, NULL, NULL,
+/* 0C */ "pi2fw", "pi2fd", NULL, NULL,
+/* 10 */ NULL, NULL, NULL, NULL,
+/* 14 */ NULL, NULL, NULL, NULL,
+/* 18 */ NULL, NULL, NULL, NULL,
+/* 1C */ "pf2iw", "pf2id", NULL, NULL,
+/* 20 */ NULL, NULL, NULL, NULL,
+/* 24 */ NULL, NULL, NULL, NULL,
+/* 28 */ NULL, NULL, NULL, NULL,
+/* 2C */ NULL, NULL, NULL, NULL,
+/* 30 */ NULL, NULL, NULL, NULL,
+/* 34 */ NULL, NULL, NULL, NULL,
+/* 38 */ NULL, NULL, NULL, NULL,
+/* 3C */ NULL, NULL, NULL, NULL,
+/* 40 */ NULL, NULL, NULL, NULL,
+/* 44 */ NULL, NULL, NULL, NULL,
+/* 48 */ NULL, NULL, NULL, NULL,
+/* 4C */ NULL, NULL, NULL, NULL,
+/* 50 */ NULL, NULL, NULL, NULL,
+/* 54 */ NULL, NULL, NULL, NULL,
+/* 58 */ NULL, NULL, NULL, NULL,
+/* 5C */ NULL, NULL, NULL, NULL,
+/* 60 */ NULL, NULL, NULL, NULL,
+/* 64 */ NULL, NULL, NULL, NULL,
+/* 68 */ NULL, NULL, NULL, NULL,
+/* 6C */ NULL, NULL, NULL, NULL,
+/* 70 */ NULL, NULL, NULL, NULL,
+/* 74 */ NULL, NULL, NULL, NULL,
+/* 78 */ NULL, NULL, NULL, NULL,
+/* 7C */ NULL, NULL, NULL, NULL,
+/* 80 */ NULL, NULL, NULL, NULL,
+/* 84 */ NULL, NULL, NULL, NULL,
+/* 88 */ NULL, NULL, "pfnacc", NULL,
+/* 8C */ NULL, NULL, "pfpnacc", NULL,
+/* 90 */ "pfcmpge", NULL, NULL, NULL,
+/* 94 */ "pfmin", NULL, "pfrcp", "pfrsqrt",
+/* 98 */ NULL, NULL, "pfsub", NULL,
+/* 9C */ NULL, NULL, "pfadd", NULL,
+/* A0 */ "pfcmpgt", NULL, NULL, NULL,
+/* A4 */ "pfmax", NULL, "pfrcpit1", "pfrsqit1",
+/* A8 */ NULL, NULL, "pfsubr", NULL,
+/* AC */ NULL, NULL, "pfacc", NULL,
+/* B0 */ "pfcmpeq", NULL, NULL, NULL,
+/* B4 */ "pfmul", NULL, "pfrcpit2", "pfmulhrw",
+/* B8 */ NULL, NULL, NULL, "pswapd",
+/* BC */ NULL, NULL, NULL, "pavgusb",
+/* C0 */ NULL, NULL, NULL, NULL,
+/* C4 */ NULL, NULL, NULL, NULL,
+/* C8 */ NULL, NULL, NULL, NULL,
+/* CC */ NULL, NULL, NULL, NULL,
+/* D0 */ NULL, NULL, NULL, NULL,
+/* D4 */ NULL, NULL, NULL, NULL,
+/* D8 */ NULL, NULL, NULL, NULL,
+/* DC */ NULL, NULL, NULL, NULL,
+/* E0 */ NULL, NULL, NULL, NULL,
+/* E4 */ NULL, NULL, NULL, NULL,
+/* E8 */ NULL, NULL, NULL, NULL,
+/* EC */ NULL, NULL, NULL, NULL,
+/* F0 */ NULL, NULL, NULL, NULL,
+/* F4 */ NULL, NULL, NULL, NULL,
+/* F8 */ NULL, NULL, NULL, NULL,
+/* FC */ NULL, NULL, NULL, NULL,
+};
+
+static void
+OP_3DNowSuffix (bytemode, sizeflag)
+ int bytemode ATTRIBUTE_UNUSED;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ const char *mnemonic;
+
+ FETCH_DATA (the_info, codep + 1);
+ /* AMD 3DNow! instructions are specified by an opcode suffix in the
+ place where an 8-bit immediate would normally go. ie. the last
+ byte of the instruction. */
+ obufp = obuf + strlen(obuf);
+ mnemonic = Suffix3DNow[*codep++ & 0xff];
+ if (mnemonic)
+ oappend (mnemonic);
+ else
+ {
+ /* Since a variable sized modrm/sib chunk is between the start
+ of the opcode (0x0f0f) and the opcode suffix, we need to do
+ all the modrm processing first, and don't know until now that
+ we have a bad opcode. This necessitates some cleaning up. */
+ op1out[0] = '\0';
+ op2out[0] = '\0';
+ BadOp();
+ }
+}
+
+
+static const char *simd_cmp_op [] = {
+ "eq",
+ "lt",
+ "le",
+ "unord",
+ "neq",
+ "nlt",
+ "nle",
+ "ord"
+};
+
+static void
+OP_SIMD_Suffix (bytemode, sizeflag)
+ int bytemode ATTRIBUTE_UNUSED;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ unsigned int cmp_type;
+
+ FETCH_DATA (the_info, codep + 1);
+ obufp = obuf + strlen(obuf);
+ cmp_type = *codep++ & 0xff;
+ if (cmp_type < 8)
+ {
+ sprintf (scratchbuf, "cmp%s%cs",
+ simd_cmp_op[cmp_type],
+ prefixes & PREFIX_REPZ ? 's' : 'p');
+ used_prefixes |= (prefixes & PREFIX_REPZ);
+ oappend (scratchbuf);
+ }
+ else
+ {
+ /* We have a bad extension byte. Clean up. */
+ op1out[0] = '\0';
+ op2out[0] = '\0';
+ BadOp();
+ }
+}
+
+static void
+SIMD_Fixup (extrachar, sizeflag)
+ int extrachar;
+ int sizeflag ATTRIBUTE_UNUSED;
+{
+ /* Change movlps/movhps to movhlps/movlhps for 2 register operand
+ forms of these instructions. */
+ if (mod == 3)
+ {
+ char *p = obuf + strlen(obuf);
+ *(p+1) = '\0';
+ *p = *(p-1);
+ *(p-1) = *(p-2);
+ *(p-2) = *(p-3);
+ *(p-3) = extrachar;
+ }
+}
+
+static void BadOp (void)
+{
+ codep = insn_codep + 1; /* throw away prefixes and 1st. opcode byte */
+ oappend ("(bad)");
+}
Index: 2.6.x-xfs/arch/i386/kdb/kdb_cmds
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kdb/kdb_cmds 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/arch/i386/kdb/kdb_cmds 2005-12-20 16:50:55.842921316 +1100
@@ -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
Index: 2.6.x-xfs/arch/i386/kdb/kdba_bp.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kdb/kdba_bp.c 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/arch/i386/kdb/kdba_bp.c 2005-12-20 16:50:55.844874171 +1100
@@ -0,0 +1,780 @@
+/*
+ * 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.
+ */
+
+static kdbhard_bp_t kdb_hardbreaks[KDB_MAXHARDBPT];
+
+/*
+ * kdba_db_trap
+ *
+ * Perform breakpoint processing upon entry to the
+ * processor debugger fault. Determine and print
+ * the active breakpoint.
+ *
+ * Parameters:
+ * regs Exception frame containing machine register state
+ * error Error number passed to kdb.
+ * Outputs:
+ * None.
+ * Returns:
+ * KDB_DB_BPT Standard instruction or data breakpoint encountered
+ * KDB_DB_SS Single Step fault ('ss' command or end of 'ssb' command)
+ * KDB_DB_SSB Single Step fault, caller should continue ('ssb' command)
+ * KDB_DB_SSBPT Single step over breakpoint
+ * KDB_DB_NOBPT No existing kdb breakpoint matches this debug exception
+ * Locking:
+ * None.
+ * Remarks:
+ * Yup, there be goto's here.
+ *
+ * If multiple processors receive debug exceptions simultaneously,
+ * one may be waiting at the kdb fence in kdb() while the user
+ * issues a 'bc' command to clear the breakpoint the processor
+ * which is waiting has already encountered. If this is the case,
+ * the debug registers will no longer match any entry in the
+ * breakpoint table, and we'll return the value KDB_DB_NOBPT.
+ * This can cause a panic in die_if_kernel(). It is safer to
+ * disable the breakpoint (bd), go until all processors are past
+ * the breakpoint then clear the breakpoint (bc). This code
+ * recognises a breakpoint even when disabled but not when it has
+ * been cleared.
+ *
+ * WARNING: This routine clears the debug state. It should be called
+ * once per debug and the result cached.
+ */
+
+kdb_dbtrap_t
+kdba_db_trap(struct pt_regs *regs, int error_unused)
+{
+ kdb_machreg_t dr6;
+ kdb_machreg_t dr7;
+ int rw, reg;
+ int i;
+ kdb_dbtrap_t rv = KDB_DB_BPT;
+ kdb_bp_t *bp;
+
+ if (KDB_NULL_REGS(regs))
+ return KDB_DB_NOBPT;
+
+ dr6 = kdba_getdr6();
+ dr7 = kdba_getdr7();
+
+ if (KDB_DEBUG(BP))
+ kdb_printf("kdb: dr6 0x%lx dr7 0x%lx\n", dr6, dr7);
+ if (dr6 & DR6_BS) {
+ if (KDB_STATE(SSBPT)) {
+ if (KDB_DEBUG(BP))
+ kdb_printf("ssbpt\n");
+ KDB_STATE_CLEAR(SSBPT);
+ for(i=0,bp=kdb_breakpoints;
+ i < KDB_MAXBPT;
+ i++, bp++) {
+ if (KDB_DEBUG(BP))
+ kdb_printf("bp 0x%p enabled %d delayed %d global %d cpu %d\n",
+ bp, bp->bp_enabled, bp->bp_delayed, bp->bp_global, bp->bp_cpu);
+ if (!bp->bp_enabled)
+ continue;
+ if (!bp->bp_global && bp->bp_cpu != smp_processor_id())
+ continue;
+ if (KDB_DEBUG(BP))
+ kdb_printf("bp for this cpu\n");
+ if (bp->bp_delayed) {
+ bp->bp_delayed = 0;
+ if (KDB_DEBUG(BP))
+ kdb_printf("kdba_installbp\n");
+ kdba_installbp(regs, bp);
+ if (!KDB_STATE(DOING_SS)) {
+ regs->eflags &= ~EF_TF;
+ return(KDB_DB_SSBPT);
+ }
+ break;
+ }
+ }
+ if (i == KDB_MAXBPT) {
+ kdb_printf("kdb: Unable to find delayed breakpoint\n");
+ }
+ if (!KDB_STATE(DOING_SS)) {
+ regs->eflags &= ~EF_TF;
+ return(KDB_DB_NOBPT);
+ }
+ /* FALLTHROUGH */
+ }
+
+ /*
+ * KDB_STATE_DOING_SS is set when the kernel debugger is using
+ * the processor trap flag to single-step a processor. If a
+ * single step trap occurs and this flag is clear, the SS trap
+ * will be ignored by KDB and the kernel will be allowed to deal
+ * with it as necessary (e.g. for ptrace).
+ */
+ if (!KDB_STATE(DOING_SS))
+ goto unknown;
+
+ /* single step */
+ rv = KDB_DB_SS; /* Indicate single step */
+ if (KDB_STATE(DOING_SSB)) {
+ unsigned char instruction[2];
+
+ kdb_id1(regs->eip);
+ if (kdb_getarea(instruction, regs->eip) ||
+ (instruction[0]&0xf0) == 0xe0 || /* short disp jumps */
+ (instruction[0]&0xf0) == 0x70 || /* Misc. jumps */
+ instruction[0] == 0xc2 || /* ret */
+ instruction[0] == 0x9a || /* call */
+ (instruction[0]&0xf8) == 0xc8 || /* enter, leave, iret, int, */
+ ((instruction[0] == 0x0f) &&
+ ((instruction[1]&0xf0)== 0x80))
+ ) {
+ /*
+ * End the ssb command here.
+ */
+ KDB_STATE_CLEAR(DOING_SSB);
+ KDB_STATE_CLEAR(DOING_SS);
+ } else {
+ rv = KDB_DB_SSB; /* Indicate ssb - dismiss immediately */
+ }
+ } else {
+ /*
+ * Print current insn
+ */
+ kdb_printf("SS trap at ");
+ kdb_symbol_print(regs->eip, NULL, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+ kdb_id1(regs->eip);
+ KDB_STATE_CLEAR(DOING_SS);
+ }
+
+ if (rv != KDB_DB_SSB)
+ regs->eflags &= ~EF_TF;
+ }
+
+ if (dr6 & DR6_B0) {
+ rw = DR7_RW0(dr7);
+ reg = 0;
+ goto handle;
+ }
+
+ if (dr6 & DR6_B1) {
+ rw = DR7_RW1(dr7);
+ reg = 1;
+ goto handle;
+ }
+
+ if (dr6 & DR6_B2) {
+ rw = DR7_RW2(dr7);
+ reg = 2;
+ goto handle;
+ }
+
+ if (dr6 & DR6_B3) {
+ rw = DR7_RW3(dr7);
+ reg = 3;
+ goto handle;
+ }
+
+ if (rv > 0)
+ goto handled;
+
+ goto unknown; /* dismiss */
+
+handle:
+ /*
+ * Set Resume Flag
+ */
+ regs->eflags |= EF_RF;
+
+ /*
+ * Determine which breakpoint was encountered.
+ */
+ for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+ if (!(bp->bp_free)
+ && (bp->bp_global || bp->bp_cpu == smp_processor_id())
+ && (bp->bp_hard)
+ && (bp->bp_hard->bph_reg == reg)) {
+ /*
+ * Hit this breakpoint.
+ */
+ kdb_printf("%s breakpoint #%d at " kdb_bfd_vma_fmt "\n",
+ kdba_rwtypes[rw],
+ i, bp->bp_addr);
+
+ /*
+ * For an instruction breakpoint, disassemble
+ * the current instruction.
+ */
+ if (rw == 0) {
+ kdb_id1(regs->eip);
+ }
+
+ goto handled;
+ }
+ }
+
+unknown:
+ regs->eflags |= EF_RF; /* Supress further faults */
+ rv = KDB_DB_NOBPT; /* Cause kdb() to return */
+
+handled:
+
+ /*
+ * Clear the pending exceptions.
+ */
+ kdba_putdr6(0);
+
+ return rv;
+}
+
+/*
+ * kdba_bp_trap
+ *
+ * Perform breakpoint processing upon entry to the
+ * processor breakpoint instruction fault. Determine and print
+ * the active breakpoint.
+ *
+ * Parameters:
+ * regs Exception frame containing machine register state
+ * error Error number passed to kdb.
+ * Outputs:
+ * None.
+ * Returns:
+ * 0 Standard instruction or data breakpoint encountered
+ * 1 Single Step fault ('ss' command)
+ * 2 Single Step fault, caller should continue ('ssb' command)
+ * 3 No existing kdb breakpoint matches this debug exception
+ * Locking:
+ * None.
+ * Remarks:
+ *
+ * If multiple processors receive debug exceptions simultaneously,
+ * one may be waiting at the kdb fence in kdb() while the user
+ * issues a 'bc' command to clear the breakpoint the processor which
+ * is waiting has already encountered. If this is the case, the
+ * debug registers will no longer match any entry in the breakpoint
+ * table, and we'll return the value '3'. This can cause a panic
+ * in die_if_kernel(). It is safer to disable the breakpoint (bd),
+ * 'go' until all processors are past the breakpoint then clear the
+ * breakpoint (bc). This code recognises a breakpoint even when
+ * disabled but not when it has been cleared.
+ *
+ * WARNING: This routine resets the eip. It should be called
+ * once per breakpoint and the result cached.
+ */
+
+kdb_dbtrap_t
+kdba_bp_trap(struct pt_regs *regs, int error_unused)
+{
+ int i;
+ kdb_dbtrap_t rv;
+ kdb_bp_t *bp;
+
+ if (KDB_NULL_REGS(regs))
+ return KDB_DB_NOBPT;
+
+ /*
+ * Determine which breakpoint was encountered.
+ */
+ if (KDB_DEBUG(BP))
+ kdb_printf("kdba_bp_trap: eip=0x%lx (not adjusted) "
+ "eflags=0x%lx regs=0x%p esp=0x%lx\n",
+ regs->eip, regs->eflags, regs, regs->esp);
+
+ rv = KDB_DB_NOBPT; /* Cause kdb() to return */
+
+ for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+ if (bp->bp_free)
+ continue;
+ if (!bp->bp_global && bp->bp_cpu != smp_processor_id())
+ continue;
+ if ((void *)bp->bp_addr == (void *)(regs->eip - bp->bp_adjust)) {
+ /* Hit this breakpoint. */
+ regs->eip -= bp->bp_adjust;
+ kdb_printf("Instruction(i) breakpoint #%d at 0x%lx (adjusted)\n",
+ i, regs->eip);
+ kdb_id1(regs->eip);
+ rv = KDB_DB_BPT;
+ bp->bp_delay = 1;
+ /* SSBPT is set when the kernel debugger must single
+ * step a task in order to re-establish an instruction
+ * breakpoint which uses the instruction replacement
+ * mechanism. It is cleared by any action that removes
+ * the need to single-step the breakpoint.
+ */
+ KDB_STATE_SET(SSBPT);
+ break;
+ }
+ }
+
+ return rv;
+}
+
+/*
+ * kdba_handle_bp
+ *
+ * Handle an instruction-breakpoint trap. Called when re-installing
+ * an enabled breakpoint which has has the bp_delay bit set.
+ *
+ * Parameters:
+ * Returns:
+ * Locking:
+ * Remarks:
+ *
+ * Ok, we really need to:
+ * 1) Restore the original instruction byte
+ * 2) Single Step
+ * 3) Restore breakpoint instruction
+ * 4) Continue.
+ *
+ *
+ */
+
+static void
+kdba_handle_bp(struct pt_regs *regs, kdb_bp_t *bp)
+{
+ if (KDB_NULL_REGS(regs))
+ return;
+
+ if (KDB_DEBUG(BP))
+ kdb_printf("regs->eip = 0x%lx\n", regs->eip);
+
+ /*
+ * Setup single step
+ */
+ kdba_setsinglestep(regs);
+
+ /*
+ * Reset delay attribute
+ */
+ bp->bp_delay = 0;
+ bp->bp_delayed = 1;
+}
+
+
+/*
+ * kdba_bptype
+ *
+ * Return a string describing type of breakpoint.
+ *
+ * Parameters:
+ * bph Pointer to hardware breakpoint description
+ * Outputs:
+ * None.
+ * Returns:
+ * Character string.
+ * Locking:
+ * None.
+ * Remarks:
+ */
+
+char *
+kdba_bptype(kdbhard_bp_t *bph)
+{
+ char *mode;
+
+ mode = kdba_rwtypes[bph->bph_mode];
+
+ return mode;
+}
+
+/*
+ * kdba_printbpreg
+ *
+ * Print register name assigned to breakpoint
+ *
+ * Parameters:
+ * bph Pointer hardware breakpoint structure
+ * Outputs:
+ * None.
+ * Returns:
+ * None.
+ * Locking:
+ * None.
+ * Remarks:
+ */
+
+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) {
+ kdba_printbpreg(bp->bp_hard);
+ if (bp->bp_hard->bph_mode != 0) {
+ kdb_printf(" for %d bytes",
+ bp->bp_hard->bph_length+1);
+ }
+ }
+}
+
+/*
+ * kdba_parsebp
+ *
+ * Parse architecture dependent portion of the
+ * breakpoint command.
+ *
+ * Parameters:
+ * None.
+ * Outputs:
+ * None.
+ * Returns:
+ * Zero for success, a kdb diagnostic for failure
+ * Locking:
+ * None.
+ * Remarks:
+ * for Ia32 architure, data access, data write and
+ * I/O breakpoints are supported in addition to instruction
+ * breakpoints.
+ *
+ * {datar|dataw|io|inst} [length]
+ */
+
+int
+kdba_parsebp(int argc, const char **argv, int *nextargp, kdb_bp_t *bp)
+{
+ int nextarg = *nextargp;
+ int diag;
+ kdbhard_bp_t *bph = &bp->bp_template;
+
+ bph->bph_mode = 0; /* Default to instruction breakpoint */
+ bph->bph_length = 0; /* Length must be zero for insn bp */
+ if ((argc + 1) != nextarg) {
+ if (strnicmp(argv[nextarg], "datar", sizeof("datar")) == 0) {
+ bph->bph_mode = 3;
+ } else if (strnicmp(argv[nextarg], "dataw", sizeof("dataw")) == 0) {
+ bph->bph_mode = 1;
+ } else if (strnicmp(argv[nextarg], "io", sizeof("io")) == 0) {
+ bph->bph_mode = 2;
+ } else if (strnicmp(argv[nextarg], "inst", sizeof("inst")) == 0) {
+ bph->bph_mode = 0;
+ } else {
+ return KDB_ARGCOUNT;
+ }
+
+ bph->bph_length = 3; /* Default to 4 byte */
+
+ nextarg++;
+
+ if ((argc + 1) != nextarg) {
+ unsigned long len;
+
+ diag = kdbgetularg((char *)argv[nextarg],
+ &len);
+ if (diag)
+ return diag;
+
+
+ if ((len > 4) || (len == 3))
+ return KDB_BADLENGTH;
+
+ bph->bph_length = len;
+ bph->bph_length--; /* Normalize for debug register */
+ nextarg++;
+ }
+
+ if ((argc + 1) != nextarg)
+ return KDB_ARGCOUNT;
+
+ /*
+ * Indicate to architecture independent level that
+ * a hardware register assignment is required to enable
+ * this breakpoint.
+ */
+
+ bph->bph_free = 0;
+ } else {
+ if (KDB_DEBUG(BP))
+ kdb_printf("kdba_bp: no args, forcehw is %d\n", bp->bp_forcehw);
+ if (bp->bp_forcehw) {
+ /*
+ * We are forced to use a hardware register for this
+ * breakpoint because either the bph or bpha
+ * commands were used to establish this breakpoint.
+ */
+ bph->bph_free = 0;
+ } else {
+ /*
+ * Indicate to architecture dependent level that
+ * the instruction replacement breakpoint technique
+ * should be used for this breakpoint.
+ */
+ bph->bph_free = 1;
+ bp->bp_adjust = 1; /* software, int 3 is one byte */
+ }
+ }
+
+ if (bph->bph_mode != 2 && kdba_verify_rw(bp->bp_addr, bph->bph_length+1)) {
+ kdb_printf("Invalid address for breakpoint, ignoring bp command\n");
+ return KDB_BADADDR;
+ }
+
+ *nextargp = nextarg;
+ return 0;
+}
+
+/*
+ * kdba_allocbp
+ *
+ * Associate a hardware register with a breakpoint.
+ *
+ * Parameters:
+ * None.
+ * Outputs:
+ * None.
+ * Returns:
+ * A pointer to the allocated register kdbhard_bp_t structure for
+ * success, Null and a non-zero diagnostic for failure.
+ * Locking:
+ * None.
+ * Remarks:
+ */
+
+kdbhard_bp_t *
+kdba_allocbp(kdbhard_bp_t *bph, int *diagp)
+{
+ int i;
+ kdbhard_bp_t *newbph;
+
+ for(i=0,newbph=kdb_hardbreaks; i < KDB_MAXHARDBPT; i++, newbph++) {
+ if (newbph->bph_free) {
+ break;
+ }
+ }
+
+ if (i == KDB_MAXHARDBPT) {
+ *diagp = KDB_TOOMANYDBREGS;
+ return NULL;
+ }
+
+ *diagp = 0;
+
+ /*
+ * Copy data from template. Can't just copy the entire template
+ * here because the register number in kdb_hardbreaks must be
+ * preserved.
+ */
+ newbph->bph_data = bph->bph_data;
+ newbph->bph_write = bph->bph_write;
+ newbph->bph_mode = bph->bph_mode;
+ newbph->bph_length = bph->bph_length;
+
+ /*
+ * Mark entry allocated.
+ */
+ newbph->bph_free = 0;
+
+ return newbph;
+}
+
+/*
+ * kdba_freebp
+ *
+ * Deallocate a hardware breakpoint
+ *
+ * Parameters:
+ * None.
+ * Outputs:
+ * None.
+ * Returns:
+ * Zero for success, a kdb diagnostic for failure
+ * Locking:
+ * None.
+ * Remarks:
+ */
+
+void
+kdba_freebp(kdbhard_bp_t *bph)
+{
+ bph->bph_free = 1;
+}
+
+/*
+ * kdba_initbp
+ *
+ * Initialize the breakpoint table for the hardware breakpoint
+ * register.
+ *
+ * Parameters:
+ * None.
+ * Outputs:
+ * None.
+ * Returns:
+ * Zero for success, a kdb diagnostic for failure
+ * Locking:
+ * None.
+ * Remarks:
+ *
+ * There is one entry per register. On the ia32 architecture
+ * all the registers are interchangeable, so no special allocation
+ * criteria are required.
+ */
+
+void
+kdba_initbp(void)
+{
+ int i;
+ kdbhard_bp_t *bph;
+
+ /*
+ * Clear the hardware breakpoint table
+ */
+
+ memset(kdb_hardbreaks, '\0', sizeof(kdb_hardbreaks));
+
+ for(i=0,bph=kdb_hardbreaks; i<KDB_MAXHARDBPT; i++, bph++) {
+ bph->bph_reg = i;
+ bph->bph_free = 1;
+ }
+}
+
+/*
+ * kdba_installbp
+ *
+ * Install a breakpoint
+ *
+ * Parameters:
+ * regs Exception frame
+ * bp Breakpoint structure for the breakpoint to be installed
+ * Outputs:
+ * None.
+ * Returns:
+ * 0 if breakpoint installed.
+ * Locking:
+ * None.
+ * Remarks:
+ * For hardware breakpoints, a debug register is allocated
+ * and assigned to the breakpoint. If no debug register is
+ * available, a warning message is printed and the breakpoint
+ * is disabled.
+ *
+ * For instruction replacement breakpoints, we must single-step
+ * over the replaced instruction at this point so we can re-install
+ * the breakpoint instruction after the single-step. SSBPT is set
+ * when the breakpoint is initially hit and is cleared by any action
+ * that removes the need for single-step over the breakpoint.
+ */
+
+int
+kdba_installbp(struct pt_regs *regs, kdb_bp_t *bp)
+{
+ /*
+ * Install the breakpoint, if it is not already installed.
+ */
+
+ if (KDB_DEBUG(BP)) {
+ kdb_printf("kdba_installbp bp_installed %d\n", bp->bp_installed);
+ }
+ if (!KDB_STATE(SSBPT))
+ bp->bp_delay = 0;
+ if (!bp->bp_installed) {
+ if (bp->bp_hardtype) {
+ kdba_installdbreg(bp);
+ bp->bp_installed = 1;
+ if (KDB_DEBUG(BP)) {
+ kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+ bp->bp_hard->bph_reg, bp->bp_addr);
+ }
+ } else if (bp->bp_delay) {
+ if (KDB_DEBUG(BP))
+ kdb_printf("kdba_installbp delayed bp\n");
+ kdba_handle_bp(regs, bp);
+ } else {
+ if (kdb_getarea_size(&(bp->bp_inst), bp->bp_addr, 1) ||
+ kdb_putword(bp->bp_addr, IA32_BREAKPOINT_INSTRUCTION, 1)) {
+ kdb_printf("kdba_installbp failed to set software breakpoint at 0x%lx\n", bp->bp_addr);
+ return(1);
+ }
+ bp->bp_installed = 1;
+ if (KDB_DEBUG(BP))
+ kdb_printf("kdba_installbp instruction 0x%x at " kdb_bfd_vma_fmt "\n",
+ IA32_BREAKPOINT_INSTRUCTION, bp->bp_addr);
+ }
+ }
+ return(0);
+}
+
+/*
+ * kdba_removebp
+ *
+ * Make a breakpoint ineffective.
+ *
+ * Parameters:
+ * None.
+ * Outputs:
+ * None.
+ * Returns:
+ * None.
+ * Locking:
+ * None.
+ * Remarks:
+ */
+
+int
+kdba_removebp(kdb_bp_t *bp)
+{
+ /*
+ * For hardware breakpoints, remove it from the active register,
+ * for software breakpoints, restore the instruction stream.
+ */
+ if (KDB_DEBUG(BP)) {
+ kdb_printf("kdba_removebp bp_installed %d\n", bp->bp_installed);
+ }
+ if (bp->bp_installed) {
+ if (bp->bp_hardtype) {
+ if (KDB_DEBUG(BP)) {
+ kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+ bp->bp_hard->bph_reg, bp->bp_addr);
+ }
+ kdba_removedbreg(bp);
+ } else {
+ if (KDB_DEBUG(BP))
+ kdb_printf("kdb: restoring instruction 0x%x at " kdb_bfd_vma_fmt "\n",
+ bp->bp_inst, bp->bp_addr);
+ if (kdb_putword(bp->bp_addr, bp->bp_inst, 1))
+ return(1);
+ }
+ bp->bp_installed = 0;
+ }
+ return(0);
+}
Index: 2.6.x-xfs/arch/i386/kdb/kdba_bt.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kdb/kdba_bt.c 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/arch/i386/kdb/kdba_bt.c 2005-12-20 16:50:55.845850598 +1100
@@ -0,0 +1,379 @@
+/*
+ * 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/config.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kallsyms.h>
+#include <linux/irq.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_FRAME_POINTER
+#define EFPSTR "EBP"
+#define EFP ebp
+#define NOBP 0
+#else
+#define EFPSTR "ESP"
+#define EFP esp
+#define NOBP esp
+#endif
+
+/*
+ * bt_print_one
+ *
+ * Print one back trace entry.
+ *
+ * Inputs:
+ * eip Current program counter, or return address.
+ * efp #ifdef CONFIG_FRAME_POINTER: Previous frame pointer ebp,
+ * 0 if not valid; #else: Stack pointer esp when at eip.
+ * ar Activation record for this frame.
+ * symtab Information about symbol that eip falls within.
+ * argcount Maximum number of arguments to print.
+ * Outputs:
+ * None.
+ * Returns:
+ * None.
+ * Locking:
+ * None.
+ * Remarks:
+ * None.
+ */
+
+static void
+bt_print_one(kdb_machreg_t eip, kdb_machreg_t efp, const kdb_ar_t *ar,
+ const kdb_symtab_t *symtab, int argcount)
+{
+ int btsymarg = 0;
+ int nosect = 0;
+ kdb_machreg_t word;
+
+ kdbgetintenv("BTSYMARG", &btsymarg);
+ kdbgetintenv("NOSECT", &nosect);
+
+ if (efp)
+ kdb_printf("0x%08lx", efp);
+ else
+ kdb_printf(" ");
+ kdb_symbol_print(eip, symtab, KDB_SP_SPACEB|KDB_SP_VALUE);
+ if (argcount && ar->args) {
+ int i, argc = ar->args / 4;
+
+ kdb_printf(" (");
+ if (argc > argcount)
+ argc = argcount;
+
+ for(i=1; i<=argc; i++){
+ kdb_machreg_t argp = ar->arg0 - ar->args + 4*i;
+
+ if (i != 1)
+ kdb_printf(", ");
+ kdb_getword(&word, argp, sizeof(word));
+ kdb_printf("0x%lx", word);
+ }
+ kdb_printf(")");
+ }
+ if (symtab->sym_name) {
+ if (!nosect) {
+ kdb_printf("\n");
+ kdb_printf(" %s",
+ 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",
+ symtab->sym_start,
+ symtab->sym_end);
+ }
+ }
+ kdb_printf("\n");
+ if (argcount && ar->args && btsymarg) {
+ int i, argc = ar->args / 4;
+ kdb_symtab_t arg_symtab;
+ kdb_machreg_t arg;
+ for(i=1; i<=argc; i++){
+ kdb_machreg_t argp = ar->arg0 - ar->args + 4*i;
+ kdb_getword(&arg, argp, sizeof(arg));
+ if (kdbnearsym(arg, &arg_symtab)) {
+ kdb_printf(" ");
+ kdb_symbol_print(arg, &arg_symtab, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+ }
+ }
+ }
+}
+
+/*
+ * kdba_bt_stack
+ *
+ * Inputs:
+ * addr Pointer to Address provided to 'bt' command, if any.
+ * argcount
+ * p Pointer to task for 'btp' command.
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ * mds comes in handy when examining the stack to do a manual
+ * traceback.
+ */
+
+static int
+kdba_bt_stack(kdb_machreg_t addr, int argcount, const struct task_struct *p)
+{
+ kdb_ar_t ar;
+ kdb_machreg_t eip, esp, ebp, ss, cs, esp_base;
+ kdb_symtab_t symtab;
+ int count, kernel_stack, alt_stack = 0;
+
+ /*
+ * The caller may have supplied an address at which the
+ * stack traceback operation should begin. This address
+ * is assumed by this code to point to a return-address
+ * on the stack to be traced back.
+ *
+ * The end result of this will make it appear as if a function
+ * entitled '<unknown>' was called from the function which
+ * contains return-address.
+ */
+ if (addr) {
+ eip = 0;
+ ebp = 0;
+ esp = addr;
+ cs = __KERNEL_CS; /* have to assume kernel space */
+ } else {
+ if (task_curr(p)) {
+ struct kdb_running_process *krp = kdb_running_process + task_cpu(p);
+ struct pt_regs *regs;
+
+ if (!krp->seqno) {
+ kdb_printf("Process did not save state, cannot backtrace\n");
+ kdb_ps1(p);
+ return 0;
+ }
+ regs = krp->regs;
+ if (KDB_NULL_REGS(regs))
+ return KDB_BADREG;
+ kdba_getregcontents("eip", regs, &eip);
+ kdba_getregcontents("ebp", regs, &ebp);
+ /* CONFIG_4KSTACKS means multiple values for esp, use the last one */
+ esp = krp->arch.esp;
+ kdba_getregcontents("xcs", regs, &cs);
+ }
+ else {
+ /* Not on cpu, assume blocked. Blocked i386 tasks do
+ * not have pt_regs. p->thread.{esp,eip} are set, esp
+ * points to the ebp value, assume kernel space.
+ */
+ eip = p->thread.eip;
+ esp = p->thread.esp;
+ ebp = *(unsigned long *)esp;
+ cs = __KERNEL_CS;
+ }
+ esp_base = (unsigned long)(p->thread_info);
+ kernel_stack = esp >= esp_base && esp < (esp_base + THREAD_SIZE);
+#ifdef CONFIG_4KSTACKS
+ if (!kernel_stack && kdb_task_has_cpu(p)) {
+ int cpu = kdb_process_cpu(p);
+ struct thread_info *tinfo = (struct thread_info *)(esp & -THREAD_SIZE);
+ if (kdba_irq_ctx_type(cpu, tinfo))
+ alt_stack = kernel_stack = 1;
+ }
+#endif /* CONFIG_4KSTACKS */
+ if (!kernel_stack) {
+ kdb_printf("esp is not in a valid kernel stack, backtrace not available\n");
+ kdb_printf("esp_base=%lx, esp=%lx\n", esp_base, esp);
+ return(0);
+ }
+ }
+ ss = esp & -THREAD_SIZE;
+
+ if ((cs & 0xffff) != __KERNEL_CS) {
+ kdb_printf("Stack is not in kernel space, backtrace not available\n");
+ return 0;
+ }
+
+ kdb_printf(EFPSTR " EIP Function (args)\n");
+ if (alt_stack)
+ kdb_printf("Starting on an alternate kernel stack\n");
+
+ /*
+ * Run through the activation records and print them.
+ */
+
+ for (count = 0; count < 200; ++count) {
+ kdb_ar_t save_ar = ar;
+ kdbnearsym(eip, &symtab);
+ if (!kdb_get_next_ar(esp, symtab.sym_start, eip, ebp, ss,
+ &ar, &symtab)) {
+ struct thread_info *tinfo = (struct thread_info *)ss;
+ esp = tinfo->previous_esp;
+ if (!esp)
+ break;
+ ss = esp & -THREAD_SIZE;
+ kdb_printf(" =======================\n");
+ }
+
+ if (strncmp(".text.lock.", symtab.sym_name, 11) == 0) {
+ /*
+ * Instructions in the .text.lock area are generated by
+ * the out of line code in lock handling, see
+ * include/asm-i386 semaphore.h and rwlock.h. There can
+ * be multiple instructions which eventually end with a
+ * jump back to the mainline code. Use the disassmebler
+ * to silently step through the code until we find the
+ * jump, resolve its destination and translate it to a
+ * symbol. Replace '.text.lock' with the symbol.
+ */
+ unsigned char inst;
+ kdb_machreg_t offset = 0, realeip = eip;
+ int length, offsize = 0;
+ kdb_symtab_t lock_symtab;
+ /* Dummy out the disassembler print function */
+ fprintf_ftype save_fprintf_func = kdb_di.fprintf_func;
+
+ kdb_di.fprintf_func = &kdb_dis_fprintf_dummy;
+ while((length = kdba_id_printinsn(realeip, &kdb_di)) > 0) {
+ kdb_getarea(inst, realeip);
+ offsize = 0;
+ switch (inst) {
+ case 0xeb: /* jmp with 1 byte offset */
+ offsize = 1-4;
+ /* drop through */
+ case 0xe9: /* jmp with 4 byte offset */
+ offsize += 4;
+ kdb_getword(&offset, realeip+1, offsize);
+ break;
+ default:
+ realeip += length; /* next instruction */
+ break;
+ }
+ if (offsize)
+ break;
+ }
+ kdb_di.fprintf_func = save_fprintf_func;
+
+ if (offsize) {
+ realeip += 1 + offsize + (offsize == 1 ? (s8)offset : (s32)offset);
+ if (kdbnearsym(realeip, &lock_symtab)) {
+ /* Print the stext entry without args */
+ bt_print_one(eip, NOBP, &ar, &symtab, 0);
+ /* Point to mainline code */
+ eip = realeip;
+ ar = save_ar; /* lock text does not consume an activation frame */
+ continue;
+ }
+ }
+ }
+
+ if (strcmp("ret_from_intr", symtab.sym_name) == 0 ||
+ strcmp("error_code", symtab.sym_name) == 0) {
+ if (strcmp("ret_from_intr", symtab.sym_name) == 0) {
+ /*
+ * Non-standard frame. ret_from_intr is
+ * preceded by 9 registers (ebx, ecx, edx, esi,
+ * edi, ebp, eax, ds, cs), original eax and the
+ * return address for a total of 11 words.
+ */
+ ar.start = ar.end + 11*4;
+ }
+ if (strcmp("error_code", symtab.sym_name) == 0) {
+ /*
+ * Non-standard frame. error_code is preceded
+ * by two parameters (-> registers, error code),
+ * 9 registers (ebx, ecx, edx, esi, edi, ebp,
+ * eax, ds, cs), original eax and the return
+ * address for a total of 13 words.
+ */
+ ar.start = ar.end + 13*4;
+ }
+ /* Print the non-standard entry without args */
+ bt_print_one(eip, NOBP, &ar, &symtab, 0);
+ kdb_printf("Interrupt registers:\n");
+ kdba_dumpregs((struct pt_regs *)(ar.end), NULL, NULL);
+ /* Step the frame to the interrupted code */
+ kdb_getword(&eip, ar.start-4, 4);
+ ebp = 0;
+ esp = ar.start;
+ if ((((struct pt_regs *)(ar.end))->xcs & 0xffff) != __KERNEL_CS) {
+ kdb_printf("Interrupt from user space, end of kernel trace\n");
+ break;
+ }
+ continue;
+ }
+
+ bt_print_one(eip, EFP, &ar, &symtab, argcount);
+
+ if (ar.ret == 0)
+ break; /* End of frames */
+ eip = ar.ret;
+ ebp = ar.oldfp;
+ esp = ar.start;
+ }
+ if (count >= 200)
+ kdb_printf("bt truncated, count limit reached\n");
+
+ return 0;
+}
+
+/*
+ * kdba_bt_address
+ *
+ * Do a backtrace starting at a specified stack address. Use this if the
+ * heuristics get the i386 stack decode wrong.
+ *
+ * Inputs:
+ * addr Address provided to 'bt' command.
+ * argcount
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ * mds %esp comes in handy when examining the stack to do a manual
+ * traceback.
+ */
+
+int
+kdba_bt_address(kdb_machreg_t addr, int argcount)
+{
+ return kdba_bt_stack(addr, argcount, NULL);
+}
+
+/*
+ * kdba_bt_process
+ *
+ * Do a backtrace for a specified process.
+ *
+ * Inputs:
+ * p Struct task pointer extracted by 'bt' command.
+ * argcount
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ */
+
+int
+kdba_bt_process(const struct task_struct *p, int argcount)
+{
+ return kdba_bt_stack(0, argcount, p);
+}
Index: 2.6.x-xfs/arch/i386/kdb/kdba_id.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kdb/kdba_id.c 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/arch/i386/kdb/kdba_id.c 2005-12-20 16:50:55.846827025 +1100
@@ -0,0 +1,255 @@
+/*
+ * 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",
+ 2*sizeof(addr), addr, symtab.sym_name);
+ if ((offset = addr - symtab.sym_start) == 0) {
+ spaces += 4;
+ }
+ else {
+ unsigned int o = offset;
+ while (o >>= 4)
+ --spaces;
+ dip->fprintf_func(dip->stream, "+0x%x", offset);
+ }
+
+ } else {
+ dip->fprintf_func(dip->stream, "0x%x", addr);
+ }
+
+ if (flag) {
+ if (spaces < 1) {
+ spaces = 1;
+ }
+ dip->fprintf_func(dip->stream, ":%*s", spaces, " ");
+ }
+}
+
+/*
+ * kdba_dis_printaddr
+ *
+ * Print (symbolically) an address. Called by GNU disassembly
+ * code via disassemble_info structure.
+ *
+ * Parameters:
+ * addr Address for which to get symbol
+ * dip Pointer to disassemble_info
+ * Returns:
+ * 0
+ * Locking:
+ * Remarks:
+ * This function will never append ":<tab>" to the printed
+ * symbolic address.
+ */
+
+static void
+kdba_dis_printaddr(bfd_vma addr, disassemble_info *dip)
+{
+ kdba_printaddress(addr, dip, 0);
+}
+
+/*
+ * kdba_dis_getmem
+ *
+ * Fetch 'length' bytes from 'addr' into 'buf'.
+ *
+ * Parameters:
+ * addr Address for which to get symbol
+ * buf Address of buffer to fill with bytes from 'addr'
+ * length Number of bytes to fetch
+ * dip Pointer to disassemble_info
+ * Returns:
+ * 0 if data is available, otherwise error.
+ * Locking:
+ * Remarks:
+ *
+ */
+
+/* ARGSUSED */
+static int
+kdba_dis_getmem(bfd_vma addr, bfd_byte *buf, unsigned int length, disassemble_info *dip)
+{
+ return kdb_getarea_size(buf, addr, length);
+}
+
+/*
+ * kdba_id_parsemode
+ *
+ * Parse IDMODE environment variable string and
+ * set appropriate value into "disassemble_info" structure.
+ *
+ * Parameters:
+ * mode Mode string
+ * dip Disassemble_info structure pointer
+ * Returns:
+ * Locking:
+ * Remarks:
+ * We handle the values 'x86' and '8086' to enable either
+ * 32-bit instruction set or 16-bit legacy instruction set.
+ */
+
+int
+kdba_id_parsemode(const char *mode, disassemble_info *dip)
+{
+
+ if (mode) {
+ if (strcmp(mode, "x86") == 0) {
+ dip->mach = bfd_mach_i386_i386;
+ } else if (strcmp(mode, "8086") == 0) {
+ dip->mach = bfd_mach_i386_i8086;
+ } else {
+ return KDB_BADMODE;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * kdba_check_pc
+ *
+ * Check that the pc is satisfactory.
+ *
+ * Parameters:
+ * pc Program Counter Value.
+ * Returns:
+ * None
+ * Locking:
+ * None.
+ * Remarks:
+ * Can change pc.
+ */
+
+void
+kdba_check_pc(kdb_machreg_t *pc)
+{
+ /* No action */
+}
+
+/*
+ * kdba_id_printinsn
+ *
+ * Format and print a single instruction at 'pc'. Return the
+ * length of the instruction.
+ *
+ * Parameters:
+ * pc Program Counter Value.
+ * dip Disassemble_info structure pointer
+ * Returns:
+ * Length of instruction, -1 for error.
+ * Locking:
+ * None.
+ * Remarks:
+ * Depends on 'IDMODE' environment variable.
+ */
+
+int
+kdba_id_printinsn(kdb_machreg_t pc, disassemble_info *dip)
+{
+ kdba_printaddress(pc, dip, 1);
+ return print_insn_i386_att(pc, dip);
+}
+
+/*
+ * kdba_id_init
+ *
+ * Initialize the architecture dependent elements of
+ * the disassembly information structure
+ * for the GNU disassembler.
+ *
+ * Parameters:
+ * None.
+ * Outputs:
+ * None.
+ * Returns:
+ * None.
+ * Locking:
+ * None.
+ * Remarks:
+ */
+
+void __init
+kdba_id_init(disassemble_info *dip)
+{
+ dip->read_memory_func = kdba_dis_getmem;
+ dip->print_address_func = kdba_dis_printaddr;
+ dip->symbol_at_address_func = kdba_dis_getsym;
+
+ dip->flavour = bfd_target_elf_flavour;
+ dip->arch = bfd_arch_i386;
+ dip->mach = bfd_mach_i386_i386;
+ dip->endian = BFD_ENDIAN_LITTLE;
+
+ dip->display_endian = BFD_ENDIAN_LITTLE;
+}
Index: 2.6.x-xfs/arch/i386/kdb/kdba_io.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kdb/kdba_io.c 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/arch/i386/kdb/kdba_io.c 2005-12-20 16:50:55.848779880 +1100
@@ -0,0 +1,504 @@
+/*
+ * 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-2004 Silicon Graphics, Inc. All Rights Reserved.
+ */
+
+#include <linux/config.h>
+#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
+struct kdb_usb_exchange kdb_usb_infos;
+
+EXPORT_SYMBOL(kdb_usb_infos);
+
+static unsigned char kdb_usb_keycode[256] = {
+ 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
+ 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
+ 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
+ 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
+ 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
+ 120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
+ 115,114, 0, 0, 0,124, 0,181,182,183,184,185,186,187,188,189,
+ 190,191,192,193,194,195,196,197,198, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
+ 150,158,159,128,136,177,178,176,142,152,173,140
+};
+
+/* get_usb_char
+ * This function drives the UHCI controller,
+ * fetch the USB scancode and decode it
+ */
+static int get_usb_char(void)
+{
+ static int usb_lock;
+ unsigned char keycode, spec;
+ extern u_short plain_map[], shift_map[], ctrl_map[];
+
+ /* Is USB initialized ? */
+ if(!kdb_usb_infos.poll_func || !kdb_usb_infos.urb)
+ return -1;
+
+ /* Transfer char if they are present */
+ (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb);
+
+ spec = kdb_usb_infos.buffer[0];
+ keycode = kdb_usb_infos.buffer[2];
+ kdb_usb_infos.buffer[0] = (char)0;
+ kdb_usb_infos.buffer[2] = (char)0;
+
+ if(kdb_usb_infos.buffer[3])
+ return -1;
+
+ /* A normal key is pressed, decode it */
+ if(keycode)
+ keycode = kdb_usb_keycode[keycode];
+
+ /* 2 Keys pressed at one time ? */
+ if (spec && keycode) {
+ switch(spec)
+ {
+ case 0x2:
+ case 0x20: /* Shift */
+ return shift_map[keycode];
+ case 0x1:
+ case 0x10: /* Ctrl */
+ return ctrl_map[keycode];
+ case 0x4:
+ case 0x40: /* Alt */
+ break;
+ }
+ }
+ else {
+ if(keycode) { /* If only one key pressed */
+ switch(keycode)
+ {
+ case 0x1C: /* Enter */
+ return 13;
+
+ case 0x3A: /* Capslock */
+ usb_lock ? (usb_lock = 0) : (usb_lock = 1);
+ break;
+ case 0x0E: /* Backspace */
+ return 8;
+ case 0x0F: /* TAB */
+ return 9;
+ case 0x77: /* Pause */
+ break ;
+ default:
+ if(!usb_lock) {
+ return plain_map[keycode];
+ }
+ else {
+ return shift_map[keycode];
+ }
+ }
+ }
+ }
+ return -1;
+}
+#endif /* 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)
+{
+ while (inb(KBD_STATUS_REG) & KBD_STAT_IBF)
+ ;
+ outb(byte, KBD_DATA_REG);
+}
+
+static void
+kdb_toggleled(int led)
+{
+ static int leds;
+
+ leds ^= led;
+
+ kdb_kbdsend(KBD_CMD_SET_LEDS);
+ kdb_kbdsend((unsigned char)leds);
+}
+#endif /* KDB_BLINK_LED */
+
+#if defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_CORE_CONSOLE)
+#define CONFIG_SERIAL_CONSOLE
+#endif
+
+#if defined(CONFIG_SERIAL_CONSOLE)
+
+struct kdb_serial kdb_serial;
+
+static inline unsigned int
+serial_inp(struct kdb_serial *kdb_serial, unsigned long offset)
+{
+ offset <<= kdb_serial->ioreg_shift;
+
+ switch (kdb_serial->io_type) {
+ case SERIAL_IO_MEM:
+ return readb((void *)(kdb_serial->iobase + offset));
+ break;
+ default:
+ return inb(kdb_serial->iobase + offset);
+ break;
+ }
+}
+
+/* Check if there is a byte ready at the serial port */
+static int get_serial_char(void)
+{
+ unsigned char ch;
+
+ if (kdb_serial.iobase == 0)
+ return -1;
+
+ if (serial_inp(&kdb_serial, UART_LSR) & UART_LSR_DR) {
+ ch = serial_inp(&kdb_serial, UART_RX);
+ if (ch == 0x7f)
+ ch = 8;
+ return ch;
+ }
+ return -1;
+}
+#endif /* CONFIG_SERIAL_CONSOLE */
+
+#ifdef CONFIG_VT_CONSOLE
+
+static int kbd_exists = -1;
+
+/*
+ * Check if the keyboard controller has a keypress for us.
+ * Some parts (Enter Release, LED change) are still blocking polled here,
+ * but hopefully they are all short.
+ */
+static int get_kbd_char(void)
+{
+ int scancode, scanstatus;
+ static int shift_lock; /* CAPS LOCK state (0-off, 1-on) */
+ static int shift_key; /* Shift next keypress */
+ static int ctrl_key;
+ u_short keychar;
+ extern u_short plain_map[], shift_map[], ctrl_map[];
+
+ if (kbd_exists <= 0) {
+ if (kbd_exists == 0)
+ return -1;
+
+ if (inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff) {
+ kbd_exists = 0;
+ return -1;
+ }
+ kbd_exists = 1;
+ }
+
+ if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
+ return -1;
+
+ /*
+ * Fetch the scancode
+ */
+ scancode = inb(KBD_DATA_REG);
+ scanstatus = inb(KBD_STATUS_REG);
+
+ /*
+ * Ignore mouse events.
+ */
+ if (scanstatus & KBD_STAT_MOUSE_OBF)
+ return -1;
+
+ /*
+ * Ignore release, trigger on make
+ * (except for shift keys, where we want to
+ * keep the shift state so long as the key is
+ * held down).
+ */
+
+ if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) {
+ /*
+ * Next key may use shift table
+ */
+ if ((scancode & 0x80) == 0) {
+ shift_key=1;
+ } else {
+ shift_key=0;
+ }
+ return -1;
+ }
+
+ if ((scancode&0x7f) == 0x1d) {
+ /*
+ * Left ctrl key
+ */
+ if ((scancode & 0x80) == 0) {
+ ctrl_key = 1;
+ } else {
+ ctrl_key = 0;
+ }
+ return -1;
+ }
+
+ if ((scancode & 0x80) != 0)
+ return -1;
+
+ scancode &= 0x7f;
+
+ /*
+ * Translate scancode
+ */
+
+ if (scancode == 0x3a) {
+ /*
+ * Toggle caps lock
+ */
+ shift_lock ^= 1;
+
+#ifdef KDB_BLINK_LED
+ kdb_toggleled(0x4);
+#endif
+ return -1;
+ }
+
+ if (scancode == 0x0e) {
+ /*
+ * Backspace
+ */
+ return 8;
+ }
+
+ /* Special Key */
+ switch (scancode) {
+ case 0xF: /* Tab */
+ return 9;
+ case 0x53: /* Del */
+ return 4;
+ case 0x47: /* Home */
+ return 1;
+ case 0x4F: /* End */
+ return 5;
+ case 0x4B: /* Left */
+ return 2;
+ case 0x48: /* Up */
+ return 16;
+ case 0x50: /* Down */
+ return 14;
+ case 0x4D: /* Right */
+ return 6;
+ }
+
+ if (scancode == 0xe0) {
+ return -1;
+ }
+
+ /*
+ * For Japanese 86/106 keyboards
+ * See comment in drivers/char/pc_keyb.c.
+ * - Masahiro Adegawa
+ */
+ if (scancode == 0x73) {
+ scancode = 0x59;
+ } else if (scancode == 0x7d) {
+ scancode = 0x7c;
+ }
+
+ if (!shift_lock && !shift_key && !ctrl_key) {
+ keychar = plain_map[scancode];
+ } else if (shift_lock || shift_key) {
+ keychar = shift_map[scancode];
+ } else if (ctrl_key) {
+ keychar = ctrl_map[scancode];
+ } else {
+ keychar = 0x0020;
+ kdb_printf("Unknown state/scancode (%d)\n", scancode);
+ }
+ keychar &= 0x0fff;
+ if (keychar == '\t')
+ keychar = ' ';
+ switch (KTYP(keychar)) {
+ case KT_LETTER:
+ case KT_LATIN:
+ if (isprint(keychar))
+ break; /* printable characters */
+ /* drop through */
+ case KT_SPEC:
+ if (keychar == K_ENTER)
+ break;
+ /* drop through */
+ default:
+ return(-1); /* ignore unprintables */
+ }
+
+ if ((scancode & 0x7f) == 0x1c) {
+ /*
+ * enter key. All done. Absorb the release scancode.
+ */
+ while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
+ ;
+
+ /*
+ * Fetch the scancode
+ */
+ scancode = inb(KBD_DATA_REG);
+ scanstatus = inb(KBD_STATUS_REG);
+
+ while (scanstatus & KBD_STAT_MOUSE_OBF) {
+ scancode = inb(KBD_DATA_REG);
+ scanstatus = inb(KBD_STATUS_REG);
+ }
+
+ if (scancode != 0x9c) {
+ /*
+ * Wasn't an enter-release, why not?
+ */
+ kdb_printf("kdb: expected enter got 0x%x status 0x%x\n",
+ scancode, scanstatus);
+ }
+
+ kdb_printf("\n");
+ return 13;
+ }
+
+ return keychar & 0xff;
+}
+#endif /* CONFIG_VT_CONSOLE */
+
+#ifdef KDB_BLINK_LED
+
+/* Leave numlock alone, setting it messes up laptop keyboards with the keypad
+ * mapped over normal keys.
+ */
+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
+ unsigned char c;
+
+ while (kbd_read_status() & KBD_STAT_IBF);
+ kbd_write_command(KBD_CCMD_READ_MODE);
+ mdelay(1);
+ while (kbd_read_status() & KBD_STAT_IBF);
+ while ( !(kbd_read_status() & KBD_STAT_OBF) );
+ c = kbd_read_input();
+ c &= ~KBD_MODE_KBD_INT;
+ while (kbd_read_status() & KBD_STAT_IBF);
+ kbd_write_command(KBD_CCMD_WRITE_MODE);
+ mdelay(1);
+ while (kbd_read_status() & KBD_STAT_IBF);
+ kbd_write_output(c);
+ mdelay(1);
+ while (kbd_read_status() & KBD_STAT_IBF);
+ mdelay(1);
+#endif /* CONFIG_VT_CONSOLE */
+}
+
+void kdba_local_arch_cleanup(void)
+{
+#ifdef CONFIG_VT_CONSOLE
+ unsigned char c;
+
+ while (kbd_read_status() & KBD_STAT_IBF);
+ kbd_write_command(KBD_CCMD_READ_MODE);
+ mdelay(1);
+ while (kbd_read_status() & KBD_STAT_IBF);
+ while ( !(kbd_read_status() & KBD_STAT_OBF) );
+ c = kbd_read_input();
+ c |= KBD_MODE_KBD_INT;
+ while (kbd_read_status() & KBD_STAT_IBF);
+ kbd_write_command(KBD_CCMD_WRITE_MODE);
+ mdelay(1);
+ while (kbd_read_status() & KBD_STAT_IBF);
+ kbd_write_output(c);
+ mdelay(1);
+ while (kbd_read_status() & KBD_STAT_IBF);
+ mdelay(1);
+#endif /* CONFIG_VT_CONSOLE */
+}
Index: 2.6.x-xfs/arch/i386/kdb/kdbasupport.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kdb/kdbasupport.c 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/arch/i386/kdb/kdbasupport.c 2005-12-20 16:50:55.852685588 +1100
@@ -0,0 +1,1497 @@
+/*
+ * 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/config.h>
+#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/kdb.h>
+#include <linux/kdbprivate.h>
+
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/uaccess.h>
+
+/*
+ * kdba_find_return_1
+ *
+ * Given a starting point on the stack and symtab data for the
+ * current function, scan up the stack looking for a return
+ * address for this function.
+ * Inputs:
+ * sp Starting stack pointer for scan
+ * ss Start of stack for current process
+ * symtab kallsyms symbol data for the function
+ * assume When false, do not apply tests that have to assume a branch is valid
+ * Outputs:
+ * None.
+ * Returns:
+ * Position on stack of return address, 0 if not found.
+ * Locking:
+ * None.
+ * Remarks:
+ * This is sensitive to the calling sequence generated by gcc.
+ */
+
+static kdb_machreg_t
+kdba_find_return_1(kdb_machreg_t sp, kdb_machreg_t ss, const kdb_symtab_t *symtab, int assume)
+{
+ kdb_machreg_t ret;
+ kdb_symtab_t caller_symtab;
+ unsigned long disp8;
+ unsigned long disp32;
+ unsigned char code[7];
+#define retaddr(off) code[sizeof(code)+(off)]
+
+ for (;ret = 0, sp & (THREAD_SIZE-1);sp += 4) {
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" sp=0x%lx", sp);
+ }
+ if (kdb_getword(&ret, sp, 4))
+ break;
+ if (ret > PAGE_SIZE)
+ kdbnearsym(ret, &caller_symtab);
+ else
+ memset(&caller_symtab, 0, sizeof(caller_symtab));
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" ret=");
+ kdb_symbol_print(ret, &caller_symtab, KDB_SP_DEFAULT|KDB_SP_SYMSIZE);
+ }
+ if (!caller_symtab.sym_name) {
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf("\n");
+ }
+ continue; /* not a valid kernel address */
+ }
+ KDB_STATE_SET(SUPPRESS);
+ if (kdb_getarea(code, ret-sizeof(code)) ||
+ kdb_getword(&disp32, ret-4, 4) ||
+ kdb_getword(&disp8, ret-1, 1))
+ continue; /* not a valid return address */
+ if (retaddr(-5) == 0xe8) {
+ /* call disp32 */
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" call disp32");
+ }
+ if (ret + (s32) disp32 == symtab->sym_start) {
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" matched");
+ }
+ break; /* call to this function */
+ }
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" failed");
+ }
+ } else if (retaddr(-5) == 0xe9) {
+ /* jmp disp32. I have been told that gcc may
+ * do function tail optimization and replace
+ * call with jmp.
+ */
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" jmp disp32");
+ }
+ if (ret + (s32) disp32 == symtab->sym_start) {
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" matched");
+ }
+ break; /* jmp to this function */
+ }
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" failed");
+ }
+ } else if (retaddr(-2) == 0xeb) {
+ /* jmp disp8 */
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" jmp disp8");
+ }
+ if (ret + (s8) disp8 == symtab->sym_start) {
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" matched");
+ }
+ break; /* jmp to this function */
+ }
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" failed");
+ }
+ } else if (strcmp(caller_symtab.sym_name, "ret_from_intr") == 0
+ && ret == caller_symtab.sym_start) {
+ /* ret_from_intr is pushed on stack for interrupts */
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" ret_from_intr matched");
+ }
+ break; /* special case, hand crafted frame */
+ } else if (!assume) {
+ /* All following tests cannot validate the target address so they
+ * must assume that the return address is valid.
+ */
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf("\n");
+ }
+ continue;
+ } else if (retaddr(-7) == 0xff && retaddr(-6) == 0x14 && retaddr(-5) == 0x85) {
+ /* call *disp32(,%eax,4), used by syscall.
+ * Cannot calculate address, assume it is valid
+ * if the current function name starts with
+ * 'sys_' or 'old_'.
+ */
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" call *0xnnnn(,%%eax,4)");
+ }
+ if (strncmp(symtab->sym_name, "sys_", 4) == 0 ||
+ strncmp(symtab->sym_name, "old_", 4) == 0) {
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" assume valid");
+ }
+ break; /* probably call to this function */
+ }
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" failed");
+ }
+ } else if (retaddr(-2) == 0xff &&
+ ((retaddr(-1) & 0xf8) == 0xd0 || (retaddr(-1) & 0xf8) == 0x10)) {
+ /* call *%reg. Cannot validate, have to assume
+ * it is valid.
+ */
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" call *%%reg, assume valid");
+ }
+ break; /* hope it is a call to this function */
+ } else if (retaddr(-3) == 0xff && (retaddr(-2) & 0xf8) == 0x50) {
+ /* call *disp8(%reg). Cannot validate, have to assume
+ * it is valid.
+ */
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" call *disp8(%%reg), assume valid");
+ }
+ break; /* hope it is a call to this function */
+ } else if (retaddr(-6) == 0xff && (retaddr(-5) & 0xf8) == 0x90) {
+ /* call *disp32(%reg). Cannot validate, have to assume
+ * it is valid.
+ */
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" call *disp32(%%reg), assume valid");
+ }
+ break; /* hope it is a call to this function */
+ }
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf("\n");
+ }
+ }
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" end ret=0x%lx sp=0x%lx\n", ret, sp);
+ }
+ if (ret)
+ return sp;
+ return 0;
+}
+
+/*
+ * kdba_find_return
+ *
+ * Given a starting point on the stack and symtab data for the
+ * current function, scan up the stack looking for a return
+ * address for this function.
+ * Inputs:
+ * sp Starting stack pointer for scan
+ * ss Start of stack for current process
+ * symtab kallsyms symbol data for the function
+ * Outputs:
+ * None.
+ * Returns:
+ * Position on stack of return address, 0 if not found.
+ * Locking:
+ * None.
+ * Remarks:
+ * This is sensitive to the calling sequence generated by gcc.
+ */
+
+static kdb_machreg_t
+kdba_find_return(kdb_machreg_t sp, kdb_machreg_t ss, const kdb_symtab_t *symtab)
+{
+ kdb_machreg_t ret;
+
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" kdba_find_return: start\n");
+ }
+
+ if ((sp & -THREAD_SIZE) != ss) {
+ kdb_printf(" sp is in wrong stack 0x%lx 0x%lx 0x%lx\n", sp, ss, sp & -THREAD_SIZE);
+ return 0;
+ }
+
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" kdba_find_return_1(assume==0)\n");
+ }
+ if ((ret = kdba_find_return_1(sp, ss, symtab, 0)))
+ return ret;
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" kdba_find_return_1(assume==1)\n");
+ }
+ ret = kdba_find_return_1(sp, ss, symtab, 1);
+ return ret;
+}
+
+/*
+ * kdba_prologue
+ *
+ * This function analyzes a gcc-generated function prototype
+ * with or without frame pointers to determine the amount of
+ * automatic storage and register save storage is used on the
+ * stack of the target function. It only counts instructions
+ * that have been executed up to but excluding the current eip.
+ * Inputs:
+ * code Start address of function code to analyze
+ * pc Current program counter within function
+ * sp Current stack pointer for function
+ * fp Current frame pointer for function, may not be valid
+ * ss Start of stack for current process.
+ * caller 1 if looking for data on the caller frame, 0 for callee.
+ * Outputs:
+ * ar Activation record, all fields may be set. fp and oldfp
+ * are 0 if they cannot be extracted. return is 0 if the
+ * code cannot find a valid return address. args and arg0
+ * are 0 if the number of arguments cannot be safely
+ * calculated.
+ * Returns:
+ * 1 if prologue is valid, 0 otherwise. If pc is 0 treat it as a
+ * valid prologue to allow bt on wild branches.
+ * Locking:
+ * None.
+ * Remarks:
+ *
+ * A prologue for ia32 generally looks like:
+ *
+ * pushl %ebp [All functions, but only if
+ * movl %esp, %ebp compiled with frame pointers]
+ * subl $auto, %esp [some functions]
+ * pushl %reg [some functions]
+ * pushl %reg [some functions]
+ *
+ * FIXME: Mike Galbraith says that gcc 2.95 can generate a slightly
+ * different prologue. No support for gcc 2.95 yet.
+ */
+
+int
+kdba_prologue(const kdb_symtab_t *symtab, kdb_machreg_t pc, kdb_machreg_t sp,
+ kdb_machreg_t fp, kdb_machreg_t ss, int caller, kdb_ar_t *ar)
+{
+ kdb_machreg_t ret_p, code = symtab->sym_start;
+ int oldfp_present = 0, unwound = 0;
+ unsigned char instruction[6];
+
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf("kdba_prologue: code=0x%lx %s pc=0x%lx sp=0x%lx fp=0x%lx\n",
+ code, symtab->sym_name, pc, sp, fp);
+ }
+
+ /* Special case for wild branches. Assumes top of stack is return address */
+ if (pc == 0) {
+ memset(ar, 0, sizeof(*ar));
+ ar->setup = 4;
+ ar->end = sp;
+ ar->start = ar->end + 4;
+ kdb_getword(&(ar->ret), sp, 4);
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" pc==0: ret=0x%lx\n", ar->ret);
+ }
+ return(1);
+ }
+
+ if (code == 0 || sp & 3 || ss != (sp & -THREAD_SIZE))
+ return(0);
+
+ ar->end = sp; /* End of activation record +1 */
+
+ /* Special cases galore when the caller pc is within entry.S.
+ * The return address for these routines is outside the kernel,
+ * so the normal algorithm to find the frame does not work.
+ * Hand craft the frame to no setup, regs, locals etc, assume 6
+ * parameters.
+ * This list was extracted from entry.S by looking for all call
+ * instructions that were eventually followed by RESTORE_ALL,
+ * take the label before each such instruction.
+ */
+ if (caller &&
+ (strcmp(symtab->sym_name, "lcall7") == 0 ||
+ strcmp(symtab->sym_name, "lcall27") == 0 ||
+ strcmp(symtab->sym_name, "kdb_call") == 0 ||
+ strcmp(symtab->sym_name, "system_call") == 0 ||
+ strcmp(symtab->sym_name, "tracesys") == 0 ||
+ strcmp(symtab->sym_name, "signal_return") == 0 ||
+ strcmp(symtab->sym_name, "v86_signal_return") == 0 ||
+ strcmp(symtab->sym_name, "tracesys") == 0 ||
+ strcmp(symtab->sym_name, "tracesys_exit") == 0 ||
+ strcmp(symtab->sym_name, "handle_softirq") == 0 ||
+ strcmp(symtab->sym_name, "reschedule") == 0 ||
+ strcmp(symtab->sym_name, "error_code") == 0 ||
+ strcmp(symtab->sym_name, "device_not_available") == 0 ||
+ strcmp(symtab->sym_name, "nmi") == 0)) {
+ ar->start = ar->end + 6*4; /* 6 parameters */
+ if ((ar->start & -THREAD_SIZE) != ss)
+ ar->start = 0;
+ return(1);
+ }
+
+ ar->setup = 4; /* Return address is always on stack */
+
+ /* Kludge. If we are sitting on 'ret' then the stack has been unwound,
+ * ignore all the startup code.
+ */
+ if (kdb_getarea(instruction[0], pc))
+ return(0);
+ if (instruction[0] == 0xc3) {
+ /* ret */
+ unwound = 1;
+ }
+
+ if (kdb_getarea(instruction, code))
+ return(0);
+ if (!unwound && code < pc && instruction[0] == 0x55) {
+ /* pushl %ebp */
+ ar->setup += 4; /* Frame pointer is on stack */
+ oldfp_present = 1;
+ ++code;
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" pushl %%ebp\n");
+ }
+ if (code < pc && instruction[0] == 0x89 && instruction[1] == 0xe5) {
+ /* movl %esp,%ebp */
+ if (fp >= sp && (fp & -THREAD_SIZE) == ss)
+ ar->fp = fp; /* %ebp has been set */
+ code += 2;
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" movl %%esp,%%ebp, fp=0x%lx\n", ar->fp);
+ }
+ }
+ }
+
+ if (!unwound && code < pc) {
+ if (instruction[0] == 0x83 && instruction[1] == 0xec) {
+ /* subl $xx,%esp */
+ kdb_getword(&(ar->locals), (unsigned long)(instruction+2), 1);
+ code += 3;
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" subl $xx,%%esp, locals=%ld\n", ar->locals);
+ }
+ } else if (instruction[0] == 0x81 && instruction[1] == 0xec) {
+ /* subl $xxxxxxxx,%esp */
+ kdb_getword(&(ar->locals), (unsigned long)(instruction+2), 4);
+ code += 6;
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" subl $xxxxxxxx,%%esp, locals=%ld\n", ar->locals);
+ }
+ }
+ }
+
+ while (!unwound && code < pc &&
+ kdb_getarea(instruction, code) == 0 &&
+ (instruction[0] & 0xf8) == 0x50) {
+ /* pushl %reg */
+ ar->regs += 4;
+ ++code;
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" pushl %%reg, regs=%ld\n", ar->regs);
+ }
+ }
+
+ /* Check the return address. It must point within the kernel
+ * and the code at that location must be a valid entry sequence.
+ */
+ if (ar->fp) {
+ ret_p = ar->fp + ar->setup;
+ }
+ else {
+ ret_p = ar->end + ar->regs + ar->locals + ar->setup;
+ }
+ ret_p -= 4;
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" ret_p(0)=0x%lx\n", ret_p);
+ }
+ ar->ret = 0;
+ if ((ret_p & -THREAD_SIZE) == ss &&
+ (ret_p = kdba_find_return(ret_p, ss, symtab))) {
+ kdb_getword(&(ar->ret), ret_p, 4);
+ }
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" ret_p(1)=0x%lx ret=0x%lx\n", ret_p, ar->ret);
+ }
+ if (ar->ret) {
+ ar->fp = ret_p - ar->setup + 4; /* "accurate" fp */
+ ar->start = ret_p + 4;
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" fp=0x%lx start=0x%lx\n", ar->fp, ar->start);
+ }
+ }
+ if (oldfp_present) {
+ if (ar->fp)
+ kdb_getword(&(ar->oldfp), ar->fp, 4);
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" oldfp=0x%lx", ar->oldfp);
+ }
+ if (ar->oldfp <= ar->fp || (ar->oldfp & -THREAD_SIZE) != ss) {
+ ar->oldfp = 0;
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf(" (out of range)");
+ }
+ }
+ if (KDB_DEBUG(ARA)) {
+ kdb_printf("\n");
+ }
+ }
+ return(1);
+}
+
+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;
+ }
+}
+
+static 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)
+{
+ kdb_machreg_t dr7;
+
+ dr7 = kdba_getdr7();
+
+ kdba_putdr(bp->bp_hard->bph_reg, bp->bp_addr);
+
+ dr7 |= DR7_GE;
+ if (cpu_has_de)
+ set_in_cr4(X86_CR4_DE);
+
+ switch (bp->bp_hard->bph_reg){
+ case 0:
+ DR7_RW0SET(dr7,bp->bp_hard->bph_mode);
+ DR7_LEN0SET(dr7,bp->bp_hard->bph_length);
+ DR7_G0SET(dr7);
+ break;
+ case 1:
+ DR7_RW1SET(dr7,bp->bp_hard->bph_mode);
+ DR7_LEN1SET(dr7,bp->bp_hard->bph_length);
+ DR7_G1SET(dr7);
+ break;
+ case 2:
+ DR7_RW2SET(dr7,bp->bp_hard->bph_mode);
+ DR7_LEN2SET(dr7,bp->bp_hard->bph_length);
+ DR7_G2SET(dr7);
+ break;
+ case 3:
+ DR7_RW3SET(dr7,bp->bp_hard->bph_mode);
+ DR7_LEN3SET(dr7,bp->bp_hard->bph_length);
+ DR7_G3SET(dr7);
+ break;
+ default:
+ kdb_printf("kdb: Bad debug register!! %ld\n",
+ bp->bp_hard->bph_reg);
+ break;
+ }
+
+ kdba_putdr7(dr7);
+ return;
+}
+
+void
+kdba_removedbreg(kdb_bp_t *bp)
+{
+ int regnum;
+ kdb_machreg_t dr7;
+
+ if (!bp->bp_hard)
+ return;
+
+ regnum = bp->bp_hard->bph_reg;
+
+ dr7 = kdba_getdr7();
+
+ kdba_putdr(regnum, 0);
+
+ switch (regnum) {
+ case 0:
+ DR7_G0CLR(dr7);
+ DR7_L0CLR(dr7);
+ break;
+ case 1:
+ DR7_G1CLR(dr7);
+ DR7_L1CLR(dr7);
+ break;
+ case 2:
+ DR7_G2CLR(dr7);
+ DR7_L2CLR(dr7);
+ break;
+ case 3:
+ DR7_G3CLR(dr7);
+ DR7_L3CLR(dr7);
+ break;
+ default:
+ kdb_printf("kdb: Bad debug register!! %d\n", regnum);
+ break;
+ }
+
+ kdba_putdr7(dr7);
+}
+
+
+/*
+ * 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:
+ * ®s - Prints address of exception frame
+ * kesp - Prints kernel stack pointer at time of fault
+ * cesp - Prints current kernel stack pointer, inside kdb
+ * ceflags - Prints current flags, inside kdb
+ * %<regname> - Uses the value of the registers at the
+ * last time the user process entered kernel
+ * mode, instead of the registers at the time
+ * kdb was entered.
+ *
+ * Parameters:
+ * regname Pointer to string naming register
+ * regs Pointer to structure containing registers.
+ * Outputs:
+ * *contents Pointer to unsigned long to recieve register contents
+ * Returns:
+ * 0 Success
+ * KDB_BADREG Invalid register name
+ * Locking:
+ * None.
+ * Remarks:
+ * If kdb was entered via an interrupt from the kernel itself then
+ * ss and esp are *not* on the stack.
+ */
+
+static struct kdbregs {
+ char *reg_name;
+ size_t reg_offset;
+} kdbreglist[] = {
+ { "eax", offsetof(struct pt_regs, eax) },
+ { "ebx", offsetof(struct pt_regs, ebx) },
+ { "ecx", offsetof(struct pt_regs, ecx) },
+ { "edx", offsetof(struct pt_regs, edx) },
+
+ { "esi", offsetof(struct pt_regs, esi) },
+ { "edi", offsetof(struct pt_regs, edi) },
+ { "esp", offsetof(struct pt_regs, esp) },
+ { "eip", offsetof(struct pt_regs, eip) },
+
+ { "ebp", offsetof(struct pt_regs, ebp) },
+ { "xss", offsetof(struct pt_regs, xss) },
+ { "xcs", offsetof(struct pt_regs, xcs) },
+ { "eflags", offsetof(struct pt_regs, eflags) },
+
+ { "xds", offsetof(struct pt_regs, xds) },
+ { "xes", offsetof(struct pt_regs, xes) },
+ { "origeax", offsetof(struct pt_regs, orig_eax) },
+
+};
+
+static const int nkdbreglist = sizeof(kdbreglist) / sizeof(struct kdbregs);
+
+static struct kdbregs dbreglist[] = {
+ { "dr0", 0 },
+ { "dr1", 1 },
+ { "dr2", 2 },
+ { "dr3", 3 },
+ { "dr6", 6 },
+ { "dr7", 7 },
+};
+
+static const int ndbreglist = sizeof(dbreglist) / sizeof(struct kdbregs);
+
+int
+kdba_getregcontents(const char *regname,
+ struct pt_regs *regs,
+ kdb_machreg_t *contents)
+{
+ int i;
+
+ if (strcmp(regname, "cesp") == 0) {
+ asm volatile("movl %%esp,%0":"=m" (*contents));
+ return 0;
+ }
+
+ if (strcmp(regname, "ceflags") == 0) {
+ 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.esp0 - sizeof(struct pt_regs));
+ }
+
+ for (i=0; i<ndbreglist; i++) {
+ if (strnicmp(dbreglist[i].reg_name,
+ regname,
+ strlen(regname)) == 0)
+ break;
+ }
+
+ if ((i < ndbreglist)
+ && (strlen(dbreglist[i].reg_name) == strlen(regname))) {
+ *contents = kdba_getdr(dbreglist[i].reg_offset);
+ return 0;
+ }
+
+ if (!regs) {
+ kdb_printf("%s: pt_regs not available, use bt* or pid to select a different task\n", __FUNCTION__);
+ return KDB_BADREG;
+ }
+
+ if (strcmp(regname, "®s") == 0) {
+ *contents = (unsigned long)regs;
+ return 0;
+ }
+
+ if (strcmp(regname, "kesp") == 0) {
+ *contents = (unsigned long)regs + sizeof(struct pt_regs);
+ if ((regs->xcs & 0xffff) == __KERNEL_CS) {
+ /* esp and ss are not on stack */
+ *contents -= 2*4;
+ }
+ return 0;
+ }
+
+ for (i=0; i<nkdbreglist; i++) {
+ if (strnicmp(kdbreglist[i].reg_name,
+ regname,
+ strlen(regname)) == 0)
+ break;
+ }
+
+ if ((i < nkdbreglist)
+ && (strlen(kdbreglist[i].reg_name) == strlen(regname))) {
+ if ((regs->xcs & 0xffff) == __KERNEL_CS) {
+ /* No cpl switch, esp and ss are not on stack */
+ if (strcmp(kdbreglist[i].reg_name, "esp") == 0) {
+ *contents = (kdb_machreg_t)regs +
+ sizeof(struct pt_regs) - 2*4;
+ return(0);
+ }
+ if (strcmp(kdbreglist[i].reg_name, "xss") == 0) {
+ asm volatile(
+ "pushl %%ss\n"
+ "popl %0\n"
+ :"=m" (*contents));
+ return(0);
+ }
+ }
+ *contents = *(unsigned long *)((unsigned long)regs +
+ kdbreglist[i].reg_offset);
+ return(0);
+ }
+
+ return KDB_BADREG;
+}
+
+/*
+ * kdba_setregcontents
+ *
+ * Set the contents of the register specified by the
+ * input string argument. Return an error if the string
+ * does not match a machine register.
+ *
+ * Supports modification of user-mode registers via
+ * %<register-name>
+ *
+ * Parameters:
+ * regname Pointer to string naming register
+ * regs Pointer to structure containing registers.
+ * contents Unsigned long containing new register contents
+ * Outputs:
+ * Returns:
+ * 0 Success
+ * KDB_BADREG Invalid register name
+ * Locking:
+ * None.
+ * Remarks:
+ */
+
+int
+kdba_setregcontents(const char *regname,
+ struct pt_regs *regs,
+ unsigned long contents)
+{
+ int i;
+
+ if (regname[0] == '%') {
+ regname++;
+ regs = (struct pt_regs *)
+ (kdb_current_task->thread.esp0 - sizeof(struct pt_regs));
+ }
+
+ for (i=0; i<ndbreglist; i++) {
+ if (strnicmp(dbreglist[i].reg_name,
+ regname,
+ strlen(regname)) == 0)
+ break;
+ }
+
+ if ((i < ndbreglist)
+ && (strlen(dbreglist[i].reg_name) == strlen(regname))) {
+ kdba_putdr(dbreglist[i].reg_offset, contents);
+ return 0;
+ }
+
+ if (!regs) {
+ kdb_printf("%s: pt_regs not available, 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:
+ * m Model Specific Registers (extra defines register #)
+ * r Memory Type Range Registers (extra defines register)
+ */
+
+int
+kdba_dumpregs(struct pt_regs *regs,
+ const char *type,
+ const char *extra)
+{
+ int i;
+ int count = 0;
+
+ if (type
+ && (type[0] == 'u')) {
+ type = NULL;
+ regs = (struct pt_regs *)
+ (kdb_current_task->thread.esp0 - sizeof(struct pt_regs));
+ }
+
+ if (type == NULL) {
+ struct kdbregs *rlp;
+ kdb_machreg_t contents;
+
+ if (!regs) {
+ kdb_printf("%s: pt_regs not available, 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("®s = 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 'm':
+ break;
+ 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->eip : 0;
+}
+
+int
+kdba_setpc(struct pt_regs *regs, kdb_machreg_t newpc)
+{
+ if (KDB_NULL_REGS(regs))
+ return KDB_BADREG;
+ regs->eip = newpc;
+ KDB_STATE_SET(IP_ADJUSTED);
+ return 0;
+}
+
+/*
+ * kdba_main_loop
+ *
+ * Do any architecture specific set up before entering the main kdb loop.
+ * The primary function of this routine is to make all processes look the
+ * same to kdb, kdb must be able to list a process without worrying if the
+ * process is running or blocked, so make all process look as though they
+ * are blocked.
+ *
+ * Inputs:
+ * reason The reason KDB was invoked
+ * error The hardware-defined error code
+ * error2 kdb's current reason code. Initially error but can change
+ * acording to kdb state.
+ * db_result Result from break or debug point.
+ * regs The exception frame at time of fault/breakpoint. If reason
+ * is KDB_REASON_SILENT then regs is NULL, otherwise it should
+ * always be valid.
+ * Returns:
+ * 0 KDB was invoked for an event which it wasn't responsible
+ * 1 KDB handled the event for which it was invoked.
+ * Outputs:
+ * Sets eip and esp in current->thread.
+ * Locking:
+ * None.
+ * Remarks:
+ * none.
+ */
+
+int
+kdba_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
+ kdb_dbtrap_t db_result, struct pt_regs *regs)
+{
+ int ret;
+ kdb_save_running(regs);
+ ret = kdb_main_loop(reason, reason2, error, db_result, regs);
+ kdb_unsave_running(regs);
+ return ret;
+}
+
+void
+kdba_disableint(kdb_intstate_t *state)
+{
+ 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->eflags & EF_IE)
+ KDB_STATE_SET(A_IF);
+ else
+ KDB_STATE_CLEAR(A_IF);
+ regs->eflags = (regs->eflags | EF_TF) & ~EF_IE;
+}
+
+void
+kdba_clearsinglestep(struct pt_regs *regs)
+{
+ if (KDB_NULL_REGS(regs))
+ return;
+ if (KDB_STATE(A_IF))
+ regs->eflags |= EF_IE;
+ else
+ regs->eflags &= ~EF_IE;
+}
+
+#ifdef KDB_HAVE_LONGJMP
+int 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 */
+}
+#endif /* KDB_HAVE_LONGJMP */
+
+
+/*
+ * kdba_enable_mce
+ *
+ * This function is called once on each CPU to enable machine
+ * check exception handling.
+ *
+ * Inputs:
+ * None.
+ * Outputs:
+ * None.
+ * Returns:
+ * None.
+ * Locking:
+ * None.
+ * Remarks:
+ *
+ */
+
+void
+kdba_enable_mce(void)
+{
+ /* No longer required, arch/i386/kernel/bluesmoke.c does the job now */
+}
+
+/*
+ * kdba_enable_lbr
+ *
+ * Enable last branch recording.
+ *
+ * Parameters:
+ * None.
+ * Returns:
+ * None
+ * Locking:
+ * None
+ * Remarks:
+ * None.
+ */
+
+static unsigned char lbr_warned;
+
+void
+kdba_enable_lbr(void)
+{
+ u32 lv, hv;
+
+ if (!test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability)) {
+ if (lbr_warned) {
+ kdb_printf("kdb: machine does not support last branch recording\n");
+ lbr_warned = 1;
+ }
+ return;
+ }
+ rdmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+ lv |= 0x1; /* Set LBR enable */
+ wrmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+}
+
+/*
+ * kdba_disable_lbr
+ *
+ * disable last branch recording.
+ *
+ * Parameters:
+ * None.
+ * Returns:
+ * None
+ * Locking:
+ * None
+ * Remarks:
+ * None.
+ */
+
+void
+kdba_disable_lbr(void)
+{
+ u32 lv, hv;
+
+ if (!test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability)) {
+ if (lbr_warned) {
+ kdb_printf("kdb: machine does not support last branch recording\n");
+ lbr_warned = 1;
+ }
+ return;
+ }
+ rdmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+ lv &= ~0x1; /* Set LBR disable */
+ wrmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+}
+
+/*
+ * kdba_print_lbr
+ *
+ * Print last branch and last exception addresses
+ *
+ * Parameters:
+ * None.
+ * Returns:
+ * None
+ * Locking:
+ * None
+ * Remarks:
+ * None.
+ */
+
+void
+kdba_print_lbr(void)
+{
+ u32 from, to, dummy;
+
+ if (!test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability))
+ return;
+
+ rdmsr(MSR_IA32_LASTBRANCHFROMIP, from, dummy);
+ rdmsr(MSR_IA32_LASTBRANCHTOIP, to, dummy);
+ kdb_printf("Last Branch IP, from: ");
+ kdb_symbol_print(from, NULL, KDB_SP_DEFAULT);
+ kdb_printf(" to: ");
+ kdb_symbol_print(to, NULL, KDB_SP_DEFAULT);
+ kdb_printf("\n");
+ rdmsr(MSR_IA32_LASTINTFROMIP, from, dummy);
+ rdmsr(MSR_IA32_LASTINTTOIP, to, dummy);
+ kdb_printf("Last Int IP, from: ");
+ kdb_symbol_print(from, NULL, KDB_SP_DEFAULT);
+ kdb_printf(" to: ");
+ kdb_symbol_print(to, NULL, KDB_SP_DEFAULT);
+ kdb_printf("\n");
+}
+
+/*
+ * kdba_pt_regs
+ *
+ * Format a struct pt_regs
+ *
+ * Inputs:
+ * argc argument count
+ * argv argument vector
+ * envp environment vector
+ * regs registers at time kdb was entered.
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ * If no address is supplied, it uses regs.
+ */
+
+static int
+kdba_pt_regs(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+ int diag;
+ kdb_machreg_t addr;
+ long offset = 0;
+ int nextarg;
+ struct pt_regs *p;
+ static const char *fmt = " %-11.11s 0x%lx\n";
+
+ if (argc == 0) {
+ addr = (kdb_machreg_t) regs;
+ } else if (argc == 1) {
+ nextarg = 1;
+ diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+ if (diag)
+ return diag;
+ } else {
+ return KDB_ARGCOUNT;
+ }
+
+ p = (struct pt_regs *) addr;
+ kdb_printf("struct pt_regs %p-%p\n", p, (unsigned char *)p + sizeof(*p) - 1);
+ kdb_print_nameval("ebx", p->ebx);
+ kdb_print_nameval("ecx", p->ecx);
+ kdb_print_nameval("edx", p->edx);
+ kdb_print_nameval("esi", p->esi);
+ kdb_print_nameval("edi", p->edi);
+ kdb_print_nameval("ebp", p->ebp);
+ kdb_print_nameval("eax", p->eax);
+ kdb_printf(fmt, "xds", p->xds);
+ kdb_printf(fmt, "xes", p->xes);
+ kdb_print_nameval("orig_eax", p->orig_eax);
+ kdb_print_nameval("eip", p->eip);
+ kdb_printf(fmt, "xcs", p->xcs);
+ kdb_printf(fmt, "eflags", p->eflags);
+ kdb_printf(fmt, "esp", p->esp);
+ kdb_printf(fmt, "xss", p->xss);
+ return 0;
+}
+
+/*
+ * kdba_stackdepth
+ *
+ * Print processes that are using more than a specific percentage of their
+ * stack.
+ *
+ * Inputs:
+ * argc argument count
+ * argv argument vector
+ * envp environment vector
+ * regs registers at time kdb was entered.
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ * If no percentage is supplied, it uses 60.
+ */
+
+static void
+kdba_stackdepth1(struct task_struct *p, unsigned long esp)
+{
+ struct thread_info *tinfo;
+ int used;
+ const char *type;
+ kdb_ps1(p);
+ do {
+ tinfo = (struct thread_info *)(esp & -THREAD_SIZE);
+ used = sizeof(*tinfo) + THREAD_SIZE - (esp & (THREAD_SIZE-1));
+ type = NULL;
+#ifdef CONFIG_4KSTACKS
+ if (kdb_task_has_cpu(p))
+ type = kdba_irq_ctx_type(kdb_process_cpu(p), tinfo);
+#endif
+ if (!type)
+ type = "process";
+ kdb_printf(" %s stack %p esp %lx used %d\n", type, tinfo, esp, used);
+ esp = tinfo->previous_esp;
+ } while (esp);
+}
+
+static int
+kdba_stackdepth(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+ int diag, cpu, threshold, used, over;
+ 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, regs);
+ 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.esp;
+ 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.esp);
+ }
+ /* Now the tasks that are not on cpus */
+ kdb_do_each_thread(g, p) {
+ if (kdb_task_has_cpu(p))
+ continue;
+ esp = p->thread.esp;
+ 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;
+}
+
+/*
+ * kdba_init
+ *
+ * Architecture specific initialization.
+ *
+ * Parameters:
+ * None.
+ * Returns:
+ * None.
+ * Locking:
+ * None.
+ * Remarks:
+ * None.
+ */
+
+void __init
+kdba_init(void)
+{
+ kdba_enable_lbr();
+ kdb_register("pt_regs", kdba_pt_regs, "address", "Format struct pt_regs", 0);
+ 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 KDB_REASON_SILENT then regs is NULL, otherwise it should
+ * always be valid.
+ * Returns:
+ * None.
+ * Locking:
+ * None.
+ * Remarks:
+ * noop on ix86.
+ */
+
+void
+kdba_adjust_ip(kdb_reason_t reason, int error, struct pt_regs *regs)
+{
+ return;
+}
+
+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;
+}
Index: 2.6.x-xfs/arch/i386/kdb/pc_keyb.h
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kdb/pc_keyb.h 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/arch/i386/kdb/pc_keyb.h 2005-12-20 16:50:55.853662016 +1100
@@ -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)
Index: 2.6.x-xfs/arch/i386/kernel/entry.S
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kernel/entry.S 2005-12-05 09:56:00.828389600 +1100
+++ 2.6.x-xfs/arch/i386/kernel/entry.S 2005-12-20 16:50:55.854638443 +1100
@@ -130,6 +130,18 @@
popl %eax
jmp syscall_exit
+#if defined(CONFIG_KDB)
+ENTRY(kdb_call)
+ pushl %eax # save orig EAX
+ SAVE_ALL
+ pushl %esp # struct pt_regs
+ pushl $0 # error_code
+ pushl $7 # KDB_REASON_ENTRY
+ call kdb
+ addl $12,%esp # remove args
+ jmp restore_all
+#endif
+
/*
* Return to user mode is not as complex as all this looks,
* but we want the default path for a system call return to
@@ -640,6 +652,22 @@
pushl $do_alignment_check
jmp error_code
+#if defined(CONFIG_KDB)
+ENTRY(page_fault_mca)
+ pushl %ecx
+ pushl %edx
+ pushl %eax
+ movl $473,%ecx
+ rdmsr
+ andl $0xfffffffe,%eax /* Disable last branch recording */
+ wrmsr
+ popl %eax
+ popl %edx
+ popl %ecx
+ pushl $do_page_fault
+ jmp error_code
+#endif
+
KPROBE_ENTRY(page_fault)
pushl $do_page_fault
jmp error_code
Index: 2.6.x-xfs/arch/i386/kernel/i8259.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kernel/i8259.c 2005-10-28 15:24:22.048246051 +1000
+++ 2.6.x-xfs/arch/i386/kernel/i8259.c 2005-12-20 16:50:55.854638443 +1100
@@ -412,6 +412,10 @@
int vector = FIRST_EXTERNAL_VECTOR + i;
if (i >= NR_IRQS)
break;
+#ifdef CONFIG_KDB
+ if (vector == KDBENTER_VECTOR)
+ continue;
+#endif
if (vector != SYSCALL_VECTOR)
set_intr_gate(vector, interrupt[i]);
}
Index: 2.6.x-xfs/arch/i386/kernel/io_apic.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kernel/io_apic.c 2005-12-05 09:56:00.836201021 +1100
+++ 2.6.x-xfs/arch/i386/kernel/io_apic.c 2005-12-20 16:50:55.856591297 +1100
@@ -26,6 +26,9 @@
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/config.h>
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
#include <linux/smp_lock.h>
#include <linux/mc146818rtc.h>
#include <linux/compiler.h>
@@ -1162,6 +1165,10 @@
current_vector += 8;
if (current_vector == SYSCALL_VECTOR)
goto next;
+#ifdef CONFIG_KDB
+ if (current_vector == KDBENTER_VECTOR)
+ goto next;
+#endif /* CONFIG_KDB */
if (current_vector >= FIRST_SYSTEM_VECTOR) {
offset++;
Index: 2.6.x-xfs/arch/i386/kernel/irq.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kernel/irq.c 2005-12-05 09:56:00.851823864 +1100
+++ 2.6.x-xfs/arch/i386/kernel/irq.c 2005-12-20 16:50:55.856591297 +1100
@@ -44,6 +44,16 @@
static union irq_ctx *hardirq_ctx[NR_CPUS];
static union irq_ctx *softirq_ctx[NR_CPUS];
+#ifdef CONFIG_KDB
+const char *kdba_irq_ctx_type(int cpu, struct thread_info *tinfo)
+{
+ if (tinfo == &hardirq_ctx[cpu]->tinfo)
+ return "hardirq_ctx";
+ if (tinfo == &softirq_ctx[cpu]->tinfo)
+ return "softirq_ctx";
+ return NULL;
+}
+#endif /* CONFIG_KDB */
#endif
/*
Index: 2.6.x-xfs/arch/i386/kernel/reboot.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kernel/reboot.c 2005-12-05 09:56:00.913338806 +1100
+++ 2.6.x-xfs/arch/i386/kernel/reboot.c 2005-12-20 16:50:55.857567724 +1100
@@ -4,6 +4,10 @@
#include <linux/config.h>
#include <linux/mm.h>
+#include <linux/config.h>
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -309,6 +313,14 @@
* all of the others, and disable their local APICs.
*/
+#ifdef CONFIG_KDB
+ /*
+ * If this restart is occuring while kdb is running (e.g. reboot
+ * command), the other CPU's are already stopped. Don't try to
+ * stop them yet again.
+ */
+ if (!KDB_IS_RUNNING())
+#endif /* CONFIG_KDB */
smp_send_stop();
#endif /* CONFIG_SMP */
Index: 2.6.x-xfs/arch/i386/kernel/smp.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kernel/smp.c 2005-10-28 15:24:22.062892465 +1000
+++ 2.6.x-xfs/arch/i386/kernel/smp.c 2005-12-20 16:50:55.857567724 +1100
@@ -25,6 +25,11 @@
#include <asm/tlbflush.h>
#include <mach_apic.h>
+#include <linux/config.h>
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
+
/*
* Some notes on x86 processor bugs affecting SMP operation:
*
@@ -143,6 +148,15 @@
*/
cfg = __prepare_ICR(shortcut, vector);
+#ifdef CONFIG_KDB
+ if (vector == KDB_VECTOR) {
+ /*
+ * Setup KDB IPI to be delivered as an NMI
+ */
+ cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+ }
+#endif /* CONFIG_KDB */
+
/*
* Send the IPI. The write to APIC_ICR fires this off.
*/
@@ -220,6 +234,15 @@
* program the ICR
*/
cfg = __prepare_ICR(0, vector);
+
+#ifdef CONFIG_KDB
+ if (vector == KDB_VECTOR) {
+ /*
+ * Setup KDB IPI to be delivered as an NMI
+ */
+ cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+ }
+#endif /* CONFIG_KDB */
/*
* Send the IPI. The write to APIC_ICR fires this off.
@@ -469,6 +492,15 @@
on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
}
+#ifdef CONFIG_KDB
+void
+smp_kdb_stop(void)
+{
+ if (!KDB_FLAG(NOIPI))
+ send_IPI_allbutself(KDB_VECTOR);
+}
+#endif /* CONFIG_KDB */
+
/*
* this function sends a 'reschedule' IPI to another CPU.
* it goes straight through and wastes no time serializing
Index: 2.6.x-xfs/arch/i386/kernel/smpboot.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kernel/smpboot.c 2005-12-20 16:44:01.327979673 +1100
+++ 2.6.x-xfs/arch/i386/kernel/smpboot.c 2005-12-20 16:50:55.858544152 +1100
@@ -43,6 +43,9 @@
#include <linux/kernel_stat.h>
#include <linux/smp_lock.h>
#include <linux/bootmem.h>
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/percpu.h>
@@ -435,6 +438,11 @@
*/
cpu_set(cpuid, cpu_callin_map);
+#ifdef CONFIG_KDB
+ /* Activate any preset global breakpoints on this cpu */
+ kdb(KDB_REASON_SILENT, 0, 0);
+#endif /* CONFIG_KDB */
+
/*
* Synchronize the TSC with the BP
*/
Index: 2.6.x-xfs/arch/i386/kernel/traps.c
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kernel/traps.c 2005-12-20 16:44:01.328956101 +1100
+++ 2.6.x-xfs/arch/i386/kernel/traps.c 2005-12-20 16:50:55.859520579 +1100
@@ -38,6 +38,10 @@
#include <linux/mca.h>
#endif
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+#endif /* CONFIG_KDB */
+
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -57,6 +61,9 @@
#include "mach_traps.h"
asmlinkage int system_call(void);
+#ifdef CONFIG_KDB
+asmlinkage int kdb_call(void);
+#endif /* CONFIG_KDB */
struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
{ 0, 0 }, { 0, 0 } };
@@ -85,6 +92,9 @@
asmlinkage void stack_segment(void);
asmlinkage void general_protection(void);
asmlinkage void page_fault(void);
+#ifdef CONFIG_KDB
+asmlinkage void page_fault_mca(void);
+#endif /* CONFIG_KDB */
asmlinkage void coprocessor_error(void);
asmlinkage void simd_coprocessor_error(void);
asmlinkage void alignment_check(void);
@@ -341,6 +351,10 @@
bust_spinlocks(0);
die.lock_owner = -1;
spin_unlock_irq(&die.lock);
+#ifdef CONFIG_KDB
+ kdb_diemsg = str;
+ kdb(KDB_REASON_OOPS, err, regs);
+#endif /* CONFIG_KDB */
if (kexec_should_crash(current))
crash_kexec(regs);
@@ -447,7 +461,7 @@
}
DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip)
-#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)
@@ -549,6 +563,9 @@
static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
{
+#ifdef CONFIG_KDB
+ (void)kdb(KDB_REASON_NMI, reason, regs);
+#endif /* CONFIG_KDB */
#ifdef CONFIG_MCA
/* Might actually be able to figure out what the guilty party
* is. */
@@ -582,6 +599,9 @@
smp_processor_id(), regs->eip);
show_registers(regs);
printk("console shuts up ...\n");
+#ifdef CONFIG_KDB
+ kdb(KDB_REASON_NMI, 0, regs);
+#endif /* CONFIG_KDB */
console_silent();
spin_unlock(&nmi_print_lock);
bust_spinlocks(0);
@@ -604,7 +624,17 @@
/* Only the BSP gets external NMIs from the system. */
if (!smp_processor_id())
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, 0, SIGINT)
== NOTIFY_STOP)
@@ -673,6 +703,10 @@
#ifdef CONFIG_KPROBES
fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
{
+#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;
@@ -712,6 +746,11 @@
get_debugreg(condition, 6);
+#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;
@@ -765,6 +804,16 @@
return;
}
+#if defined(CONFIG_KDB) && !defined(CONFIG_KPROBES)
+fastcall 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
@@ -1086,7 +1135,17 @@
set_trap_gate(11,&segment_not_present);
set_trap_gate(12,&stack_segment);
set_trap_gate(13,&general_protection);
+#ifdef CONFIG_KDB
+ if (test_bit(X86_FEATURE_MCE, boot_cpu_data.x86_capability) &&
+ test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability)) {
+ set_intr_gate(14,&page_fault_mca);
+ }
+ else {
+ set_intr_gate(14,&page_fault);
+ }
+#else /* !CONFIG_KDB */
set_intr_gate(14,&page_fault);
+#endif /* CONFIG_KDB */
set_trap_gate(15,&spurious_interrupt_bug);
set_trap_gate(16,&coprocessor_error);
set_trap_gate(17,&alignment_check);
@@ -1096,6 +1155,14 @@
set_trap_gate(19,&simd_coprocessor_error);
set_system_gate(SYSCALL_VECTOR,&system_call);
+#ifdef CONFIG_KDB
+ kdb_enablehwfault();
+ /*
+ * A trap gate, used by the kernel to enter the
+ * debugger, preserving all registers.
+ */
+ set_trap_gate(KDBENTER_VECTOR, &kdb_call);
+#endif /* CONFIG_KDB */
/*
* Should be a barrier for any external CPU state.
Index: 2.6.x-xfs/arch/i386/kernel/vmlinux.lds.S
===================================================================
--- 2.6.x-xfs.orig/arch/i386/kernel/vmlinux.lds.S 2005-10-28 15:24:22.097067433 +1000
+++ 2.6.x-xfs/arch/i386/kernel/vmlinux.lds.S 2005-12-20 16:50:55.860497006 +1100
@@ -97,6 +97,11 @@
*(.con_initcall.init)
}
__con_initcall_end = .;
+ __kdb_initcall_start = .;
+ .kdb_initcall.init : AT(ADDR(.kdb_initcall.init) - LOAD_OFFSET) {
+ *(.kdb_initcall.init)
+ }
+ __kdb_initcall_end = .;
SECURITY_INIT
. = ALIGN(4);
__alt_instructions = .;
Index: 2.6.x-xfs/arch/i386/Makefile.cpu
===================================================================
--- 2.6.x-xfs.orig/arch/i386/Makefile.cpu 2005-12-05 09:49:07.597361910 +1100
+++ 2.6.x-xfs/arch/i386/Makefile.cpu 2005-12-20 16:50:55.882954832 +1100
@@ -32,6 +32,7 @@
cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586)
cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686)
+cflags-$(CONFIG_KDB) += $(call cc-option,-fno-optimize-sibling-calls,)
# AMD Elan support
cflags-$(CONFIG_X86_ELAN) += -march=i486
Index: 2.6.x-xfs/include/asm-i386/ansidecl.h
===================================================================
--- 2.6.x-xfs.orig/include/asm-i386/ansidecl.h 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/include/asm-i386/ansidecl.h 2005-12-20 16:50:55.861473433 +1100
@@ -0,0 +1,313 @@
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* ANSI and traditional C compatibility macros
+
+ ANSI C is assumed if __STDC__ is #defined.
+
+ Macro ANSI C definition Traditional C definition
+ ----- ---- - ---------- ----------- - ----------
+ 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
+
+#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
+
+/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
+ it too, but it's not in C89. */
+#undef inline
+# if GCC_VERSION >= 2007
+# define inline __inline__ /* __inline__ prevents -pedantic warnings */
+# else
+# define inline /* nothing */
+# 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 (GCC_VERSION >= 2093)
+# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
+# else
+# define ATTRIBUTE_UNUSED_LABEL
+# endif /* GNUC >= 2.93 */
+#endif /* ATTRIBUTE_UNUSED_LABEL */
+
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif /* ATTRIBUTE_UNUSED */
+
+#ifndef ATTRIBUTE_NORETURN
+#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#endif /* ATTRIBUTE_NORETURN */
+
+/* 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 */
+
+/* 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_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 */
+
+/* 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 */
Index: 2.6.x-xfs/include/asm-i386/bfd.h
===================================================================
--- 2.6.x-xfs.orig/include/asm-i386/bfd.h 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/include/asm-i386/bfd.h 2005-12-20 16:50:55.877096268 +1100
@@ -0,0 +1,4458 @@
+/* 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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if 0 /* CONFIG_KDB */
+#include "ansidecl.h"
+#include "symcat.h"
+#else
+#include <asm/ansidecl.h>
+ /* Extracts from symcat.h */
+#define CONCAT2(a,b) a##b
+#define CONCAT3(a,b,c) a##b##c
+#define CONCAT4(a,b,c,d) a##b##c##d
+#define STRINGX(s) #s
+#define XCONCAT2(a,b) CONCAT2(a,b)
+#define XCONCAT3(a,b,c) CONCAT3(a,b,c)
+#define XCONCAT4(a,b,c,d) CONCAT4(a,b,c,d)
+#define XSTRING(s) STRINGX(s)
+#endif /* CONFIG_KDB */
+
+#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 32
+
+/* 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
+
+#if 0
+/* Poison. */
+#undef false
+#undef true
+#define false dont_use_false_in_bfd
+#define true dont_use_true_in_bfd
+#endif
+
+#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 */
+
+#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;
+
+/* 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
+
+/* 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. */
+};
+
+/* 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;
+
+/* 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) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_lma(bfd, ptr) ((ptr)->lma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma = (val)), ((ptr)->user_set_vma = TRUE), TRUE)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),TRUE)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),TRUE)
+
+typedef struct stat stat_type;
+
+typedef enum bfd_print_symbol
+{
+ bfd_print_symbol_name,
+ bfd_print_symbol_more,
+ bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+/* Information about a symbol that nm needs. */
+
+typedef struct _symbol_info
+{
+ symvalue value;
+ char type;
+ const char *name; /* Symbol name. */
+ unsigned char stab_type; /* Stab type. */
+ char stab_other; /* Stab other. */
+ short stab_desc; /* Stab desc. */
+ const char *stab_name; /* String for stab type. */
+} symbol_info;
+
+/* Get the name of a stabs type code. */
+
+extern const char *bfd_get_stab_name (int);
+
+/* Hash table routines. There is no way to free up a hash table. */
+
+/* An element in the hash table. Most uses will actually use a larger
+ structure, and an instance of this will be the first field. */
+
+struct bfd_hash_entry
+{
+ /* Next entry for this hash code. */
+ struct bfd_hash_entry *next;
+ /* String being hashed. */
+ const char *string;
+ /* Hash code. This is the full hash code, not the index into the
+ table. */
+ unsigned long hash;
+};
+
+/* A hash table. */
+
+struct bfd_hash_table
+{
+ /* The hash array. */
+ struct bfd_hash_entry **table;
+ /* The number of slots in the hash table. */
+ unsigned int size;
+ /* A function used to create new elements in the hash table. The
+ first entry is itself a pointer to an element. When this
+ function is first invoked, this pointer will be NULL. However,
+ having the pointer permits a hierarchy of method functions to be
+ built each of which calls the function in the superclass. Thus
+ each function should be written to allocate a new block of memory
+ only if the argument is NULL. */
+ struct bfd_hash_entry *(*newfunc)
+ (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);
+
+#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_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);
+
+/* 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);
+extern bfd_boolean bfd_mips_ecoff_create_embedded_relocs
+ (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **);
+
+/* 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
+};
+
+extern bfd_boolean bfd_elf_record_link_assignment
+ (bfd *, 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 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 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 *);
+
+/* 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, char *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 bfd_boolean bfd_m68k_elf32_create_embedded_relocs
+ (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **);
+extern bfd_boolean bfd_mips_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, 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 *);
+
+/* 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);
+
+/* Extracted from init.c. */
+void bfd_init (void);
+
+/* Extracted from opncls.c. */
+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_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. */
+/* This structure is used for a comdat section, as in PE. A comdat
+ section is associated with a particular symbol. When the linker
+ sees a comdat section, it keeps only one of the sections with a
+ given name and associated with a given symbol. */
+
+struct bfd_comdat_info
+{
+ /* The name of the symbol associated with a comdat section. */
+ const char *name;
+
+ /* The local symbol table index of the symbol associated with a
+ comdat section. This is only meaningful to the object file format
+ specific code; it is not an index into the list returned by
+ bfd_canonicalize_symtab. */
+ long symbol;
+};
+
+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 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
+
+ /* ELF reserves 4 processor specific bits and 8 operating system
+ specific bits in sh_flags; at present we can get away with just
+ one in communicating between the assembler and BFD, but this
+ isn't a good long-term solution. */
+#define SEC_ARCH_BIT_0 0x008
+
+ /* A signal to the OS that the section contains read only data. */
+#define SEC_READONLY 0x010
+
+ /* The section contains code only. */
+#define SEC_CODE 0x020
+
+ /* The section contains data only. */
+#define SEC_DATA 0x040
+
+ /* The section will reside in ROM. */
+#define SEC_ROM 0x080
+
+ /* The section contains constructor information. This section
+ type is used by the linker to create lists of constructors and
+ destructors used by <<g++>>. When a back end sees a symbol
+ which should be used in a constructor list, it creates a new
+ section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
+ the symbol to it, and builds a relocation. To build the lists
+ of constructors, all the linker has to do is catenate all the
+ sections called <<__CTOR_LIST__>> and relocate the data
+ contained within - exactly the operations it would peform on
+ standard data. */
+#define SEC_CONSTRUCTOR 0x100
+
+ /* The section has contents - a data section could be
+ <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+ <<SEC_HAS_CONTENTS>> */
+#define SEC_HAS_CONTENTS 0x200
+
+ /* An instruction to the linker to not output the section
+ even if it has information which would normally be written. */
+#define SEC_NEVER_LOAD 0x400
+
+ /* The section is a COFF shared library section. This flag is
+ only for the linker. If this type of section appears in
+ the input file, the linker must copy it to the output file
+ without changing the vma or size. FIXME: Although this
+ was originally intended to be general, it really is COFF
+ specific (and the flag was renamed to indicate this). It
+ might be cleaner to have some more general mechanism to
+ allow the back end to control what the linker does with
+ sections. */
+#define SEC_COFF_SHARED_LIBRARY 0x800
+
+ /* The section contains thread local data. */
+#define SEC_THREAD_LOCAL 0x1000
+
+ /* 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 0x4000
+
+ /* The section contains common symbols (symbols may be defined
+ multiple times, the value of a symbol is the amount of
+ space it requires, and the largest symbol value is the one
+ used). Most targets have exactly one of these (which we
+ translate to bfd_com_section_ptr), but ECOFF has two. */
+#define SEC_IS_COMMON 0x8000
+
+ /* The section contains only debugging information. For
+ example, this is set for ELF .debug and .stab sections.
+ strip tests this flag to see if a section can be
+ discarded. */
+#define SEC_DEBUGGING 0x10000
+
+ /* The contents of this section are held in memory pointed to
+ by the contents field. This is checked by bfd_get_section_contents,
+ and the data is retrieved from memory if appropriate. */
+#define SEC_IN_MEMORY 0x20000
+
+ /* The contents of this section are to be excluded by the
+ linker for executable and shared objects unless those
+ objects are to be further relocated. */
+#define SEC_EXCLUDE 0x40000
+
+ /* The contents of this section are to be sorted 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 0x80000
+
+ /* When linking, duplicate sections of the same name should be
+ discarded, rather than being combined into a single section as
+ is usually done. This is similar to how common symbols are
+ handled. See SEC_LINK_DUPLICATES below. */
+#define SEC_LINK_ONCE 0x100000
+
+ /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+ should handle duplicate sections. */
+#define SEC_LINK_DUPLICATES 0x600000
+
+ /* This value for SEC_LINK_DUPLICATES means that duplicate
+ sections with the same name should simply be discarded. */
+#define SEC_LINK_DUPLICATES_DISCARD 0x0
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if there are any duplicate sections, although
+ it should still only link one copy. */
+#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections are a different size. */
+#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections contain different
+ contents. */
+#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000
+
+ /* This section was created by the linker as part of dynamic
+ relocation or other arcane processing. It is skipped when
+ going through the first-pass output, trusting that someone
+ else up the line will take care of it later. */
+#define SEC_LINKER_CREATED 0x800000
+
+ /* This section should not be subject to garbage collection. */
+#define SEC_KEEP 0x1000000
+
+ /* This section contains "short" data, and should be placed
+ "near" the GP. */
+#define SEC_SMALL_DATA 0x2000000
+
+ /* This section contains data which may be shared with other
+ executables or shared objects. */
+#define SEC_SHARED 0x4000000
+
+ /* 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. */
+#define SEC_BLOCK 0x8000000
+
+ /* Conditionally link this section; do not link if there are no
+ references found to any symbol in the section. */
+#define SEC_CLINK 0x10000000
+
+ /* Attempt to merge identical entities in the section.
+ Entity size is given in the entsize field. */
+#define SEC_MERGE 0x20000000
+
+ /* 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 0x40000000
+
+ /* This section contains data about section groups. */
+#define SEC_GROUP 0x80000000
+
+ /* End of section flags. */
+
+ /* Some internal packed boolean fields. */
+
+ /* See the vma field. */
+ unsigned int user_set_vma : 1;
+
+ /* Whether relocations have been processed. */
+ unsigned int reloc_done : 1;
+
+ /* A mark flag used by some of the linker backends. */
+ unsigned int linker_mark : 1;
+
+ /* 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;
+
+ /* A mark flag used by some linker backends for garbage collection. */
+ unsigned int gc_mark : 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. */
+ unsigned int has_tls_reloc:1;
+
+ /* Nonzero if this section needs the relax finalize pass. */
+ unsigned int need_finalize_relax:1;
+
+ /* Nonzero if this section has a gp reloc. */
+ unsigned int has_gp_reloc:1;
+
+ /* Unused bits. */
+ unsigned int flag13:1;
+ unsigned int flag14:1;
+ unsigned int flag15:1;
+ unsigned int flag16:4;
+ unsigned int flag20:4;
+ unsigned int flag24:8;
+
+ /* 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>>). This will be filled in after relocation. */
+ bfd_size_type _cooked_size;
+
+ /* The original size on disk of the section, in octets. Normally this
+ value is the same as the size, but if some relaxing has
+ been done, then this value will be bigger. */
+ bfd_size_type _raw_size;
+
+ /* If this section is going to be output, then this value is the
+ offset 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;
+
+ /* Optional information about a COMDAT entry; NULL if not COMDAT. */
+ struct bfd_comdat_info *comdat;
+
+ /* 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;
+
+ struct bfd_link_order *link_order_head;
+ struct bfd_link_order *link_order_tail;
+} asection;
+
+/* These sections are global, and are managed by BFD. The application
+ and target back end are not permitted to change the values in
+ these sections. New code should use the section_ptr macros rather
+ than referring directly to the const sections. The const sections
+ may eventually vanish. */
+#define BFD_ABS_SECTION_NAME "*ABS*"
+#define BFD_UND_SECTION_NAME "*UND*"
+#define BFD_COM_SECTION_NAME "*COM*"
+#define BFD_IND_SECTION_NAME "*IND*"
+
+/* The absolute section. */
+extern 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;
+#define bfd_get_section_size_before_reloc(section) \
+ ((section)->_raw_size)
+#define bfd_get_section_size_after_reloc(section) \
+ ((section)->reloc_done ? (section)->_cooked_size \
+ : (abort (), (bfd_size_type) 1))
+
+/* 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, PS) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = *_ps; \
+ *_ps = _s->next; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = _ps; \
+ } \
+ while (0)
+#define bfd_section_list_insert(ABFD, PS, S) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = S; \
+ _s->next = *_ps; \
+ *_ps = _s; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = &_s->next; \
+ } \
+ while (0)
+
+void bfd_section_list_clear (bfd *);
+
+asection *bfd_get_section_by_name (bfd *abfd, const char *name);
+
+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 (bfd *abfd, const char *name);
+
+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);
+
+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_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))
+void _bfd_strip_section_from_output
+ (struct bfd_link_info *info, asection *section);
+
+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
+ 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)
+ 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_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_sh2e 0x2e
+#define bfd_mach_sh3 0x30
+#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_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_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_cris, /* Axis CRIS */
+ 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_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,
+
+/* 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,
+
+/* Like BFD_RELOC_HI16_S, but PC relative. */
+ BFD_RELOC_PCREL_HI16_S,
+
+/* Like BFD_RELOC_LO16, but PC relative. */
+ BFD_RELOC_PCREL_LO16,
+
+/* Relocation 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,
+
+
+/* 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,
+
+
+/* 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,
+
+/* 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,
+
+/* These relocs are only used within the ARM assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_ARM_IMMEDIATE,
+ BFD_RELOC_ARM_ADRL_IMMEDIATE,
+ BFD_RELOC_ARM_OFFSET_IMM,
+ BFD_RELOC_ARM_SHIFT_IMM,
+ BFD_RELOC_ARM_SWI,
+ BFD_RELOC_ARM_MULTI,
+ BFD_RELOC_ARM_CP_OFF_IMM,
+ BFD_RELOC_ARM_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_HWLITERAL,
+ BFD_RELOC_ARM_THUMB_ADD,
+ BFD_RELOC_ARM_THUMB_IMM,
+ BFD_RELOC_ARM_THUMB_SHIFT,
+ BFD_RELOC_ARM_THUMB_OFFSET,
+ BFD_RELOC_ARM_GOT12,
+ BFD_RELOC_ARM_GOT32,
+ BFD_RELOC_ARM_JUMP_SLOT,
+ BFD_RELOC_ARM_COPY,
+ BFD_RELOC_ARM_GLOB_DAT,
+ BFD_RELOC_ARM_PLT32,
+ BFD_RELOC_ARM_RELATIVE,
+ BFD_RELOC_ARM_GOTOFF,
+ BFD_RELOC_ARM_GOTPC,
+
+/* Renesas / SuperH SH relocs. Not all of these appear in object files. */
+ BFD_RELOC_SH_PCDISP8BY2,
+ BFD_RELOC_SH_PCDISP12BY2,
+ BFD_RELOC_SH_IMM4,
+ BFD_RELOC_SH_IMM4BY2,
+ BFD_RELOC_SH_IMM4BY4,
+ BFD_RELOC_SH_IMM8,
+ BFD_RELOC_SH_IMM8BY2,
+ BFD_RELOC_SH_IMM8BY4,
+ BFD_RELOC_SH_PCRELIMM8BY2,
+ BFD_RELOC_SH_PCRELIMM8BY4,
+ BFD_RELOC_SH_SWITCH16,
+ BFD_RELOC_SH_SWITCH32,
+ BFD_RELOC_SH_USES,
+ BFD_RELOC_SH_COUNT,
+ BFD_RELOC_SH_ALIGN,
+ BFD_RELOC_SH_CODE,
+ BFD_RELOC_SH_DATA,
+ BFD_RELOC_SH_LABEL,
+ 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,
+
+/* Thumb 23-, 12- and 9-bit pc-relative branches. The lowest bit must
+be zero and is not stored in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BRANCH9,
+ BFD_RELOC_THUMB_PCREL_BRANCH12,
+ BFD_RELOC_THUMB_PCREL_BRANCH23,
+
+/* 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 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_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 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,
+
+/* 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,
+
+/* 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_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,
+
+/* 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,
+
+/* 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,
+
+/* Generic Xtensa relocations. Only the operand number is encoded
+in the relocation. The details are determined by extracting the
+instruction opcode. */
+ 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))
+
+#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;
+
+ /* To avoid dragging too many header files into every file that
+ includes `<<bfd.h>>', IOSTREAM has been declared as a "char *",
+ and MTIME as a "long". Their correct types, to which they
+ are cast when used, are "FILE *" and "time_t". The iostream
+ is the result of an fopen on the filename. However, if the
+ BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+ to a bfd_in_memory struct. */
+ void *iostream;
+
+ /* 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 place where we add to the section list. */
+ struct bfd_section **section_tail;
+
+ /* 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;
+
+ /* 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);
+
+const char *bfd_archive_filename (bfd *);
+
+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_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_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_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(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_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_tail;
+ 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 asthe 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_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 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##_get_lineno, \
+ NAME##_find_nearest_line, \
+ 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 *);
+
+ 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 *);
+ /* 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_discard_group
+
+ 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 *);
+
+ /* Discard members of a group. */
+ bfd_boolean (*_bfd_discard_group) (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_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 **);
+ /* 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))
+
+/* 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: 2.6.x-xfs/include/asm-i386/kdb.h
===================================================================
--- 2.6.x-xfs.orig/include/asm-i386/kdb.h 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/include/asm-i386/kdb.h 2005-12-20 16:50:55.877096268 +1100
@@ -0,0 +1,135 @@
+#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.
+ */
+#define KDB_ENTER() do {if (kdb_on && !KDB_IS_RUNNING()) { asm("\tint $129\n"); }} while(0)
+
+/*
+ * Needed for exported symbols.
+ */
+typedef unsigned long kdb_machreg_t;
+
+#define kdb_machreg_fmt "0x%lx"
+#define kdb_machreg_fmt0 "0x%08lx"
+#define kdb_bfd_vma_fmt "0x%lx"
+#define kdb_bfd_vma_fmt0 "0x%08lx"
+#define kdb_elfw_addr_fmt "0x%x"
+#define kdb_elfw_addr_fmt0 "0x%08x"
+
+/*
+ * Per cpu arch specific kdb state. Must be in range 0xff000000.
+ */
+#define KDB_STATE_A_IF 0x01000000 /* Saved IF flag */
+
+/*
+ * Functions to safely read and write kernel areas. The {to,from}_xxx
+ * addresses are not necessarily valid, these functions must check for
+ * validity. If the arch already supports get and put routines with
+ * suitable validation and/or recovery on invalid addresses then use
+ * those routines, otherwise check it yourself.
+ */
+
+/*
+ * asm-i386 uaccess.h supplies __copy_to_user which relies on MMU to
+ * trap invalid addresses in the _xxx fields. Verify the other address
+ * of the pair is valid by accessing the first and last byte ourselves,
+ * then any access violations should only be caused by the _xxx
+ * addresses,
+ */
+
+#include <asm/uaccess.h>
+
+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);
+ switch (size) {
+ case 1:
+ r = __copy_to_user_inatomic(to, (void *)from_xxx, 1);
+ break;
+ case 2:
+ r = __copy_to_user_inatomic(to, (void *)from_xxx, 2);
+ break;
+ case 4:
+ r = __copy_to_user_inatomic(to, (void *)from_xxx, 4);
+ break;
+ case 8:
+ r = __copy_to_user_inatomic(to, (void *)from_xxx, 8);
+ break;
+ default:
+ r = __copy_to_user_inatomic(to, (void *)from_xxx, size);
+ break;
+ }
+ set_fs(oldfs);
+ return r;
+}
+
+/* For numa with replicated code/data, the platform must supply its own
+ * kdba_putarea_size and kdba_getarea_size routines. Without replication kdb
+ * uses the standard architecture routines.
+ */
+#ifdef CONFIG_NUMA_REPLICATE
+extern int kdba_putarea_size(unsigned long to_xxx, void *from, size_t size);
+extern int kdba_getarea_size(void *to, unsigned long from_xxx, size_t size);
+#else
+#define kdba_putarea_size __kdba_putarea_size
+#define kdba_getarea_size __kdba_getarea_size
+#endif
+
+static inline int
+kdba_verify_rw(unsigned long addr, size_t size)
+{
+ unsigned char data[size];
+ return(kdba_getarea_size(data, addr, size) || kdba_putarea_size(addr, data, size));
+}
+
+static inline unsigned long
+kdba_funcptr_value(void *fp)
+{
+ return (unsigned long)fp;
+}
+
+#endif /* !_ASM_KDB_H */
Index: 2.6.x-xfs/include/asm-i386/kdbprivate.h
===================================================================
--- 2.6.x-xfs.orig/include/asm-i386/kdbprivate.h 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/include/asm-i386/kdbprivate.h 2005-12-20 16:50:55.878072696 +1100
@@ -0,0 +1,182 @@
+#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.
+ */
+
+typedef unsigned char kdb_machinst_t;
+
+/*
+ * KDB_MAXBPT describes the total number of breakpoints
+ * supported by this architecure.
+ */
+#define KDB_MAXBPT 16
+
+/*
+ * KDB_MAXHARDBPT describes the total number of hardware
+ * breakpoint registers that exist.
+ */
+#define KDB_MAXHARDBPT 4
+
+/*
+ * Platform specific environment entries
+ */
+#define KDB_PLATFORM_ENV "IDMODE=x86", "BYTESPERWORD=4", "IDCOUNT=16"
+
+/*
+ * Define the direction that the stack grows
+ */
+#define KDB_STACK_DIRECTION (-1) /* Stack grows down */
+
+/*
+ * Support for ia32 debug registers
+ */
+typedef struct _kdbhard_bp {
+ kdb_machreg_t bph_reg; /* Register this breakpoint uses */
+
+ unsigned int bph_free:1; /* Register available for use */
+ unsigned int bph_data:1; /* Data Access breakpoint */
+
+ unsigned int bph_write:1; /* Write Data breakpoint */
+ unsigned int bph_mode:2; /* 0=inst, 1=write, 2=io, 3=read */
+ unsigned int bph_length:2; /* 0=1, 1=2, 2=BAD, 3=4 (bytes) */
+} kdbhard_bp_t;
+
+#define IA32_BREAKPOINT_INSTRUCTION 0xcc
+
+#define DR6_BT 0x00008000
+#define DR6_BS 0x00004000
+#define DR6_BD 0x00002000
+
+#define DR6_B3 0x00000008
+#define DR6_B2 0x00000004
+#define DR6_B1 0x00000002
+#define DR6_B0 0x00000001
+#define DR6_DR_MASK 0x0000000F
+
+#define DR7_RW_VAL(dr, drnum) \
+ (((dr) >> (16 + (4 * (drnum)))) & 0x3)
+
+#define DR7_RW_SET(dr, drnum, rw) \
+ do { \
+ (dr) &= ~(0x3 << (16 + (4 * (drnum)))); \
+ (dr) |= (((rw) & 0x3) << (16 + (4 * (drnum)))); \
+ } while (0)
+
+#define DR7_RW0(dr) DR7_RW_VAL(dr, 0)
+#define DR7_RW0SET(dr,rw) DR7_RW_SET(dr, 0, rw)
+#define DR7_RW1(dr) DR7_RW_VAL(dr, 1)
+#define DR7_RW1SET(dr,rw) DR7_RW_SET(dr, 1, rw)
+#define DR7_RW2(dr) DR7_RW_VAL(dr, 2)
+#define DR7_RW2SET(dr,rw) DR7_RW_SET(dr, 2, rw)
+#define DR7_RW3(dr) DR7_RW_VAL(dr, 3)
+#define DR7_RW3SET(dr,rw) DR7_RW_SET(dr, 3, rw)
+
+
+#define DR7_LEN_VAL(dr, drnum) \
+ (((dr) >> (18 + (4 * (drnum)))) & 0x3)
+
+#define DR7_LEN_SET(dr, drnum, rw) \
+ do { \
+ (dr) &= ~(0x3 << (18 + (4 * (drnum)))); \
+ (dr) |= (((rw) & 0x3) << (18 + (4 * (drnum)))); \
+ } while (0)
+
+#define DR7_LEN0(dr) DR7_LEN_VAL(dr, 0)
+#define DR7_LEN0SET(dr,len) DR7_LEN_SET(dr, 0, len)
+#define DR7_LEN1(dr) DR7_LEN_VAL(dr, 1)
+#define DR7_LEN1SET(dr,len) DR7_LEN_SET(dr, 1, len)
+#define DR7_LEN2(dr) DR7_LEN_VAL(dr, 2)
+#define DR7_LEN2SET(dr,len) DR7_LEN_SET(dr, 2, len)
+#define DR7_LEN3(dr) DR7_LEN_VAL(dr, 3)
+#define DR7_LEN3SET(dr,len) DR7_LEN_SET(dr, 3, len)
+
+#define DR7_G0(dr) (((dr)>>1)&0x1)
+#define DR7_G0SET(dr) ((dr) |= 0x2)
+#define DR7_G0CLR(dr) ((dr) &= ~0x2)
+#define DR7_G1(dr) (((dr)>>3)&0x1)
+#define DR7_G1SET(dr) ((dr) |= 0x8)
+#define DR7_G1CLR(dr) ((dr) &= ~0x8)
+#define DR7_G2(dr) (((dr)>>5)&0x1)
+#define DR7_G2SET(dr) ((dr) |= 0x20)
+#define DR7_G2CLR(dr) ((dr) &= ~0x20)
+#define DR7_G3(dr) (((dr)>>7)&0x1)
+#define DR7_G3SET(dr) ((dr) |= 0x80)
+#define DR7_G3CLR(dr) ((dr) &= ~0x80)
+
+#define DR7_L0(dr) (((dr))&0x1)
+#define DR7_L0SET(dr) ((dr) |= 0x1)
+#define DR7_L0CLR(dr) ((dr) &= ~0x1)
+#define DR7_L1(dr) (((dr)>>2)&0x1)
+#define DR7_L1SET(dr) ((dr) |= 0x4)
+#define DR7_L1CLR(dr) ((dr) &= ~0x4)
+#define DR7_L2(dr) (((dr)>>4)&0x1)
+#define DR7_L2SET(dr) ((dr) |= 0x10)
+#define DR7_L2CLR(dr) ((dr) &= ~0x10)
+#define DR7_L3(dr) (((dr)>>6)&0x1)
+#define DR7_L3SET(dr) ((dr) |= 0x40)
+#define DR7_L3CLR(dr) ((dr) &= ~0x40)
+
+#define DR7_GD 0x00002000 /* General Detect Enable */
+#define DR7_GE 0x00000200 /* Global exact */
+#define DR7_LE 0x00000100 /* Local exact */
+
+#define DR_TYPE_EXECUTE 0x0
+#define DR_TYPE_WRITE 0x1
+#define DR_TYPE_IO 0x2
+#define DR_TYPE_RW 0x3
+
+extern kdb_machreg_t kdba_getdr6(void);
+extern void kdba_putdr6(kdb_machreg_t);
+
+extern kdb_machreg_t kdba_getdr7(void);
+
+#define KDB_HAVE_LONGJMP
+#ifdef KDB_HAVE_LONGJMP
+/*
+ * Support for setjmp/longjmp
+ */
+#define JB_BX 0
+#define JB_SI 1
+#define JB_DI 2
+#define JB_BP 3
+#define JB_SP 4
+#define JB_PC 5
+
+typedef struct __kdb_jmp_buf {
+ unsigned long regs[6]; /* kdba_setjmp assumes fixed offsets here */
+} kdb_jmp_buf;
+
+extern int asmlinkage kdba_setjmp(kdb_jmp_buf *);
+extern void asmlinkage kdba_longjmp(kdb_jmp_buf *, int);
+
+extern kdb_jmp_buf *kdbjmpbuf;
+#endif /* KDB_HAVE_LONGJMP */
+
+/* Arch specific data saved for running processes */
+
+struct kdba_running_process {
+ long esp; /* CONFIG_4KSTACKS may be on a different stack */
+};
+
+static inline
+void kdba_save_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+ k->esp = current_stack_pointer;
+}
+
+static inline
+void kdba_unsave_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+}
+
+extern const char *kdba_irq_ctx_type(int cpu, struct thread_info *tinfo);
+
+#endif /* !_ASM_KDBPRIVATE_H */
Index: 2.6.x-xfs/include/asm-i386/kmap_types.h
===================================================================
--- 2.6.x-xfs.orig/include/asm-i386/kmap_types.h 2005-01-06 11:10:16.000000000 +1100
+++ 2.6.x-xfs/include/asm-i386/kmap_types.h 2005-12-20 16:50:55.879049123 +1100
@@ -23,7 +23,8 @@
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: 2.6.x-xfs/include/asm-i386/mach-default/irq_vectors.h
===================================================================
--- 2.6.x-xfs.orig/include/asm-i386/mach-default/irq_vectors.h 2005-01-06 11:10:16.000000000 +1100
+++ 2.6.x-xfs/include/asm-i386/mach-default/irq_vectors.h 2005-12-20 16:50:55.879049123 +1100
@@ -29,6 +29,7 @@
#define FIRST_EXTERNAL_VECTOR 0x20
#define SYSCALL_VECTOR 0x80
+#define KDBENTER_VECTOR 0x81
/*
* Vectors 0x20-0x2f are used for ISA interrupts.
@@ -48,6 +49,7 @@
#define INVALIDATE_TLB_VECTOR 0xfd
#define RESCHEDULE_VECTOR 0xfc
#define CALL_FUNCTION_VECTOR 0xfb
+#define KDB_VECTOR 0xf9
#define THERMAL_APIC_VECTOR 0xf0
/*
Index: 2.6.x-xfs/include/asm-i386/ptrace.h
===================================================================
--- 2.6.x-xfs.orig/include/asm-i386/ptrace.h 2005-10-28 15:24:25.070289643 +1000
+++ 2.6.x-xfs/include/asm-i386/ptrace.h 2005-12-20 16:50:55.879049123 +1100
@@ -54,6 +54,29 @@
#define PTRACE_GET_THREAD_AREA 25
#define PTRACE_SET_THREAD_AREA 26
+enum EFLAGS {
+ EF_CF = 0x00000001,
+ EF_PF = 0x00000004,
+ EF_AF = 0x00000010,
+ EF_ZF = 0x00000040,
+ EF_SF = 0x00000080,
+ EF_TF = 0x00000100,
+ EF_IE = 0x00000200,
+ EF_DF = 0x00000400,
+ EF_OF = 0x00000800,
+ EF_IOPL = 0x00003000,
+ EF_IOPL_RING0 = 0x00000000,
+ EF_IOPL_RING1 = 0x00001000,
+ EF_IOPL_RING2 = 0x00002000,
+ EF_NT = 0x00004000, /* nested task */
+ EF_RF = 0x00010000, /* resume */
+ EF_VM = 0x00020000, /* virtual mode */
+ EF_AC = 0x00040000, /* alignment */
+ EF_VIF = 0x00080000, /* virtual interrupt */
+ EF_VIP = 0x00100000, /* virtual interrupt pending */
+ EF_ID = 0x00200000, /* id */
+};
+
#ifdef __KERNEL__
#include <asm/vm86.h>
Index: 2.6.x-xfs/kdb/modules/kdbm_x86.c
===================================================================
--- 2.6.x-xfs.orig/kdb/modules/kdbm_x86.c 2005-05-25 01:08:16.000000000 +1000
+++ 2.6.x-xfs/kdb/modules/kdbm_x86.c 2005-12-20 16:50:55.881978404 +1100
@@ -0,0 +1,919 @@
+/*
+ * 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.
+ */
+
+#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");
+
+typedef struct _kdb_desc {
+ unsigned short limit;
+ unsigned short base;
+ unsigned char base_h1;
+ unsigned char type:4;
+ unsigned char seg:1;
+ unsigned char dpl:2;
+ unsigned char present:1;
+ unsigned char limit_h:4;
+ unsigned char avl:2;
+ unsigned char db:1;
+ unsigned char g:1; /* granularity */
+ unsigned char base_h2;
+} kdb_desc_t;
+
+typedef struct _kdb_gate_desc {
+ unsigned short offset;
+ unsigned short sel;
+ unsigned char res;
+ unsigned char type:4;
+ unsigned char seg:1;
+ unsigned char dpl:2;
+ unsigned char present:1;
+ unsigned short offset_h;
+} kdb_gate_desc_t;
+
+#define KDB_SEL_MAX 0x2000
+#define KDB_IDT_MAX 0x100
+#define KDB_SYS_DESC_TYPE_TSS 0x01
+#define KDB_SYS_DESC_TYPE_LDT 0x02
+#define KDB_SYS_DESC_TYPE_TSSB 0x03
+#define KDB_SYS_DESC_TYPE_CALLG 0x04
+#define KDB_SYS_DESC_TYPE_TASKG 0x05
+#define KDB_SYS_DESC_TYPE_INTG 0x06
+#define KDB_SYS_DESC_TYPE_TRAPG 0x07
+
+#define KDB_SYS_DESC_TYPE_TSS32 0x09
+#define KDB_SYS_DESC_TYPE_TSS32B 0x0b
+#define KDB_SYS_DESC_TYPE_CALLG32 0x0c
+#define KDB_SYS_DESC_TYPE_INTG32 0x0e
+#define KDB_SYS_DESC_TYPE_TRAPG32 0x0f
+
+#define KDB_SYS_DESC_OFFSET(d) ((unsigned long)(d->offset_h << 16 | d->offset))
+#define KDB_SYS_DESC_CALLG_COUNT(d) ((unsigned int)(d->res & 0x0F))
+
+#define KDB_SEG_DESC_TYPE_CODE 0x08
+#define KDB_SEG_DESC_TYPE_CODE_R 0x02
+#define KDB_SEG_DESC_TYPE_DATA_W 0x02
+#define KDB_SEG_DESC_TYPE_CODE_C 0x02 /* conforming */
+#define KDB_SEG_DESC_TYPE_DATA_D 0x02 /* expand-down */
+#define KDB_SEG_DESC_TYPE_A 0x01 /* accessed */
+
+#define KDB_SEG_DESC_BASE(d) ((unsigned long)(d->base_h2 << 24 | d->base_h1 << 16 | d->base))
+#define _LIMIT(d) ((unsigned long)(d->limit_h << 16 | d->limit))
+#define KDB_SEG_DESC_LIMIT(d) (d->g ? ((_LIMIT(d)+1) << 12) -1 : _LIMIT(d))
+
+/* helper functions to display system registers in verbose mode */
+static void display_gdtr(void)
+{
+ struct Xgt_desc_struct gdtr;
+
+ __asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+ kdb_printf("gdtr.address = 0x%8.8lx, gdtr.size = 0x%x\n", gdtr.address, gdtr.size);
+
+ return;
+}
+
+static void display_ldtr(void)
+{
+ struct Xgt_desc_struct gdtr;
+ unsigned long ldtr;
+
+ __asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+ __asm__ __volatile__ ("sldt %0\n\t" : "=m"(ldtr));
+
+ kdb_printf("ldtr = 0x%8.8lx ", ldtr);
+
+ if (ldtr < gdtr.size) {
+ kdb_desc_t *ldt_desc = (kdb_desc_t *)(gdtr.address + (ldtr & ~7));
+ kdb_printf("base=0x%8.8lx, limit=0x%8.8lx\n", KDB_SEG_DESC_BASE(ldt_desc),
+ KDB_SEG_DESC_LIMIT(ldt_desc));
+ } else {
+ kdb_printf("invalid\n");
+ }
+
+ return;
+}
+
+static void display_idtr(void)
+{
+ struct Xgt_desc_struct idtr;
+ __asm__ __volatile__ ("sidt %0\n\t" : "=m"(idtr));
+ kdb_printf("idtr.address = 0x%8.8lx, idtr.size = 0x%x\n", idtr.address, idtr.size);
+ return;
+}
+
+static char *cr0_flags[] = {
+ "pe", "mp", "em", "ts", "et", "ne", NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "wp", NULL, "am", NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, "nw", "cd", "pg"};
+
+static void display_cr0(void)
+{
+ kdb_machreg_t cr0;
+ int i;
+ __asm__ ("movl %%cr0,%0\n\t":"=r"(cr0));
+ kdb_printf("cr0=0x%08lx ", cr0);
+ for (i = 0; i < 32; i++) {
+ if (test_bit(i, &cr0) && cr0_flags[i])
+ kdb_printf("%s ", cr0_flags[i]);
+ }
+ kdb_printf("\n");
+ return;
+}
+
+static void display_cr3(void)
+{
+ kdb_machreg_t cr3;
+ __asm__ ("movl %%cr3,%0\n\t":"=r"(cr3));
+ kdb_printf("cr3 = 0x%08lx ", cr3);
+ if (cr3 & 0x08)
+ kdb_printf("pwt ");
+ if (cr3 & 0x10)
+ kdb_printf("pcd ");
+ kdb_printf("pgdir=%8.8lx\n", cr3 & PAGE_MASK);
+ return;
+}
+
+static char *cr4_flags[] = {
+ "vme", "pvi", "tsd", "de", "pse", "pae", "mce", "pge", "pce"};
+
+static void display_cr4(void)
+{
+ kdb_machreg_t cr4;
+ int i;
+ __asm__ ("movl %%cr4,%0\n\t":"=r"(cr4));
+ kdb_printf("cr4 = 0x%08lx ", cr4);
+ for (i = 0; i < 9; i++) {
+ if (test_bit(i, &cr4))
+ kdb_printf("%s ", cr4_flags[i]);
+ }
+ kdb_printf("\n");
+ return;
+}
+
+static char *dr_type_name[] = { "exec", "write", "io", "rw" };
+
+static void display_dr_status(int nr, int enabled, int local, int len, int type)
+{
+ if (!enabled) {
+ kdb_printf("\tdebug register %d: not enabled\n", nr);
+ return;
+ }
+
+ kdb_printf("\tdebug register %d: %s, len = %d, type = %s\n",
+ nr,
+ local? " local":"global",
+ len,
+ dr_type_name[type]);
+}
+
+static void display_dr(void)
+{
+ kdb_machreg_t dr0, dr1, dr2, dr3, dr6, dr7;
+ int dbnr, set;
+
+ __asm__ ("movl %%db0,%0\n\t":"=r"(dr0));
+ __asm__ ("movl %%db1,%0\n\t":"=r"(dr1));
+ __asm__ ("movl %%db2,%0\n\t":"=r"(dr2));
+ __asm__ ("movl %%db3,%0\n\t":"=r"(dr3));
+ __asm__ ("movl %%db6,%0\n\t":"=r"(dr6));
+ __asm__ ("movl %%db7,%0\n\t":"=r"(dr7));
+
+ kdb_printf("dr0 = 0x%08lx dr1 = 0x%08lx dr2 = 0x%08lx dr3 = 0x%08lx\n",
+ dr0, dr1, dr2, dr3);
+ kdb_printf("dr6 = 0x%08lx ", dr6);
+ dbnr = dr6 & DR6_DR_MASK;
+ if (dbnr) {
+ int nr;
+ switch(dbnr) {
+ case 1:
+ nr = 0; break;
+ case 2:
+ nr = 1; break;
+ case 4:
+ nr = 2; break;
+ default:
+ nr = 3; break;
+ }
+ kdb_printf("debug register hit = %d", nr);
+ } else if (dr6 & DR_STEP) {
+ kdb_printf("single step");
+ } else if (dr6 & DR_SWITCH) {
+ kdb_printf("task switch");
+ }
+ kdb_printf("\n");
+
+ kdb_printf("dr7 = 0x%08lx\n", dr7);
+ set = DR7_L0(dr7) || DR7_G0(dr7);
+ display_dr_status(0, set, DR7_L0(dr7), DR7_LEN0(dr7), DR7_RW0(dr7));
+ set = DR7_L1(dr7) || DR7_G1(dr7);
+ display_dr_status(1, set, DR7_L1(dr7), DR7_LEN1(dr7), DR7_RW1(dr7));
+ set = DR7_L2(dr7) || DR7_G2(dr7);
+ display_dr_status(2, set, DR7_L2(dr7), DR7_LEN2(dr7), DR7_RW2(dr7));
+ set = DR7_L3(dr7) || DR7_G3(dr7);
+ display_dr_status(3, set, DR7_L3(dr7), DR7_LEN3(dr7), DR7_RW3(dr7));
+}
+
+static char *set_eflags[] = {
+ "carry", NULL, "parity", NULL, "adjust", NULL, "zero", "sign",
+ "trace", "intr-on", "dir", "overflow", NULL, NULL, "nestedtask", NULL,
+ "resume", "vm", "align", "vif", "vip", "id", NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+
+static void display_eflags(unsigned long ef)
+{
+ int i, iopl;
+ kdb_printf("eflags = 0x%08lx ", ef);
+ for (i = 0; i < 22; i++) {
+ if (test_bit(i, &ef) && set_eflags[i])
+ kdb_printf("%s ", set_eflags[i]);
+ }
+
+ iopl = ((unsigned long)(ef & 0x00003000)) >> 12;
+ kdb_printf("iopl=%c\n", '0'+iopl);
+ return;
+}
+
+static void display_tss(struct tss_struct *t)
+{
+ kdb_printf(" cs = %04x, eip = 0x%8.8lx\n", t->es, t->eip);
+ kdb_printf(" ss = %04x, esp = 0x%8.8lx\n", t->ss, t->esp);
+ kdb_printf(" ss0 = %04x, esp0 = 0x%8.8lx\n", t->ss0, t->esp0);
+ kdb_printf(" ss1 = %04x, esp1 = 0x%8.8lx\n", t->ss1, t->esp1);
+ kdb_printf(" ss2 = %04x, esp2 = 0x%8.8lx\n", t->ss2, t->esp2);
+ kdb_printf(" ldt = %04x, cr3 = 0x%8.8lx\n", t->ldt, t->__cr3);
+ kdb_printf(" ds = %04x, es = %04x fs = %04x gs = %04x\n",
+ t->ds, t->es, t->fs, t->gs);
+ kdb_printf(" eax = 0x%8.8lx, ebx = 0x%8.8lx ecx = 0x%8.8lx edx = 0x%8.8lx\n",
+ t->eax, t->ebx, t->ecx, t->edx);
+ kdb_printf(" esi = 0x%8.8lx, edi = 0x%8.8lx ebp = 0x%8.8lx\n",
+ t->esi, t->edi, t->ebp);
+}
+
+static char *gate_desc_types[] = {
+ "invalid", "tss-avlb", "ldt", "tss-busy",
+ "callgate", "taskgate", "intgate", "trapgate",
+ "invalid", "tss32-avlb", "invalid", "tss32-busy",
+ "callgate32", "invalid", "intgate32", "trapgate32",
+ NULL };
+
+static int
+display_gate_desc(kdb_gate_desc_t * d)
+{
+ kdb_printf("%-11s ", gate_desc_types[d->type]);
+
+ switch(d->type) {
+ case KDB_SYS_DESC_TYPE_LDT:
+ kdb_printf("base=0x%8.8lx limit=0x%8.8lx dpl=%d\n",
+ KDB_SEG_DESC_BASE(((kdb_desc_t *)d)),
+ KDB_SEG_DESC_LIMIT(((kdb_desc_t *)d)), d->dpl);
+ break;
+ case KDB_SYS_DESC_TYPE_TSS32:
+ case KDB_SYS_DESC_TYPE_TSS32B:
+ {
+ struct tss_struct *tss = (struct tss_struct *)KDB_SEG_DESC_BASE(((kdb_desc_t *)d));
+ kdb_printf("base=0x%8.8lx limit=0x%8.8lx dpl=%d\n",
+ (unsigned long)tss,
+ KDB_SEG_DESC_LIMIT(((kdb_desc_t *)d)), d->dpl);
+ display_tss(tss);
+ break;
+ }
+ case KDB_SYS_DESC_TYPE_CALLG:
+ kdb_printf("sel=0x%4.4x off=0x%8.8lx dpl=%d wc=%d\n",
+ d->sel, KDB_SYS_DESC_OFFSET(d), d->dpl,
+ KDB_SYS_DESC_CALLG_COUNT(d));
+ break;
+ case KDB_SYS_DESC_TYPE_CALLG32:
+ kdb_printf("sel=0x%4.4x off=0x%8.8lx dpl=%d dwc=%d\n",
+ d->sel, KDB_SYS_DESC_OFFSET(d), d->dpl,
+ KDB_SYS_DESC_CALLG_COUNT(d));
+ break;
+ default:
+ kdb_printf("sel=0x%4.4x off=0x%8.8lx dpl=%d\n",
+ d->sel, KDB_SYS_DESC_OFFSET(d), d->dpl);
+ break;
+ }
+
+ return 0;
+}
+
+static int
+display_seg_desc(kdb_desc_t * d)
+{
+ unsigned char type = d->type;
+
+ if (type & KDB_SEG_DESC_TYPE_CODE) {
+ kdb_printf("%-7s base=0x%8.8lx limit=0x%8.8lx dpl=%d %c%c%c %s %s %s \n",
+ "code",
+ KDB_SEG_DESC_BASE(d), KDB_SEG_DESC_LIMIT(d),
+ d->dpl,
+ (type & KDB_SEG_DESC_TYPE_CODE_R)?'r':'-',
+ '-', 'x',
+ d->db ? "32b" : "16b",
+ (type & KDB_SEG_DESC_TYPE_A)?"ac":"",
+ (type & KDB_SEG_DESC_TYPE_CODE_C)?"conf":"");
+ }
+ else {
+ kdb_printf("%-7s base=0x%8.8lx limit=0x%8.8lx dpl=%d %c%c%c %s %s %s \n",
+ "data",
+ KDB_SEG_DESC_BASE(d), KDB_SEG_DESC_LIMIT(d),
+ d->dpl,
+ 'r',
+ (type & KDB_SEG_DESC_TYPE_DATA_W)?'w':'-',
+ '-',
+ d->db ? "32b" : "16b",
+ (type & KDB_SEG_DESC_TYPE_A)?"ac":"",
+ (type & KDB_SEG_DESC_TYPE_DATA_D)?"down":"");
+ }
+
+ return 0;
+}
+
+static int
+kdb_parse_two_numbers(int argc, const char **argv, int *sel, int *count, int *last_sel, int *last_count)
+{
+ int diag;
+
+ if (argc > 2)
+ return KDB_ARGCOUNT;
+
+ kdbgetintenv("MDCOUNT", count);
+
+ if (argc == 0) {
+ *sel = *last_sel;
+ if (*last_count)
+ *count = *last_count;
+ } else {
+ unsigned long val;
+
+ if (argc >= 1) {
+ diag = kdbgetularg(argv[1], &val);
+ if (diag)
+ return diag;
+ *sel = val;
+ }
+ if (argc >= 2) {
+ diag = kdbgetularg(argv[2], &val);
+ if (diag)
+ return diag;
+ *count = (int) val;
+ *last_count = (int) val;
+ } else if (*last_count) {
+ *count = *last_count;
+ }
+ }
+ return 0;
+}
+
+/*
+ * kdb_gdt
+ *
+ * This function implements the 'gdt' command.
+ *
+ * gdt [<selector> [<line count>]]
+ *
+ * Inputs:
+ * argc argument count
+ * argv argument vector
+ * envp environment vector
+ * regs registers at time kdb was entered.
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ */
+static int
+kdb_gdt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+ int sel = 0;
+ struct Xgt_desc_struct gdtr;
+ int diag, count = 8;
+ kdb_desc_t * gdt;
+ unsigned int max_sel;
+ static int last_sel = 0, last_count = 0;
+
+ diag = kdb_parse_two_numbers(argc, argv, &sel, &count, &last_sel, &last_count);
+ if (diag)
+ return diag;
+
+ __asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+ gdt = (kdb_desc_t *) gdtr.address;
+
+ max_sel = (gdtr.size + 1) / sizeof(kdb_desc_t);
+ if (sel >= max_sel) {
+ sel = 0;
+ }
+
+ if (sel + count > max_sel)
+ count = max_sel - sel;
+
+ while (count--) {
+ kdb_desc_t * d = &gdt[sel];
+ kdb_printf("0x%4.4x ", sel++);
+
+ if (!d->present) {
+ kdb_printf("not present\n");
+ continue;
+ }
+ if (d->seg)
+ display_seg_desc(d);
+ else
+ display_gate_desc((kdb_gate_desc_t *)d);
+ }
+
+ last_sel = sel;
+ return 0;
+}
+
+/*
+ * kdb_ldt
+ *
+ * This function implements the 'ldt' command.
+ *
+ * ldt [<selector> [<line count>]]
+ *
+ * Inputs:
+ * argc argument count
+ * argv argument vector
+ * envp environment vector
+ * regs registers at time kdb was entered.
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ */
+static int
+kdb_ldt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+ int sel = 0;
+ struct Xgt_desc_struct gdtr;
+ unsigned long ldtr = 0;
+ int diag, count = 8;
+ kdb_desc_t * ldt, *ldt_desc;
+ unsigned int max_sel;
+ static int last_sel = 0, last_count = 0;
+
+ diag = kdb_parse_two_numbers(argc, argv, &sel, &count, &last_sel, &last_count);
+ if (diag)
+ return diag;
+
+ if (strcmp(argv[0], "ldtp") == 0) {
+ kdb_printf("pid=%d, process=%s\n", kdb_current_task->pid, kdb_current_task->comm);
+ if (!kdb_current_task->mm || !kdb_current_task->mm->context.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));
+
+ if (ldtr > gdtr.size+1) {
+ kdb_printf("invalid ldtr\n");
+ return 0;
+ }
+
+ ldt_desc = (kdb_desc_t *)(gdtr.address + (ldtr & ~7));
+ ldt = (kdb_desc_t *) KDB_SEG_DESC_BASE(ldt_desc);
+ max_sel = (KDB_SEG_DESC_LIMIT(ldt_desc)+1) / sizeof(kdb_desc_t);
+ }
+
+ if (sel >= max_sel) {
+ sel = 0;
+ }
+
+ if (sel + count > max_sel)
+ count = max_sel - sel;
+
+ while (count--) {
+ kdb_desc_t * d = &ldt[sel];
+ kdb_printf("0x%4.4x ", sel++);
+
+ if (d->seg)
+ display_seg_desc(d);
+ else
+ display_gate_desc((kdb_gate_desc_t *)d);
+ }
+
+ last_sel = sel;
+ return 0;
+}
+
+/*
+ * kdb_idt
+ *
+ * This function implements the 'idt' command.
+ *
+ * idt [<vector> [<line count>]]
+ *
+ * Inputs:
+ * argc argument count
+ * argv argument vector
+ * envp environment vector
+ * regs registers at time kdb was entered.
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ */
+static int
+kdb_idt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+ int vec = 0;
+ struct Xgt_desc_struct idtr;
+ int diag, count = 8;
+ kdb_gate_desc_t * idt;
+ unsigned int max_entries;
+ static int last_vec = 0, last_count = 0;
+
+ diag = kdb_parse_two_numbers(argc, argv, &vec, &count, &last_vec, &last_count);
+ if (diag)
+ return diag;
+
+ __asm__ __volatile__ ("sidt %0\n\t" : "=m"(idtr));
+ idt = (kdb_gate_desc_t *) idtr.address;
+
+ max_entries = (idtr.size+1) / sizeof(kdb_gate_desc_t);
+ if (vec >= max_entries) {
+ vec = 0;
+ }
+
+ if (vec + count > max_entries)
+ count = max_entries - vec;
+
+ while (count--) {
+ kdb_gate_desc_t * d = &idt[vec];
+ kdb_printf("0x%4.4x ", vec++);
+ if (!d->present) {
+ kdb_printf("not present\n");
+ continue;
+ }
+ if (d->seg) {
+ kdb_printf("invalid\n");
+ continue;
+ }
+ display_gate_desc(d);
+ }
+
+ last_vec = vec;
+
+ return 0;
+}
+
+#define _PAGE_PSE 0x080
+
+#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
+ * envp environment vector
+ * regs registers at time kdb was entered.
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ */
+static int
+kdb_pte(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+ static unsigned long last_addr = 0, last_count = 0;
+ int count = 8;
+ unsigned long addr;
+ long offset = 0;
+ pgd_t *pgdir;
+ pmd_t *pgmiddle;
+ pte_t *pte;
+
+#ifdef CONFIG_X86_PAE
+ kdb_printf("This kernel is compiled with PAE support.");
+ return KDB_NOTIMP;
+#endif
+ kdbgetintenv("MDCOUNT", &count);
+
+ if (argc == 0) {
+ if (last_addr == 0)
+ return KDB_ARGCOUNT;
+ addr = last_addr;
+ if (last_count)
+ count = last_count;
+ } else {
+ kdb_machreg_t val;
+ int diag, nextarg = 1;
+ diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+ if (diag)
+ return diag;
+ if (argc > nextarg+1)
+ return KDB_ARGCOUNT;
+
+ if (argc >= nextarg) {
+ diag = kdbgetularg(argv[nextarg], &val);
+ if (!diag) {
+ count = (int) val;
+ last_count = count;
+ } else if (last_count) {
+ count = last_count;
+ }
+ }
+ }
+
+ /*
+ * round off the addr to a page boundary.
+ */
+ addr &= PAGE_MASK;
+
+ get_pagetables(addr, &pgdir, &pgmiddle, &pte);
+
+ if (pgdir)
+ display_pgdir(addr, pgdir, 1);
+#if 0 /* for now, let's not print pgmiddle. */
+ if (pgmiddle)
+ display_pgmiddle(addr, pgmiddle, 1);
+#endif
+ if (pte) {
+ int displayed;
+ displayed = display_pte(addr, pte, count);
+ addr += (displayed << PAGE_SHIFT);
+ }
+ last_addr = addr;
+ return 0;
+}
+#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, const char **envp, struct pt_regs *regs)
+{
+ 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
+ * envp environment vector
+ * regs registers at time kdb was entered.
+ * Outputs:
+ * None.
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ * Locking:
+ * none.
+ * Remarks:
+ * This should have been an option to rd command say "rd v",
+ * but it is here as it is a non-essential x86-only command,
+ * that need not clutter arch/i386/kdb/kdbasupport.c.
+ */
+static int
+kdb_rdv(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+ kdba_dumpregs(regs, NULL, NULL);
+ kdb_printf("\n");
+ display_eflags(regs->eflags);
+ kdb_printf("\n");
+ display_gdtr();
+ display_idtr();
+ display_ldtr();
+ kdb_printf("\n");
+ display_cr0();
+ display_cr3();
+ display_cr4();
+ kdb_printf("\n");
+ display_dr();
+ return 0;
+}
+
+static int __init kdbm_x86_init(void)
+{
+ kdb_register("rdv", kdb_rdv, NULL, "Display registers in verbose mode", 0);
+ kdb_register_repeat("gdt", kdb_gdt, "<sel> [<count>]", "Display GDT", 0, KDB_REPEAT_NO_ARGS);
+ kdb_register_repeat("idt", kdb_idt, "<int> [<count>]", "Display IDT", 0, KDB_REPEAT_NO_ARGS);
+ kdb_register_repeat("ldt", kdb_ldt, "<sel> [<count>]", "Display LDT", 0, KDB_REPEAT_NO_ARGS);
+ kdb_register_repeat("ptex", kdb_pte, "<addr> [<count>]", "Display pagetables", 0, KDB_REPEAT_NO_ARGS);
+ kdb_register_repeat("ldtp", kdb_ldt, "<sel> [<count>]", "Display Process LDT", 0, KDB_REPEAT_NO_ARGS);
+ return 0;
+}
+
+static void __exit kdbm_x86_exit(void)
+{
+ kdb_unregister("rdv");
+ kdb_unregister("gdt");
+ kdb_unregister("ldt");
+ kdb_unregister("idt");
+ kdb_unregister("ptex");
+ kdb_unregister("ldtp");
+}
+
+module_init(kdbm_x86_init)
+module_exit(kdbm_x86_exit)
%diffstat
arch/i386/Kconfig.debug | 78
arch/i386/Makefile | 1
arch/i386/Makefile.cpu | 1
arch/i386/kdb/ChangeLog | 487 +++
arch/i386/kdb/Makefile | 13
arch/i386/kdb/i386-dis.c | 3781 +++++++++++++++++++++++
arch/i386/kdb/kdb_cmds | 17
arch/i386/kdb/kdba_bp.c | 780 ++++
arch/i386/kdb/kdba_bt.c | 379 ++
arch/i386/kdb/kdba_id.c | 255 +
arch/i386/kdb/kdba_io.c | 504 +++
arch/i386/kdb/kdbasupport.c | 1497 +++++++++
arch/i386/kdb/pc_keyb.h | 137
arch/i386/kernel/entry.S | 28
arch/i386/kernel/i8259.c | 4
arch/i386/kernel/io_apic.c | 7
arch/i386/kernel/irq.c | 10
arch/i386/kernel/reboot.c | 12
arch/i386/kernel/smp.c | 32
arch/i386/kernel/smpboot.c | 8
arch/i386/kernel/traps.c | 71
arch/i386/kernel/vmlinux.lds.S | 5
include/asm-i386/ansidecl.h | 313 +
include/asm-i386/bfd.h | 4458 ++++++++++++++++++++++++++++
include/asm-i386/kdb.h | 135
include/asm-i386/kdbprivate.h | 182 +
include/asm-i386/kmap_types.h | 3
include/asm-i386/mach-default/irq_vectors.h | 2
include/asm-i386/ptrace.h | 23
kdb/modules/kdbm_x86.c | 919 +++++
30 files changed, 14139 insertions(+), 3 deletions(-)