00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "bfd.h"
00027 #include "sysdep.h"
00028 #include "libbfd.h"
00029 #include "aout/ar.h"
00030
00031
00032
00033
00034 bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
00035 bfd_boolean bfd_elf64_archive_write_armap
00036 (bfd *, unsigned int, struct orl *, unsigned int, int);
00037
00038
00039
00040 bfd_boolean
00041 bfd_elf64_archive_slurp_armap (bfd *abfd)
00042 {
00043 struct artdata *ardata = bfd_ardata (abfd);
00044 char nextname[17];
00045 file_ptr arhdrpos;
00046 bfd_size_type i, parsed_size, nsymz, stringsize, carsym_size, ptrsize;
00047 struct areltdata *mapdata;
00048 bfd_byte int_buf[8];
00049 char *stringbase;
00050 bfd_byte *raw_armap = NULL;
00051 carsym *carsyms;
00052 bfd_size_type amt;
00053
00054 ardata->symdefs = NULL;
00055
00056
00057 arhdrpos = bfd_tell (abfd);
00058 i = bfd_bread (nextname, 16, abfd);
00059 if (i == 0)
00060 return TRUE;
00061 if (i != 16)
00062 return FALSE;
00063
00064 if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
00065 return FALSE;
00066
00067
00068 if (strncmp (nextname, "/ ", 16) == 0)
00069 return bfd_slurp_armap (abfd);
00070
00071 if (strncmp (nextname, "/SYM64/ ", 16) != 0)
00072 {
00073 bfd_has_map (abfd) = FALSE;
00074 return TRUE;
00075 }
00076
00077 mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
00078 if (mapdata == NULL)
00079 return FALSE;
00080 parsed_size = mapdata->parsed_size;
00081 bfd_release (abfd, mapdata);
00082
00083 if (bfd_bread (int_buf, 8, abfd) != 8)
00084 {
00085 if (bfd_get_error () != bfd_error_system_call)
00086 bfd_set_error (bfd_error_malformed_archive);
00087 return FALSE;
00088 }
00089
00090 nsymz = bfd_getb64 (int_buf);
00091 stringsize = parsed_size - 8 * nsymz - 8;
00092
00093 carsym_size = nsymz * sizeof (carsym);
00094 ptrsize = 8 * nsymz;
00095
00096 amt = carsym_size + stringsize + 1;
00097 ardata->symdefs = bfd_zalloc (abfd, amt);
00098 if (ardata->symdefs == NULL)
00099 return FALSE;
00100 carsyms = ardata->symdefs;
00101 stringbase = ((char *) ardata->symdefs) + carsym_size;
00102
00103 raw_armap = bfd_alloc (abfd, ptrsize);
00104 if (raw_armap == NULL)
00105 goto release_symdefs;
00106
00107 if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
00108 || bfd_bread (stringbase, stringsize, abfd) != stringsize)
00109 {
00110 if (bfd_get_error () != bfd_error_system_call)
00111 bfd_set_error (bfd_error_malformed_archive);
00112 goto release_raw_armap;
00113 }
00114
00115 for (i = 0; i < nsymz; i++)
00116 {
00117 carsyms->file_offset = bfd_getb64 (raw_armap + i * 8);
00118 carsyms->name = stringbase;
00119 stringbase += strlen (stringbase) + 1;
00120 ++carsyms;
00121 }
00122 *stringbase = '\0';
00123
00124 ardata->symdef_count = nsymz;
00125 ardata->first_file_filepos = bfd_tell (abfd);
00126
00127 ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
00128
00129 bfd_has_map (abfd) = TRUE;
00130 bfd_release (abfd, raw_armap);
00131
00132 return TRUE;
00133
00134 release_raw_armap:
00135 bfd_release (abfd, raw_armap);
00136 release_symdefs:
00137 bfd_release (abfd, ardata->symdefs);
00138 return FALSE;
00139 }
00140
00141
00142
00143
00144
00145 bfd_boolean
00146 bfd_elf64_archive_write_armap (bfd *arch,
00147 unsigned int elength,
00148 struct orl *map,
00149 unsigned int symbol_count,
00150 int stridx)
00151 {
00152 unsigned int ranlibsize = (symbol_count * 8) + 8;
00153 unsigned int stringsize = stridx;
00154 unsigned int mapsize = stringsize + ranlibsize;
00155 file_ptr archive_member_file_ptr;
00156 bfd *current = arch->archive_head;
00157 unsigned int count;
00158 struct ar_hdr hdr;
00159 unsigned int i;
00160 int padding;
00161 bfd_byte buf[8];
00162
00163 padding = BFD_ALIGN (mapsize, 8) - mapsize;
00164 mapsize += padding;
00165
00166
00167 archive_member_file_ptr = (mapsize
00168 + elength
00169 + sizeof (struct ar_hdr)
00170 + SARMAG);
00171
00172 memset (&hdr, 0, sizeof (struct ar_hdr));
00173 strcpy (hdr.ar_name, "/SYM64/");
00174 sprintf (hdr.ar_size, "%-10d", (int) mapsize);
00175 sprintf (hdr.ar_date, "%ld", (long) time (NULL));
00176
00177 sprintf ((hdr.ar_uid), "%d", 0);
00178 sprintf ((hdr.ar_gid), "%d", 0);
00179 sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0);
00180 strncpy (hdr.ar_fmag, ARFMAG, 2);
00181
00182 for (i = 0; i < sizeof (struct ar_hdr); i++)
00183 if (((char *) (&hdr))[i] == '\0')
00184 (((char *) (&hdr))[i]) = ' ';
00185
00186
00187
00188 if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
00189 != sizeof (struct ar_hdr))
00190 return FALSE;
00191
00192 bfd_putb64 ((bfd_vma) symbol_count, buf);
00193 if (bfd_bwrite (buf, 8, arch) != 8)
00194 return FALSE;
00195
00196
00197
00198
00199
00200
00201
00202 current = arch->archive_head;
00203 count = 0;
00204 while (current != NULL && count < symbol_count)
00205 {
00206
00207
00208
00209 while (map[count].u.abfd == current)
00210 {
00211 bfd_putb64 ((bfd_vma) archive_member_file_ptr, buf);
00212 if (bfd_bwrite (buf, 8, arch) != 8)
00213 return FALSE;
00214 count++;
00215 }
00216
00217 archive_member_file_ptr += (arelt_size (current)
00218 + sizeof (struct ar_hdr));
00219
00220 archive_member_file_ptr += archive_member_file_ptr % 2;
00221 current = current->next;
00222 }
00223
00224
00225 for (count = 0; count < symbol_count; count++)
00226 {
00227 size_t len = strlen (*map[count].name) + 1;
00228
00229 if (bfd_bwrite (*map[count].name, len, arch) != len)
00230 return FALSE;
00231 }
00232
00233
00234
00235 while (padding != 0)
00236 {
00237 if (bfd_bwrite ("", 1, arch) != 1)
00238 return FALSE;
00239 --padding;
00240 }
00241
00242 return TRUE;
00243 }