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