]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/archive64.c
[PATCH] fix windmc typedef bug
[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;
6f8f95b4 50 ufile_ptr filesize;
36b45482
TS
51
52 ardata->symdefs = NULL;
53
54 /* Get the name of the first element. */
c58b9523 55 i = bfd_bread (nextname, 16, abfd);
36b45482 56 if (i == 0)
b34976b6 57 return TRUE;
36b45482 58 if (i != 16)
b34976b6 59 return FALSE;
36b45482
TS
60
61 if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
b34976b6 62 return FALSE;
36b45482
TS
63
64 /* Archives with traditional armaps are still permitted. */
0112cd26 65 if (CONST_STRNEQ (nextname, "/ "))
36b45482
TS
66 return bfd_slurp_armap (abfd);
67
0112cd26 68 if (! CONST_STRNEQ (nextname, "/SYM64/ "))
36b45482 69 {
ed48ec2e 70 abfd->has_armap = FALSE;
b34976b6 71 return TRUE;
36b45482
TS
72 }
73
74 mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
75 if (mapdata == NULL)
b34976b6 76 return FALSE;
36b45482 77 parsed_size = mapdata->parsed_size;
06e7acd7 78 free (mapdata);
36b45482 79
6f8f95b4
AM
80 filesize = bfd_get_file_size (abfd);
81 if (filesize != 0 && parsed_size > filesize)
82 {
83 bfd_set_error (bfd_error_malformed_archive);
84 return FALSE;
85 }
86
c58b9523 87 if (bfd_bread (int_buf, 8, abfd) != 8)
36b45482
TS
88 {
89 if (bfd_get_error () != bfd_error_system_call)
90 bfd_set_error (bfd_error_malformed_archive);
b34976b6 91 return FALSE;
36b45482
TS
92 }
93
94 nsymz = bfd_getb64 (int_buf);
95 stringsize = parsed_size - 8 * nsymz - 8;
96
97 carsym_size = nsymz * sizeof (carsym);
98 ptrsize = 8 * nsymz;
99
100 amt = carsym_size + stringsize + 1;
97b031c5
AM
101 if (/* Catch overflow in stringsize (and ptrsize) expression. */
102 nsymz >= (bfd_size_type) -1 / 8
103 || stringsize > parsed_size
104 /* Catch overflow in carsym_size expression. */
105 || nsymz > (bfd_size_type) -1 / sizeof (carsym)
106 /* Catch overflow in amt expression. */
107 || amt <= carsym_size
108 || amt <= stringsize)
f64e188b
NC
109 {
110 bfd_set_error (bfd_error_malformed_archive);
111 return FALSE;
112 }
6f8f95b4 113 ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt);
36b45482 114 if (ardata->symdefs == NULL)
b34976b6 115 return FALSE;
36b45482
TS
116 carsyms = ardata->symdefs;
117 stringbase = ((char *) ardata->symdefs) + carsym_size;
118
2bb3687b
AM
119 raw_armap = (bfd_byte *) _bfd_alloc_and_read (abfd, ptrsize, ptrsize);
120 if (raw_armap == NULL
36b45482
TS
121 || bfd_bread (stringbase, stringsize, abfd) != stringsize)
122 {
123 if (bfd_get_error () != bfd_error_system_call)
124 bfd_set_error (bfd_error_malformed_archive);
806470a2 125 goto release_symdefs;
36b45482
TS
126 }
127
8abac803
AM
128 stringend = stringbase + stringsize;
129 *stringend = 0;
36b45482
TS
130 for (i = 0; i < nsymz; i++)
131 {
132 carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
133 carsyms->name = stringbase;
8abac803
AM
134 stringbase += strlen (stringbase);
135 if (stringbase != stringend)
136 ++stringbase;
36b45482
TS
137 ++carsyms;
138 }
36b45482
TS
139
140 ardata->symdef_count = nsymz;
141 ardata->first_file_filepos = bfd_tell (abfd);
142 /* Pad to an even boundary if you have to. */
143 ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
144
ed48ec2e 145 abfd->has_armap = TRUE;
36b45482
TS
146 bfd_release (abfd, raw_armap);
147
b34976b6 148 return TRUE;
36b45482 149
dc1e8a47 150 release_symdefs:
36b45482 151 bfd_release (abfd, ardata->symdefs);
b34976b6 152 return FALSE;
36b45482
TS
153}
154
155/* Write out an Irix 6 armap. The Irix 6 tools are supposed to be
156 able to handle ordinary ELF armaps, but at least on Irix 6.2 the
157 linker crashes. */
158
b34976b6 159bfd_boolean
e6cc316a
L
160_bfd_archive_64_bit_write_armap (bfd *arch,
161 unsigned int elength,
162 struct orl *map,
163 unsigned int symbol_count,
164 int stridx)
36b45482
TS
165{
166 unsigned int ranlibsize = (symbol_count * 8) + 8;
167 unsigned int stringsize = stridx;
168 unsigned int mapsize = stringsize + ranlibsize;
169 file_ptr archive_member_file_ptr;
170 bfd *current = arch->archive_head;
171 unsigned int count;
172 struct ar_hdr hdr;
36b45482
TS
173 int padding;
174 bfd_byte buf[8];
175
176 padding = BFD_ALIGN (mapsize, 8) - mapsize;
177 mapsize += padding;
178
179 /* work out where the first object file will go in the archive */
180 archive_member_file_ptr = (mapsize
181 + elength
182 + sizeof (struct ar_hdr)
183 + SARMAG);
184
390c0e42
JJ
185 memset (&hdr, ' ', sizeof (struct ar_hdr));
186 memcpy (hdr.ar_name, "/SYM64/", strlen ("/SYM64/"));
f1bb16f8
NC
187 if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize))
188 return FALSE;
390c0e42 189 _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
07d6d2b8 190 time (NULL));
36b45482 191 /* This, at least, is what Intel coff sets the values to.: */
390c0e42
JJ
192 _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
193 _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
194 _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-7lo", 0);
195 memcpy (hdr.ar_fmag, ARFMAG, 2);
36b45482
TS
196
197 /* Write the ar header for this item and the number of symbols */
198
c58b9523 199 if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
36b45482 200 != sizeof (struct ar_hdr))
b34976b6 201 return FALSE;
36b45482
TS
202
203 bfd_putb64 ((bfd_vma) symbol_count, buf);
c58b9523 204 if (bfd_bwrite (buf, 8, arch) != 8)
b34976b6 205 return FALSE;
36b45482
TS
206
207 /* Two passes, first write the file offsets for each symbol -
208 remembering that each offset is on a two byte boundary. */
209
210 /* Write out the file offset for the file associated with each
211 symbol, and remember to keep the offsets padded out. */
36b45482 212 count = 0;
61e8a5ea
NS
213 for (current = arch->archive_head;
214 current != NULL && count < symbol_count;
215 current = current->archive_next)
36b45482
TS
216 {
217 /* For each symbol which is used defined in this object, write out
17e3916e 218 the object file's address in the archive. */
36b45482 219
61e8a5ea
NS
220 for (;
221 count < symbol_count && map[count].u.abfd == current;
222 count++)
36b45482
TS
223 {
224 bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf);
c58b9523 225 if (bfd_bwrite (buf, 8, arch) != 8)
b34976b6 226 return FALSE;
36b45482 227 }
17e3916e 228
36b45482 229 /* Add size of this archive entry */
17e3916e
NC
230 archive_member_file_ptr += sizeof (struct ar_hdr);
231 if (! bfd_is_thin_archive (arch))
232 archive_member_file_ptr += arelt_size (current);
36b45482
TS
233 /* remember about the even alignment */
234 archive_member_file_ptr += archive_member_file_ptr % 2;
36b45482
TS
235 }
236
237 /* now write the strings themselves */
238 for (count = 0; count < symbol_count; count++)
239 {
240 size_t len = strlen (*map[count].name) + 1;
241
c58b9523 242 if (bfd_bwrite (*map[count].name, len, arch) != len)
b34976b6 243 return FALSE;
36b45482
TS
244 }
245
246 /* The spec says that this should be padded to an 8 byte boundary.
247 However, the Irix 6.2 tools do not appear to do this. */
248 while (padding != 0)
249 {
c58b9523 250 if (bfd_bwrite ("", 1, arch) != 1)
b34976b6 251 return FALSE;
36b45482
TS
252 --padding;
253 }
254
b34976b6 255 return TRUE;
36b45482 256}