Back to index

cell-binutils  2.17cvs20070401
archive64.c
Go to the documentation of this file.
00001 /* MIPS-specific support for 64-bit ELF
00002    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2006
00003    Free Software Foundation, Inc.
00004    Ian Lance Taylor, Cygnus Support
00005    Linker support added by Mark Mitchell, CodeSourcery, LLC.
00006    <mark@codesourcery.com>
00007 
00008    This file is part of BFD, the Binary File Descriptor library.
00009 
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014 
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00023 
00024 /* This file supports the 64-bit (MIPS) ELF archives.  */
00025 
00026 #include "bfd.h"
00027 #include "sysdep.h"
00028 #include "libbfd.h"
00029 #include "aout/ar.h"
00030 
00031 /* Irix 6 defines a 64bit archive map format, so that they can
00032    have archives more than 4 GB in size.  */
00033 
00034 bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
00035 bfd_boolean bfd_elf64_archive_write_armap
00036   (bfd *, unsigned int, struct orl *, unsigned int, int);
00037 
00038 /* Read an Irix 6 armap.  */
00039 
00040 bfd_boolean
00041 bfd_elf64_archive_slurp_armap (bfd *abfd)
00042 {
00043   struct artdata *ardata = bfd_ardata (abfd);
00044   char nextname[17];
00045   file_ptr arhdrpos;
00046   bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
00047   struct areltdata *mapdata;
00048   bfd_byte int_buf[8];
00049   char *stringbase;
00050   bfd_byte *raw_armap = NULL;
00051   carsym *carsyms;
00052   bfd_size_type amt;
00053 
00054   ardata->symdefs = NULL;
00055 
00056   /* Get the name of the first element.  */
00057   arhdrpos = bfd_tell (abfd);
00058   i = bfd_bread (nextname, 16, abfd);
00059   if (i == 0)
00060     return TRUE;
00061   if (i != 16)
00062     return FALSE;
00063 
00064   if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
00065     return FALSE;
00066 
00067   /* Archives with traditional armaps are still permitted.  */
00068   if (CONST_STRNEQ (nextname, "/               "))
00069     return bfd_slurp_armap (abfd);
00070 
00071   if (! CONST_STRNEQ (nextname, "/SYM64/         "))
00072     {
00073       bfd_has_map (abfd) = FALSE;
00074       return TRUE;
00075     }
00076 
00077   mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
00078   if (mapdata == NULL)
00079     return FALSE;
00080   parsed_size = mapdata->parsed_size;
00081   bfd_release (abfd, mapdata);
00082 
00083   if (bfd_bread (int_buf, 8, abfd) != 8)
00084     {
00085       if (bfd_get_error () != bfd_error_system_call)
00086        bfd_set_error (bfd_error_malformed_archive);
00087       return FALSE;
00088     }
00089 
00090   nsymz = bfd_getb64 (int_buf);
00091   stringsize = parsed_size - 8 * nsymz - 8;
00092 
00093   carsym_size = nsymz * sizeof (carsym);
00094   ptrsize = 8 * nsymz;
00095 
00096   amt = carsym_size + stringsize + 1;
00097   ardata->symdefs = bfd_zalloc (abfd, amt);
00098   if (ardata->symdefs == NULL)
00099     return FALSE;
00100   carsyms = ardata->symdefs;
00101   stringbase = ((char *) ardata->symdefs) + carsym_size;
00102 
00103   raw_armap = bfd_alloc (abfd, ptrsize);
00104   if (raw_armap == NULL)
00105     goto release_symdefs;
00106 
00107   if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
00108       || bfd_bread (stringbase, stringsize, abfd) != stringsize)
00109     {
00110       if (bfd_get_error () != bfd_error_system_call)
00111        bfd_set_error (bfd_error_malformed_archive);
00112       goto release_raw_armap;
00113     }
00114 
00115   for (i = 0; i < nsymz; i++)
00116     {
00117       carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
00118       carsyms->name = stringbase;
00119       stringbase += strlen (stringbase) + 1;
00120       ++carsyms;
00121     }
00122   *stringbase = '\0';
00123 
00124   ardata->symdef_count = nsymz;
00125   ardata->first_file_filepos = bfd_tell (abfd);
00126   /* Pad to an even boundary if you have to.  */
00127   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
00128 
00129   bfd_has_map (abfd) = TRUE;
00130   bfd_release (abfd, raw_armap);
00131 
00132   return TRUE;
00133 
00134 release_raw_armap:
00135   bfd_release (abfd, raw_armap);
00136 release_symdefs:
00137   bfd_release (abfd, ardata->symdefs);
00138   return FALSE;
00139 }
00140 
00141 /* Write out an Irix 6 armap.  The Irix 6 tools are supposed to be
00142    able to handle ordinary ELF armaps, but at least on Irix 6.2 the
00143    linker crashes.  */
00144 
00145 bfd_boolean
00146 bfd_elf64_archive_write_armap (bfd *arch,
00147                             unsigned int elength,
00148                             struct orl *map,
00149                             unsigned int symbol_count,
00150                             int stridx)
00151 {
00152   unsigned int ranlibsize = (symbol_count * 8) + 8;
00153   unsigned int stringsize = stridx;
00154   unsigned int mapsize = stringsize + ranlibsize;
00155   file_ptr archive_member_file_ptr;
00156   bfd *current = arch->archive_head;
00157   unsigned int count;
00158   struct ar_hdr hdr;
00159   int padding;
00160   bfd_byte buf[8];
00161 
00162   padding = BFD_ALIGN (mapsize, 8) - mapsize;
00163   mapsize += padding;
00164 
00165   /* work out where the first object file will go in the archive */
00166   archive_member_file_ptr = (mapsize
00167                           + elength
00168                           + sizeof (struct ar_hdr)
00169                           + SARMAG);
00170 
00171   memset (&hdr, ' ', sizeof (struct ar_hdr));
00172   memcpy (hdr.ar_name, "/SYM64/", strlen ("/SYM64/"));
00173   _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
00174                     mapsize);
00175   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
00176                     time (NULL));
00177   /* This, at least, is what Intel coff sets the values to.: */
00178   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
00179   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
00180   _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-7lo", 0);
00181   memcpy (hdr.ar_fmag, ARFMAG, 2);
00182 
00183   /* Write the ar header for this item and the number of symbols */
00184 
00185   if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
00186       != sizeof (struct ar_hdr))
00187     return FALSE;
00188 
00189   bfd_putb64 ((bfd_vma) symbol_count, buf);
00190   if (bfd_bwrite (buf, 8, arch) != 8)
00191     return FALSE;
00192 
00193   /* Two passes, first write the file offsets for each symbol -
00194      remembering that each offset is on a two byte boundary.  */
00195 
00196   /* Write out the file offset for the file associated with each
00197      symbol, and remember to keep the offsets padded out.  */
00198 
00199   current = arch->archive_head;
00200   count = 0;
00201   while (current != NULL && count < symbol_count)
00202     {
00203       /* For each symbol which is used defined in this object, write out
00204         the object file's address in the archive */
00205 
00206       while (map[count].u.abfd == current)
00207        {
00208          bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf);
00209          if (bfd_bwrite (buf, 8, arch) != 8)
00210            return FALSE;
00211          count++;
00212        }
00213       /* Add size of this archive entry */
00214       archive_member_file_ptr += (arelt_size (current)
00215                               + sizeof (struct ar_hdr));
00216       /* remember about the even alignment */
00217       archive_member_file_ptr += archive_member_file_ptr % 2;
00218       current = current->next;
00219     }
00220 
00221   /* now write the strings themselves */
00222   for (count = 0; count < symbol_count; count++)
00223     {
00224       size_t len = strlen (*map[count].name) + 1;
00225 
00226       if (bfd_bwrite (*map[count].name, len, arch) != len)
00227        return FALSE;
00228     }
00229 
00230   /* The spec says that this should be padded to an 8 byte boundary.
00231      However, the Irix 6.2 tools do not appear to do this.  */
00232   while (padding != 0)
00233     {
00234       if (bfd_bwrite ("", 1, arch) != 1)
00235        return FALSE;
00236       --padding;
00237     }
00238 
00239   return TRUE;
00240 }