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 + -
显示快捷键?