nlm32-alpha.c

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

C
893
字号
      BFD_ASSERT (sym != NULL);      /* We don't need to set sym_ptr_ptr for this case.  It is set in	 nlm_canonicalize_reloc.  */      rel->sym_ptr_ptr = NULL;      rel->addend = 0;    }  else    {      /* Internal relocations are only used for local relocation	 fixups.  If they are not NW_RELOC or GPDISP or IGNORE, they	 must be against .text or .data.  */      BFD_ASSERT (r_type == ALPHA_R_NW_RELOC || sym == NULL);      if (r_type == ALPHA_R_NW_RELOC	  || r_type == ALPHA_R_GPDISP	  || r_type == ALPHA_R_IGNORE)	{	  rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;	  rel->addend = 0;	}      else if (r_symndx == ALPHA_RELOC_SECTION_TEXT)	{	  rel->sym_ptr_ptr = code_sec->symbol_ptr_ptr;	  BFD_ASSERT (bfd_get_section_vma (abfd, code_sec) == 0);	  rel->addend = 0;	}      else if (r_symndx == ALPHA_RELOC_SECTION_DATA)	{	  rel->sym_ptr_ptr = data_sec->symbol_ptr_ptr;	  rel->addend = - bfd_get_section_vma (abfd, data_sec);	}      else	{	  BFD_ASSERT (0);	  rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;	  rel->addend = 0;	}    }  /* We use the address to determine whether the reloc is in the .text     or .data section.  R_NW_RELOC relocs don't really have a section,     so we put them in .text.  */  if (r_type == ALPHA_R_NW_RELOC      || r_vaddr < bfd_section_size (abfd, code_sec))    {      *secp = code_sec;      rel->address = r_vaddr;    }  else    {      *secp = data_sec;      rel->address = r_vaddr - bfd_section_size (abfd, code_sec);    }  /* We must adjust the addend based on the type.  */  BFD_ASSERT ((r_type >= 0 && r_type <= ALPHA_R_GPVALUE)	      || r_type == ALPHA_R_NW_RELOC);  switch (r_type)    {    case ALPHA_R_BRADDR:    case ALPHA_R_SREL16:    case ALPHA_R_SREL32:    case ALPHA_R_SREL64:      /* The PC relative relocs do not seem to use the section VMA as	 a negative addend.  */      rel->addend = 0;      break;    case ALPHA_R_GPREL32:      /* Copy the gp value for this object file into the addend, to	 ensure that we are not confused by the linker.  */      if (! r_extern)	rel->addend += gp_value;      break;    case ALPHA_R_LITERAL:      BFD_ASSERT (! r_extern);      rel->addend += lita_address;      break;    case ALPHA_R_LITUSE:    case ALPHA_R_GPDISP:      /* The LITUSE and GPDISP relocs do not use a symbol, or an	 addend, but they do use a special code.  Put this code in the	 addend field.  */      rel->addend = r_symndx;      rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;      break;    case ALPHA_R_OP_STORE:      /* The STORE reloc needs the size and offset fields.  We store	 them in the addend.  */      BFD_ASSERT (r_offset < 256 && r_size < 256);      rel->addend = (r_offset << 8) + r_size;      break;    case ALPHA_R_OP_PUSH:    case ALPHA_R_OP_PSUB:    case ALPHA_R_OP_PRSHIFT:      /* The PUSH, PSUB and PRSHIFT relocs do not actually use an	 address.  I believe that the address supplied is really an	 addend.  */      rel->addend = r_vaddr;      break;    case ALPHA_R_GPVALUE:      /* Record the new gp value.  */      gp_value += r_symndx;      rel->addend = gp_value;      break;    case ALPHA_R_IGNORE:      /* If the type is ALPHA_R_IGNORE, make sure this is a reference	 to the absolute section so that the reloc is ignored.  For	 some reason the address of this reloc type is not adjusted by	 the section vma.  We record the gp value for this object file	 here, for convenience when doing the GPDISP relocation.  */      rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;      rel->address = r_vaddr;      rel->addend = gp_value;      break;    case ALPHA_R_NW_RELOC:      /* If this is SETGP, we set the addend to 0.  Otherwise we set	 the addend to the size of the .lita section (this is	 r_symndx) plus 1.  We have already set the address of the	 reloc to r_vaddr.  */      if (r_size == ALPHA_R_NW_RELOC_SETGP)	{	  gp_value = r_vaddr;	  rel->addend = 0;	}      else if (r_size == ALPHA_R_NW_RELOC_LITA)	{	  lita_address = r_vaddr;	  rel->addend = r_symndx + 1;	}      else	BFD_ASSERT (0);      rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;      break;    default:      break;    }  if (r_type == ALPHA_R_NW_RELOC)    rel->howto = &nlm32_alpha_nw_howto;  else    rel->howto = &nlm32_alpha_howto_table[r_type];  return true;}/* Mangle Alpha NLM relocs for output.  */static booleannlm_alpha_mangle_relocs (abfd, sec, data, offset, count)     bfd *abfd ATTRIBUTE_UNUSED;     asection *sec ATTRIBUTE_UNUSED;     PTR data ATTRIBUTE_UNUSED;     bfd_vma offset ATTRIBUTE_UNUSED;     bfd_size_type count ATTRIBUTE_UNUSED;{  return true;}/* Read an ALPHA NLM import record */static booleannlm_alpha_read_import (abfd, sym)     bfd *abfd;     nlmNAME(symbol_type) *sym;{  struct nlm_relent *nlm_relocs;	/* relocation records for symbol */  bfd_size_type rcount;			/* number of relocs */  bfd_byte temp[NLM_TARGET_LONG_SIZE];	/* temporary 32-bit value */  unsigned char symlength;		/* length of symbol name */  char *name;  if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)      != sizeof (symlength))    return false;  sym -> symbol.the_bfd = abfd;  name = bfd_alloc (abfd, symlength + 1);  if (name == NULL)    return false;  if (bfd_read (name, symlength, 1, abfd) != symlength)    return false;  name[symlength] = '\0';  sym -> symbol.name = name;  sym -> symbol.flags = 0;  sym -> symbol.value = 0;  sym -> symbol.section = bfd_und_section_ptr;  if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))    return false;  rcount = bfd_h_get_32 (abfd, temp);  nlm_relocs = ((struct nlm_relent *)		bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));  if (!nlm_relocs)    return false;  sym -> relocs = nlm_relocs;  sym -> rcnt = 0;  while (sym -> rcnt < rcount)    {      asection *section;      if (nlm_alpha_read_reloc (abfd, sym, &section,				&nlm_relocs -> reloc)	  == false)	return false;      nlm_relocs -> section = section;      nlm_relocs++;      sym -> rcnt++;    }  return true;}/* Write an Alpha NLM reloc.  */static booleannlm_alpha_write_import (abfd, sec, rel)     bfd *abfd;     asection *sec;     arelent *rel;{  asymbol *sym;  bfd_vma r_vaddr;  long r_symndx;  int r_type, r_extern, r_offset, r_size;  struct nlm32_alpha_external_reloc ext;  sym = *rel->sym_ptr_ptr;  /* Get values for the relocation fields.  */  r_type = rel->howto->type;  if (r_type != ALPHA_R_NW_RELOC)    {      r_vaddr = bfd_get_section_vma (abfd, sec) + rel->address;      if ((sec->flags & SEC_CODE) == 0)	r_vaddr += bfd_section_size (abfd,				     bfd_get_section_by_name (abfd,							      NLM_CODE_NAME));      if (bfd_is_und_section (bfd_get_section (sym)))	{	  r_extern = 1;	  r_symndx = 0;	}      else	{	  r_extern = 0;	  if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)	    r_symndx = ALPHA_RELOC_SECTION_TEXT;	  else	    r_symndx = ALPHA_RELOC_SECTION_DATA;	}      r_offset = 0;      r_size = 0;      switch (r_type)	{	case ALPHA_R_LITUSE:	case ALPHA_R_GPDISP:	  r_symndx = rel->addend;	  break;	case ALPHA_R_OP_STORE:	  r_size = rel->addend & 0xff;	  r_offset = (rel->addend >> 8) & 0xff;	  break;	case ALPHA_R_OP_PUSH:	case ALPHA_R_OP_PSUB:	case ALPHA_R_OP_PRSHIFT:	  r_vaddr = rel->addend;	  break;	case ALPHA_R_IGNORE:	  r_vaddr = rel->address;	  break;	default:	  break;	}    }  else    {      /* r_type == ALPHA_R_NW_RELOC */      r_vaddr = rel->address;      if (rel->addend == 0)	{	  r_symndx = 0;	  r_size = ALPHA_R_NW_RELOC_SETGP;	}      else	{	  r_symndx = rel->addend - 1;	  r_size = ALPHA_R_NW_RELOC_LITA;	}      r_extern = 0;      r_offset = 0;    }  /* Swap out the relocation fields.  */  bfd_h_put_64 (abfd, r_vaddr, (bfd_byte *) ext.r_vaddr);  bfd_h_put_32 (abfd, r_symndx, (bfd_byte *) ext.r_symndx);  BFD_ASSERT (bfd_little_endian (abfd));  ext.r_bits[0] = ((r_type << RELOC_BITS0_TYPE_SH_LITTLE)		   & RELOC_BITS0_TYPE_LITTLE);  ext.r_bits[1] = ((r_extern ? RELOC_BITS1_EXTERN_LITTLE : 0)		   | ((r_offset << RELOC_BITS1_OFFSET_SH_LITTLE)		      & RELOC_BITS1_OFFSET_LITTLE));  ext.r_bits[2] = 0;  ext.r_bits[3] = ((r_size << RELOC_BITS3_SIZE_SH_LITTLE)		   & RELOC_BITS3_SIZE_LITTLE);  /* Write out the relocation.  */  if (bfd_write (&ext, sizeof ext, 1, abfd) != sizeof ext)    return false;  return true;}/* Alpha NetWare does not use the high bit to determine whether a   public symbol is in the code segment or the data segment.  Instead,   it just uses the address.  The set_public_section and   get_public_offset routines override the default code which uses the   high bit.  *//* Set the section for a public symbol.  */static booleannlm_alpha_set_public_section (abfd, sym)     bfd *abfd;     nlmNAME(symbol_type) *sym;{  asection *code_sec, *data_sec;  code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);  data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);  if (sym->symbol.value < bfd_section_size (abfd, code_sec))    {      sym->symbol.section = code_sec;      sym->symbol.flags |= BSF_FUNCTION;    }  else    {      sym->symbol.section = data_sec;      sym->symbol.value -= bfd_section_size (abfd, code_sec);      /* The data segment had better be aligned.  */      BFD_ASSERT ((bfd_section_size (abfd, code_sec) & 0xf) == 0);    }  return true;}/* Get the offset to write out for a public symbol.  */static bfd_vmanlm_alpha_get_public_offset (abfd, sym)     bfd *abfd ATTRIBUTE_UNUSED;     asymbol *sym;{  return bfd_asymbol_value (sym);}/* Write an Alpha NLM external symbol.  */static booleannlm_alpha_write_external (abfd, count, sym, relocs)     bfd *abfd;     bfd_size_type count;     asymbol *sym;     struct reloc_and_sec *relocs;{  int i;  bfd_byte len;  unsigned char temp[NLM_TARGET_LONG_SIZE];  arelent r;  len = strlen (sym->name);  if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof (bfd_byte))      || bfd_write (sym->name, len, 1, abfd) != len)    return false;  bfd_put_32 (abfd, count + 2, temp);  if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))    return false;  /* The first two relocs for each external symbol are the .lita     address and the GP value.  */  r.sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;  r.howto = &nlm32_alpha_nw_howto;  r.address = nlm_alpha_backend_data (abfd)->lita_address;  r.addend = nlm_alpha_backend_data (abfd)->lita_size + 1;  if (nlm_alpha_write_import (abfd, (asection *) NULL, &r) == false)    return false;  r.address = nlm_alpha_backend_data (abfd)->gp;  r.addend = 0;  if (nlm_alpha_write_import (abfd, (asection *) NULL, &r) == false)    return false;  for (i = 0; i < count; i++)    {      if (nlm_alpha_write_import (abfd, relocs[i].sec,				  relocs[i].rel) == false)	return false;    }  return true;}#include "nlmswap.h"static const struct nlm_backend_data nlm32_alpha_backend ={  "NetWare Alpha Module   \032",  sizeof (Nlm32_alpha_External_Fixed_Header),  sizeof (struct nlm32_alpha_external_prefix_header),  bfd_arch_alpha,  0,  true, /* no uninitialized data permitted by Alpha NetWare.  */  nlm_alpha_backend_object_p,  nlm_alpha_write_prefix,  nlm_alpha_read_reloc,  nlm_alpha_mangle_relocs,  nlm_alpha_read_import,  nlm_alpha_write_import,  nlm_alpha_set_public_section,  nlm_alpha_get_public_offset,  nlm_swap_fixed_header_in,  nlm_swap_fixed_header_out,  nlm_alpha_write_external,  0,	/* write_export */};#define TARGET_LITTLE_NAME		"nlm32-alpha"#define TARGET_LITTLE_SYM		nlmNAME(alpha_vec)#define TARGET_BACKEND_DATA		&nlm32_alpha_backend#include "nlm-target.h"

⌨️ 快捷键说明

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