archive64.c revision 130562
1169689Skan/* MIPS-specific support for 64-bit ELF 2169689Skan Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 3169689Skan Free Software Foundation, Inc. 4169689Skan Ian Lance Taylor, Cygnus Support 5169689Skan Linker support added by Mark Mitchell, CodeSourcery, LLC. 6169689Skan <mark@codesourcery.com> 7169689Skan 8169689SkanThis file is part of BFD, the Binary File Descriptor library. 9169689Skan 10169689SkanThis program is free software; you can redistribute it and/or modify 11169689Skanit under the terms of the GNU General Public License as published by 12169689Skanthe Free Software Foundation; either version 2 of the License, or 13169689Skan(at your option) any later version. 14169689Skan 15169689SkanThis program is distributed in the hope that it will be useful, 16169689Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 17169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18169689SkanGNU General Public License for more details. 19169689Skan 20169689SkanYou should have received a copy of the GNU General Public License 21169689Skanalong with this program; if not, write to the Free Software 22169689SkanFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 23169689Skan 24169689Skan/* This file supports the 64-bit (MIPS) ELF archives. */ 25169689Skan 26169689Skan#include "bfd.h" 27169689Skan#include "sysdep.h" 28169689Skan#include "libbfd.h" 29169689Skan#include "aout/ar.h" 30169689Skan 31169689Skan/* Irix 6 defines a 64bit archive map format, so that they can 32169689Skan have archives more than 4 GB in size. */ 33169689Skan 34169689Skanbfd_boolean bfd_elf64_archive_slurp_armap (bfd *); 35169689Skanbfd_boolean bfd_elf64_archive_write_armap 36169689Skan (bfd *, unsigned int, struct orl *, unsigned int, int); 37169689Skan 38169689Skan/* Read an Irix 6 armap. */ 39169689Skan 40169689Skanbfd_boolean 41169689Skanbfd_elf64_archive_slurp_armap (bfd *abfd) 42169689Skan{ 43169689Skan struct artdata *ardata = bfd_ardata (abfd); 44169689Skan char nextname[17]; 45169689Skan file_ptr arhdrpos; 46169689Skan bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize; 47169689Skan struct areltdata *mapdata; 48169689Skan bfd_byte int_buf[8]; 49169689Skan char *stringbase; 50169689Skan bfd_byte *raw_armap = NULL; 51169689Skan carsym *carsyms; 52169689Skan bfd_size_type amt; 53169689Skan 54169689Skan ardata->symdefs = NULL; 55169689Skan 56169689Skan /* Get the name of the first element. */ 57169689Skan arhdrpos = bfd_tell (abfd); 58169689Skan i = bfd_bread (nextname, 16, abfd); 59169689Skan if (i == 0) 60169689Skan return TRUE; 61169689Skan if (i != 16) 62169689Skan return FALSE; 63169689Skan 64169689Skan if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0) 65169689Skan return FALSE; 66169689Skan 67169689Skan /* Archives with traditional armaps are still permitted. */ 68169689Skan if (strncmp (nextname, "/ ", 16) == 0) 69169689Skan return bfd_slurp_armap (abfd); 70169689Skan 71169689Skan if (strncmp (nextname, "/SYM64/ ", 16) != 0) 72169689Skan { 73169689Skan bfd_has_map (abfd) = FALSE; 74169689Skan return TRUE; 75169689Skan } 76169689Skan 77169689Skan mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); 78169689Skan if (mapdata == NULL) 79169689Skan return FALSE; 80169689Skan parsed_size = mapdata->parsed_size; 81169689Skan bfd_release (abfd, mapdata); 82169689Skan 83169689Skan if (bfd_bread (int_buf, 8, abfd) != 8) 84169689Skan { 85169689Skan if (bfd_get_error () != bfd_error_system_call) 86169689Skan bfd_set_error (bfd_error_malformed_archive); 87169689Skan return FALSE; 88169689Skan } 89169689Skan 90169689Skan nsymz = bfd_getb64 (int_buf); 91169689Skan stringsize = parsed_size - 8 * nsymz - 8; 92169689Skan 93169689Skan carsym_size = nsymz * sizeof (carsym); 94169689Skan ptrsize = 8 * nsymz; 95169689Skan 96169689Skan amt = carsym_size + stringsize + 1; 97169689Skan ardata->symdefs = bfd_zalloc (abfd, amt); 98169689Skan if (ardata->symdefs == NULL) 99169689Skan return FALSE; 100169689Skan carsyms = ardata->symdefs; 101169689Skan stringbase = ((char *) ardata->symdefs) + carsym_size; 102169689Skan 103169689Skan raw_armap = bfd_alloc (abfd, ptrsize); 104169689Skan if (raw_armap == NULL) 105169689Skan goto release_symdefs; 106169689Skan 107169689Skan if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize 108169689Skan || bfd_bread (stringbase, stringsize, abfd) != stringsize) 109169689Skan { 110169689Skan if (bfd_get_error () != bfd_error_system_call) 111169689Skan bfd_set_error (bfd_error_malformed_archive); 112169689Skan goto release_raw_armap; 113169689Skan } 114169689Skan 115169689Skan for (i = 0; i < nsymz; i++) 116169689Skan { 117169689Skan carsyms->file_offset = bfd_getb64 (raw_armap + i * 8); 118169689Skan carsyms->name = stringbase; 119169689Skan stringbase += strlen (stringbase) + 1; 120169689Skan ++carsyms; 121169689Skan } 122169689Skan *stringbase = '\0'; 123169689Skan 124169689Skan ardata->symdef_count = nsymz; 125169689Skan ardata->first_file_filepos = bfd_tell (abfd); 126169689Skan /* Pad to an even boundary if you have to. */ 127169689Skan ardata->first_file_filepos += (ardata->first_file_filepos) % 2; 128169689Skan 129169689Skan bfd_has_map (abfd) = TRUE; 130169689Skan bfd_release (abfd, raw_armap); 131169689Skan 132169689Skan return TRUE; 133169689Skan 134169689Skanrelease_raw_armap: 135169689Skan bfd_release (abfd, raw_armap); 136169689Skanrelease_symdefs: 137169689Skan bfd_release (abfd, ardata->symdefs); 138169689Skan return FALSE; 139169689Skan} 140169689Skan 141169689Skan/* Write out an Irix 6 armap. The Irix 6 tools are supposed to be 142169689Skan able to handle ordinary ELF armaps, but at least on Irix 6.2 the 143169689Skan linker crashes. */ 144169689Skan 145169689Skanbfd_boolean 146169689Skanbfd_elf64_archive_write_armap (bfd *arch, 147169689Skan unsigned int elength, 148169689Skan struct orl *map, 149169689Skan unsigned int symbol_count, 150169689Skan int stridx) 151169689Skan{ 152169689Skan unsigned int ranlibsize = (symbol_count * 8) + 8; 153169689Skan unsigned int stringsize = stridx; 154169689Skan unsigned int mapsize = stringsize + ranlibsize; 155169689Skan file_ptr archive_member_file_ptr; 156169689Skan bfd *current = arch->archive_head; 157169689Skan unsigned int count; 158169689Skan struct ar_hdr hdr; 159169689Skan unsigned int i; 160169689Skan int padding; 161169689Skan bfd_byte buf[8]; 162169689Skan 163169689Skan padding = BFD_ALIGN (mapsize, 8) - mapsize; 164169689Skan mapsize += padding; 165169689Skan 166169689Skan /* work out where the first object file will go in the archive */ 167169689Skan archive_member_file_ptr = (mapsize 168169689Skan + elength 169169689Skan + sizeof (struct ar_hdr) 170169689Skan + SARMAG); 171169689Skan 172169689Skan memset (&hdr, 0, sizeof (struct ar_hdr)); 173169689Skan strcpy (hdr.ar_name, "/SYM64/"); 174169689Skan sprintf (hdr.ar_size, "%-10d", (int) mapsize); 175169689Skan sprintf (hdr.ar_date, "%ld", (long) time (NULL)); 176169689Skan /* This, at least, is what Intel coff sets the values to.: */ 177169689Skan sprintf ((hdr.ar_uid), "%d", 0); 178169689Skan sprintf ((hdr.ar_gid), "%d", 0); 179169689Skan sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0); 180169689Skan strncpy (hdr.ar_fmag, ARFMAG, 2); 181169689Skan 182169689Skan for (i = 0; i < sizeof (struct ar_hdr); i++) 183169689Skan if (((char *) (&hdr))[i] == '\0') 184169689Skan (((char *) (&hdr))[i]) = ' '; 185169689Skan 186169689Skan /* Write the ar header for this item and the number of symbols */ 187169689Skan 188169689Skan if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch) 189169689Skan != sizeof (struct ar_hdr)) 190169689Skan return FALSE; 191169689Skan 192169689Skan bfd_putb64 ((bfd_vma) symbol_count, buf); 193169689Skan if (bfd_bwrite (buf, 8, arch) != 8) 194169689Skan return FALSE; 195169689Skan 196169689Skan /* Two passes, first write the file offsets for each symbol - 197169689Skan remembering that each offset is on a two byte boundary. */ 198169689Skan 199169689Skan /* Write out the file offset for the file associated with each 200169689Skan symbol, and remember to keep the offsets padded out. */ 201169689Skan 202169689Skan current = arch->archive_head; 203169689Skan count = 0; 204169689Skan while (current != NULL && count < symbol_count) 205169689Skan { 206169689Skan /* For each symbol which is used defined in this object, write out 207169689Skan the object file's address in the archive */ 208169689Skan 209169689Skan while (map[count].u.abfd == current) 210169689Skan { 211169689Skan bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf); 212169689Skan if (bfd_bwrite (buf, 8, arch) != 8) 213169689Skan return FALSE; 214169689Skan count++; 215169689Skan } 216169689Skan /* Add size of this archive entry */ 217169689Skan archive_member_file_ptr += (arelt_size (current) 218169689Skan + sizeof (struct ar_hdr)); 219169689Skan /* remember about the even alignment */ 220169689Skan archive_member_file_ptr += archive_member_file_ptr % 2; 221169689Skan current = current->next; 222169689Skan } 223169689Skan 224169689Skan /* now write the strings themselves */ 225169689Skan for (count = 0; count < symbol_count; count++) 226169689Skan { 227169689Skan size_t len = strlen (*map[count].name) + 1; 228169689Skan 229169689Skan if (bfd_bwrite (*map[count].name, len, arch) != len) 230169689Skan return FALSE; 231169689Skan } 232169689Skan 233169689Skan /* The spec says that this should be padded to an 8 byte boundary. 234169689Skan However, the Irix 6.2 tools do not appear to do this. */ 235169689Skan while (padding != 0) 236169689Skan { 237169689Skan if (bfd_bwrite ("", 1, arch) != 1) 238169689Skan return FALSE; 239169689Skan --padding; 240169689Skan } 241169689Skan 242169689Skan return TRUE; 243169689Skan} 244169689Skan