coff.c

来自「motorola自己开发的针对coldfire 5272的Dbug bootlo」· C语言 代码 · 共 451 行

C
451
字号
/*
 * File:		coff.c
 * Purpose:		Implement COFF binary download into dBUG.
 *
 * Notes:
 *
 * Author:		Eric DeVolder
 * Date:		1-9-96
 *
 * Modifications:
 *
 */

#include "src/include/dbug.h"
#include "src/uif/uif.h"

/********************************************************************/

#ifndef COFF_MAX_SCNS
#define COFF_MAX_SCNS	(10)
#endif

/********************************************************************/
typedef struct filehdr
{
	unsigned short	f_magic;	/* magic				*/
	unsigned short	f_nscns;	/* number of sections	*/
	long			f_timdat;	/* date stamp			*/
	long			f_symptr;	/* fileptr to symtab	*/
	long			f_nsyms;	/* symtab count			*/
	unsigned short	f_opthdr;	/* sizeof (optional hdr)*/
	unsigned short	f_flags;	/* flags				*/
} FILEHDR;
#define F_RELFLG	(0x0001)
#define F_EXEC		(0x0002)
#define F_LNNO		(0x0004)
#define F_LSYMS		(0x0008)
#define F_AR32W		(0x0200)
#define F_MAGIC_68K_0	(0x0150)	/* 68K and ColdFire			*/
#define F_MAGIC_68K_1	(0x0195)	/* MIT 68000/010			*/
#define F_MAGIC_68K_2	(0x0198)	/* MIT 68020/030/040/060	*/
#define F_MAGIC_PPC		(0x0170)	/* PowerPC					*/

/********************************************************************/
typedef struct aouthdr
{
	short	magic;			/* a.out magic		*/
	short	vstamp;			/* version stamp	*/
	long	tsize;			/* .text size		*/
	long	dsize;			/* .data size		*/
	long	bsize;			/* .bss size		*/
	long	entry;			/* entry point		*/
	long	text_start;		/* fileptr to .text	*/
	long	data_start;		/* fileptr to .data */
} AOUTHDR;

/********************************************************************/
typedef struct scnhdr
{
	char	s_name[8];		/* section name			*/
	long	s_paddr;		/* physical address		*/
	long	s_vaddr;		/* virtual address		*/
	long	s_size;			/* size of section		*/
	long	s_scnptr;		/* fileptr to raw data	*/
	long	s_relptr;		/* fileptr to reloc		*/
	long	s_lnnoptr;		/* fileptr to lineno	*/
#if (defined (CPU_ARCH_CF))
	unsigned short	s_nreloc;	/* reloc count		*/
	unsigned short	s_nlnno;	/* lnno count		*/
#elif (defined (CPU_ARCH_PPC))
	unsigned long   s_nreloc;   /* reloc count      */
	unsigned long   s_nlnno;    /* lnno count       */
#else
#error "Unsupported CPU in coff.c"
#endif
	long			s_flags;	/* flags			*/
} SCNHDR;

#if (defined(CPU_ARCH_CF))
#define SCNHSZ  (sizeof(SCNHDR))
#elif (defined(CPU_ARCH_PPC))
#define SCNHSZ  (sizeof(SCNHDR))
#else
#error "Unsupported CPU in coff.c"
#endif

#define STYP_TEXT	(0x0020)
#define STYP_DATA	(0x0040)
#define STYP_BSS	(0x0080)
#define STYP_INFO	(0x0200)

/********************************************************************/
typedef struct reloc
{
	long			r_vaddr;	/* address of reference */
	long			r_symndx;	/* index into symtab	*/
	unsigned short	r_type;		/* relocation type		*/
#if (defined(CPU_ARCH_PPC))
	unsigned short	r_offset;	/* hi word of rel addr */
#endif
} RELOC;

#if (defined (CPU_ARCH_CF))
#define RELSZ	(10)
#elif (defined (CPU_ARCH_PPC))
#define RELSZ	(sizeof(RELOC))
#else
#error "Unsupported CPU in coff.c"
#endif

/********************************************************************/
typedef struct syment
{
	union {
		char	_n_name[8];			/* if len <= 8				*/
		struct
		{
			long	_n_zeroes;		/* == 0 if len > 8 			*/
			long	_n_offset;		/* offset into string table	*/
		} _n_n;
	} _n;
	long	n_value;				/* value of symbol			*/
	short	n_scnum;				/* section number			*/
	unsigned short	n_type;			/* type and derived type	*/
	char			n_sclass;		/* storage class			*/
	char			n_numaux;		/* no of aux. entries		*/
#if (defined(CPU_ARCH_PPC))
	short			n_pad;
#endif

} SYMENT;

#if (defined(CPU_ARCH_CF))
#define SYMESZ	(18)
#elif (defined (CPU_ARCH_PPC))
#define SYMESZ	(20)
#else
#error "Unsupported CPU in coff.c"
#endif

/********************************************************************/
#define DIMNUM (4)
#define FILNMLEN	(14)
typedef union auxent
{
	struct {
		long   x_tagndx;
		union {
			struct {
				unsigned short  x_lnno;
				unsigned short  x_size;
			} x_lnsz;
			long     x_fsize;
		} x_misc;
		union {
			struct {
				long   x_lnnoptr;
				long   x_endndx;
			}  x_fcn;
			struct {
				unsigned short  x_dimen[DIMNUM];
			} x_ary;
		} x_fcnary;
		unsigned short  x_tvndx;
	} x_sym;

	struct {
		char   x_fname[FILNMLEN];
	} x_file;

	struct {
		long       x_scnlen;
		unsigned short  x_nreloc;
		unsigned short  x_nlinno;
	} x_scn;

	struct {
		long            x_tvfill;
		unsigned short  x_tvlen;
		unsigned short  x_tvran[2];
	} x_tv;
} AUXENT;

/********************************************************************/

static int coff_numaux;
static int coff_bytes_read;
static int coff_sym_incomplete;

/********************************************************************/
static int
coff_read (char *buf, int size)
{
	int i;
	for (i = 0; i < size; i++)
	{
		buf[i] = (char)board_dlio_getchar();
		++coff_bytes_read;
	}
	return i;
}

/********************************************************************/
static void
coff_read_filehdr (FILEHDR *filehdr)
{
	coff_read((char *)filehdr,sizeof(FILEHDR));
}

/********************************************************************/
static void
coff_read_aouthdr (AOUTHDR *aouthdr)
{
	coff_read((char *)aouthdr,sizeof(AOUTHDR));
}

/********************************************************************/
static void
coff_read_scnhdr (SCNHDR *scnhdr)
{
	coff_read((char *)scnhdr,SCNHSZ);
}

/********************************************************************/
static void
coff_read_rawdata (SCNHDR *scnhdr)
{
	int i;
	char c;

	printf("Section:  %-8s (Paddr: 0x%08X  Size: 0x%08X)\n",
		scnhdr->s_name,
		(unsigned int)scnhdr->s_paddr,
		(unsigned int)scnhdr->s_size);

	/* Skip to section.  NOTE:  assumes sections appear sequentially! */
	for (i = coff_bytes_read; i < scnhdr->s_scnptr; ++i)
	{
		coff_read((char *)&c, 1);
	}

	if (board_dlio_vda((ADDRESS)scnhdr->s_paddr))
	{
		if ((scnhdr->s_flags & STYP_BSS) != STYP_BSS)
		{
			for (i = 0; i < scnhdr->s_size; i++)
			{
				coff_read((char *)&c,1);
				((char *)(scnhdr->s_paddr))[i] = c;
			}
		}
		else
		{
			for (i = 0; i < scnhdr->s_size; i++)
			{
				((char *)(scnhdr->s_paddr))[i] = 0;
			}
		}
	}
	else
	{
		printf("Error: Invalid download address: %#08X\n",scnhdr->s_paddr);
		return;
	}
}

/********************************************************************/
static void
coff_read_syment (SYMENT *syment)
{
	int i,n_numaux;
	char symb[9];

	coff_read((char *)syment,SYMESZ);

	if (syment->_n._n_n._n_zeroes)
	{
		switch (syment->n_sclass)
		{
			case 0x02:	/* real symbols		*/
			/*case 0x03:*/
				if (syment->n_numaux == 0)
				{
				symb[0] = syment->_n._n_name[0];
				symb[1] = syment->_n._n_name[1];
				symb[2] = syment->_n._n_name[2];
				symb[3] = syment->_n._n_name[3];
				symb[4] = syment->_n._n_name[4];
				symb[5] = syment->_n._n_name[5];
				symb[6] = syment->_n._n_name[6];
				symb[7] = syment->_n._n_name[7];
				symb[8] = 0;
				symtab_add(symb,(ADDRESS)syment->n_value);
				}
				break;
			default:
				break;
		}
	}
	else
	{
		switch (syment->n_sclass)
		{
			case 0x02:	/* real symbols		*/
			/*case 0x03:*/
				if (syment->n_numaux == 0)
				symtab_add_incomplete(syment->_n._n_n._n_offset,
					(ADDRESS)syment->n_value);
				break;
			default:
				break;
		}
		++coff_sym_incomplete;
	}

	n_numaux = syment->n_numaux;
	for (i = 0; i < n_numaux; ++i)
	{
		coff_read((char *)syment,SYMESZ);
		--coff_numaux;
	}
}

/********************************************************************/
void
download_coff (void)
{
	FILEHDR	filehdr;
	AOUTHDR aouthdr;
	SYMENT  syment;
	int i, c, strtabsize, strtaboffset;
	char ch;
	SCNHDR  scnhdr[COFF_MAX_SCNS];

	coff_bytes_read = 0;

	coff_read_filehdr(&filehdr);
	switch (filehdr.f_magic)
	{
#if (defined (CPU_ARCH_CF))
		case F_MAGIC_68K_0:
		case F_MAGIC_68K_1:
		case F_MAGIC_68K_2:
#elif (defined (CPU_ARCH_PPC))
		case F_MAGIC_PPC:
#else
#error "Unsupported CPU in coff.c"
#endif
			break;
		default:
			printf("Error:  Not a recognized COFF format:  %04X\n",
				filehdr.f_magic);
			return;
			break;
	}

	if ((filehdr.f_flags & F_EXEC) != F_EXEC)
	{
		printf("Error:  Not a COFF executable.\n");
		return;
	}

	/* Read the optional header (a.out) */
	if (filehdr.f_opthdr == sizeof(AOUTHDR))
	{
		coff_read_aouthdr(&aouthdr);
		cpu_pc_modify((ADDRESS)aouthdr.entry);
	}
	else
	{
		for (i = 0; i < filehdr.f_opthdr; ++i)
		{
			coff_read((char *)&c, 1);
		}
	}

	/* Read in the section headers */
	for (i = 0; i < filehdr.f_nscns; i++)
	{
		if (i < (COFF_MAX_SCNS - 1))
		{
			coff_read_scnhdr(&scnhdr[i]);
		}
		else
		{
			coff_read_scnhdr(&scnhdr[COFF_MAX_SCNS]);
		}
	}

#if (defined(CPU_ARCH_PPC))
	/*
	 * For some unkown reason, there are 4 bytes of zeros(?)
	 * after the section headers before the raw data when
	 * examing Diab Data v3.6d tools.  FIX !!!
	 */
	for (i = 0; i < 4; ++i)
	{
		coff_read((char *)&c, 1);
	}
#endif

	for (i = 0; i < filehdr.f_nscns; i++)
	{
		coff_read_rawdata( &scnhdr[i]);
	}

	/* Skip reloc and line number info */
	for (i = coff_bytes_read; i < filehdr.f_symptr; ++i)
	{
		coff_read((char *)&c, 1);
	}

	/* Read in symbol table, if present */
	coff_sym_incomplete = 0;
	if (filehdr.f_nsyms)
	{
		/* Read in symbol table stuff */
		coff_numaux = filehdr.f_nsyms;
		while (coff_numaux--)
		{
			coff_read_syment(&syment);
		}
	}

	/* Read in string table, if present */
	if (coff_sym_incomplete != 0)
	{
		strtaboffset = coff_bytes_read;
		coff_read((char *)&strtabsize, 4);

		for (i = 0; i < coff_sym_incomplete; i++)
		{
			int j, offset;
			char sstr[100];
	
			offset = coff_bytes_read - strtaboffset;
			j = 0;
			while (1)
			{
				coff_read((char *)&ch, 1);
				sstr[j++] = ch;
				if (ch == '\0')
					break;
			}
			symtab_add_complete(sstr,offset);
		}
	}
}

/********************************************************************/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?