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