1 |
/* MIPS-specific support for 64-bit ELF |
/* MIPS-specific support for 64-bit ELF |
2 |
Copyright 1996, 1997, 1998, 1999, 2000, 2001 |
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 |
3 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
4 |
Ian Lance Taylor, Cygnus Support |
Ian Lance Taylor, Cygnus Support |
5 |
Linker support added by Mark Mitchell, CodeSourcery, LLC. |
Linker support added by Mark Mitchell, CodeSourcery, LLC. |
31 |
/* Irix 6 defines a 64bit archive map format, so that they can |
/* Irix 6 defines a 64bit archive map format, so that they can |
32 |
have archives more than 4 GB in size. */ |
have archives more than 4 GB in size. */ |
33 |
|
|
34 |
boolean bfd_elf64_archive_slurp_armap PARAMS ((bfd *)); |
bfd_boolean bfd_elf64_archive_slurp_armap (bfd *); |
35 |
boolean bfd_elf64_archive_write_armap |
bfd_boolean bfd_elf64_archive_write_armap |
36 |
PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int)); |
(bfd *, unsigned int, struct orl *, unsigned int, int); |
37 |
|
|
38 |
/* Read an Irix 6 armap. */ |
/* Read an Irix 6 armap. */ |
39 |
|
|
40 |
boolean |
bfd_boolean |
41 |
bfd_elf64_archive_slurp_armap (abfd) |
bfd_elf64_archive_slurp_armap (bfd *abfd) |
|
bfd *abfd; |
|
42 |
{ |
{ |
43 |
struct artdata *ardata = bfd_ardata (abfd); |
struct artdata *ardata = bfd_ardata (abfd); |
44 |
char nextname[17]; |
char nextname[17]; |
55 |
|
|
56 |
/* Get the name of the first element. */ |
/* Get the name of the first element. */ |
57 |
arhdrpos = bfd_tell (abfd); |
arhdrpos = bfd_tell (abfd); |
58 |
i = bfd_bread ((PTR) nextname, (bfd_size_type) 16, abfd); |
i = bfd_bread (nextname, 16, abfd); |
59 |
if (i == 0) |
if (i == 0) |
60 |
return true; |
return TRUE; |
61 |
if (i != 16) |
if (i != 16) |
62 |
return false; |
return FALSE; |
63 |
|
|
64 |
if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0) |
if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0) |
65 |
return false; |
return FALSE; |
66 |
|
|
67 |
/* Archives with traditional armaps are still permitted. */ |
/* Archives with traditional armaps are still permitted. */ |
68 |
if (strncmp (nextname, "/ ", 16) == 0) |
if (strncmp (nextname, "/ ", 16) == 0) |
70 |
|
|
71 |
if (strncmp (nextname, "/SYM64/ ", 16) != 0) |
if (strncmp (nextname, "/SYM64/ ", 16) != 0) |
72 |
{ |
{ |
73 |
bfd_has_map (abfd) = false; |
bfd_has_map (abfd) = FALSE; |
74 |
return true; |
return TRUE; |
75 |
} |
} |
76 |
|
|
77 |
mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); |
mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); |
78 |
if (mapdata == NULL) |
if (mapdata == NULL) |
79 |
return false; |
return FALSE; |
80 |
parsed_size = mapdata->parsed_size; |
parsed_size = mapdata->parsed_size; |
81 |
bfd_release (abfd, (PTR) mapdata); |
bfd_release (abfd, mapdata); |
82 |
|
|
83 |
if (bfd_bread (int_buf, (bfd_size_type) 8, abfd) != 8) |
if (bfd_bread (int_buf, 8, abfd) != 8) |
84 |
{ |
{ |
85 |
if (bfd_get_error () != bfd_error_system_call) |
if (bfd_get_error () != bfd_error_system_call) |
86 |
bfd_set_error (bfd_error_malformed_archive); |
bfd_set_error (bfd_error_malformed_archive); |
87 |
return false; |
return FALSE; |
88 |
} |
} |
89 |
|
|
90 |
nsymz = bfd_getb64 (int_buf); |
nsymz = bfd_getb64 (int_buf); |
94 |
ptrsize = 8 * nsymz; |
ptrsize = 8 * nsymz; |
95 |
|
|
96 |
amt = carsym_size + stringsize + 1; |
amt = carsym_size + stringsize + 1; |
97 |
ardata->symdefs = (carsym *) bfd_zalloc (abfd, amt); |
ardata->symdefs = bfd_zalloc (abfd, amt); |
98 |
if (ardata->symdefs == NULL) |
if (ardata->symdefs == NULL) |
99 |
return false; |
return FALSE; |
100 |
carsyms = ardata->symdefs; |
carsyms = ardata->symdefs; |
101 |
stringbase = ((char *) ardata->symdefs) + carsym_size; |
stringbase = ((char *) ardata->symdefs) + carsym_size; |
102 |
|
|
103 |
raw_armap = (bfd_byte *) bfd_alloc (abfd, ptrsize); |
raw_armap = bfd_alloc (abfd, ptrsize); |
104 |
if (raw_armap == NULL) |
if (raw_armap == NULL) |
105 |
goto release_symdefs; |
goto release_symdefs; |
106 |
|
|
126 |
/* Pad to an even boundary if you have to. */ |
/* Pad to an even boundary if you have to. */ |
127 |
ardata->first_file_filepos += (ardata->first_file_filepos) % 2; |
ardata->first_file_filepos += (ardata->first_file_filepos) % 2; |
128 |
|
|
129 |
bfd_has_map (abfd) = true; |
bfd_has_map (abfd) = TRUE; |
130 |
bfd_release (abfd, raw_armap); |
bfd_release (abfd, raw_armap); |
131 |
|
|
132 |
return true; |
return TRUE; |
133 |
|
|
134 |
release_raw_armap: |
release_raw_armap: |
135 |
bfd_release (abfd, raw_armap); |
bfd_release (abfd, raw_armap); |
136 |
release_symdefs: |
release_symdefs: |
137 |
bfd_release (abfd, ardata->symdefs); |
bfd_release (abfd, ardata->symdefs); |
138 |
return false; |
return FALSE; |
139 |
} |
} |
140 |
|
|
141 |
/* Write out an Irix 6 armap. The Irix 6 tools are supposed to be |
/* 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 |
able to handle ordinary ELF armaps, but at least on Irix 6.2 the |
143 |
linker crashes. */ |
linker crashes. */ |
144 |
|
|
145 |
boolean |
bfd_boolean |
146 |
bfd_elf64_archive_write_armap (arch, elength, map, symbol_count, stridx) |
bfd_elf64_archive_write_armap (bfd *arch, |
147 |
bfd *arch; |
unsigned int elength, |
148 |
unsigned int elength; |
struct orl *map, |
149 |
struct orl *map; |
unsigned int symbol_count, |
150 |
unsigned int symbol_count; |
int stridx) |
|
int stridx; |
|
151 |
{ |
{ |
152 |
unsigned int ranlibsize = (symbol_count * 8) + 8; |
unsigned int ranlibsize = (symbol_count * 8) + 8; |
153 |
unsigned int stringsize = stridx; |
unsigned int stringsize = stridx; |
169 |
+ sizeof (struct ar_hdr) |
+ sizeof (struct ar_hdr) |
170 |
+ SARMAG); |
+ SARMAG); |
171 |
|
|
172 |
memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); |
memset (&hdr, 0, sizeof (struct ar_hdr)); |
173 |
strcpy (hdr.ar_name, "/SYM64/"); |
strcpy (hdr.ar_name, "/SYM64/"); |
174 |
sprintf (hdr.ar_size, "%-10d", (int) mapsize); |
sprintf (hdr.ar_size, "%-10d", (int) mapsize); |
175 |
sprintf (hdr.ar_date, "%ld", (long) time (NULL)); |
sprintf (hdr.ar_date, "%ld", (long) time (NULL)); |
185 |
|
|
186 |
/* Write the ar header for this item and the number of symbols */ |
/* Write the ar header for this item and the number of symbols */ |
187 |
|
|
188 |
if (bfd_bwrite ((PTR) &hdr, (bfd_size_type) sizeof (struct ar_hdr), arch) |
if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch) |
189 |
!= sizeof (struct ar_hdr)) |
!= sizeof (struct ar_hdr)) |
190 |
return false; |
return FALSE; |
191 |
|
|
192 |
bfd_putb64 ((bfd_vma) symbol_count, buf); |
bfd_putb64 ((bfd_vma) symbol_count, buf); |
193 |
if (bfd_bwrite (buf, (bfd_size_type) 8, arch) != 8) |
if (bfd_bwrite (buf, 8, arch) != 8) |
194 |
return false; |
return FALSE; |
195 |
|
|
196 |
/* Two passes, first write the file offsets for each symbol - |
/* Two passes, first write the file offsets for each symbol - |
197 |
remembering that each offset is on a two byte boundary. */ |
remembering that each offset is on a two byte boundary. */ |
201 |
|
|
202 |
current = arch->archive_head; |
current = arch->archive_head; |
203 |
count = 0; |
count = 0; |
204 |
while (current != (bfd *) NULL && count < symbol_count) |
while (current != NULL && count < symbol_count) |
205 |
{ |
{ |
206 |
/* For each symbol which is used defined in this object, write out |
/* For each symbol which is used defined in this object, write out |
207 |
the object file's address in the archive */ |
the object file's address in the archive */ |
209 |
while (map[count].u.abfd == current) |
while (map[count].u.abfd == current) |
210 |
{ |
{ |
211 |
bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf); |
bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf); |
212 |
if (bfd_bwrite (buf, (bfd_size_type) 8, arch) != 8) |
if (bfd_bwrite (buf, 8, arch) != 8) |
213 |
return false; |
return FALSE; |
214 |
count++; |
count++; |
215 |
} |
} |
216 |
/* Add size of this archive entry */ |
/* Add size of this archive entry */ |
226 |
{ |
{ |
227 |
size_t len = strlen (*map[count].name) + 1; |
size_t len = strlen (*map[count].name) + 1; |
228 |
|
|
229 |
if (bfd_bwrite (*map[count].name, (bfd_size_type) len, arch) != len) |
if (bfd_bwrite (*map[count].name, len, arch) != len) |
230 |
return false; |
return FALSE; |
231 |
} |
} |
232 |
|
|
233 |
/* The spec says that this should be padded to an 8 byte boundary. |
/* The spec says that this should be padded to an 8 byte boundary. |
234 |
However, the Irix 6.2 tools do not appear to do this. */ |
However, the Irix 6.2 tools do not appear to do this. */ |
235 |
while (padding != 0) |
while (padding != 0) |
236 |
{ |
{ |
237 |
if (bfd_bwrite ("", (bfd_size_type) 1, arch) != 1) |
if (bfd_bwrite ("", 1, arch) != 1) |
238 |
return false; |
return FALSE; |
239 |
--padding; |
--padding; |
240 |
} |
} |
241 |
|
|
242 |
return true; |
return TRUE; |
243 |
} |
} |