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