This is the mail archive of the binutils@sourceware.org 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] bfd_elf_bfd_from_remote_memory() workaround for the ELF misalignment


On Wed, 22 Aug 2007 00:22:36 +0200, Jan Kratochvil wrote:
> On Tue, 21 Aug 2007 23:27:35 +0200, Daniel Jacobowitz wrote:
> > On Tue, 21 Aug 2007 22:43:53 +0200, Roland McGrath wrote:
> > > At least at some point in the past, I think it may have been
> > > required for gdb to find everything it should, because it didn't find
> > > everything from PT_GNU_EH_FRAME, PT_DYNAMIC, DT_*, etc.  (I don't know if
> > > that is an issue with today's code.)
> > 
> > If it is still an issue, IMHO we should fix that instead of attempting
> > to recover the section headers.  The corner cases are too cornered.
...
> You are tight it would work if GDB (IMO BFD) has to be fixed to parse PHDRs
> instead.  Attaching IA64 VDSO + its variant as it gets cut+cleared by
> bfd_elf_bfd_from_remote_memory().

Patch attached.  It cannot be placed only to GDB as GDB uses the symbols
parsing code from BFD and if BFD cannot find those symbols...  GDB could also
patch the ELF_OBJ_TDATA structure itself before calling BFD symbols retrieval.

It works on IA64 together with aligning-less bfd_elf_bfd_from_remote_memory():
	http://sourceware.org/ml/binutils/2007-08/msg00321.html

Not sure if it is worth it as the current code works for any real-world cases.


Regards,
Jan
2007-08-24  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* Makefile.am (elf32.lo, elf64.lo): Updated dependencies.
	* Makefile.in: Likewise.
	* elf-bfd.h (struct elf_obj_tdata): New field CODE_SEGMENT_SECTION.
	* elf.c (bfd_elf_get_elf_syms): Optionally patch ST_SHNDX according to
	CODE_SEGMENT_SECTION.
	* elfcode.h: Include "safe-ctype.h".
	(find_code_segment): New function.
	(elf_object_p): Create sections from PHDRs if no SHDRs were found.
	If no dynamic symbols were found create them from PT_DYNAMIC pointers.

--- bfd/Makefile.am	23 Aug 2007 16:29:49 -0000	1.204
+++ bfd/Makefile.am	24 Aug 2007 08:50:29 -0000
@@ -1559,7 +1559,8 @@ elf32-xc16x.lo: elf32-xc16x.c $(INCDIR)/
   $(INCDIR)/elf/dwarf2.h $(INCDIR)/libiberty.h elf32-target.h
 elf32.lo: elf32.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
   $(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
-  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h
+  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h \
+  $(INCDIR)/safe-ctype.h
 elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/safe-ctype.h \
@@ -1894,7 +1895,8 @@ elf64-sparc.lo: elf64-sparc.c $(INCDIR)/
   $(INCDIR)/opcode/sparc.h elfxx-sparc.h elf64-target.h
 elf64.lo: elf64.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
   $(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
-  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h
+  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h \
+  $(INCDIR)/safe-ctype.h
 mmo.lo: mmo.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/libiberty.h $(INCDIR)/elf/mmix.h $(INCDIR)/elf/reloc-macros.h \
   $(INCDIR)/opcode/mmix.h
--- bfd/Makefile.in	23 Aug 2007 16:29:49 -0000	1.224
+++ bfd/Makefile.in	24 Aug 2007 08:50:32 -0000
@@ -2141,7 +2141,8 @@ elf32-xc16x.lo: elf32-xc16x.c $(INCDIR)/
   $(INCDIR)/elf/dwarf2.h $(INCDIR)/libiberty.h elf32-target.h
 elf32.lo: elf32.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
   $(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
-  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h
+  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h \
+  $(INCDIR)/safe-ctype.h
 elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
   $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/safe-ctype.h \
@@ -2476,7 +2477,8 @@ elf64-sparc.lo: elf64-sparc.c $(INCDIR)/
   $(INCDIR)/opcode/sparc.h elfxx-sparc.h elf64-target.h
 elf64.lo: elf64.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \
   $(INCDIR)/bfdlink.h $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \
-  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h
+  $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h elfcore.h \
+  $(INCDIR)/safe-ctype.h
 mmo.lo: mmo.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/libiberty.h $(INCDIR)/elf/mmix.h $(INCDIR)/elf/reloc-macros.h \
   $(INCDIR)/opcode/mmix.h
--- bfd/elf-bfd.h	4 Aug 2007 16:31:00 -0000	1.239
+++ bfd/elf-bfd.h	24 Aug 2007 08:50:32 -0000
@@ -1352,6 +1352,8 @@ struct elf_obj_tdata
   unsigned int strtab_section, dynsymtab_section;
   unsigned int symtab_shndx_section;
   unsigned int dynversym_section, dynverdef_section, dynverref_section;
+  /* The first `loadX' section from PT_LOAD PHDR using SEC_CODE.  */
+  unsigned int code_segment_section;
   file_ptr next_file_pos;
   bfd_vma gp;				/* The gp value */
   unsigned int gp_size;			/* The gp size */
--- bfd/elf.c	16 Aug 2007 18:49:42 -0000	1.410
+++ bfd/elf.c	24 Aug 2007 08:50:35 -0000
@@ -408,15 +408,20 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   for (esym = extsym_buf, isym = intsym_buf, shndx = extshndx_buf;
        isym < isymend;
        esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
-    if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
-      {
-	symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
-	(*_bfd_error_handler) (_("%B symbol number %lu references "
-				 "nonexistent SHT_SYMTAB_SHNDX section"),
-			       ibfd, (unsigned long) symoffset);
-	intsym_buf = NULL;
-	goto out;
-      }
+    {
+      if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
+	{
+	  symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
+	  (*_bfd_error_handler) (_("%B symbol number %lu references "
+				   "nonexistent SHT_SYMTAB_SHNDX section"),
+				 ibfd, (unsigned long) symoffset);
+	  intsym_buf = NULL;
+	  goto out;
+	}
+      if (elf_tdata (ibfd)->code_segment_section != 0
+	  && ELF_ST_TYPE (isym->st_info) == STT_FUNC)
+	isym->st_shndx = elf_tdata (ibfd)->code_segment_section;
+    }
 
  out:
   if (alloc_ext != NULL)
Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.86
diff -u -p -r1.86 elfcode.h
--- bfd/elfcode.h	14 Aug 2007 08:04:47 -0000	1.86
+++ bfd/elfcode.h	24 Aug 2007 08:50:36 -0000
@@ -73,6 +73,7 @@
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
+#include "safe-ctype.h"
 
 /* Renaming structures, typedefs, macros and functions to be size-specific.  */
 #define Elf_External_Ehdr	NAME(Elf,External_Ehdr)
@@ -483,6 +484,20 @@ valid_section_index_p (unsigned index, u
   return (index >= SHN_LOPROC && index <= SHN_HIOS);
 }
 
+/* Find the section by BFD_SECTION_FROM_PHDR coming from the first PT_LOAD
+   using PF_X.  */
+
+static bfd_boolean
+find_code_segment (bfd *abfd ATTRIBUTE_UNUSED, asection *sect,
+		   void *obj ATTRIBUTE_UNUSED)
+{
+  return (sect->flags & SEC_ALLOC) != 0
+	 && (sect->flags & SEC_LOAD) != 0
+	 && (sect->flags & SEC_CODE) != 0
+	 && CONST_STRNEQ (sect->name, "load")
+	 && ISDIGIT (sect->name[sizeof "load" - 1]);
+}
+
 /* Check to see if the file associated with ABFD matches the target vector
    that ABFD points to.
 
@@ -861,6 +876,183 @@ elf_object_p (bfd *abfd)
       if (! _bfd_elf_setup_sections (abfd))
 	goto got_wrong_format_error;
     }
+  else
+    {
+      unsigned int phindex;
+
+      /* Even non-core ELF files may have the sections stripped.
+         Process each program header.  */
+      for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex)
+	if (! bfd_section_from_phdr (abfd, elf_tdata (abfd)->phdr + phindex, (int) phindex))
+	  return NULL;
+    }
+
+  /* We may need to reconstruct the symbol section from PT_DYNAMIC.  */
+  if (elf_tdata (abfd)->dynsymtab_hdr.sh_size == 0)
+    {
+      unsigned int phindex;
+      Elf_Internal_Phdr *seg_dynamic = NULL;
+
+      for (phindex = 0; phindex < elf_elfheader (abfd)->e_phnum; ++phindex)
+	if (elf_tdata (abfd)->phdr[phindex].p_type == PT_DYNAMIC)
+	  {
+	    seg_dynamic = elf_tdata (abfd)->phdr + phindex;
+	    break;
+	  }
+      if (seg_dynamic != NULL)
+	{
+	  bfd_vma seg_size;
+	  bfd_byte *bufend, *bufstart, *buf;
+	  int arch_size;
+
+	  seg_size = seg_dynamic->p_filesz;
+	  buf = bufstart = alloca (seg_size);
+	  arch_size = bfd_get_arch_size (abfd);
+	  if ((arch_size == 32 || arch_size == 64)
+	      && bfd_seek (abfd, seg_dynamic->p_offset, SEEK_SET) == 0
+	      && bfd_bread (buf, seg_size, abfd) == seg_size)
+	    {
+	      size_t step;
+	      bfd_uint64_t ptr_symtab = 0, ptr_strtab = 0;
+	      Elf_Internal_Shdr *hdr_symtab = &elf_tdata (abfd)->dynsymtab_hdr;
+	      Elf_Internal_Shdr *hdr_strtab = &elf_tdata (abfd)->dynstrtab_hdr;
+	      Elf_Internal_Shdr *hdr_versym = &elf_tdata (abfd)->dynversym_hdr;
+	      bfd_vma baseaddr = 0;
+
+	      /* PT_DYNAMIC D_PTRs are VMAs, we need file offsets instead.  */
+	      for (phindex = 0;
+		   phindex < elf_elfheader (abfd)->e_phnum;
+		   ++phindex)
+	        {
+		  Elf_Internal_Phdr *seg_load;
+
+		  seg_load = elf_tdata (abfd)->phdr + phindex;
+		  if (seg_load->p_type == PT_LOAD)
+		    {
+		      baseaddr = seg_load->p_vaddr - seg_load->p_offset;
+		      break;
+		    }
+		}
+	      step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
+				       : sizeof (Elf64_External_Dyn);
+	      for (bufend = buf + seg_size; buf < bufend; buf += step)
+	        {
+		  /* We use DYN_VAL even for D_UN.D_PTR.  */
+		  bfd_uint64_t dyn_tag, dyn_val;
+
+		  if (arch_size == 32)
+		    {
+		      Elf32_External_Dyn *x_dynp_32;
+		      x_dynp_32 = (Elf32_External_Dyn *) buf;
+		      dyn_tag = bfd_h_get_32 (abfd,
+					      (bfd_byte *) x_dynp_32->d_tag);
+		      dyn_val = bfd_h_get_32 (abfd,
+					    (bfd_byte *) x_dynp_32->d_un.d_val);
+		    }
+		  else
+		    {
+		      Elf64_External_Dyn *x_dynp_64;
+		      x_dynp_64 = (Elf64_External_Dyn *) buf;
+		      dyn_tag = bfd_h_get_64 (abfd,
+					      (bfd_byte *) x_dynp_64->d_tag);
+		      dyn_val = bfd_h_get_64 (abfd,
+					    (bfd_byte *) x_dynp_64->d_un.d_val);
+		    }
+		  if (dyn_tag == DT_NULL)
+		    break;
+		  switch (dyn_tag)
+		    {
+		      case DT_SYMTAB:
+		        ptr_symtab = dyn_val - baseaddr;
+		        break;
+		      case DT_SYMENT:
+		        hdr_symtab->sh_entsize = dyn_val;
+		        break;
+		      case DT_STRTAB:
+		        ptr_strtab = dyn_val - baseaddr;
+			break;
+		      case DT_STRSZ:
+		        hdr_strtab->sh_size = dyn_val;
+			break;
+		      case DT_VERSYM:
+			hdr_versym->sh_offset = dyn_val - baseaddr;
+			break;
+		    }
+		}
+	      if (ptr_symtab != 0 && ptr_strtab != 0)
+	        {
+		  asection *code_bfd_sect;
+
+		  /* BFD_SECTION_FROM_PHDR does not enlist its result there.  */
+		  BFD_ASSERT (elf_numsections (abfd) == 0);
+		  BFD_ASSERT (elf_elfsections (abfd) == NULL);
+
+		  /* Two last sections are optional.  */
+		  elf_numsections (abfd) = 3;
+		  elf_elfsections (abfd) = bfd_zalloc2 (abfd, 3 + 1 + 1,
+					      sizeof (*elf_elfsections (abfd)));
+		  if (elf_elfsections (abfd) == NULL)
+		    return NULL;
+		  abfd->flags |= HAS_SYMS;
+
+		  /* Section #0 - SHT_NULL.  */
+		  elf_elfsections (abfd)[0] = bfd_zalloc (abfd,
+					   sizeof (*elf_elfsections (abfd)[0]));
+		  if (elf_elfsections (abfd)[0] == NULL)
+		    return NULL;
+		  elf_elfsections (abfd)[0]->sh_type = SHT_NULL;
+
+		  /* Section #1 - .dynsym. - SHT_DYNSYM.  */
+		  elf_dynsymtab (abfd) = 1;
+		  elf_elfsections (abfd)[elf_dynsymtab (abfd)] = hdr_symtab;
+		  hdr_symtab->sh_type = SHT_DYNSYM;
+		  /* We assume that the string table follows the symbol table,
+		     because there is no way in ELF to know the size of the
+		     dynamic symbol table without looking at the section
+		     headers.  */
+		  hdr_symtab->sh_size = ptr_strtab - ptr_symtab;
+		  hdr_symtab->sh_offset = ptr_symtab;
+		  hdr_symtab->sh_link = 2;
+
+		  /* Section #2 - .dynstr. - SHT_STRTAB.  */
+		  elf_elfsections (abfd)[hdr_symtab->sh_link] = hdr_strtab;
+		  hdr_strtab->sh_type = SHT_STRTAB;
+		  hdr_strtab->sh_offset = ptr_strtab;
+		  hdr_strtab->sh_link = 1;
+
+		  /* Section #3 (optional) - .gnu.version - SHT_GNU_versym.  */
+		  if (hdr_versym->sh_offset != 0)
+		    {
+		      elf_dynversym (abfd) = elf_numsections (abfd)++;
+		      elf_elfsections (abfd)[elf_dynversym (abfd)] = hdr_versym;
+		      hdr_versym->sh_type = SHT_GNU_versym;
+		      hdr_versym->sh_size = (hdr_symtab->sh_size
+					     / hdr_symtab->sh_entsize)
+					    * sizeof (Elf_External_Versym);
+		    }
+
+		  /* Section #4 (optional) for - .text - SHT_PROGBITS.
+		     We need to supply valid ELF section with associated
+		     BFD_SECTION to be able to fixup symbols' ST_SHNDXes.
+		     GDB's would ELF_SYMTAB_READ would ignore BSF_FUNCTION for
+		     symbols with BFD_ABS_SECTION otherwise.  */
+		  code_bfd_sect = bfd_sections_find_if (abfd, find_code_segment,
+							NULL);
+		  if (code_bfd_sect != NULL)
+		    {
+		      Elf_Internal_Shdr *hdr = bfd_zalloc (abfd, sizeof (*hdr));
+		      if (hdr == NULL)
+		        return NULL;
+		      elf_tdata (abfd)->code_segment_section
+						     = elf_numsections (abfd)++;
+		      elf_elfsections (abfd)[elf_tdata (abfd)
+		                             ->code_segment_section] = hdr;
+		      hdr->bfd_section = code_bfd_sect;
+		    }
+		}
+	    }
+	}
+    }
 
   /* Let the backend double check the format and override global
      information.  */

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