bfd/
[deliverable/binutils-gdb.git] / bfd / archive64.c
CommitLineData
36b45482 1/* MIPS-specific support for 64-bit ELF
3db64b00 2 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2007
36b45482
TS
3 Free Software Foundation, Inc.
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
12 the Free Software Foundation; either version 2 of the License, or
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
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 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];
45 file_ptr arhdrpos;
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. */
57 arhdrpos = bfd_tell (abfd);
c58b9523 58 i = bfd_bread (nextname, 16, abfd);
36b45482 59 if (i == 0)
b34976b6 60 return TRUE;
36b45482 61 if (i != 16)
b34976b6 62 return FALSE;
36b45482
TS
63
64 if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
b34976b6 65 return FALSE;
36b45482
TS
66
67 /* Archives with traditional armaps are still permitted. */
0112cd26 68 if (CONST_STRNEQ (nextname, "/ "))
36b45482
TS
69 return bfd_slurp_armap (abfd);
70
0112cd26 71 if (! CONST_STRNEQ (nextname, "/SYM64/ "))
36b45482 72 {
b34976b6
AM
73 bfd_has_map (abfd) = FALSE;
74 return TRUE;
36b45482
TS
75 }
76
77 mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
78 if (mapdata == NULL)
b34976b6 79 return FALSE;
36b45482 80 parsed_size = mapdata->parsed_size;
c58b9523 81 bfd_release (abfd, mapdata);
36b45482 82
c58b9523 83 if (bfd_bread (int_buf, 8, abfd) != 8)
36b45482
TS
84 {
85 if (bfd_get_error () != bfd_error_system_call)
86 bfd_set_error (bfd_error_malformed_archive);
b34976b6 87 return FALSE;
36b45482
TS
88 }
89
90 nsymz = bfd_getb64 (int_buf);
91 stringsize = parsed_size - 8 * nsymz - 8;
92
93 carsym_size = nsymz * sizeof (carsym);
94 ptrsize = 8 * nsymz;
95
96 amt = carsym_size + stringsize + 1;
c58b9523 97 ardata->symdefs = bfd_zalloc (abfd, amt);
36b45482 98 if (ardata->symdefs == NULL)
b34976b6 99 return FALSE;
36b45482
TS
100 carsyms = ardata->symdefs;
101 stringbase = ((char *) ardata->symdefs) + carsym_size;
102
c58b9523 103 raw_armap = bfd_alloc (abfd, ptrsize);
36b45482
TS
104 if (raw_armap == NULL)
105 goto release_symdefs;
106
107 if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
108 || bfd_bread (stringbase, stringsize, abfd) != stringsize)
109 {
110 if (bfd_get_error () != bfd_error_system_call)
111 bfd_set_error (bfd_error_malformed_archive);
112 goto release_raw_armap;
113 }
114
115 for (i = 0; i < nsymz; i++)
116 {
117 carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
118 carsyms->name = stringbase;
119 stringbase += strlen (stringbase) + 1;
120 ++carsyms;
121 }
122 *stringbase = '\0';
123
124 ardata->symdef_count = nsymz;
125 ardata->first_file_filepos = bfd_tell (abfd);
126 /* Pad to an even boundary if you have to. */
127 ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
128
b34976b6 129 bfd_has_map (abfd) = TRUE;
36b45482
TS
130 bfd_release (abfd, raw_armap);
131
b34976b6 132 return TRUE;
36b45482
TS
133
134release_raw_armap:
135 bfd_release (abfd, raw_armap);
136release_symdefs:
137 bfd_release (abfd, ardata->symdefs);
b34976b6 138 return FALSE;
36b45482
TS
139}
140
141/* Write out an Irix 6 armap. The Irix 6 tools are supposed to be
142 able to handle ordinary ELF armaps, but at least on Irix 6.2 the
143 linker crashes. */
144
b34976b6 145bfd_boolean
c58b9523
AM
146bfd_elf64_archive_write_armap (bfd *arch,
147 unsigned int elength,
148 struct orl *map,
149 unsigned int symbol_count,
150 int stridx)
36b45482
TS
151{
152 unsigned int ranlibsize = (symbol_count * 8) + 8;
153 unsigned int stringsize = stridx;
154 unsigned int mapsize = stringsize + ranlibsize;
155 file_ptr archive_member_file_ptr;
156 bfd *current = arch->archive_head;
157 unsigned int count;
158 struct ar_hdr hdr;
36b45482
TS
159 int padding;
160 bfd_byte buf[8];
161
162 padding = BFD_ALIGN (mapsize, 8) - mapsize;
163 mapsize += padding;
164
165 /* work out where the first object file will go in the archive */
166 archive_member_file_ptr = (mapsize
167 + elength
168 + sizeof (struct ar_hdr)
169 + SARMAG);
170
390c0e42
JJ
171 memset (&hdr, ' ', sizeof (struct ar_hdr));
172 memcpy (hdr.ar_name, "/SYM64/", strlen ("/SYM64/"));
173 _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
174 mapsize);
175 _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
176 time (NULL));
36b45482 177 /* This, at least, is what Intel coff sets the values to.: */
390c0e42
JJ
178 _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
179 _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
180 _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-7lo", 0);
181 memcpy (hdr.ar_fmag, ARFMAG, 2);
36b45482
TS
182
183 /* Write the ar header for this item and the number of symbols */
184
c58b9523 185 if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
36b45482 186 != sizeof (struct ar_hdr))
b34976b6 187 return FALSE;
36b45482
TS
188
189 bfd_putb64 ((bfd_vma) symbol_count, buf);
c58b9523 190 if (bfd_bwrite (buf, 8, arch) != 8)
b34976b6 191 return FALSE;
36b45482
TS
192
193 /* Two passes, first write the file offsets for each symbol -
194 remembering that each offset is on a two byte boundary. */
195
196 /* Write out the file offset for the file associated with each
197 symbol, and remember to keep the offsets padded out. */
198
199 current = arch->archive_head;
200 count = 0;
c58b9523 201 while (current != NULL && count < symbol_count)
36b45482
TS
202 {
203 /* For each symbol which is used defined in this object, write out
204 the object file's address in the archive */
205
206 while (map[count].u.abfd == current)
207 {
208 bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf);
c58b9523 209 if (bfd_bwrite (buf, 8, arch) != 8)
b34976b6 210 return FALSE;
36b45482
TS
211 count++;
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;
218 current = current->next;
219 }
220
221 /* now write the strings themselves */
222 for (count = 0; count < symbol_count; count++)
223 {
224 size_t len = strlen (*map[count].name) + 1;
225
c58b9523 226 if (bfd_bwrite (*map[count].name, len, arch) != len)
b34976b6 227 return FALSE;
36b45482
TS
228 }
229
230 /* The spec says that this should be padded to an 8 byte boundary.
231 However, the Irix 6.2 tools do not appear to do this. */
232 while (padding != 0)
233 {
c58b9523 234 if (bfd_bwrite ("", 1, arch) != 1)
b34976b6 235 return FALSE;
36b45482
TS
236 --padding;
237 }
238
b34976b6 239 return TRUE;
36b45482 240}
This page took 0.309379 seconds and 4 git commands to generate.