vms-tir.c

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

C
2,461
字号
/* vms-tir.c -- BFD back-end for VAX (openVMS/VAX) and   EVAX (openVMS/Alpha) files.   Copyright 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.   TIR record handling functions   ETIR record handling functions   go and read the openVMS linker manual (esp. appendix B)   if you don't know what's going on here :-)   Written by Klaus K"ampf (kkaempf@rmi.de)This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  *//* The following type abbreviations are used:	cs	counted string (ascii string with length byte)	by	byte (1 byte)	sh	short (2 byte, 16 bit)	lw	longword (4 byte, 32 bit)	qw	quadword (8 byte, 64 bit)	da	data stream  */#include <ctype.h>#include "bfd.h"#include "sysdep.h"#include "bfdlink.h"#include "libbfd.h"#include "vms.h"static void image_set_ptr PARAMS ((bfd *abfd, int psect, uquad offset));static void image_inc_ptr PARAMS ((bfd *abfd, uquad offset));static void image_dump PARAMS ((bfd *abfd, unsigned char *ptr, int size, int offset));static void image_write_b PARAMS ((bfd *abfd, unsigned int value));static void image_write_w PARAMS ((bfd *abfd, unsigned int value));static void image_write_l PARAMS ((bfd *abfd, unsigned long value));static void image_write_q PARAMS ((bfd *abfd, uquad value));/*-----------------------------------------------------------------------------*/static intcheck_section (abfd, size)     bfd *abfd;     int size;{  int offset;  offset = PRIV(image_ptr) - PRIV(image_section)->contents;  if ((bfd_size_type) (offset + size) > PRIV(image_section)->_raw_size)    {      PRIV(image_section)->contents = bfd_realloc (PRIV(image_section)->contents, offset + size);      if (PRIV(image_section)->contents == 0)	{	  (*_bfd_error_handler) (_("No Mem !"));	  return -1;	}      PRIV(image_section)->_raw_size = offset + size;      PRIV(image_ptr) = PRIV(image_section)->contents + offset;    }  return 0;}/* routines to fill sections contents during tir/etir read *//* Initialize image buffer pointer to be filled  */static voidimage_set_ptr (abfd, psect, offset)     bfd *abfd;     int psect;     uquad offset;{#if VMS_DEBUG  _bfd_vms_debug (4, "image_set_ptr (%d=%s, %d)\n",		psect, PRIV(sections)[psect]->name, offset);#endif  PRIV(image_ptr) = PRIV(sections)[psect]->contents + offset;  PRIV(image_section) = PRIV(sections)[psect];  return;}/* Increment image buffer pointer by offset  */static voidimage_inc_ptr (abfd, offset)     bfd *abfd;     uquad offset;{#if VMS_DEBUG  _bfd_vms_debug (4, "image_inc_ptr (%d)\n", offset);#endif  PRIV(image_ptr) += offset;  return;}/* Dump multiple bytes to section image  */static voidimage_dump (abfd, ptr, size, offset)    bfd *abfd;    unsigned char *ptr;    int size;    int offset ATTRIBUTE_UNUSED;{#if VMS_DEBUG  _bfd_vms_debug (8, "image_dump from (%p, %d) to (%p)\n", ptr, size, PRIV(image_ptr));  _bfd_hexdump (9, ptr, size, offset);#endif  if (PRIV(is_vax) && check_section (abfd, size))    return;  while (size-- > 0)    *PRIV(image_ptr)++ = *ptr++;  return;}/* Write byte to section image  */static voidimage_write_b (abfd, value)     bfd *abfd;     unsigned int value;{#if VMS_DEBUG  _bfd_vms_debug (6, "image_write_b(%02x)\n", (int)value);#endif  if (PRIV(is_vax) && check_section (abfd, 1))    return;  *PRIV(image_ptr)++ = (value & 0xff);  return;}/* Write 2-byte word to image  */static voidimage_write_w (abfd, value)     bfd *abfd;     unsigned int value;{#if VMS_DEBUG  _bfd_vms_debug (6, "image_write_w(%04x)\n", (int)value);#endif  if (PRIV(is_vax) && check_section (abfd, 2))    return;  bfd_putl16 (value, PRIV(image_ptr));  PRIV(image_ptr) += 2;  return;}/* Write 4-byte long to image  */static voidimage_write_l (abfd, value)     bfd *abfd;     unsigned long value;{#if VMS_DEBUG  _bfd_vms_debug (6, "image_write_l (%08lx)\n", value);#endif  if (PRIV(is_vax) && check_section (abfd, 4))    return;  bfd_putl32 (value, PRIV(image_ptr));  PRIV(image_ptr) += 4;  return;}/* Write 8-byte quad to image  */static voidimage_write_q (abfd, value)     bfd *abfd;     uquad value;{#if VMS_DEBUG  _bfd_vms_debug (6, "image_write_q (%016lx)\n", value);#endif  if (PRIV(is_vax) && check_section (abfd, 8))    return;  bfd_putl64 (value, PRIV(image_ptr));  PRIV(image_ptr) += 8;  return;}#define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L)/* etir_sta   vms stack commands   handle sta_xxx commands in etir section   ptr points to data area in record   see table B-8 of the openVMS linker manual  */static booleanetir_sta (abfd, cmd, ptr)     bfd *abfd;     int cmd;     unsigned char *ptr;{#if VMS_DEBUG  _bfd_vms_debug (5, "etir_sta %d/%x\n", cmd, cmd);  _bfd_hexdump (8, ptr, 16, (int)ptr);#endif  switch (cmd)    {      /* stack */      /* stack global	   arg: cs	symbol name	   stack 32 bit value of symbol (high bits set to 0)  */      case ETIR_S_C_STA_GBL:	{	  char *name;	  vms_symbol_entry *entry;	  name = _bfd_vms_save_counted_string (ptr);	  entry = (vms_symbol_entry *)		  bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false);	  if (entry == (vms_symbol_entry *)NULL)	    {#if VMS_DEBUG	      _bfd_vms_debug (3, "ETIR_S_C_STA_GBL: no symbol \"%s\"\n", name);#endif	      _bfd_vms_push (abfd, (uquad)0, -1);	    }	  else	    {	      _bfd_vms_push (abfd, (uquad) (entry->symbol->value), -1);	    }	}      break;	/* stack longword	   arg: lw	value	   stack 32 bit value, sign extend to 64 bit  */      case ETIR_S_C_STA_LW:	_bfd_vms_push (abfd, (uquad)bfd_getl32 (ptr), -1);      break;	/* stack global	   arg: qw	value	   stack 64 bit value of symbol	 */      case ETIR_S_C_STA_QW:	_bfd_vms_push (abfd, (uquad)bfd_getl64(ptr), -1);      break;	/* stack psect base plus quadword offset	   arg: lw	section index	  	qw	signed quadword offset (low 32 bits)	   stack qw argument and section index	   (see ETIR_S_C_STO_OFF, ETIR_S_C_CTL_SETRB)  */      case ETIR_S_C_STA_PQ:  	{	  uquad dummy;	  unsigned int psect;	  psect = bfd_getl32 (ptr);	  if (psect >= PRIV(section_count))	    {	      (*_bfd_error_handler) (_("Bad section index in ETIR_S_C_STA_PQ"));	      bfd_set_error (bfd_error_bad_value);	      return false;	    }	  dummy = bfd_getl64 (ptr+4);	  _bfd_vms_push (abfd, dummy, psect);        }      break;	/* all not supported  */      case ETIR_S_C_STA_LI:      case ETIR_S_C_STA_MOD:      case ETIR_S_C_STA_CKARG:	(*_bfd_error_handler) (_("Unsupported STA cmd %d"), cmd);	return false;      break;      default:	(*_bfd_error_handler) (_("Reserved STA cmd %d"), cmd);	return false;      break;    }#if VMS_DEBUG  _bfd_vms_debug (5, "etir_sta true\n");#endif  return true;}/*   etir_sto   vms store commands   handle sto_xxx commands in etir section   ptr points to data area in record   see table B-9 of the openVMS linker manual  */static booleanetir_sto (abfd, cmd, ptr)     bfd *abfd;     int cmd;     unsigned char *ptr;{  uquad dummy;  int psect;#if VMS_DEBUG  _bfd_vms_debug (5, "etir_sto %d/%x\n", cmd, cmd);  _bfd_hexdump (8, ptr, 16, (int)ptr);#endif  switch (cmd)    {      /* store byte: pop stack, write byte	 arg: -  */    case ETIR_S_C_STO_B:      dummy = _bfd_vms_pop (abfd, &psect);#if 0      if (is_share)		/* FIXME */	(*_bfd_error_handler) ("ETIR_S_C_STO_B: byte fixups not supported");#endif      image_write_b (abfd, dummy & 0xff);	/* FIXME: check top bits */      break;      /* store word: pop stack, write word	 arg: -  */    case ETIR_S_C_STO_W:      dummy = _bfd_vms_pop (abfd, &psect);#if 0      if (is_share)		/* FIXME */	(*_bfd_error_handler) ("ETIR_S_C_STO_B: word fixups not supported");#endif      image_write_w (abfd, dummy & 0xffff);	/* FIXME: check top bits */      break;      /* store longword: pop stack, write longword	 arg: -  */    case ETIR_S_C_STO_LW:      dummy = _bfd_vms_pop (abfd, &psect);      dummy += (PRIV(sections)[psect])->vma;      image_write_l (abfd, dummy & 0xffffffff);/* FIXME: check top bits */      break;      /* store quadword: pop stack, write quadword	 arg: -  */    case ETIR_S_C_STO_QW:      dummy = _bfd_vms_pop (abfd, &psect);      dummy += (PRIV(sections)[psect])->vma;      image_write_q (abfd, dummy);		/* FIXME: check top bits */      break;      /* store immediate repeated: pop stack for repeat count	 arg: lw	byte count	 da	data  */    case ETIR_S_C_STO_IMMR:      {	unsigned long size;	size = bfd_getl32 (ptr);	dummy = (unsigned long)_bfd_vms_pop (abfd, NULL);	while (dummy-- > 0L)	  image_dump (abfd, ptr+4, size, 0);      }      break;      /* store global: write symbol value	 arg: cs	global symbol name  */    case ETIR_S_C_STO_GBL:      {	vms_symbol_entry *entry;	char *name;	name = _bfd_vms_save_counted_string (ptr);	entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false);	if (entry == (vms_symbol_entry *)NULL)	  {	    (*_bfd_error_handler) (_("ETIR_S_C_STO_GBL: no symbol \"%s\""),				   name);	    return false;	  }	else	  image_write_q (abfd, (uquad) (entry->symbol->value));	/* FIXME, reloc */      }      break;      /* store code address: write address of entry point	 arg: cs	global symbol name (procedure)  */    case ETIR_S_C_STO_CA:      {	vms_symbol_entry *entry;	char *name;	name = _bfd_vms_save_counted_string (ptr);	entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false);	if (entry == (vms_symbol_entry *)NULL)	  {	    (*_bfd_error_handler) (_("ETIR_S_C_STO_CA: no symbol \"%s\""),				   name);	    return false;	  }	else	  image_write_q (abfd, (uquad) (entry->symbol->value));	/* FIXME, reloc */      }      break;      /* not supported  */    case ETIR_S_C_STO_RB:    case ETIR_S_C_STO_AB:      (*_bfd_error_handler) (_("ETIR_S_C_STO_RB/AB: Not supported"));      break;    /* store offset to psect: pop stack, add low 32 bits to base of psect       arg: -  */    case ETIR_S_C_STO_OFF:      {	uquad q;	int psect;	q = _bfd_vms_pop (abfd, &psect);	q += (PRIV(sections)[psect])->vma;	image_write_q (abfd, q);      }      break;      /* store immediate	 arg: lw	count of bytes	 da	data  */    case ETIR_S_C_STO_IMM:      {	int size;	size = bfd_getl32 (ptr);	image_dump (abfd, ptr+4, size, 0);      }      break;      /* this code is 'reserved to digital' according to the openVMS linker manual,	 however it is generated by the DEC C compiler and defined in the include file.	 FIXME, since the following is just a guess	 store global longword: store 32bit value of symbol	 arg: cs	symbol name  */    case ETIR_S_C_STO_GBL_LW:      {	vms_symbol_entry *entry;	char *name;	name = _bfd_vms_save_counted_string (ptr);	entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false);	if (entry == (vms_symbol_entry *)NULL)	  {#if VMS_DEBUG	    _bfd_vms_debug (3, "ETIR_S_C_STO_GBL_LW: no symbol \"%s\"\n", name);#endif	    image_write_l (abfd, (unsigned long)0);	/* FIXME, reloc */	  }	else	  image_write_l (abfd, (unsigned long) (entry->symbol->value));	/* FIXME, reloc */      }      break;      /* not supported  */    case ETIR_S_C_STO_LP_PSB:      (*_bfd_error_handler) (_("ETIR_S_C_STO_LP_PSB: Not supported"));      break;    /* */    case ETIR_S_C_STO_HINT_GBL:      (*_bfd_error_handler) (_("ETIR_S_C_STO_HINT_GBL: not implemented"));      break;    /* */    case ETIR_S_C_STO_HINT_PS:      (*_bfd_error_handler) (_("ETIR_S_C_STO_HINT_PS: not implemented"));      break;    default:      (*_bfd_error_handler) (_("Reserved STO cmd %d"), cmd);      break;    }  return true;}/* stack operator commands   all 32 bit signed arithmetic   all word just like a stack calculator   arguments are popped from stack, results are pushed on stack   see table B-10 of the openVMS linker manual  */static booleanetir_opr (abfd, cmd, ptr)     bfd *abfd;     int cmd;     unsigned char *ptr ATTRIBUTE_UNUSED;{  long op1, op2;#if VMS_DEBUG  _bfd_vms_debug (5, "etir_opr %d/%x\n", cmd, cmd);  _bfd_hexdump (8, ptr, 16, (int)ptr);#endif  switch (cmd)    {      /* operation */      /* no-op  */    case ETIR_S_C_OPR_NOP:      break;      /* add  */    case ETIR_S_C_OPR_ADD:      op1 = (long)_bfd_vms_pop (abfd, NULL);      op2 = (long)_bfd_vms_pop (abfd, NULL);      _bfd_vms_push (abfd, (uquad) (op1 + op2), -1);      break;      /* subtract  */    case ETIR_S_C_OPR_SUB:      op1 = (long)_bfd_vms_pop (abfd, NULL);      op2 = (long)_bfd_vms_pop (abfd, NULL);      _bfd_vms_push (abfd, (uquad) (op2 - op1), -1);      break;      /* multiply  */    case ETIR_S_C_OPR_MUL:      op1 = (long)_bfd_vms_pop (abfd, NULL);      op2 = (long)_bfd_vms_pop (abfd, NULL);      _bfd_vms_push (abfd, (uquad) (op1 * op2), -1);      break;      /* divide  */    case ETIR_S_C_OPR_DIV:      op1 = (long)_bfd_vms_pop (abfd, NULL);      op2 = (long)_bfd_vms_pop (abfd, NULL);      if (op2 == 0)	_bfd_vms_push (abfd, (uquad)0L, -1);      else	_bfd_vms_push (abfd, (uquad) (op2 / op1), -1);      break;      /* logical and  */    case ETIR_S_C_OPR_AND:      op1 = (long)_bfd_vms_pop (abfd, NULL);      op2 = (long)_bfd_vms_pop (abfd, NULL);      _bfd_vms_push (abfd, (uquad) (op1 & op2), -1);      break;      /* logical inclusive or	 */

⌨️ 快捷键说明

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