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

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

Revision 1.9, Tue Feb 28 14:25:03 2006 UTC (11 years, 7 months ago) by nathans.longdrop.melbourne.sgi.com
Branch: MAIN
Changes since 1.8: +0 -0 lines

Merge up to 2.6.16-rc5.
Merge of 2.6.x-xfs-melb:linux:25320a by kenmcd.

/*
 * Kernel Debugger Architecture Dependent Instruction Disassembly
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (c) 1999-2004 Silicon Graphics, Inc.  All Rights Reserved.
 */

#include <stdarg.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/kdb.h>
#include <linux/kdbprivate.h>

#define KDBA_PRINTBUF_LEN	64	/* buffer len to print a single instr */
#define KDBA_READBUFFER_LEN	256	/* buffer for BFD disassembler */

#define BUNDLE_MULTIPLIER	3	/* how many instr/bundle */
#define BUNDLE_SIZE		16	/* how many bytes/bundle */
#define KDBA_DEFAULT_IDLEN	3	/* default number of bundles to disassemble */

/*
 * kdba_dis_getsym
 *
 *	Get a symbol for the disassembler.
 *
 * Parameters:
 *	addr	Address for which to get symbol
 *	dip	Pointer to disassemble_info
 * Returns:
 *	0
 * Locking:
 * Remarks:
 *	Not used for kdb.
 */

/* ARGSUSED */
static int
kdba_dis_getsym(bfd_vma addr, disassemble_info *dip)
{

	return 0;
}

/*
 * kdba_printaddress
 *
 *	Print (symbolically) an address.
 *
 * Parameters:
 *	addr	Address for which to get symbol
 *	dip	Pointer to disassemble_info
 *	flag	True if a ":<tab>" sequence should follow the address
 * Returns:
 *	0
 * Locking:
 * Remarks:
 *
 */

/* ARGSUSED */
static void
kdba_printaddress(kdb_machreg_t addr, disassemble_info *dip, int flag)
{
	kdb_symtab_t symtab;
	int spaces = 5;
	unsigned int offset;
	int slot;

	/* Some code prints slot number, some prints "byte" offset
	 * from start of bundle.  Standardise on "byte" offset.
	 */
	slot = addr & 0x0f;
	if (slot < 3)
		slot *= 6;
	addr = (addr & ~0x0f) + slot;

	/*
	 * Print a symbol name or address as necessary.
	 */
	dip->fprintf_func(dip->stream, "0x%0*lx ", 2*sizeof(addr), addr);
	kdbnearsym(addr, &symtab);
	if (symtab.sym_name) {
		/* Do not use kdb_symbol_print here, it always does
		 * kdb_printf but we want dip->fprintf_func.
		 */
		dip->fprintf_func(dip->stream, "%s", symtab.sym_name);
		if ((offset = addr - symtab.sym_start) == 0) {
			spaces += 4;
		}
		else {
			unsigned int o = offset;
			while (o >>= 4)
				--spaces;
			dip->fprintf_func(dip->stream, "+0x%x", offset);
		}
	}

	if (flag) {
		if (spaces < 1) {
			spaces = 1;
		}
		dip->fprintf_func(dip->stream, ":%*s", spaces, " ");
	}
}

/*
 * kdba_dis_printaddr
 *
 *	Print (symbolically) an address.  Called by GNU disassembly
 *	code via disassemble_info structure.
 *
 * Parameters:
 *	addr	Address for which to get symbol
 *	dip	Pointer to disassemble_info
 * Returns:
 *	0
 * Locking:
 * Remarks:
 *	This function will never append ":<tab>" to the printed
 *	symbolic address.
 */

static void
kdba_dis_printaddr(bfd_vma addr, disassemble_info *dip)
{
	kdba_printaddress(addr, dip, 0);
}

/*
 * kdba_dis_getmem
 *
 *	Fetch 'length' bytes from 'addr' into 'buf'.
 *
 * Parameters:
 *	addr	Address for which to get symbol
 *	buf	Address of buffer to fill with bytes from 'addr'
 *	length	Number of bytes to fetch
 *	dip	Pointer to disassemble_info
 * Returns:
 *	0
 * Locking:
 * Remarks:
 *
 */

/* ARGSUSED */
static int
kdba_dis_getmem(bfd_vma addr, bfd_byte *buf, unsigned int length, disassemble_info *dip)
{
	return kdb_getarea_size(buf, addr, length);
}

/*
 * kdba_id_parsemode
 *
 * 	Parse IDMODE environment variable string and
 *	set appropriate value into "disassemble_info" structure.
 *
 * Parameters:
 *	mode	Mode string
 *	dip	Disassemble_info structure pointer
 * Returns:
 * Locking:
 * Remarks:
 *	No mode supported yet.
 */

int
kdba_id_parsemode(const char *mode, disassemble_info *dip)
{
	if (mode && strcmp(mode, "ia64"))
		return KDB_BADMODE;
	return 0;
}

/*
 * kdba_check_pc
 *
 * 	Check that the pc is satisfactory.
 *
 * Parameters:
 *	pc	Program Counter Value.
 * Returns:
 *	None
 * Locking:
 *	None.
 * Remarks:
 *	Can change pc.
 */

void
kdba_check_pc(kdb_machreg_t *pc)
{
	(*pc) &= ~0xf;	/* pc must be 16 byte aligned */
}

/*
 * kdba_id_printinsn
 *
 * 	Format and print a single bundle at 'pc'. Return the
 *	length of the bundle.
 *
 * Parameters:
 *	pc	Program Counter Value.
 *	dip	Disassemble_info structure pointer
 * Returns:
 *	Length of instruction, -1 for error.
 * Locking:
 *	None.
 * Remarks:
 *	None.
 */

int
kdba_id_printinsn(kdb_machreg_t pc, disassemble_info *dip)
{
	int ret;
	int byte = 0;
	int off = 0;

	dip->fprintf_func = dip->fprintf_dummy;
	off = pc & 0xf;
	kdba_check_pc(&pc);
	while (byte < 16) {
		if (byte == off)
			dip->fprintf_func = kdb_dis_fprintf;
		else
			dip->fprintf_func = dip->fprintf_dummy;
		kdba_dis_printaddr(pc+byte, dip);
		ret = print_insn_ia64((kdb_machreg_t)(pc+byte), dip);
		dip->fprintf_func(dip->stream, "\n");
		if (ret < 0)
			break;
		byte += ret;
	}
	return(byte);
}

/*
 * kdba_id_init
 *
 * 	Initialize the architecture dependent elements of
 *	the disassembly information structure
 *	for the GNU disassembler.
 *
 * Parameters:
 *	None.
 * Outputs:
 *	None.
 * Returns:
 *	None.
 * Locking:
 *	None.
 * Remarks:
 */

void __init
kdba_id_init(disassemble_info *dip)
{
	dip->read_memory_func       = kdba_dis_getmem;
	dip->print_address_func     = kdba_dis_printaddr;
	dip->symbol_at_address_func = kdba_dis_getsym;

	dip->flavour                = bfd_target_elf_flavour;
	dip->arch		    = bfd_arch_ia64;
	dip->endian	    	    = BFD_ENDIAN_LITTLE;

	dip->display_endian         = BFD_ENDIAN_LITTLE;
}