* libhppa.h (PA_PAGESIZE): Define.
authorJeff Law <law@redhat.com>
Sat, 19 Mar 1994 03:54:49 +0000 (03:54 +0000)
committerJeff Law <law@redhat.com>
Sat, 19 Mar 1994 03:54:49 +0000 (03:54 +0000)
        * som.c (SOM_ALIGN): Define.
        (som_begin_writing): If writing an executable, initialize all
        fields in the exec header to zero.  Update fields in the exec
        header as sizes of loadable subspaces are computed.  Carefully
        preserve alignments when building executables.  Actually write the
        exec after all the fields are filled in.

bfd/ChangeLog
bfd/som.c

index e37ff15661424db87186d347116c99d1033d8672..6bd7b5010ddd8ef192239d64577429f4a4c80e74 100644 (file)
@@ -1,5 +1,14 @@
 Fri Mar 18 18:13:49 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
 
+       * libhppa.h (PA_PAGESIZE): Define.
+
+       * som.c (SOM_ALIGN): Define.
+       (som_begin_writing): If writing an executable, initialize all
+       fields in the exec header to zero.  Update fields in the exec
+       header as sizes of loadable subspaces are computed.  Carefully
+       preserve alignments when building executables.  Actually write the
+       exec after all the fields are filled in.
+
         * Better long-filename handling.  Reads SOM ABI compliant extended
        names, but doesn't quite write compliant extended names yet.
        * som.c (som_slurp_extended_name_table): Delete function.  The
index 92b2e6fd4784f397b316c523cd04126fc2adf400..630f7c8cfee6d3dcd3920e5106a43a49c0ddb9a8 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
 /* Max number of SOMs to be found in an archive.  */
 #define SOM_LST_MODULE_LIMIT 1024
 
+/* Generic alignment macro.  */
+#define SOM_ALIGN(val, alignment) \
+  (((val) + (alignment) - 1) & ~((alignment) - 1))
+
 /* SOM allows any one of the four previous relocations to be reused
    with a "R_PREV_FIXUP" relocation entry.  Since R_PREV_FIXUP
    relocations are always a single byte, using a R_PREV_FIXUP instead
@@ -2654,6 +2658,7 @@ som_begin_writing (abfd)
   asection *section;
   asymbol **syms = bfd_get_outsymbols (abfd);
   unsigned int total_subspaces = 0;
+  struct som_exec_auxhdr exec_header;
 
   /* The file header will always be first in an object file, 
      everything else can be in random locations.  To keep things
@@ -2676,10 +2681,13 @@ som_begin_writing (abfd)
   if (abfd->flags & EXEC_P)
     {
       /* Parts of the exec header will be filled in later, so
-        delay writing the header itself.  Just leave space for
-        it.  */
-      current_offset += sizeof (struct som_exec_auxhdr);
-      obj_som_file_hdr (abfd)->aux_header_size += sizeof (struct som_exec_auxhdr);
+        delay writing the header itself.  Fill in the defaults,
+        and write it later.  */
+      current_offset += sizeof (exec_header);
+      obj_som_file_hdr (abfd)->aux_header_size += sizeof (exec_header);
+      memset (&exec_header, 0, sizeof (exec_header));
+      exec_header.som_auxhdr.type = HPUX_AUX_ID;
+      exec_header.som_auxhdr.length = 40;
     }
   if (obj_som_version_hdr (abfd) != NULL)
     {
@@ -2841,32 +2849,73 @@ som_begin_writing (abfd)
   obj_som_file_hdr (abfd)->compiler_location = current_offset;
   obj_som_file_hdr (abfd)->compiler_total = 0;
 
-  /* Now compute the file positions for the loadable subspaces.  */
+  /* Now compute the file positions for the loadable subspaces, taking
+     care to make sure everything stays properly aligned.  */
 
   section = abfd->sections;
   for (i = 0; i < num_spaces; i++)
     {
       asection *subsection;
+      int first_subspace;
 
       /* Find a space.  */
       while (som_section_data (section)->is_space == 0)
        section = section->next;
 
+      first_subspace = 1;
       /* Now look for all its subspaces.  */
       for (subsection = abfd->sections;
           subsection != NULL;
           subsection = subsection->next)
        {
-         
+
          if (som_section_data (subsection)->is_subspace == 0
              || som_section_data (subsection)->containing_space != section
              || (subsection->flags & SEC_ALLOC) == 0)
            continue;
 
+         /* If this is the first subspace in the space, and we are
+            building an executable, then take care to make sure all
+            the alignments are correct and update the exec header.  */
+         if (first_subspace
+             && (abfd->flags & EXEC_P))
+           {
+             /* Demand paged executables have each space aligned to a
+                page boundary.  Sharable executables (write-protected
+                text) have just the private (aka data & bss) space aligned
+                to a page boundary.  */
+             if (abfd->flags & D_PAGED
+                 || ((abfd->flags & WP_TEXT)
+                     && (subsection->flags & SEC_DATA)))
+               current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
+
+             /* Update the exec header.  */
+             if (subsection->flags & SEC_CODE && exec_header.exec_tfile == 0)
+               {
+                 exec_header.exec_tmem = section->vma;
+                 exec_header.exec_tfile = current_offset;
+               }
+             if (subsection->flags & SEC_DATA && exec_header.exec_dfile == 0)
+               {
+                 exec_header.exec_dmem = section->vma;
+                 exec_header.exec_dfile = current_offset;
+               }
+
+             /* Only do this for the first subspace within each space.  */
+             first_subspace = 0;
+           }
+
          som_section_data (subsection)->subspace_index = total_subspaces++;
          /* This is real data to be loaded from the file.  */
          if (subsection->flags & SEC_LOAD)
            {
+             /* Update the size of the code & data.  */
+             if (abfd->flags & EXEC_P
+                 && subsection->flags & SEC_CODE)
+               exec_header.exec_tsize += subsection->_cooked_size;
+             else if (abfd->flags & EXEC_P
+                      && subsection->flags & SEC_DATA)
+               exec_header.exec_dsize += subsection->_cooked_size;
              som_section_data (subsection)->subspace_dict.file_loc_init_value
                = current_offset;
              section->filepos = current_offset;
@@ -2875,6 +2924,10 @@ som_begin_writing (abfd)
          /* Looks like uninitialized data.  */
          else
            {
+             /* Update the size of the bss section.  */
+             if (abfd->flags & EXEC_P)
+               exec_header.exec_bsize += subsection->_cooked_size;
+
              som_section_data (subsection)->subspace_dict.file_loc_init_value
                = 0;
              som_section_data (subsection)->subspace_dict.
@@ -2885,7 +2938,12 @@ som_begin_writing (abfd)
       section = section->next; 
     }
 
-  /* Finally compute the file positions for unloadable subspaces.  */
+  /* Finally compute the file positions for unloadable subspaces.
+     If building an executable, start the unloadable stuff on its
+     own page.  */
+
+  if (abfd->flags & EXEC_P)
+    current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
 
   obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
   section = abfd->sections;
@@ -2897,6 +2955,8 @@ som_begin_writing (abfd)
       while (som_section_data (section)->is_space == 0)
        section = section->next;
 
+      current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
+
       /* Now look for all its subspaces.  */
       for (subsection = abfd->sections;
           subsection != NULL;
@@ -2930,6 +2990,22 @@ som_begin_writing (abfd)
       section = section->next; 
     }
 
+  /* If building an executable, then make sure to seek to and write
+     one byte at the end of the file to make sure any necessary
+     zeros are filled in.  Ugh.  */
+  if (abfd->flags & EXEC_P)
+    current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
+  if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
+    {
+      bfd_set_error (bfd_error_system_call);
+      return false;
+    }
+  if (bfd_write ((PTR) "", 1, 1, abfd) != 1)
+    {
+      bfd_set_error (bfd_error_system_call);
+      return false;
+    }
+
   obj_som_file_hdr (abfd)->unloadable_sp_size
     = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
 
@@ -2939,6 +3015,29 @@ som_begin_writing (abfd)
 
   /* Done.  Store the total size of the SOM.  */
   obj_som_file_hdr (abfd)->som_length = current_offset;
+
+  /* Now write the exec header.  */
+  if (abfd->flags & EXEC_P)
+    {
+      long tmp;
+
+      /* Oh joys.  Ram some of the BSS data into the DATA section
+        to be compatable with how the hp linker makes objects
+        (saves memory space).  */
+      tmp = exec_header.exec_dsize;
+      tmp = SOM_ALIGN (tmp, PA_PAGESIZE);
+      exec_header.exec_bsize -= (tmp - exec_header.exec_dsize);
+      exec_header.exec_dsize = tmp;
+
+      bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location, SEEK_SET);
+
+      if (bfd_write ((PTR) &exec_header, AUX_HDR_SIZE, 1, abfd)
+         != AUX_HDR_SIZE)
+       {
+         bfd_set_error (bfd_error_system_call);
+         return false;
+       }
+    }
   return true;
 }