elf64-hppa.c

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

C
2,237
字号
      stub = bfd_make_section (dynobj, ".stub");      if (!stub	  || !bfd_set_section_flags (dynobj, stub,				     (SEC_ALLOC				      | SEC_LOAD				      | SEC_HAS_CONTENTS				      | SEC_IN_MEMORY				      | SEC_READONLY				      | SEC_LINKER_CREATED))	  || !bfd_set_section_alignment (abfd, stub, 3))	{	  BFD_ASSERT (0);	  return false;	}      hppa_info->stub_sec = stub;    }  return true;}/* Create sections necessary for dynamic linking.  This is only a rough   cut and will likely change as we learn more about the somewhat   unusual dynamic linking scheme HP uses.   .stub:	Contains code to implement cross-space calls.  The first time one	of the stubs is used it will call into the dynamic linker, later	calls will go straight to the target.	The only stub we support right now looks like	ldd OFFSET(%dp),%r1	bve %r0(%r1)	ldd OFFSET+8(%dp),%dp	Other stubs may be needed in the future.  We may want the remove	the break/nop instruction.  It is only used right now to keep the	offset of a .plt entry and a .stub entry in sync.   .dlt:	This is what most people call the .got.  HP used a different name.	Losers.   .rela.dlt:	Relocations for the DLT.   .plt:	Function pointers as address,gp pairs.   .rela.plt:	Should contain dynamic IPLT (and EPLT?) relocations.   .opd:	FPTRS   .rela.opd:	EPLT relocations for symbols exported from shared libraries.  */static booleanelf64_hppa_create_dynamic_sections (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  asection *s;  if (! get_stub (abfd, info, elf64_hppa_hash_table (info)))    return false;  if (! get_dlt (abfd, info, elf64_hppa_hash_table (info)))    return false;  if (! get_plt (abfd, info, elf64_hppa_hash_table (info)))    return false;  if (! get_opd (abfd, info, elf64_hppa_hash_table (info)))    return false;  s = bfd_make_section(abfd, ".rela.dlt");  if (s == NULL      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD					   | SEC_HAS_CONTENTS					   | SEC_IN_MEMORY					   | SEC_READONLY					   | SEC_LINKER_CREATED))      || !bfd_set_section_alignment (abfd, s, 3))    return false;  elf64_hppa_hash_table (info)->dlt_rel_sec = s;  s = bfd_make_section(abfd, ".rela.plt");  if (s == NULL      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD					   | SEC_HAS_CONTENTS					   | SEC_IN_MEMORY					   | SEC_READONLY					   | SEC_LINKER_CREATED))      || !bfd_set_section_alignment (abfd, s, 3))    return false;  elf64_hppa_hash_table (info)->plt_rel_sec = s;  s = bfd_make_section(abfd, ".rela.data");  if (s == NULL      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD					   | SEC_HAS_CONTENTS					   | SEC_IN_MEMORY					   | SEC_READONLY					   | SEC_LINKER_CREATED))      || !bfd_set_section_alignment (abfd, s, 3))    return false;  elf64_hppa_hash_table (info)->other_rel_sec = s;  s = bfd_make_section(abfd, ".rela.opd");  if (s == NULL      || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD					   | SEC_HAS_CONTENTS					   | SEC_IN_MEMORY					   | SEC_READONLY					   | SEC_LINKER_CREATED))      || !bfd_set_section_alignment (abfd, s, 3))    return false;  elf64_hppa_hash_table (info)->opd_rel_sec = s;  return true;}/* Allocate dynamic relocations for those symbols that turned out   to be dynamic.  */static booleanallocate_dynrel_entries (dyn_h, data)     struct elf64_hppa_dyn_hash_entry *dyn_h;     PTR data;{  struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;  struct elf64_hppa_link_hash_table *hppa_info;  struct elf64_hppa_dyn_reloc_entry *rent;  boolean dynamic_symbol, shared;  hppa_info = elf64_hppa_hash_table (x->info);  dynamic_symbol = elf64_hppa_dynamic_symbol_p (dyn_h->h, x->info);  shared = x->info->shared;  /* We may need to allocate relocations for a non-dynamic symbol     when creating a shared library.  */  if (!dynamic_symbol && !shared)    return true;  /* Take care of the normal data relocations.  */  for (rent = dyn_h->reloc_entries; rent; rent = rent->next)    {      switch (rent->type)	{	case R_PARISC_FPTR64:	  /* Allocate one iff we are not building a shared library and	     !want_opd, which by this point will be true only if we're	     actually allocating one statically in the main executable.  */	  if (!x->info->shared && dyn_h->want_opd)	    continue;	  break;	}      hppa_info->other_rel_sec->_raw_size += sizeof (Elf64_External_Rela);      /* Make sure this symbol gets into the dynamic symbol table if it is	 not already recorded.  ?!? This should not be in the loop since	 the symbol need only be added once.  */      if (dyn_h->h == 0 || dyn_h->h->dynindx == -1)	if (!_bfd_elf64_link_record_local_dynamic_symbol	    (x->info, rent->sec->owner, dyn_h->sym_indx))	  return false;    }  /* Take care of the GOT and PLT relocations.  */  if ((dynamic_symbol || shared) && dyn_h->want_dlt)    hppa_info->dlt_rel_sec->_raw_size += sizeof (Elf64_External_Rela);  /* If we are building a shared library, then every symbol that has an     opd entry will need an EPLT relocation to relocate the symbol's address     and __gp value based on the runtime load address.  */  if (shared && dyn_h->want_opd)    hppa_info->opd_rel_sec->_raw_size += sizeof (Elf64_External_Rela);  if (dyn_h->want_plt && dynamic_symbol)    {      bfd_size_type t = 0;      /* Dynamic symbols get one IPLT relocation.  Local symbols in	 shared libraries get two REL relocations.  Local symbols in	 main applications get nothing.  */      if (dynamic_symbol)	t = sizeof (Elf64_External_Rela);      else if (shared)	t = 2 * sizeof (Elf64_External_Rela);      hppa_info->plt_rel_sec->_raw_size += t;    }  return true;}/* Adjust a symbol defined by a dynamic object and referenced by a   regular object.  */static booleanelf64_hppa_adjust_dynamic_symbol (info, h)     struct bfd_link_info *info ATTRIBUTE_UNUSED;     struct elf_link_hash_entry *h;{  /* ??? Undefined symbols with PLT entries should be re-defined     to be the PLT entry.  */  /* If this is a weak symbol, and there is a real definition, the     processor independent code will have arranged for us to see the     real definition first, and we can just use the same value.  */  if (h->weakdef != NULL)    {      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined		  || h->weakdef->root.type == bfd_link_hash_defweak);      h->root.u.def.section = h->weakdef->root.u.def.section;      h->root.u.def.value = h->weakdef->root.u.def.value;      return true;    }  /* If this is a reference to a symbol defined by a dynamic object which     is not a function, we might allocate the symbol in our .dynbss section     and allocate a COPY dynamic relocation.     But PA64 code is canonically PIC, so as a rule we can avoid this sort     of hackery.  */  return true;}/* Set the final sizes of the dynamic sections and allocate memory for   the contents of our special sections.  */static booleanelf64_hppa_size_dynamic_sections (output_bfd, info)     bfd *output_bfd;     struct bfd_link_info *info;{  bfd *dynobj;  asection *s;  boolean plt;  boolean relocs;  boolean reltext;  struct elf64_hppa_allocate_data data;  struct elf64_hppa_link_hash_table *hppa_info;  hppa_info = elf64_hppa_hash_table (info);  dynobj = elf_hash_table (info)->dynobj;  BFD_ASSERT (dynobj != NULL);  if (elf_hash_table (info)->dynamic_sections_created)    {      /* Set the contents of the .interp section to the interpreter.  */      if (! info->shared)	{	  s = bfd_get_section_by_name (dynobj, ".interp");	  BFD_ASSERT (s != NULL);	  s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;	}    }  else    {      /* We may have created entries in the .rela.got section.	 However, if we are not creating the dynamic sections, we will	 not actually use these entries.  Reset the size of .rela.dlt,	 which will cause it to get stripped from the output file	 below.  */      s = bfd_get_section_by_name (dynobj, ".rela.dlt");      if (s != NULL)	s->_raw_size = 0;    }  /* Allocate the GOT entries.  */  data.info = info;  if (elf64_hppa_hash_table (info)->dlt_sec)    {      data.ofs = 0x0;      elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,				    allocate_global_data_dlt, &data);      hppa_info->dlt_sec->_raw_size = data.ofs;      data.ofs = 0x0;      elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,				    allocate_global_data_plt, &data);      hppa_info->plt_sec->_raw_size = data.ofs;      data.ofs = 0x0;      elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,				    allocate_global_data_stub, &data);      hppa_info->stub_sec->_raw_size = data.ofs;    }  /* Mark each function this program exports so that we will allocate     space in the .opd section for each function's FPTR.     We have to traverse the main linker hash table since we have to     find functions which may not have been mentioned in any relocs.  */  elf_link_hash_traverse (elf_hash_table (info),			  elf64_hppa_mark_exported_functions,			  info);  /* Allocate space for entries in the .opd section.  */  if (elf64_hppa_hash_table (info)->opd_sec)    {      data.ofs = 0;      elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,				    allocate_global_data_opd, &data);      hppa_info->opd_sec->_raw_size = data.ofs;    }  /* Now allocate space for dynamic relocations, if necessary.  */  if (hppa_info->root.dynamic_sections_created)    elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,				  allocate_dynrel_entries, &data);  /* The sizes of all the sections are set.  Allocate memory for them.  */  plt = false;  relocs = false;  reltext = false;  for (s = dynobj->sections; s != NULL; s = s->next)    {      const char *name;      boolean strip;      if ((s->flags & SEC_LINKER_CREATED) == 0)	continue;      /* It's OK to base decisions on the section name, because none	 of the dynobj section names depend upon the input files.  */      name = bfd_get_section_name (dynobj, s);      strip = 0;      if (strcmp (name, ".plt") == 0)	{	  if (s->_raw_size == 0)	    {	      /* Strip this section if we don't need it; see the		 comment below.  */	      strip = true;	    }	  else	    {	      /* Remember whether there is a PLT.  */	      plt = true;	    }	}      else if (strcmp (name, ".dlt") == 0)	{	  if (s->_raw_size == 0)	    {	      /* Strip this section if we don't need it; see the		 comment below.  */	      strip = true;	    }	}      else if (strcmp (name, ".opd") == 0)	{	  if (s->_raw_size == 0)	    {	      /* Strip this section if we don't need it; see the		 comment below.  */	      strip = true;	    }	}      else if (strncmp (name, ".rela", 4) == 0)	{	  if (s->_raw_size == 0)	    {	      /* If we don't need this section, strip it from the		 output file.  This is mostly to handle .rela.bss and		 .rela.plt.  We must create both sections in		 create_dynamic_sections, because they must be created		 before the linker maps input sections to output		 sections.  The linker does that before		 adjust_dynamic_symbol is called, and it is that		 function which decides whether anything needs to go		 into these sections.  */	      strip = true;	    }	  else	    {	      asection *target;	      /* Remember whether there are any reloc sections other		 than .rela.plt.  */	      if (strcmp (name, ".rela.plt") != 0)		{		  const char *outname;		  relocs = true;		  /* If this relocation section applies to a read only		     section, then we probably need a DT_TEXTREL		     entry.  The entries in the .rela.plt section		     really apply to the .got section, which we		     created ourselves and so know is not readonly.  */		  outname = bfd_get_section_name (output_bfd,						  s->output_section);		  target = bfd_get_section_by_name (output_bfd, outname + 4);		  if (target != NULL		      && (target->flags & SEC_READONLY) != 0		      && (target->flags & SEC_ALLOC) != 0)		    reltext = true;		}	      /* We use the reloc_count field as a counter if we need		 to copy relocs into the output file.  */	      s->reloc_count = 0;	    }	}      else if (strncmp (name, ".dlt", 4) != 0	       && strcmp (name, ".stub") != 0	       && strcmp (name, ".got") != 0)	{	  /* It's not one of our sections, so don't allocate space.  */	  continue;	}      if (strip)	{	  _bfd_strip_section_from_output (info, s);	  continue;	}      /* Allocate memory for the section contents if it has not	 been allocated already.  We use bfd_zalloc here in case	 unused entries are not reclaimed before the section's	 contents are written out.  This should not happen, but this	 way if it does, we get a R_PARISC_NONE reloc instead of	 garbage.  */      if (s->contents == NULL)	{	  s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);	  if (s->contents == NULL && s->_raw_size != 0)	    return false;	}    }  if (elf_hash_table (info)->dynamic_sections_created)    {

⌨️ 快捷键说明

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