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