This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils 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]

Re: [PATCH] Deleting discardable stabs


On Tue, Nov 13, 2001 at 08:55:52AM +1030, Alan Modra wrote:
> On Mon, Nov 12, 2001 at 10:28:08AM -0500, Daniel Jacobowitz wrote:
> > On Tue, Nov 13, 2001 at 12:22:31AM +1030, Alan Modra wrote:
> > > On Sun, Nov 11, 2001 at 10:03:40PM -0500, Daniel Jacobowitz wrote:
> > > > +
> > > > +      if (! rcookie->bad_symtab)
> > > > +	if (rcookie->rel->r_offset > offset)
> > > > +	  return false;
> > > 
> > > Hmm, I guess it's reasonable to assume the relocs will always be sorted.
> > > Assemblers other than gas?
> > 
> > My reading is that the relocs will be sorted unless elf_bad_symtab() is
> > true.  Maybe that's not correct... I could read in the relocations and
> > then sort them, I suppose.  Should I do that explicitly?
> 
> No, I don't think it worth doing unless someone can show a situation
> where some other assembler emits relocs out of order.  That doesn't seem
> likely, and "ld -r" keeps the relocs sorted too.

OK.  I see that for MIPS shared objects we sort dynamic relocs by
symbol index instead of by offset, which strikes me as somewhat odd,
but I'll assume that object files are always OK.

For what it's worth, I suspect info->emitrelocations won't work
properly; I never modify the relocs, just the cooked sections.  That
was already true for stabs sections though.  It could be fixed but I'm
not going to do it right now.  This also depends on us not crashing
when we actually do a reloc against a removed symbol; I only supress
the warning.  I can't zero the relocs at the appropriate time without
adding another callback, because if info->keep_memory is zero, they'll
be re-read from the input bfd before the final link is performed.

I think I've fixed all other issues with this patch, as well as added
support for pruning .pdr in a similar fashion on MIPS.  How's it look?

-- 
Daniel Jacobowitz                           Carnegie Mellon University
MontaVista Software                         Debian GNU/Linux Developer

2001-11-11  Daniel Jacobowitz  <drow@mvista.com>

	* bfd-in.h (bfd_elf32_discard_info): Add prototype.
	(bfd_elf64_discard_info): Likewise.
	* bfd-in2.h: Regenerate.
	* elf-bfd.h (struct elf_reloc_cookie): New.
	(struct elf_backend_data): Add elf_backend_discard_info,
	elf_backend_ignore_discarded_relocs, and elf_backend_write_section.
	(_bfd_elf32_reloc_symbol_deleted_p): Add prototype.
	(_bfd_elf64_reloc_symbol_deleted_p): Likewise.
	* elf32-mips.c (_bfd_elf32_mips_discard_info): New.
	(_bfd_elf32_mips_ignore_discarded_relocs): New.
	(_bfd_elf32_mips_write_section): New.
	(elf_backend_discard_info): Define.
	(elf_backend_ignore_discarded_relocs): Define.
	(elf_backend_write_section): Define.
	* elfcode.h (elf_bfd_discard_info): Define.
	(elf_reloc_symbol_deleted_p): Define.
	* elflink.h (elf_link_input_bfd): Check
	elf_section_ignore_discarded_relocs.  Call
	bed->elf_backend_write_section if available.
	(elf_reloc_symbol_deleted_p): New.
	(elf_bfd_discard_info): New.
	(elf_section_ignore_discarded_relocs): New.
	* elfxx-target.h (elf_backend_discard_info): Define.
	(elf_backend_ignore_discarded_relocs): Define.
	(elf_backend_write_section): Define.
	(elfNN_bed): Add elf_backend_discard_info,
	elf_backend_ignore_discarded_relocs, and
	elf_backend_write_section.
	* libbfd-in.h (_bfd_discard_section_stabs): Add prototype.
	* libbfd.h: Regenerate.
	* stabs.c (_bfd_discard_section_stabs): New.

2001-11-11  Daniel Jacobowitz  <drow@mvista.com>

	* emultempl/elf32.em (gld${EMULATION_NAME}_finish): New.
	(struct ld_emulation_xfer_struct): Use it.

Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.35
diff -u -p -r1.35 bfd-in.h
--- bfd-in.h	2001/10/02 05:58:37	1.35
+++ bfd-in.h	2001/11/13 21:10:11
@@ -635,6 +635,10 @@ extern void bfd_elf_set_dt_needed_soname
 extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
 extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
   PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf32_discard_info
+  PARAMS ((struct bfd_link_info *));
+extern boolean bfd_elf64_discard_info
+  PARAMS ((struct bfd_link_info *));
 
 /* Return an upper bound on the number of bytes required to store a
    copy of ABFD's program header table entries.  Return -1 if an error
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.126
diff -u -p -r1.126 bfd-in2.h
--- bfd-in2.h	2001/10/30 15:20:02	1.126
+++ bfd-in2.h	2001/11/13 21:10:12
@@ -641,6 +641,10 @@ extern void bfd_elf_set_dt_needed_soname
 extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
 extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
   PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf32_discard_info
+  PARAMS ((struct bfd_link_info *));
+extern boolean bfd_elf64_discard_info
+  PARAMS ((struct bfd_link_info *));
 
 /* Return an upper bound on the number of bytes required to store a
    copy of ABFD's program header table entries.  Return -1 if an error
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.54
diff -u -p -r1.54 elf-bfd.h
--- elf-bfd.h	2001/11/10 00:23:34	1.54
+++ elf-bfd.h	2001/11/13 21:10:12
@@ -381,6 +381,17 @@ enum elf_reloc_type_class {
   reloc_class_copy
 };
 
+struct elf_reloc_cookie
+{
+  Elf_Internal_Rela *rels, *rel, *relend;
+  void *locsyms;
+  bfd *abfd;
+  size_t locsymcount;
+  size_t extsymoff;
+  struct elf_link_hash_entry **sym_hashes;
+  boolean bad_symtab;
+};
+
 struct elf_backend_data
 {
   /* The architecture for this backend.  */
@@ -703,6 +714,21 @@ struct elf_backend_data
   enum elf_reloc_type_class (*elf_backend_reloc_type_class)
     PARAMS ((const Elf_Internal_Rela *));
 
+  /* This function, if defined, removes information about discarded functions
+     from other sections which mention them.  */
+  boolean (*elf_backend_discard_info)
+    PARAMS ((bfd *, struct elf_reloc_cookie *, struct bfd_link_info *));
+
+  /* This function, if defined, signals that the function above has removed
+     the discarded relocations for this section.  */
+  boolean (*elf_backend_ignore_discarded_relocs)
+    PARAMS ((asection *));
+
+  /* This function, if defined, may write out the given section.
+     Returns true if it did so and false if the caller should.  */
+  boolean (*elf_backend_write_section)
+    PARAMS ((bfd *, asection *, bfd_byte *));
+
   /* The swapping table to use when dealing with ECOFF information.
      Used for the MIPS ELF .mdebug section.  */
   const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap;
@@ -1436,6 +1462,11 @@ extern boolean _bfd_elf64_gc_record_vtin
   PARAMS ((bfd *, asection *, struct elf_link_hash_entry *, bfd_vma));
 extern boolean _bfd_elf64_gc_record_vtentry
   PARAMS ((bfd *, asection *, struct elf_link_hash_entry *, bfd_vma));
+
+extern boolean _bfd_elf32_reloc_symbol_deleted_p
+  PARAMS ((bfd_vma, PTR));
+extern boolean _bfd_elf64_reloc_symbol_deleted_p
+  PARAMS ((bfd_vma, PTR));
 
 /* MIPS ELF specific routines.  */
 
Index: bfd/elf32-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-mips.c,v
retrieving revision 1.125
diff -u -p -r1.125 elf32-mips.c
--- elf32-mips.c	2001/11/11 23:51:36	1.125
+++ elf32-mips.c	2001/11/13 21:10:12
@@ -219,6 +219,12 @@ static boolean _bfd_elf32_mips_grok_prst
   PARAMS ((bfd *, Elf_Internal_Note *));
 static boolean _bfd_elf32_mips_grok_psinfo
   PARAMS ((bfd *, Elf_Internal_Note *));
+static boolean _bfd_elf32_mips_discard_info
+  PARAMS ((bfd *, struct elf_reloc_cookie *, struct bfd_link_info *));
+static boolean _bfd_elf32_mips_ignore_discarded_relocs
+  PARAMS ((asection *));
+static boolean _bfd_elf32_mips_write_section
+  PARAMS ((bfd *, asection *, bfd_byte *));
 
 extern const bfd_target bfd_elf32_tradbigmips_vec;
 extern const bfd_target bfd_elf32_tradlittlemips_vec;
@@ -9226,6 +9232,114 @@ _bfd_elf32_mips_grok_psinfo (abfd, note)
   return true;
 }
 
+#define PDR_SIZE 32
+
+static boolean
+_bfd_elf32_mips_discard_info (abfd, cookie, info)
+     bfd *abfd;
+     struct elf_reloc_cookie *cookie;
+     struct bfd_link_info *info;
+{
+  asection *o;
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  boolean ret = false;
+  unsigned char *tdata;
+  size_t i, skip;
+
+  o = bfd_get_section_by_name (abfd, ".pdr");
+  if (! o)
+    return false;
+  if (o->_raw_size == 0)
+    return false;
+  if (o->_raw_size % PDR_SIZE != 0)
+    return false;
+  if (o->output_section != NULL
+      && bfd_is_abs_section (o->output_section))
+    return false;
+
+  tdata = bfd_zmalloc (o->_raw_size / PDR_SIZE);
+  if (! tdata)
+    return false;
+
+  cookie->rels = _bfd_elf32_link_read_relocs (abfd, o, (PTR) NULL,
+					     (Elf_Internal_Rela *) NULL,
+					      info->keep_memory);
+  if (!cookie->rels)
+    {
+      free (tdata);
+      return false;
+    }
+
+  cookie->rel = cookie->rels;
+  cookie->relend =
+    cookie->rels + o->reloc_count * bed->s->int_rels_per_ext_rel;
+      
+  for (i = 0, skip = 0; i < o->_raw_size; i ++)
+    {
+      if (_bfd_elf32_reloc_symbol_deleted_p (i * PDR_SIZE, cookie))
+	{
+	  tdata[i] = 1;
+	  skip ++;
+	}
+    }
+
+  if (skip != 0)
+    {
+      elf_section_data (o)->tdata = tdata;
+      o->_cooked_size = o->_raw_size - skip * PDR_SIZE;
+      ret = true;
+    }
+  else
+    free (tdata);
+
+  if (! info->keep_memory)
+    free (cookie->rels);
+
+  return ret;
+}
+
+static boolean
+_bfd_elf32_mips_ignore_discarded_relocs (sec)
+     asection *sec;
+{
+  if (strcmp (sec->name, ".pdr") == 0)
+    return true;
+  return false;
+}
+
+static boolean
+_bfd_elf32_mips_write_section (output_bfd, sec, contents)
+     bfd *output_bfd;
+     asection *sec;
+     bfd_byte *contents;
+{
+  bfd_byte *to, *from, *end;
+  int i;
+
+  if (strcmp (sec->name, ".pdr") != 0)
+    return false;
+
+  if (elf_section_data (sec)->tdata == NULL)
+    return false;
+
+  to = contents;
+  end = contents + sec->_raw_size;
+  for (from = contents, i = 0;
+       from < end;
+       from += PDR_SIZE, i++)
+    {
+      if (((unsigned char *)elf_section_data (sec)->tdata)[i] == 1)
+	continue;
+      if (to != from)
+	memcpy (to, from, PDR_SIZE);
+      to += PDR_SIZE;
+    }
+  bfd_set_section_contents (output_bfd, sec->output_section, contents,
+			    (file_ptr) sec->output_offset,
+			    sec->_cooked_size);
+  return true;
+}
+
 /* This is almost identical to bfd_generic_get_... except that some
    MIPS relocations need to be handled specially.  Sigh.  */
 
@@ -9515,6 +9629,11 @@ static const struct ecoff_debug_swap mip
 #define elf_backend_hide_symbol		_bfd_mips_elf_hide_symbol
 #define elf_backend_grok_prstatus	_bfd_elf32_mips_grok_prstatus
 #define elf_backend_grok_psinfo		_bfd_elf32_mips_grok_psinfo
+
+#define elf_backend_discard_info	_bfd_elf32_mips_discard_info
+#define elf_backend_ignore_discarded_relocs \
+					_bfd_elf32_mips_ignore_discarded_relocs
+#define elf_backend_write_section	_bfd_elf32_mips_write_section
 
 #define bfd_elf32_bfd_is_local_label_name \
 					mips_elf_is_local_label_name
Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.23
diff -u -p -r1.23 elfcode.h
--- elfcode.h	2001/10/19 16:29:12	1.23
+++ elfcode.h	2001/11/13 21:10:12
@@ -123,6 +123,8 @@ Foundation, Inc., 59 Temple Place - Suit
 #define elf_slurp_reloc_table		NAME(bfd_elf,slurp_reloc_table)
 #define elf_link_create_dynamic_sections \
   NAME(bfd_elf,link_create_dynamic_sections)
+#define elf_bfd_discard_info		NAME(bfd_elf,discard_info)
+#define elf_reloc_symbol_deleted_p	NAME(_bfd_elf,reloc_symbol_deleted_p)
 #define elf_link_record_dynamic_symbol  _bfd_elf_link_record_dynamic_symbol
 #define elf_bfd_final_link		NAME(bfd_elf,bfd_final_link)
 #define elf_create_pointer_linker_section NAME(bfd_elf,create_pointer_linker_section)
Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.123
diff -u -p -r1.123 elflink.h
--- elflink.h	2001/11/10 00:23:35	1.123
+++ elflink.h	2001/11/13 21:10:12
@@ -75,6 +75,8 @@ static int elf_link_sort_cmp2
   PARAMS ((const void *, const void *));
 static size_t elf_link_sort_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection **));
+static boolean elf_section_ignore_discarded_relocs
+  PARAMS ((asection *));
 
 /* Given an ELF BFD, add symbols to the global hash table as
    appropriate.  */
@@ -6287,7 +6289,8 @@ elf_link_input_bfd (finfo, input_bfd)
 	     .eh_frame to describe a routine in the linkonce section,
 	     and it turns out to be hard to remove the .eh_frame
 	     entry too.  FIXME.  */
-	  if (!finfo->info->relocateable)
+	  if (!finfo->info->relocateable
+	      && !elf_section_ignore_discarded_relocs (o))
 	    {
 	      Elf_Internal_Rela *rel, *relend;
 
@@ -6591,6 +6594,11 @@ elf_link_input_bfd (finfo, input_bfd)
 	}
 
       /* Write out the modified section contents.  */
+      if (bed->elf_backend_write_section
+	  && bed->elf_backend_write_section (output_bfd, o, contents))
+	{
+	  /* Section written out.  */
+	}
       if (elf_section_data (o)->stab_info)
 	{
 	  if (! (_bfd_write_section_stabs
@@ -7756,3 +7764,200 @@ elf_collect_hash_codes (h, data)
 
   return true;
 }
+
+boolean
+elf_reloc_symbol_deleted_p (offset, cookie)
+     bfd_vma offset;
+     PTR cookie;
+{
+  struct elf_reloc_cookie *rcookie = (struct elf_reloc_cookie *)cookie;
+
+  if (rcookie->bad_symtab)
+    rcookie->rel = rcookie->rels;
+
+  for (; rcookie->rel < rcookie->relend; rcookie->rel++)
+    {
+      unsigned long r_symndx = ELF_R_SYM (rcookie->rel->r_info);
+      Elf_Internal_Sym isym;
+
+      if (! rcookie->bad_symtab)
+	if (rcookie->rel->r_offset > offset)
+	  return false;
+      if (rcookie->rel->r_offset != offset)
+	continue;
+
+      if (rcookie->locsyms)
+	elf_swap_symbol_in (rcookie->abfd,
+			    ((Elf_External_Sym *)rcookie->locsyms) + r_symndx,
+			    &isym);
+
+      if (r_symndx >= rcookie->locsymcount
+	  || (rcookie->locsyms
+	      && ELF_ST_BIND (isym.st_info) != STB_LOCAL))
+	{
+	  struct elf_link_hash_entry *h;
+
+	  h = rcookie->sym_hashes[r_symndx - rcookie->extsymoff];
+
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+	  if ((h->root.type == bfd_link_hash_defined
+	       || h->root.type == bfd_link_hash_defweak)
+	      && ! bfd_is_abs_section (h->root.u.def.section)
+	      && bfd_is_abs_section (h->root.u.def.section
+				     ->output_section))
+	    return true;
+	  else
+	    return false;
+	}
+      else if (rcookie->locsyms)
+	{
+	  /* It's not a relocation against a global symbol,
+	     but it could be a relocation against a section
+	     symbol for a discarded section.  */
+	  asection *isec;
+
+	  /* Need to: get the symbol; get the section.  */
+	  if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
+	    {
+	      isec = section_from_elf_index (rcookie->abfd, isym.st_shndx);
+	      if (isec != NULL
+		  && ELF_ST_TYPE (isym.st_info) == STT_SECTION
+		  && ! bfd_is_abs_section (isec)
+		  && bfd_is_abs_section (isec->output_section))
+		return true;
+	    }
+	}
+      return false;
+    }
+  return false;
+}
+
+/* Discard unneeded references to discarded sections.
+   Returns true if any section's size was changed.  */
+/* This function assumes that the relocations are in sorted order,
+   which is true for all known assemblers.  */
+
+boolean
+elf_bfd_discard_info (info)
+     struct bfd_link_info *info;
+{
+  struct elf_reloc_cookie cookie;
+  asection *o;
+  Elf_Internal_Shdr *symtab_hdr;
+  Elf_External_Sym *freesyms;
+  struct elf_backend_data *bed;
+  bfd *abfd;
+  boolean ret = false;
+
+  if (info->relocateable
+      || info->traditional_format
+      || info->hash->creator->flavour != bfd_target_elf_flavour
+      || ! is_elf_hash_table (info)
+      || info->strip == strip_all
+      || info->strip == strip_debugger)
+    return false;
+  for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+    {
+      bed = get_elf_backend_data (abfd);
+
+      if ((abfd->flags & DYNAMIC) != 0)
+	continue;
+
+      o = bfd_get_section_by_name (abfd, ".stab");
+      if (! o && ! bed->elf_backend_discard_info)
+	continue;
+
+      symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+
+      cookie.abfd = abfd;
+      cookie.sym_hashes = elf_sym_hashes (abfd);
+      cookie.bad_symtab = elf_bad_symtab (abfd);
+      if (cookie.bad_symtab)
+	{
+	  cookie.locsymcount =
+	    symtab_hdr->sh_size / sizeof (Elf_External_Sym);
+	  cookie.extsymoff = 0;
+	}
+      else
+	{
+	  cookie.locsymcount = symtab_hdr->sh_info;
+	  cookie.extsymoff = symtab_hdr->sh_info;
+	}
+
+      freesyms = NULL;
+      if (symtab_hdr->contents)
+        cookie.locsyms = (void *) symtab_hdr->contents;
+      else if (cookie.locsymcount == 0)
+        cookie.locsyms = NULL;
+      else
+        {
+          bfd_size_type amt = cookie.locsymcount * sizeof (Elf_External_Sym);
+          cookie.locsyms = bfd_malloc (amt);
+          if (cookie.locsyms == NULL
+              || bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
+              || bfd_bread (cookie.locsyms, amt, abfd) != amt)
+	    {
+	      /* Something is very wrong - but we can still do our job for
+		 global symbols, so don't give up.  */
+	      if (cookie.locsyms)
+		free (cookie.locsyms);
+	      cookie.locsyms = NULL;
+            }
+	  else
+	    {
+	      freesyms = cookie.locsyms;
+	    }
+        }
+
+      if (o)
+	{
+	  cookie.rels = (NAME(_bfd_elf,link_read_relocs)
+			 (abfd, o, (PTR) NULL,
+			  (Elf_Internal_Rela *) NULL,
+			  info->keep_memory));
+	  if (cookie.rels)
+	    {
+	      cookie.rel = cookie.rels;
+	      cookie.relend =
+		cookie.rels + o->reloc_count * bed->s->int_rels_per_ext_rel;
+	      if (_bfd_discard_section_stabs (abfd, o,
+					      elf_section_data (o)->stab_info,
+					      elf_reloc_symbol_deleted_p,
+					      &cookie))
+		ret = true;
+	      if (! info->keep_memory)
+		free (cookie.rels);
+	    }
+	}
+
+      if (bed->elf_backend_discard_info)
+	{
+	  if (bed->elf_backend_discard_info (abfd, &cookie, info))
+	    ret = true;
+	}
+
+      if (freesyms)
+	free (freesyms);
+    }
+  return ret;
+}
+
+static boolean
+elf_section_ignore_discarded_relocs (sec)
+     asection *sec;
+{
+  if (strcmp (sec->name, ".stab") == 0)
+    return true;
+  else if ((get_elf_backend_data (sec->owner)
+	    ->elf_backend_ignore_discarded_relocs != NULL)
+	   && (get_elf_backend_data (sec->owner)
+	       ->elf_backend_ignore_discarded_relocs (sec)))
+    return true;
+  else
+    return false;
+}
+
+
Index: bfd/elfxx-target.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-target.h,v
retrieving revision 1.34
diff -u -p -r1.34 elfxx-target.h
--- elfxx-target.h	2001/11/03 03:18:34	1.34
+++ elfxx-target.h	2001/11/13 21:10:12
@@ -358,6 +358,15 @@ Foundation, Inc., 59 Temple Place - Suit
 #ifndef elf_backend_reloc_type_class
 #define elf_backend_reloc_type_class		_bfd_elf_reloc_type_class
 #endif
+#ifndef elf_backend_discard_info
+#define elf_backend_discard_info		NULL
+#endif
+#ifndef elf_backend_ignore_discarded_relocs
+#define elf_backend_ignore_discarded_relocs	NULL
+#endif
+#ifndef elf_backend_write_section
+#define elf_backend_write_section		NULL
+#endif
 
 /* Previously, backends could only use SHT_REL or SHT_RELA relocation
    sections, but not both.  They defined USE_REL to indicate SHT_REL
@@ -446,6 +455,9 @@ static const struct elf_backend_data elf
   elf_backend_sprintf_vma,
   elf_backend_fprintf_vma,
   elf_backend_reloc_type_class,
+  elf_backend_discard_info,
+  elf_backend_ignore_discarded_relocs,
+  elf_backend_write_section,
   elf_backend_ecoff_debug_swap,
   ELF_MACHINE_ALT1,
   ELF_MACHINE_ALT2,
Index: bfd/libbfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd-in.h,v
retrieving revision 1.16
diff -u -p -r1.16 libbfd-in.h
--- libbfd-in.h	2001/10/01 14:03:35	1.16
+++ libbfd-in.h	2001/11/13 21:10:12
@@ -446,6 +446,11 @@ extern bfd_reloc_status_type _bfd_reloca
 extern boolean _bfd_link_section_stabs
   PARAMS ((bfd *, PTR *, asection *, asection *, PTR *));
 
+/* Eliminate stabs for discarded functions and symbols.  */
+extern boolean _bfd_discard_section_stabs
+  PARAMS ((bfd *, asection *, PTR,
+	   boolean (*) (bfd_vma, PTR), PTR));
+
 /* Write out the .stab section when linking stabs in sections.  */
 
 extern boolean _bfd_write_section_stabs
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd.h,v
retrieving revision 1.48
diff -u -p -r1.48 libbfd.h
--- libbfd.h	2001/10/30 15:20:02	1.48
+++ libbfd.h	2001/11/13 21:10:12
@@ -451,6 +451,11 @@ extern bfd_reloc_status_type _bfd_reloca
 extern boolean _bfd_link_section_stabs
   PARAMS ((bfd *, PTR *, asection *, asection *, PTR *));
 
+/* Eliminate stabs for discarded functions and symbols.  */
+extern boolean _bfd_discard_section_stabs
+  PARAMS ((bfd *, asection *, PTR,
+	   boolean (*) (bfd_vma, PTR), PTR));
+
 /* Write out the .stab section when linking stabs in sections.  */
 
 extern boolean _bfd_write_section_stabs
Index: bfd/stabs.c
===================================================================
RCS file: /cvs/src/src/bfd/stabs.c,v
retrieving revision 1.7
diff -u -p -r1.7 stabs.c
--- stabs.c	2001/09/19 05:33:13	1.7
+++ stabs.c	2001/11/13 21:10:12
@@ -502,6 +502,176 @@ _bfd_link_section_stabs (abfd, psinfo, s
   return false;
 }
 
+
+/* This function is called for each input file before the stab
+   section is relocated.  It discards stab entries for discarded
+   functions and variables.  The function returns true iff
+   any entries have been deleted.
+*/
+
+boolean
+_bfd_discard_section_stabs (abfd, stabsec, psecinfo,
+			    reloc_symbol_deleted_p, cookie)
+     bfd *abfd;
+     asection *stabsec;
+     PTR psecinfo;
+     boolean (*reloc_symbol_deleted_p) (bfd_vma, PTR);
+     PTR cookie;
+{
+  bfd_size_type count, amt;
+  struct stab_section_info *secinfo;
+  bfd_byte *stabbuf = NULL;
+  bfd_byte *sym, *symend;
+  bfd_size_type skip;
+  bfd_size_type *pstridx;
+  int deleting;
+
+  if (stabsec->_raw_size == 0)
+    {
+      /* This file does not contain stabs debugging information.  */
+      return false;
+    }
+
+  if (stabsec->_raw_size % STABSIZE != 0)
+    {
+      /* Something is wrong with the format of these stab symbols.
+         Don't try to optimize them.  */
+      return false;
+    }
+
+  if ((stabsec->output_section != NULL
+       && bfd_is_abs_section (stabsec->output_section)))
+    {
+      /* At least one of the sections is being discarded from the
+         link, so we should just ignore them.  */
+      return false;
+    }
+
+  /* We should have initialized our data in _bfd_link_stab_sections.
+     If there was some bizarre error reading the string sections, though,
+     we might not have.  Bail rather than asserting.  */
+  if (psecinfo == NULL)
+    return false;
+
+  count = stabsec->_raw_size / STABSIZE;
+  secinfo = (struct stab_section_info *) psecinfo;
+
+  /* Read the stabs information from abfd.  */
+
+  stabbuf = (bfd_byte *) bfd_malloc (stabsec->_raw_size);
+  if (stabbuf == NULL)
+    goto error_return;
+
+  if (! bfd_get_section_contents (abfd, stabsec, stabbuf, (bfd_vma) 0,
+				  stabsec->_raw_size))
+    goto error_return;
+
+  /* Look through the stabs symbols and discard any information for
+     discarded functions.  */
+
+  skip = 0;
+  deleting = -1;
+
+  symend = stabbuf + stabsec->_raw_size;
+  for (sym = stabbuf, pstridx = secinfo->stridxs;
+       sym < symend;
+       sym += STABSIZE, ++pstridx)
+    {
+      int type;
+
+      if (*pstridx == (bfd_size_type) -1)
+	{
+	  /* This stab was deleted in a previous pass.  */
+	  continue;
+	}
+
+      type = sym[TYPEOFF];
+
+      if (type == N_FUN)
+	{
+	  int strx = bfd_get_32 (abfd, sym + STRDXOFF);
+
+	  if (strx == 0)
+	    {
+	      if (deleting)
+		{
+		  skip++;
+		  *pstridx = -1;
+		}
+	      deleting = -1;
+	      continue;
+	    }
+	  deleting = 0;
+	  if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
+	    deleting = 1;
+	}
+
+      if (deleting == 1)
+	{
+	  *pstridx = -1;
+	  skip++;
+	}
+      else if (deleting == -1)
+	{
+	  /* Outside of a function.  Check for deleted variables.  */
+	  if (type == N_STSYM || type == N_LCSYM)
+	    if ((*reloc_symbol_deleted_p) (sym + VALOFF - stabbuf, cookie))
+	      {
+		*pstridx = -1;
+		skip ++;
+	      }
+	  /* We should also check for N_GSYM entries which reference a
+	     deleted global, but those are less harmful to debuggers
+	     and would require parsing the stab strings.  */
+	}
+    }
+
+  free (stabbuf);
+  stabbuf = NULL;
+
+  /* Shrink the stabsec as needed.  */
+  stabsec->_cooked_size -= skip * STABSIZE;
+  if (stabsec->_cooked_size == 0)
+    stabsec->flags |= SEC_EXCLUDE;
+
+  /* Recalculate the `cumulative_skips' array now that stabs have been
+     deleted for this section.  */
+
+  if (skip != 0)
+    {
+      bfd_size_type i, offset;
+      bfd_size_type *pskips;
+
+      if (secinfo->cumulative_skips == NULL)
+	{
+	  amt = count * sizeof (bfd_size_type);
+	  secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt);
+	  if (secinfo->cumulative_skips == NULL)
+	    goto error_return;
+	}
+
+      pskips = secinfo->cumulative_skips;
+      pstridx = secinfo->stridxs;
+      offset = 0;
+
+      for (i = 0; i < count; i++, pskips++, pstridx++)
+	{
+	  *pskips = offset;
+	  if (*pstridx == (bfd_size_type) -1)
+	    offset += STABSIZE;
+	}
+
+      BFD_ASSERT (offset != 0);
+    }
+
+  return (skip > 0);
+
+ error_return:
+  if (stabbuf != NULL)
+    free (stabbuf);
+  return false;
+}
+
 /* Write out the stab section.  This is called with the relocated
    contents.  */
 
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.64
diff -u -p -r1.64 elf32.em
--- elf32.em	2001/10/15 23:28:21	1.64
+++ elf32.em	2001/11/13 21:10:12
@@ -80,6 +80,8 @@ static asection *output_prev_sec_find
   PARAMS ((lang_output_section_statement_type *));
 static boolean gld${EMULATION_NAME}_place_orphan
   PARAMS ((lang_input_statement_type *, asection *));
+static void gld${EMULATION_NAME}_finish
+  PARAMS ((void));
 static char *gld${EMULATION_NAME}_get_script
   PARAMS ((int *isfile));
 
@@ -1319,6 +1321,25 @@ gld${EMULATION_NAME}_place_orphan (file,
   return true;
 }
 
+static void
+gld${EMULATION_NAME}_finish ()
+{
+  ${LDEMUL_FINISH+${LDEMUL_FINISH} ();}
+
+  if (bfd_elf${ELFSIZE}_discard_info (&link_info))
+    {
+      /* Resize the sections.  */
+      lang_size_sections (stat_ptr->head, abs_output_section,
+			  &stat_ptr->head, 0, (bfd_vma) 0, false);
+
+      /* Redo special stuff.  */
+      ldemul_after_allocation ();
+
+      /* Do the assignments again.  */
+      lang_do_assignments (stat_ptr->head, abs_output_section,
+			   (fill_type) 0, (bfd_vma) 0);
+    }
+}
 EOF
 fi
 
@@ -1618,7 +1639,7 @@ struct ld_emulation_xfer_struct ld_${EMU
   ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
   "${EMULATION_NAME}",
   "${OUTPUT_FORMAT}",
-  ${LDEMUL_FINISH-NULL},
+  gld${EMULATION_NAME}_finish,
   ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
   ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
   ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},


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