]> git.eshelyaron.com Git - emacs.git/commitdiff
Handle both AIX 3.2 and 4.1 bind output.
authorRichard M. Stallman <rms@gnu.org>
Thu, 7 Mar 1996 20:17:45 +0000 (20:17 +0000)
committerRichard M. Stallman <rms@gnu.org>
Thu, 7 Mar 1996 20:17:45 +0000 (20:17 +0000)
(make_hdr): Handle data_start being non-zero for 4.1.  Padding
sections are omitted in 4.1, but padding bytes can still be
present.  Calculate bias directly from first real section following bss.

(copy_text_and_data): Correct data section starting point for 4.1.

(adjust_lnnoptrs): Adjust line number pointers correctly for both
3.2 and 4.1, based on published IBM documentation.

(unrelocate_symbols): Compute and subtract relocation offsets for
text and data sections.  Handle data_start being non-zero for 4.1.
Skip unnecessary writes.

src/unexaix.c

index 69b19d2dc5477e222ef053d8ec91a835fe2c73b8..445f01886dd27906cc778baf91cfdf2064a20f99 100644 (file)
@@ -33,6 +33,14 @@ what you give them.   Help stamp out software-hoarding!  */
  * Date:       Tue Mar  2 1982
  * Modified heavily since then.
  *
+ * Updated for AIX 4.1.3 by Bill_Mann @ PraxisInt.com, Feb 1996
+ *   As of AIX 4.1, text, data, and bss are pre-relocated by the binder in
+ *   such a way that the file can be mapped with code in one segment and
+ *   data/bss in another segment, without reading or copying the file, by
+ *   the AIX exec loader.  Padding sections are omitted, nevertheless
+ *   small amounts of 'padding' still occurs between sections in the file.
+ *   As modified, this code handles both 3.2 and 4.1 conventions.
+ *
  * Synopsis:
  *     unexec (new_name, a_name, data_start, bss_start, entry_address)
  *     char *new_name, *a_name;
@@ -203,21 +211,20 @@ extern int _end;
 #endif /* not UMAX */
 #endif /* Not STRIDE */
 #endif /* not USG */
-static long block_copy_start;          /* Old executable start point */
 static struct filehdr f_hdr;           /* File header */
 static struct aouthdr f_ohdr;          /* Optional file header (a.out) */
 long bias;                     /* Bias to add for growth */
 long lnnoptr;                  /* Pointer to line-number info within file */
-#define SYMS_START block_copy_start
 
 static long text_scnptr;
 static long data_scnptr;
 #ifdef XCOFF
+#define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1))
 static long load_scnptr;
 static long orig_load_scnptr;
 static long orig_data_scnptr;
 #endif
-static long data_st;
+static ulong data_st;                   /* start of data area written out */
 
 #ifndef MAX_SECTIONS
 #define MAX_SECTIONS   10
@@ -381,7 +388,6 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
 
 #ifdef COFF
   /* Salvage as much info from the existing file as possible */
-  block_copy_start = 0;
   f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL;
   f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL;
   if (a_out >= 0)
@@ -390,14 +396,12 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
        {
          PERROR (a_name);
        }
-      block_copy_start += sizeof (f_hdr);
       if (f_hdr.f_opthdr > 0)
        {
          if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
            {
              PERROR (a_name);
            }
-         block_copy_start += sizeof (f_ohdr);
        }
       if (f_hdr.f_nscns > MAX_SECTIONS)
        {
@@ -410,11 +414,6 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
          {
            PERROR (a_name);
          }
-       if (s->s_scnptr > 0L)
-         {
-            if (block_copy_start < s->s_scnptr + s->s_size)
-             block_copy_start = s->s_scnptr + s->s_size;
-         }
 
 #define CHECK_SCNHDR(ptr, name, flags) \
   if (strcmp(s->s_name, name) == 0) { \
@@ -459,7 +458,11 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
 
   /* Now we alter the contents of all the f_*hdr variables
      to correspond to what we want to dump.  */
-  f_hdr.f_flags |= (F_RELFLG | F_EXEC);                /* Why? */
+
+  /* Indicate that the reloc information is no longer valid for ld (bind);
+     we only update it enough to fake out the exec-time loader.  */
+  f_hdr.f_flags |= (F_RELFLG | F_EXEC);
+
 #ifdef EXEC_MAGIC
   f_ohdr.magic = EXEC_MAGIC;
 #endif
@@ -467,73 +470,77 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
   f_ohdr.tsize = data_start - f_ohdr.text_start;
   f_ohdr.text_start = (long) start_of_text ();
 #endif
-  f_ohdr.dsize = bss_start - ((unsigned) &_data);
+  data_st = f_ohdr.data_start ? f_ohdr.data_start : (ulong) &_data;
+  f_ohdr.dsize = bss_start - data_st;
   f_ohdr.bsize = bss_end - bss_start;
 
   f_dhdr->s_size = f_ohdr.dsize;
   f_bhdr->s_size = f_ohdr.bsize;
-  f_bhdr->s_paddr = f_ohdr.dsize;
-  f_bhdr->s_vaddr = f_ohdr.dsize;
+  f_bhdr->s_paddr = f_ohdr.data_start + f_ohdr.dsize;
+  f_bhdr->s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
 
   /* fix scnptr's */
   {
-    long ptr;
+    ulong ptr = section[0].s_scnptr;
 
-    for (scns = 0; scns < f_hdr.f_nscns; scns++) {
-      struct scnhdr *s = &section[scns];
-      if (scns == 0)
-       ptr = s->s_scnptr;
+    bias = -1;
+    for (scns = 0; scns < f_hdr.f_nscns; scns++)
+      {
+       struct scnhdr *s = &section[scns];
 
-      if (s->s_scnptr != 0)
-       {
+       if (s->s_flags & STYP_PAD)        /* .pad sections omitted in AIX 4.1 */
+         {
+           /*
+            * the text_start should probably be o_algntext but that doesn't
+            * seem to change
+            */
+           if (f_ohdr.text_start != 0) /* && scns != 0 */
+             {
+               s->s_size = 512 - (ptr % 512);
+               if (s->s_size == 512)
+                 s->s_size = 0;
+             }
+           s->s_scnptr = ptr;
+         }
+       else if (s->s_flags & STYP_DATA)
          s->s_scnptr = ptr;
-       }
-
-      if ((s->s_flags & 0xffff) == STYP_PAD)
-       {
-         /*
-          * the text_start should probably be o_algntext but that doesn't
-          * seem to change
-          */
-         if (f_ohdr.text_start != 0) /* && scns != 0 */
-           {
-             s->s_size = 512 - (s->s_scnptr % 512);
-             if (s->s_size == 512)
-               s->s_size = 0;
-           }
-       }
-
-      ptr = ptr + s->s_size;
-    }
+       else if (!(s->s_flags & (STYP_TEXT | STYP_BSS)))
+         {
+           if (bias == -1)                /* if first section after bss */
+             bias = ptr - s->s_scnptr;
 
-    bias = ptr - block_copy_start;
+           s->s_scnptr += bias;
+           ptr = s->s_scnptr;
+         }
+  
+       ptr = ptr + s->s_size;
+      }
   }
 
   /* fix other pointers */
-  for (scns = 0; scns < f_hdr.f_nscns; scns++) {
-    struct scnhdr *s = &section[scns];
+  for (scns = 0; scns < f_hdr.f_nscns; scns++)
+    {
+      struct scnhdr *s = &section[scns];
 
-    if (s->s_relptr != 0)
-      {
-       s->s_relptr += bias;
-      }
-    if (s->s_lnnoptr != 0)
-      {
-       if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
-       s->s_lnnoptr += bias;
-      }
-  }
+      if (s->s_relptr != 0)
+       {
+         s->s_relptr += bias;
+       }
+      if (s->s_lnnoptr != 0)
+       {
+         if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
+         s->s_lnnoptr += bias;
+       }
+    }
 
   if (f_hdr.f_symptr > 0L)
     {
       f_hdr.f_symptr += bias;
     }
 
-  data_st = data_start;
   text_scnptr = f_thdr->s_scnptr;
   data_scnptr = f_dhdr->s_scnptr;
   load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
-  block_copy_start = orig_load_scnptr;
 
 #ifdef ADJUST_EXEC_HEADER
   ADJUST_EXEC_HEADER
@@ -583,7 +590,7 @@ copy_text_and_data (new)
   write_segment (new, ptr, end);
 
   lseek (new, (long) data_scnptr, 0);
-  ptr = (char *) &_data;
+  ptr = (char *) data_st;
   end = ptr + f_ohdr.dsize;
   write_segment (new, ptr, end);
 
@@ -644,13 +651,13 @@ copy_sym (new, a_out, a_name, new_name)
   if (a_out < 0)
     return 0;
 
-  if (SYMS_START == 0L)
+  if (orig_load_scnptr == 0L)
     return 0;
 
-  if (lnnoptr && lnnoptr < SYMS_START) /* if there is line number info */
-    lseek (a_out, lnnoptr, 0);         /* start copying from there */
+  if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info  */
+    lseek (a_out, lnnoptr, 0);  /* start copying from there */
   else
-    lseek (a_out, SYMS_START, 0);      /* Position a.out to symtab. */
+    lseek (a_out, orig_load_scnptr, 0); /* Position a.out to symtab. */
 
   while ((n = read (a_out, page, sizeof page)) > 0)
     {
@@ -703,6 +710,8 @@ mark_x (name)
  *     the auxiliary entries that need adjustment, this routine will
  *     be fixed.  As it is now, all such entries are wrong and sdb
  *     will complain.   Fred Fish, UniSoft Systems Inc.
+ *
+ *      I believe this is now fixed correctly.  Bill Mann
  */
 
 #ifdef COFF
@@ -743,15 +752,17 @@ adjust_lnnoptrs (writedesc, readdesc, new_name)
   for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
     {
       read (new, &symentry, SYMESZ);
-      for (naux = 0; naux < symentry.n_numaux; naux++)
+      for (naux = symentry.n_numaux; naux-- != 0; )
        {
          read (new, &auxentry, AUXESZ);
          nsyms++;
-         if (ISFCN (symentry.n_type)) {
-           auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
-           lseek (new, -AUXESZ, 1);
-           write (new, &auxentry, AUXESZ);
-         }
+         if (naux != 0              /* skip csect auxentry (last entry) */
+              && (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT))
+            {
+              auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
+              lseek (new, -AUXESZ, 1);
+              write (new, &auxentry, AUXESZ);
+            }
        }
     }
   close (new);
@@ -774,8 +785,8 @@ unrelocate_symbols (new, a_out, a_name, new_name)
   register LDREL *ldrel;
   LDHDR ldhdr;
   LDREL ldrel_buf [20];
-  ulong t_start = (ulong) &_text;
-  ulong d_start = (ulong) &_data;
+  ulong t_reloc = (ulong) &_text - f_ohdr.text_start;
+  ulong d_reloc = (ulong) &_data - ALIGN(f_ohdr.data_start, 2);
   int * p;
   int dirty;
 
@@ -837,49 +848,37 @@ unrelocate_symbols (new, a_out, a_name, new_name)
        {
          int orig_int;
 
-#ifdef AIX4_1
-         lseek (a_out, orig_data_scnptr + (ldrel->l_vaddr - d_start), 0);
-#else
-         lseek (a_out, orig_data_scnptr + ldrel->l_vaddr, 0);
-#endif
+         lseek (a_out,
+                 orig_data_scnptr + (ldrel->l_vaddr - f_ohdr.data_start), 0);
 
          if (read (a_out, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))
            {
              PERROR (a_name);
            }
 
+          p = (int *) (ldrel->l_vaddr + d_reloc);
+
          switch (ldrel->l_symndx) {
          case SYMNDX_TEXT:
-#ifdef AIX4_1
-           p = (int *) (ldrel->l_vaddr);
-           orig_int = * p;
-#else
-           p = (int *) (d_start + ldrel->l_vaddr);
-           orig_int = * p - (t_start - f_ohdr.text_start);
-#endif
+           orig_int = * p - t_reloc;
            break;
 
          case SYMNDX_DATA:
          case SYMNDX_BSS:
-#ifdef AIX4_1
-           p = (int *) (ldrel->l_vaddr);
-           orig_int = * p;
-#else
-           p = (int *) (d_start + ldrel->l_vaddr);
-           orig_int = * p - (d_start - f_ohdr.data_start);
-#endif
+           orig_int = * p - d_reloc;
            break;
          }
 
-#ifdef AIX4_1
-         lseek (new, data_scnptr + (ldrel->l_vaddr - d_start), 0);
-#else
-         lseek (new, data_scnptr + ldrel->l_vaddr, 0);
-#endif
-         if (write (new, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))
-           {
-             PERROR (new_name);
-           }
+          if (orig_int != * p)
+            {
+              lseek (new,
+                     data_scnptr + (ldrel->l_vaddr - f_ohdr.data_start), 0);
+              if (write (new, (void *) &orig_int, sizeof (orig_int))
+                  != sizeof (orig_int))
+                {
+                  PERROR (new_name);
+                }
+            }
        }
     }
 }