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: 64k+-sections-change causes problems preserving section info in elf_object_p and elf_core_file_p


This should fix it.

bfd/ChangeLog
	* elfcode.h (struct bfd_preserve): New.
	(elf_object_p): Replace preserved_* vars with instance of above.
	Save and restore arch_info pointer rather than arch, mach so that
	more cases can be restored.  Save and restore new section_tail,
	section_htab structure, and init appropriately.  Move "rest of
	section header" code so that i_shdrp needs no NULL initialisation.
	Free old section_htab on success.
	* elfcore.h (elf_core_file_p): Likewise.

-- 
Alan Modra

Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.26
diff -u -p -r1.26 elfcode.h
--- elfcode.h	2001/12/17 00:52:34	1.26
+++ elfcode.h	2001/12/18 07:05:48
@@ -503,6 +503,16 @@ elf_file_p (x_ehdrp)
 	  && (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3));
 }
 
+struct bfd_preserve
+{
+  const struct bfd_arch_info *arch_info;
+  struct elf_obj_tdata *tdata;
+  struct bfd_hash_table section_htab;
+  struct sec *sections;
+  struct sec **section_tail;
+  unsigned int section_count;
+};
+
 /* Check to see if the file associated with ABFD matches the target vector
    that ABFD points to.
 
@@ -519,23 +529,16 @@ elf_object_p (abfd)
   Elf_Internal_Ehdr *i_ehdrp;	/* Elf file header, internal form */
   Elf_External_Shdr x_shdr;	/* Section header table entry, external form */
   Elf_Internal_Shdr i_shdr;
-  Elf_Internal_Shdr *i_shdrp = NULL; /* Section header table, internal form */
+  Elf_Internal_Shdr *i_shdrp;	/* Section header table, internal form */
   unsigned int shindex;
   char *shstrtab;		/* Internal copy of section header stringtab */
   struct elf_backend_data *ebd;
-  struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd);
-  struct sec *preserved_sections = abfd->sections;
-  unsigned int preserved_section_count = abfd->section_count;
-  enum bfd_architecture previous_arch = bfd_get_arch (abfd);
-  unsigned long previous_mach = bfd_get_mach (abfd);
+  struct bfd_preserve preserve;
   struct elf_obj_tdata *new_tdata = NULL;
   asection *s;
   bfd_size_type amt;
 
-  /* Clear section information, since there might be a recognized bfd that
-     we now check if we can replace, and we don't want to append to it.  */
-  abfd->sections = NULL;
-  abfd->section_count = 0;
+  preserve.arch_info = abfd->arch_info;
 
   /* Read in the ELF header in external format.  */
 
@@ -582,8 +585,21 @@ elf_object_p (abfd)
   new_tdata = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt);
   if (new_tdata == NULL)
     goto got_no_match;
+  preserve.tdata = elf_tdata (abfd);
   elf_tdata (abfd) = new_tdata;
 
+  /* Clear section information, since there might be a recognized bfd that
+     we now check if we can replace, and we don't want to append to it.  */
+  preserve.sections = abfd->sections;
+  preserve.section_tail = abfd->section_tail;
+  preserve.section_count = abfd->section_count;
+  preserve.section_htab = abfd->section_htab;
+  abfd->sections = NULL;
+  abfd->section_tail = &abfd->sections;
+  abfd->section_count = 0;
+  if (!bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc))
+    goto got_no_match;
+
   /* Now that we know the byte order, swap in the rest of the header */
   i_ehdrp = elf_elfheader (abfd);
   elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
@@ -711,27 +727,28 @@ elf_object_p (abfd)
 	}
       for ( ; shindex < num_sec; shindex++)
 	elf_elfsections (abfd)[shindex] = shdrp++;
-    }
 
-  /* Read in the rest of the section header table and convert it to
-     internal form.  */
-  for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++)
-    {
-      if (bfd_bread ((PTR) & x_shdr, (bfd_size_type) sizeof x_shdr, abfd)
-	  != sizeof (x_shdr))
-	goto got_no_match;
-      elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
+      /* Read in the rest of the section header table and convert it
+	 to internal form.  */
+      for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++)
+	{
+	  if (bfd_bread ((PTR) & x_shdr, (bfd_size_type) sizeof x_shdr, abfd)
+	      != sizeof (x_shdr))
+	    goto got_no_match;
+	  elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
 
-      /* If the section is loaded, but not page aligned, clear
-         D_PAGED.  */
-      if (i_shdrp[shindex].sh_size != 0
-	  && (i_shdrp[shindex].sh_flags & SHF_ALLOC) != 0
-	  && i_shdrp[shindex].sh_type != SHT_NOBITS
-	  && (((i_shdrp[shindex].sh_addr - i_shdrp[shindex].sh_offset)
-	       % ebd->maxpagesize)
-	      != 0))
-	abfd->flags &= ~D_PAGED;
+	  /* If the section is loaded, but not page aligned, clear
+	     D_PAGED.  */
+	  if (i_shdrp[shindex].sh_size != 0
+	      && (i_shdrp[shindex].sh_flags & SHF_ALLOC) != 0
+	      && i_shdrp[shindex].sh_type != SHT_NOBITS
+	      && (((i_shdrp[shindex].sh_addr - i_shdrp[shindex].sh_offset)
+		   % ebd->maxpagesize)
+		  != 0))
+	    abfd->flags &= ~D_PAGED;
+	}
     }
+
   if (i_ehdrp->e_shstrndx)
     {
       if (! bfd_section_from_shdr (abfd, i_ehdrp->e_shstrndx))
@@ -818,6 +835,10 @@ elf_object_p (abfd)
 	}
     }
 
+  /* It would be nice to be able to free more memory here, eg. old
+     elf_elfsections, old tdata, but that's not possible since these
+     blocks are sitting inside obj_alloc'd memory.  */
+  bfd_hash_table_free (&preserve.section_htab);
   return (abfd->xvec);
 
  got_wrong_format_error:
@@ -830,15 +851,22 @@ elf_object_p (abfd)
      target-specific elf_backend_object_p function.  Note that saving the
      whole bfd here and restoring it would be even worse; the first thing
      you notice is that the cached bfd file position gets out of sync.  */
-  bfd_default_set_arch_mach (abfd, previous_arch, previous_mach);
   bfd_set_error (bfd_error_wrong_format);
+
  got_no_match:
+  abfd->arch_info = preserve.arch_info;
   if (new_tdata != NULL)
-    bfd_release (abfd, new_tdata);
-  elf_tdata (abfd) = preserved_tdata;
-  abfd->sections = preserved_sections;
-  abfd->section_count = preserved_section_count;
-  return (NULL);
+    {
+      /* bfd_release frees all memory more recently bfd_alloc'd than
+	 its arg, as well as its arg.  */
+      bfd_release (abfd, new_tdata);
+      elf_tdata (abfd) = preserve.tdata;
+      abfd->section_htab = preserve.section_htab;
+      abfd->sections = preserve.sections;
+      abfd->section_tail = preserve.section_tail;
+      abfd->section_count = preserve.section_count;
+    }
+  return NULL;
 }
 
 /* ELF .o/exec file writing */
Index: bfd/elfcore.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcore.h,v
retrieving revision 1.10
diff -u -p -r1.10 elfcore.h
--- elfcore.h	2001/11/02 13:12:56	1.10
+++ elfcore.h	2001/12/18 07:05:48
@@ -81,21 +81,14 @@ elf_core_file_p (abfd)
 {
   Elf_External_Ehdr x_ehdr;	/* Elf file header, external form */
   Elf_Internal_Ehdr *i_ehdrp;	/* Elf file header, internal form */
-  Elf_Internal_Phdr *i_phdrp = NULL;	/* Elf program header, internal form */
+  Elf_Internal_Phdr *i_phdrp;	/* Elf program header, internal form */
   unsigned int phindex;
   struct elf_backend_data *ebd;
-  struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd);
-  struct sec *preserved_sections = abfd->sections;
-  unsigned int preserved_section_count = abfd->section_count;
-  enum bfd_architecture previous_arch = bfd_get_arch (abfd);
-  unsigned long previous_mach = bfd_get_mach (abfd);
+  struct bfd_preserve preserve;
   struct elf_obj_tdata *new_tdata = NULL;
   bfd_size_type amt;
 
-  /* Clear section information, since there might be a recognized bfd that
-     we now check if we can replace, and we don't want to append to it.  */
-  abfd->sections = NULL;
-  abfd->section_count = 0;
+  preserve.arch_info = abfd->arch_info;
 
   /* Read in the ELF header in external format.  */
   if (bfd_bread ((PTR) &x_ehdr, (bfd_size_type) sizeof (x_ehdr), abfd)
@@ -136,8 +129,21 @@ elf_core_file_p (abfd)
   new_tdata = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt);
   if (new_tdata == NULL)
     return NULL;
+  preserve.tdata = elf_tdata (abfd);
   elf_tdata (abfd) = new_tdata;
 
+  /* Clear section information, since there might be a recognized bfd that
+     we now check if we can replace, and we don't want to append to it.  */
+  preserve.sections = abfd->sections;
+  preserve.section_tail = abfd->section_tail;
+  preserve.section_count = abfd->section_count;
+  preserve.section_htab = abfd->section_htab;
+  abfd->sections = NULL;
+  abfd->section_tail = &abfd->sections;
+  abfd->section_count = 0;
+  if (!bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc))
+    goto fail;
+
   /* Swap in the rest of the header, now that we have the byte order.  */
   i_ehdrp = elf_elfheader (abfd);
   elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
@@ -240,6 +246,7 @@ elf_core_file_p (abfd)
 	goto wrong;
     }
 
+  bfd_hash_table_free (&preserve.section_htab);
   return abfd->xvec;
 
 wrong:
@@ -252,15 +259,20 @@ wrong:
      target-specific elf_backend_object_p function.  Note that saving the
      whole bfd here and restoring it would be even worse; the first thing
      you notice is that the cached bfd file position gets out of sync.  */
-  bfd_default_set_arch_mach (abfd, previous_arch, previous_mach);
   bfd_set_error (bfd_error_wrong_format);
+
 fail:
-  if (i_phdrp != NULL)
-    bfd_release (abfd, i_phdrp);
+  abfd->arch_info = preserve.arch_info;
   if (new_tdata != NULL)
-    bfd_release (abfd, new_tdata);
-  elf_tdata (abfd) = preserved_tdata;
-  abfd->sections = preserved_sections;
-  abfd->section_count = preserved_section_count;
+    {
+      /* bfd_release frees all memory more recently bfd_alloc'd than
+	 its arg, as well as its arg.  */
+      bfd_release (abfd, new_tdata);
+      elf_tdata (abfd) = preserve.tdata;
+      abfd->section_htab = preserve.section_htab;
+      abfd->sections = preserve.sections;
+      abfd->section_tail = preserve.section_tail;
+      abfd->section_count = preserve.section_count;
+    }
   return NULL;
 }


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