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]

More than 64k ELF sections.


This is the first step in teaching binutils how to handle greater than
64k elf sections.  The second part, which I've yet to write, will deal
with symbol st_shndx.

bfd/ChangeLog
	* elfcode.h (elf_swap_ehdr_out): Adjust value written for e_shnum
	and e_shstrndx if out of range.
	(elf_object_p): Read extended values for e_shnum and e_shstrndx
	from the first section header.  Allocate space in elf_elfsections
	for reserved sections and set to NULLs.
	(elf_write_shdrs_and_ehdr): Set overflow fields in first section
	header.  Skip reserved sections in elf_elfsections.  Remove
	duplicate size calculation.

binutils/ChangeLog
	* readelf.c (process_file_header): Print extended e_shnum and
	e_shdtrndx values.  Set elf_header values for same.
	(get_32bit_section_headers): Add "num" arg to read "num" headers.
	(get_64bit_section_headers): Likewise.
	(process_section_headers): Update calls.
	(get_file_header): Call get_32bit_section_headers or 64bit variant.

include/elf/ChangeLog
	* common.h (SHN_XINDEX): Comment typo fix.
	* internal.h (Elf_Internal_Ehdr): Change existing "unsigned short"
	size, count and index fields to "unsigned int".

-- 
Alan Modra

Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.24
diff -u -p -r1.24 elfcode.h
--- elfcode.h	2001/11/15 01:34:10	1.24
+++ elfcode.h	2001/12/11 02:54:01
@@ -277,6 +277,7 @@ elf_swap_ehdr_out (abfd, src, dst)
      const Elf_Internal_Ehdr *src;
      Elf_External_Ehdr *dst;
 {
+  unsigned int tmp;
   int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
   memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
   /* note that all elements of dst are *arrays of unsigned char* already...  */
@@ -294,8 +295,14 @@ elf_swap_ehdr_out (abfd, src, dst)
   H_PUT_16 (abfd, src->e_phentsize, dst->e_phentsize);
   H_PUT_16 (abfd, src->e_phnum, dst->e_phnum);
   H_PUT_16 (abfd, src->e_shentsize, dst->e_shentsize);
-  H_PUT_16 (abfd, src->e_shnum, dst->e_shnum);
-  H_PUT_16 (abfd, src->e_shstrndx, dst->e_shstrndx);
+  tmp = src->e_shnum;
+  if (tmp >= SHN_LORESERVE)
+    tmp = 0;
+  H_PUT_16 (abfd, tmp, dst->e_shnum);
+  tmp = src->e_shstrndx;
+  if (tmp >= SHN_LORESERVE)
+    tmp = SHN_XINDEX;
+  H_PUT_16 (abfd, tmp, dst->e_shstrndx);
 }
 
 /* Translate an ELF section header table entry in external format into an
@@ -494,6 +501,7 @@ elf_object_p (abfd)
   Elf_External_Ehdr x_ehdr;	/* Elf file header, external form */
   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 */
   unsigned int shindex;
   char *shstrtab;		/* Internal copy of section header stringtab */
@@ -634,27 +642,65 @@ elf_object_p (abfd)
   /* Remember the entry point specified in the ELF file header.  */
   bfd_set_start_address (abfd, i_ehdrp->e_entry);
 
+  /* Seek to the section header table in the file.  */
+  if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0)
+    goto got_no_match;
+
+  /* Read the first section header at index 0, and convert to internal
+     form.  */
+  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_shdr);
+
+  /* If the section count is zero, the actual count is in the first
+     section header.  */
+  if (i_ehdrp->e_shnum == 0)
+    i_ehdrp->e_shnum = i_shdr.sh_size;
+
+  /* And similarly for the string table index.  */
+  if (i_ehdrp->e_shstrndx == SHN_XINDEX)
+    i_ehdrp->e_shstrndx = i_shdr.sh_link;
+
   /* Allocate space for a copy of the section header table in
-     internal form, seek to the section header table in the file,
-     read it in, and convert it to internal form.  */
+     internal form.  */
   if (i_ehdrp->e_shnum != 0)
     {
+      Elf_Internal_Shdr *shdrp;
+
       amt = sizeof (*i_shdrp) * i_ehdrp->e_shnum;
       i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
+      if (!i_shdrp)
+	goto got_no_match;
       amt = sizeof (i_shdrp) * i_ehdrp->e_shnum;
+      if (i_ehdrp->e_shnum > SHN_LORESERVE)
+	amt += sizeof (i_shdrp) * (SHN_HIRESERVE + 1 - SHN_LORESERVE);
       elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
-      if (!i_shdrp || !elf_elfsections (abfd))
+      if (!elf_elfsections (abfd))
 	goto got_no_match;
-      if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0)
-	goto got_no_match;
+
+      memcpy (i_shdrp, &i_shdr, sizeof (*i_shdrp));
+      shdrp = i_shdrp;
+      shindex = 0;
+      if (i_ehdrp->e_shnum > SHN_LORESERVE)
+	{
+	  for ( ; shindex < SHN_LORESERVE; shindex++)
+	    elf_elfsections (abfd)[shindex] = shdrp++;
+	  for ( ; shindex < SHN_HIRESERVE + 1; shindex++)
+	    elf_elfsections (abfd)[shindex] = NULL;
+	}
+      for ( ; shindex < i_ehdrp->e_shnum; shindex++)
+	elf_elfsections (abfd)[shindex] = shdrp++;
     }
-  for (shindex = 0; shindex < i_ehdrp->e_shnum; 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);
-      elf_elfsections (abfd)[shindex] = i_shdrp + shindex;
 
       /* If the section is loaded, but not page aligned, clear
          D_PAGED.  */
@@ -987,21 +1033,30 @@ elf_write_shdrs_and_ehdr (abfd)
       || bfd_bwrite ((PTR) & x_ehdr, amt, abfd) != amt)
     return false;
 
+  /* Some fields in the first section header handle overflow of ehdr
+     fields.  */
+  if (i_ehdrp->e_shnum >= SHN_LORESERVE)
+    i_shdrp[0]->sh_size = i_ehdrp->e_shnum;
+  if (i_ehdrp->e_shstrndx >= SHN_LORESERVE)
+    i_shdrp[0]->sh_link = i_ehdrp->e_shstrndx;
+
   /* at this point we've concocted all the ELF sections...  */
-  amt = sizeof (*x_shdrp) * i_ehdrp->e_shnum;
+  amt = i_ehdrp->e_shnum;
+  amt *= sizeof (*x_shdrp);
   x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt);
   if (!x_shdrp)
     return false;
 
-  for (count = 0; count < i_ehdrp->e_shnum; count++)
+  for (count = 0; count < i_ehdrp->e_shnum; i_shdrp++, count++)
     {
 #if DEBUG & 2
-      elf_debug_section (count, i_shdrp[count]);
+      elf_debug_section (count, *i_shdrp);
 #endif
-      elf_swap_shdr_out (abfd, i_shdrp[count], x_shdrp + count);
+      elf_swap_shdr_out (abfd, *i_shdrp, x_shdrp + count);
+      
+      if (count == SHN_LORESERVE - 1)
+	i_shdrp += SHN_HIRESERVE + 1 - SHN_LORESERVE;
     }
-  amt = i_ehdrp->e_shnum;
-  amt *= sizeof (*x_shdrp);
   if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0
       || bfd_bwrite ((PTR) x_shdrp, amt, abfd) != amt)
     return false;
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.137
diff -u -p -r1.137 readelf.c
--- readelf.c	2001/12/08 03:45:51	1.137
+++ readelf.c	2001/12/11 02:54:30
@@ -197,8 +197,8 @@ static int                process_file  
 static int                process_relocs              PARAMS ((FILE *));
 static int                process_version_sections    PARAMS ((FILE *));
 static char *             get_ver_flags               PARAMS ((unsigned int));
-static int                get_32bit_section_headers   PARAMS ((FILE *));
-static int                get_64bit_section_headers   PARAMS ((FILE *));
+static int                get_32bit_section_headers   PARAMS ((FILE *, unsigned int));
+static int                get_64bit_section_headers   PARAMS ((FILE *, unsigned int));
 static int		  get_32bit_program_headers   PARAMS ((FILE *, Elf_Internal_Phdr *));
 static int		  get_64bit_program_headers   PARAMS ((FILE *, Elf_Internal_Phdr *));
 static int                get_file_header             PARAMS ((FILE *));
@@ -2442,12 +2442,28 @@ process_file_header ()
 	      (long) elf_header.e_phnum);
       printf (_("  Size of section headers:           %ld (bytes)\n"),
 	      (long) elf_header.e_shentsize);
-      printf (_("  Number of section headers:         %ld\n"),
+      printf (_("  Number of section headers:         %ld"),
 	      (long) elf_header.e_shnum);
-      printf (_("  Section header string table index: %ld\n"),
+      if (section_headers != NULL && elf_header.e_shnum == 0)
+	printf (" (%ld)", (long) section_headers[0].sh_size);
+      putc ('\n', stdout);
+      printf (_("  Section header string table index: %ld"),
 	      (long) elf_header.e_shstrndx);
+      if (section_headers != NULL && elf_header.e_shstrndx == SHN_XINDEX)
+	printf (" (%ld)", (long) section_headers[0].sh_link);
+      putc ('\n', stdout);
     }
 
+  if (section_headers != NULL)
+    {
+      if (elf_header.e_shnum == 0)
+	elf_header.e_shnum = section_headers[0].sh_size;
+      if (elf_header.e_shstrndx == SHN_XINDEX)
+	elf_header.e_shstrndx = section_headers[0].sh_link;
+      free (section_headers);
+      section_headers = NULL;
+    }
+
   return 1;
 }
 
@@ -2760,8 +2776,9 @@ process_program_headers (file)
 
 
 static int
-get_32bit_section_headers (file)
+get_32bit_section_headers (file, num)
      FILE * file;
+     unsigned int num;
 {
   Elf32_External_Shdr * shdrs;
   Elf32_Internal_Shdr * internal;
@@ -2769,13 +2786,13 @@ get_32bit_section_headers (file)
 
   shdrs = ((Elf32_External_Shdr *)
 	   get_data (NULL, file, elf_header.e_shoff,
-		     elf_header.e_shentsize * elf_header.e_shnum,
+		     elf_header.e_shentsize * num,
 		     _("section headers")));
   if (!shdrs)
     return 0;
 
-  section_headers = (Elf_Internal_Shdr *) malloc
-    (elf_header.e_shnum * sizeof (Elf_Internal_Shdr));
+  section_headers = ((Elf_Internal_Shdr *)
+		     malloc (num * sizeof (Elf_Internal_Shdr)));
 
   if (section_headers == NULL)
     {
@@ -2784,7 +2801,7 @@ get_32bit_section_headers (file)
     }
 
   for (i = 0, internal = section_headers;
-       i < elf_header.e_shnum;
+       i < num;
        i ++, internal ++)
     {
       internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
@@ -2805,8 +2822,9 @@ get_32bit_section_headers (file)
 }
 
 static int
-get_64bit_section_headers (file)
+get_64bit_section_headers (file, num)
      FILE * file;
+     unsigned int num;
 {
   Elf64_External_Shdr * shdrs;
   Elf64_Internal_Shdr * internal;
@@ -2814,13 +2832,13 @@ get_64bit_section_headers (file)
 
   shdrs = ((Elf64_External_Shdr *)
 	   get_data (NULL, file, elf_header.e_shoff,
-		     elf_header.e_shentsize * elf_header.e_shnum,
+		     elf_header.e_shentsize * num,
 		     _("section headers")));
   if (!shdrs)
     return 0;
 
-  section_headers = (Elf_Internal_Shdr *) malloc
-    (elf_header.e_shnum * sizeof (Elf_Internal_Shdr));
+  section_headers = ((Elf_Internal_Shdr *)
+		     malloc (num * sizeof (Elf_Internal_Shdr)));
 
   if (section_headers == NULL)
     {
@@ -2829,7 +2847,7 @@ get_64bit_section_headers (file)
     }
 
   for (i = 0, internal = section_headers;
-       i < elf_header.e_shnum;
+       i < num;
        i ++, internal ++)
     {
       internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
@@ -3007,10 +3025,10 @@ process_section_headers (file)
 
   if (is_32bit_elf)
     {
-      if (! get_32bit_section_headers (file))
+      if (! get_32bit_section_headers (file, elf_header.e_shnum))
 	return 0;
     }
-  else if (! get_64bit_section_headers (file))
+  else if (! get_64bit_section_headers (file, elf_header.e_shnum))
     return 0;
 
   /* Read in the string table, so that we have names to display.  */
@@ -9185,6 +9203,13 @@ get_file_header (file)
       elf_header.e_shnum     = BYTE_GET (ehdr64.e_shnum);
       elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
     }
+
+  /* There may be some extensions in the first section header.  Don't
+     bomb if we can't read it.  */
+  if (is_32bit_elf)
+    get_32bit_section_headers (file, 1);
+  else
+    get_64bit_section_headers (file, 1);
 
   return 1;
 }
Index: include/elf/common.h
===================================================================
RCS file: /cvs/src/src/include/elf/common.h,v
retrieving revision 1.36
diff -u -p -r1.36 common.h
--- common.h	2001/12/08 03:46:03	1.36
+++ common.h	2001/12/11 02:54:53
@@ -405,7 +405,7 @@ Foundation, Inc., 59 Temple Place - Suit
 #define SHN_HIOS        0xFF3F		/* OS specific semantics, hi */
 #define SHN_ABS	        0xFFF1		/* Associated symbol is absolute */
 #define SHN_COMMON      0xFFF2		/* Associated symbol is in common */
-#define SHN_XINDEX      0xFFFF		/* Section index it held elsewhere */
+#define SHN_XINDEX      0xFFFF		/* Section index is held elsewhere */
 #define SHN_HIRESERVE   0xFFFF		/* End range of reserved indices */
 
 /* The following constants control how a symbol may be accessed once it has
Index: include/elf/internal.h
===================================================================
RCS file: /cvs/src/src/include/elf/internal.h,v
retrieving revision 1.6
diff -u -p -r1.6 internal.h
--- internal.h	2001/10/23 04:42:12	1.6
+++ internal.h	2001/12/11 02:54:53
@@ -50,12 +50,12 @@ typedef struct elf_internal_ehdr {
   unsigned long		e_flags;	/* Processor-specific flags */
   unsigned short	e_type;		/* Identifies object file type */
   unsigned short	e_machine;	/* Specifies required architecture */
-  unsigned short	e_ehsize;	/* ELF header size in bytes */
-  unsigned short	e_phentsize;	/* Program header table entry size */
-  unsigned short	e_phnum;	/* Program header table entry count */
-  unsigned short	e_shentsize;	/* Section header table entry size */
-  unsigned short	e_shnum;	/* Section header table entry count */
-  unsigned short	e_shstrndx;	/* Section header string table index */
+  unsigned int		e_ehsize;	/* ELF header size in bytes */
+  unsigned int		e_phentsize;	/* Program header table entry size */
+  unsigned int		e_phnum;	/* Program header table entry count */
+  unsigned int		e_shentsize;	/* Section header table entry size */
+  unsigned int		e_shnum;	/* Section header table entry count */
+  unsigned int		e_shstrndx;	/* Section header string table index */
 } Elf_Internal_Ehdr;
 
 #define elf32_internal_ehdr elf_internal_ehdr


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