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