versados.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 902 行 · 第 1/2 页

C
902
字号
/* BFD back-end for VERSAdos-E objects.   Copyright 1995, 1996, 1998, 1999, 2000 Free Software Foundation, Inc.   Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.   Versados is a Motorola trademark.   This file is part of BFD, the Binary File Descriptor library.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  *//*   SUBSECTION   VERSAdos-E relocateable object file format   DESCRIPTION   This module supports reading of VERSAdos relocateable   object files.   A VERSAdos file looks like contains   o Indentification Record   o External Symbol Definition Record   o Object Text Recrod   o End Record */#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#include "libiberty.h"static boolean versados_mkobject PARAMS ((bfd *));static boolean versados_scan PARAMS ((bfd *));static const bfd_target *versados_object_p PARAMS ((bfd *));#define VHEADER '1'#define VESTDEF '2'#define VOTR '3'#define VEND '4'#define ES_BASE 17		/* first symbol has esdid 17 *//* Per file target dependent information *//* one for each section */struct esdid  {    asection *section;		/* ptr to bfd version */    unsigned char *contents;	/* used to build image */    int pc;    int relocs;			/* reloc count, valid end of pass 1 */    int donerel;		/* have relocs been translated */  };typedef struct versados_data_struct  {    int es_done;		/* count of symbol index, starts at ES_BASE */    asymbol *symbols;		/* pointer to local symbols */    char *strings;		/* strings of all the above */    int stringlen;		/* len of string table (valid end of pass1) */    int nsecsyms;		/* number of sections */    int ndefs;			/* number of exported symbols (they dont get esdids) */    int nrefs;			/* number of imported symbols  (valid end of pass1) */    int ref_idx;		/* current processed value of the above */    int def_idx;    int pass_2_done;    struct esdid e[16];		/* per section info */    int alert;			/* to see if we're trampling */    asymbol *rest[256 - 16];	/* per symbol info */  }tdata_type;#define VDATA(abfd)       (abfd->tdata.versados_data)#define EDATA(abfd, n)    (abfd->tdata.versados_data->e[n])#define RDATA(abfd, n)    (abfd->tdata.versados_data->rest[n])struct ext_otr  {    unsigned char size;    char type;    unsigned char map[4];    unsigned char esdid;    unsigned char data[200];  };struct ext_vheader  {    unsigned char size;    char type;			/* record type */    char name[10];		/* module name */    char rev;			/* module rev number */    char lang;    char vol[4];    char user[2];    char cat[8];    char fname[8];    char ext[2];    char time[3];    char date[3];    char rest[211];  };struct ext_esd  {    unsigned char size;    char type;    unsigned char esd_entries[1];  };#define ESD_ABS 	0#define ESD_COMMON 	1#define ESD_STD_REL_SEC 2#define ESD_SHRT_REL_SEC 3#define ESD_XDEF_IN_SEC 4#define ESD_XREF_SYM    7#define ESD_XREF_SEC	6#define ESD_XDEF_IN_ABS 5union ext_any  {    unsigned char size;    struct ext_vheader header;    struct ext_esd esd;    struct ext_otr otr;  };/* Initialize by filling in the hex conversion array.  *//* Set up the tdata information.  */static booleanversados_mkobject (abfd)     bfd *abfd;{  if (abfd->tdata.versados_data == NULL)    {      tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));      if (tdata == NULL)	return false;      abfd->tdata.versados_data = tdata;      tdata->symbols = NULL;      VDATA (abfd)->alert = 0x12345678;    }  bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);  return true;}/* Report a problem in an S record file.  FIXME: This probably should   not call fprintf, but we really do need some mechanism for printing   error messages.  */static asymbol *versados_new_symbol (abfd, snum, name, val, sec)     bfd *abfd;     int snum;     const char *name;     bfd_vma val;     asection *sec;{  asymbol *n = VDATA (abfd)->symbols + snum;  n->name = name;  n->value = val;  n->section = sec;  n->the_bfd = abfd;  n->flags = 0;  return n;}static intget_record (abfd, ptr)     bfd *abfd;     union ext_any *ptr;{  bfd_read (&ptr->size, 1, 1, abfd);  if (bfd_read ((char *) ptr + 1, 1, ptr->size, abfd) != ptr->size)    return 0;  return 1;}intget_4 (pp)     unsigned char **pp;{  unsigned char *p = *pp;  *pp += 4;  return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);}voidget_10 (pp, name)     unsigned char **pp;     char *name;{  char *p = (char *) *pp;  int len = 10;  *pp += len;  while (*p != ' '	 && len)    {      *name++ = *p++;      len--;    }  *name = 0;}static char *new_symbol_string (abfd, name)     bfd *abfd;     char *name;{  char *n = VDATA (abfd)->strings;  strcpy (VDATA (abfd)->strings, name);  VDATA (abfd)->strings += strlen (VDATA (abfd)->strings) + 1;  return n;}static voidprocess_esd (abfd, esd, pass)     bfd *abfd;     struct ext_esd *esd;     int pass;{  /* Read through the ext def for the est entries */  int togo = esd->size - 2;  bfd_vma size;  bfd_vma start;  asection *sec;  char name[11];  unsigned char *ptr = esd->esd_entries;  unsigned char *end = ptr + togo;  while (ptr < end)    {      int scn = *ptr & 0xf;      int typ = (*ptr >> 4) & 0xf;      /* Declare this section */      sprintf (name, "%d", scn);      sec = bfd_make_section_old_way (abfd, strdup (name));      sec->target_index = scn;      EDATA (abfd, scn).section = sec;      ptr++;      switch (typ)	{	default:	  abort ();	case ESD_XREF_SEC:	case ESD_XREF_SYM:	  {	    int snum = VDATA (abfd)->ref_idx++;	    get_10 (&ptr, name);	    if (pass == 1)	      {		VDATA (abfd)->stringlen += strlen (name) + 1;	      }	    else	      {		int esidx;		asymbol *s;		char *n = new_symbol_string (abfd, name);		s = versados_new_symbol (abfd, snum, n, 0,					 &bfd_und_section, scn);		esidx = VDATA (abfd)->es_done++;		RDATA (abfd, esidx - ES_BASE) = s;	      }	  }	  break;	case ESD_ABS:	  size = get_4 (&ptr);	  start = get_4 (&ptr);	  break;	case ESD_STD_REL_SEC:	case ESD_SHRT_REL_SEC:	  {	    sec->_raw_size = get_4 (&ptr);	    sec->flags |= SEC_ALLOC;	  }	  break;	case ESD_XDEF_IN_ABS:	  sec = (asection *) & bfd_abs_section;	case ESD_XDEF_IN_SEC:	  {	    int snum = VDATA (abfd)->def_idx++;	    long val;	    get_10 (&ptr, name);	    val = get_4 (&ptr);	    if (pass == 1)	      {		/* Just remember the symbol */		VDATA (abfd)->stringlen += strlen (name) + 1;	      }	    else	      {		asymbol *s;		char *n = new_symbol_string (abfd, name);		s = versados_new_symbol (abfd, snum + VDATA (abfd)->nrefs, n, val, sec, scn);		s->flags |= BSF_GLOBAL;	      }	  }	  break;	}    }}#define R_RELWORD 1#define R_RELLONG 2#define R_RELWORD_NEG 3#define R_RELLONG_NEG 4reloc_howto_type versados_howto_table[] ={  HOWTO (R_RELWORD, 0, 1, 16, false,	 0, complain_overflow_dont, 0,	 "+v16", true, 0x0000ffff, 0x0000ffff, false),  HOWTO (R_RELLONG, 0, 2, 32, false,	 0, complain_overflow_dont, 0,	 "+v32", true, 0xffffffff, 0xffffffff, false),  HOWTO (R_RELWORD_NEG, 0, -1, 16, false,	 0, complain_overflow_dont, 0,	 "-v16", true, 0x0000ffff, 0x0000ffff, false),  HOWTO (R_RELLONG_NEG, 0, -2, 32, false,	 0, complain_overflow_dont, 0,	 "-v32", true, 0xffffffff, 0xffffffff, false),};static intget_offset (len, ptr)     int len;     unsigned char *ptr;{  int val = 0;  if (len)    {      int i;      val = *ptr++;      if (val & 0x80)	val |= ~0xff;      for (i = 1; i < len; i++)	val = (val << 8) | *ptr++;    }  return val;}static voidprocess_otr (abfd, otr, pass)     bfd *abfd;     struct ext_otr *otr;     int pass;{  unsigned long shift;  unsigned char *srcp = otr->data;  unsigned char *endp = (unsigned char *) otr + otr->size;  unsigned int bits = (otr->map[0] << 24)  | (otr->map[1] << 16)  | (otr->map[2] << 8)  | (otr->map[3] << 0);  struct esdid *esdid = &EDATA (abfd, otr->esdid - 1);  unsigned char *contents = esdid->contents;  int need_contents = 0;  unsigned int dst_idx = esdid->pc;  for (shift = (1 << 31); shift && srcp < endp; shift >>= 1)    {      if (bits & shift)	{	  int flag = *srcp++;	  int esdids = (flag >> 5) & 0x7;	  int sizeinwords = ((flag >> 3) & 1) ? 2 : 1;	  int offsetlen = flag & 0x7;	  int j;	  if (esdids == 0)	    {	      /* A zero esdid means the new pc is the offset given */	      dst_idx += get_offset (offsetlen, srcp);	      srcp += offsetlen;	    }	  else	    {	      int val = get_offset (offsetlen, srcp + esdids);	      if (pass == 1)		need_contents = 1;	      else		for (j = 0; j < sizeinwords * 2; j++)		  {		    contents[dst_idx + (sizeinwords * 2) - j - 1] = val;		    val >>= 8;		  }	      for (j = 0; j < esdids; j++)		{		  int esdid = *srcp++;		  if (esdid)		    {		      int rn = EDATA (abfd, otr->esdid - 1).relocs++;		      if (pass == 1)			{			  /* this is the first pass over the data,			     just remember that we need a reloc */			}		      else			{			  arelent *n =			  EDATA (abfd, otr->esdid - 1).section->relocation + rn;			  n->address = dst_idx;			  n->sym_ptr_ptr = (asymbol **) esdid;			  n->addend = 0;			  n->howto = versados_howto_table + ((j & 1) * 2) + (sizeinwords - 1);			}		    }		}	      srcp += offsetlen;	      dst_idx += sizeinwords * 2;	    }	}      else	{	  need_contents = 1;	  if (dst_idx < esdid->section->_raw_size)	    if (pass == 2)	      {		/* absolute code, comes in 16 bit lumps */		contents[dst_idx] = srcp[0];		contents[dst_idx + 1] = srcp[1];	      }	  dst_idx += 2;	  srcp += 2;	}

⌨️ 快捷键说明

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