coff-alpha.c

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

C
2,226
字号
	     a memory reference, and permits removing a value from	     .lita thus saving GP relative space.	     We do not these optimizations.  To do them we would need	     to arrange to link the .lita section first, so that by	     the time we got here we would know the final values to	     use.  This would not be particularly difficult, but it is	     not currently implemented.  */	  {	    unsigned long insn;	    /* I believe that the LITERAL reloc will only apply to a	       ldq or ldl instruction, so check my assumption.  */	    insn = bfd_get_32 (input_bfd, data + rel->address);	    BFD_ASSERT (((insn >> 26) & 0x3f) == 0x29			|| ((insn >> 26) & 0x3f) == 0x28);	    rel->addend -= gp;	    r = bfd_perform_relocation (input_bfd, rel, data, input_section,					output_bfd, &err);	    if (r == bfd_reloc_ok && gp_undefined)	      {		r = bfd_reloc_dangerous;		err =		  (char *) _("GP relative relocation used when GP not defined");	      }	  }	  break;	case ALPHA_R_LITUSE:	  /* See ALPHA_R_LITERAL above for the uses of this reloc.  It	     does not cause anything to happen, itself.  */	  rel->address += input_section->output_offset;	  break;	case ALPHA_R_GPDISP:	  /* This marks the ldah of an ldah/lda pair which loads the	     gp register with the difference of the gp value and the	     current location.  The second of the pair is r_size bytes	     ahead; it used to be marked with an ALPHA_R_IGNORE reloc,	     but that no longer happens in OSF/1 3.2.  */	  {	    unsigned long insn1, insn2;	    bfd_vma addend;	    /* Get the two instructions.  */	    insn1 = bfd_get_32 (input_bfd, data + rel->address);	    insn2 = bfd_get_32 (input_bfd, data + rel->address + rel->addend);	    BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */	    BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */	    /* Get the existing addend.  We must account for the sign	       extension done by lda and ldah.  */	    addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff);	    if (insn1 & 0x8000)	      {		addend -= 0x80000000;		addend -= 0x80000000;	      }	    if (insn2 & 0x8000)	      addend -= 0x10000;	    /* The existing addend includes the different between the	       gp of the input BFD and the address in the input BFD.	       Subtract this out.  */	    addend -= (ecoff_data (input_bfd)->gp		       - (input_section->vma + rel->address));	    /* Now add in the final gp value, and subtract out the	       final address.  */	    addend += (gp		       - (input_section->output_section->vma			  + input_section->output_offset			  + rel->address));	    /* Change the instructions, accounting for the sign	       extension, and write them out.  */	    if (addend & 0x8000)	      addend += 0x10000;	    insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff);	    insn2 = (insn2 & 0xffff0000) | (addend & 0xffff);	    bfd_put_32 (input_bfd, (bfd_vma) insn1, data + rel->address);	    bfd_put_32 (input_bfd, (bfd_vma) insn2,			data + rel->address + rel->addend);	    rel->address += input_section->output_offset;	  }	  break;	case ALPHA_R_OP_PUSH:	  /* Push a value on the reloc evaluation stack.  */	  {	    asymbol *symbol;	    bfd_vma relocation;	    if (relocateable)	      {		rel->address += input_section->output_offset;		break;	      }	    /* Figure out the relocation of this symbol.  */	    symbol = *rel->sym_ptr_ptr;	    if (bfd_is_und_section (symbol->section))	      r = bfd_reloc_undefined;	    if (bfd_is_com_section (symbol->section))	      relocation = 0;	    else	      relocation = symbol->value;	    relocation += symbol->section->output_section->vma;	    relocation += symbol->section->output_offset;	    relocation += rel->addend;	    if (tos >= RELOC_STACKSIZE)	      abort ();	    stack[tos++] = relocation;	  }	  break;	case ALPHA_R_OP_STORE:	  /* Store a value from the reloc stack into a bitfield.  */	  {	    bfd_vma val;	    int offset, size;	    if (relocateable)	      {		rel->address += input_section->output_offset;		break;	      }	    if (tos == 0)	      abort ();	    /* The offset and size for this reloc are encoded into the	       addend field by alpha_adjust_reloc_in.  */	    offset = (rel->addend >> 8) & 0xff;	    size = rel->addend & 0xff;	    val = bfd_get_64 (abfd, data + rel->address);	    val &=~ (((1 << size) - 1) << offset);	    val |= (stack[--tos] & ((1 << size) - 1)) << offset;	    bfd_put_64 (abfd, val, data + rel->address);	  }	  break;	case ALPHA_R_OP_PSUB:	  /* Subtract a value from the top of the stack.  */	  {	    asymbol *symbol;	    bfd_vma relocation;	    if (relocateable)	      {		rel->address += input_section->output_offset;		break;	      }	    /* Figure out the relocation of this symbol.  */	    symbol = *rel->sym_ptr_ptr;	    if (bfd_is_und_section (symbol->section))	      r = bfd_reloc_undefined;	    if (bfd_is_com_section (symbol->section))	      relocation = 0;	    else	      relocation = symbol->value;	    relocation += symbol->section->output_section->vma;	    relocation += symbol->section->output_offset;	    relocation += rel->addend;	    if (tos == 0)	      abort ();	    stack[tos - 1] -= relocation;	  }	  break;	case ALPHA_R_OP_PRSHIFT:	  /* Shift the value on the top of the stack.  */	  {	    asymbol *symbol;	    bfd_vma relocation;	    if (relocateable)	      {		rel->address += input_section->output_offset;		break;	      }	    /* Figure out the relocation of this symbol.  */	    symbol = *rel->sym_ptr_ptr;	    if (bfd_is_und_section (symbol->section))	      r = bfd_reloc_undefined;	    if (bfd_is_com_section (symbol->section))	      relocation = 0;	    else	      relocation = symbol->value;	    relocation += symbol->section->output_section->vma;	    relocation += symbol->section->output_offset;	    relocation += rel->addend;	    if (tos == 0)	      abort ();	    stack[tos - 1] >>= relocation;	  }	  break;	case ALPHA_R_GPVALUE:	  /* I really don't know if this does the right thing.  */	  gp = rel->addend;	  gp_undefined = false;	  break;	default:	  abort ();	}      if (relocateable)	{	  asection *os = input_section->output_section;	  /* A partial link, so keep the relocs.  */	  os->orelocation[os->reloc_count] = rel;	  os->reloc_count++;	}      if (r != bfd_reloc_ok)	{	  switch (r)	    {	    case bfd_reloc_undefined:	      if (! ((*link_info->callbacks->undefined_symbol)		     (link_info, bfd_asymbol_name (*rel->sym_ptr_ptr),		      input_bfd, input_section, rel->address, true)))		goto error_return;	      break;	    case bfd_reloc_dangerous:	      if (! ((*link_info->callbacks->reloc_dangerous)		     (link_info, err, input_bfd, input_section,		      rel->address)))		goto error_return;	      break;	    case bfd_reloc_overflow:	      if (! ((*link_info->callbacks->reloc_overflow)		     (link_info, bfd_asymbol_name (*rel->sym_ptr_ptr),		      rel->howto->name, rel->addend, input_bfd,		      input_section, rel->address)))		goto error_return;	      break;	    case bfd_reloc_outofrange:	    default:	      abort ();	      break;	    }	}    }  if (tos != 0)    abort (); successful_return:  if (reloc_vector != NULL)    free (reloc_vector);  return data; error_return:  if (reloc_vector != NULL)    free (reloc_vector);  return NULL;}/* Get the howto structure for a generic reloc type.  */static reloc_howto_type *alpha_bfd_reloc_type_lookup (abfd, code)     bfd *abfd ATTRIBUTE_UNUSED;     bfd_reloc_code_real_type code;{  int alpha_type;  switch (code)    {    case BFD_RELOC_32:      alpha_type = ALPHA_R_REFLONG;      break;    case BFD_RELOC_64:    case BFD_RELOC_CTOR:      alpha_type = ALPHA_R_REFQUAD;      break;    case BFD_RELOC_GPREL32:      alpha_type = ALPHA_R_GPREL32;      break;    case BFD_RELOC_ALPHA_LITERAL:      alpha_type = ALPHA_R_LITERAL;      break;    case BFD_RELOC_ALPHA_LITUSE:      alpha_type = ALPHA_R_LITUSE;      break;    case BFD_RELOC_ALPHA_GPDISP_HI16:      alpha_type = ALPHA_R_GPDISP;      break;    case BFD_RELOC_ALPHA_GPDISP_LO16:      alpha_type = ALPHA_R_IGNORE;      break;    case BFD_RELOC_23_PCREL_S2:      alpha_type = ALPHA_R_BRADDR;      break;    case BFD_RELOC_ALPHA_HINT:      alpha_type = ALPHA_R_HINT;      break;    case BFD_RELOC_16_PCREL:      alpha_type = ALPHA_R_SREL16;      break;    case BFD_RELOC_32_PCREL:      alpha_type = ALPHA_R_SREL32;      break;    case BFD_RELOC_64_PCREL:      alpha_type = ALPHA_R_SREL64;      break;#if 0    case ???:      alpha_type = ALPHA_R_OP_PUSH;      break;    case ???:      alpha_type = ALPHA_R_OP_STORE;      break;    case ???:      alpha_type = ALPHA_R_OP_PSUB;      break;    case ???:      alpha_type = ALPHA_R_OP_PRSHIFT;      break;    case ???:      alpha_type = ALPHA_R_GPVALUE;      break;#endif    default:      return (reloc_howto_type *) NULL;    }  return &alpha_howto_table[alpha_type];}/* A helper routine for alpha_relocate_section which converts an   external reloc when generating relocateable output.  Returns the   relocation amount.  */static bfd_vmaalpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h)     bfd *output_bfd ATTRIBUTE_UNUSED;     struct bfd_link_info *info;     bfd *input_bfd;     struct external_reloc *ext_rel;     struct ecoff_link_hash_entry *h;{  unsigned long r_symndx;  bfd_vma relocation;  BFD_ASSERT (info->relocateable);  if (h->root.type == bfd_link_hash_defined      || h->root.type == bfd_link_hash_defweak)    {      asection *hsec;      const char *name;      /* This symbol is defined in the output.  Convert the reloc from	 being against the symbol to being against the section.  */      /* Clear the r_extern bit.  */      ext_rel->r_bits[1] &=~ RELOC_BITS1_EXTERN_LITTLE;      /* Compute a new r_symndx value.  */      hsec = h->root.u.def.section;      name = bfd_get_section_name (output_bfd, hsec->output_section);      r_symndx = -1;      switch (name[1])	{	case 'A':	  if (strcmp (name, "*ABS*") == 0)	    r_symndx = RELOC_SECTION_ABS;	  break;	case 'b':	  if (strcmp (name, ".bss") == 0)	    r_symndx = RELOC_SECTION_BSS;	  break;	case 'd':	  if (strcmp (name, ".data") == 0)	    r_symndx = RELOC_SECTION_DATA;	  break;	case 'f':	  if (strcmp (name, ".fini") == 0)	    r_symndx = RELOC_SECTION_FINI;	  break;	case 'i':	  if (strcmp (name, ".init") == 0)	    r_symndx = RELOC_SECTION_INIT;	  break;	case 'l':	  if (strcmp (name, ".lita") == 0)	    r_symndx = RELOC_SECTION_LITA;	  else if (strcmp (name, ".lit8") == 0)	    r_symndx = RELOC_SECTION_LIT8;	  else if (strcmp (name, ".lit4") == 0)	    r_symndx = RELOC_SECTION_LIT4;	  break;	case 'p':	  if (strcmp (name, ".pdata") == 0)	    r_symndx = RELOC_SECTION_PDATA;	  break;	case 'r':	  if (strcmp (name, ".rdata") == 0)	    r_symndx = RELOC_SECTION_RDATA;	  else if (strcmp (name, ".rconst") == 0)	    r_symndx = RELOC_SECTION_RCONST;	  break;	case 's':	  if (strcmp (name, ".sdata") == 0)	    r_symndx = RELOC_SECTION_SDATA;	  else if (strcmp (name, ".sbss") == 0)	    r_symndx = RELOC_SECTION_SBSS;	  break;	case 't':	  if (strcmp (name, ".text") == 0)	    r_symndx = RELOC_SECTION_TEXT;	  break;	case 'x':	  if (strcmp (name, ".xdata") == 0)	    r_symndx = RELOC_SECTION_XDATA;	  break;	}      if (r_symndx == -1)	abort ();

⌨️ 快捷键说明

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