changeset 13222:93a5a82b3b75

(unexec): Find the old data section. New variable new_offsets_shift used instead of new_data2_size since they are not always the same. Simplify logic for copying the headers and inserting new ones.
author Richard M. Stallman <rms@gnu.org>
date Sun, 15 Oct 1995 00:59:48 +0000
parents 994440ef957f
children b0717b54e8b6
files src/=unexsgi.c
diffstat 1 files changed, 98 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/src/=unexsgi.c	Sat Oct 14 20:42:26 1995 +0000
+++ b/src/=unexsgi.c	Sun Oct 15 00:59:48 1995 +0000
@@ -491,6 +491,7 @@
   Elf32_Word old_bss_size, new_data2_size;
   Elf32_Off  new_data2_offset;
   Elf32_Addr new_data2_addr;
+  Elf32_Addr new_offsets_shift;
 
   int n, nn, old_bss_index, old_data_index, new_data2_index;
   int old_mdebug_index;
@@ -536,10 +537,9 @@
 	break;
     }
   if (old_mdebug_index == old_file_h->e_shnum)
-    old_mdebug_index = -1; /* just means no such section was present */
+    old_mdebug_index = -1;	/* just means no such section was present */
 
-  /* Find the old .bss section.  Figure out parameters of the new
-     data2 and bss sections.  */
+  /* Find the old .bss section. */
 
   for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
     {
@@ -554,6 +554,24 @@
   if (old_bss_index == old_file_h->e_shnum)
     fatal ("Can't find .bss in %s.\n", old_name, 0);
 
+  /* Find the old .data section.  Figure out parameters of
+     the new data2 and bss sections.  */
+
+  for (old_data_index = 1;
+       old_data_index < old_file_h->e_shnum;
+       old_data_index++)
+    {
+#ifdef DEBUG
+      fprintf (stderr, "Looking for .data - found %s\n",
+	       old_section_names + OLD_SECTION_H(old_data_index).sh_name);
+#endif
+      if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name,
+		   ".data"))
+	break;
+    }
+  if (old_data_index == old_file_h->e_shnum)
+    fatal ("Can't find .data in %s.\n", old_name, 0);
+
   old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
   old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
 #if defined(emacs) || !defined(DEBUG)
@@ -564,7 +582,10 @@
 #endif
   new_data2_addr = old_bss_addr;
   new_data2_size = new_bss_addr - old_bss_addr;
-  new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset;
+  new_data2_offset  = OLD_SECTION_H (old_data_index).sh_offset +
+    (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
+  new_offsets_shift = new_bss_addr -
+    ((old_bss_addr & ~0xfff) + ((old_bss_addr & 0xfff) ? 0x1000 : 0));
 
 #ifdef DEBUG
   fprintf (stderr, "old_bss_index %d\n", old_bss_index);
@@ -574,6 +595,7 @@
   fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
   fprintf (stderr, "new_data2_size %x\n", new_data2_size);
   fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
+  fprintf (stderr, "new_offsets_shift %x\n", new_offsets_shift);
 #endif
 
   if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
@@ -587,7 +609,7 @@
   if (new_file < 0)
     fatal ("Can't creat (%s): errno %d\n", new_name, errno);
 
-  new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
+  new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_offsets_shift; 
 
   if (ftruncate (new_file, new_file_size))
     fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
@@ -602,7 +624,7 @@
   new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
   new_section_h
     = (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff
-		      + new_data2_size);
+		      + new_offsets_shift);
 
   /* Make our new file, program and section headers as copies of the
      originals.  */
@@ -617,7 +639,7 @@
   /* Fix up file header.  We'll add one section.  Section header is
      further away now.  */
 
-  new_file_h->e_shoff += new_data2_size;
+  new_file_h->e_shoff += new_offsets_shift;
   new_file_h->e_shnum += 1;
 
 #ifdef DEBUG
@@ -657,18 +679,18 @@
   if (n < 0)
     fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
 
-  NEW_PROGRAM_H (n).p_filesz += new_data2_size;
+  NEW_PROGRAM_H (n).p_filesz += new_offsets_shift;
   NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
 
-#if 1 /* Maybe allow section after data2 - does this ever happen?  */
+#if 1				/* Maybe allow section after data2 - does this ever happen?  */
   for (n = new_file_h->e_phnum - 1; n >= 0; n--)
     {
       if (NEW_PROGRAM_H (n).p_vaddr
 	  && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
-	NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
+	NEW_PROGRAM_H (n).p_vaddr += new_offsets_shift - old_bss_size;
 
       if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
-	NEW_PROGRAM_H (n).p_offset += new_data2_size;
+	NEW_PROGRAM_H (n).p_offset += new_offsets_shift;
     }
 #endif
 
@@ -690,9 +712,17 @@
   for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
     {
       caddr_t src;
-      /* If it is bss section, insert the new data2 section before it.  */
-      if (n == old_bss_index)
+
+      if (n < old_bss_index)
 	{
+	  memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), 
+		  old_file_h->e_shentsize);
+	  
+	}
+      else if (n == old_bss_index)
+	{
+	  
+	  /* If it is bss section, insert the new data2 section before it.  */
 	  /* Steal the data section header for this data2 section.  */
 	  memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
 		  new_file_h->e_shentsize);
@@ -710,28 +740,32 @@
 		  (caddr_t) OLD_SECTION_H (n).sh_addr, 
 		  new_data2_size);
 	  nn++;
-	}
-      
-      memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), 
-	      old_file_h->e_shentsize);
+	  memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), 
+		  old_file_h->e_shentsize);
       
-      /* The new bss section's size is zero, and its file offset and virtual
-	 address should be off by NEW_DATA2_SIZE.  */
-      if (n == old_bss_index)
-	{
-	  /* NN should be `old_bss_index + 1' at this point. */
-	  NEW_SECTION_H (nn).sh_offset += new_data2_size;
-	  NEW_SECTION_H (nn).sh_addr += new_data2_size;
+	  /* The new bss section's size is zero, and its file offset and virtual
+	     address should be off by NEW_OFFSETS_SHIFT.  */
+	  NEW_SECTION_H (nn).sh_offset += new_offsets_shift;
+	  NEW_SECTION_H (nn).sh_addr	= new_bss_addr;
 	  /* Let the new bss section address alignment be the same as the
 	     section address alignment followed the old bss section, so 
 	     this section will be placed in exactly the same place.  */
 	  NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
 	  NEW_SECTION_H (nn).sh_size = 0;
 	}
-      /* Any section that was original placed AFTER the bss section should now
-	 be off by NEW_DATA2_SIZE.  */
-      else if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
-	NEW_SECTION_H (nn).sh_offset += new_data2_size;
+      else			/* n > old_bss_index */
+	{
+	  
+	  memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), 
+		  old_file_h->e_shentsize);
+      
+	}
+
+      /* Any section that was original placed AFTER the bss
+	 section must now be adjusted by NEW_OFFSETS_SHIFT.  */
+
+      if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
+	NEW_SECTION_H (nn).sh_offset += new_offsets_shift;
       
       /* If any section hdr refers to the section after the new .data
 	 section, make it refer to next one because we have inserted 
@@ -753,8 +787,8 @@
 	 ".data" in the strings table) get copied from the current process
 	 instead of the old file.  */
       if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
-	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
-		      ".data1"))
+	  || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1")
+	  || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".got"))
 	src = (caddr_t) OLD_SECTION_H (n).sh_addr;
       else
 	src = old_base + OLD_SECTION_H (n).sh_offset;
@@ -778,42 +812,42 @@
       n_phdrr->__fileaddr += movement;		\
     }
 
-	HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
-	HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
-	unsigned movement = new_data2_size;
+	  HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
+	  HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
+	  unsigned movement = new_offsets_shift;
 
-	MDEBUGADJUST (idnMax, cbDnOffset);
-	MDEBUGADJUST (ipdMax, cbPdOffset);
-	MDEBUGADJUST (isymMax, cbSymOffset);
-	MDEBUGADJUST (ioptMax, cbOptOffset);
-	MDEBUGADJUST (iauxMax, cbAuxOffset);
-	MDEBUGADJUST (issMax, cbSsOffset);
-	MDEBUGADJUST (issExtMax, cbSsExtOffset);
-	MDEBUGADJUST (ifdMax, cbFdOffset);
-	MDEBUGADJUST (crfd, cbRfdOffset);
-	MDEBUGADJUST (iextMax, cbExtOffset);
-	/* The Line Section, being possible off in a hole of the object,
-	   requires special handling.  */
-	if (n_phdrr->cbLine > 0)
-	  {
-	    if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
-					 + OLD_SECTION_H (n).sh_size))
-	      {
-		/* line data is in a hole in elf. do special copy and adjust
-		   for this ld mistake.
-		   */
-		n_phdrr->cbLineOffset += movement;
+	  MDEBUGADJUST (idnMax, cbDnOffset);
+	  MDEBUGADJUST (ipdMax, cbPdOffset);
+	  MDEBUGADJUST (isymMax, cbSymOffset);
+	  MDEBUGADJUST (ioptMax, cbOptOffset);
+	  MDEBUGADJUST (iauxMax, cbAuxOffset);
+	  MDEBUGADJUST (issMax, cbSsOffset);
+	  MDEBUGADJUST (issExtMax, cbSsExtOffset);
+	  MDEBUGADJUST (ifdMax, cbFdOffset);
+	  MDEBUGADJUST (crfd, cbRfdOffset);
+	  MDEBUGADJUST (iextMax, cbExtOffset);
+	  /* The Line Section, being possible off in a hole of the object,
+	     requires special handling.  */
+	  if (n_phdrr->cbLine > 0)
+	    {
+	      if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
+					   + OLD_SECTION_H (n).sh_size))
+		{
+		  /* line data is in a hole in elf. do special copy and adjust
+		     for this ld mistake.
+		     */
+		  n_phdrr->cbLineOffset += movement;
 
-		memcpy (n_phdrr->cbLineOffset + new_base,
-			o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
-	      }
-	    else
-	      {
-		/* somehow line data is in .mdebug as it is supposed to be.  */
-		MDEBUGADJUST (cbLine, cbLineOffset);
-	      }
-	  }
-      }
+		  memcpy (n_phdrr->cbLineOffset + new_base,
+			  o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
+		}
+	      else
+		{
+		  /* somehow line data is in .mdebug as it is supposed to be.  */
+		  MDEBUGADJUST (cbLine, cbLineOffset);
+		}
+	    }
+	}
 
       /* If it is the symbol table, its st_shndx field needs to be patched. */
       if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB