]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/archive64.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / bfd / archive64.c
CommitLineData
e6cc316a 1/* Support for 64-bit archives.
b3adc24a 2 Copyright (C) 1996-2020 Free Software Foundation, Inc.
36b45482
TS
3 Ian Lance Taylor, Cygnus Support
4 Linker support added by Mark Mitchell, CodeSourcery, LLC.
5 <mark@codesourcery.com>
6
0112cd26 7 This file is part of BFD, the Binary File Descriptor library.
36b45482 8
0112cd26
NC
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
cd123cb7 11 the Free Software Foundation; either version 3 of the License, or
0112cd26 12 (at your option) any later version.
36b45482 13
0112cd26
NC
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.
36b45482 18
0112cd26
NC
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
cd123cb7
NC
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
36b45482 23
e6cc316a
L
24/* This file supports the 64-bit archives. We use the same format as
25 the 64-bit (MIPS) ELF archives. */
36b45482 26
36b45482 27#include "sysdep.h"
3db64b00 28#include "bfd.h"
36b45482
TS
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
36b45482
TS
35/* Read an Irix 6 armap. */
36
b34976b6 37bfd_boolean
e6cc316a 38_bfd_archive_64_bit_slurp_armap (bfd *abfd)
36b45482
TS
39{
40 struct artdata *ardata = bfd_ardata (abfd);
41 char nextname[17];
36b45482
TS
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;
f64e188b 46 char *stringend;
36b45482
TS
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. */
c58b9523 54 i = bfd_bread (nextname, 16, abfd);
36b45482 55 if (i == 0)
b34976b6 56 return TRUE;
36b45482 57 if (i != 16)
b34976b6 58 return FALSE;
36b45482
TS
59
60 if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
b34976b6 61 return FALSE;
36b45482
TS
62
63 /* Archives with traditional armaps are still permitted. */
0112cd26 64 if (CONST_STRNEQ (nextname, "/ "))
36b45482
TS
65 return bfd_slurp_armap (abfd);
66
0112cd26 67 if (! CONST_STRNEQ (nextname, "/SYM64/ "))
36b45482 68 {
ed48ec2e 69 abfd->has_armap = FALSE;
b34976b6 70 return TRUE;
36b45482
TS
71 }
72
73 mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
74 if (mapdata == NULL)
b34976b6 75 return FALSE;
36b45482 76 parsed_size = mapdata->parsed_size;
06e7acd7 77 free (mapdata);
36b45482 78
c58b9523 79 if (bfd_bread (int_buf, 8, abfd) != 8)
36b45482
TS
80 {
81 if (bfd_get_error () != bfd_error_system_call)
82 bfd_set_error (bfd_error_malformed_archive);
b34976b6 83 return FALSE;
36b45482
TS
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;
97b031c5
AM
93 if (/* Catch overflow in stringsize (and ptrsize) expression. */
94 nsymz >= (bfd_size_type) -1 / 8
95 || stringsize > parsed_size
96 /* Catch overflow in carsym_size expression. */
97 || nsymz > (bfd_size_type) -1 / sizeof (carsym)
98 /* Catch overflow in amt expression. */
99 || amt <= carsym_size
100 || amt <= stringsize)
f64e188b
NC
101 {
102 bfd_set_error (bfd_error_malformed_archive);
103 return FALSE;
104 }
a50b1753 105 ardata->symdefs = (struct carsym *) bfd_zalloc (abfd, amt);
36b45482 106 if (ardata->symdefs == NULL)
b34976b6 107 return FALSE;
36b45482
TS
108 carsyms = ardata->symdefs;
109 stringbase = ((char *) ardata->symdefs) + carsym_size;
110
a50b1753 111 raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
36b45482
TS
112 if (raw_armap == NULL)
113 goto release_symdefs;
114
115 if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
116 || bfd_bread (stringbase, stringsize, abfd) != stringsize)
117 {
118 if (bfd_get_error () != bfd_error_system_call)
119 bfd_set_error (bfd_error_malformed_archive);
120 goto release_raw_armap;
121 }
122
8abac803
AM
123 stringend = stringbase + stringsize;
124 *stringend = 0;
36b45482
TS
125 for (i = 0; i < nsymz; i++)
126 {
127 carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
128 carsyms->name = stringbase;
8abac803
AM
129 stringbase += strlen (stringbase);
130 if (stringbase != stringend)
131 ++stringbase;
36b45482
TS
132 ++carsyms;
133 }
36b45482
TS
134
135 ardata->symdef_count = nsymz;
136 ardata->first_file_filepos = bfd_tell (abfd);
137 /* Pad to an even boundary if you have to. */
138 ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
139
ed48ec2e 140 abfd->has_armap = TRUE;
36b45482
TS
141 bfd_release (abfd, raw_armap);
142
b34976b6 143 return TRUE;
36b45482
TS
144
145release_raw_armap:
146 bfd_release (abfd, raw_armap);
147release_symdefs:
148 bfd_release (abfd, ardata->symdefs);
b34976b6 149 return FALSE;
36b45482
TS
150}
151
152/* Write out an Irix 6 armap. The Irix 6 tools are supposed to be
153 able to handle ordinary ELF armaps, but at least on Irix 6.2 the
154 linker crashes. */
155
b34976b6 156bfd_boolean
e6cc316a
L
157_bfd_archive_64_bit_write_armap (bfd *arch,
158 unsigned int elength,
159 struct orl *map,
160 unsigned int symbol_count,
161 int stridx)
36b45482
TS
162{
163 unsigned int ranlibsize = (symbol_count * 8) + 8;
164 unsigned int stringsize = stridx;
165 unsigned int mapsize = stringsize + ranlibsize;
166 file_ptr archive_member_file_ptr;
167 bfd *current = arch->archive_head;
168 unsigned int count;
169 struct ar_hdr hdr;
36b45482
TS
170 int padding;
171 bfd_byte buf[8];
172
173 padding = BFD_ALIGN (mapsize, 8) - mapsize;
174 mapsize += padding;
175
176 /* work out where the first object file will go in the archive */
177 archive_member_file_ptr = (mapsize
178 + elength
179 + sizeof (struct ar_hdr)
180 + SARMAG);
181
390c0e42
JJ
182 memset (&hdr, ' ', sizeof (struct ar_hdr));
183 memcpy (hdr.ar_name, "/SYM64/", strlen ("/SYM64/"));
f1bb16f8
NC
184 if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize))
185 return FALSE;
390c0e42 186 _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
07d6d2b8 187 time (NULL));
36b45482 188 /* This, at least, is what Intel coff sets the values to.: */
390c0e42
JJ
189 _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
190 _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
191 _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-7lo", 0);
192 memcpy (hdr.ar_fmag, ARFMAG, 2);
36b45482
TS
193
194 /* Write the ar header for this item and the number of symbols */
195
c58b9523 196 if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
36b45482 197 != sizeof (struct ar_hdr))
b34976b6 198 return FALSE;
36b45482
TS
199
200 bfd_putb64 ((bfd_vma) symbol_count, buf);
c58b9523 201 if (bfd_bwrite (buf, 8, arch) != 8)
b34976b6 202 return FALSE;
36b45482
TS
203
204 /* Two passes, first write the file offsets for each symbol -
205 remembering that each offset is on a two byte boundary. */
206
207 /* Write out the file offset for the file associated with each
208 symbol, and remember to keep the offsets padded out. */
36b45482 209 count = 0;
61e8a5ea
NS
210 for (current = arch->archive_head;
211 current != NULL && count < symbol_count;
212 current = current->archive_next)
36b45482
TS
213 {
214 /* For each symbol which is used defined in this object, write out
17e3916e 215 the object file's address in the archive. */
36b45482 216
61e8a5ea
NS
217 for (;
218 count < symbol_count && map[count].u.abfd == current;
219 count++)
36b45482
TS
220 {
221 bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf);
c58b9523 222 if (bfd_bwrite (buf, 8, arch) != 8)
b34976b6 223 return FALSE;
36b45482 224 }
17e3916e 225
36b45482 226 /* Add size of this archive entry */
17e3916e
NC
227 archive_member_file_ptr += sizeof (struct ar_hdr);
228 if (! bfd_is_thin_archive (arch))
229 archive_member_file_ptr += arelt_size (current);
36b45482
TS
230 /* remember about the even alignment */
231 archive_member_file_ptr += archive_member_file_ptr % 2;
36b45482
TS
232 }
233
234 /* now write the strings themselves */
235 for (count = 0; count < symbol_count; count++)
236 {
237 size_t len = strlen (*map[count].name) + 1;
238
c58b9523 239 if (bfd_bwrite (*map[count].name, len, arch) != len)
b34976b6 240 return FALSE;
36b45482
TS
241 }
242
243 /* The spec says that this should be padded to an 8 byte boundary.
244 However, the Irix 6.2 tools do not appear to do this. */
245 while (padding != 0)
246 {
c58b9523 247 if (bfd_bwrite ("", 1, arch) != 1)
b34976b6 248 return FALSE;
36b45482
TS
249 --padding;
250 }
251
b34976b6 252 return TRUE;
36b45482 253}