diff src/unexelf.c @ 25398:4b8cf5270829

Merge IRIX debugging info patch from unexsgi.c Auto-detect .sbss section. (round_up): Make it static. (unexec): Declare alignment as Elf Word. Skip ``Program segment above .bss'' test on MIPS without .sbss. Copy sections .got and .sdata1 sections. Adjust offsets in sections .sdata, .lit4, .lit8, .got and .sdata1.
author Karl Heuer <kwzh@gnu.org>
date Wed, 25 Aug 1999 16:15:29 +0000
parents f0d69d0f8222
children 3d7b096fb086
line wrap: on
line diff
--- a/src/unexelf.c	Wed Aug 25 16:15:06 1999 +0000
+++ b/src/unexelf.c	Wed Aug 25 16:15:29 1999 +0000
@@ -427,16 +427,10 @@
 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
 #include <sys/elf_mips.h>
 #include <sym.h>
-#define HAS_SBSS_SECTION
 #endif /* __sony_news && _SYSTYPE_SYSV */
-
-#if defined (__NetBSD__) && defined (__powerpc__)
-#define HAS_SBSS_SECTION
-#endif
-
-#if defined (__linux__) && defined (__alpha__)
-#define HAS_SBSS_SECTION
-#endif
+#if __sgi
+#include <sym.h> /* for HDRR declaration */
+#endif /* __sgi */
 
 #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
 /* Declare COFF debugging symbol table.  This used to be in
@@ -543,7 +537,7 @@
 /* Get the address of a particular section or program header entry,
  * accounting for the size of the entries.
  */
-/* 
+/*
    On PPC Reference Platform running Solaris 2.5.1
    the plt section is also of type NOBI like the bss section.
    (not really stored) and therefore sections after the bss
@@ -552,7 +546,7 @@
    Thus, we modify the test from
       if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
    to
-      if (NEW_SECTION_H (nn).sh_offset >= 
+      if (NEW_SECTION_H (nn).sh_offset >=
                OLD_SECTION_H (old_bss_index-1).sh_offset)
    This is just a hack. We should put the new data section
    before the .plt section.
@@ -584,7 +578,7 @@
 
 /* Round X up to a multiple of Y.  */
 
-ElfW(Addr)
+static ElfW(Addr)
 round_up (x, y)
      ElfW(Addr) x, y;
 {
@@ -629,9 +623,7 @@
   ElfW(Addr) new_data2_addr;
 
   int n, nn, old_bss_index, old_data_index, new_data2_index;
-#if defined (HAS_SBSS_SECTION)
   int old_sbss_index, old_mdebug_index;
-#endif /* HAS_SBSS_SECTION */
   struct stat stat_buf;
 
   /* Open the old file & map it into the address space. */
@@ -681,7 +673,6 @@
   if (old_bss_index == old_file_h->e_shnum)
     fatal ("Can't find .bss in %s.\n", old_name, 0);
 
-#if defined (HAS_SBSS_SECTION)
   for (old_sbss_index = 1; old_sbss_index < (int) old_file_h->e_shnum;
        old_sbss_index++)
     {
@@ -695,6 +686,7 @@
     }
   if (old_sbss_index == old_file_h->e_shnum)
     {
+      old_sbss_index = -1;
       old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
       old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
       new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset;
@@ -722,10 +714,7 @@
     }
     if (old_mdebug_index == old_file_h->e_shnum)
 	old_mdebug_index = 0;
-#else /* not HAS_SBSS_SECTION */	    
-  old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
-  old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
-#endif /* not HAS_SBSS_SECTION */	    
+
 #if defined (emacs) || !defined (DEBUG)
   new_bss_addr = (ElfW(Addr)) sbrk (0);
 #else
@@ -733,9 +722,6 @@
 #endif
   new_data2_addr = old_bss_addr;
   new_data2_size = new_bss_addr - old_bss_addr;
-#if !defined (HAS_SBSS_SECTION)
-  new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset;
-#endif /* not HAS_SBSS_SECTION */
 
 #ifdef DEBUG
   fprintf (stderr, "old_bss_index %d\n", old_bss_index);
@@ -816,18 +802,22 @@
   for (n = new_file_h->e_phnum - 1; n >= 0; n--)
     {
       /* Compute maximum of all requirements for alignment of section.  */
-      int alignment = (NEW_PROGRAM_H (n)).p_align;
+      ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align;
       if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
 	alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
 
-#if defined (HAS_SBSS_SECTION)
+#ifdef __mips
+	  /* According to r02kar@x4u2.desy.de (Karsten Kuenne)
+	     and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we
+	     always get "Program segment above .bss" when dumping
+	     when the executable doesn't have an sbss section.  */
+      if (old_sbss_index != -1)
+#endif /* __mips */
       if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
-	  > round_up (old_bss_addr, alignment))
-	fatal ("Program segment above .bss in %s\n", old_name, 0);
-#else /* not HAS_SBSS_SECTION */
-      if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr)
-	fatal ("Program segment above .bss in %s\n", old_name, 0);
-#endif /* not HAS_SBSS_SECTION */
+	  > (old_sbss_index == -1
+	     ? old_bss_addr
+	     : round_up (old_bss_addr, alignment)))
+	  fatal ("Program segment above .bss in %s\n", old_name, 0);
 
       if (NEW_PROGRAM_H (n).p_type == PT_LOAD
 	  && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
@@ -875,17 +865,10 @@
   for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++)
     {
       caddr_t src;
-      int temp_index;
-#if defined (HAS_SBSS_SECTION)
       /* If it is (s)bss section, insert the new data2 section before it.  */
       /* new_data2_index is the index of either old_sbss or old_bss, that was
 	 chosen as a section for new_data2.   */
-      temp_index = new_data2_index;
-#else /* not HAS_SBSS_SECTION */
-      /* If it is bss section, insert the new data2 section before it.  */
-      temp_index = old_bss_index;
-#endif /* not HAS_SBSS_SECTION */
-      if (n == temp_index)
+      if (n == new_data2_index)
 	{
 	  /* Steal the data section header for this data2 section. */
 	  memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
@@ -910,16 +893,16 @@
 	      old_file_h->e_shentsize);
       
       if (n == old_bss_index
-#if defined (HAS_SBSS_SECTION)
 	  /* The new bss and sbss section's size is zero, and its file offset
 	     and virtual address should be off by NEW_DATA2_SIZE.  */
 	  || n == old_sbss_index
-#endif /* HAS_SBSS_SECTION */
 	  )
 	{
-	  /* 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;
+	  /* NN should be `old_s?bss_index + 1' at this point. */
+	  NEW_SECTION_H (nn).sh_offset =
+	    NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size;
+	  NEW_SECTION_H (nn).sh_addr =
+	    NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size;
 	  /* 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. */
@@ -975,18 +958,16 @@
 	 ".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")
-#ifdef _nec_ews_svr4				/* hir, 1994.6.13 */
-	  || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name),
-		      ".sdata")
-#endif
-#if defined (HAS_SBSS_SECTION)
 	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
 		      ".sdata")
 	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
 		      ".lit4")
 	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
 		      ".lit8")
-#endif /* HAS_SBSS_SECTION */
+	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+		      ".got")
+	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+		      ".sdata1")
 	  || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
 		      ".data1"))
 	src = (caddr_t) OLD_SECTION_H (n).sh_addr;
@@ -1040,6 +1021,62 @@
 	    }
 	}
 #endif /* __sony_news && _SYSTYPE_SYSV */
+
+#if __sgi
+      /* Adjust  the HDRR offsets in .mdebug and copy the 
+	 line data if it's in its usual 'hole' in the object.
+	 Makes the new file debuggable with dbx.
+	 patches up two problems: the absolute file offsets
+	 in the HDRR record of .mdebug (see /usr/include/syms.h), and
+	 the ld bug that gets the line table in a hole in the
+	 elf file rather than in the .mdebug section proper.
+	 David Anderson. davea@sgi.com  Jan 16,1994.  */
+      if (n == old_mdebug_index)
+	{
+#define MDEBUGADJUST(__ct,__fileaddr)		\
+  if (n_phdrr->__ct > 0)			\
+    {						\
+      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;
+
+	  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);
+		}
+	    }
+	}
+#endif /* __sgi */
+
       /* If it is the symbol table, its st_shndx field needs to be patched.  */
       if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
 	  || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
@@ -1099,6 +1136,16 @@
 	nn = section.sh_info;
 	if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
 	    || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
+			".sdata")
+	    || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
+			".lit4")
+	    || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
+			".lit8")
+	    || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
+			".got")
+	    || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
+			".sdata1")
+	    || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
 			".data1"))
 	  {
 	    ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr -