* testsuite/Makefile.am (final_layout_script.lds): Add .sbss.
[deliverable/binutils-gdb.git] / bfd / archive64.c
CommitLineData
36b45482 1/* MIPS-specific support for 64-bit ELF
c9736ba0 2 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007,
f1bb16f8 3 2010, 2012 Free Software Foundation, Inc.
36b45482
TS
4 Ian Lance Taylor, Cygnus Support
5 Linker support added by Mark Mitchell, CodeSourcery, LLC.
6 <mark@codesourcery.com>
7
0112cd26 8 This file is part of BFD, the Binary File Descriptor library.
36b45482 9
0112cd26
NC
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
cd123cb7 12 the Free Software Foundation; either version 3 of the License, or
0112cd26 13 (at your option) any later version.
36b45482 14
0112cd26
NC
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
36b45482 19
0112cd26
NC
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
cd123cb7
NC
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
36b45482
TS
24
25/* This file supports the 64-bit (MIPS) ELF archives. */
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
c58b9523 35bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
b34976b6 36bfd_boolean bfd_elf64_archive_write_armap
c58b9523 37 (bfd *, unsigned int, struct orl *, unsigned int, int);
36b45482
TS
38
39/* Read an Irix 6 armap. */
40
b34976b6 41bfd_boolean
c58b9523 42bfd_elf64_archive_slurp_armap (bfd *abfd)
36b45482
TS
43{
44 struct artdata *ardata = bfd_ardata (abfd);
45 char nextname[17];
36b45482
TS
46 bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
47 struct areltdata *mapdata;
48 bfd_byte int_buf[8];
49 char *stringbase;
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;
a50b1753 96 ardata->symdefs = (struct carsym *) bfd_zalloc (abfd, amt);
36b45482 97 if (ardata->symdefs == NULL)
b34976b6 98 return FALSE;
36b45482
TS
99 carsyms = ardata->symdefs;
100 stringbase = ((char *) ardata->symdefs) + carsym_size;
101
a50b1753 102 raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize);
36b45482
TS
103 if (raw_armap == NULL)
104 goto release_symdefs;
105
106 if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
107 || bfd_bread (stringbase, stringsize, abfd) != stringsize)
108 {
109 if (bfd_get_error () != bfd_error_system_call)
110 bfd_set_error (bfd_error_malformed_archive);
111 goto release_raw_armap;
112 }
113
114 for (i = 0; i < nsymz; i++)
115 {
116 carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
117 carsyms->name = stringbase;
118 stringbase += strlen (stringbase) + 1;
119 ++carsyms;
120 }
121 *stringbase = '\0';
122
123 ardata->symdef_count = nsymz;
124 ardata->first_file_filepos = bfd_tell (abfd);
125 /* Pad to an even boundary if you have to. */
126 ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
127
b34976b6 128 bfd_has_map (abfd) = TRUE;
36b45482
TS
129 bfd_release (abfd, raw_armap);
130
b34976b6 131 return TRUE;
36b45482
TS
132
133release_raw_armap:
134 bfd_release (abfd, raw_armap);
135release_symdefs:
136 bfd_release (abfd, ardata->symdefs);
b34976b6 137 return FALSE;
36b45482
TS
138}
139
140/* Write out an Irix 6 armap. The Irix 6 tools are supposed to be
141 able to handle ordinary ELF armaps, but at least on Irix 6.2 the
142 linker crashes. */
143
b34976b6 144bfd_boolean
c58b9523
AM
145bfd_elf64_archive_write_armap (bfd *arch,
146 unsigned int elength,
147 struct orl *map,
148 unsigned int symbol_count,
149 int stridx)
36b45482
TS
150{
151 unsigned int ranlibsize = (symbol_count * 8) + 8;
152 unsigned int stringsize = stridx;
153 unsigned int mapsize = stringsize + ranlibsize;
154 file_ptr archive_member_file_ptr;
155 bfd *current = arch->archive_head;
156 unsigned int count;
157 struct ar_hdr hdr;
36b45482
TS
158 int padding;
159 bfd_byte buf[8];
160
161 padding = BFD_ALIGN (mapsize, 8) - mapsize;
162 mapsize += padding;
163
164 /* work out where the first object file will go in the archive */
165 archive_member_file_ptr = (mapsize
166 + elength
167 + sizeof (struct ar_hdr)
168 + SARMAG);
169
390c0e42
JJ
170 memset (&hdr, ' ', sizeof (struct ar_hdr));
171 memcpy (hdr.ar_name, "/SYM64/", strlen ("/SYM64/"));
f1bb16f8
NC
172 if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize))
173 return FALSE;
390c0e42
JJ
174 _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
175 time (NULL));
36b45482 176 /* This, at least, is what Intel coff sets the values to.: */
390c0e42
JJ
177 _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
178 _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
179 _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-7lo", 0);
180 memcpy (hdr.ar_fmag, ARFMAG, 2);
36b45482
TS
181
182 /* Write the ar header for this item and the number of symbols */
183
c58b9523 184 if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
36b45482 185 != sizeof (struct ar_hdr))
b34976b6 186 return FALSE;
36b45482
TS
187
188 bfd_putb64 ((bfd_vma) symbol_count, buf);
c58b9523 189 if (bfd_bwrite (buf, 8, arch) != 8)
b34976b6 190 return FALSE;
36b45482
TS
191
192 /* Two passes, first write the file offsets for each symbol -
193 remembering that each offset is on a two byte boundary. */
194
195 /* Write out the file offset for the file associated with each
196 symbol, and remember to keep the offsets padded out. */
36b45482 197 count = 0;
61e8a5ea
NS
198 for (current = arch->archive_head;
199 current != NULL && count < symbol_count;
200 current = current->archive_next)
36b45482
TS
201 {
202 /* For each symbol which is used defined in this object, write out
203 the object file's address in the archive */
204
61e8a5ea
NS
205 for (;
206 count < symbol_count && map[count].u.abfd == current;
207 count++)
36b45482
TS
208 {
209 bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf);
c58b9523 210 if (bfd_bwrite (buf, 8, arch) != 8)
b34976b6 211 return FALSE;
36b45482
TS
212 }
213 /* Add size of this archive entry */
214 archive_member_file_ptr += (arelt_size (current)
215 + sizeof (struct ar_hdr));
216 /* remember about the even alignment */
217 archive_member_file_ptr += archive_member_file_ptr % 2;
36b45482
TS
218 }
219
220 /* now write the strings themselves */
221 for (count = 0; count < symbol_count; count++)
222 {
223 size_t len = strlen (*map[count].name) + 1;
224
c58b9523 225 if (bfd_bwrite (*map[count].name, len, arch) != len)
b34976b6 226 return FALSE;
36b45482
TS
227 }
228
229 /* The spec says that this should be padded to an 8 byte boundary.
230 However, the Irix 6.2 tools do not appear to do this. */
231 while (padding != 0)
232 {
c58b9523 233 if (bfd_bwrite ("", 1, arch) != 1)
b34976b6 234 return FALSE;
36b45482
TS
235 --padding;
236 }
237
b34976b6 238 return TRUE;
36b45482 239}
This page took 0.714576 seconds and 4 git commands to generate.