Home | History | Annotate | Download | only in bfd
      1 /* Support for 64-bit archives.
      2    Copyright (C) 1996-2016 Free Software Foundation, Inc.
      3    Ian Lance Taylor, Cygnus Support
      4    Linker support added by Mark Mitchell, CodeSourcery, LLC.
      5    <mark (at) codesourcery.com>
      6 
      7    This file is part of BFD, the Binary File Descriptor library.
      8 
      9    This program is free software; you can redistribute it and/or modify
     10    it under the terms of the GNU General Public License as published by
     11    the Free Software Foundation; either version 3 of the License, or
     12    (at your option) any later version.
     13 
     14    This program is distributed in the hope that it will be useful,
     15    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17    GNU General Public License for more details.
     18 
     19    You should have received a copy of the GNU General Public License
     20    along with this program; if not, write to the Free Software
     21    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     22    MA 02110-1301, USA.  */
     23 
     24 /* This file supports the 64-bit archives.  We use the same format as
     25    the 64-bit (MIPS) ELF archives.  */
     26 
     27 #include "sysdep.h"
     28 #include "bfd.h"
     29 #include "libbfd.h"
     30 #include "aout/ar.h"
     31 
     32 /* Irix 6 defines a 64bit archive map format, so that they can
     33    have archives more than 4 GB in size.  */
     34 
     35 /* Read an Irix 6 armap.  */
     36 
     37 bfd_boolean
     38 _bfd_archive_64_bit_slurp_armap (bfd *abfd)
     39 {
     40   struct artdata *ardata = bfd_ardata (abfd);
     41   char nextname[17];
     42   bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
     43   struct areltdata *mapdata;
     44   bfd_byte int_buf[8];
     45   char *stringbase;
     46   char *stringend;
     47   bfd_byte *raw_armap = NULL;
     48   carsym *carsyms;
     49   bfd_size_type amt;
     50 
     51   ardata->symdefs = NULL;
     52 
     53   /* Get the name of the first element.  */
     54   i = bfd_bread (nextname, 16, abfd);
     55   if (i == 0)
     56     return TRUE;
     57   if (i != 16)
     58     return FALSE;
     59 
     60   if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
     61     return FALSE;
     62 
     63   /* Archives with traditional armaps are still permitted.  */
     64   if (CONST_STRNEQ (nextname, "/               "))
     65     return bfd_slurp_armap (abfd);
     66 
     67   if (! CONST_STRNEQ (nextname, "/SYM64/         "))
     68     {
     69       bfd_has_map (abfd) = FALSE;
     70       return TRUE;
     71     }
     72 
     73   mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
     74   if (mapdata == NULL)
     75     return FALSE;
     76   parsed_size = mapdata->parsed_size;
     77   free (mapdata);
     78 
     79   if (bfd_bread (int_buf, 8, abfd) != 8)
     80     {
     81       if (bfd_get_error () != bfd_error_system_call)
     82 	bfd_set_error (bfd_error_malformed_archive);
     83       return FALSE;
     84     }
     85 
     86   nsymz = bfd_getb64 (int_buf);
     87   stringsize = parsed_size - 8 * nsymz - 8;
     88 
     89   carsym_size = nsymz * sizeof (carsym);
     90   ptrsize = 8 * nsymz;
     91 
     92   amt = carsym_size + stringsize + 1;
     93   if (carsym_size < nsymz || ptrsize < nsymz || amt < nsymz)
     94     {
     95       bfd_set_error (bfd_error_malformed_archive);
     96       return FALSE;
     97     }
     98   ardata->symdefs = (struct carsym *) bfd_zalloc (abfd, amt);
     99   if (ardata->symdefs == NULL)
    100     return FALSE;
    101   carsyms = ardata->symdefs;
    102   stringbase = ((char *) ardata->symdefs) + carsym_size;
    103   stringbase[stringsize] = 0;
    104   stringend = stringbase + stringsize;
    105 
    106   raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
    107   if (raw_armap == NULL)
    108     goto release_symdefs;
    109 
    110   if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
    111       || bfd_bread (stringbase, stringsize, abfd) != stringsize)
    112     {
    113       if (bfd_get_error () != bfd_error_system_call)
    114 	bfd_set_error (bfd_error_malformed_archive);
    115       goto release_raw_armap;
    116     }
    117 
    118   for (i = 0; i < nsymz; i++)
    119     {
    120       carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
    121       carsyms->name = stringbase;
    122       if (stringbase < stringend)
    123 	stringbase += strlen (stringbase) + 1;
    124       ++carsyms;
    125     }
    126   *stringbase = '\0';
    127 
    128   ardata->symdef_count = nsymz;
    129   ardata->first_file_filepos = bfd_tell (abfd);
    130   /* Pad to an even boundary if you have to.  */
    131   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
    132 
    133   bfd_has_map (abfd) = TRUE;
    134   bfd_release (abfd, raw_armap);
    135 
    136   return TRUE;
    137 
    138 release_raw_armap:
    139   bfd_release (abfd, raw_armap);
    140 release_symdefs:
    141   bfd_release (abfd, ardata->symdefs);
    142   return FALSE;
    143 }
    144 
    145 /* Write out an Irix 6 armap.  The Irix 6 tools are supposed to be
    146    able to handle ordinary ELF armaps, but at least on Irix 6.2 the
    147    linker crashes.  */
    148 
    149 bfd_boolean
    150 _bfd_archive_64_bit_write_armap (bfd *arch,
    151 				 unsigned int elength,
    152 				 struct orl *map,
    153 				 unsigned int symbol_count,
    154 				 int stridx)
    155 {
    156   unsigned int ranlibsize = (symbol_count * 8) + 8;
    157   unsigned int stringsize = stridx;
    158   unsigned int mapsize = stringsize + ranlibsize;
    159   file_ptr archive_member_file_ptr;
    160   bfd *current = arch->archive_head;
    161   unsigned int count;
    162   struct ar_hdr hdr;
    163   int padding;
    164   bfd_byte buf[8];
    165 
    166   padding = BFD_ALIGN (mapsize, 8) - mapsize;
    167   mapsize += padding;
    168 
    169   /* work out where the first object file will go in the archive */
    170   archive_member_file_ptr = (mapsize
    171 			     + elength
    172 			     + sizeof (struct ar_hdr)
    173 			     + SARMAG);
    174 
    175   memset (&hdr, ' ', sizeof (struct ar_hdr));
    176   memcpy (hdr.ar_name, "/SYM64/", strlen ("/SYM64/"));
    177   if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize))
    178     return FALSE;
    179   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
    180                     time (NULL));
    181   /* This, at least, is what Intel coff sets the values to.: */
    182   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
    183   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
    184   _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-7lo", 0);
    185   memcpy (hdr.ar_fmag, ARFMAG, 2);
    186 
    187   /* Write the ar header for this item and the number of symbols */
    188 
    189   if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
    190       != sizeof (struct ar_hdr))
    191     return FALSE;
    192 
    193   bfd_putb64 ((bfd_vma) symbol_count, buf);
    194   if (bfd_bwrite (buf, 8, arch) != 8)
    195     return FALSE;
    196 
    197   /* Two passes, first write the file offsets for each symbol -
    198      remembering that each offset is on a two byte boundary.  */
    199 
    200   /* Write out the file offset for the file associated with each
    201      symbol, and remember to keep the offsets padded out.  */
    202   count = 0;
    203   for (current = arch->archive_head;
    204        current != NULL && count < symbol_count;
    205        current = current->archive_next)
    206     {
    207       /* For each symbol which is used defined in this object, write out
    208 	 the object file's address in the archive.  */
    209 
    210       for (;
    211 	   count < symbol_count && map[count].u.abfd == current;
    212 	   count++)
    213 	{
    214 	  bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf);
    215 	  if (bfd_bwrite (buf, 8, arch) != 8)
    216 	    return FALSE;
    217 	}
    218 
    219       /* Add size of this archive entry */
    220       archive_member_file_ptr += sizeof (struct ar_hdr);
    221       if (! bfd_is_thin_archive (arch))
    222 	archive_member_file_ptr += arelt_size (current);
    223       /* remember about the even alignment */
    224       archive_member_file_ptr += archive_member_file_ptr % 2;
    225     }
    226 
    227   /* now write the strings themselves */
    228   for (count = 0; count < symbol_count; count++)
    229     {
    230       size_t len = strlen (*map[count].name) + 1;
    231 
    232       if (bfd_bwrite (*map[count].name, len, arch) != len)
    233 	return FALSE;
    234     }
    235 
    236   /* The spec says that this should be padded to an 8 byte boundary.
    237      However, the Irix 6.2 tools do not appear to do this.  */
    238   while (padding != 0)
    239     {
    240       if (bfd_bwrite ("", 1, arch) != 1)
    241 	return FALSE;
    242       --padding;
    243     }
    244 
    245   return TRUE;
    246 }
    247