[BACK]Return to kdba_bt.c CVS log [TXT][DIR] Up to [Development] / linux-2.6-xfs / arch / x86 / kdb

File: [Development] / linux-2.6-xfs / arch / x86 / kdb / kdba_bt.c (download)

Revision 1.4, Mon Aug 4 17:03:13 2008 UTC (9 years, 2 months ago) by lachlan.longdrop.melbourne.sgi.com
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +5 -11 lines

Merge up to 2.6.26
Merge of 2.6.x-xfs-melb:linux:31804b by kenmcd.

/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (c) 2006, 2007-2008 Silicon Graphics, Inc.  All Rights Reserved.
 *
 * Common code for doing accurate backtraces on i386 and x86_64, including
 * printing the values of arguments.
 */

#include <linux/init.h>
#include <linux/kallsyms.h>
#include <linux/kdb.h>
#include <linux/kdbprivate.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/stringify.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/nmi.h>
#include <asm/asm-offsets.h>
#include <asm/system.h>

#define KDB_DEBUG_BB(fmt, ...)							\
	{if (KDB_DEBUG(BB)) kdb_printf(fmt, ## __VA_ARGS__);}
#define KDB_DEBUG_BB_OFFSET_PRINTF(offset, prefix, suffix)			\
	kdb_printf(prefix "%c0x%x" suffix,					\
		   offset >= 0 ? '+' : '-',					\
		   offset >= 0 ? offset : -offset)
#define KDB_DEBUG_BB_OFFSET(offset, prefix, suffix)				\
	{if (KDB_DEBUG(BB)) KDB_DEBUG_BB_OFFSET_PRINTF(offset, prefix, suffix);}

#define	BB_CHECK(expr, val, ret)						\
({										\
	if (unlikely(expr)) {							\
		kdb_printf("%s, line %d: BB_CHECK(" #expr ") failed "		\
			#val "=%lx\n",						\
			__FUNCTION__, __LINE__, (long)val);			\
		bb_giveup = 1;							\
		return ret;							\
	}									\
})

static int bb_giveup;

/* Use BBRG_Rxx for both i386 and x86_64.  RAX through R15 must be at the end,
 * starting with RAX.  Some of these codes do not reflect actual registers,
 * such codes are special cases when parsing the record of register changes.
 * When updating BBRG_ entries, update bbrg_name as well.
 */

enum bb_reg_code
{
	BBRG_UNDEFINED = 0,	/* Register contents are undefined */
	BBRG_OSP,		/* original stack pointer on entry to function */
	BBRG_RAX,
	BBRG_RBX,
	BBRG_RCX,
	BBRG_RDX,
	BBRG_RDI,
	BBRG_RSI,
	BBRG_RBP,
	BBRG_RSP,
	BBRG_R8,
	BBRG_R9,
	BBRG_R10,
	BBRG_R11,
	BBRG_R12,
	BBRG_R13,
	BBRG_R14,
	BBRG_R15,
};

const static char *bbrg_name[] = {
	[BBRG_UNDEFINED]   = "undefined",
	[BBRG_OSP]         = "osp",
	[BBRG_RAX]         = "rax",
	[BBRG_RBX]         = "rbx",
	[BBRG_RCX]         = "rcx",
	[BBRG_RDX]         = "rdx",
	[BBRG_RDI]         = "rdi",
	[BBRG_RSI]         = "rsi",
	[BBRG_RBP]         = "rbp",
	[BBRG_RSP]         = "rsp",
	[BBRG_R8]          = "r8",
	[BBRG_R9]          = "r9",
	[BBRG_R10]         = "r10",
	[BBRG_R11]         = "r11",
	[BBRG_R12]         = "r12",
	[BBRG_R13]         = "r13",
	[BBRG_R14]         = "r14",
	[BBRG_R15]         = "r15",
};

/* Map a register name to its register code.  This includes the sub-register
 * addressable fields, e.g. parts of rax can be addressed as ax, al, ah, eax.
 * The list is sorted so it can be binary chopped, sort command is:
 *   LANG=C sort -t '"' -k2
 */

struct bb_reg_code_map {
	enum bb_reg_code reg;
	const char *name;
};

const static struct bb_reg_code_map
bb_reg_code_map[] = {
	{ BBRG_RAX, "ah" },
	{ BBRG_RAX, "al" },
	{ BBRG_RAX, "ax" },
	{ BBRG_RBX, "bh" },
	{ BBRG_RBX, "bl" },
	{ BBRG_RBP, "bp" },
	{ BBRG_RBP, "bpl" },
	{ BBRG_RBX, "bx" },
	{ BBRG_RCX, "ch" },
	{ BBRG_RCX, "cl" },
	{ BBRG_RCX, "cx" },
	{ BBRG_RDX, "dh" },
	{ BBRG_RDI, "di" },
	{ BBRG_RDI, "dil" },
	{ BBRG_RDX, "dl" },
	{ BBRG_RDX, "dx" },
	{ BBRG_RAX, "eax" },
	{ BBRG_RBP, "ebp" },
	{ BBRG_RBX, "ebx" },
	{ BBRG_RCX, "ecx" },
	{ BBRG_RDI, "edi" },
	{ BBRG_RDX, "edx" },
	{ BBRG_RSI, "esi" },
	{ BBRG_RSP, "esp" },
	{ BBRG_R10, "r10" },
	{ BBRG_R10, "r10d" },
	{ BBRG_R10, "r10l" },
	{ BBRG_R10, "r10w" },
	{ BBRG_R11, "r11" },
	{ BBRG_R11, "r11d" },
	{ BBRG_R11, "r11l" },
	{ BBRG_R11, "r11w" },
	{ BBRG_R12, "r12" },
	{ BBRG_R12, "r12d" },
	{ BBRG_R12, "r12l" },
	{ BBRG_R12, "r12w" },
	{ BBRG_R13, "r13" },
	{ BBRG_R13, "r13d" },
	{ BBRG_R13, "r13l" },
	{ BBRG_R13, "r13w" },
	{ BBRG_R14, "r14" },
	{ BBRG_R14, "r14d" },
	{ BBRG_R14, "r14l" },
	{ BBRG_R14, "r14w" },
	{ BBRG_R15, "r15" },
	{ BBRG_R15, "r15d" },
	{ BBRG_R15, "r15l" },
	{ BBRG_R15, "r15w" },
	{ BBRG_R8,  "r8" },
	{ BBRG_R8,  "r8d" },
	{ BBRG_R8,  "r8l" },
	{ BBRG_R8,  "r8w" },
	{ BBRG_R9,  "r9" },
	{ BBRG_R9,  "r9d" },
	{ BBRG_R9,  "r9l" },
	{ BBRG_R9,  "r9w" },
	{ BBRG_RAX, "rax" },
	{ BBRG_RBP, "rbp" },
	{ BBRG_RBX, "rbx" },
	{ BBRG_RCX, "rcx" },
	{ BBRG_RDI, "rdi" },
	{ BBRG_RDX, "rdx" },
	{ BBRG_RSI, "rsi" },
	{ BBRG_RSP, "rsp" },
	{ BBRG_RSI, "si" },
	{ BBRG_RSI, "sil" },
	{ BBRG_RSP, "sp" },
	{ BBRG_RSP, "spl" },
};

/* Record register contents in terms of the values that were passed to this
 * function, IOW track which registers contain an input value.  A register's
 * contents can be undefined, it can contain an input register value or it can
 * contain an offset from the original stack pointer.
 *
 * This structure is used to represent the current contents of the integer
 * registers, it is held in an array that is indexed by BBRG_xxx.  The element
 * for BBRG_xxx indicates what input value is currently in BBRG_xxx.  When
 * 'value' is BBRG_OSP then register BBRG_xxx contains a stack pointer,
 * pointing at 'offset' from the original stack pointer on entry to the
 * function.  When 'value' is not BBRG_OSP then element BBRG_xxx contains the
 * original contents of an input register and offset is ignored.
 *
 * An input register 'value' can be stored in more than one register and/or in
 * more than one memory location.
 */

struct bb_reg_contains
{
	enum bb_reg_code value: 8;
	short offset;
};

/* Note: the offsets in struct bb_mem_contains in this code are _NOT_ offsets
 * from OSP, they are offsets from current RSP.  It fits better with the way
 * that struct pt_regs is built, some code pushes extra data before pt_regs so
 * working with OSP relative offsets gets messy.  struct bb_mem_contains
 * entries must be in descending order of RSP offset.
 */

typedef struct { DECLARE_BITMAP(bits, BBRG_R15+1); } bbrgmask_t;
#define BB_SKIP(reg) (1 << (BBRG_ ## reg))
struct bb_mem_contains {
	short offset_address;
	enum bb_reg_code value: 8;
};

/* Transfer of control to a label outside the current function.  If the
 * transfer is to a known common restore path that expects known registers
 * and/or a known memory state (e.g. struct pt_regs) then do a sanity check on
 * the state at this point.
 */

struct bb_name_state {
	const char *name;			/* target function */
	bfd_vma address;			/* Address of target function */
	const char *fname;			/* optional from function name */
	const struct bb_mem_contains *mem;	/* expected memory state */
	const struct bb_reg_contains *regs;	/* expected register state */
	const unsigned short mem_size;		/* ARRAY_SIZE(mem) */
	const unsigned short regs_size;		/* ARRAY_SIZE(regs) */
	const short osp_offset;			/* RSP in regs == OSP+osp_offset */
	const bbrgmask_t skip_mem;		/* Some slots in mem may be undefined */
	const bbrgmask_t skip_regs;		/* Some slots in regs may be undefined */
};

/* NS (NAME_STATE) macros define the register and memory state when we transfer
 * control to or start decoding a special case name.  Use NS when the target
 * label always has the same state.  Use NS_FROM and specify the source label
 * if the target state is slightly different depending on where it is branched
 * from.  This gives better state checking, by isolating the special cases.
 *
 * Note: for the same target label, NS_FROM entries must be followed by a
 * single NS entry.
 */

#define	NS_FROM(iname, ifname, imem, iregs, iskip_mem, iskip_regs, iosp_offset) \
	{ \
		.name = iname, \
		.fname = ifname, \
		.mem = imem, \
		.regs = iregs, \
		.mem_size = ARRAY_SIZE(imem), \
		.regs_size = ARRAY_SIZE(iregs), \
		.skip_mem.bits[0] = iskip_mem, \
		.skip_regs.bits[0] = iskip_regs, \
		.osp_offset = iosp_offset, \
       		.address = 0 \
	}

/* Shorter forms for the common cases */
#define	NS(iname, imem, iregs, iskip_mem, iskip_regs, iosp_offset) \
	  NS_FROM(iname, NULL, imem, iregs, iskip_mem, iskip_regs, iosp_offset)
#define	NS_MEM(iname, imem, iskip_mem) \
	  NS_FROM(iname, NULL, imem, no_regs, iskip_mem, 0, 0)
#define	NS_MEM_FROM(iname, ifname, imem, iskip_mem) \
	  NS_FROM(iname, ifname, imem, no_regs, iskip_mem, 0, 0)
#define	NS_REG(iname, iregs, iskip_regs) \
	  NS_FROM(iname, NULL, no_memory, iregs, 0, iskip_regs, 0)
#define	NS_REG_FROM(iname, ifname, iregs, iskip_regs) \
	  NS_FROM(iname, ifname, no_memory, iregs, 0, iskip_regs, 0)

static void
bb_reg_code_set_value(enum bb_reg_code dst, enum bb_reg_code src);

static const char *bb_mod_name, *bb_func_name;

static int
bb_noret(const char *name)
{
	if (strcmp(name, "panic") == 0 ||
	    strcmp(name, "do_exit") == 0 ||
	    strcmp(name, "do_group_exit") == 0 ||
	    strcmp(name, "complete_and_exit") == 0)
		return 1;
	return 0;
}

/*============================================================================*/
/*                                                                            */
/* Most of the basic block code and data is common to x86_64 and i386.  This  */
/* large ifdef  contains almost all of the differences between the two        */
/* architectures.                                                             */
/*                                                                            */
/* Make sure you update the correct section of this ifdef.                    */
/*                                                                            */
/*============================================================================*/

#ifdef	CONFIG_X86_64

/* Registers that can be used to pass parameters, in the order that parameters
 * are passed.
 */

const static enum bb_reg_code
bb_param_reg[] = {
	BBRG_RDI,
	BBRG_RSI,
	BBRG_RDX,
	BBRG_RCX,
	BBRG_R8,
	BBRG_R9,
};

const static enum bb_reg_code
bb_preserved_reg[] = {
	BBRG_RBX,
	BBRG_RBP,
	BBRG_RSP,
	BBRG_R12,
	BBRG_R13,
	BBRG_R14,
	BBRG_R15,
};

static const struct bb_mem_contains full_pt_regs[] = {
	{ 0x70, BBRG_RDI },
	{ 0x68, BBRG_RSI },
	{ 0x60, BBRG_RDX },
	{ 0x58, BBRG_RCX },
	{ 0x50, BBRG_RAX },
	{ 0x48, BBRG_R8  },
	{ 0x40, BBRG_R9  },
	{ 0x38, BBRG_R10 },
	{ 0x30, BBRG_R11 },
	{ 0x28, BBRG_RBX },
	{ 0x20, BBRG_RBP },
	{ 0x18, BBRG_R12 },
	{ 0x10, BBRG_R13 },
	{ 0x08, BBRG_R14 },
	{ 0x00, BBRG_R15 },
};
static const struct bb_mem_contains partial_pt_regs[] = {
	{ 0x40, BBRG_RDI },
	{ 0x38, BBRG_RSI },
	{ 0x30, BBRG_RDX },
	{ 0x28, BBRG_RCX },
	{ 0x20, BBRG_RAX },
	{ 0x18, BBRG_R8  },
	{ 0x10, BBRG_R9  },
	{ 0x08, BBRG_R10 },
	{ 0x00, BBRG_R11 },
};
static const struct bb_mem_contains partial_pt_regs_plus_1[] = {
	{ 0x48, BBRG_RDI },
	{ 0x40, BBRG_RSI },
	{ 0x38, BBRG_RDX },
	{ 0x30, BBRG_RCX },
	{ 0x28, BBRG_RAX },
	{ 0x20, BBRG_R8  },
	{ 0x18, BBRG_R9  },
	{ 0x10, BBRG_R10 },
	{ 0x08, BBRG_R11 },
};
static const struct bb_mem_contains partial_pt_regs_plus_2[] = {
	{ 0x50, BBRG_RDI },
	{ 0x48, BBRG_RSI },
	{ 0x40, BBRG_RDX },
	{ 0x38, BBRG_RCX },
	{ 0x30, BBRG_RAX },
	{ 0x28, BBRG_R8  },
	{ 0x20, BBRG_R9  },
	{ 0x18, BBRG_R10 },
	{ 0x10, BBRG_R11 },
};
static const struct bb_mem_contains no_memory[] = {
};
/* Hardware has already pushed an error_code on the stack.  Use undefined just
 * to set the initial stack offset.
 */
static const struct bb_mem_contains error_code[] = {
	{ 0x0, BBRG_UNDEFINED },
};
/* error_code plus original rax */
static const struct bb_mem_contains error_code_rax[] = {
	{ 0x8, BBRG_UNDEFINED },
	{ 0x0, BBRG_RAX },
};

static const struct bb_reg_contains all_regs[] = {
	[BBRG_RAX] = { BBRG_RAX, 0 },
	[BBRG_RBX] = { BBRG_RBX, 0 },
	[BBRG_RCX] = { BBRG_RCX, 0 },
	[BBRG_RDX] = { BBRG_RDX, 0 },
	[BBRG_RDI] = { BBRG_RDI, 0 },
	[BBRG_RSI] = { BBRG_RSI, 0 },
	[BBRG_RBP] = { BBRG_RBP, 0 },
	[BBRG_RSP] = { BBRG_OSP, 0 },
	[BBRG_R8 ] = { BBRG_R8,  0 },
	[BBRG_R9 ] = { BBRG_R9,  0 },
	[BBRG_R10] = { BBRG_R10, 0 },
	[BBRG_R11] = { BBRG_R11, 0 },
	[BBRG_R12] = { BBRG_R12, 0 },
	[BBRG_R13] = { BBRG_R13, 0 },
	[BBRG_R14] = { BBRG_R14, 0 },
	[BBRG_R15] = { BBRG_R15, 0 },
};
static const struct bb_reg_contains no_regs[] = {
};

static struct bb_name_state bb_special_cases[] = {

	/* First the cases that pass data only in memory.  We do not check any
	 * register state for these cases.
	 */

	/* Simple cases, no exceptions */
	NS_MEM("ia32_ptregs_common", partial_pt_regs_plus_1, 0),
	NS_MEM("ia32_sysret", partial_pt_regs, 0),
	NS_MEM("int_careful", partial_pt_regs, 0),
	NS_MEM("int_restore_rest", full_pt_regs, 0),
	NS_MEM("int_signal", full_pt_regs, 0),
	NS_MEM("int_very_careful", partial_pt_regs, 0),
	NS_MEM("int_with_check", partial_pt_regs, 0),
#ifdef	CONFIG_TRACE_IRQFLAGS
	NS_MEM("paranoid_exit0", full_pt_regs, 0),
#endif	/* CONFIG_TRACE_IRQFLAGS */
	NS_MEM("paranoid_exit1", full_pt_regs, 0),
	NS_MEM("ptregscall_common", partial_pt_regs_plus_1, 0),
	NS_MEM("restore_norax", partial_pt_regs, 0),
	NS_MEM("restore", partial_pt_regs, 0),
	NS_MEM("ret_from_intr", partial_pt_regs_plus_2, 0),
	NS_MEM("stub32_clone", partial_pt_regs_plus_1, 0),
	NS_MEM("stub32_execve", partial_pt_regs_plus_1, 0),
	NS_MEM("stub32_fork", partial_pt_regs_plus_1, 0),
	NS_MEM("stub32_iopl", partial_pt_regs_plus_1, 0),
	NS_MEM("stub32_rt_sigreturn", partial_pt_regs_plus_1, 0),
	NS_MEM("stub32_rt_sigsuspend", partial_pt_regs_plus_1, 0),
	NS_MEM("stub32_sigaltstack", partial_pt_regs_plus_1, 0),
	NS_MEM("stub32_sigreturn", partial_pt_regs_plus_1, 0),
	NS_MEM("stub32_sigsuspend", partial_pt_regs_plus_1, 0),
	NS_MEM("stub32_vfork", partial_pt_regs_plus_1, 0),
	NS_MEM("stub_clone", partial_pt_regs_plus_1, 0),
	NS_MEM("stub_execve", partial_pt_regs_plus_1, 0),
	NS_MEM("stub_fork", partial_pt_regs_plus_1, 0),
	NS_MEM("stub_iopl", partial_pt_regs_plus_1, 0),
	NS_MEM("stub_rt_sigreturn", partial_pt_regs_plus_1, 0),
	NS_MEM("stub_rt_sigsuspend", partial_pt_regs_plus_1, 0),
	NS_MEM("stub_sigaltstack", partial_pt_regs_plus_1, 0),
	NS_MEM("stub_vfork", partial_pt_regs_plus_1, 0),

	NS_MEM_FROM("ia32_badsys", "ia32_sysenter_target",
		partial_pt_regs,
		/* ia32_sysenter_target uses CLEAR_RREGS to clear R8-R11 on
		 * some paths.  It also stomps on RAX.
		 */
		BB_SKIP(R8) | BB_SKIP(R9) | BB_SKIP(R10) | BB_SKIP(R11) |
		BB_SKIP(RAX)),
	NS_MEM_FROM("ia32_badsys", "ia32_cstar_target",
		partial_pt_regs,
		/* ia32_cstar_target uses CLEAR_RREGS to clear R8-R11 on some
		 * paths.  It also stomps on RAX.  Even more confusing, instead
		 * of storing RCX it stores RBP.  WTF?
		 */
		BB_SKIP(R8) | BB_SKIP(R9) | BB_SKIP(R10) | BB_SKIP(R11) |
		BB_SKIP(RAX) | BB_SKIP(RCX)),
	NS_MEM("ia32_badsys", partial_pt_regs, 0),

	/* Various bits of code branch to int_ret_from_sys_call, with slightly
	 * different missing values in pt_regs.
	 */
	NS_MEM_FROM("int_ret_from_sys_call", "ret_from_fork",
		partial_pt_regs,
		BB_SKIP(R11)),
	NS_MEM_FROM("int_ret_from_sys_call", "stub_execve",
		partial_pt_regs,
		BB_SKIP(RAX) | BB_SKIP(RCX)),
	NS_MEM_FROM("int_ret_from_sys_call", "stub_rt_sigreturn",
		partial_pt_regs,
		BB_SKIP(RAX) | BB_SKIP(RCX)),
	NS_MEM_FROM("int_ret_from_sys_call", "kernel_execve",
		partial_pt_regs,
		BB_SKIP(RAX)),
	NS_MEM_FROM("int_ret_from_sys_call", "ia32_syscall",
		partial_pt_regs,
		/* ia32_syscall only saves RDI through RCX. */
		BB_SKIP(R8) | BB_SKIP(R9) | BB_SKIP(R10) | BB_SKIP(R11) |
		BB_SKIP(RAX)),
	NS_MEM_FROM("int_ret_from_sys_call", "ia32_sysenter_target",
		partial_pt_regs,
		/* ia32_sysenter_target uses CLEAR_RREGS to clear R8-R11 on
		* some paths.  It also stomps on RAX.
		*/
		BB_SKIP(R8) | BB_SKIP(R9) | BB_SKIP(R10) | BB_SKIP(R11) |
		BB_SKIP(RAX)),
	NS_MEM_FROM("int_ret_from_sys_call", "ia32_cstar_target",
		partial_pt_regs,
		/* ia32_cstar_target uses CLEAR_RREGS to clear R8-R11 on some
		 * paths.  It also stomps on RAX.  Even more confusing, instead
		 * of storing RCX it stores RBP.  WTF?
		 */
		BB_SKIP(R8) | BB_SKIP(R9) | BB_SKIP(R10) | BB_SKIP(R11) |
		BB_SKIP(RAX) | BB_SKIP(RCX)),
	NS_MEM("int_ret_from_sys_call", partial_pt_regs, 0),

#ifdef	CONFIG_PREEMPT
	NS_MEM("retint_kernel", partial_pt_regs, BB_SKIP(RAX)),
#endif	/* CONFIG_PREEMPT */

	NS_MEM("retint_careful", partial_pt_regs, BB_SKIP(RAX)),

	/* Horrible hack: For a brand new x86_64 task, switch_to() branches to
	 * ret_from_fork with a totally different stack state from all the
	 * other tasks that come out of switch_to().  This non-standard state
	 * cannot be represented so just ignore the branch from switch_to() to
	 * ret_from_fork.  Due to inlining and linker labels, switch_to() can
	 * appear as several different function labels, including schedule,
	 * context_switch and __sched_text_start.
	 */
	NS_MEM_FROM("ret_from_fork", "schedule", no_memory, 0),
	NS_MEM_FROM("ret_from_fork", "__sched_text_start", no_memory, 0),
	NS_MEM_FROM("ret_from_fork", "context_switch", no_memory, 0),
	NS_MEM("ret_from_fork", full_pt_regs, 0),


	NS_MEM_FROM("ret_from_sys_call", "ret_from_fork",
		partial_pt_regs,
		BB_SKIP(R11)),
	NS_MEM("ret_from_sys_call", partial_pt_regs, 0),

	NS_MEM("retint_restore_args",
		partial_pt_regs,
		BB_SKIP(RAX) | BB_SKIP(RCX)),

	NS_MEM("retint_swapgs",
		partial_pt_regs,
		BB_SKIP(RAX) | BB_SKIP(RCX)),

	/* Now the cases that pass data in registers.  We do not check any
	 * memory state for these cases.
	 */

	NS_REG("bad_put_user",
		all_regs,
		BB_SKIP(RAX) | BB_SKIP(RCX) | BB_SKIP(R8)),

	NS_REG("bad_get_user",
		all_regs,
		BB_SKIP(RAX) | BB_SKIP(RCX) | BB_SKIP(R8)),

	NS_REG("bad_to_user",
		all_regs,
		BB_SKIP(RAX) | BB_SKIP(RCX)),

	NS_REG("ia32_ptregs_common",
		all_regs,
		0),

	NS_REG("copy_user_generic_unrolled",
		all_regs,
		BB_SKIP(RAX) | BB_SKIP(RCX)),

	NS_REG("copy_user_generic_string",
		all_regs,
		BB_SKIP(RAX) | BB_SKIP(RCX)),

	NS_REG("irq_return",
		all_regs,
		0),

	/* Finally the cases that pass data in both registers and memory.
	 */

	NS("invalid_TSS", error_code, all_regs, 0, 0, 0),
	NS("segment_not_present", error_code, all_regs, 0, 0, 0),
	NS("alignment_check", error_code, all_regs, 0, 0, 0),
	NS("page_fault", error_code, all_regs, 0, 0, 0),
	NS("general_protection", error_code, all_regs, 0, 0, 0),
	NS("error_entry", error_code_rax, all_regs, 0, BB_SKIP(RAX), -0x10),
	NS("common_interrupt", error_code, all_regs, 0, 0, -0x8),
};

static const char *bb_spurious[] = {
				/* schedule */
	"thread_return",
				/* ret_from_fork */
	"rff_action",
	"rff_trace",
				/* system_call */
	"ret_from_sys_call",
	"sysret_check",
	"sysret_careful",
	"sysret_signal",
	"badsys",
	"tracesys",
	"int_ret_from_sys_call",
	"int_with_check",
	"int_careful",
	"int_very_careful",
	"int_signal",
	"int_restore_rest",
				/* common_interrupt */
	"ret_from_intr",
	"exit_intr",
	"retint_with_reschedule",
	"retint_check",
	"retint_swapgs",
	"retint_restore_args",
	"restore_args",
	"irq_return",
	"bad_iret",
	"retint_careful",
	"retint_signal",
#ifdef	CONFIG_PREEMPT
	"retint_kernel",
#endif	/* CONFIG_PREEMPT */
				/* .macro paranoidexit */
#ifdef	CONFIG_TRACE_IRQFLAGS
	"paranoid_exit0",
	"paranoid_userspace0",
	"paranoid_restore0",
	"paranoid_swapgs0",
	"paranoid_schedule0",
#endif	/* CONFIG_TRACE_IRQFLAGS */
	"paranoid_exit1",
	"paranoid_swapgs1",
	"paranoid_restore1",
	"paranoid_userspace1",
	"paranoid_schedule1",
				/* error_entry */
	"error_swapgs",
	"error_sti",
	"error_exit",
	"error_kernelspace",
				/* load_gs_index */
	"gs_change",
	"bad_gs",
				/* ia32_sysenter_target */
	"sysenter_do_call",
	"sysenter_tracesys",
				/* ia32_cstar_target */
	"cstar_do_call",
	"cstar_tracesys",
	"ia32_badarg",
				/* ia32_syscall */
	"ia32_do_syscall",
	"ia32_sysret",
	"ia32_tracesys",
	"ia32_badsys",
#ifdef	CONFIG_HIBERNATION
				/* restore_image */
	"loop",
	"done",
#endif	/* CONFIG_HIBERNATION */
#ifdef	CONFIG_KPROBES
				/* jprobe_return */
	"jprobe_return_end",
				/* kretprobe_trampoline_holder */
	"kretprobe_trampoline",
#endif	/* CONFIG_KPROBES */
#ifdef	CONFIG_KEXEC
				/* relocate_kernel */
	"relocate_new_kernel",
#endif	/* CONFIG_KEXEC */
#ifdef	CONFIG_XEN
				/* arch/i386/xen/xen-asm.S */
	"xen_irq_enable_direct_end",
	"xen_irq_disable_direct_end",
	"xen_save_fl_direct_end",
	"xen_restore_fl_direct_end",
	"xen_iret_start_crit",
	"iret_restore_end",
	"xen_iret_end_crit",
	"hyper_iret",
#endif	/* CONFIG_XEN */
};

static const char *bb_hardware_handlers[] = {
	"system_call",
	"common_interrupt",
	"error_entry",
	"debug",
	"nmi",
	"int3",
	"double_fault",
	"stack_segment",
	"machine_check",
	"kdb_call",
};

static int
bb_hardware_pushed_arch(kdb_machreg_t rsp,
			const struct kdb_activation_record *ar)
{
	/* x86_64 interrupt stacks are 16 byte aligned and you must get the
	 * next rsp from stack, it cannot be statically calculated.  Do not
	 * include the word at rsp, it is pushed by hardware but is treated as
	 * a normal software return value.
	 *
	 * When an IST switch occurs (e.g. NMI) then the saved rsp points to
	 * another stack entirely.  Assume that the IST stack is 16 byte
	 * aligned and just return the size of the hardware data on this stack.
	 * The stack unwind code will take care of the stack switch.
	 */
	kdb_machreg_t saved_rsp = *((kdb_machreg_t *)rsp + 3);
	int hardware_pushed = saved_rsp - rsp - KDB_WORD_SIZE;
	if (hardware_pushed < 4 * KDB_WORD_SIZE ||
	    saved_rsp < ar->stack.logical_start ||
	    saved_rsp >= ar->stack.logical_end)
		return 4 * KDB_WORD_SIZE;
	else
		return hardware_pushed;
}

static void
bb_start_block0(void)
{
	bb_reg_code_set_value(BBRG_RAX, BBRG_RAX);
	bb_reg_code_set_value(BBRG_RBX, BBRG_RBX);
	bb_reg_code_set_value(BBRG_RCX, BBRG_RCX);
	bb_reg_code_set_value(BBRG_RDX, BBRG_RDX);
	bb_reg_code_set_value(BBRG_RDI, BBRG_RDI);
	bb_reg_code_set_value(BBRG_RSI, BBRG_RSI);
	bb_reg_code_set_value(BBRG_RBP, BBRG_RBP);
	bb_reg_code_set_value(BBRG_RSP, BBRG_OSP);
	bb_reg_code_set_value(BBRG_R8, BBRG_R8);
	bb_reg_code_set_value(BBRG_R9, BBRG_R9);
	bb_reg_code_set_value(BBRG_R10, BBRG_R10);
	bb_reg_code_set_value(BBRG_R11, BBRG_R11);
	bb_reg_code_set_value(BBRG_R12, BBRG_R12);
	bb_reg_code_set_value(BBRG_R13, BBRG_R13);
	bb_reg_code_set_value(BBRG_R14, BBRG_R14);
	bb_reg_code_set_value(BBRG_R15, BBRG_R15);
}

/* x86_64 does not have a special case for __switch_to */

static void
bb_fixup_switch_to(char *p)
{
}

static int
bb_asmlinkage_arch(void)
{
	return strncmp(bb_func_name, "__down", 6) == 0 ||
	       strncmp(bb_func_name, "__up", 4) == 0 ||
	       strncmp(bb_func_name, "stub_", 5) == 0 ||
	       strcmp(bb_func_name, "ret_from_fork") == 0 ||
	       strcmp(bb_func_name, "ptregscall_common") == 0;
}

#else	/* !CONFIG_X86_64 */

/* Registers that can be used to pass parameters, in the order that parameters
 * are passed.
 */

const static enum bb_reg_code
bb_param_reg[] = {
	BBRG_RAX,
	BBRG_RDX,
	BBRG_RCX,
};

const static enum bb_reg_code
bb_preserved_reg[] = {
	BBRG_RBX,
	BBRG_RBP,
	BBRG_RSP,
	BBRG_RSI,
	BBRG_RDI,
};

static const struct bb_mem_contains full_pt_regs[] = {
	{ 0x18, BBRG_RAX },
	{ 0x14, BBRG_RBP },
	{ 0x10, BBRG_RDI },
	{ 0x0c, BBRG_RSI },
	{ 0x08, BBRG_RDX },
	{ 0x04, BBRG_RCX },
	{ 0x00, BBRG_RBX },
};
static const struct bb_mem_contains no_memory[] = {
};
/* Hardware has already pushed an error_code on the stack.  Use undefined just
 * to set the initial stack offset.
 */
static const struct bb_mem_contains error_code[] = {
	{ 0x0, BBRG_UNDEFINED },
};
/* rbx already pushed */
static const struct bb_mem_contains rbx_pushed[] = {
	{ 0x0, BBRG_RBX },
};
#ifdef	CONFIG_MATH_EMULATION
static const struct bb_mem_contains mem_fpu_reg_round[] = {
	{ 0xc, BBRG_RBP },
	{ 0x8, BBRG_RSI },
	{ 0x4, BBRG_RDI },
	{ 0x0, BBRG_RBX },
};
#endif	/* CONFIG_MATH_EMULATION */

static const struct bb_reg_contains all_regs[] = {
	[BBRG_RAX] = { BBRG_RAX, 0 },
	[BBRG_RBX] = { BBRG_RBX, 0 },
	[BBRG_RCX] = { BBRG_RCX, 0 },
	[BBRG_RDX] = { BBRG_RDX, 0 },
	[BBRG_RDI] = { BBRG_RDI, 0 },
	[BBRG_RSI] = { BBRG_RSI, 0 },
	[BBRG_RBP] = { BBRG_RBP, 0 },
	[BBRG_RSP] = { BBRG_OSP, 0 },
};
static const struct bb_reg_contains no_regs[] = {
};
#ifdef	CONFIG_MATH_EMULATION
static const struct bb_reg_contains reg_fpu_reg_round[] = {
	[BBRG_RBP] = { BBRG_OSP, -0x4 },
	[BBRG_RSP] = { BBRG_OSP, -0x10 },
};
#endif	/* CONFIG_MATH_EMULATION */

static struct bb_name_state bb_special_cases[] = {

	/* First the cases that pass data only in memory.  We do not check any
	 * register state for these cases.
	 */

	/* Simple cases, no exceptions */
	NS_MEM("check_userspace", full_pt_regs, 0),
	NS_MEM("device_not_available_emulate", full_pt_regs, 0),
	NS_MEM("ldt_ss", full_pt_regs, 0),
	NS_MEM("no_singlestep", full_pt_regs, 0),
	NS_MEM("restore_all", full_pt_regs, 0),
	NS_MEM("restore_nocheck", full_pt_regs, 0),
	NS_MEM("restore_nocheck_notrace", full_pt_regs, 0),
	NS_MEM("ret_from_exception", full_pt_regs, 0),
	NS_MEM("ret_from_fork", full_pt_regs, 0),
	NS_MEM("ret_from_intr", full_pt_regs, 0),
	NS_MEM("work_notifysig", full_pt_regs, 0),
	NS_MEM("work_pending", full_pt_regs, 0),

#ifdef	CONFIG_PREEMPT
	NS_MEM("resume_kernel", full_pt_regs, 0),
#endif	/* CONFIG_PREEMPT */

	NS_MEM("common_interrupt", error_code, 0),
	NS_MEM("error_code", error_code, 0),

	NS_MEM("bad_put_user", rbx_pushed, 0),

	NS_MEM_FROM("resume_userspace", "syscall_badsys",
		full_pt_regs, BB_SKIP(RAX)),
	NS_MEM_FROM("resume_userspace", "syscall_fault",
		full_pt_regs, BB_SKIP(RAX)),
	NS_MEM_FROM("resume_userspace", "syscall_trace_entry",
		full_pt_regs, BB_SKIP(RAX)),
	/* Too difficult to trace through the various vm86 functions for now.
	 * They are C functions that start off with some memory state, fiddle
	 * the registers then jmp directly to resume_userspace.  For the
	 * moment, just assume that they are valid and do no checks.
	 */
	NS_FROM("resume_userspace", "do_int",
		no_memory, no_regs, 0, 0, 0),
	NS_FROM("resume_userspace", "do_sys_vm86",
		no_memory, no_regs, 0, 0, 0),
	NS_FROM("resume_userspace", "handle_vm86_fault",
		no_memory, no_regs, 0, 0, 0),
	NS_FROM("resume_userspace", "handle_vm86_trap",
		no_memory, no_regs, 0, 0, 0),
	NS_MEM("resume_userspace", full_pt_regs, 0),

	NS_MEM_FROM("syscall_badsys", "ia32_sysenter_target",
		full_pt_regs, BB_SKIP(RBP)),
	NS_MEM("syscall_badsys", full_pt_regs, 0),

	NS_MEM_FROM("syscall_call", "syscall_trace_entry",
		full_pt_regs, BB_SKIP(RAX)),
	NS_MEM("syscall_call", full_pt_regs, 0),

	NS_MEM_FROM("syscall_exit", "syscall_trace_entry",
		full_pt_regs, BB_SKIP(RAX)),
	NS_MEM("syscall_exit", full_pt_regs, 0),

	NS_MEM_FROM("syscall_exit_work", "ia32_sysenter_target",
		full_pt_regs, BB_SKIP(RAX) | BB_SKIP(RBP)),
	NS_MEM_FROM("syscall_exit_work", "system_call",
		full_pt_regs, BB_SKIP(RAX)),
	NS_MEM("syscall_exit_work", full_pt_regs, 0),

	NS_MEM_FROM("syscall_trace_entry", "ia32_sysenter_target",
		full_pt_regs, BB_SKIP(RBP)),
	NS_MEM_FROM("syscall_trace_entry", "system_call",
		full_pt_regs, BB_SKIP(RAX)),
	NS_MEM("syscall_trace_entry", full_pt_regs, 0),

	/* Now the cases that pass data in registers.  We do not check any
	 * memory state for these cases.
	 */

	NS_REG("syscall_fault", all_regs, 0),

	NS_REG("bad_get_user", all_regs,
		BB_SKIP(RAX) | BB_SKIP(RDX)),

	/* Finally the cases that pass data in both registers and memory.
	*/

	/* This entry is redundant now because bb_fixup_switch_to() hides the
	 * jmp __switch_to case, however the entry is left here as
	 * documentation.
	 *
	 * NS("__switch_to", no_memory, no_regs, 0, 0, 0),
	 */

	NS("iret_exc", no_memory, all_regs, 0, 0, 0x20),

#ifdef	CONFIG_MATH_EMULATION
	NS("fpu_reg_round", mem_fpu_reg_round, reg_fpu_reg_round, 0, 0, 0),
#endif	/* CONFIG_MATH_EMULATION */
};

static const char *bb_spurious[] = {
				/* ret_from_exception */
	"ret_from_intr",
	"check_userspace",
	"resume_userspace",
				/* resume_kernel */
#ifdef	CONFIG_PREEMPT
	"need_resched",
#endif	/* CONFIG_PREEMPT */
				/* ia32_sysenter_target */
	"sysenter_past_esp",
				/* system_call */
	"no_singlestep",
	"syscall_call",
	"syscall_exit",
	"restore_all",
	"restore_nocheck",
	"restore_nocheck_notrace",
	"ldt_ss",
	/* do not include iret_exc, it is in a .fixup section */
				/* work_pending */
	"work_resched",
	"work_notifysig",
#ifdef	CONFIG_VM86
	"work_notifysig_v86",
#endif	/* CONFIG_VM86 */
				/* page_fault */
	"error_code",
				/* device_not_available */
	"device_not_available_emulate",
				/* debug */
	"debug_esp_fix_insn",
	"debug_stack_correct",
				/* nmi */
	"nmi_stack_correct",
	"nmi_stack_fixup",
	"nmi_debug_stack_check",
	"nmi_espfix_stack",
#ifdef	CONFIG_HIBERNATION
				/* restore_image */
	"copy_loop",
	"done",
#endif	/* CONFIG_HIBERNATION */
#ifdef	CONFIG_KPROBES
				/* jprobe_return */
	"jprobe_return_end",
#endif	/* CONFIG_KPROBES */
#ifdef	CONFIG_KEXEC
				/* relocate_kernel */
	"relocate_new_kernel",
#endif	/* CONFIG_KEXEC */
#ifdef	CONFIG_MATH_EMULATION
				/* assorted *.S files in arch/i386/math_emu */
	"Denorm_done",
	"Denorm_shift_more_than_32",
	"Denorm_shift_more_than_63",
	"Denorm_shift_more_than_64",
	"Do_unmasked_underflow",
	"Exp_not_underflow",
	"fpu_Arith_exit",
	"fpu_reg_round",
	"fpu_reg_round_signed_special_exit",
	"fpu_reg_round_special_exit",
	"L_accum_done",
	"L_accum_loaded",
	"L_accum_loop",
	"L_arg1_larger",
	"L_bugged",
	"L_bugged_1",
	"L_bugged_2",
	"L_bugged_3",
	"L_bugged_4",
	"L_bugged_denorm_486",
	"L_bugged_round24",
	"L_bugged_round53",
	"L_bugged_round64",
	"LCheck_24_round_up",
	"LCheck_53_round_up",
	"LCheck_Round_Overflow",
	"LCheck_truncate_24",
	"LCheck_truncate_53",
	"LCheck_truncate_64",
	"LDenormal_adj_exponent",
	"L_deNormalised",
	"LDo_24_round_up",
	"LDo_2nd_32_bits",
	"LDo_2nd_div",
	"LDo_3rd_32_bits",
	"LDo_3rd_div",
	"LDo_53_round_up",
	"LDo_64_round_up",
	"L_done",
	"LDo_truncate_24",
	"LDown_24",
	"LDown_53",
	"LDown_64",
	"L_entry_bugged",
	"L_error_exit",
	"L_exactly_32",
	"L_exception_exit",
	"L_exit",
	"L_exit_nuo_valid",
	"L_exit_nuo_zero",
	"L_exit_valid",
	"L_extent_zero",
	"LFirst_div_done",
	"LFirst_div_not_1",
	"L_Full_Division",
	"LGreater_Half_24",
	"LGreater_Half_53",
	"LGreater_than_1",
	"LLess_than_1",
	"L_Make_denorm",
	"L_more_31_no_low",
	"L_more_63_no_low",
	"L_more_than_31",
	"L_more_than_63",
	"L_more_than_64",
	"L_more_than_65",
	"L_more_than_95",
	"L_must_be_zero",
	"L_n_exit",
	"L_no_adjust",
	"L_no_bit_lost",
	"L_no_overflow",
	"L_no_precision_loss",
	"L_Normalised",
	"L_norm_bugged",
	"L_n_shift_1",
	"L_nuo_shift_1",
	"L_overflow",
	"L_precision_lost_down",
	"L_precision_lost_up",
	"LPrevent_2nd_overflow",
	"LPrevent_3rd_overflow",
	"LPseudoDenormal",
	"L_Re_normalise",
	"LResult_Normalised",
	"L_round",
	"LRound_large",
	"LRound_nearest_24",
	"LRound_nearest_53",
	"LRound_nearest_64",
	"LRound_not_small",
	"LRound_ovfl",
	"LRound_precision",
	"LRound_prep",
	"L_round_the_result",
	"LRound_To_24",
	"LRound_To_53",
	"LRound_To_64",
	"LSecond_div_done",
	"LSecond_div_not_1",
	"L_shift_1",
	"L_shift_32",
	"L_shift_65_nc",
	"L_shift_done",
	"Ls_less_than_32",
	"Ls_more_than_63",
	"Ls_more_than_95",
	"L_Store_significand",
	"L_subtr",
	"LTest_over",
	"LTruncate_53",
	"LTruncate_64",
	"L_underflow",
	"L_underflow_to_zero",
	"LUp_24",
	"LUp_53",
	"LUp_64",
	"L_zero",
	"Normalise_result",
	"Signal_underflow",
	"sqrt_arg_ge_2",
	"sqrt_get_more_precision",
	"sqrt_more_prec_large",
	"sqrt_more_prec_ok",
	"sqrt_more_prec_small",
	"sqrt_near_exact",
	"sqrt_near_exact_large",
	"sqrt_near_exact_ok",
	"sqrt_near_exact_small",
	"sqrt_near_exact_x",
	"sqrt_prelim_no_adjust",
	"sqrt_round_result",
	"sqrt_stage_2_done",
	"sqrt_stage_2_error",
	"sqrt_stage_2_finish",
	"sqrt_stage_2_positive",
	"sqrt_stage_3_error",
	"sqrt_stage_3_finished",
	"sqrt_stage_3_no_error",
	"sqrt_stage_3_positive",
	"Unmasked_underflow",
	"xExp_not_underflow",
#endif	/* CONFIG_MATH_EMULATION */
};

static const char *bb_hardware_handlers[] = {
	"ret_from_exception",
	"system_call",
	"work_pending",
	"syscall_fault",
	"page_fault",
	"coprocessor_error",
	"simd_coprocessor_error",
	"device_not_available",
	"debug",
	"nmi",
	"int3",
	"overflow",
	"bounds",
	"invalid_op",
	"coprocessor_segment_overrun",
	"invalid_TSS",
	"segment_not_present",
	"stack_segment",
	"general_protection",
	"alignment_check",
	"kdb_call",
	"divide_error",
	"machine_check",
	"spurious_interrupt_bug",
};

static int
bb_hardware_pushed_arch(kdb_machreg_t rsp,
			const struct kdb_activation_record *ar)
{
	return (2 * KDB_WORD_SIZE);
}

static void
bb_start_block0(void)
{
	bb_reg_code_set_value(BBRG_RAX, BBRG_RAX);
	bb_reg_code_set_value(BBRG_RBX, BBRG_RBX);
	bb_reg_code_set_value(BBRG_RCX, BBRG_RCX);
	bb_reg_code_set_value(BBRG_RDX, BBRG_RDX);
	bb_reg_code_set_value(BBRG_RDI, BBRG_RDI);
	bb_reg_code_set_value(BBRG_RSI, BBRG_RSI);
	bb_reg_code_set_value(BBRG_RBP, BBRG_RBP);
	bb_reg_code_set_value(BBRG_RSP, BBRG_OSP);
}

/* The i386 code that switches stack in a context switch is an extremely
 * special case.  It saves the rip pointing to a label that is not otherwise
 * referenced, saves the current rsp then pushes a word.  The magic code that
 * resumes the new task picks up the saved rip and rsp, effectively referencing
 * a label that otherwise is not used and ignoring the pushed word.
 *
 * The simplest way to handle this very strange case is to recognise jmp
 * address <__switch_to> and treat it as a popfl instruction.  This avoids
 * terminating the block on this jmp and removes one word from the stack state,
 * which is the end effect of all the magic code.
 *
 * Called with the instruction line, starting after the first ':'.
 */

static void
bb_fixup_switch_to(char *p)
{
	char *p1 = p;
	p += strspn(p, " \t");		/* start of instruction */
	if (strncmp(p, "jmp", 3))
		return;
	p += strcspn(p, " \t");		/* end of instruction */
	p += strspn(p, " \t");		/* start of address */
	p += strcspn(p, " \t");		/* end of address */
	p += strspn(p, " \t");		/* start of comment */
	if (strcmp(p, "<__switch_to>") == 0)
		strcpy(p1, "popfl");
}

static int
bb_asmlinkage_arch(void)
{
	return strcmp(bb_func_name, "ret_from_exception") == 0 ||
	       strcmp(bb_func_name, "syscall_trace_entry") == 0;
}

#endif	/* CONFIG_X86_64 */


/*============================================================================*/
/*                                                                            */
/* Common code and data.                                                      */
/*                                                                            */
/*============================================================================*/


/* Tracking registers by decoding the instructions is quite a bit harder than
 * doing the same tracking using compiler generated information.  Register
 * contents can remain in the same register, they can be copied to other
 * registers, they can be stored on stack or they can be modified/overwritten.
 * At any one time, there are 0 or more copies of the original value that was
 * supplied in each register on input to the current function.  If a register
 * exists in multiple places, one copy of that register is the master version,
 * the others are temporary copies which may or may not be destroyed before the
 * end of the function.
 *
 * The compiler knows which copy of a register is the master and which are
 * temporary copies, which makes it relatively easy to track register contents
 * as they are saved and restored.  Without that compiler based knowledge, this
 * code has to track _every_ possible copy of each register, simply because we
 * do not know which is the master copy and which are temporary copies which
 * may be destroyed later.
 *
 * It gets worse: registers that contain parameters can be copied to other
 * registers which are then saved on stack in a lower level function.  Also the
 * stack pointer may be held in multiple registers (typically RSP and RBP)
 * which contain different offsets from the base of the stack on entry to this
 * function.  All of which means that we have to track _all_ register
 * movements, or at least as much as possible.
 *
 * Start with the basic block that contains the start of the function, by
 * definition all registers contain their initial value.  Track each
 * instruction's effect on register contents, this includes reading from a
 * parameter register before any write to that register, IOW the register
 * really does contain a parameter.  The register state is represented by a
 * dynamically sized array with each entry containing :-
 *
 *   Register name
 *   Location it is copied to (another register or stack + offset)
 *
 * Besides the register tracking array, we track which parameter registers are
 * read before being written, to determine how many parameters are passed in
 * registers.  We also track which registers contain stack pointers, including
 * their offset from the original stack pointer on entry to the function.
 *
 * At each exit from the current basic block (via JMP instruction or drop
 * through), the register state is cloned to form the state on input to the
 * target basic block and the target is marked for processing using this state.
 * When there are multiple ways to enter a basic block (e.g. several JMP
 * instructions referencing the same target) then there will be multiple sets
 * of register state to form the "input" for that basic block, there is no
 * guarantee that all paths to that block will have the same register state.
 *
 * As each target block is processed, all the known sets of register state are
 * merged to form a suitable subset of the state which agrees with all the
 * inputs.  The most common case is where one path to this block copies a
 * register to another register but another path does not, therefore the copy
 * is only a temporary and should not be propogated into this block.
 *
 * If the target block already has an input state from the current transfer
 * point and the new input state is identical to the previous input state then
 * we have reached a steady state for the arc from the current location to the
 * target block.  Therefore there is no need to process the target block again.
 *
 * The steps of "process a block, create state for target block(s), pick a new
 * target block, merge state for target block, process target block" will
 * continue until all the state changes have propogated all the way down the
 * basic block tree, including round any cycles in the tree.  The merge step
 * only deletes tracking entries from the input state(s), it never adds a
 * tracking entry.  Therefore the overall algorithm is guaranteed to converge
 * to a steady state, the worst possible case is that every tracking entry into
 * a block is deleted, which will result in an empty output state.
 *
 * As each instruction is decoded, it is checked to see if this is the point at
 * which execution left this function.  This can be a call to another function
 * (actually the return address to this function) or is the instruction which
 * was about to be executed when an interrupt occurred (including an oops).
 * Save the register state at this point.
 *
 * We always know what the registers contain when execution left this function.
 * For an interrupt, the registers are in struct pt_regs.  For a call to
 * another function, we have already deduced the register state on entry to the
 * other function by unwinding to the start of that function.  Given the
 * register state on exit from this function plus the known register contents
 * on entry to the next function, we can determine the stack pointer value on
 * input to this function.  That in turn lets us calculate the address of input
 * registers that have been stored on stack, giving us the input parameters.
 * Finally the stack pointer gives us the return address which is the exit
 * point from the calling function, repeat the unwind process on that function.
 *
 * The data that tracks which registers contain input parameters is function
 * global, not local to any basic block.  To determine which input registers
 * contain parameters, we have to decode the entire function.  Otherwise an
 * exit early in the function might not have read any parameters yet.
 */

/* Record memory contents in terms of the values that were passed to this
 * function, IOW track which memory locations contain an input value.  A memory
 * location's contents can be undefined, it can contain an input register value
 * or it can contain an offset from the original stack pointer.
 *
 * This structure is used to record register contents that have been stored in
 * memory.  Location (BBRG_OSP + 'offset_address') contains the input value
 * from register 'value'.  When 'value' is BBRG_OSP then offset_value contains
 * the offset from the original stack pointer that was stored in this memory
 * location.  When 'value' is not BBRG_OSP then the memory location contains
 * the original contents of an input register and offset_value is ignored.
 *
 * An input register 'value' can be stored in more than one register and/or in
 * more than one memory location.
 */

struct bb_memory_contains
{
	short offset_address;
	enum bb_reg_code value: 8;
	short offset_value;
};

/* Track the register state in each basic block. */

struct bb_reg_state
{
	/* Indexed by register value 'reg - BBRG_RAX' */
	struct bb_reg_contains contains[KDB_INT_REGISTERS];
	int ref_count;
	int mem_count;
	/* dynamic size for memory locations, see mem_count */
	struct bb_memory_contains memory[0];
};

static struct bb_reg_state *bb_reg_state, *bb_exit_state;
static int bb_reg_state_max, bb_reg_params, bb_memory_params;

struct bb_actual
{
	bfd_vma value;
	int valid;
};

/* Contains the actual hex value of a register, plus a valid bit.  Indexed by
 * register value 'reg - BBRG_RAX'
 */
static struct bb_actual bb_actual[KDB_INT_REGISTERS];

static bfd_vma bb_func_start, bb_func_end;
static bfd_vma bb_common_interrupt, bb_error_entry, bb_ret_from_intr,
	       bb_thread_return, bb_sync_regs, bb_save_v86_state,
	       bb__sched_text_start, bb__sched_text_end;

/* Record jmp instructions, both conditional and unconditional.  These form the
 * arcs between the basic blocks.  This is also used to record the state when
 * one block drops through into the next.
 *
 * A bb can have multiple associated bb_jmp entries, one for each jcc
 * instruction plus at most one bb_jmp for the drop through case.  If a bb
 * drops through to the next bb then the drop through bb_jmp entry will be the
 * last entry in the set of bb_jmp's that are associated with the bb.  This is
 * enforced by the fact that jcc entries are added during the disassembly phase
 * of pass 1, the drop through entries are added near the end of pass 1.
 *
 * At address 'from' in this block, we have a jump to address 'to'.  The
 * register state at 'from' is copied to the target block.
 */

struct bb_jmp
{
	bfd_vma from;
	bfd_vma to;
	struct bb_reg_state *state;
	unsigned int drop_through: 1;
};

struct bb
{
	bfd_vma start;
	/* The end address of a basic block is sloppy.  It can be the first
	 * byte of the last instruction in the block or it can be the last byte
	 * of the block.
	 */
	bfd_vma end;
	unsigned int changed: 1;
	unsigned int drop_through: 1;
};

static struct bb **bb_list, *bb_curr;
static int bb_max, bb_count;

static struct bb_jmp *bb_jmp_list;
static int bb_jmp_max, bb_jmp_count;

/* Add a new bb entry to the list.  This does an insert sort. */

static struct bb *
bb_new(bfd_vma order)
{
	int i, j;
	struct bb *bb, *p;
	if (bb_giveup)
		return NULL;
	if (bb_count == bb_max) {
		struct bb **bb_list_new;
		bb_max += 10;
		bb_list_new = debug_kmalloc(bb_max*sizeof(*bb_list_new),
					    GFP_ATOMIC);
		if (!bb_list_new) {
			kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
			bb_giveup = 1;
			return NULL;
		}
		memcpy(bb_list_new, bb_list, bb_count*sizeof(*bb_list));
		debug_kfree(bb_list);
		bb_list = bb_list_new;
	}
	bb = debug_kmalloc(sizeof(*bb), GFP_ATOMIC);
	if (!bb) {
		kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
		bb_giveup = 1;
		return NULL;
	}
	memset(bb, 0, sizeof(*bb));
	for (i = 0; i < bb_count; ++i) {
		p = bb_list[i];
		if ((p->start && p->start > order) ||
		    (p->end && p->end > order))
			break;
	}
	for (j = bb_count-1; j >= i; --j)
		bb_list[j+1] = bb_list[j];
	bb_list[i] = bb;
	++bb_count;
	return bb;
}

/* Add a new bb_jmp entry to the list.  This list is not sorted. */

static struct bb_jmp *
bb_jmp_new(bfd_vma from, bfd_vma to, unsigned int drop_through)
{
	struct bb_jmp *bb_jmp;
	if (bb_giveup)
		return NULL;
	if (bb_jmp_count == bb_jmp_max) {
		struct bb_jmp *bb_jmp_list_new;
		bb_jmp_max += 10;
		bb_jmp_list_new =
			debug_kmalloc(bb_jmp_max*sizeof(*bb_jmp_list_new),
				      GFP_ATOMIC);
		if (!bb_jmp_list_new) {
			kdb_printf("\n\n%s: out of debug_kmalloc\n",
				   __FUNCTION__);
			bb_giveup = 1;
			return NULL;
		}
		memcpy(bb_jmp_list_new, bb_jmp_list,
		       bb_jmp_count*sizeof(*bb_jmp_list));
		debug_kfree(bb_jmp_list);
		bb_jmp_list = bb_jmp_list_new;
	}
	bb_jmp = bb_jmp_list + bb_jmp_count++;
	bb_jmp->from = from;
	bb_jmp->to = to;
	bb_jmp->drop_through = drop_through;
	bb_jmp->state = NULL;
	return bb_jmp;
}

static void
bb_delete(int i)
{
	struct bb *bb = bb_list[i];
	memcpy(bb_list+i, bb_list+i+1, (bb_count-i-1)*sizeof(*bb_list));
	bb_list[--bb_count] = NULL;
	debug_kfree(bb);
}

static struct bb *
bb_add(bfd_vma start, bfd_vma end)
{
	int i;
	struct bb *bb;
	/* Ignore basic blocks whose start address is outside the current
	 * function.  These occur for call instructions and for tail recursion.
	 */
	if (start &&
	    (start < bb_func_start || start >= bb_func_end))
		       return NULL;
	for (i = 0; i < bb_count; ++i) {
		bb = bb_list[i];
		if ((start && bb->start == start) ||
		    (end && bb->end == end))
			return bb;
	}
	bb = bb_new(start ? start : end);
	if (bb) {
		bb->start = start;
		bb->end = end;
	}
	return bb;
}

static struct bb_jmp *
bb_jmp_add(bfd_vma from, bfd_vma to, unsigned int drop_through)
{
	int i;
	struct bb_jmp *bb_jmp;
	for (i = 0, bb_jmp = bb_jmp_list; i < bb_jmp_count; ++i, ++bb_jmp) {
		if (bb_jmp->from == from &&
		    bb_jmp->to == to &&
		    bb_jmp->drop_through == drop_through)
			return bb_jmp;
	}
	bb_jmp = bb_jmp_new(from, to, drop_through);
	return bb_jmp;
}

static unsigned long bb_curr_addr, bb_exit_addr;
static char bb_buffer[256];	/* A bit too big to go on stack */

/* Computed jmp uses 'jmp *addr(,%reg,[48])' where 'addr' is the start of a
 * table of addresses that point into the current function.  Run the table and
 * generate bb starts for each target address plus a bb_jmp from this address
 * to the target address.
 *
 * Only called for 'jmp' instructions, with the pointer starting at 'jmp'.
 */

static void
bb_pass1_computed_jmp(char *p)
{
	unsigned long table, scale;
	kdb_machreg_t addr;
	struct bb* bb;
	p += strcspn(p, " \t");		/* end of instruction */
	p += strspn(p, " \t");		/* start of address */
	if (*p++ != '*')
		return;
	table = simple_strtoul(p, &p, 0);
	if (strncmp(p, "(,%", 3) != 0)
		return;
	p += 3;
	p += strcspn(p, ",");		/* end of reg */
	if (*p++ != ',')
		return;
	scale = simple_strtoul(p, &p, 0);
	if (scale != KDB_WORD_SIZE || strcmp(p, ")"))
		return;
	while (!bb_giveup) {
		if (kdb_getword(&addr, table, sizeof(addr)))
			return;
		if (addr < bb_func_start || addr >= bb_func_end)
			return;
		bb = bb_add(addr, 0);
		if (bb)
			bb_jmp_add(bb_curr_addr, addr, 0);
		table += KDB_WORD_SIZE;
	}
}

/* Pass 1, identify the start and end of each basic block */

static int
bb_dis_pass1(PTR file, const char *fmt, ...)
{
	int l = strlen(bb_buffer);
	char *p;
	va_list ap;
	va_start(ap, fmt);
	vsnprintf(bb_buffer + l, sizeof(bb_buffer) - l, fmt, ap);
	va_end(ap);
	if ((p = strchr(bb_buffer, '\n'))) {
		*p = '\0';
		/* ret[q], iret[q], sysexit, sysret, ud2a or jmp[q] end a
		 * block.  As does a call to a function marked noret.
		 */
		p = bb_buffer;
		p += strcspn(p, ":");
		if (*p++ == ':') {
			bb_fixup_switch_to(p);
			p += strspn(p, " \t");	/* start of instruction */
			if (strncmp(p, "ret", 3) == 0 ||
			    strncmp(p, "iret", 4) == 0 ||
			    strncmp(p, "sysexit", 7) == 0 ||
			    strncmp(p, "sysret", 6) == 0 ||
			    strncmp(p, "ud2a", 4) == 0 ||
			    strncmp(p, "jmp", 3) == 0) {
				if (strncmp(p, "jmp", 3) == 0)
					bb_pass1_computed_jmp(p);
				bb_add(0, bb_curr_addr);
			};
			if (strncmp(p, "call", 4) == 0) {
				strsep(&p, " \t");	/* end of opcode */
				if (p)
					p += strspn(p, " \t");	/* operand(s) */
				if (p && strchr(p, '<')) {
					p = strchr(p, '<') + 1;
					*strchr(p, '>') = '\0';
					if (bb_noret(p))
						bb_add(0, bb_curr_addr);
				}
			};
		}
		bb_buffer[0] = '\0';
	}
	return 0;
}

static void
bb_printaddr_pass1(bfd_vma addr, disassemble_info *dip)
{
	kdb_symtab_t symtab;
	unsigned int offset;
	struct bb* bb;
	/* disasm only calls the printaddr routine for the target of jmp, loop
	 * or call instructions, i.e. the start of a basic block.  call is
	 * ignored by bb_add because the target address is outside the current
	 * function.
	 */
	dip->fprintf_func(dip->stream, "0x%lx", addr);
	kdbnearsym(addr, &symtab);
	if (symtab.sym_name) {
		dip->fprintf_func(dip->stream, " <%s", symtab.sym_name);
		if ((offset = addr - symtab.sym_start))
			dip->fprintf_func(dip->stream, "+0x%x", offset);
		dip->fprintf_func(dip->stream, ">");
	}
	bb = bb_add(addr, 0);
	if (bb)
		bb_jmp_add(bb_curr_addr, addr, 0);
}

static void
bb_pass1(void)
{
	int i;
	unsigned long addr;
	struct bb *bb;
	struct bb_jmp *bb_jmp;

	if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
		kdb_printf("%s: func_name %s func_start " kdb_bfd_vma_fmt0
			   " func_end " kdb_bfd_vma_fmt0 "\n",
			   __FUNCTION__,
			   bb_func_name,
			   bb_func_start,
			   bb_func_end);
	kdb_di.fprintf_func = bb_dis_pass1;
	kdb_di.print_address_func = bb_printaddr_pass1;

	bb_add(bb_func_start, 0);
	for (bb_curr_addr = bb_func_start;
	     bb_curr_addr < bb_func_end;
	     ++bb_curr_addr) {
		unsigned char c;
		if (kdb_getarea(c, bb_curr_addr)) {
			kdb_printf("%s: unreadable function code at ",
				   __FUNCTION__);
			kdb_symbol_print(bb_curr_addr, NULL, KDB_SP_DEFAULT);
			kdb_printf(", giving up\n");
			bb_giveup = 1;
			return;
		}
	}
	for (addr = bb_func_start; addr < bb_func_end; ) {
		bb_curr_addr = addr;
		addr += kdba_id_printinsn(addr, &kdb_di);
		kdb_di.fprintf_func(NULL, "\n");
	}
	if (bb_giveup)
		goto out;

	/* Special case: a block consisting of a single instruction which is
	 * both the target of a jmp and is also an ending instruction, so we
	 * add two blocks using the same address, one as a start and one as an
	 * end, in no guaranteed order.  The end must be ordered after the
	 * start.
	 */
	for (i = 0; i < bb_count-1; ++i) {
		struct bb *bb1 = bb_list[i], *bb2 = bb_list[i+1];
		if (bb1->end && bb1->end == bb2->start) {
			bb = bb_list[i+1];
			bb_list[i+1] = bb_list[i];
			bb_list[i] = bb;
		}
	}

	/* Some bb have a start address, some have an end address.  Collapse
	 * them into entries that have both start and end addresses.  The first
	 * entry is guaranteed to have a start address.
	 */
	for (i = 0; i < bb_count-1; ++i) {
		struct bb *bb1 = bb_list[i], *bb2 = bb_list[i+1];
		if (bb1->end)
			continue;
		if (bb2->start) {
			bb1->end = bb2->start - 1;
			bb1->drop_through = 1;
			bb_jmp_add(bb1->end, bb2->start, 1);
		} else {
			bb1->end = bb2->end;
			bb_delete(i+1);
		}
	}
	bb = bb_list[bb_count-1];
	if (!bb->end)
		bb->end = bb_func_end - 1;

	/* It would be nice to check that all bb have a valid start and end
	 * address but there is just too much garbage code in the kernel to do
	 * that check.  Aligned functions in assembler code mean that there is
	 * space between the end of one function and the start of the next and
	 * that space contains previous code from the assembler's buffers.  It
	 * looks like dead code with nothing that branches to it, so no start
	 * address.  do_sys_vm86() ends with 'jmp resume_userspace' which the C
	 * compiler does not know about so gcc appends the normal exit code,
	 * again nothing branches to this dangling code.
	 *
	 * The best we can do is delete bb entries with no start address.
	 */
	for (i = 0; i < bb_count; ++i) {
		struct bb *bb = bb_list[i];
		if (!bb->start)
			bb_delete(i--);
	}
	for (i = 0; i < bb_count; ++i) {
		struct bb *bb = bb_list[i];
		if (!bb->end) {
			kdb_printf("%s: incomplete bb state\n", __FUNCTION__);
			bb_giveup = 1;
			goto debug;
		}
	}

out:
	if (!KDB_DEBUG(BB))
		return;
debug:
	kdb_printf("%s: end\n", __FUNCTION__);
	for (i = 0; i < bb_count; ++i) {
		bb = bb_list[i];
		kdb_printf("  bb[%d] start "
			   kdb_bfd_vma_fmt0
			   " end " kdb_bfd_vma_fmt0
			   " drop_through %d",
			   i, bb->start, bb->end, bb->drop_through);
		kdb_printf("\n");
	}
	for (i = 0; i < bb_jmp_count; ++i) {
		bb_jmp = bb_jmp_list + i;
		kdb_printf("  bb_jmp[%d] from "
			   kdb_bfd_vma_fmt0
			   " to " kdb_bfd_vma_fmt0
			   " drop_through %d\n",
			   i, bb_jmp->from, bb_jmp->to, bb_jmp->drop_through);
	}
}

/* Pass 2, record register changes in each basic block */

/* For each opcode that we care about, indicate how it uses its operands.  Most
 * opcodes can be handled generically because they completely specify their
 * operands in the instruction, however many opcodes have side effects such as
 * reading or writing rax or updating rsp.  Instructions that change registers
 * that are not listed in the operands must be handled as special cases.  In
 * addition, instructions that copy registers while preserving their contents
 * (push, pop, mov) or change the contents in a well defined way (add with an
 * immediate, lea) must be handled as special cases in order to track the
 * register contents.
 *
 * The tables below only list opcodes that are actually used in the Linux
 * kernel, so they omit most of the floating point and all of the SSE type
 * instructions.  The operand usage entries only cater for accesses to memory
 * and to the integer registers, accesses to floating point registers and flags
 * are not relevant for kernel backtraces.
 */

enum bb_operand_usage {
	BBOU_UNKNOWN = 0,
		/* generic entries.  because xchg can do any combinations of
		 * read src, write src, read dst and  write dst we need to
		 * define all 16 possibilities.  These are ordered by rs = 1,
		 * rd = 2, ws = 4, wd = 8, bb_usage_x*() functions rely on this
		 * order.
		 */
	BBOU_RS = 1,	/* read src */		/*  1 */
	BBOU_RD,	/* read dst */		/*  2 */
	BBOU_RSRD,				/*  3 */
	BBOU_WS,	/* write src */		/*  4 */
	BBOU_RSWS,				/*  5 */
	BBOU_RDWS,				/*  6 */
	BBOU_RSRDWS,				/*  7 */
	BBOU_WD,	/* write dst */		/*  8 */
	BBOU_RSWD,				/*  9 */
	BBOU_RDWD,				/* 10 */
	BBOU_RSRDWD,				/* 11 */
	BBOU_WSWD,				/* 12 */
	BBOU_RSWSWD,				/* 13 */
	BBOU_RDWSWD,				/* 14 */
	BBOU_RSRDWSWD,				/* 15 */
		/* opcode specific entries */
	BBOU_ADD,
	BBOU_CALL,
	BBOU_CBW,
	BBOU_CMOV,
	BBOU_CMPXCHG,
	BBOU_CMPXCHGD,
	BBOU_CPUID,
	BBOU_CWD,
	BBOU_DIV,
	BBOU_IDIV,
	BBOU_IMUL,
	BBOU_IRET,
	BBOU_JMP,
	BBOU_LAHF,
	BBOU_LEA,
	BBOU_LEAVE,
	BBOU_LODS,
	BBOU_LOOP,
	BBOU_LSS,
	BBOU_MONITOR,
	BBOU_MOV,
	BBOU_MOVS,
	BBOU_MUL,
	BBOU_MWAIT,
	BBOU_NOP,
	BBOU_OUTS,
	BBOU_POP,
	BBOU_POPF,
	BBOU_PUSH,
	BBOU_PUSHF,
	BBOU_RDMSR,
	BBOU_RDTSC,
	BBOU_RET,
	BBOU_SAHF,
	BBOU_SCAS,
	BBOU_SUB,
	BBOU_SYSEXIT,
	BBOU_SYSRET,
	BBOU_WRMSR,
	BBOU_XADD,
	BBOU_XCHG,
	BBOU_XOR,
};

struct bb_opcode_usage {
	int length;
	enum bb_operand_usage usage;
	const char *opcode;
};

/* This table is sorted in alphabetical order of opcode, except that the
 * trailing '"' is treated as a high value.  For example, 'in' sorts after
 * 'inc', 'bt' after 'btc'.  This modified sort order ensures that shorter
 * opcodes come after long ones.  A normal sort would put 'in' first, so 'in'
 * would match both 'inc' and 'in'.  When adding any new entries to this table,
 * be careful to put shorter entries last in their group.
 *
 * To automatically sort the table (in vi)
 *   Mark the first and last opcode line with 'a and 'b
 *   'a
 *   !'bsed -e 's/"}/}}/' | LANG=C sort -t '"' -k2 | sed -e 's/}}/"}/'
 *
 * If a new instruction has to be added, first consider if it affects registers
 * other than those listed in the operands.  Also consider if you want to track
 * the results of issuing the instruction, IOW can you extract useful
 * information by looking in detail at the modified registers or memory.  If
 * either test is true then you need a special case to handle the instruction.
 *
 * The generic entries at the start of enum bb_operand_usage all have one thing
 * in common, if a register or memory location is updated then that location
 * becomes undefined, i.e. we lose track of anything that was previously saved
 * in that location.  So only use a generic BBOU_* value when the result of the
 * instruction cannot be calculated exactly _and_ when all the affected
 * registers are listed in the operands.
 *
 * Examples:
 *
 * 'call' does not generate a known result, but as a side effect of call,
 * several scratch registers become undefined, so it needs a special BBOU_CALL
 * entry.
 *
 * 'adc' generates a variable result, it depends on the carry flag, so 'adc'
 * gets a generic entry.  'add' can generate an exact result (add with
 * immediate on a register that points to the stack) or it can generate an
 * unknown result (add a variable, or add immediate to a register that does not
 * contain a stack pointer) so 'add' has its own BBOU_ADD entry.
 */

static const struct bb_opcode_usage
bb_opcode_usage_all[] = {
	{3, BBOU_RSRDWD,  "adc"},
	{3, BBOU_ADD,     "add"},
	{3, BBOU_RSRDWD,  "and"},
	{3, BBOU_RSWD,    "bsf"},
	{3, BBOU_RSWD,    "bsr"},
	{5, BBOU_RSWS,    "bswap"},
	{3, BBOU_RSRDWD,  "btc"},
	{3, BBOU_RSRDWD,  "btr"},
	{3, BBOU_RSRDWD,  "bts"},
	{2, BBOU_RSRD,    "bt"},
	{4, BBOU_CALL,    "call"},
	{4, BBOU_CBW,     "cbtw"},	/* Intel cbw */
	{3, BBOU_NOP,     "clc"},
	{3, BBOU_NOP,     "cld"},
	{7, BBOU_RS,      "clflush"},
	{4, BBOU_NOP,     "clgi"},
	{3, BBOU_NOP,     "cli"},
	{4, BBOU_CWD,     "cltd"},	/* Intel cdq */
	{4, BBOU_CBW,     "cltq"},	/* Intel cdqe */
	{4, BBOU_NOP,     "clts"},
	{4, BBOU_CMOV,    "cmov"},
	{9, BBOU_CMPXCHGD,"cmpxchg16"},
	{8, BBOU_CMPXCHGD,"cmpxchg8"},
	{7, BBOU_CMPXCHG, "cmpxchg"},
	{3, BBOU_RSRD,    "cmp"},
	{5, BBOU_CPUID,   "cpuid"},
	{4, BBOU_CWD,     "cqto"},	/* Intel cdo */
	{4, BBOU_CWD,     "cwtd"},	/* Intel cwd */
	{4, BBOU_CBW,     "cwtl"},	/* Intel cwde */
	{4, BBOU_NOP,     "data"},	/* alternative ASM_NOP<n> generates data16 on x86_64 */
	{3, BBOU_RSWS,    "dec"},
	{3, BBOU_DIV,     "div"},
	{5, BBOU_RS,      "fdivl"},
	{5, BBOU_NOP,     "finit"},
	{6, BBOU_RS,      "fistpl"},
	{4, BBOU_RS,      "fldl"},
	{4, BBOU_RS,      "fmul"},
	{6, BBOU_NOP,     "fnclex"},
	{6, BBOU_NOP,     "fninit"},
	{6, BBOU_RS,      "fnsave"},
	{7, BBOU_NOP,     "fnsetpm"},
	{6, BBOU_RS,      "frstor"},
	{5, BBOU_WS,      "fstsw"},
	{5, BBOU_RS,      "fsubp"},
	{5, BBOU_NOP,     "fwait"},
	{7, BBOU_RS,      "fxrstor"},
	{6, BBOU_RS,      "fxsave"},
	{3, BBOU_NOP,     "hlt"},
	{4, BBOU_IDIV,    "idiv"},
	{4, BBOU_IMUL,    "imul"},
	{3, BBOU_RSWS,    "inc"},
	{3, BBOU_NOP,     "int"},
	{7, BBOU_RSRD,    "invlpga"},
	{6, BBOU_RS,      "invlpg"},
	{2, BBOU_RSWD,    "in"},
	{4, BBOU_IRET,    "iret"},
	{1, BBOU_JMP,     "j"},
	{4, BBOU_LAHF,    "lahf"},
	{3, BBOU_RSWD,    "lar"},
	{5, BBOU_RS,      "lcall"},
	{5, BBOU_LEAVE,   "leave"},
	{3, BBOU_LEA,     "lea"},
	{6, BBOU_NOP,     "lfence"},
	{4, BBOU_RS,      "lgdt"},
	{4, BBOU_RS,      "lidt"},
	{4, BBOU_RS,      "ljmp"},
	{4, BBOU_RS,      "lldt"},
	{4, BBOU_RS,      "lmsw"},
	{4, BBOU_LODS,    "lods"},
	{4, BBOU_LOOP,    "loop"},
	{4, BBOU_NOP,     "lret"},
	{3, BBOU_RSWD,    "lsl"},
	{3, BBOU_LSS,     "lss"},
	{3, BBOU_RS,      "ltr"},
	{6, BBOU_NOP,     "mfence"},
	{7, BBOU_MONITOR, "monitor"},
	{4, BBOU_MOVS,    "movs"},
	{3, BBOU_MOV,     "mov"},
	{3, BBOU_MUL,     "mul"},
	{5, BBOU_MWAIT,   "mwait"},
	{3, BBOU_RSWS,    "neg"},
	{3, BBOU_NOP,     "nop"},
	{3, BBOU_RSWS,    "not"},
	{2, BBOU_RSRDWD,  "or"},
	{4, BBOU_OUTS,    "outs"},
	{3, BBOU_RSRD,    "out"},
	{5, BBOU_NOP,     "pause"},
	{4, BBOU_POPF,    "popf"},
	{3, BBOU_POP,     "pop"},
	{8, BBOU_RS,      "prefetch"},
	{5, BBOU_PUSHF,   "pushf"},
	{4, BBOU_PUSH,    "push"},
	{3, BBOU_RSRDWD,  "rcl"},
	{3, BBOU_RSRDWD,  "rcr"},
	{5, BBOU_RDMSR,   "rdmsr"},
	{5, BBOU_RDMSR,   "rdpmc"},	/* same side effects as rdmsr */
	{5, BBOU_RDTSC,   "rdtsc"},
	{3, BBOU_RET,     "ret"},
	{3, BBOU_RSRDWD,  "rol"},
	{3, BBOU_RSRDWD,  "ror"},
	{4, BBOU_SAHF,    "sahf"},
	{3, BBOU_RSRDWD,  "sar"},
	{3, BBOU_RSRDWD,  "sbb"},
	{4, BBOU_SCAS,    "scas"},
	{3, BBOU_WS,      "set"},
	{6, BBOU_NOP,     "sfence"},
	{4, BBOU_WS,      "sgdt"},
	{3, BBOU_RSRDWD,  "shl"},
	{3, BBOU_RSRDWD,  "shr"},
	{4, BBOU_WS,      "sidt"},
	{4, BBOU_WS,      "sldt"},
	{3, BBOU_NOP,     "stc"},
	{3, BBOU_NOP,     "std"},
	{4, BBOU_NOP,     "stgi"},
	{3, BBOU_NOP,     "sti"},
	{4, BBOU_SCAS,    "stos"},
	{4, BBOU_WS,      "strl"},
	{3, BBOU_WS,      "str"},
	{3, BBOU_SUB,     "sub"},
	{6, BBOU_NOP,     "swapgs"},
	{7, BBOU_SYSEXIT, "sysexit"},
	{6, BBOU_SYSRET,  "sysret"},
	{4, BBOU_NOP,     "test"},
	{4, BBOU_NOP,     "ud2a"},
	{7, BBOU_RS,      "vmclear"},
	{8, BBOU_NOP,     "vmlaunch"},
	{6, BBOU_RS,      "vmload"},
	{7, BBOU_RS,      "vmptrld"},
	{6, BBOU_WD,      "vmread"},	/* vmread src is an encoding, not a register */
	{8, BBOU_NOP,     "vmresume"},
	{5, BBOU_RS,      "vmrun"},
	{6, BBOU_RS,      "vmsave"},
	{7, BBOU_WD,      "vmwrite"},	/* vmwrite src is an encoding, not a register */
	{6, BBOU_NOP,     "wbinvd"},
	{5, BBOU_WRMSR,   "wrmsr"},
	{4, BBOU_XADD,    "xadd"},
	{4, BBOU_XCHG,    "xchg"},
	{3, BBOU_XOR,     "xor"},
       {10, BBOU_WS,      "xstore-rng"},
};

/* To speed up searching, index bb_opcode_usage_all by the first letter of each
 * opcode.
 */
static struct {
	const struct bb_opcode_usage *opcode;
	int size;
} bb_opcode_usage[26];

struct bb_operand {
	char *base;
	char *index;
	char *segment;
	long disp;
	unsigned int scale;
	enum bb_reg_code base_rc;		/* UNDEFINED or RAX through R15 */
	enum bb_reg_code index_rc;		/* UNDEFINED or RAX through R15 */
	unsigned int present		:1;
	unsigned int disp_present	:1;
	unsigned int indirect		:1;	/* must be combined with reg or memory */
	unsigned int immediate		:1;	/* exactly one of these 3 must be set */
	unsigned int reg		:1;
	unsigned int memory		:1;
};

struct bb_decode {
	char *prefix;
	char *opcode;
	const struct bb_opcode_usage *match;
	struct bb_operand src;
	struct bb_operand dst;
	struct bb_operand dst2;
};

static struct bb_decode bb_decode;

static enum bb_reg_code
bb_reg_map(const char *reg)
{
	int lo, hi, c;
	const struct bb_reg_code_map *p;
	lo = 0;
	hi = ARRAY_SIZE(bb_reg_code_map) - 1;
	while (lo <= hi) {
		int mid = (hi + lo) / 2;
		p = bb_reg_code_map + mid;
		c = strcmp(p->name, reg+1);
		if (c == 0)
			return p->reg;
		else if (c > 0)
			hi = mid - 1;
		else
			lo = mid + 1;
	}
	return BBRG_UNDEFINED;
}

static void
bb_parse_operand(char *str, struct bb_operand *operand)
{
	char *p = str;
	int sign = 1;
	operand->present = 1;
	/* extract any segment prefix */
	if (p[0] == '%' && p[1] && p[2] == 's' && p[3] == ':') {
		operand->memory = 1;
		operand->segment = p;
		p[3] = '\0';
		p += 4;
	}
	/* extract displacement, base, index, scale */
	if (*p == '*') {
		/* jmp/call *disp(%reg), *%reg or *0xnnn */
		operand->indirect = 1;
		++p;
	}
	if (*p == '-') {
		sign = -1;
		++p;
	}
	if (*p == '$') {
		operand->immediate = 1;
		operand->disp_present = 1;
		operand->disp = simple_strtoul(p+1, &p, 0);
	} else if (isdigit(*p)) {
		operand->memory = 1;
		operand->disp_present = 1;
		operand->disp = simple_strtoul(p, &p, 0) * sign;
	}
	if (*p == '%') {
		operand->reg = 1;
		operand->base = p;
	} else if (*p == '(') {
		operand->memory = 1;
		operand->base = ++p;
		p += strcspn(p, ",)");
		if (p == operand->base)
			operand->base = NULL;
		if (*p == ',') {
			*p = '\0';
			operand->index = ++p;
			p += strcspn(p, ",)");
			if (p == operand->index)
				operand->index = NULL;
		}
		if (*p == ',') {
			*p = '\0';
			operand->scale = simple_strtoul(p+1, &p, 0);
		}
		*p = '\0';
	} else if (*p) {
		kdb_printf("%s: unexpected token '%c' after disp '%s'\n",
			   __FUNCTION__, *p, str);
		bb_giveup = 1;
	}
	if ((operand->immediate + operand->reg + operand->memory != 1) ||
	    (operand->indirect && operand->immediate)) {
		kdb_printf("%s: incorrect decode '%s' N %d I %d R %d M %d\n",
			   __FUNCTION__, str,
			   operand->indirect, operand->immediate, operand->reg,
			   operand->memory);
		bb_giveup = 1;
	}
	if (operand->base)
		operand->base_rc = bb_reg_map(operand->base);
	if (operand->index)
		operand->index_rc = bb_reg_map(operand->index);
}

static void
bb_print_operand(const char *type, const struct bb_operand *operand)
{
	if (!operand->present)
		return;
	kdb_printf("  %s %c%c: ",
		   type,
		   operand->indirect ? 'N' : ' ',
		   operand->immediate ? 'I' :
		     operand->reg ? 'R' :
		     operand->memory ? 'M' :
		     '?'
		   );
	if (operand->segment)
		kdb_printf("%s:", operand->segment);
	if (operand->immediate) {
		kdb_printf("$0x%lx", operand->disp);
	} else if (operand->reg) {
		if (operand->indirect)
			kdb_printf("*");
		kdb_printf("%s", operand->base);
	} else if (operand->memory) {
		if (operand->indirect && (operand->base || operand->index))
			kdb_printf("*");
		if (operand->disp_present) {
			kdb_printf("0x%lx", operand->disp);
		}
		if (operand->base || operand->index || operand->scale) {
			kdb_printf("(");
			if (operand->base)
				kdb_printf("%s", operand->base);
			if (operand->index || operand->scale)
				kdb_printf(",");
			if (operand->index)
				kdb_printf("%s", operand->index);
			if (operand->scale)
				kdb_printf(",%d", operand->scale);
			kdb_printf(")");
		}
	}
	if (operand->base_rc)
		kdb_printf(" base_rc %d (%s)",
			   operand->base_rc, bbrg_name[operand->base_rc]);
	if (operand->index_rc)
		kdb_printf(" index_rc %d (%s)",
			   operand->index_rc,
			   bbrg_name[operand->index_rc]);
	kdb_printf("\n");
}

static void
bb_print_opcode(void)
{
	const struct bb_opcode_usage *o = bb_decode.match;
	kdb_printf("  ");
	if (bb_decode.prefix)
		kdb_printf("%s ", bb_decode.prefix);
	kdb_printf("opcode '%s' matched by '%s', usage %d\n",
		   bb_decode.opcode, o->opcode, o->usage);
}

static int
bb_parse_opcode(void)
{
	int c, i;
	const struct bb_opcode_usage *o;
	static int bb_parse_opcode_error_limit = 5;
	c = bb_decode.opcode[0] - 'a';
	if (c < 0 || c >= ARRAY_SIZE(bb_opcode_usage))
		goto nomatch;
	o = bb_opcode_usage[c].opcode;
	if (!o)
		goto nomatch;
	for (i = 0; i < bb_opcode_usage[c].size; ++i, ++o) {
		if (strncmp(bb_decode.opcode, o->opcode, o->length) == 0) {
			bb_decode.match = o;
			if (KDB_DEBUG(BB))
				bb_print_opcode();
			return 0;
		}
	}
nomatch:
	if (!bb_parse_opcode_error_limit)
		return 1;
	--bb_parse_opcode_error_limit;
	kdb_printf("%s: no match at [%s]%s " kdb_bfd_vma_fmt0 " - '%s'\n",
		   __FUNCTION__,
		   bb_mod_name, bb_func_name, bb_curr_addr,
		   bb_decode.opcode);
	return 1;
}

static bool
bb_is_int_reg(enum bb_reg_code reg)
{
	return reg >= BBRG_RAX && reg < (BBRG_RAX + KDB_INT_REGISTERS);
}

static bool
bb_is_simple_memory(const struct bb_operand *operand)
{
	return operand->memory &&
	       bb_is_int_reg(operand->base_rc) &&
	       !operand->index_rc &&
	       operand->scale == 0 &&
	       !operand->segment;
}

static bool
bb_is_static_disp(const struct bb_operand *operand)
{
	return operand->memory &&
	       !operand->base_rc &&
	       !operand->index_rc &&
	       operand->scale == 0 &&
	       !operand->segment &&
	       !operand->indirect;
}

static enum bb_reg_code
bb_reg_code_value(enum bb_reg_code reg)
{
	BB_CHECK(!bb_is_int_reg(reg), reg, 0);
	return bb_reg_state->contains[reg - BBRG_RAX].value;
}

static short
bb_reg_code_offset(enum bb_reg_code reg)
{
	BB_CHECK(!bb_is_int_reg(reg), reg, 0);
	return bb_reg_state->contains[reg - BBRG_RAX].offset;
}

static void
bb_reg_code_set_value(enum bb_reg_code dst, enum bb_reg_code src)
{
	BB_CHECK(!bb_is_int_reg(dst), dst, );
	bb_reg_state->contains[dst - BBRG_RAX].value = src;
}

static void
bb_reg_code_set_offset(enum bb_reg_code dst, short offset)
{
	BB_CHECK(!bb_is_int_reg(dst), dst, );
	bb_reg_state->contains[dst - BBRG_RAX].offset = offset;
}

static bool
bb_is_osp_defined(enum bb_reg_code reg)
{
	if (bb_is_int_reg(reg))
		return bb_reg_code_value(reg) == BBRG_OSP;
	else
		return 0;
}

static bfd_vma
bb_actual_value(enum bb_reg_code reg)
{
	BB_CHECK(!bb_is_int_reg(reg), reg, 0);
	return bb_actual[reg - BBRG_RAX].value;
}

static int
bb_actual_valid(enum bb_reg_code reg)
{
	BB_CHECK(!bb_is_int_reg(reg), reg, 0);
	return bb_actual[reg - BBRG_RAX].valid;
}

static void
bb_actual_set_value(enum bb_reg_code reg, bfd_vma value)
{
	BB_CHECK(!bb_is_int_reg(reg), reg, );
	bb_actual[reg - BBRG_RAX].value = value;
}

static void
bb_actual_set_valid(enum bb_reg_code reg, int valid)
{
	BB_CHECK(!bb_is_int_reg(reg), reg, );
	bb_actual[reg - BBRG_RAX].valid = valid;
}

/* The scheduler code switches RSP then does PUSH, it is not an error for RSP
 * to be undefined in this area of the code.
 */
static bool
bb_is_scheduler_address(void)
{
	return bb_curr_addr >= bb__sched_text_start &&
	       bb_curr_addr < bb__sched_text_end;
}

static void
bb_reg_read(enum bb_reg_code reg)
{
	int i, r = 0;
	if (!bb_is_int_reg(reg) ||
	    bb_reg_code_value(reg) != reg)
		return;
	for (i = 0;
	     i < min_t(unsigned int, REGPARM, ARRAY_SIZE(bb_param_reg));
	     ++i) {
		if (reg == bb_param_reg[i]) {
			r = i + 1;
			break;
		}
	}
	bb_reg_params = max(bb_reg_params, r);
}

static void
bb_do_reg_state_print(const struct bb_reg_state *s)
{
	int i, offset_address, offset_value;
	const struct bb_memory_contains *c;
	enum bb_reg_code value;
	kdb_printf("  bb_reg_state %p\n", s);
	for (i = 0; i < ARRAY_SIZE(s->contains); ++i) {
		value = s->contains[i].value;
		offset_value = s->contains[i].offset;
		kdb_printf("    %s = %s",
			   bbrg_name[i + BBRG_RAX], bbrg_name[value]);
		if (value == BBRG_OSP)
			KDB_DEBUG_BB_OFFSET_PRINTF(offset_value, "", "");
		kdb_printf("\n");
	}
	for (i = 0, c = s->memory; i < s->mem_count; ++i, ++c) {
		offset_address = c->offset_address;
		value = c->value;
		offset_value = c->offset_value;
		kdb_printf("    slot %d offset_address %c0x%x %s",
			   i,
			   offset_address >= 0 ? '+' : '-',
			   offset_address >= 0 ? offset_address : -offset_address,
			   bbrg_name[value]);
		if (value == BBRG_OSP)
			KDB_DEBUG_BB_OFFSET_PRINTF(offset_value, "", "");
		kdb_printf("\n");
	}
}

static void
bb_reg_state_print(const struct bb_reg_state *s)
{
	if (KDB_DEBUG(BB))
		bb_do_reg_state_print(s);
}

/* Set register 'dst' to contain the value from 'src'.  This includes reading
 * from 'src' and writing to 'dst'.  The offset value is copied iff 'src'
 * contains a stack pointer.
 *
 * Be very careful about the context here.  'dst' and 'src' reflect integer
 * registers by name, _not_ by the value of their contents.  "mov %rax,%rsi"
 * will call this function as bb_reg_set_reg(BBRG_RSI, BBRG_RAX), which
 * reflects what the assembler code is doing.  However we need to track the
 * _values_ in the registers, not their names.  IOW, we really care about "what
 * value does rax contain when it is copied into rsi?", so we can record the
 * fact that we now have two copies of that value, one in rax and one in rsi.
 */

static void
bb_reg_set_reg(enum bb_reg_code dst, enum bb_reg_code src)
{
	enum bb_reg_code src_value = BBRG_UNDEFINED;
	short offset_value = 0;
	KDB_DEBUG_BB("  %s = %s", bbrg_name[dst], bbrg_name[src]);
	if (bb_is_int_reg(src)) {
		bb_reg_read(src);
		src_value = bb_reg_code_value(src);
		KDB_DEBUG_BB(" (%s", bbrg_name[src_value]);
		if (bb_is_osp_defined(src)) {
			offset_value = bb_reg_code_offset(src);
			KDB_DEBUG_BB_OFFSET(offset_value, "", "");
		}
		KDB_DEBUG_BB(")");
	}
	if (bb_is_int_reg(dst)) {
		bb_reg_code_set_value(dst, src_value);
		bb_reg_code_set_offset(dst, offset_value);
	}
	KDB_DEBUG_BB("\n");
}

static void
bb_reg_set_undef(enum bb_reg_code dst)
{
	bb_reg_set_reg(dst, BBRG_UNDEFINED);
}

/* Delete any record of a stored register held in osp + 'offset' */

static void
bb_delete_memory(short offset)
{
	int i;
	struct bb_memory_contains *c;
	for (i = 0, c = bb_reg_state->memory;
	     i < bb_reg_state->mem_count;
	     ++i, ++c) {
		if (c->offset_address == offset &&
		    c->value != BBRG_UNDEFINED) {
			KDB_DEBUG_BB("  delete %s from ",
				     bbrg_name[c->value]);
			KDB_DEBUG_BB_OFFSET(offset, "osp", "");
			KDB_DEBUG_BB(" slot %d\n",
				     (int)(c - bb_reg_state->memory));
			memset(c, BBRG_UNDEFINED, sizeof(*c));
			if (i == bb_reg_state->mem_count - 1)
				--bb_reg_state->mem_count;
		}
	}
}

/* Set memory location *('dst' + 'offset_address') to contain the supplied
 * value and offset.  'dst' is assumed to be a register that contains a stack
 * pointer.
 */

static void
bb_memory_set_reg_value(enum bb_reg_code dst, short offset_address,
			enum bb_reg_code value, short offset_value)
{
	int i;
	struct bb_memory_contains *c, *free = NULL;
	BB_CHECK(!bb_is_osp_defined(dst), dst, );
	KDB_DEBUG_BB("  *(%s", bbrg_name[dst]);
	KDB_DEBUG_BB_OFFSET(offset_address, "", "");
	offset_address += bb_reg_code_offset(dst);
	KDB_DEBUG_BB_OFFSET(offset_address, " osp", ") = ");
	KDB_DEBUG_BB("%s", bbrg_name[value]);
	if (value == BBRG_OSP)
		KDB_DEBUG_BB_OFFSET(offset_value, "", "");
	for (i = 0, c = bb_reg_state->memory;
	     i < bb_reg_state_max;
	     ++i, ++c) {
		if (c->offset_address == offset_address)
			free = c;
		else if (c->value == BBRG_UNDEFINED && !free)
			free = c;
	}
	if (!free) {
		struct bb_reg_state *new, *old = bb_reg_state;
		size_t old_size, new_size;
		int slot;
		old_size = sizeof(*old) + bb_reg_state_max *
				  sizeof(old->memory[0]);
		slot = bb_reg_state_max;
		bb_reg_state_max += 5;
		new_size = sizeof(*new) + bb_reg_state_max *
				  sizeof(new->memory[0]);
		new = debug_kmalloc(new_size, GFP_ATOMIC);
		if (!new) {
			kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
			bb_giveup = 1;
		} else {
			memcpy(new, old, old_size);
			memset((char *)new + old_size, BBRG_UNDEFINED,
			       new_size - old_size);
			bb_reg_state = new;
			debug_kfree(old);
			free = bb_reg_state->memory + slot;
		}
	}
	if (free) {
		int slot = free - bb_reg_state->memory;
		free->offset_address = offset_address;
		free->value = value;
		free->offset_value = offset_value;
		KDB_DEBUG_BB(" slot %d", slot);
		bb_reg_state->mem_count = max(bb_reg_state->mem_count, slot+1);
	}
	KDB_DEBUG_BB("\n");
}

/* Set memory location *('dst' + 'offset') to contain the value from register
 * 'src'.  'dst' is assumed to be a register that contains a stack pointer.
 * This differs from bb_memory_set_reg_value because it takes a src register
 * which contains a value and possibly an offset, bb_memory_set_reg_value is
 * passed the value and offset directly.
 */

static void
bb_memory_set_reg(enum bb_reg_code dst, enum bb_reg_code src,
		  short offset_address)
{
	int offset_value;
	enum bb_reg_code value;
	BB_CHECK(!bb_is_osp_defined(dst), dst, );
	if (!bb_is_int_reg(src))
		return;
	value = bb_reg_code_value(src);
	if (value == BBRG_UNDEFINED) {
		bb_delete_memory(offset_address + bb_reg_code_offset(dst));
		return;
	}
	offset_value = bb_reg_code_offset(src);
	bb_reg_read(src);
	bb_memory_set_reg_value(dst, offset_address, value, offset_value);
}

/* Set register 'dst' to contain the value from memory *('src' + offset_address).
 * 'src' is assumed to be a register that contains a stack pointer.
 */

static void
bb_reg_set_memory(enum bb_reg_code dst, enum bb_reg_code src, short offset_address)
{
	int i, defined = 0;
	struct bb_memory_contains *s;
	BB_CHECK(!bb_is_osp_defined(src), src, );
	KDB_DEBUG_BB("  %s = *(%s",
		     bbrg_name[dst], bbrg_name[src]);
	KDB_DEBUG_BB_OFFSET(offset_address, "", ")");
	offset_address += bb_reg_code_offset(src);
	KDB_DEBUG_BB_OFFSET(offset_address, " (osp", ")");
	for (i = 0, s = bb_reg_state->memory;
	     i < bb_reg_state->mem_count;
	     ++i, ++s) {
		if (s->offset_address == offset_address && bb_is_int_reg(dst)) {
			bb_reg_code_set_value(dst, s->value);
			KDB_DEBUG_BB(" value %s", bbrg_name[s->value]);
			if (s->value == BBRG_OSP) {
				bb_reg_code_set_offset(dst, s->offset_value);
				KDB_DEBUG_BB_OFFSET(s->offset_value, "", "");
			} else {
				bb_reg_code_set_offset(dst, 0);
			}
			defined = 1;
		}
	}
	if (!defined)
		bb_reg_set_reg(dst, BBRG_UNDEFINED);
	else
		KDB_DEBUG_BB("\n");
}

/* A generic read from an operand. */

static void
bb_read_operand(const struct bb_operand *operand)
{
	int m = 0;
	if (operand->base_rc)
		bb_reg_read(operand->base_rc);
	if (operand->index_rc)
		bb_reg_read(operand->index_rc);
	if (bb_is_simple_memory(operand) &&
	    bb_is_osp_defined(operand->base_rc) &&
	    bb_decode.match->usage != BBOU_LEA) {
		m = (bb_reg_code_offset(operand->base_rc) + operand->disp +
		     KDB_WORD_SIZE - 1) / KDB_WORD_SIZE;
		bb_memory_params = max(bb_memory_params, m);
	}
}

/* A generic write to an operand, resulting in an undefined value in that
 * location.  All well defined operands are handled separately, this function
 * only handles the opcodes where the result is undefined.
 */

static void
bb_write_operand(const struct bb_operand *operand)
{
	enum bb_reg_code base_rc = operand->base_rc;
	if (operand->memory) {
		if (base_rc)
			bb_reg_read(base_rc);
		if (operand->index_rc)
			bb_reg_read(operand->index_rc);
	} else if (operand->reg && base_rc) {
		bb_reg_set_undef(base_rc);
	}
	if (bb_is_simple_memory(operand) && bb_is_osp_defined(base_rc)) {
		int offset;
		offset = bb_reg_code_offset(base_rc) + operand->disp;
		offset = ALIGN(offset - KDB_WORD_SIZE + 1, KDB_WORD_SIZE);
		bb_delete_memory(offset);
	}
}

/* Adjust a register that contains a stack pointer */

static void
bb_adjust_osp(enum bb_reg_code reg, int adjust)
{
	int offset = bb_reg_code_offset(reg), old_offset = offset;
	KDB_DEBUG_BB("  %s osp offset ", bbrg_name[reg]);
	KDB_DEBUG_BB_OFFSET(bb_reg_code_offset(reg), "", " -> ");
	offset += adjust;
	bb_reg_code_set_offset(reg, offset);
	KDB_DEBUG_BB_OFFSET(bb_reg_code_offset(reg), "", "\n");
	/* When RSP is adjusted upwards, it invalidates any memory
	 * stored between the old and current stack offsets.
	 */
	if (reg == BBRG_RSP) {
		while (old_offset < bb_reg_code_offset(reg)) {
			bb_delete_memory(old_offset);
			old_offset += KDB_WORD_SIZE;
		}
	}
}

/* The current instruction adjusts a register that contains a stack pointer.
 * Direction is 1 or -1, depending on whether the instruction is add/lea or
 * sub.
 */

static void
bb_adjust_osp_instruction(int direction)
{
	enum bb_reg_code dst_reg = bb_decode.dst.base_rc;
	if (bb_decode.src.immediate ||
	    bb_decode.match->usage == BBOU_LEA /* lea has its own checks */) {
		int adjust = direction * bb_decode.src.disp;
		bb_adjust_osp(dst_reg, adjust);
	} else {
		/* variable stack adjustment, osp offset is not well defined */
		KDB_DEBUG_BB("  %s osp offset ", bbrg_name[dst_reg]);
		KDB_DEBUG_BB_OFFSET(bb_reg_code_offset(dst_reg), "", " -> undefined\n");
		bb_reg_code_set_value(dst_reg, BBRG_UNDEFINED);
		bb_reg_code_set_offset(dst_reg, 0);
	}
}

/* Some instructions using memory have an explicit length suffix (b, w, l, q).
 * The equivalent instructions using a register imply the length from the
 * register name.  Deduce the operand length.
 */

static int
bb_operand_length(const struct bb_operand *operand, char opcode_suffix)
{
	int l = 0;
	switch (opcode_suffix) {
	case 'b':
		l = 8;
		break;
	case 'w':
		l = 16;
		break;
	case 'l':
		l = 32;
		break;
	case 'q':
		l = 64;
		break;
	}
	if (l == 0 && operand->reg) {
		switch (strlen(operand->base)) {
		case 3:
			switch (operand->base[2]) {
			case 'h':
			case 'l':
				l = 8;
				break;
			default:
				l = 16;
				break;
			}
		case 4:
			if (operand->base[1] == 'r')
				l = 64;
			else
				l = 32;
			break;
		}
	}
	return l;
}

static int
bb_reg_state_size(const struct bb_reg_state *state)
{
	return sizeof(*state) +
	       state->mem_count * sizeof(state->memory[0]);
}

/* Canonicalize the current bb_reg_state so it can be compared against
 * previously created states.  Sort the memory entries in descending order of
 * offset_address (stack grows down).  Empty slots are moved to the end of the
 * list and trimmed.
 */

static void
bb_reg_state_canonicalize(void)
{
	int i, order, changed;
	struct bb_memory_contains *p1, *p2, temp;
	do {
		changed = 0;
		for (i = 0, p1 = bb_reg_state->memory;
		     i < bb_reg_state->mem_count-1;
		     ++i, ++p1) {
			p2 = p1 + 1;
			if (p2->value == BBRG_UNDEFINED) {
				order = 0;
			} else if (p1->value == BBRG_UNDEFINED) {
				order = 1;
			} else if (p1->offset_address < p2->offset_address) {
				order = 1;
			} else if (p1->offset_address > p2->offset_address) {
				order = -1;
			} else {
				order = 0;
			}
			if (order > 0) {
				temp = *p2;
				*p2 = *p1;
				*p1 = temp;
				changed = 1;
			}
		}
	} while(changed);
	for (i = 0, p1 = bb_reg_state->memory;
	     i < bb_reg_state_max;
	     ++i, ++p1) {
		if (p1->value != BBRG_UNDEFINED)
			bb_reg_state->mem_count = i + 1;
	}
	bb_reg_state_print(bb_reg_state);
}

static int
bb_special_case(bfd_vma to)
{
	int i, j, rsp_offset, expect_offset, offset, errors = 0, max_errors = 40;
	enum bb_reg_code reg, expect_value, value;
	struct bb_name_state *r;

	for (i = 0, r = bb_special_cases;
	     i < ARRAY_SIZE(bb_special_cases);
	     ++i, ++r) {
		if (to == r->address &&
		    (r->fname == NULL || strcmp(bb_func_name, r->fname) == 0))
			goto match;
	}
	/* Some inline assembler code has jumps to .fixup sections which result
	 * in out of line transfers with undefined state, ignore them.
	 */
	if (strcmp(bb_func_name, "strnlen_user") == 0 ||
	    strcmp(bb_func_name, "copy_from_user") == 0)
		return 1;
	return 0;

match:
	/* Check the running registers match */
	for (reg = BBRG_RAX; reg < r->regs_size; ++reg) {
		expect_value = r->regs[reg].value;
		if (test_bit(expect_value, r->skip_regs.bits)) {
			/* this regs entry is not defined for this label */
			continue;
		}
		if (expect_value == BBRG_UNDEFINED)
			continue;
		expect_offset = r->regs[reg].offset;
		value = bb_reg_code_value(reg);
		offset = bb_reg_code_offset(reg);
		if (expect_value == value &&
		    (value != BBRG_OSP || r->osp_offset == offset))
			continue;
		kdb_printf("%s: Expected %s to contain %s",
			   __FUNCTION__,
			   bbrg_name[reg],
			   bbrg_name[expect_value]);
		if (r->osp_offset)
			KDB_DEBUG_BB_OFFSET_PRINTF(r->osp_offset, "", "");
		kdb_printf(".  It actually contains %s", bbrg_name[value]);
		if (offset)
			KDB_DEBUG_BB_OFFSET_PRINTF(offset, "", "");
		kdb_printf("\n");
		++errors;
		if (max_errors-- == 0)
			goto fail;
	}
	/* Check that any memory data on stack matches */
	i = j = 0;
	while (i < bb_reg_state->mem_count &&
	       j < r->mem_size) {
		expect_value = r->mem[j].value;
		if (test_bit(expect_value, r->skip_mem.bits) ||
		    expect_value == BBRG_UNDEFINED) {
			/* this memory slot is not defined for this label */
			++j;
			continue;
		}
		rsp_offset = bb_reg_state->memory[i].offset_address -
			bb_reg_code_offset(BBRG_RSP);
		if (rsp_offset >
		    r->mem[j].offset_address) {
			/* extra slots in memory are OK */
			++i;
		} else if (rsp_offset <
			   r->mem[j].offset_address) {
			/* Required memory slot is missing */
			kdb_printf("%s: Invalid bb_reg_state.memory, "
			           "missing memory entry[%d] %s\n",
			   __FUNCTION__, j, bbrg_name[expect_value]);
			++errors;
			if (max_errors-- == 0)
				goto fail;
			++j;
		} else {
			if (bb_reg_state->memory[i].offset_value ||
			    bb_reg_state->memory[i].value != expect_value) {
				/* memory slot is present but contains wrong
				 * value.
				 */
				kdb_printf("%s: Invalid bb_reg_state.memory, "
					    "wrong value in slot %d, "
					    "should be %s, it is %s\n",
				   __FUNCTION__, i,
				   bbrg_name[expect_value],
				   bbrg_name[bb_reg_state->memory[i].value]);
				++errors;
				if (max_errors-- == 0)
					goto fail;
			}
			++i;
			++j;
		}
	}
	while (j < r->mem_size) {
		expect_value = r->mem[j].value;
		if (test_bit(expect_value, r->skip_mem.bits) ||
		    expect_value == BBRG_UNDEFINED)
			++j;
		else
			break;
	}
	if (j != r->mem_size) {
		/* Hit end of memory before testing all the pt_reg slots */
		kdb_printf("%s: Invalid bb_reg_state.memory, "
			    "missing trailing entries\n",
		   __FUNCTION__);
		++errors;
		if (max_errors-- == 0)
			goto fail;
	}
	if (errors)
		goto fail;
	return 1;
fail:
	kdb_printf("%s: on transfer to %s\n", __FUNCTION__, r->name);
	bb_giveup = 1;
	return 1;
}

/* Transfer of control to a label outside the current function.  If the
 * transfer is to a known common code path then do a sanity check on the state
 * at this point.
 */

static void
bb_sanity_check(int type)
{
	enum bb_reg_code expect, actual;
	int i, offset, error = 0;

	for (i = 0; i < ARRAY_SIZE(bb_preserved_reg); ++i) {
		expect = bb_preserved_reg[i];
		actual = bb_reg_code_value(expect);
		offset = bb_reg_code_offset(expect);
		if (expect == actual)
			continue;
		/* type == 1 is sysret/sysexit, ignore RSP */
		if (type && expect == BBRG_RSP)
			continue;
		/* type == 1 is sysret/sysexit, ignore RBP for i386 */
		/* We used to have "#ifndef CONFIG_X86_64" for the type=1 RBP
		 * test; however, x86_64 can run ia32 compatible mode and
		 * hit this problem. Perform the following test anyway!
		 */
		if (type && expect == BBRG_RBP)
			continue;
		/* RSP should contain OSP+0.  Except for ptregscall_common and
		 * ia32_ptregs_common, they get a partial pt_regs, fudge the
		 * stack to make it a full pt_regs then reverse the effect on
		 * exit, so the offset is -0x50 on exit.
		 */
		if (expect == BBRG_RSP &&
		    bb_is_osp_defined(expect) &&
		    (offset == 0 ||
		     (offset == -0x50 &&
		      (strcmp(bb_func_name, "ptregscall_common") == 0 ||
		       strcmp(bb_func_name, "ia32_ptregs_common") == 0))))
			continue;
		kdb_printf("%s: Expected %s, got %s",
			   __FUNCTION__,
			   bbrg_name[expect], bbrg_name[actual]);
		if (offset)
			KDB_DEBUG_BB_OFFSET_PRINTF(offset, "", "");
		kdb_printf("\n");
		error = 1;
	}
	BB_CHECK(error, error, );
}

/* Transfer of control.  Follow the arc and save the current state as input to
 * another basic block.
 */

static void
bb_transfer(bfd_vma from, bfd_vma to, unsigned int drop_through)
{
	int i, found;
	size_t size;
	struct bb* bb = NULL;	/*stupid gcc */
	struct bb_jmp *bb_jmp;
	struct bb_reg_state *state;
	bb_reg_state_canonicalize();
	found = 0;
	for (i = 0; i < bb_jmp_count; ++i) {
		bb_jmp = bb_jmp_list + i;
		if (bb_jmp->from == from &&
		    bb_jmp->to == to &&
		    bb_jmp->drop_through == drop_through) {
			found = 1;
			break;
		}
	}
	if (!found) {
		/* Transfer outside the current function.  Check the special
		 * cases (mainly in entry.S) first.  If it is not a known
		 * special case then check if the target address is the start
		 * of a function or not.  If it is the start of a function then
		 * assume tail recursion and require that the state be the same
		 * as on entry.  Otherwise assume out of line code (e.g.
		 * spinlock contention path) and ignore it, the state can be
		 * anything.
		 */
		kdb_symtab_t symtab;
		if (bb_special_case(to))
			return;
		kdbnearsym(to, &symtab);
		if (symtab.sym_start != to)
			return;
		bb_sanity_check(0);
		if (bb_giveup)
			return;
#ifdef	NO_SIBLINGS
		/* Only print this message when the kernel is compiled with
		 * -fno-optimize-sibling-calls.  Otherwise it would print a
		 * message for every tail recursion call.  If you see the
		 * message below then you probably have an assembler label that
		 * is not listed in the special cases.
		 */
		kdb_printf("  not matched: from "
			   kdb_bfd_vma_fmt0
			   " to " kdb_bfd_vma_fmt0
			   " drop_through %d bb_jmp[%d]\n",
			   from, to, drop_through, i);
#endif	/* NO_SIBLINGS */
		return;
	}
	KDB_DEBUG_BB("  matched: from " kdb_bfd_vma_fmt0
		     " to " kdb_bfd_vma_fmt0
		     " drop_through %d bb_jmp[%d]\n",
		     from, to, drop_through, i);
	found = 0;
	for (i = 0; i < bb_count; ++i) {
		bb = bb_list[i];
		if (bb->start == to) {
			found = 1;
			break;
		}
	}
	BB_CHECK(!found, to, );
	/* If the register state for this arc has already been set (we are
	 * rescanning the block that originates the arc) and the state is the
	 * same as the previous state for this arc then this input to the
	 * target block is the same as last time, so there is no need to rescan
	 * the target block.
	 */
	state = bb_jmp->state;
	size = bb_reg_state_size(bb_reg_state);
	if (state) {
		bb_reg_state->ref_count = state->ref_count;
		if (memcmp(state, bb_reg_state, size) == 0) {
			KDB_DEBUG_BB("  no state change\n");
			return;
		}
		if (--state->ref_count == 0)
			debug_kfree(state);
		bb_jmp->state = NULL;
	}
	/* New input state is required.  To save space, check if any other arcs
	 * have the same state and reuse them where possible.  The overall set
	 * of inputs to the target block is now different so the target block
	 * must be rescanned.
	 */
	bb->changed = 1;
	for (i = 0; i < bb_jmp_count; ++i) {
		state = bb_jmp_list[i].state;
		if (!state)
			continue;
		bb_reg_state->ref_count = state->ref_count;
		if (memcmp(state, bb_reg_state, size) == 0) {
			KDB_DEBUG_BB("  reuse bb_jmp[%d]\n", i);
			bb_jmp->state = state;
			++state->ref_count;
			return;
		}
	}
	state = debug_kmalloc(size, GFP_ATOMIC);
	if (!state) {
		kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
		bb_giveup = 1;
		return;
	}
	memcpy(state, bb_reg_state, size);
	state->ref_count = 1;
	bb_jmp->state = state;
	KDB_DEBUG_BB("  new state %p\n", state);
}

/* Isolate the processing for 'mov' so it can be used for 'xadd'/'xchg' as
 * well.
 *
 * xadd/xchg expect this function to return BBOU_NOP for special cases,
 * otherwise it returns BBOU_RSWD.  All special cases must be handled entirely
 * within this function, including doing bb_read_operand or bb_write_operand
 * where necessary.
 */

static enum bb_operand_usage
bb_usage_mov(const struct bb_operand *src, const struct bb_operand *dst, int l)
{
	int full_register_src, full_register_dst;
	full_register_src = bb_operand_length(src, bb_decode.opcode[l])
			    == KDB_WORD_SIZE * 8;
	full_register_dst = bb_operand_length(dst, bb_decode.opcode[l])
			    == KDB_WORD_SIZE * 8;
	/* If both src and dst are full integer registers then record the
	 * register change.
	 */
	if (src->reg &&
	    bb_is_int_reg(src->base_rc) &&
	    dst->reg &&
	    bb_is_int_reg(dst->base_rc) &&
	    full_register_src &&
	    full_register_dst) {
		/* Special case for the code that switches stacks in
		 * jprobe_return.  That code must modify RSP but it does it in
		 * a well defined manner.  Do not invalidate RSP.
		 */
		if (src->base_rc == BBRG_RBX &&
		    dst->base_rc == BBRG_RSP &&
		    strcmp(bb_func_name, "jprobe_return") == 0) {
			bb_read_operand(src);
			return BBOU_NOP;
		}
		/* math_abort takes the equivalent of a longjmp structure and
		 * resets the stack.  Ignore this, it leaves RSP well defined.
		 */
		if (dst->base_rc == BBRG_RSP &&
		    strcmp(bb_func_name, "math_abort") == 0) {
			bb_read_operand(src);
			return BBOU_NOP;
		}
		bb_reg_set_reg(dst->base_rc, src->base_rc);
		return BBOU_NOP;
	}
	/* If the move is from a full integer register to stack then record it.
	 */
	if (src->reg &&
	    bb_is_simple_memory(dst) &&
	    bb_is_osp_defined(dst->base_rc) &&
	    full_register_src) {
		/* Ugly special case.  Initializing list heads on stack causes
		 * false references to stack variables when the list head is
		 * used.  Static code analysis cannot detect that the list head
		 * has been changed by a previous execution loop and that a
		 * basic block is only executed after the list head has been
		 * changed.
		 *
		 * These false references can result in valid stack variables
		 * being incorrectly cleared on some logic paths.  Ignore
		 * stores to stack variables which point to themselves or to
		 * the previous word so the list head initialization is not
		 * recorded.
		 */
		if (bb_is_osp_defined(src->base_rc)) {
			int stack1 = bb_reg_code_offset(src->base_rc);
			int stack2 = bb_reg_code_offset(dst->base_rc) +
				     dst->disp;
			if (stack1 == stack2 ||
			    stack1 == stack2 - KDB_WORD_SIZE)
				return BBOU_NOP;
		}
		bb_memory_set_reg(dst->base_rc, src->base_rc, dst->disp);
		return BBOU_NOP;
	}
	/* If the move is from stack to a full integer register then record it.
	 */
	if (bb_is_simple_memory(src) &&
	    bb_is_osp_defined(src->base_rc) &&
	    dst->reg &&
	    bb_is_int_reg(dst->base_rc) &&
	    full_register_dst) {
#ifdef	CONFIG_X86_32
		/* mov from TSS_sysenter_sp0+offset to esp to fix up the
		 * sysenter stack, it leaves esp well defined.  mov
		 * TSS_ysenter_sp0+offset(%esp),%esp is followed by up to 5
		 * push instructions to mimic the hardware stack push.  If
		 * TSS_sysenter_sp0 is offset then only 3 words will be
		 * pushed.
		 */
		if (dst->base_rc == BBRG_RSP &&
		    src->disp >= TSS_sysenter_sp0 &&
		    bb_is_osp_defined(BBRG_RSP)) {
			int pushes;
			pushes = src->disp == TSS_sysenter_sp0 ? 5 : 3;
			bb_reg_code_set_offset(BBRG_RSP,
				bb_reg_code_offset(BBRG_RSP) +
					pushes * KDB_WORD_SIZE);
			KDB_DEBUG_BB_OFFSET(
				bb_reg_code_offset(BBRG_RSP),
				"  sysenter fixup, RSP",
			       "\n");
			return BBOU_NOP;
		}
#endif	/* CONFIG_X86_32 */
		bb_read_operand(src);
		bb_reg_set_memory(dst->base_rc, src->base_rc, src->disp);
		return BBOU_NOP;
	}
	/* move %gs:0x<nn>,%rsp is used to unconditionally switch to another
	 * stack.  Ignore this special case, it is handled by the stack
	 * unwinding code.
	 */
	if (src->segment &&
	    strcmp(src->segment, "%gs") == 0 &&
	    dst->reg &&
	    dst->base_rc == BBRG_RSP)
		return BBOU_NOP;
	/* move %reg,%reg is a nop */
	if (src->reg &&
	    dst->reg &&
	    !src->segment &&
	    !dst->segment &&
	    strcmp(src->base, dst->base) == 0)
		return BBOU_NOP;
	/* Special case for the code that switches stacks in the scheduler
	 * (switch_to()).  That code must modify RSP but it does it in a well
	 * defined manner.  Do not invalidate RSP.
	 */
	if (dst->reg &&
	    dst->base_rc == BBRG_RSP &&
	    full_register_dst &&
	    bb_is_scheduler_address()) {
		bb_read_operand(src);
		return BBOU_NOP;
	}
	/* Special case for the code that switches stacks in resume from
	 * hibernation code.  That code must modify RSP but it does it in a
	 * well defined manner.  Do not invalidate RSP.
	 */
	if (src->memory &&
	    dst->reg &&
	    dst->base_rc == BBRG_RSP &&
	    full_register_dst &&
	    strcmp(bb_func_name, "restore_image") == 0) {
		bb_read_operand(src);
		return BBOU_NOP;
	}
	return BBOU_RSWD;
}

static enum bb_operand_usage
bb_usage_xadd(const struct bb_operand *src, const struct bb_operand *dst)
{
	/* Simulate xadd as a series of instructions including mov, that way we
	 * get the benefit of all the special cases already handled by
	 * BBOU_MOV.
	 *
	 * tmp = src + dst, src = dst, dst = tmp.
	 *
	 * For tmp, pick a register that is undefined.  If all registers are
	 * defined then pick one that is not being used by xadd.
	 */
	enum bb_reg_code reg = BBRG_UNDEFINED;
	struct bb_operand tmp;
	struct bb_reg_contains save_tmp;
	enum bb_operand_usage usage;
	int undefined = 0;
	for (reg = BBRG_RAX; reg < BBRG_RAX + KDB_INT_REGISTERS; ++reg) {
		if (bb_reg_code_value(reg) == BBRG_UNDEFINED) {
			undefined = 1;
			break;
		}
	}
	if (!undefined) {
		for (reg = BBRG_RAX; reg < BBRG_RAX + KDB_INT_REGISTERS; ++reg) {
			if (reg != src->base_rc &&
			    reg != src->index_rc &&
			    reg != dst->base_rc &&
			    reg != dst->index_rc &&
			    reg != BBRG_RSP)
				break;
		}
	}
	KDB_DEBUG_BB("  %s saving tmp %s\n", __FUNCTION__, bbrg_name[reg]);
	save_tmp = bb_reg_state->contains[reg - BBRG_RAX];
	bb_reg_set_undef(reg);
	memset(&tmp, 0, sizeof(tmp));
	tmp.present = 1;
	tmp.reg = 1;
	tmp.base = debug_kmalloc(strlen(bbrg_name[reg]) + 2, GFP_ATOMIC);
	if (tmp.base) {
		tmp.base[0] = '%';
		strcpy(tmp.base + 1, bbrg_name[reg]);
	}
	tmp.base_rc = reg;
	bb_read_operand(src);
	bb_read_operand(dst);
	if (bb_usage_mov(src, dst, sizeof("xadd")-1) == BBOU_NOP)
		usage = BBOU_RSRD;
	else
		usage = BBOU_RSRDWS;
	bb_usage_mov(&tmp, dst, sizeof("xadd")-1);
	KDB_DEBUG_BB("  %s restoring tmp %s\n", __FUNCTION__, bbrg_name[reg]);
	bb_reg_state->contains[reg - BBRG_RAX] = save_tmp;
	debug_kfree(tmp.base);
	return usage;
}

static enum bb_operand_usage
bb_usage_xchg(const struct bb_operand *src, const struct bb_operand *dst)
{
	/* Simulate xchg as a series of mov instructions, that way we get the
	 * benefit of all the special cases already handled by BBOU_MOV.
	 *
	 * mov dst,tmp; mov src,dst; mov tmp,src;
	 *
	 * For tmp, pick a register that is undefined.  If all registers are
	 * defined then pick one that is not being used by xchg.
	 */
	enum bb_reg_code reg = BBRG_UNDEFINED;
	int rs = BBOU_RS, rd = BBOU_RD, ws = BBOU_WS, wd = BBOU_WD;
	struct bb_operand tmp;
	struct bb_reg_contains save_tmp;
	int undefined = 0;
	for (reg = BBRG_RAX; reg < BBRG_RAX + KDB_INT_REGISTERS; ++reg) {
		if (bb_reg_code_value(reg) == BBRG_UNDEFINED) {
			undefined = 1;
			break;
		}
	}
	if (!undefined) {
		for (reg = BBRG_RAX; reg < BBRG_RAX + KDB_INT_REGISTERS; ++reg) {
			if (reg != src->base_rc &&
			    reg != src->index_rc &&
			    reg != dst->base_rc &&
			    reg != dst->index_rc &&
			    reg != BBRG_RSP)
				break;
		}
	}
	KDB_DEBUG_BB("  %s saving tmp %s\n", __FUNCTION__, bbrg_name[reg]);
	save_tmp = bb_reg_state->contains[reg - BBRG_RAX];
	memset(&tmp, 0, sizeof(tmp));
	tmp.present = 1;
	tmp.reg = 1;
	tmp.base = debug_kmalloc(strlen(bbrg_name[reg]) + 2, GFP_ATOMIC);
	if (tmp.base) {
		tmp.base[0] = '%';
		strcpy(tmp.base + 1, bbrg_name[reg]);
	}
	tmp.base_rc = reg;
	if (bb_usage_mov(dst, &tmp, sizeof("xchg")-1) == BBOU_NOP)
		rd = 0;
	if (bb_usage_mov(src, dst, sizeof("xchg")-1) == BBOU_NOP) {
		rs = 0;
		wd = 0;
	}
	if (bb_usage_mov(&tmp, src, sizeof("xchg")-1) == BBOU_NOP)
		ws = 0;
	KDB_DEBUG_BB("  %s restoring tmp %s\n", __FUNCTION__, bbrg_name[reg]);
	bb_reg_state->contains[reg - BBRG_RAX] = save_tmp;
	debug_kfree(tmp.base);
	return rs | rd | ws | wd;
}

/* Invalidate all the scratch registers */

static void
bb_invalidate_scratch_reg(void)
{
	int i, j;
	for (i = BBRG_RAX; i < BBRG_RAX + KDB_INT_REGISTERS; ++i) {
		for (j = 0; j < ARRAY_SIZE(bb_preserved_reg); ++j) {
			if (i == bb_preserved_reg[j])
				goto preserved;
		}
		bb_reg_set_undef(i);
preserved:
		continue;
	}
}

static void
bb_pass2_computed_jmp(const struct bb_operand *src)
{
	unsigned long table = src->disp;
	kdb_machreg_t addr;
	while (!bb_giveup) {
		if (kdb_getword(&addr, table, sizeof(addr)))
			return;
		if (addr < bb_func_start || addr >= bb_func_end)
			return;
		bb_transfer(bb_curr_addr, addr, 0);
		table += KDB_WORD_SIZE;
	}
}

/* The current instruction has been decoded and all the information is in
 * bb_decode.  Based on the opcode, track any operand usage that we care about.
 */

static void
bb_usage(void)
{
	enum bb_operand_usage usage = bb_decode.match->usage;
	struct bb_operand *src = &bb_decode.src;
	struct bb_operand *dst = &bb_decode.dst;
	struct bb_operand *dst2 = &bb_decode.dst2;
	int opcode_suffix, operand_length;

	/* First handle all the special usage cases, and map them to a generic
	 * case after catering for the side effects.
	 */

	if (usage == BBOU_IMUL &&
	    src->present && !dst->present && !dst2->present) {
		/* single operand imul, same effects as mul */
		usage = BBOU_MUL;
	}

	/* AT&T syntax uses movs<l1><l2> for move with sign extension, instead
	 * of the Intel movsx.  The AT&T syntax causes problems for the opcode
	 * mapping; movs with sign extension needs to be treated as a generic
	 * read src, write dst, but instead it falls under the movs I/O
	 * instruction.  Fix it.
	 */
	if (usage == BBOU_MOVS && strlen(bb_decode.opcode) > 5)
		usage = BBOU_RSWD;

	/* This switch statement deliberately does not use 'default' at the top
	 * level.  That way the compiler will complain if a new BBOU_ enum is
	 * added above and not explicitly handled here.
	 */
	switch (usage) {
	case BBOU_UNKNOWN:	/* drop through */
	case BBOU_RS:		/* drop through */
	case BBOU_RD:		/* drop through */
	case BBOU_RSRD:		/* drop through */
	case BBOU_WS:		/* drop through */
	case BBOU_RSWS:		/* drop through */
	case BBOU_RDWS:		/* drop through */
	case BBOU_RSRDWS:	/* drop through */
	case BBOU_WD:		/* drop through */
	case BBOU_RSWD:		/* drop through */
	case BBOU_RDWD:		/* drop through */
	case BBOU_RSRDWD:	/* drop through */
	case BBOU_WSWD:		/* drop through */
	case BBOU_RSWSWD:	/* drop through */
	case BBOU_RDWSWD:	/* drop through */
	case BBOU_RSRDWSWD:
		break;		/* ignore generic usage for now */
	case BBOU_ADD:
		/* Special case for add instructions that adjust registers
		 * which are mapping the stack.
		 */
		if (dst->reg && bb_is_osp_defined(dst->base_rc)) {
			bb_adjust_osp_instruction(1);
			usage = BBOU_RS;
		} else {
			usage = BBOU_RSRDWD;
		}
		break;
	case BBOU_CALL:
		/* Invalidate the scratch registers.  Functions sync_regs and
		 * save_v86_state are special, their return value is the new
		 * stack pointer.
		 */
		bb_reg_state_print(bb_reg_state);
		bb_invalidate_scratch_reg();
		if (bb_is_static_disp(src)) {
			if (src->disp == bb_sync_regs) {
				bb_reg_set_reg(BBRG_RAX, BBRG_RSP);
			} else if (src->disp == bb_save_v86_state) {
				bb_reg_set_reg(BBRG_RAX, BBRG_RSP);
				bb_adjust_osp(BBRG_RAX, +KDB_WORD_SIZE);
			}
		}
		usage = BBOU_NOP;
		break;
	case BBOU_CBW:
		/* Convert word in RAX.  Read RAX, write RAX */
		bb_reg_read(BBRG_RAX);
		bb_reg_set_undef(BBRG_RAX);
		usage = BBOU_NOP;
		break;
	case BBOU_CMOV:
		/* cmove %gs:0x<nn>,%rsp is used to conditionally switch to
		 * another stack.  Ignore this special case, it is handled by
		 * the stack unwinding code.
		 */
		if (src->segment &&
		    strcmp(src->segment, "%gs") == 0 &&
		    dst->reg &&
		    dst->base_rc == BBRG_RSP)
			usage = BBOU_NOP;
		else
			usage = BBOU_RSWD;
		break;
	case BBOU_CMPXCHG:
		/* Read RAX, write RAX plus src read, dst write */
		bb_reg_read(BBRG_RAX);
		bb_reg_set_undef(BBRG_RAX);
		usage = BBOU_RSWD;
		break;
	case BBOU_CMPXCHGD:
		/* Read RAX, RBX, RCX, RDX, write RAX, RDX plus src read/write */
		bb_reg_read(BBRG_RAX);
		bb_reg_read(BBRG_RBX);
		bb_reg_read(BBRG_RCX);
		bb_reg_read(BBRG_RDX);
		bb_reg_set_undef(BBRG_RAX);
		bb_reg_set_undef(BBRG_RDX);
		usage = BBOU_RSWS;
		break;
	case BBOU_CPUID:
		/* Read RAX, write RAX, RBX, RCX, RDX */
		bb_reg_read(BBRG_RAX);
		bb_reg_set_undef(BBRG_RAX);
		bb_reg_set_undef(BBRG_RBX);
		bb_reg_set_undef(BBRG_RCX);
		bb_reg_set_undef(BBRG_RDX);
		usage = BBOU_NOP;
		break;
	case BBOU_CWD:
		/* Convert word in RAX, RDX.  Read RAX, write RDX */
		bb_reg_read(BBRG_RAX);
		bb_reg_set_undef(BBRG_RDX);
		usage = BBOU_NOP;
		break;
	case BBOU_DIV:	/* drop through */
	case BBOU_IDIV:
		/* The 8 bit variants only affect RAX, the 16, 32 and 64 bit
		 * variants affect RDX as well.
		 */
		switch (usage) {
		case BBOU_DIV:
			opcode_suffix = bb_decode.opcode[3];
			break;
		case BBOU_IDIV:
			opcode_suffix = bb_decode.opcode[4];
			break;
		default:
			opcode_suffix = 'q';
			break;
		}
		operand_length = bb_operand_length(src, opcode_suffix);
		bb_reg_read(BBRG_RAX);
		bb_reg_set_undef(BBRG_RAX);
		if (operand_length != 8) {
			bb_reg_read(BBRG_RDX);
			bb_reg_set_undef(BBRG_RDX);
		}
		usage = BBOU_RS;
		break;
	case BBOU_IMUL:
		/* Only the two and three operand forms get here.  The one
		 * operand form is treated as mul.
		 */
		if (dst2->present) {
			/* The three operand form is a special case, read the first two
			 * operands, write the third.
			 */
			bb_read_operand(src);
			bb_read_operand(dst);
			bb_write_operand(dst2);
			usage = BBOU_NOP;
		} else {
			usage = BBOU_RSRDWD;
		}
		break;
	case BBOU_IRET:
		bb_sanity_check(0);
		usage = BBOU_NOP;
		break;
	case BBOU_JMP:
		if (bb_is_static_disp(src))
			bb_transfer(bb_curr_addr, src->disp, 0);
		else if (src->indirect &&
			 src->disp &&
			 src->base == NULL &&
			 src->index &&
			 src->scale == KDB_WORD_SIZE)
			bb_pass2_computed_jmp(src);
		usage = BBOU_RS;
		break;
	case BBOU_LAHF:
		/* Write RAX */
		bb_reg_set_undef(BBRG_RAX);
		usage = BBOU_NOP;
		break;
	case BBOU_LEA:
		/* dst = src + disp.  Often used to calculate offsets into the
		 * stack, so check if it uses a stack pointer.
		 */
		usage = BBOU_RSWD;
		if (bb_is_simple_memory(src)) {
		       if (bb_is_osp_defined(src->base_rc)) {
				bb_reg_set_reg(dst->base_rc, src->base_rc);
				bb_adjust_osp_instruction(1);
				usage = BBOU_RS;
			} else if (src->disp == 0 &&
				   src->base_rc == dst->base_rc) {
				/* lea 0(%reg),%reg is generated by i386
				 * GENERIC_NOP7.
				 */
				usage = BBOU_NOP;
			} else if (src->disp == 4096 &&
				   (src->base_rc == BBRG_R8 ||
				    src->base_rc == BBRG_RDI) &&
				   strcmp(bb_func_name, "relocate_kernel") == 0) {
				/* relocate_kernel: setup a new stack at the
				 * end of the physical control page, using
				 * (x86_64) lea 4096(%r8),%rsp or (i386) lea
				 * 4096(%edi),%esp
				 */
				usage = BBOU_NOP;
			}
		}
		break;
	case BBOU_LEAVE:
		/* RSP = RBP; RBP = *(RSP); RSP += KDB_WORD_SIZE; */
		bb_reg_set_reg(BBRG_RSP, BBRG_RBP);
		if (bb_is_osp_defined(BBRG_RSP))
			bb_reg_set_memory(BBRG_RBP, BBRG_RSP, 0);
		else
			bb_reg_set_undef(BBRG_RBP);
		if (bb_is_osp_defined(BBRG_RSP))
			bb_adjust_osp(BBRG_RSP, KDB_WORD_SIZE);
		/* common_interrupt uses leave in a non-standard manner */
		if (strcmp(bb_func_name, "common_interrupt") != 0)
			bb_sanity_check(0);
		usage = BBOU_NOP;
		break;
	case BBOU_LODS:
		/* Read RSI, write RAX, RSI */
		bb_reg_read(BBRG_RSI);
		bb_reg_set_undef(BBRG_RAX);
		bb_reg_set_undef(BBRG_RSI);
		usage = BBOU_NOP;
		break;
	case BBOU_LOOP:
		/* Read and write RCX */
		bb_reg_read(BBRG_RCX);
		bb_reg_set_undef(BBRG_RCX);
		if (bb_is_static_disp(src))
			bb_transfer(bb_curr_addr, src->disp, 0);
		usage = BBOU_NOP;
		break;
	case BBOU_LSS:
		/* lss offset(%esp),%esp leaves esp well defined */
		if (dst->reg &&
		    dst->base_rc == BBRG_RSP &&
		    bb_is_simple_memory(src) &&
		    src->base_rc == BBRG_RSP) {
			bb_adjust_osp(BBRG_RSP, 2*KDB_WORD_SIZE + src->disp);
			usage = BBOU_NOP;
		} else {
			usage = BBOU_RSWD;
		}
		break;
	case BBOU_MONITOR:
		/* Read RAX, RCX, RDX */
		bb_reg_set_undef(BBRG_RAX);
		bb_reg_set_undef(BBRG_RCX);
		bb_reg_set_undef(BBRG_RDX);
		usage = BBOU_NOP;
		break;
	case BBOU_MOV:
		usage = bb_usage_mov(src, dst, sizeof("mov")-1);
		break;
	case BBOU_MOVS:
		/* Read RSI, RDI, write RSI, RDI */
		bb_reg_read(BBRG_RSI);
		bb_reg_read(BBRG_RDI);
		bb_reg_set_undef(BBRG_RSI);
		bb_reg_set_undef(BBRG_RDI);
		usage = BBOU_NOP;
		break;
	case BBOU_MUL:
		/* imul (one operand form only) or mul.  Read RAX.  If the
		 * operand length is not 8 then write RDX.
		 */
		if (bb_decode.opcode[0] == 'i')
			opcode_suffix = bb_decode.opcode[4];
		else
			opcode_suffix = bb_decode.opcode[3];
		operand_length = bb_operand_length(src, opcode_suffix);
		bb_reg_read(BBRG_RAX);
		if (operand_length != 8)
			bb_reg_set_undef(BBRG_RDX);
		usage = BBOU_NOP;
		break;
	case BBOU_MWAIT:
		/* Read RAX, RCX */
		bb_reg_read(BBRG_RAX);
		bb_reg_read(BBRG_RCX);
		usage = BBOU_NOP;
		break;
	case BBOU_NOP:
		break;
	case BBOU_OUTS:
		/* Read RSI, RDX, write RSI */
		bb_reg_read(BBRG_RSI);
		bb_reg_read(BBRG_RDX);
		bb_reg_set_undef(BBRG_RSI);
		usage = BBOU_NOP;
		break;
	case BBOU_POP:
		/* Complicated by the fact that you can pop from top of stack
		 * to a stack location, for this case the destination location
		 * is calculated after adjusting RSP.  Analysis of the kernel
		 * code shows that gcc only uses this strange format to get the
		 * flags into a local variable, e.g. pushf; popl 0x10(%esp); so
		 * I am going to ignore this special case.
		 */
		usage = BBOU_WS;
		if (!bb_is_osp_defined(BBRG_RSP)) {
			if (!bb_is_scheduler_address()) {
				kdb_printf("pop when BBRG_RSP is undefined?\n");
				bb_giveup = 1;
			}
		} else {
			if (src->reg) {
				bb_reg_set_memory(src->base_rc, BBRG_RSP, 0);
				usage = BBOU_NOP;
			}
			/* pop %rsp does not adjust rsp */
			if (!src->reg ||
			    src->base_rc != BBRG_RSP)
				bb_adjust_osp(BBRG_RSP, KDB_WORD_SIZE);
		}
		break;
	case BBOU_POPF:
		/* Do not care about flags, just adjust RSP */
		if (!bb_is_osp_defined(BBRG_RSP)) {
			if (!bb_is_scheduler_address()) {
				kdb_printf("popf when BBRG_RSP is undefined?\n");
				bb_giveup = 1;
			}
		} else {
			bb_adjust_osp(BBRG_RSP, KDB_WORD_SIZE);
		}
		usage = BBOU_WS;
		break;
	case BBOU_PUSH:
		/* Complicated by the fact that you can push from a stack
		 * location to top of stack, the source location is calculated
		 * before adjusting RSP.  Analysis of the kernel code shows
		 * that gcc only uses this strange format to restore the flags
		 * from a local variable, e.g. pushl 0x10(%esp); popf; so I am
		 * going to ignore this special case.
		 */
		usage = BBOU_RS;
		if (!bb_is_osp_defined(BBRG_RSP)) {
			if (!bb_is_scheduler_address()) {
				kdb_printf("push when BBRG_RSP is undefined?\n");
				bb_giveup = 1;
			}
		} else {
			bb_adjust_osp(BBRG_RSP, -KDB_WORD_SIZE);
			if (src->reg &&
			    bb_reg_code_offset(BBRG_RSP) <= 0)
				bb_memory_set_reg(BBRG_RSP, src->base_rc, 0);
		}
		break;
	case BBOU_PUSHF:
		/* Do not care about flags, just adjust RSP */
		if (!bb_is_osp_defined(BBRG_RSP)) {
			if (!bb_is_scheduler_address()) {
				kdb_printf("pushf when BBRG_RSP is undefined?\n");
				bb_giveup = 1;
			}
		} else {
			bb_adjust_osp(BBRG_RSP, -KDB_WORD_SIZE);
		}
		usage = BBOU_WS;
		break;
	case BBOU_RDMSR:
		/* Read RCX, write RAX, RDX */
		bb_reg_read(BBRG_RCX);
		bb_reg_set_undef(BBRG_RAX);
		bb_reg_set_undef(BBRG_RDX);
		usage = BBOU_NOP;
		break;
	case BBOU_RDTSC:
		/* Write RAX, RDX */
		bb_reg_set_undef(BBRG_RAX);
		bb_reg_set_undef(BBRG_RDX);
		usage = BBOU_NOP;
		break;
	case BBOU_RET:
		usage = BBOU_NOP;
		/* Functions that restore state which was saved by another
		 * function or build new kernel stacks.  We cannot verify what
		 * is being restored so skip the sanity check.
		 */
		if (strcmp(bb_func_name, "restore_image") == 0 ||
		    strcmp(bb_func_name, "relocate_kernel") == 0 ||
		    strcmp(bb_func_name, "identity_mapped") == 0 ||
		    strcmp(bb_func_name, "xen_iret_crit_fixup") == 0 ||
		    strcmp(bb_func_name, "math_abort") == 0)
			break;
		bb_sanity_check(0);
		break;
	case BBOU_SAHF:
		/* Read RAX */
		bb_reg_read(BBRG_RAX);
		usage = BBOU_NOP;
		break;
	case BBOU_SCAS:
		/* Read RAX, RDI, write RDI */
		bb_reg_read(BBRG_RAX);
		bb_reg_read(BBRG_RDI);
		bb_reg_set_undef(BBRG_RDI);
		usage = BBOU_NOP;
		break;
	case BBOU_SUB:
		/* Special case for sub instructions that adjust registers
		 * which are mapping the stack.
		 */
		if (dst->reg && bb_is_osp_defined(dst->base_rc)) {
			bb_adjust_osp_instruction(-1);
			usage = BBOU_RS;
		} else {
			usage = BBOU_RSRDWD;
		}
		break;
	case BBOU_SYSEXIT:
		bb_sanity_check(1);
		usage = BBOU_NOP;
		break;
	case BBOU_SYSRET:
		bb_sanity_check(1);
		usage = BBOU_NOP;
		break;
	case BBOU_WRMSR:
		/* Read RCX, RAX, RDX */
		bb_reg_read(BBRG_RCX);
		bb_reg_read(BBRG_RAX);
		bb_reg_read(BBRG_RDX);
		usage = BBOU_NOP;
		break;
	case BBOU_XADD:
		usage = bb_usage_xadd(src, dst);
		break;
	case BBOU_XCHG:
		/* i386 do_IRQ with 4K stacks does xchg %ebx,%esp; call
		 * irq_handler; mov %ebx,%esp; to switch stacks.  Ignore this
		 * stack switch when tracking registers, it is handled by
		 * higher level backtrace code.  Convert xchg %ebx,%esp to mov
		 * %esp,%ebx so the later mov %ebx,%esp becomes a NOP and the
		 * stack remains defined so we can backtrace through do_IRQ's
		 * stack switch.
		 *
		 * Ditto for do_softirq.
		 */
		if (src->reg &&
		    dst->reg &&
		    src->base_rc == BBRG_RBX &&
		    dst->base_rc == BBRG_RSP &&
		    (strcmp(bb_func_name, "do_IRQ") == 0 ||
		     strcmp(bb_func_name, "do_softirq") == 0)) {
			strcpy(bb_decode.opcode, "mov");
			usage = bb_usage_mov(dst, src, sizeof("mov")-1);
		} else {
			usage = bb_usage_xchg(src, dst);
		}
		break;
	case BBOU_XOR:
		/* xor %reg,%reg only counts as a register write, the original
		 * contents of reg are irrelevant.
		 */
		if (src->reg && dst->reg && src->base_rc == dst->base_rc)
			usage = BBOU_WS;
		else
			usage = BBOU_RSRDWD;
		break;
	}

	/* The switch statement above handled all the special cases.  Every
	 * opcode should now have a usage of NOP or one of the generic cases.
	 */
	if (usage == BBOU_UNKNOWN || usage == BBOU_NOP) {
		/* nothing to do */
	} else if (usage >= BBOU_RS && usage <= BBOU_RSRDWSWD) {
		if (usage & BBOU_RS)
			bb_read_operand(src);
		if (usage & BBOU_RD)
			bb_read_operand(dst);
		if (usage & BBOU_WS)
			bb_write_operand(src);
		if (usage & BBOU_WD)
			bb_write_operand(dst);
	} else {
		kdb_printf("%s: opcode not fully handled\n", __FUNCTION__);
		if (!KDB_DEBUG(BB)) {
			bb_print_opcode();
			if (bb_decode.src.present)
				bb_print_operand("src", &bb_decode.src);
			if (bb_decode.dst.present)
				bb_print_operand("dst", &bb_decode.dst);
			if (bb_decode.dst2.present)
				bb_print_operand("dst2", &bb_decode.dst2);
		}
		bb_giveup = 1;
	}
}

static void
bb_parse_buffer(void)
{
	char *p, *src, *dst = NULL, *dst2 = NULL;
	int paren = 0;
	p = bb_buffer;
	memset(&bb_decode, 0, sizeof(bb_decode));
	KDB_DEBUG_BB(" '%s'\n", p);
	p += strcspn(p, ":");	/* skip address and function name+offset: */
	if (*p++ != ':') {
		kdb_printf("%s: cannot find ':' in buffer '%s'\n",
			   __FUNCTION__, bb_buffer);
		bb_giveup = 1;
		return;
	}
	p += strspn(p, " \t");	/* step to opcode */
	if (strncmp(p, "(bad)", 5) == 0)
		strcpy(p, "nop");
	/* separate any opcode prefix */
	if (strncmp(p, "lock", 4) == 0 ||
	    strncmp(p, "rep", 3) == 0 ||
	    strncmp(p, "rex", 3) == 0 ||
	    strncmp(p, "addr", 4) == 0) {
		bb_decode.prefix = p;
		p += strcspn(p, " \t");
		*p++ = '\0';
		p += strspn(p, " \t");
	}
	bb_decode.opcode = p;
	strsep(&p, " \t");	/* step to end of opcode */
	if (bb_parse_opcode())
		return;
	if (!p)
		goto no_operands;
	p += strspn(p, " \t");	/* step to operand(s) */
	if (!*p)
		goto no_operands;
	src = p;
	p = strsep(&p, " \t");	/* strip comments after operands */
	/* split 'src','dst' but ignore ',' inside '(' ')' */
	while (*p) {
		if (*p == '(') {
			++paren;
		} else if (*p == ')') {
			--paren;
		} else if (*p == ',' && paren == 0) {
			*p = '\0';
			if (dst)
				dst2 = p+1;
			else
				dst = p+1;
		}
		++p;
	}
	bb_parse_operand(src, &bb_decode.src);
	if (KDB_DEBUG(BB))
		bb_print_operand("src", &bb_decode.src);
	if (dst && !bb_giveup) {
		bb_parse_operand(dst, &bb_decode.dst);
		if (KDB_DEBUG(BB))
			bb_print_operand("dst", &bb_decode.dst);
	}
	if (dst2 && !bb_giveup) {
		bb_parse_operand(dst2, &bb_decode.dst2);
		if (KDB_DEBUG(BB))
			bb_print_operand("dst2", &bb_decode.dst2);
	}
no_operands:
	if (!bb_giveup)
		bb_usage();
}

static int
bb_dis_pass2(PTR file, const char *fmt, ...)
{
	char *p;
	int l = strlen(bb_buffer);
	va_list ap;
	va_start(ap, fmt);
	vsnprintf(bb_buffer + l, sizeof(bb_buffer) - l, fmt, ap);
	va_end(ap);
	if ((p = strchr(bb_buffer, '\n'))) {
		*p = '\0';
		p = bb_buffer;
		p += strcspn(p, ":");
		if (*p++ == ':')
			bb_fixup_switch_to(p);
		bb_parse_buffer();
		bb_buffer[0] = '\0';
	}
	return 0;
}

static void
bb_printaddr_pass2(bfd_vma addr, disassemble_info *dip)
{
	kdb_symtab_t symtab;
	unsigned int offset;
	dip->fprintf_func(dip->stream, "0x%lx", addr);
	kdbnearsym(addr, &symtab);
	if (symtab.sym_name) {
		dip->fprintf_func(dip->stream, " <%s", symtab.sym_name);
		if ((offset = addr - symtab.sym_start))
			dip->fprintf_func(dip->stream, "+0x%x", offset);
		dip->fprintf_func(dip->stream, ">");
	}
}

/* Set the starting register and memory state for the current bb */

static void
bb_start_block0_special(void)
{
	int i;
	short offset_address;
	enum bb_reg_code reg, value;
	struct bb_name_state *r;
	for (i = 0, r = bb_special_cases;
	     i < ARRAY_SIZE(bb_special_cases);
	     ++i, ++r) {
		if (bb_func_start == r->address && r->fname == NULL)
			goto match;
	}
	return;
match:
	/* Set the running registers */
	for (reg = BBRG_RAX; reg < r->regs_size; ++reg) {
		value = r->regs[reg].value;
		if (test_bit(value, r->skip_regs.bits)) {
			/* this regs entry is not defined for this label */
			continue;
		}
		bb_reg_code_set_value(reg, value);
		bb_reg_code_set_offset(reg, r->regs[reg].offset);
	}
	/* Set any memory contents, e.g. pt_regs.  Adjust RSP as required. */
	offset_address = 0;
	for (i = 0; i < r->mem_size; ++i) {
		offset_address = max_t(int,
				r->mem[i].offset_address + KDB_WORD_SIZE,
				offset_address);
	}
	if (bb_reg_code_offset(BBRG_RSP) > -offset_address)
		bb_adjust_osp(BBRG_RSP, -offset_address - bb_reg_code_offset(BBRG_RSP));
	for (i = 0; i < r->mem_size; ++i) {
		value = r->mem[i].value;
		if (test_bit(value, r->skip_mem.bits)) {
			/* this memory entry is not defined for this label */
			continue;
		}
		bb_memory_set_reg_value(BBRG_RSP, r->mem[i].offset_address,
					value, 0);
		bb_reg_set_undef(value);
	}
	return;
}

static void
bb_pass2_start_block(int number)
{
	int i, j, k, first, changed;
	size_t size;
	struct bb_jmp *bb_jmp;
	struct bb_reg_state *state;
	struct bb_memory_contains *c1, *c2;
	bb_reg_state->mem_count = bb_reg_state_max;
	size = bb_reg_state_size(bb_reg_state);
	memset(bb_reg_state, 0, size);

	if (number == 0) {
		/* The first block is assumed to have well defined inputs */
		bb_start_block0();
		/* Some assembler labels have non-standard entry
		 * states.
		 */
		bb_start_block0_special();
		bb_reg_state_print(bb_reg_state);
		return;
	}

	/* Merge all the input states for the current bb together */
	first = 1;
	changed = 0;
	for (i = 0; i < bb_jmp_count; ++i) {
		bb_jmp = bb_jmp_list + i;
		if (bb_jmp->to != bb_curr->start)
			continue;
		state = bb_jmp->state;
		if (!state)
			continue;
		if (first) {
			size = bb_reg_state_size(state);
			memcpy(bb_reg_state, state, size);
			KDB_DEBUG_BB("  first state %p\n", state);
			bb_reg_state_print(bb_reg_state);
			first = 0;
			continue;
		}

		KDB_DEBUG_BB("  merging state %p\n", state);
		/* Merge the register states */
		for (j = 0; j < ARRAY_SIZE(state->contains); ++j) {
			if (memcmp(bb_reg_state->contains + j,
				   state->contains + j,
				   sizeof(bb_reg_state->contains[0]))) {
				/* Different states for this register from two
				 * or more inputs, make it undefined.
				 */
				if (bb_reg_state->contains[j].value ==
				    BBRG_UNDEFINED) {
					KDB_DEBUG_BB("  ignoring %s\n",
						    bbrg_name[j + BBRG_RAX]);
				} else {
					bb_reg_set_undef(BBRG_RAX + j);
					changed = 1;
				}
			}
		}

		/* Merge the memory states.  This relies on both
		 * bb_reg_state->memory and state->memory being sorted in
		 * descending order, with undefined entries at the end.
		 */
		c1 = bb_reg_state->memory;
		c2 = state->memory;
		j = k = 0;
		while (j < bb_reg_state->mem_count &&
		       k < state->mem_count) {
			if (c1->offset_address < c2->offset_address) {
				KDB_DEBUG_BB_OFFSET(c2->offset_address,
						    "  ignoring c2->offset_address ",
						    "\n");
				++c2;
				++k;
				continue;
			}
			if (c1->offset_address > c2->offset_address) {
				/* Memory location is not in all input states,
				 * delete the memory location.
				 */
				bb_delete_memory(c1->offset_address);
				changed = 1;
				++c1;
				++j;
				continue;
			}
			if (memcmp(c1, c2, sizeof(*c1))) {
				/* Same location, different contents, delete
				 * the memory location.
				 */
				bb_delete_memory(c1->offset_address);
				KDB_DEBUG_BB_OFFSET(c2->offset_address,
						    "  ignoring c2->offset_address ",
						    "\n");
				changed = 1;
			}
			++c1;
			++c2;
			++j;
			++k;
		}
		while (j < bb_reg_state->mem_count) {
			bb_delete_memory(c1->offset_address);
			changed = 1;
			++c1;
			++j;
		}
	}
	if (changed) {
		KDB_DEBUG_BB("  final state\n");
		bb_reg_state_print(bb_reg_state);
	}
}

/* We have reached the exit point from the current function, either a call to
 * the next function or the instruction that was about to executed when an
 * interrupt occurred.  Save the current register state in bb_exit_state.
 */

static void
bb_save_exit_state(void)
{
	size_t size;
	debug_kfree(bb_exit_state);
	bb_exit_state = NULL;
	bb_reg_state_canonicalize();
	size = bb_reg_state_size(bb_reg_state);
	bb_exit_state = debug_kmalloc(size, GFP_ATOMIC);
	if (!bb_exit_state) {
		kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
		bb_giveup = 1;
		return;
	}
	memcpy(bb_exit_state, bb_reg_state, size);
}

static int
bb_pass2_do_changed_blocks(int allow_missing)
{
	int i, j, missing, changed, maxloops;
	unsigned long addr;
	struct bb_jmp *bb_jmp;
	KDB_DEBUG_BB("\n  %s: allow_missing %d\n", __FUNCTION__, allow_missing);
	/* Absolute worst case is we have to iterate over all the basic blocks
	 * in an "out of order" state, each iteration losing one register or
	 * memory state.  Any more loops than that is a bug.  "out of order"
	 * means that the layout of blocks in memory does not match the logic
	 * flow through those blocks so (for example) block 27 comes before
	 * block 2.  To allow for out of order blocks, multiply maxloops by the
	 * number of blocks.
	 */
	maxloops = (KDB_INT_REGISTERS + bb_reg_state_max) * bb_count;
	changed = 1;
	do {
		changed = 0;
		for (i = 0; i < bb_count; ++i) {
			bb_curr = bb_list[i];
			if (!bb_curr->changed)
				continue;
			missing = 0;
			for (j = 0, bb_jmp = bb_jmp_list;
			     j < bb_jmp_count;
			     ++j, ++bb_jmp) {
				if (bb_jmp->to == bb_curr->start &&
				    !bb_jmp->state)
					++missing;
			}
			if (missing > allow_missing)
				continue;
			bb_curr->changed = 0;
			changed = 1;
			KDB_DEBUG_BB("\n  bb[%d]\n", i);
			bb_pass2_start_block(i);
			for (addr = bb_curr->start;
			     addr <= bb_curr->end; ) {
				bb_curr_addr = addr;
				if (addr == bb_exit_addr)
					bb_save_exit_state();
				addr += kdba_id_printinsn(addr, &kdb_di);
				kdb_di.fprintf_func(NULL, "\n");
				if (bb_giveup)
					goto done;
			}
			if (!bb_exit_state) {
				/* ATTRIB_NORET functions are a problem with
				 * the current gcc.  Allow the trailing address
				 * a bit of leaway.
				 */
				if (addr == bb_exit_addr ||
				    addr == bb_exit_addr + 1)
					bb_save_exit_state();
			}
			if (bb_curr->drop_through)
				bb_transfer(bb_curr->end,
					    bb_list[i+1]->start, 1);
		}
		if (maxloops-- == 0) {
			kdb_printf("\n\n%s maxloops reached\n",
				   __FUNCTION__);
			bb_giveup = 1;
			goto done;
		}
	} while(changed);
done:
	for (i = 0; i < bb_count; ++i) {
		bb_curr = bb_list[i];
		if (bb_curr->changed)
			return 1;	/* more to do, increase allow_missing */
	}
	return 0;	/* all blocks done */
}

/* Assume that the current function is a pass through function that does not
 * refer to its register parameters.  Exclude known asmlinkage functions and
 * assume the other functions actually use their registers.
 */

static void
bb_assume_pass_through(void)
{
	static int first_time = 1;
	if (strncmp(bb_func_name, "sys_", 4) == 0 ||
	    strncmp(bb_func_name, "compat_sys_", 11) == 0 ||
	    strcmp(bb_func_name, "schedule") == 0 ||
	    strcmp(bb_func_name, "do_softirq") == 0 ||
	    strcmp(bb_func_name, "printk") == 0 ||
	    strcmp(bb_func_name, "vprintk") == 0 ||
	    strcmp(bb_func_name, "preempt_schedule") == 0 ||
	    strcmp(bb_func_name, "start_kernel") == 0 ||
	    strcmp(bb_func_name, "csum_partial") == 0 ||
	    strcmp(bb_func_name, "csum_partial_copy_generic") == 0 ||
	    strcmp(bb_func_name, "math_state_restore") == 0 ||
	    strcmp(bb_func_name, "panic") == 0 ||
	    strcmp(bb_func_name, "kdb_printf") == 0 ||
	    strcmp(bb_func_name, "kdb_interrupt") == 0)
		return;
	if (bb_asmlinkage_arch())
		return;
	bb_reg_params = REGPARM;
	if (first_time) {
		kdb_printf("  %s has memory parameters but no register "
			   "parameters.\n  Assuming it is a 'pass "
			   "through' function that does not refer to "
			   "its register\n  parameters and setting %d "
			   "register parameters\n",
			   bb_func_name, REGPARM);
		first_time = 0;
		return;
	}
	kdb_printf("  Assuming %s is 'pass through' with %d register "
		   "parameters\n",
		   bb_func_name, REGPARM);
}

static void
bb_pass2(void)
{
	int allow_missing;
	if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
		kdb_printf("%s: start\n", __FUNCTION__);

	kdb_di.fprintf_func = bb_dis_pass2;
	kdb_di.print_address_func = bb_printaddr_pass2;

	bb_reg_state = debug_kmalloc(sizeof(*bb_reg_state), GFP_ATOMIC);
	if (!bb_reg_state) {
		kdb_printf("\n\n%s: out of debug_kmalloc\n", __FUNCTION__);
		bb_giveup = 1;
		return;
	}
	bb_list[0]->changed = 1;

	/* If a block does not have all its input states available then it is
	 * possible for a register to initially appear to hold a known value,
	 * but when other inputs are available then it becomes a variable
	 * value.  The initial false state of "known" can generate false values
	 * for other registers and can even make it look like stack locations
	 * are being changed.
	 *
	 * To avoid these false positives, only process blocks which have all
	 * their inputs defined.  That gives a clean depth first traversal of
	 * the tree, except for loops.  If there are any loops, then start
	 * processing blocks with one missing input, then two missing inputs
	 * etc.
	 *
	 * Absolute worst case is we have to iterate over all the jmp entries,
	 * each iteration allowing one more missing input.  Any more loops than
	 * that is a bug.  Watch out for the corner case of 0 jmp entries.
	 */
	for (allow_missing = 0; allow_missing <= bb_jmp_count; ++allow_missing) {
		if (!bb_pass2_do_changed_blocks(allow_missing))
			break;
		if (bb_giveup)
			break;
	}
	if (allow_missing > bb_jmp_count) {
		kdb_printf("\n\n%s maxloops reached\n",
			   __FUNCTION__);
		bb_giveup = 1;
		return;
	}

	if (bb_memory_params && bb_reg_params)
		bb_reg_params = REGPARM;
	if (REGPARM &&
	    bb_memory_params &&
	    !bb_reg_params)
		bb_assume_pass_through();
	if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM)) {
		kdb_printf("%s: end bb_reg_params %d bb_memory_params %d\n",
			   __FUNCTION__, bb_reg_params, bb_memory_params);
		if (bb_exit_state) {
			kdb_printf("%s: bb_exit_state at " kdb_bfd_vma_fmt0 "\n",
				   __FUNCTION__, bb_exit_addr);
			bb_do_reg_state_print(bb_exit_state);
		}
	}
}

static void
bb_cleanup(void)
{
	int i;
	struct bb* bb;
	struct bb_reg_state *state;
	while (bb_count) {
		bb = bb_list[0];
		bb_delete(0);
	}
	debug_kfree(bb_list);
	bb_list = NULL;
	bb_count = bb_max = 0;
	for (i = 0; i < bb_jmp_count; ++i) {
		state = bb_jmp_list[i].state;
		if (state && --state->ref_count == 0)
			debug_kfree(state);
	}
	debug_kfree(bb_jmp_list);
	bb_jmp_list = NULL;
	bb_jmp_count = bb_jmp_max = 0;
	debug_kfree(bb_reg_state);
	bb_reg_state = NULL;
	bb_reg_state_max = 0;
	debug_kfree(bb_exit_state);
	bb_exit_state = NULL;
	bb_reg_params = bb_memory_params = 0;
	bb_giveup = 0;
}

static int
bb_spurious_global_label(const char *func_name)
{
	int i;
	for (i = 0; i < ARRAY_SIZE(bb_spurious); ++i) {
		if (strcmp(bb_spurious[i], func_name) == 0)
			return 1;
	}
	return 0;
}

/* Given the current actual register contents plus the exit state deduced from
 * a basic block analysis of the current function, rollback the actual register
 * contents to the values they had on entry to this function.
 */

static void
bb_actual_rollback(const struct kdb_activation_record *ar)
{
	int i, offset_address;
	struct bb_memory_contains *c;
	enum bb_reg_code reg;
	unsigned long address, osp = 0;
	struct bb_actual new[ARRAY_SIZE(bb_actual)];


	if (!bb_exit_state) {
		kdb_printf("%s: no bb_exit_state, cannot rollback\n",
			   __FUNCTION__);
		bb_giveup = 1;
		return;
	}
	memcpy(bb_reg_state, bb_exit_state, bb_reg_state_size(bb_exit_state));
	memset(new, 0, sizeof(new));

	/* The most important register for obtaining saved state is rsp so get
	 * its new value first.  Prefer rsp if it is valid, then other
	 * registers.  Saved values of rsp in memory are unusable without a
	 * register that points to memory.
	 */
	if (!bb_actual_valid(BBRG_RSP)) {
		kdb_printf("%s: no starting value for RSP, cannot rollback\n",
			   __FUNCTION__);
		bb_giveup = 1;
		return;
	}
	if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
		kdb_printf("%s: rsp " kdb_bfd_vma_fmt0,
			   __FUNCTION__, bb_actual_value(BBRG_RSP));
	i = BBRG_RSP;
	if (!bb_is_osp_defined(i)) {
	       	for (i = BBRG_RAX; i < BBRG_RAX + KDB_INT_REGISTERS; ++i) {
			if (bb_is_osp_defined(i) && bb_actual_valid(i))
				break;
		}
	}
	if (bb_is_osp_defined(i) && bb_actual_valid(i)) {
		osp = new[BBRG_RSP - BBRG_RAX].value =
		      bb_actual_value(i) - bb_reg_code_offset(i);
		new[BBRG_RSP - BBRG_RAX].valid = 1;
		if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
			kdb_printf(" -> osp " kdb_bfd_vma_fmt0 "\n", osp);
	} else {
		bb_actual_set_valid(BBRG_RSP, 0);
		if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
			kdb_printf(" -> undefined\n");
		kdb_printf("%s: no ending value for RSP, cannot rollback\n",
			   __FUNCTION__);
		bb_giveup = 1;
		return;
	}

	/* Now the other registers.  First look at register values that have
	 * been copied to other registers.
	 */
	for (i = BBRG_RAX; i < BBRG_RAX + KDB_INT_REGISTERS; ++i) {
		reg = bb_reg_code_value(i);
		if (bb_is_int_reg(reg)) {
			new[reg - BBRG_RAX] = bb_actual[i - BBRG_RAX];
			if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM)) {
				kdb_printf("%s: %s is in %s ",
					    __FUNCTION__,
					    bbrg_name[reg],
					    bbrg_name[i]);
				if (bb_actual_valid(i))
					kdb_printf(" -> " kdb_bfd_vma_fmt0 "\n",
						    bb_actual_value(i));
				else
					kdb_printf("(invalid)\n");
			}
		}
	}

	/* Finally register values that have been saved on stack */
	for (i = 0, c = bb_reg_state->memory;
	     i < bb_reg_state->mem_count;
	     ++i, ++c) {
		offset_address = c->offset_address;
		reg = c->value;
		if (!bb_is_int_reg(reg))
			continue;
		address = osp + offset_address;
		if (address < ar->stack.logical_start ||
		    address >= ar->stack.logical_end) {
			new[reg - BBRG_RAX].value = 0;
			new[reg - BBRG_RAX].valid = 0;
			if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
				kdb_printf("%s: %s -> undefined\n",
					   __FUNCTION__,
					   bbrg_name[reg]);
		} else {
			if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM)) {
				kdb_printf("%s: %s -> *(osp",
					   __FUNCTION__,
					   bbrg_name[reg]);
				KDB_DEBUG_BB_OFFSET_PRINTF(offset_address, "", " ");
				kdb_printf(kdb_bfd_vma_fmt0, address);
			}
			new[reg - BBRG_RAX].value = *(bfd_vma *)address;
			new[reg - BBRG_RAX].valid = 1;
			if (KDB_DEBUG(BB) | KDB_DEBUG(BB_SUMM))
				kdb_printf(") = " kdb_bfd_vma_fmt0 "\n",
					   new[reg - BBRG_RAX].value);
		}
	}

	memcpy(bb_actual, new, sizeof(bb_actual));
}

/* Return true if the current function is an interrupt handler */

static bool
bb_interrupt_handler(kdb_machreg_t rip)
{
	unsigned long disp8, disp32, target, addr = (unsigned long)rip;
	unsigned char code[5];
	int i;

	for (i = 0; i < ARRAY_SIZE(bb_hardware_handlers); ++i)
		if (strcmp(bb_func_name, bb_hardware_handlers[i]) == 0)
			return 1;

	/* Given the large number of interrupt handlers, it is easiest to look
	 * at the next instruction and see if it is a jmp to the common exit
	 * routines.
	 */
	if (kdb_getarea(code, addr) ||
	    kdb_getword(&disp32, addr+1, 4) ||
	    kdb_getword(&disp8, addr+1, 1))
		return 0;	/* not a valid code address */
	if (code[0] == 0xe9) {
		target = addr + (s32) disp32 + 5;	/* jmp disp32 */
		if (target == bb_ret_from_intr ||
		    target == bb_common_interrupt ||
		    target == bb_error_entry)
			return 1;
	}
	if (code[0] == 0xeb) {
		target = addr + (s8) disp8 + 2;		/* jmp disp8 */
		if (target == bb_ret_from_intr ||
		    target == bb_common_interrupt ||
		    target == bb_error_entry)
			return 1;
	}

	return 0;
}

/* Copy argument information that was deduced by the basic block analysis and
 * rollback into the kdb stack activation record.
 */

static void
bb_arguments(struct kdb_activation_record *ar)
{
	int i;
	enum bb_reg_code reg;
	kdb_machreg_t rsp;
	ar->args = bb_reg_params + bb_memory_params;
	bitmap_zero(ar->valid.bits, KDBA_MAXARGS);
	for (i = 0; i < bb_reg_params; ++i) {
		reg = bb_param_reg[i];
		if (bb_actual_valid(reg)) {
			ar->arg[i] = bb_actual_value(reg);
			set_bit(i, ar->valid.bits);
		}
	}
	if (!bb_actual_valid(BBRG_RSP))
		return;
	rsp = bb_actual_value(BBRG_RSP);
	for (i = bb_reg_params; i < ar->args; ++i) {
		rsp += KDB_WORD_SIZE;
		if (kdb_getarea(ar->arg[i], rsp) == 0)
			set_bit(i, ar->valid.bits);
	}
}

/* Given an exit address from a function, decompose the entire function into
 * basic blocks and determine the register state at the exit point.
 */

static void
kdb_bb(unsigned long exit)
{
	kdb_symtab_t symtab;
	if (!kdbnearsym(exit, &symtab)) {
		kdb_printf("%s: address " kdb_bfd_vma_fmt0 " not recognised\n",
			   __FUNCTION__, exit);
		bb_giveup = 1;
		return;
	}
	bb_exit_addr = exit;
	bb_mod_name = symtab.mod_name;
	bb_func_name = symtab.sym_name;
	bb_func_start = symtab.sym_start;
	bb_func_end = symtab.sym_end;
	/* Various global labels exist in the middle of assembler code and have
	 * a non-standard state.  Ignore these labels and use the start of the
	 * previous label instead.
	 */
	while (bb_spurious_global_label(symtab.sym_name)) {
		if (!kdbnearsym(symtab.sym_start - 1, &symtab))
			break;
		bb_func_start = symtab.sym_start;
	}
	bb_mod_name = symtab.mod_name;
	bb_func_name = symtab.sym_name;
	bb_func_start = symtab.sym_start;
	/* Ignore spurious labels past this point and use the next non-spurious
	 * label as the end point.
	 */
	if (kdbnearsym(bb_func_end, &symtab)) {
		while (bb_spurious_global_label(symtab.sym_name)) {
			bb_func_end = symtab.sym_end;
			if (!kdbnearsym(symtab.sym_end + 1, &symtab))
				break;
		}
	}
	bb_pass1();
	if (!bb_giveup)
		bb_pass2();
	if (bb_giveup)
		kdb_printf("%s: " kdb_bfd_vma_fmt0
			   " [%s]%s failed at " kdb_bfd_vma_fmt0 "\n\n",
			   __FUNCTION__, exit,
			   bb_mod_name, bb_func_name, bb_curr_addr);
}

static int
kdb_bb1(int argc, const char **argv)
{
	int diag;
	unsigned long addr;
	bb_cleanup();	/* in case previous command was interrupted */
	kdba_id_init(&kdb_di);
	if (argc != 1)
		return KDB_ARGCOUNT;
	if ((diag = kdbgetularg((char *)argv[1], &addr)))
		return diag;
	kdb_save_flags();
	kdb_flags |= KDB_DEBUG_FLAG_BB << KDB_DEBUG_FLAG_SHIFT;
	kdb_bb(addr);
	bb_cleanup();
	kdb_restore_flags();
	kdbnearsym_cleanup();
	return 0;
}

/* Run a basic block analysis on every function in the base kernel.  Used as a
 * global sanity check to find errors in the basic block code.
 */

static int
kdb_bb_all(int argc, const char **argv)
{
	loff_t pos = 0;
	const char *symname;
	unsigned long addr;
	int i, max_errors = 20;
	struct bb_name_state *r;
	kdb_printf("%s: build variables:"
		   " CCVERSION \"" __stringify(CCVERSION) "\""
#ifdef	CONFIG_X86_64
		   " CONFIG_X86_64"
#endif
#ifdef	CONFIG_4KSTACKS
		   " CONFIG_4KSTACKS"
#endif
#ifdef	CONFIG_PREEMPT
		   " CONFIG_PREEMPT"
#endif
#ifdef	CONFIG_VM86
		   " CONFIG_VM86"
#endif
#ifdef	CONFIG_FRAME_POINTER
		   " CONFIG_FRAME_POINTER"
#endif
#ifdef	CONFIG_TRACE_IRQFLAGS
		   " CONFIG_TRACE_IRQFLAGS"
#endif
#ifdef	CONFIG_HIBERNATION
		   " CONFIG_HIBERNATION"
#endif
#ifdef	CONFIG_KPROBES
		   " CONFIG_KPROBES"
#endif
#ifdef	CONFIG_KEXEC
		   " CONFIG_KEXEC"
#endif
#ifdef	CONFIG_MATH_EMULATION
		   " CONFIG_MATH_EMULATION"
#endif
#ifdef	CONFIG_XEN
		   " CONFIG_XEN"
#endif
#ifdef	CONFIG_DEBUG_INFO
		   " CONFIG_DEBUG_INFO"
#endif
#ifdef	NO_SIBLINGS
		   " NO_SIBLINGS"
#endif
		   " REGPARM=" __stringify(REGPARM)
		   "\n\n", __FUNCTION__);
	for (i = 0, r = bb_special_cases;
	     i < ARRAY_SIZE(bb_special_cases);
	     ++i, ++r) {
		if (!r->address)
			kdb_printf("%s: cannot find special_case name %s\n",
				   __FUNCTION__, r->name);
	}
	for (i = 0; i < ARRAY_SIZE(bb_spurious); ++i) {
		if (!kallsyms_lookup_name(bb_spurious[i]))
			kdb_printf("%s: cannot find spurious label %s\n",
				   __FUNCTION__, bb_spurious[i]);
	}
	while ((symname = kdb_walk_kallsyms(&pos))) {
		if (strcmp(symname, "_stext") == 0 ||
		    strcmp(symname, "stext") == 0)
			break;
	}
	if (!symname) {
		kdb_printf("%s: cannot find _stext\n", __FUNCTION__);
		return 0;
	}
	kdba_id_init(&kdb_di);
	i = 0;
	while ((symname = kdb_walk_kallsyms(&pos))) {
		if (strcmp(symname, "_etext") == 0)
			break;
		if (i++ % 100 == 0)
			kdb_printf(".");
		/* x86_64 has some 16 bit functions that appear between stext
		 * and _etext.  Skip them.
		 */
		if (strcmp(symname, "verify_cpu") == 0 ||
		    strcmp(symname, "verify_cpu_noamd") == 0 ||
		    strcmp(symname, "verify_cpu_sse_test") == 0 ||
		    strcmp(symname, "verify_cpu_no_longmode") == 0 ||
		    strcmp(symname, "verify_cpu_sse_ok") == 0 ||
		    strcmp(symname, "mode_seta") == 0 ||
		    strcmp(symname, "bad_address") == 0 ||
		    strcmp(symname, "wakeup_code") == 0 ||
		    strcmp(symname, "wakeup_code_start") == 0 ||
		    strcmp(symname, "wakeup_start") == 0 ||
		    strcmp(symname, "wakeup_32_vector") == 0 ||
		    strcmp(symname, "wakeup_32") == 0 ||
		    strcmp(symname, "wakeup_long64_vector") == 0 ||
		    strcmp(symname, "wakeup_long64") == 0 ||
		    strcmp(symname, "gdta") == 0 ||
		    strcmp(symname, "idt_48a") == 0 ||
		    strcmp(symname, "gdt_48a") == 0 ||
		    strcmp(symname, "bogus_real_magic") == 0 ||
		    strcmp(symname, "bogus_64_magic") == 0 ||
		    strcmp(symname, "no_longmode") == 0 ||
		    strcmp(symname, "mode_set") == 0 ||
		    strcmp(symname, "mode_seta") == 0 ||
		    strcmp(symname, "setbada") == 0 ||
		    strcmp(symname, "check_vesa") == 0 ||
		    strcmp(symname, "check_vesaa") == 0 ||
		    strcmp(symname, "_setbada") == 0 ||
		    strcmp(symname, "wakeup_stack_begin") == 0 ||
		    strcmp(symname, "wakeup_stack") == 0 ||
		    strcmp(symname, "wakeup_level4_pgt") == 0 ||
		    strcmp(symname, "acpi_copy_wakeup_routine") == 0 ||
		    strcmp(symname, "wakeup_end") == 0 ||
		    strcmp(symname, "do_suspend_lowlevel_s4bios") == 0 ||
		    strcmp(symname, "do_suspend_lowlevel") == 0 ||
		    strcmp(symname, "wakeup_pmode_return") == 0 ||
		    strcmp(symname, "restore_registers") == 0)
			continue;
		/* __kprobes_text_end contains branches to the middle of code,
		 * with undefined states.
		 */
		if (strcmp(symname, "__kprobes_text_end") == 0)
			continue;
		/* Data in the middle of the text segment :( */
		if (strcmp(symname, "level2_kernel_pgt") == 0 ||
		    strcmp(symname, "level3_kernel_pgt") == 0)
			continue;
		if (bb_spurious_global_label(symname))
			continue;
		if ((addr = kallsyms_lookup_name(symname)) == 0)
			continue;
		// kdb_printf("BB " kdb_bfd_vma_fmt0 " %s\n", addr, symname);
		bb_cleanup();	/* in case previous command was interrupted */
		kdbnearsym_cleanup();
		kdb_bb(addr);
		touch_nmi_watchdog();
		if (bb_giveup) {
			if (max_errors-- == 0) {
				kdb_printf("%s: max_errors reached, giving up\n",
					   __FUNCTION__);
				break;
			} else {
				bb_giveup = 0;
			}
		}
	}
	kdb_printf("\n");
	bb_cleanup();
	kdbnearsym_cleanup();
	return 0;
}

/*
 *=============================================================================
 *
 * Everything above this line is doing basic block analysis, function by
 * function.  Everything below this line uses the basic block data to do a
 * complete backtrace over all functions that are used by a process.
 *
 *=============================================================================
 */


/*============================================================================*/
/*                                                                            */
/* Most of the backtrace code and data is common to x86_64 and i386.  This    */
/* large ifdef contains all of the differences between the two architectures. */
/*                                                                            */
/* Make sure you update the correct section of this ifdef.                    */
/*                                                                            */
/*============================================================================*/
#define XCS "cs"
#define RSP "sp"
#define RIP "ip"
#define ARCH_RSP sp
#define ARCH_RIP ip

#ifdef	CONFIG_X86_64

#define ARCH_NORMAL_PADDING (16 * 8)

/* x86_64 has multiple alternate stacks, with different sizes and different
 * offsets to get the link from one stack to the next.  Some of the stacks are
 * referenced via cpu_pda, some via per_cpu orig_ist.  Debug events can even
 * have multiple nested stacks within the single physical stack, each nested
 * stack has its own link and some of those links are wrong.
 *
 * Consistent it's not!
 *
 * Do not assume that these stacks are aligned on their size.
 */
#define INTERRUPT_STACK (N_EXCEPTION_STACKS + 1)
void
kdba_get_stack_info_alternate(kdb_machreg_t addr, int cpu,
			      struct kdb_activation_record *ar)
{
	static struct {
		const char *id;
		unsigned int total_size;
		unsigned int nested_size;
		unsigned int next;
	} *sdp, stack_data[] = {
		[STACKFAULT_STACK - 1] =  { "stackfault",    EXCEPTION_STKSZ, EXCEPTION_STKSZ, EXCEPTION_STKSZ - 2*sizeof(void *) },
		[DOUBLEFAULT_STACK - 1] = { "doublefault",   EXCEPTION_STKSZ, EXCEPTION_STKSZ, EXCEPTION_STKSZ - 2*sizeof(void *) },
		[NMI_STACK - 1] =         { "nmi",           EXCEPTION_STKSZ, EXCEPTION_STKSZ, EXCEPTION_STKSZ - 2*sizeof(void *) },
		[DEBUG_STACK - 1] =       { "debug",         DEBUG_STKSZ,     EXCEPTION_STKSZ, EXCEPTION_STKSZ - 2*sizeof(void *) },
		[MCE_STACK - 1] =         { "machine check", EXCEPTION_STKSZ, EXCEPTION_STKSZ, EXCEPTION_STKSZ - 2*sizeof(void *) },
		[INTERRUPT_STACK - 1] =   { "interrupt",     IRQSTACKSIZE,    IRQSTACKSIZE,    IRQSTACKSIZE    -   sizeof(void *) },
	};
	unsigned long total_start = 0, total_size, total_end;
	int sd, found = 0;
	extern unsigned long kdba_orig_ist(int, int);

	for (sd = 0, sdp = stack_data;
	     sd < ARRAY_SIZE(stack_data);
	     ++sd, ++sdp) {
		total_size = sdp->total_size;
		if (!total_size)
			continue;	/* in case stack_data[] has any holes */
		if (cpu < 0) {
			/* Arbitrary address which can be on any cpu, see if it
			 * falls within any of the alternate stacks
			 */
			int c;
			for_each_online_cpu(c) {
				if (sd == INTERRUPT_STACK - 1)
					total_end = (unsigned long)cpu_pda(c)->irqstackptr;
				else
					total_end = per_cpu(orig_ist, c).ist[sd];
				total_start = total_end - total_size;
				if (addr >= total_start && addr < total_end) {
					found = 1;
					cpu = c;
					break;
				}
			}
			if (!found)
				continue;
		}
		/* Only check the supplied or found cpu */
		if (sd == INTERRUPT_STACK - 1)
			total_end = (unsigned long)cpu_pda(cpu)->irqstackptr;
		else
			total_end = per_cpu(orig_ist, cpu).ist[sd];
		total_start = total_end - total_size;
		if (addr >= total_start && addr < total_end) {
			found = 1;
			break;
		}
	}
	if (!found)
		return;
	/* find which nested stack the address is in */
	while (addr > total_start + sdp->nested_size)
		total_start += sdp->nested_size;
	ar->stack.physical_start = total_start;
	ar->stack.physical_end = total_start + sdp->nested_size;
	ar->stack.logical_start = total_start;
	ar->stack.logical_end = total_start + sdp->next;
	ar->stack.next = *(unsigned long *)ar->stack.logical_end;
	ar->stack.id = sdp->id;

	/* Nasty: when switching to the interrupt stack, the stack state of the
	 * caller is split over two stacks, the original stack and the
	 * interrupt stack.  One word (the previous frame pointer) is stored on
	 * the interrupt stack, the rest of the interrupt data is in the old
	 * frame.  To make the interrupted stack state look as though it is
	 * contiguous, copy the missing word from the interrupt stack to the
	 * original stack and adjust the new stack pointer accordingly.
	 */

	if (sd == INTERRUPT_STACK - 1) {
		*(unsigned long *)(ar->stack.next - KDB_WORD_SIZE) =
			ar->stack.next;
		ar->stack.next -= KDB_WORD_SIZE;
	}
}

/* rip is not in the thread struct for x86_64.  We know that the stack value
 * was saved in schedule near the label thread_return.  Setting rip to
 * thread_return lets the stack trace find that we are in schedule and
 * correctly decode its prologue.
 */

static kdb_machreg_t
kdba_bt_stack_rip(const struct task_struct *p)
{
	return bb_thread_return;
}

#else	/* !CONFIG_X86_64 */

#define ARCH_NORMAL_PADDING (19 * 4)

#ifdef	CONFIG_4KSTACKS
static struct thread_info **kdba_hardirq_ctx, **kdba_softirq_ctx;
#endif	/* CONFIG_4KSTACKS */

/* On a 4K stack kernel, hardirq_ctx and softirq_ctx are [NR_CPUS] arrays.  The
 * first element of each per-cpu stack is a struct thread_info.
 */
void
kdba_get_stack_info_alternate(kdb_machreg_t addr, int cpu,
			      struct kdb_activation_record *ar)
{
#ifdef	CONFIG_4KSTACKS
	struct thread_info *tinfo;
	tinfo = (struct thread_info *)(addr & -THREAD_SIZE);
	if (cpu < 0) {
		/* Arbitrary address, see if it falls within any of the irq
		 * stacks
		 */
		int found = 0;
		for_each_online_cpu(cpu) {
			if (tinfo == kdba_hardirq_ctx[cpu] ||
			    tinfo == kdba_softirq_ctx[cpu]) {
				found = 1;
				break;
			}
		}
		if (!found)
			return;
	}
	if (tinfo == kdba_hardirq_ctx[cpu] ||
	    tinfo == kdba_softirq_ctx[cpu]) {
		ar->stack.physical_start = (kdb_machreg_t)tinfo;
		ar->stack.physical_end = ar->stack.physical_start + THREAD_SIZE;
		ar->stack.logical_start = ar->stack.physical_start +
					  sizeof(struct thread_info);
		ar->stack.logical_end = ar->stack.physical_end;
		ar->stack.next = tinfo->previous_esp;
		if (tinfo == kdba_hardirq_ctx[cpu])
			ar->stack.id = "hardirq_ctx";
		else
			ar->stack.id = "softirq_ctx";
	}
#endif	/* CONFIG_4KSTACKS */
}

/* rip is in the thread struct for i386 */

static kdb_machreg_t
kdba_bt_stack_rip(const struct task_struct *p)
{
	return p->thread.ip;
}

#endif	/* CONFIG_X86_64 */

/* Given an address which claims to be on a stack, an optional cpu number and
 * an optional task address, get information about the stack.
 *
 * t == NULL, cpu < 0 indicates an arbitrary stack address with no associated
 * struct task, the address can be in an alternate stack or any task's normal
 * stack.
 *
 * t != NULL, cpu >= 0 indicates a running task, the address can be in an
 * alternate stack or that task's normal stack.
 *
 * t != NULL, cpu < 0 indicates a blocked task, the address can only be in that
 * task's normal stack.
 *
 * t == NULL, cpu >= 0 is not a valid combination.
 */

static void
kdba_get_stack_info(kdb_machreg_t rsp, int cpu,
		    struct kdb_activation_record *ar,
		    const struct task_struct *t)
{
	struct thread_info *tinfo;
	struct task_struct *g, *p;
	memset(&ar->stack, 0, sizeof(ar->stack));
	if (KDB_DEBUG(ARA))
		kdb_printf("%s: " RSP "=0x%lx cpu=%d task=%p\n",
			   __FUNCTION__, rsp, cpu, t);
	if (t == NULL || cpu >= 0) {
		kdba_get_stack_info_alternate(rsp, cpu, ar);
		if (ar->stack.logical_start)
			goto out;
	}
	rsp &= -THREAD_SIZE;
	tinfo = (struct thread_info *)rsp;
	if (t == NULL) {
		/* Arbitrary stack address without an associated task, see if
		 * it falls within any normal process stack, including the idle
		 * tasks.
		 */
		kdb_do_each_thread(g, p) {
			if (tinfo == task_thread_info(p)) {
				t = p;
				goto found;
			}
		} kdb_while_each_thread(g, p);
		for_each_online_cpu(cpu) {
			p = idle_task(cpu);
			if (tinfo == task_thread_info(p)) {
				t = p;
				goto found;
			}
		}
	found:
		if (KDB_DEBUG(ARA))
			kdb_printf("%s: found task %p\n", __FUNCTION__, t);
	} else if (cpu >= 0) {
		/* running task */
		struct kdb_running_process *krp = kdb_running_process + cpu;
		if (krp->p != t || tinfo != task_thread_info(t))
			t = NULL;
		if (KDB_DEBUG(ARA))
			kdb_printf("%s: running task %p\n", __FUNCTION__, t);
	} else {
		/* blocked task */
		if (tinfo != task_thread_info(t))
			t = NULL;
		if (KDB_DEBUG(ARA))
			kdb_printf("%s: blocked task %p\n", __FUNCTION__, t);
	}
	if (t) {
		ar->stack.physical_start = rsp;
		ar->stack.physical_end = rsp + THREAD_SIZE;
		ar->stack.logical_start = rsp + sizeof(struct thread_info);
		ar->stack.logical_end = ar->stack.physical_end - ARCH_NORMAL_PADDING;
		ar->stack.next = 0;
		ar->stack.id = "normal";
	}
out:
	if (ar->stack.physical_start && KDB_DEBUG(ARA)) {
		kdb_printf("%s: ar->stack\n", __FUNCTION__);
		kdb_printf("    physical_start=0x%lx\n", ar->stack.physical_start);
		kdb_printf("    physical_end=0x%lx\n", ar->stack.physical_end);
		kdb_printf("    logical_start=0x%lx\n", ar->stack.logical_start);
		kdb_printf("    logical_end=0x%lx\n", ar->stack.logical_end);
		kdb_printf("    next=0x%lx\n", ar->stack.next);
		kdb_printf("    id=%s\n", ar->stack.id);
		kdb_printf("    set MDCOUNT %ld\n",
			   (ar->stack.physical_end - ar->stack.physical_start) /
			   KDB_WORD_SIZE);
		kdb_printf("    mds " kdb_machreg_fmt0 "\n",
			   ar->stack.physical_start);
	}
}

static void
bt_print_one(kdb_machreg_t rip, kdb_machreg_t rsp,
	      const struct kdb_activation_record *ar,
	      const kdb_symtab_t *symtab, int argcount)
{
	int btsymarg = 0;
	int nosect = 0;

	kdbgetintenv("BTSYMARG", &btsymarg);
	kdbgetintenv("NOSECT", &nosect);

	kdb_printf(kdb_machreg_fmt0, rsp);
	kdb_symbol_print(rip, symtab,
			 KDB_SP_SPACEB|KDB_SP_VALUE);
	if (argcount && ar->args) {
		int i, argc = ar->args;
		kdb_printf(" (");
		if (argc > argcount)
			argc = argcount;
		for (i = 0; i < argc; i++) {
			if (i)
				kdb_printf(", ");
			if (test_bit(i, ar->valid.bits))
				kdb_printf("0x%lx", ar->arg[i]);
			else
				kdb_printf("invalid");
		}
		kdb_printf(")");
	}
	kdb_printf("\n");
	if (symtab->sym_name) {
		if (!nosect) {
			kdb_printf("                               %s",
				   symtab->mod_name);
			if (symtab->sec_name && symtab->sec_start)
				kdb_printf(" 0x%lx 0x%lx",
					   symtab->sec_start, symtab->sec_end);
			kdb_printf(" 0x%lx 0x%lx\n",
				   symtab->sym_start, symtab->sym_end);
		}
	}
	if (argcount && ar->args && btsymarg) {
		int i, argc = ar->args;
		kdb_symtab_t arg_symtab;
		for (i = 0; i < argc; i++) {
			kdb_machreg_t arg = ar->arg[i];
			if (test_bit(i, ar->valid.bits) &&
			    kdbnearsym(arg, &arg_symtab)) {
				kdb_printf("                       ARG %2d ", i);
				kdb_symbol_print(arg, &arg_symtab,
						 KDB_SP_DEFAULT|KDB_SP_NEWLINE);
			}
		}
	}
}

static void
kdba_bt_new_stack(struct kdb_activation_record *ar, kdb_machreg_t *rsp,
		   int *count, int *suppress)
{
	/* Nasty: common_interrupt builds a partial pt_regs, with r15 through
	 * rbx not being filled in.  It passes struct pt_regs* to do_IRQ (in
	 * rdi) but the stack pointer is not adjusted to account for r15
	 * through rbx.  This has two effects :-
	 *
	 * (1) struct pt_regs on an external interrupt actually overlaps with
	 *     the local stack area used by do_IRQ.  Not only are r15-rbx
	 *     undefined, the area that claims to hold their values can even
	 *     change as the irq is processed.
	 *
	 * (2) The back stack pointer saved for the new frame is not pointing
	 *     at pt_regs, it is pointing at rbx within the pt_regs passed to
	 *     do_IRQ.
	 *
	 * There is nothing that I can do about (1) but I have to fix (2)
	 * because kdb backtrace looks for the "start" address of pt_regs as it
	 * walks back through the stacks.  When switching from the interrupt
	 * stack to another stack, we have to assume that pt_regs has been
	 * seen and turn off backtrace supression.
	 */
	int probable_pt_regs = strcmp(ar->stack.id, "interrupt") == 0;
	*rsp = ar->stack.next;
	if (KDB_DEBUG(ARA))
		kdb_printf("new " RSP "=" kdb_machreg_fmt0 "\n", *rsp);
	bb_actual_set_value(BBRG_RSP, *rsp);
	kdba_get_stack_info(*rsp, -1, ar, NULL);
	if (!ar->stack.physical_start) {
		kdb_printf("+++ Cannot resolve next stack\n");
	} else if (!*suppress) {
		kdb_printf(" ======================= <%s>\n",
			   ar->stack.id);
		++*count;
	}
	if (probable_pt_regs)
		*suppress = 0;
}

/*
 * kdba_bt_stack
 *
 * Inputs:
 *	addr	Address provided to 'bt' command, if any.
 *	argcount
 *	p	Pointer to task for 'btp' command.
 * Outputs:
 *	None.
 * Returns:
 *	zero for success, a kdb diagnostic if error
 * Locking:
 *	none.
 * Remarks:
 *	Ultimately all the bt* commands come through this routine.  If
 *	old_style is 0 then it uses the basic block analysis to get an accurate
 *	backtrace with arguments, otherwise it falls back to the old method of
 *	printing anything on stack that looks like a kernel address.
 *
 *	Allowing for the stack data pushed by the hardware is tricky.  We
 *	deduce the presence of hardware pushed data by looking for interrupt
 *	handlers, either by name or by the code that they contain.  This
 *	information must be applied to the next function up the stack, because
 *	the hardware data is above the saved rip for the interrupted (next)
 *	function.
 *
 *	To make things worse, the amount of data pushed is arch specific and
 *	may depend on the rsp for the next function, not the current function.
 *	The number of bytes pushed by hardware cannot be calculated until we
 *	are actually processing the stack for the interrupted function and have
 *	its rsp.
 *
 *	It is also possible for an interrupt to occur in user space and for the
 *	interrupt handler to also be interrupted.  Check the code selector
 *	whenever the previous function is an interrupt handler and stop
 *	backtracing if the interrupt was not in kernel space.
 */

static int
kdba_bt_stack(kdb_machreg_t addr, int argcount, const struct task_struct *p,
	       int old_style)
{
	struct kdb_activation_record ar;
	kdb_machreg_t rip = 0, rsp = 0, prev_rsp, cs;
	kdb_symtab_t symtab;
	int rip_at_rsp = 0, count = 0, btsp = 0, suppress,
	    interrupt_handler = 0, prev_interrupt_handler = 0, hardware_pushed,
	    prev_noret = 0;
	struct pt_regs *regs = NULL;

	kdbgetintenv("BTSP", &btsp);
	suppress = !btsp;
	memset(&ar, 0, sizeof(ar));
	if (old_style)
		kdb_printf("Using old style backtrace, unreliable with no arguments\n");

	/*
	 * The caller may have supplied an address at which the stack traceback
	 * operation should begin.  This address is assumed by this code to
	 * point to a return address on the stack to be traced back.
	 *
	 * Warning: type in the wrong address and you will get garbage in the
	 * backtrace.
	 */
	if (addr) {
		rsp = addr;
		kdb_getword(&rip, rsp, sizeof(rip));
		rip_at_rsp = 1;
		suppress = 0;
		kdba_get_stack_info(rsp, -1, &ar, NULL);
	} else {
		if (task_curr(p)) {
			struct kdb_running_process *krp =
			    kdb_running_process + task_cpu(p);
			kdb_machreg_t cs;
			regs = krp->regs;
			if (krp->seqno &&
			    krp->p == p &&
			    krp->seqno >= kdb_seqno - 1 &&
			    !KDB_NULL_REGS(regs)) {
				/* valid saved state, continue processing */
			} else {
				kdb_printf
				    ("Process did not save state, cannot backtrace\n");
				kdb_ps1(p);
				return 0;
			}
			kdba_getregcontents(XCS, regs, &cs);
			if ((cs & 0xffff) != __KERNEL_CS) {
				kdb_printf("Stack is not in kernel space, backtrace not available\n");
				return 0;
			}
			rip = krp->arch.ARCH_RIP;
			rsp = krp->arch.ARCH_RSP;
			kdba_get_stack_info(rsp, kdb_process_cpu(p), &ar, p);
		} else {
			/* Not on cpu, assume blocked.  Blocked tasks do not
			 * have pt_regs.  p->thread contains some data, alas
			 * what it contains differs between i386 and x86_64.
			 */
			rip = kdba_bt_stack_rip(p);
			rsp = p->thread.sp;
			suppress = 0;
			kdba_get_stack_info(rsp, -1, &ar, p);
		}
	}
	if (!ar.stack.physical_start) {
		kdb_printf(RSP "=0x%lx is not in a valid kernel stack, backtrace not available\n",
			   rsp);
		return 0;
	}
	memset(&bb_actual, 0, sizeof(bb_actual));
	bb_actual_set_value(BBRG_RSP, rsp);
	bb_actual_set_valid(BBRG_RSP, 1);

	kdb_printf(RSP "%*s" RIP "%*sFunction (args)\n",
		   2*KDB_WORD_SIZE, " ",
		   2*KDB_WORD_SIZE, " ");
	if (ar.stack.next && !suppress)
		kdb_printf(" ======================= <%s>\n",
			   ar.stack.id);

	bb_cleanup();
	/* Run through all the stacks */
	while (ar.stack.physical_start) {
		if (rip_at_rsp) {
			rip = *(kdb_machreg_t *)rsp;
			/* I wish that gcc was fixed to include a nop
			 * instruction after ATTRIB_NORET functions.  The lack
			 * of a nop means that the return address points to the
			 * start of next function, so fudge it to point to one
			 * byte previous.
			 *
			 * No, we cannot just decrement all rip values.
			 * Sometimes an rip legally points to the start of a
			 * function, e.g. interrupted code or hand crafted
			 * assembler.
			 */
			if (prev_noret) {
				kdbnearsym(rip, &symtab);
				if (rip == symtab.sym_start) {
					--rip;
					if (KDB_DEBUG(ARA))
						kdb_printf("\tprev_noret, " RIP
							   "=0x%lx\n", rip);
				}
			}
		}
		kdbnearsym(rip, &symtab);
		if (old_style) {
		       	if (__kernel_text_address(rip) && !suppress) {
				bt_print_one(rip, rsp, &ar, &symtab, 0);
				++count;
			}
			if (rsp == (unsigned long)regs) {
				if (ar.stack.next && suppress)
					kdb_printf(" ======================= <%s>\n",
						   ar.stack.id);
				++count;
				suppress = 0;
			}
			rsp += sizeof(rip);
			rip_at_rsp = 1;
			if (rsp >= ar.stack.logical_end) {
				if (!ar.stack.next)
					break;
				kdba_bt_new_stack(&ar, &rsp, &count, &suppress);
				rip_at_rsp = 0;
				continue;
			}
		} else {
			/* Start each analysis with no dynamic data from the
			 * previous kdb_bb() run.
			 */
			bb_cleanup();
			kdb_bb(rip);
			if (bb_giveup)
				break;
			prev_interrupt_handler = interrupt_handler;
			interrupt_handler = bb_interrupt_handler(rip);
			prev_rsp = rsp;
			if (rip_at_rsp) {
				if (prev_interrupt_handler) {
					cs = *((kdb_machreg_t *)rsp + 1) & 0xffff;
					hardware_pushed =
						bb_hardware_pushed_arch(rsp, &ar);
				} else {
					cs = __KERNEL_CS;
					hardware_pushed = 0;
				}
				rsp += sizeof(rip) + hardware_pushed;
				if (KDB_DEBUG(ARA))
					kdb_printf("%s: " RSP " "
						   kdb_machreg_fmt0
						   " -> " kdb_machreg_fmt0
						   " hardware_pushed %d"
						   " prev_interrupt_handler %d"
						   " cs 0x%lx\n",
						   __FUNCTION__,
						   prev_rsp,
						   rsp,
						   hardware_pushed,
						   prev_interrupt_handler,
						   cs);
				if (rsp >= ar.stack.logical_end &&
				    ar.stack.next) {
					kdba_bt_new_stack(&ar, &rsp, &count,
							   &suppress);
					rip_at_rsp = 0;
					continue;
				}
				bb_actual_set_value(BBRG_RSP, rsp);
			} else {
				cs = __KERNEL_CS;
			}
			rip_at_rsp = 1;
			bb_actual_rollback(&ar);
			if (bb_giveup)
				break;
			if (bb_actual_value(BBRG_RSP) < rsp) {
				kdb_printf("%s: " RSP " is going backwards, "
					   kdb_machreg_fmt0 " -> "
					   kdb_machreg_fmt0 "\n",
					   __FUNCTION__,
					   rsp,
					   bb_actual_value(BBRG_RSP));
				bb_giveup = 1;
				break;
			}
			bb_arguments(&ar);
			if (!suppress) {
				bt_print_one(rip, prev_rsp, &ar, &symtab, argcount);
				++count;
			}
			/* Functions that terminate the backtrace */
			if (strcmp(bb_func_name, "cpu_idle") == 0 ||
			    strcmp(bb_func_name, "child_rip") == 0)
				break;
			if (rsp >= ar.stack.logical_end &&
			    !ar.stack.next)
				break;
			if (rsp <= (unsigned long)regs &&
			    bb_actual_value(BBRG_RSP) > (unsigned long)regs) {
				if (ar.stack.next && suppress)
					kdb_printf(" ======================= <%s>\n",
						   ar.stack.id);
				++count;
				suppress = 0;
			}
			if (cs != __KERNEL_CS) {
				kdb_printf("Reached user space\n");
				break;
			}
			rsp = bb_actual_value(BBRG_RSP);
		}
		prev_noret = bb_noret(bb_func_name);
		if (count > 200)
			break;
	}
	if (bb_giveup)
		return 1;
	bb_cleanup();
	kdbnearsym_cleanup();

	if (count > 200) {
		kdb_printf("bt truncated, count limit reached\n");
		return 1;
	} else if (suppress) {
		kdb_printf
		    ("bt did not find pt_regs - no trace produced.  Suggest 'set BTSP 1'\n");
		return 1;
	}

	return 0;
}

/*
 * kdba_bt_address
 *
 *	Do a backtrace starting at a specified stack address.  Use this if the
 *	heuristics get the stack decode wrong.
 *
 * Inputs:
 *	addr	Address provided to 'bt' command.
 *	argcount
 * Outputs:
 *	None.
 * Returns:
 *	zero for success, a kdb diagnostic if error
 * Locking:
 *	none.
 * Remarks:
 *	mds %rsp comes in handy when examining the stack to do a manual
 *	traceback.
 */

int kdba_bt_address(kdb_machreg_t addr, int argcount)
{
	int ret;
	kdba_id_init(&kdb_di);			/* kdb_bb needs this done once */
	ret = kdba_bt_stack(addr, argcount, NULL, 0);
	if (ret == 1)
		ret = kdba_bt_stack(addr, argcount, NULL, 1);
	return ret;
}

/*
 * kdba_bt_process
 *
 *	Do a backtrace for a specified process.
 *
 * Inputs:
 *	p	Struct task pointer extracted by 'bt' command.
 *	argcount
 * Outputs:
 *	None.
 * Returns:
 *	zero for success, a kdb diagnostic if error
 * Locking:
 *	none.
 */

int kdba_bt_process(const struct task_struct *p, int argcount)
{
	int ret;
	kdba_id_init(&kdb_di);			/* kdb_bb needs this done once */
	ret = kdba_bt_stack(0, argcount, p, 0);
	if (ret == 1)
		ret = kdba_bt_stack(0, argcount, p, 1);
	return ret;
}

static int __init kdba_bt_x86_init(void)
{
	int i, c, cp = -1;
	struct bb_name_state *r;

	kdb_register_repeat("bb1", kdb_bb1, "<vaddr>",	"Analyse one basic block", 0, KDB_REPEAT_NONE);
	kdb_register_repeat("bb_all", kdb_bb_all, "",	"Backtrace check on all built in functions", 0, KDB_REPEAT_NONE);

	/* Split the opcode usage table by the first letter of each set of
	 * opcodes, for faster mapping of opcode to its operand usage.
	 */
	for (i = 0; i < ARRAY_SIZE(bb_opcode_usage_all); ++i) {
		c = bb_opcode_usage_all[i].opcode[0] - 'a';
		if (c != cp) {
			cp = c;
			bb_opcode_usage[c].opcode = bb_opcode_usage_all + i;
		}
		++bb_opcode_usage[c].size;
	}

	bb_common_interrupt = kallsyms_lookup_name("common_interrupt");
	bb_error_entry = kallsyms_lookup_name("error_entry");
	bb_ret_from_intr = kallsyms_lookup_name("ret_from_intr");
	bb_thread_return = kallsyms_lookup_name("thread_return");
	bb_sync_regs = kallsyms_lookup_name("sync_regs");
	bb_save_v86_state = kallsyms_lookup_name("save_v86_state");
	bb__sched_text_start = kallsyms_lookup_name("__sched_text_start");
	bb__sched_text_end = kallsyms_lookup_name("__sched_text_end");
	for (i = 0, r = bb_special_cases;
	     i < ARRAY_SIZE(bb_special_cases);
	     ++i, ++r) {
		r->address = kallsyms_lookup_name(r->name);
	}

#ifdef	CONFIG_4KSTACKS
	kdba_hardirq_ctx = (struct thread_info **)kallsyms_lookup_name("hardirq_ctx");
	kdba_softirq_ctx = (struct thread_info **)kallsyms_lookup_name("softirq_ctx");
#endif	/* CONFIG_4KSTACKS */

	return 0;
}

static void __exit kdba_bt_x86_exit(void)
{
	kdb_unregister("bb1");
	kdb_unregister("bb_all");
}

module_init(kdba_bt_x86_init)
module_exit(kdba_bt_x86_exit)