Movatterモバイル変換


[0]ホーム

URL:


This is the mail archive of thebinutils@sources.redhat.commailing list for thebinutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav:[Date Prev] [Date Next][Thread Prev] [Thread Next]
Other format:[Raw text]

powerpc64 multiple toc refinement


Reduces the number of toc-adjusting stubs needed, by recognizing thatcalls to leaf functions that don't use the toc can do without a stub.I've also put in a hack for the linux kernel .fixup section.  Ifsomeone can figure out how to tell a normal branch from a sibling call,we could do without the hack..bfd/ChangeLog* elf64-ppc.c (toc_adjusting_stub_needed): New function.(ppc64_elf_next_input_section): Use it here to set has_gp_reloc.Return error condition.(ppc64_elf_size_stubs): Restrict toc adjusting stubs to sectionsthat have has_gp_reloc set.(struct ppc_link_hash_table): Add stub_count.(ppc_build_one_stub): Increment it.(ppc64_elf_link_hash_table_create): zmalloc rather than clearingindividual fields.* elf64-ppc.h (ppc64_elf_next_input_section): Update prototype.ld/ChangeLog* emultempl/ppc64elf.em (build_section_lists): Check return statusfrom ppc64_elf_next_input_section.Index: bfd/elf64-ppc.c===================================================================RCS file: /cvs/src/src/bfd/elf64-ppc.c,vretrieving revision 1.109diff -u -p -r1.109 elf64-ppc.c--- bfd/elf64-ppc.c18 Jun 2003 03:26:22 -00001.109+++ bfd/elf64-ppc.c19 Jun 2003 08:37:32 -0000@@ -2803,6 +2803,9 @@ struct ppc_link_hash_table     bfd_vma offset;   } tlsld_got; +  /* Statistics.  */+  unsigned long stub_count[ppc_stub_plt_call];+   /* Set if we should emit symbols for stubs.  */   unsigned int emit_stub_syms; @@ -2893,6 +2896,8 @@ static bfd_boolean ppc_build_one_stub   PARAMS ((struct bfd_hash_entry *, PTR)); static bfd_boolean ppc_size_one_stub   PARAMS ((struct bfd_hash_entry *, PTR));+static int toc_adjusting_stub_needed+  PARAMS ((struct bfd_link_info *, asection *)); static void group_sections   PARAMS ((struct ppc_link_hash_table *, bfd_size_type, bfd_boolean)); static bfd_boolean ppc64_elf_relocate_section@@ -3031,7 +3036,7 @@ ppc64_elf_link_hash_table_create (abfd)   struct ppc_link_hash_table *htab;   bfd_size_type amt = sizeof (struct ppc_link_hash_table); -  htab = (struct ppc_link_hash_table *) bfd_malloc (amt);+  htab = (struct ppc_link_hash_table *) bfd_zmalloc (amt);   if (htab == NULL)     return NULL; @@ -3049,41 +3054,6 @@ ppc64_elf_link_hash_table_create (abfd)   if (!bfd_hash_table_init (&htab->branch_hash_table, branch_hash_newfunc))     return NULL; -  htab->stub_bfd = NULL;-  htab->add_stub_section = NULL;-  htab->layout_sections_again = NULL;-  htab->stub_group = NULL;-  htab->no_multi_toc = 0;-  htab->multi_toc_needed = 0;-  htab->toc_curr = 0;-  htab->sgot = NULL;-  htab->srelgot = NULL;-  htab->splt = NULL;-  htab->srelplt = NULL;-  htab->sdynbss = NULL;-  htab->srelbss = NULL;-  htab->sglink = NULL;-  htab->sfpr = NULL;-  htab->sbrlt = NULL;-  htab->srelbrlt = NULL;-  htab->tls_sec = NULL;-  htab->tls_get_addr = NULL;-  htab->tlsld_got.refcount = 0;-  htab->emit_stub_syms = 0;-  htab->stub_error = 0;-  htab->has_14bit_branch = 0;-  htab->have_undefweak = 0;-  htab->stub_iteration = 0;-  htab->sym_sec.abfd = NULL;-  /* Initializing two fields of the union is just cosmetic.  We really-     only care about glist, but when compiled on a 32-bit host the-     bfd_vma fields are larger.  Setting the bfd_vma to zero makes-     debugger inspection of these fields look nicer.  */-  htab->elf.init_refcount.refcount = 0;-  htab->elf.init_refcount.glist = NULL;-  htab->elf.init_offset.offset = 0;-  htab->elf.init_offset.glist = NULL;-   return &htab->elf.root; } @@ -6221,6 +6191,7 @@ ppc_build_one_stub (gen_entry, in_arg)    stub_bfd = stub_sec->owner; +  htab->stub_count[(int) stub_entry->stub_type - 1] += 1;   switch (stub_entry->stub_type)     {     case ppc_stub_long_branch:@@ -6598,17 +6569,77 @@ ppc64_elf_reinit_toc (output_bfd, info)   htab->toc_curr = TOC_BASE_OFF; } +/* No toc references were found in ISEC.  If the code in ISEC makes no+   calls, then there's no need to use toc adjusting stubs when branching+   into ISEC.  Actually, indirect calls from ISEC are OK as they will+   load r2.  */++static int+toc_adjusting_stub_needed (info, isec)+     struct bfd_link_info *info;+     asection *isec;+{+  bfd_byte *contents;+  bfd_size_type i;+  int ret;+  int branch_ok;++  /* Hack for linux kernel.  .fixup contains branches, but only back to+     the function that hit an exception.  */+  branch_ok = strcmp (isec->name, ".fixup") == 0;++  contents = elf_section_data (isec)->this_hdr.contents;+  if (contents == NULL)+    {+      contents = bfd_malloc (isec->_raw_size);+      if (contents == NULL)+return -1;+      if (! bfd_get_section_contents (isec->owner, isec, contents,+      (file_ptr) 0, isec->_raw_size))+{+  free (contents);+  return -1;+}+      if (info->keep_memory)+elf_section_data (isec)->this_hdr.contents = contents;+    }++  /* Code scan, because we don't necessarily have relocs on calls to+     static functions.  */+  ret = 0;+  for (i = 0; i < isec->_raw_size; i += 4)+    {+      unsigned long insn = bfd_get_32 (isec->owner, contents + i);+      /* Is this a branch?  */+      if ((insn & (0x1f << 26)) == (18 << 26)+  /* If branch and link, it's a function call.  */+  && ((insn & 1) != 0+      /* Sibling calls use a plain branch.  I don't know a way+ of deciding whether a branch is really a sibling call.  */+      || !branch_ok))+{+  ret = 1;+  break;+}+    }++  if (elf_section_data (isec)->this_hdr.contents != contents)+    free (contents);+  return ret;+}+ /* The linker repeatedly calls this function for each input section,    in the order that input sections are linked into output sections.    Build lists of input sections to determine groupings between which    we may insert linker stubs.  */ -void+bfd_boolean ppc64_elf_next_input_section (info, isec)      struct bfd_link_info *info;      asection *isec; {   struct ppc_link_hash_table *htab = ppc_hash_table (info);+  int ret;    if ((isec->output_section->flags & SEC_CODE) != 0       && isec->output_section->index <= htab->top_index)@@ -6626,13 +6657,20 @@ ppc64_elf_next_input_section (info, isec      to use the right TOC (obviously).  Also, make sure that .opd gets      the correct TOC value.  */   if (isec->has_gp_reloc || (isec->flags & SEC_CODE) == 0)-    if (elf_gp (isec->owner) != 0)-      htab->toc_curr = elf_gp (isec->owner);+    {+      if (elf_gp (isec->owner) != 0)+htab->toc_curr = elf_gp (isec->owner);+    }+  else if ((ret = toc_adjusting_stub_needed (info, isec)) < 0)+    return FALSE;+  else+    isec->has_gp_reloc = ret;    /* Functions that don't use the TOC can belong in any TOC group.      Use the last TOC base.  This happens to make _init and _fini      pasting work.  */   htab->stub_group[isec->id].toc_off = htab->toc_curr;+  return TRUE; }  /* See whether we can group stub sections together.  Grouping stub@@ -6904,7 +6942,9 @@ ppc64_elf_size_stubs (output_bfd, stub_b       if (sym_sec != NULL   && sym_sec->output_section != NULL   && (htab->stub_group[sym_sec->id].toc_off-      != htab->stub_group[section->id].toc_off))+      != htab->stub_group[section->id].toc_off)+  && sym_sec->has_gp_reloc+  && section->has_gp_reloc) stub_type = ppc_stub_long_branch_r2off;     } Index: bfd/elf64-ppc.h===================================================================RCS file: /cvs/src/src/bfd/elf64-ppc.h,vretrieving revision 1.9diff -u -p -r1.9 elf64-ppc.h--- bfd/elf64-ppc.h8 Jun 2003 14:06:38 -00001.9+++ bfd/elf64-ppc.h19 Jun 2003 04:50:30 -0000@@ -33,7 +33,7 @@ void ppc64_elf_next_toc_section   PARAMS ((struct bfd_link_info *, asection *)); void ppc64_elf_reinit_toc   PARAMS ((bfd *, struct bfd_link_info *));-void ppc64_elf_next_input_section+bfd_boolean ppc64_elf_next_input_section   PARAMS ((struct bfd_link_info *, asection *)); bfd_boolean ppc64_elf_size_stubs   PARAMS ((bfd *, bfd *, struct bfd_link_info *, bfd_signed_vma,Index: ld/emultempl/ppc64elf.em===================================================================RCS file: /cvs/src/src/ld/emultempl/ppc64elf.em,vretrieving revision 1.17diff -u -p -r1.17 ppc64elf.em--- ld/emultempl/ppc64elf.em8 Jun 2003 14:07:34 -00001.17+++ ld/emultempl/ppc64elf.em19 Jun 2003 04:50:30 -0000@@ -323,8 +323,9 @@ build_section_lists (statement)       && statement->input_section.section->output_section != NULL       && statement->input_section.section->output_section->owner == output_bfd)     {-      ppc64_elf_next_input_section (&link_info,-    statement->input_section.section);+      if (!ppc64_elf_next_input_section (&link_info,+ statement->input_section.section))+einfo ("%X%P: can not size stub section: %E\n");     } } -- Alan ModraIBM OzLabs - Linux Technology Centre

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav:[Date Prev] [Date Next][Thread Prev] [Thread Next]

[8]ページ先頭

©2009-2025 Movatter.jp