| 1 | /* BFD back-end for archive files (libraries). | 
|---|
| 2 | Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, | 
|---|
| 3 | 2000, 2001, 2002 | 
|---|
| 4 | Free Software Foundation, Inc. | 
|---|
| 5 | Written by Cygnus Support.  Mostly Gumby Henkel-Wallace's fault. | 
|---|
| 6 |  | 
|---|
| 7 | This file is part of BFD, the Binary File Descriptor library. | 
|---|
| 8 |  | 
|---|
| 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 | 
|---|
| 11 | the Free Software Foundation; either version 2 of the License, or | 
|---|
| 12 | (at your option) any later version. | 
|---|
| 13 |  | 
|---|
| 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. | 
|---|
| 18 |  | 
|---|
| 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 | 
|---|
| 21 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ | 
|---|
| 22 |  | 
|---|
| 23 | /* | 
|---|
| 24 | @setfilename archive-info | 
|---|
| 25 | SECTION | 
|---|
| 26 | Archives | 
|---|
| 27 |  | 
|---|
| 28 | DESCRIPTION | 
|---|
| 29 | An archive (or library) is just another BFD.  It has a symbol | 
|---|
| 30 | table, although there's not much a user program will do with it. | 
|---|
| 31 |  | 
|---|
| 32 | The big difference between an archive BFD and an ordinary BFD | 
|---|
| 33 | is that the archive doesn't have sections.  Instead it has a | 
|---|
| 34 | chain of BFDs that are considered its contents.  These BFDs can | 
|---|
| 35 | be manipulated like any other.  The BFDs contained in an | 
|---|
| 36 | archive opened for reading will all be opened for reading.  You | 
|---|
| 37 | may put either input or output BFDs into an archive opened for | 
|---|
| 38 | output; they will be handled correctly when the archive is closed. | 
|---|
| 39 |  | 
|---|
| 40 | Use <<bfd_openr_next_archived_file>> to step through | 
|---|
| 41 | the contents of an archive opened for input.  You don't | 
|---|
| 42 | have to read the entire archive if you don't want | 
|---|
| 43 | to!  Read it until you find what you want. | 
|---|
| 44 |  | 
|---|
| 45 | Archive contents of output BFDs are chained through the | 
|---|
| 46 | <<next>> pointer in a BFD.  The first one is findable through | 
|---|
| 47 | the <<archive_head>> slot of the archive.  Set it with | 
|---|
| 48 | <<bfd_set_archive_head>> (q.v.).  A given BFD may be in only one | 
|---|
| 49 | open output archive at a time. | 
|---|
| 50 |  | 
|---|
| 51 | As expected, the BFD archive code is more general than the | 
|---|
| 52 | archive code of any given environment.  BFD archives may | 
|---|
| 53 | contain files of different formats (e.g., a.out and coff) and | 
|---|
| 54 | even different architectures.  You may even place archives | 
|---|
| 55 | recursively into archives! | 
|---|
| 56 |  | 
|---|
| 57 | This can cause unexpected confusion, since some archive | 
|---|
| 58 | formats are more expressive than others.  For instance, Intel | 
|---|
| 59 | COFF archives can preserve long filenames; SunOS a.out archives | 
|---|
| 60 | cannot.  If you move a file from the first to the second | 
|---|
| 61 | format and back again, the filename may be truncated. | 
|---|
| 62 | Likewise, different a.out environments have different | 
|---|
| 63 | conventions as to how they truncate filenames, whether they | 
|---|
| 64 | preserve directory names in filenames, etc.  When | 
|---|
| 65 | interoperating with native tools, be sure your files are | 
|---|
| 66 | homogeneous. | 
|---|
| 67 |  | 
|---|
| 68 | Beware: most of these formats do not react well to the | 
|---|
| 69 | presence of spaces in filenames.  We do the best we can, but | 
|---|
| 70 | can't always handle this case due to restrictions in the format of | 
|---|
| 71 | archives.  Many Unix utilities are braindead in regards to | 
|---|
| 72 | spaces and such in filenames anyway, so this shouldn't be much | 
|---|
| 73 | of a restriction. | 
|---|
| 74 |  | 
|---|
| 75 | Archives are supported in BFD in <<archive.c>>. | 
|---|
| 76 |  | 
|---|
| 77 | */ | 
|---|
| 78 |  | 
|---|
| 79 | /* Assumes: | 
|---|
| 80 | o - all archive elements start on an even boundary, newline padded; | 
|---|
| 81 | o - all arch headers are char *; | 
|---|
| 82 | o - all arch headers are the same size (across architectures). | 
|---|
| 83 | */ | 
|---|
| 84 |  | 
|---|
| 85 | /* Some formats provide a way to cram a long filename into the short | 
|---|
| 86 | (16 chars) space provided by a BSD archive.  The trick is: make a | 
|---|
| 87 | special "file" in the front of the archive, sort of like the SYMDEF | 
|---|
| 88 | entry.  If the filename is too long to fit, put it in the extended | 
|---|
| 89 | name table, and use its index as the filename.  To prevent | 
|---|
| 90 | confusion prepend the index with a space.  This means you can't | 
|---|
| 91 | have filenames that start with a space, but then again, many Unix | 
|---|
| 92 | utilities can't handle that anyway. | 
|---|
| 93 |  | 
|---|
| 94 | This scheme unfortunately requires that you stand on your head in | 
|---|
| 95 | order to write an archive since you need to put a magic file at the | 
|---|
| 96 | front, and need to touch every entry to do so.  C'est la vie. | 
|---|
| 97 |  | 
|---|
| 98 | We support two variants of this idea: | 
|---|
| 99 | The SVR4 format (extended name table is named "//"), | 
|---|
| 100 | and an extended pseudo-BSD variant (extended name table is named | 
|---|
| 101 | "ARFILENAMES/").  The origin of the latter format is uncertain. | 
|---|
| 102 |  | 
|---|
| 103 | BSD 4.4 uses a third scheme:  It writes a long filename | 
|---|
| 104 | directly after the header.  This allows 'ar q' to work. | 
|---|
| 105 | We currently can read BSD 4.4 archives, but not write them. | 
|---|
| 106 | */ | 
|---|
| 107 |  | 
|---|
| 108 | /* Summary of archive member names: | 
|---|
| 109 |  | 
|---|
| 110 | Symbol table (must be first): | 
|---|
| 111 | "__.SYMDEF       " - Symbol table, Berkeley style, produced by ranlib. | 
|---|
| 112 | "/               " - Symbol table, system 5 style. | 
|---|
| 113 |  | 
|---|
| 114 | Long name table (must be before regular file members): | 
|---|
| 115 | "//              " - Long name table, System 5 R4 style. | 
|---|
| 116 | "ARFILENAMES/    " - Long name table, non-standard extended BSD (not BSD 4.4). | 
|---|
| 117 |  | 
|---|
| 118 | Regular file members with short names: | 
|---|
| 119 | "filename.o/     " - Regular file, System 5 style (embedded spaces ok). | 
|---|
| 120 | "filename.o      " - Regular file, Berkeley style (no embedded spaces). | 
|---|
| 121 |  | 
|---|
| 122 | Regular files with long names (or embedded spaces, for BSD variants): | 
|---|
| 123 | "/18             " - SVR4 style, name at offset 18 in name table. | 
|---|
| 124 | "#1/23           " - Long name (or embedded paces) 23 characters long, | 
|---|
| 125 | BSD 4.4 style, full name follows header. | 
|---|
| 126 | Implemented for reading, not writing. | 
|---|
| 127 | " 18             " - Long name 18 characters long, extended pseudo-BSD. | 
|---|
| 128 | */ | 
|---|
| 129 |  | 
|---|
| 130 | #include "bfd.h" | 
|---|
| 131 | #include "sysdep.h" | 
|---|
| 132 | #include "libbfd.h" | 
|---|
| 133 | #include "aout/ar.h" | 
|---|
| 134 | #include "aout/ranlib.h" | 
|---|
| 135 | #include "safe-ctype.h" | 
|---|
| 136 |  | 
|---|
| 137 | #ifndef errno | 
|---|
| 138 | extern int errno; | 
|---|
| 139 | #endif | 
|---|
| 140 |  | 
|---|
| 141 | #ifdef GNU960 | 
|---|
| 142 | #define BFD_GNU960_ARMAG(abfd)  (BFD_COFF_FILE_P((abfd)) ? ARMAG : ARMAGB) | 
|---|
| 143 | #endif | 
|---|
| 144 |  | 
|---|
| 145 | /* We keep a cache of archive filepointers to archive elements to | 
|---|
| 146 | speed up searching the archive by filepos.  We only add an entry to | 
|---|
| 147 | the cache when we actually read one.  We also don't sort the cache; | 
|---|
| 148 | it's generally short enough to search linearly. | 
|---|
| 149 | Note that the pointers here point to the front of the ar_hdr, not | 
|---|
| 150 | to the front of the contents!  */ | 
|---|
| 151 | struct ar_cache { | 
|---|
| 152 | file_ptr ptr; | 
|---|
| 153 | bfd *arelt; | 
|---|
| 154 | struct ar_cache *next; | 
|---|
| 155 | }; | 
|---|
| 156 |  | 
|---|
| 157 | #define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char) | 
|---|
| 158 | #define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen) | 
|---|
| 159 |  | 
|---|
| 160 | #define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data)) | 
|---|
| 161 | #define arch_hdr(bfd) ((struct ar_hdr *)arch_eltdata(bfd)->arch_header) | 
|---|
| 162 |  | 
|---|
| 163 | static char *get_extended_arelt_filename | 
|---|
| 164 | PARAMS ((bfd *arch, const char *name)); | 
|---|
| 165 | static bfd_boolean do_slurp_bsd_armap | 
|---|
| 166 | PARAMS ((bfd *abfd)); | 
|---|
| 167 | static bfd_boolean do_slurp_coff_armap | 
|---|
| 168 | PARAMS ((bfd *abfd)); | 
|---|
| 169 | bfd_boolean bfd_elf64_archive_slurp_armap | 
|---|
| 170 | PARAMS ((bfd *abfd)); | 
|---|
| 171 | static const char *normalize | 
|---|
| 172 | PARAMS ((bfd *, const char *file)); | 
|---|
| 173 | static struct areltdata *bfd_ar_hdr_from_filesystem | 
|---|
| 174 | PARAMS ((bfd *abfd, const char *, bfd *member)); | 
|---|
| 175 |  | 
|---|
| 176 |  | 
|---|
| 177 | bfd_boolean | 
|---|
| 178 | _bfd_generic_mkarchive (abfd) | 
|---|
| 179 | bfd *abfd; | 
|---|
| 180 | { | 
|---|
| 181 | bfd_size_type amt = sizeof (struct artdata); | 
|---|
| 182 |  | 
|---|
| 183 | abfd->tdata.aout_ar_data = (struct artdata *) bfd_zalloc (abfd, amt); | 
|---|
| 184 | if (bfd_ardata (abfd) == NULL) | 
|---|
| 185 | return FALSE; | 
|---|
| 186 |  | 
|---|
| 187 | bfd_ardata (abfd)->cache = NULL; | 
|---|
| 188 | bfd_ardata (abfd)->archive_head = NULL; | 
|---|
| 189 | bfd_ardata (abfd)->symdefs = NULL; | 
|---|
| 190 | bfd_ardata (abfd)->extended_names = NULL; | 
|---|
| 191 | bfd_ardata (abfd)->tdata = NULL; | 
|---|
| 192 |  | 
|---|
| 193 | return TRUE; | 
|---|
| 194 | } | 
|---|
| 195 |  | 
|---|
| 196 | /* | 
|---|
| 197 | FUNCTION | 
|---|
| 198 | bfd_get_next_mapent | 
|---|
| 199 |  | 
|---|
| 200 | SYNOPSIS | 
|---|
| 201 | symindex bfd_get_next_mapent(bfd *abfd, symindex previous, carsym **sym); | 
|---|
| 202 |  | 
|---|
| 203 | DESCRIPTION | 
|---|
| 204 | Step through archive @var{abfd}'s symbol table (if it | 
|---|
| 205 | has one).  Successively update @var{sym} with the next symbol's | 
|---|
| 206 | information, returning that symbol's (internal) index into the | 
|---|
| 207 | symbol table. | 
|---|
| 208 |  | 
|---|
| 209 | Supply <<BFD_NO_MORE_SYMBOLS>> as the @var{previous} entry to get | 
|---|
| 210 | the first one; returns <<BFD_NO_MORE_SYMBOLS>> when you've already | 
|---|
| 211 | got the last one. | 
|---|
| 212 |  | 
|---|
| 213 | A <<carsym>> is a canonical archive symbol.  The only | 
|---|
| 214 | user-visible element is its name, a null-terminated string. | 
|---|
| 215 | */ | 
|---|
| 216 |  | 
|---|
| 217 | symindex | 
|---|
| 218 | bfd_get_next_mapent (abfd, prev, entry) | 
|---|
| 219 | bfd *abfd; | 
|---|
| 220 | symindex prev; | 
|---|
| 221 | carsym **entry; | 
|---|
| 222 | { | 
|---|
| 223 | if (!bfd_has_map (abfd)) | 
|---|
| 224 | { | 
|---|
| 225 | bfd_set_error (bfd_error_invalid_operation); | 
|---|
| 226 | return BFD_NO_MORE_SYMBOLS; | 
|---|
| 227 | } | 
|---|
| 228 |  | 
|---|
| 229 | if (prev == BFD_NO_MORE_SYMBOLS) | 
|---|
| 230 | prev = 0; | 
|---|
| 231 | else | 
|---|
| 232 | ++prev; | 
|---|
| 233 | if (prev >= bfd_ardata (abfd)->symdef_count) | 
|---|
| 234 | return BFD_NO_MORE_SYMBOLS; | 
|---|
| 235 |  | 
|---|
| 236 | *entry = (bfd_ardata (abfd)->symdefs + prev); | 
|---|
| 237 | return prev; | 
|---|
| 238 | } | 
|---|
| 239 |  | 
|---|
| 240 | /* To be called by backends only */ | 
|---|
| 241 |  | 
|---|
| 242 | bfd * | 
|---|
| 243 | _bfd_create_empty_archive_element_shell (obfd) | 
|---|
| 244 | bfd *obfd; | 
|---|
| 245 | { | 
|---|
| 246 | return _bfd_new_bfd_contained_in (obfd); | 
|---|
| 247 | } | 
|---|
| 248 |  | 
|---|
| 249 | /* | 
|---|
| 250 | FUNCTION | 
|---|
| 251 | bfd_set_archive_head | 
|---|
| 252 |  | 
|---|
| 253 | SYNOPSIS | 
|---|
| 254 | bfd_boolean bfd_set_archive_head(bfd *output, bfd *new_head); | 
|---|
| 255 |  | 
|---|
| 256 | DESCRIPTION | 
|---|
| 257 | Set the head of the chain of | 
|---|
| 258 | BFDs contained in the archive @var{output} to @var{new_head}. | 
|---|
| 259 | */ | 
|---|
| 260 |  | 
|---|
| 261 | bfd_boolean | 
|---|
| 262 | bfd_set_archive_head (output_archive, new_head) | 
|---|
| 263 | bfd *output_archive; | 
|---|
| 264 | bfd *new_head; | 
|---|
| 265 | { | 
|---|
| 266 |  | 
|---|
| 267 | output_archive->archive_head = new_head; | 
|---|
| 268 | return TRUE; | 
|---|
| 269 | } | 
|---|
| 270 |  | 
|---|
| 271 | bfd * | 
|---|
| 272 | _bfd_look_for_bfd_in_cache (arch_bfd, filepos) | 
|---|
| 273 | bfd *arch_bfd; | 
|---|
| 274 | file_ptr filepos; | 
|---|
| 275 | { | 
|---|
| 276 | struct ar_cache *current; | 
|---|
| 277 |  | 
|---|
| 278 | for (current = bfd_ardata (arch_bfd)->cache; current != NULL; | 
|---|
| 279 | current = current->next) | 
|---|
| 280 | if (current->ptr == filepos) | 
|---|
| 281 | return current->arelt; | 
|---|
| 282 |  | 
|---|
| 283 | return NULL; | 
|---|
| 284 | } | 
|---|
| 285 |  | 
|---|
| 286 | /* Kind of stupid to call cons for each one, but we don't do too many */ | 
|---|
| 287 | bfd_boolean | 
|---|
| 288 | _bfd_add_bfd_to_archive_cache (arch_bfd, filepos, new_elt) | 
|---|
| 289 | bfd *arch_bfd, *new_elt; | 
|---|
| 290 | file_ptr filepos; | 
|---|
| 291 | { | 
|---|
| 292 | bfd_size_type amt = sizeof (struct ar_cache); | 
|---|
| 293 |  | 
|---|
| 294 | struct ar_cache *new_cache = (struct ar_cache *) bfd_zalloc (arch_bfd, amt); | 
|---|
| 295 | if (new_cache == NULL) | 
|---|
| 296 | return FALSE; | 
|---|
| 297 |  | 
|---|
| 298 | new_cache->ptr = filepos; | 
|---|
| 299 | new_cache->arelt = new_elt; | 
|---|
| 300 | new_cache->next = (struct ar_cache *) NULL; | 
|---|
| 301 | if (bfd_ardata (arch_bfd)->cache == NULL) | 
|---|
| 302 | bfd_ardata (arch_bfd)->cache = new_cache; | 
|---|
| 303 | else | 
|---|
| 304 | { | 
|---|
| 305 | struct ar_cache *current = bfd_ardata (arch_bfd)->cache; | 
|---|
| 306 |  | 
|---|
| 307 | while (current->next != NULL) | 
|---|
| 308 | current = current->next; | 
|---|
| 309 | current->next = new_cache; | 
|---|
| 310 | } | 
|---|
| 311 |  | 
|---|
| 312 | return TRUE; | 
|---|
| 313 | } | 
|---|
| 314 |  | 
|---|
| 315 |  | 
|---|
| 316 | /* The name begins with space.  Hence the rest of the name is an index into | 
|---|
| 317 | the string table.  */ | 
|---|
| 318 |  | 
|---|
| 319 | static char * | 
|---|
| 320 | get_extended_arelt_filename (arch, name) | 
|---|
| 321 | bfd *arch; | 
|---|
| 322 | const char *name; | 
|---|
| 323 | { | 
|---|
| 324 | unsigned long index = 0; | 
|---|
| 325 |  | 
|---|
| 326 | /* Should extract string so that I can guarantee not to overflow into | 
|---|
| 327 | the next region, but I'm too lazy.  */ | 
|---|
| 328 | errno = 0; | 
|---|
| 329 | /* Skip first char, which is '/' in SVR4 or ' ' in some other variants.  */ | 
|---|
| 330 | index = strtol (name + 1, NULL, 10); | 
|---|
| 331 | if (errno != 0) | 
|---|
| 332 | { | 
|---|
| 333 | bfd_set_error (bfd_error_malformed_archive); | 
|---|
| 334 | return NULL; | 
|---|
| 335 | } | 
|---|
| 336 |  | 
|---|
| 337 | return bfd_ardata (arch)->extended_names + index; | 
|---|
| 338 | } | 
|---|
| 339 |  | 
|---|
| 340 | /* This functions reads an arch header and returns an areltdata pointer, or | 
|---|
| 341 | NULL on error. | 
|---|
| 342 |  | 
|---|
| 343 | Presumes the file pointer is already in the right place (ie pointing | 
|---|
| 344 | to the ar_hdr in the file).   Moves the file pointer; on success it | 
|---|
| 345 | should be pointing to the front of the file contents; on failure it | 
|---|
| 346 | could have been moved arbitrarily. | 
|---|
| 347 | */ | 
|---|
| 348 |  | 
|---|
| 349 | PTR | 
|---|
| 350 | _bfd_generic_read_ar_hdr (abfd) | 
|---|
| 351 | bfd *abfd; | 
|---|
| 352 | { | 
|---|
| 353 | return _bfd_generic_read_ar_hdr_mag (abfd, (const char *) NULL); | 
|---|
| 354 | } | 
|---|
| 355 |  | 
|---|
| 356 | /* Alpha ECOFF uses an optional different ARFMAG value, so we have a | 
|---|
| 357 | variant of _bfd_generic_read_ar_hdr which accepts a magic string.  */ | 
|---|
| 358 |  | 
|---|
| 359 | PTR | 
|---|
| 360 | _bfd_generic_read_ar_hdr_mag (abfd, mag) | 
|---|
| 361 | bfd *abfd; | 
|---|
| 362 | const char *mag; | 
|---|
| 363 | { | 
|---|
| 364 | struct ar_hdr hdr; | 
|---|
| 365 | char *hdrp = (char *) &hdr; | 
|---|
| 366 | size_t parsed_size; | 
|---|
| 367 | struct areltdata *ared; | 
|---|
| 368 | char *filename = NULL; | 
|---|
| 369 | bfd_size_type namelen = 0; | 
|---|
| 370 | bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr); | 
|---|
| 371 | char *allocptr = 0; | 
|---|
| 372 |  | 
|---|
| 373 | if (bfd_bread ((PTR) hdrp, (bfd_size_type) sizeof (struct ar_hdr), abfd) | 
|---|
| 374 | != sizeof (struct ar_hdr)) | 
|---|
| 375 | { | 
|---|
| 376 | if (bfd_get_error () != bfd_error_system_call) | 
|---|
| 377 | bfd_set_error (bfd_error_no_more_archived_files); | 
|---|
| 378 | return NULL; | 
|---|
| 379 | } | 
|---|
| 380 | if (strncmp (hdr.ar_fmag, ARFMAG, 2) != 0 | 
|---|
| 381 | && (mag == NULL | 
|---|
| 382 | || strncmp (hdr.ar_fmag, mag, 2) != 0)) | 
|---|
| 383 | { | 
|---|
| 384 | bfd_set_error (bfd_error_malformed_archive); | 
|---|
| 385 | return NULL; | 
|---|
| 386 | } | 
|---|
| 387 |  | 
|---|
| 388 | errno = 0; | 
|---|
| 389 | parsed_size = strtol (hdr.ar_size, NULL, 10); | 
|---|
| 390 | if (errno != 0) | 
|---|
| 391 | { | 
|---|
| 392 | bfd_set_error (bfd_error_malformed_archive); | 
|---|
| 393 | return NULL; | 
|---|
| 394 | } | 
|---|
| 395 |  | 
|---|
| 396 | /* Extract the filename from the archive - there are two ways to | 
|---|
| 397 | specify an extended name table, either the first char of the | 
|---|
| 398 | name is a space, or it's a slash.  */ | 
|---|
| 399 | if ((hdr.ar_name[0] == '/' | 
|---|
| 400 | || (hdr.ar_name[0] == ' ' | 
|---|
| 401 | && memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL)) | 
|---|
| 402 | && bfd_ardata (abfd)->extended_names != NULL) | 
|---|
| 403 | { | 
|---|
| 404 | filename = get_extended_arelt_filename (abfd, hdr.ar_name); | 
|---|
| 405 | if (filename == NULL) | 
|---|
| 406 | { | 
|---|
| 407 | bfd_set_error (bfd_error_malformed_archive); | 
|---|
| 408 | return NULL; | 
|---|
| 409 | } | 
|---|
| 410 | } | 
|---|
| 411 | /* BSD4.4-style long filename. | 
|---|
| 412 | Only implemented for reading, so far!  */ | 
|---|
| 413 | else if (hdr.ar_name[0] == '#' | 
|---|
| 414 | && hdr.ar_name[1] == '1' | 
|---|
| 415 | && hdr.ar_name[2] == '/' | 
|---|
| 416 | && ISDIGIT (hdr.ar_name[3])) | 
|---|
| 417 | { | 
|---|
| 418 | /* BSD-4.4 extended name */ | 
|---|
| 419 | namelen = atoi (&hdr.ar_name[3]); | 
|---|
| 420 | allocsize += namelen + 1; | 
|---|
| 421 | parsed_size -= namelen; | 
|---|
| 422 |  | 
|---|
| 423 | allocptr = bfd_zalloc (abfd, allocsize); | 
|---|
| 424 | if (allocptr == NULL) | 
|---|
| 425 | return NULL; | 
|---|
| 426 | filename = (allocptr | 
|---|
| 427 | + sizeof (struct areltdata) | 
|---|
| 428 | + sizeof (struct ar_hdr)); | 
|---|
| 429 | if (bfd_bread (filename, namelen, abfd) != namelen) | 
|---|
| 430 | { | 
|---|
| 431 | if (bfd_get_error () != bfd_error_system_call) | 
|---|
| 432 | bfd_set_error (bfd_error_no_more_archived_files); | 
|---|
| 433 | return NULL; | 
|---|
| 434 | } | 
|---|
| 435 | filename[namelen] = '\0'; | 
|---|
| 436 | } | 
|---|
| 437 | else | 
|---|
| 438 | { | 
|---|
| 439 | /* We judge the end of the name by looking for '/' or ' '. | 
|---|
| 440 | Note:  The SYSV format (terminated by '/') allows embedded | 
|---|
| 441 | spaces, so only look for ' ' if we don't find '/'.  */ | 
|---|
| 442 |  | 
|---|
| 443 | char *e; | 
|---|
| 444 | e = (char *) memchr (hdr.ar_name, '\0', ar_maxnamelen (abfd)); | 
|---|
| 445 | if (e == NULL) | 
|---|
| 446 | { | 
|---|
| 447 | e = (char *) memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)); | 
|---|
| 448 | if (e == NULL) | 
|---|
| 449 | e = (char *) memchr (hdr.ar_name, ' ', ar_maxnamelen (abfd)); | 
|---|
| 450 | } | 
|---|
| 451 |  | 
|---|
| 452 | if (e != NULL) | 
|---|
| 453 | namelen = e - hdr.ar_name; | 
|---|
| 454 | else | 
|---|
| 455 | { | 
|---|
| 456 | /* If we didn't find a termination character, then the name | 
|---|
| 457 | must be the entire field.  */ | 
|---|
| 458 | namelen = ar_maxnamelen (abfd); | 
|---|
| 459 | } | 
|---|
| 460 |  | 
|---|
| 461 | allocsize += namelen + 1; | 
|---|
| 462 | } | 
|---|
| 463 |  | 
|---|
| 464 | if (!allocptr) | 
|---|
| 465 | { | 
|---|
| 466 | allocptr = bfd_zalloc (abfd, allocsize); | 
|---|
| 467 | if (allocptr == NULL) | 
|---|
| 468 | return NULL; | 
|---|
| 469 | } | 
|---|
| 470 |  | 
|---|
| 471 | ared = (struct areltdata *) allocptr; | 
|---|
| 472 |  | 
|---|
| 473 | ared->arch_header = allocptr + sizeof (struct areltdata); | 
|---|
| 474 | memcpy ((char *) ared->arch_header, (char *) &hdr, sizeof (struct ar_hdr)); | 
|---|
| 475 | ared->parsed_size = parsed_size; | 
|---|
| 476 |  | 
|---|
| 477 | if (filename != NULL) | 
|---|
| 478 | ared->filename = filename; | 
|---|
| 479 | else | 
|---|
| 480 | { | 
|---|
| 481 | ared->filename = allocptr + (sizeof (struct areltdata) + | 
|---|
| 482 | sizeof (struct ar_hdr)); | 
|---|
| 483 | if (namelen) | 
|---|
| 484 | memcpy (ared->filename, hdr.ar_name, (size_t) namelen); | 
|---|
| 485 | ared->filename[namelen] = '\0'; | 
|---|
| 486 | } | 
|---|
| 487 |  | 
|---|
| 488 | return (PTR) ared; | 
|---|
| 489 | } | 
|---|
| 490 |  | 
|---|
| 491 |  | 
|---|
| 492 | /* This is an internal function; it's mainly used when indexing | 
|---|
| 493 | through the archive symbol table, but also used to get the next | 
|---|
| 494 | element, since it handles the bookkeeping so nicely for us.  */ | 
|---|
| 495 |  | 
|---|
| 496 | bfd * | 
|---|
| 497 | _bfd_get_elt_at_filepos (archive, filepos) | 
|---|
| 498 | bfd *archive; | 
|---|
| 499 | file_ptr filepos; | 
|---|
| 500 | { | 
|---|
| 501 | struct areltdata *new_areldata; | 
|---|
| 502 | bfd *n_nfd; | 
|---|
| 503 |  | 
|---|
| 504 | n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos); | 
|---|
| 505 | if (n_nfd) | 
|---|
| 506 | return n_nfd; | 
|---|
| 507 |  | 
|---|
| 508 | if (0 > bfd_seek (archive, filepos, SEEK_SET)) | 
|---|
| 509 | return NULL; | 
|---|
| 510 |  | 
|---|
| 511 | if ((new_areldata = (struct areltdata *) _bfd_read_ar_hdr (archive)) == NULL) | 
|---|
| 512 | return NULL; | 
|---|
| 513 |  | 
|---|
| 514 | n_nfd = _bfd_create_empty_archive_element_shell (archive); | 
|---|
| 515 | if (n_nfd == NULL) | 
|---|
| 516 | { | 
|---|
| 517 | bfd_release (archive, (PTR) new_areldata); | 
|---|
| 518 | return NULL; | 
|---|
| 519 | } | 
|---|
| 520 |  | 
|---|
| 521 | n_nfd->origin = bfd_tell (archive); | 
|---|
| 522 | n_nfd->arelt_data = (PTR) new_areldata; | 
|---|
| 523 | n_nfd->filename = new_areldata->filename; | 
|---|
| 524 |  | 
|---|
| 525 | if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd)) | 
|---|
| 526 | return n_nfd; | 
|---|
| 527 |  | 
|---|
| 528 | /* Huh?  */ | 
|---|
| 529 | bfd_release (archive, (PTR) n_nfd); | 
|---|
| 530 | bfd_release (archive, (PTR) new_areldata); | 
|---|
| 531 | return NULL; | 
|---|
| 532 | } | 
|---|
| 533 |  | 
|---|
| 534 | /* Return the BFD which is referenced by the symbol in ABFD indexed by | 
|---|
| 535 | INDEX.  INDEX should have been returned by bfd_get_next_mapent.  */ | 
|---|
| 536 |  | 
|---|
| 537 | bfd * | 
|---|
| 538 | _bfd_generic_get_elt_at_index (abfd, index) | 
|---|
| 539 | bfd *abfd; | 
|---|
| 540 | symindex index; | 
|---|
| 541 | { | 
|---|
| 542 | carsym *entry; | 
|---|
| 543 |  | 
|---|
| 544 | entry = bfd_ardata (abfd)->symdefs + index; | 
|---|
| 545 | return _bfd_get_elt_at_filepos (abfd, entry->file_offset); | 
|---|
| 546 | } | 
|---|
| 547 |  | 
|---|
| 548 | /* | 
|---|
| 549 | FUNCTION | 
|---|
| 550 | bfd_openr_next_archived_file | 
|---|
| 551 |  | 
|---|
| 552 | SYNOPSIS | 
|---|
| 553 | bfd *bfd_openr_next_archived_file(bfd *archive, bfd *previous); | 
|---|
| 554 |  | 
|---|
| 555 | DESCRIPTION | 
|---|
| 556 | Provided a BFD, @var{archive}, containing an archive and NULL, open | 
|---|
| 557 | an input BFD on the first contained element and returns that. | 
|---|
| 558 | Subsequent calls should pass | 
|---|
| 559 | the archive and the previous return value to return a created | 
|---|
| 560 | BFD to the next contained element. NULL is returned when there | 
|---|
| 561 | are no more. | 
|---|
| 562 | */ | 
|---|
| 563 |  | 
|---|
| 564 | bfd * | 
|---|
| 565 | bfd_openr_next_archived_file (archive, last_file) | 
|---|
| 566 | bfd *archive; | 
|---|
| 567 | bfd *last_file; | 
|---|
| 568 | { | 
|---|
| 569 | if ((bfd_get_format (archive) != bfd_archive) || | 
|---|
| 570 | (archive->direction == write_direction)) | 
|---|
| 571 | { | 
|---|
| 572 | bfd_set_error (bfd_error_invalid_operation); | 
|---|
| 573 | return NULL; | 
|---|
| 574 | } | 
|---|
| 575 |  | 
|---|
| 576 | return BFD_SEND (archive, | 
|---|
| 577 | openr_next_archived_file, | 
|---|
| 578 | (archive, | 
|---|
| 579 | last_file)); | 
|---|
| 580 | } | 
|---|
| 581 |  | 
|---|
| 582 | bfd * | 
|---|
| 583 | bfd_generic_openr_next_archived_file (archive, last_file) | 
|---|
| 584 | bfd *archive; | 
|---|
| 585 | bfd *last_file; | 
|---|
| 586 | { | 
|---|
| 587 | file_ptr filestart; | 
|---|
| 588 |  | 
|---|
| 589 | if (!last_file) | 
|---|
| 590 | filestart = bfd_ardata (archive)->first_file_filepos; | 
|---|
| 591 | else | 
|---|
| 592 | { | 
|---|
| 593 | unsigned int size = arelt_size (last_file); | 
|---|
| 594 | /* Pad to an even boundary... | 
|---|
| 595 | Note that last_file->origin can be odd in the case of | 
|---|
| 596 | BSD-4.4-style element with a long odd size.  */ | 
|---|
| 597 | filestart = last_file->origin + size; | 
|---|
| 598 | filestart += filestart % 2; | 
|---|
| 599 | } | 
|---|
| 600 |  | 
|---|
| 601 | return _bfd_get_elt_at_filepos (archive, filestart); | 
|---|
| 602 | } | 
|---|
| 603 |  | 
|---|
| 604 | const bfd_target * | 
|---|
| 605 | bfd_generic_archive_p (abfd) | 
|---|
| 606 | bfd *abfd; | 
|---|
| 607 | { | 
|---|
| 608 | struct artdata *tdata_hold; | 
|---|
| 609 | char armag[SARMAG + 1]; | 
|---|
| 610 | bfd_size_type amt; | 
|---|
| 611 |  | 
|---|
| 612 | if (bfd_bread ((PTR) armag, (bfd_size_type) SARMAG, abfd) != SARMAG) | 
|---|
| 613 | { | 
|---|
| 614 | if (bfd_get_error () != bfd_error_system_call) | 
|---|
| 615 | bfd_set_error (bfd_error_wrong_format); | 
|---|
| 616 | return NULL; | 
|---|
| 617 | } | 
|---|
| 618 |  | 
|---|
| 619 | #ifdef GNU960 | 
|---|
| 620 | if (strncmp (armag, BFD_GNU960_ARMAG (abfd), SARMAG) != 0) | 
|---|
| 621 | return 0; | 
|---|
| 622 | #else | 
|---|
| 623 | if (strncmp (armag, ARMAG, SARMAG) != 0 && | 
|---|
| 624 | strncmp (armag, ARMAGB, SARMAG) != 0) | 
|---|
| 625 | return 0; | 
|---|
| 626 | #endif | 
|---|
| 627 |  | 
|---|
| 628 | tdata_hold = bfd_ardata (abfd); | 
|---|
| 629 |  | 
|---|
| 630 | amt = sizeof (struct artdata); | 
|---|
| 631 | bfd_ardata (abfd) = (struct artdata *) bfd_zalloc (abfd, amt); | 
|---|
| 632 | if (bfd_ardata (abfd) == NULL) | 
|---|
| 633 | { | 
|---|
| 634 | bfd_ardata (abfd) = tdata_hold; | 
|---|
| 635 | return NULL; | 
|---|
| 636 | } | 
|---|
| 637 |  | 
|---|
| 638 | bfd_ardata (abfd)->first_file_filepos = SARMAG; | 
|---|
| 639 | bfd_ardata (abfd)->cache = NULL; | 
|---|
| 640 | bfd_ardata (abfd)->archive_head = NULL; | 
|---|
| 641 | bfd_ardata (abfd)->symdefs = NULL; | 
|---|
| 642 | bfd_ardata (abfd)->extended_names = NULL; | 
|---|
| 643 | bfd_ardata (abfd)->tdata = NULL; | 
|---|
| 644 |  | 
|---|
| 645 | if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd)) | 
|---|
| 646 | || !BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) | 
|---|
| 647 | { | 
|---|
| 648 | if (bfd_get_error () != bfd_error_system_call) | 
|---|
| 649 | bfd_set_error (bfd_error_wrong_format); | 
|---|
| 650 | bfd_release (abfd, bfd_ardata (abfd)); | 
|---|
| 651 | bfd_ardata (abfd) = tdata_hold; | 
|---|
| 652 | return NULL; | 
|---|
| 653 | } | 
|---|
| 654 |  | 
|---|
| 655 | if (bfd_has_map (abfd)) | 
|---|
| 656 | { | 
|---|
| 657 | bfd *first; | 
|---|
| 658 |  | 
|---|
| 659 | /* This archive has a map, so we may presume that the contents | 
|---|
| 660 | are object files.  Make sure that if the first file in the | 
|---|
| 661 | archive can be recognized as an object file, it is for this | 
|---|
| 662 | target.  If not, assume that this is the wrong format.  If | 
|---|
| 663 | the first file is not an object file, somebody is doing | 
|---|
| 664 | something weird, and we permit it so that ar -t will work. | 
|---|
| 665 |  | 
|---|
| 666 | This is done because any normal format will recognize any | 
|---|
| 667 | normal archive, regardless of the format of the object files. | 
|---|
| 668 | We do accept an empty archive.  */ | 
|---|
| 669 |  | 
|---|
| 670 | first = bfd_openr_next_archived_file (abfd, (bfd *) NULL); | 
|---|
| 671 | if (first != NULL) | 
|---|
| 672 | { | 
|---|
| 673 | bfd_boolean fail; | 
|---|
| 674 |  | 
|---|
| 675 | first->target_defaulted = FALSE; | 
|---|
| 676 | fail = FALSE; | 
|---|
| 677 | if (bfd_check_format (first, bfd_object) | 
|---|
| 678 | && first->xvec != abfd->xvec) | 
|---|
| 679 | { | 
|---|
| 680 | #if 0 | 
|---|
| 681 | /* We ought to close `first' here, but we can't, because | 
|---|
| 682 | we have no way to remove it from the archive cache. | 
|---|
| 683 | It's close to impossible to figure out when we can | 
|---|
| 684 | release bfd_ardata.  FIXME.  */ | 
|---|
| 685 | (void) bfd_close (first); | 
|---|
| 686 | bfd_release (abfd, bfd_ardata (abfd)); | 
|---|
| 687 | #endif | 
|---|
| 688 | bfd_set_error (bfd_error_wrong_object_format); | 
|---|
| 689 | bfd_ardata (abfd) = tdata_hold; | 
|---|
| 690 | return NULL; | 
|---|
| 691 | } | 
|---|
| 692 | /* And we ought to close `first' here too.  */ | 
|---|
| 693 | } | 
|---|
| 694 | } | 
|---|
| 695 |  | 
|---|
| 696 | return abfd->xvec; | 
|---|
| 697 | } | 
|---|
| 698 |  | 
|---|
| 699 | /* Some constants for a 32 bit BSD archive structure.  We do not | 
|---|
| 700 | support 64 bit archives presently; so far as I know, none actually | 
|---|
| 701 | exist.  Supporting them would require changing these constants, and | 
|---|
| 702 | changing some H_GET_32 to H_GET_64.  */ | 
|---|
| 703 |  | 
|---|
| 704 | /* The size of an external symdef structure.  */ | 
|---|
| 705 | #define BSD_SYMDEF_SIZE 8 | 
|---|
| 706 |  | 
|---|
| 707 | /* The offset from the start of a symdef structure to the file offset.  */ | 
|---|
| 708 | #define BSD_SYMDEF_OFFSET_SIZE 4 | 
|---|
| 709 |  | 
|---|
| 710 | /* The size of the symdef count.  */ | 
|---|
| 711 | #define BSD_SYMDEF_COUNT_SIZE 4 | 
|---|
| 712 |  | 
|---|
| 713 | /* The size of the string count.  */ | 
|---|
| 714 | #define BSD_STRING_COUNT_SIZE 4 | 
|---|
| 715 |  | 
|---|
| 716 | /* Returns FALSE on error, TRUE otherwise */ | 
|---|
| 717 |  | 
|---|
| 718 | static bfd_boolean | 
|---|
| 719 | do_slurp_bsd_armap (abfd) | 
|---|
| 720 | bfd *abfd; | 
|---|
| 721 | { | 
|---|
| 722 | struct areltdata *mapdata; | 
|---|
| 723 | unsigned int counter; | 
|---|
| 724 | bfd_byte *raw_armap, *rbase; | 
|---|
| 725 | struct artdata *ardata = bfd_ardata (abfd); | 
|---|
| 726 | char *stringbase; | 
|---|
| 727 | bfd_size_type parsed_size, amt; | 
|---|
| 728 | carsym *set; | 
|---|
| 729 |  | 
|---|
| 730 | mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); | 
|---|
| 731 | if (mapdata == NULL) | 
|---|
| 732 | return FALSE; | 
|---|
| 733 | parsed_size = mapdata->parsed_size; | 
|---|
| 734 | bfd_release (abfd, (PTR) mapdata);    /* Don't need it any more.  */ | 
|---|
| 735 |  | 
|---|
| 736 | raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size); | 
|---|
| 737 | if (raw_armap == (bfd_byte *) NULL) | 
|---|
| 738 | return FALSE; | 
|---|
| 739 |  | 
|---|
| 740 | if (bfd_bread ((PTR) raw_armap, parsed_size, abfd) != parsed_size) | 
|---|
| 741 | { | 
|---|
| 742 | if (bfd_get_error () != bfd_error_system_call) | 
|---|
| 743 | bfd_set_error (bfd_error_malformed_archive); | 
|---|
| 744 | byebye: | 
|---|
| 745 | bfd_release (abfd, (PTR) raw_armap); | 
|---|
| 746 | return FALSE; | 
|---|
| 747 | } | 
|---|
| 748 |  | 
|---|
| 749 | ardata->symdef_count = H_GET_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE; | 
|---|
| 750 |  | 
|---|
| 751 | if (ardata->symdef_count * BSD_SYMDEF_SIZE > | 
|---|
| 752 | parsed_size - BSD_SYMDEF_COUNT_SIZE) | 
|---|
| 753 | { | 
|---|
| 754 | /* Probably we're using the wrong byte ordering.  */ | 
|---|
| 755 | bfd_set_error (bfd_error_wrong_format); | 
|---|
| 756 | goto byebye; | 
|---|
| 757 | } | 
|---|
| 758 |  | 
|---|
| 759 | ardata->cache = 0; | 
|---|
| 760 | rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE; | 
|---|
| 761 | stringbase = ((char *) rbase | 
|---|
| 762 | + ardata->symdef_count * BSD_SYMDEF_SIZE | 
|---|
| 763 | + BSD_STRING_COUNT_SIZE); | 
|---|
| 764 | amt = (bfd_size_type) ardata->symdef_count * sizeof (carsym); | 
|---|
| 765 | ardata->symdefs = (carsym *) bfd_alloc (abfd, amt); | 
|---|
| 766 | if (!ardata->symdefs) | 
|---|
| 767 | return FALSE; | 
|---|
| 768 |  | 
|---|
| 769 | for (counter = 0, set = ardata->symdefs; | 
|---|
| 770 | counter < ardata->symdef_count; | 
|---|
| 771 | counter++, set++, rbase += BSD_SYMDEF_SIZE) | 
|---|
| 772 | { | 
|---|
| 773 | set->name = H_GET_32 (abfd, rbase) + stringbase; | 
|---|
| 774 | set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); | 
|---|
| 775 | } | 
|---|
| 776 |  | 
|---|
| 777 | ardata->first_file_filepos = bfd_tell (abfd); | 
|---|
| 778 | /* Pad to an even boundary if you have to.  */ | 
|---|
| 779 | ardata->first_file_filepos += (ardata->first_file_filepos) % 2; | 
|---|
| 780 | /* FIXME, we should provide some way to free raw_ardata when | 
|---|
| 781 | we are done using the strings from it.  For now, it seems | 
|---|
| 782 | to be allocated on an objalloc anyway...  */ | 
|---|
| 783 | bfd_has_map (abfd) = TRUE; | 
|---|
| 784 | return TRUE; | 
|---|
| 785 | } | 
|---|
| 786 |  | 
|---|
| 787 | /* Returns FALSE on error, TRUE otherwise.  */ | 
|---|
| 788 |  | 
|---|
| 789 | static bfd_boolean | 
|---|
| 790 | do_slurp_coff_armap (abfd) | 
|---|
| 791 | bfd *abfd; | 
|---|
| 792 | { | 
|---|
| 793 | struct areltdata *mapdata; | 
|---|
| 794 | int *raw_armap, *rawptr; | 
|---|
| 795 | struct artdata *ardata = bfd_ardata (abfd); | 
|---|
| 796 | char *stringbase; | 
|---|
| 797 | bfd_size_type stringsize; | 
|---|
| 798 | unsigned int parsed_size; | 
|---|
| 799 | carsym *carsyms; | 
|---|
| 800 | bfd_size_type nsymz;          /* Number of symbols in armap.  */ | 
|---|
| 801 | bfd_vma (*swap) PARAMS ((const bfd_byte *)); | 
|---|
| 802 | char int_buf[sizeof (long)]; | 
|---|
| 803 | bfd_size_type carsym_size, ptrsize; | 
|---|
| 804 | unsigned int i; | 
|---|
| 805 |  | 
|---|
| 806 | mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); | 
|---|
| 807 | if (mapdata == NULL) | 
|---|
| 808 | return FALSE; | 
|---|
| 809 | parsed_size = mapdata->parsed_size; | 
|---|
| 810 | bfd_release (abfd, (PTR) mapdata);    /* Don't need it any more.  */ | 
|---|
| 811 |  | 
|---|
| 812 | if (bfd_bread ((PTR) int_buf, (bfd_size_type) 4, abfd) != 4) | 
|---|
| 813 | { | 
|---|
| 814 | if (bfd_get_error () != bfd_error_system_call) | 
|---|
| 815 | bfd_set_error (bfd_error_malformed_archive); | 
|---|
| 816 | return FALSE; | 
|---|
| 817 | } | 
|---|
| 818 | /* It seems that all numeric information in a coff archive is always | 
|---|
| 819 | in big endian format, nomatter the host or target.  */ | 
|---|
| 820 | swap = bfd_getb32; | 
|---|
| 821 | nsymz = bfd_getb32 ((PTR) int_buf); | 
|---|
| 822 | stringsize = parsed_size - (4 * nsymz) - 4; | 
|---|
| 823 |  | 
|---|
| 824 | #if 1 | 
|---|
| 825 | /* ... except that some archive formats are broken, and it may be our | 
|---|
| 826 | fault - the i960 little endian coff sometimes has big and sometimes | 
|---|
| 827 | little, because our tools changed.  Here's a horrible hack to clean | 
|---|
| 828 | up the crap.  */ | 
|---|
| 829 |  | 
|---|
| 830 | if (stringsize > 0xfffff | 
|---|
| 831 | && bfd_get_arch (abfd) == bfd_arch_i960 | 
|---|
| 832 | && bfd_get_flavour (abfd) == bfd_target_coff_flavour) | 
|---|
| 833 | { | 
|---|
| 834 | /* This looks dangerous, let's do it the other way around.  */ | 
|---|
| 835 | nsymz = bfd_getl32 ((PTR) int_buf); | 
|---|
| 836 | stringsize = parsed_size - (4 * nsymz) - 4; | 
|---|
| 837 | swap = bfd_getl32; | 
|---|
| 838 | } | 
|---|
| 839 | #endif | 
|---|
| 840 |  | 
|---|
| 841 | /* The coff armap must be read sequentially.  So we construct a | 
|---|
| 842 | bsd-style one in core all at once, for simplicity.  */ | 
|---|
| 843 |  | 
|---|
| 844 | carsym_size = (nsymz * sizeof (carsym)); | 
|---|
| 845 | ptrsize = (4 * nsymz); | 
|---|
| 846 |  | 
|---|
| 847 | ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1); | 
|---|
| 848 | if (ardata->symdefs == NULL) | 
|---|
| 849 | return FALSE; | 
|---|
| 850 | carsyms = ardata->symdefs; | 
|---|
| 851 | stringbase = ((char *) ardata->symdefs) + carsym_size; | 
|---|
| 852 |  | 
|---|
| 853 | /* Allocate and read in the raw offsets.  */ | 
|---|
| 854 | raw_armap = (int *) bfd_alloc (abfd, ptrsize); | 
|---|
| 855 | if (raw_armap == NULL) | 
|---|
| 856 | goto release_symdefs; | 
|---|
| 857 | if (bfd_bread ((PTR) raw_armap, ptrsize, abfd) != ptrsize | 
|---|
| 858 | || (bfd_bread ((PTR) stringbase, stringsize, abfd) != stringsize)) | 
|---|
| 859 | { | 
|---|
| 860 | if (bfd_get_error () != bfd_error_system_call) | 
|---|
| 861 | bfd_set_error (bfd_error_malformed_archive); | 
|---|
| 862 | goto release_raw_armap; | 
|---|
| 863 | } | 
|---|
| 864 |  | 
|---|
| 865 | /* OK, build the carsyms.  */ | 
|---|
| 866 | for (i = 0; i < nsymz; i++) | 
|---|
| 867 | { | 
|---|
| 868 | rawptr = raw_armap + i; | 
|---|
| 869 | carsyms->file_offset = swap ((PTR) rawptr); | 
|---|
| 870 | carsyms->name = stringbase; | 
|---|
| 871 | stringbase += strlen (stringbase) + 1; | 
|---|
| 872 | carsyms++; | 
|---|
| 873 | } | 
|---|
| 874 | *stringbase = 0; | 
|---|
| 875 |  | 
|---|
| 876 | ardata->symdef_count = nsymz; | 
|---|
| 877 | ardata->first_file_filepos = bfd_tell (abfd); | 
|---|
| 878 | /* Pad to an even boundary if you have to.  */ | 
|---|
| 879 | ardata->first_file_filepos += (ardata->first_file_filepos) % 2; | 
|---|
| 880 |  | 
|---|
| 881 | bfd_has_map (abfd) = TRUE; | 
|---|
| 882 | bfd_release (abfd, (PTR) raw_armap); | 
|---|
| 883 |  | 
|---|
| 884 | /* Check for a second archive header (as used by PE).  */ | 
|---|
| 885 | { | 
|---|
| 886 | struct areltdata *tmp; | 
|---|
| 887 |  | 
|---|
| 888 | bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET); | 
|---|
| 889 | tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd); | 
|---|
| 890 | if (tmp != NULL) | 
|---|
| 891 | { | 
|---|
| 892 | if (tmp->arch_header[0] == '/' | 
|---|
| 893 | && tmp->arch_header[1] == ' ') | 
|---|
| 894 | { | 
|---|
| 895 | ardata->first_file_filepos += | 
|---|
| 896 | (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1; | 
|---|
| 897 | } | 
|---|
| 898 | bfd_release (abfd, tmp); | 
|---|
| 899 | } | 
|---|
| 900 | } | 
|---|
| 901 |  | 
|---|
| 902 | return TRUE; | 
|---|
| 903 |  | 
|---|
| 904 | release_raw_armap: | 
|---|
| 905 | bfd_release (abfd, (PTR) raw_armap); | 
|---|
| 906 | release_symdefs: | 
|---|
| 907 | bfd_release (abfd, (PTR) (ardata)->symdefs); | 
|---|
| 908 | return FALSE; | 
|---|
| 909 | } | 
|---|
| 910 |  | 
|---|
| 911 | /* This routine can handle either coff-style or bsd-style armaps. | 
|---|
| 912 | Returns FALSE on error, TRUE otherwise */ | 
|---|
| 913 |  | 
|---|
| 914 | bfd_boolean | 
|---|
| 915 | bfd_slurp_armap (abfd) | 
|---|
| 916 | bfd *abfd; | 
|---|
| 917 | { | 
|---|
| 918 | char nextname[17]; | 
|---|
| 919 | int i = bfd_bread ((PTR) nextname, (bfd_size_type) 16, abfd); | 
|---|
| 920 |  | 
|---|
| 921 | if (i == 0) | 
|---|
| 922 | return TRUE; | 
|---|
| 923 | if (i != 16) | 
|---|
| 924 | return FALSE; | 
|---|
| 925 |  | 
|---|
| 926 | if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0) | 
|---|
| 927 | return FALSE; | 
|---|
| 928 |  | 
|---|
| 929 | if (!strncmp (nextname, "__.SYMDEF       ", 16) | 
|---|
| 930 | || !strncmp (nextname, "__.SYMDEF/      ", 16)) /* old Linux archives */ | 
|---|
| 931 | return do_slurp_bsd_armap (abfd); | 
|---|
| 932 | else if (!strncmp (nextname, "/               ", 16)) | 
|---|
| 933 | return do_slurp_coff_armap (abfd); | 
|---|
| 934 | else if (!strncmp (nextname, "/SYM64/         ", 16)) | 
|---|
| 935 | { | 
|---|
| 936 | /* 64bit ELF (Irix 6) archive.  */ | 
|---|
| 937 | #ifdef BFD64 | 
|---|
| 938 | return bfd_elf64_archive_slurp_armap (abfd); | 
|---|
| 939 | #else | 
|---|
| 940 | bfd_set_error (bfd_error_wrong_format); | 
|---|
| 941 | return FALSE; | 
|---|
| 942 | #endif | 
|---|
| 943 | } | 
|---|
| 944 |  | 
|---|
| 945 | bfd_has_map (abfd) = FALSE; | 
|---|
| 946 | return TRUE; | 
|---|
| 947 | } | 
|---|
| 948 |  | 
|---|
| 949 |  | 
|---|
| 950 | /* Returns FALSE on error, TRUE otherwise */ | 
|---|
| 951 | /* flavor 2 of a bsd armap, similar to bfd_slurp_bsd_armap except the | 
|---|
| 952 | header is in a slightly different order and the map name is '/'. | 
|---|
| 953 | This flavour is used by hp300hpux.  */ | 
|---|
| 954 |  | 
|---|
| 955 | #define HPUX_SYMDEF_COUNT_SIZE 2 | 
|---|
| 956 |  | 
|---|
| 957 | bfd_boolean | 
|---|
| 958 | bfd_slurp_bsd_armap_f2 (abfd) | 
|---|
| 959 | bfd *abfd; | 
|---|
| 960 | { | 
|---|
| 961 | struct areltdata *mapdata; | 
|---|
| 962 | char nextname[17]; | 
|---|
| 963 | unsigned int counter; | 
|---|
| 964 | bfd_byte *raw_armap, *rbase; | 
|---|
| 965 | struct artdata *ardata = bfd_ardata (abfd); | 
|---|
| 966 | char *stringbase; | 
|---|
| 967 | unsigned int stringsize; | 
|---|
| 968 | bfd_size_type amt; | 
|---|
| 969 | carsym *set; | 
|---|
| 970 | int i = bfd_bread ((PTR) nextname, (bfd_size_type) 16, abfd); | 
|---|
| 971 |  | 
|---|
| 972 | if (i == 0) | 
|---|
| 973 | return TRUE; | 
|---|
| 974 | if (i != 16) | 
|---|
| 975 | return FALSE; | 
|---|
| 976 |  | 
|---|
| 977 | /* The archive has at least 16 bytes in it.  */ | 
|---|
| 978 | if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0) | 
|---|
| 979 | return FALSE; | 
|---|
| 980 |  | 
|---|
| 981 | if (!strncmp (nextname, "__.SYMDEF       ", 16) | 
|---|
| 982 | || !strncmp (nextname, "__.SYMDEF/      ", 16)) /* old Linux archives */ | 
|---|
| 983 | return do_slurp_bsd_armap (abfd); | 
|---|
| 984 |  | 
|---|
| 985 | if (strncmp (nextname, "/               ", 16)) | 
|---|
| 986 | { | 
|---|
| 987 | bfd_has_map (abfd) = FALSE; | 
|---|
| 988 | return TRUE; | 
|---|
| 989 | } | 
|---|
| 990 |  | 
|---|
| 991 | mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); | 
|---|
| 992 | if (mapdata == NULL) | 
|---|
| 993 | return FALSE; | 
|---|
| 994 |  | 
|---|
| 995 | amt = mapdata->parsed_size; | 
|---|
| 996 | raw_armap = (bfd_byte *) bfd_zalloc (abfd, amt); | 
|---|
| 997 | if (raw_armap == NULL) | 
|---|
| 998 | { | 
|---|
| 999 | byebye: | 
|---|
| 1000 | bfd_release (abfd, (PTR) mapdata); | 
|---|
| 1001 | return FALSE; | 
|---|
| 1002 | } | 
|---|
| 1003 |  | 
|---|
| 1004 | if (bfd_bread ((PTR) raw_armap, amt, abfd) != amt) | 
|---|
| 1005 | { | 
|---|
| 1006 | if (bfd_get_error () != bfd_error_system_call) | 
|---|
| 1007 | bfd_set_error (bfd_error_malformed_archive); | 
|---|
| 1008 | byebyebye: | 
|---|
| 1009 | bfd_release (abfd, (PTR) raw_armap); | 
|---|
| 1010 | goto byebye; | 
|---|
| 1011 | } | 
|---|
| 1012 |  | 
|---|
| 1013 | ardata->symdef_count = H_GET_16 (abfd, (PTR) raw_armap); | 
|---|
| 1014 |  | 
|---|
| 1015 | if (ardata->symdef_count * BSD_SYMDEF_SIZE | 
|---|
| 1016 | > mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE) | 
|---|
| 1017 | { | 
|---|
| 1018 | /* Probably we're using the wrong byte ordering.  */ | 
|---|
| 1019 | bfd_set_error (bfd_error_wrong_format); | 
|---|
| 1020 | goto byebyebye; | 
|---|
| 1021 | } | 
|---|
| 1022 |  | 
|---|
| 1023 | ardata->cache = 0; | 
|---|
| 1024 |  | 
|---|
| 1025 | stringsize = H_GET_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE); | 
|---|
| 1026 | /* Skip sym count and string sz.  */ | 
|---|
| 1027 | stringbase = ((char *) raw_armap | 
|---|
| 1028 | + HPUX_SYMDEF_COUNT_SIZE | 
|---|
| 1029 | + BSD_STRING_COUNT_SIZE); | 
|---|
| 1030 | rbase = (bfd_byte *) stringbase + stringsize; | 
|---|
| 1031 | amt = (bfd_size_type) ardata->symdef_count * BSD_SYMDEF_SIZE; | 
|---|
| 1032 | ardata->symdefs = (carsym *) bfd_alloc (abfd, amt); | 
|---|
| 1033 | if (!ardata->symdefs) | 
|---|
| 1034 | return FALSE; | 
|---|
| 1035 |  | 
|---|
| 1036 | for (counter = 0, set = ardata->symdefs; | 
|---|
| 1037 | counter < ardata->symdef_count; | 
|---|
| 1038 | counter++, set++, rbase += BSD_SYMDEF_SIZE) | 
|---|
| 1039 | { | 
|---|
| 1040 | set->name = H_GET_32 (abfd, rbase) + stringbase; | 
|---|
| 1041 | set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); | 
|---|
| 1042 | } | 
|---|
| 1043 |  | 
|---|
| 1044 | ardata->first_file_filepos = bfd_tell (abfd); | 
|---|
| 1045 | /* Pad to an even boundary if you have to.  */ | 
|---|
| 1046 | ardata->first_file_filepos += (ardata->first_file_filepos) % 2; | 
|---|
| 1047 | /* FIXME, we should provide some way to free raw_ardata when | 
|---|
| 1048 | we are done using the strings from it.  For now, it seems | 
|---|
| 1049 | to be allocated on an objalloc anyway...  */ | 
|---|
| 1050 | bfd_has_map (abfd) = TRUE; | 
|---|
| 1051 | return TRUE; | 
|---|
| 1052 | } | 
|---|
| 1053 |  | 
|---|
| 1054 |  | 
|---|
| 1055 | /** Extended name table. | 
|---|
| 1056 |  | 
|---|
| 1057 | Normally archives support only 14-character filenames. | 
|---|
| 1058 |  | 
|---|
| 1059 | Intel has extended the format: longer names are stored in a special | 
|---|
| 1060 | element (the first in the archive, or second if there is an armap); | 
|---|
| 1061 | the name in the ar_hdr is replaced by <space><index into filename | 
|---|
| 1062 | element>.  Index is the P.R. of an int (decimal).  Data General have | 
|---|
| 1063 | extended the format by using the prefix // for the special element.  */ | 
|---|
| 1064 |  | 
|---|
| 1065 | /* Returns FALSE on error, TRUE otherwise.  */ | 
|---|
| 1066 |  | 
|---|
| 1067 | bfd_boolean | 
|---|
| 1068 | _bfd_slurp_extended_name_table (abfd) | 
|---|
| 1069 | bfd *abfd; | 
|---|
| 1070 | { | 
|---|
| 1071 | char nextname[17]; | 
|---|
| 1072 | struct areltdata *namedata; | 
|---|
| 1073 | bfd_size_type amt; | 
|---|
| 1074 |  | 
|---|
| 1075 | /* FIXME:  Formatting sucks here, and in case of failure of BFD_READ, | 
|---|
| 1076 | we probably don't want to return TRUE.  */ | 
|---|
| 1077 | bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET); | 
|---|
| 1078 | if (bfd_bread ((PTR) nextname, (bfd_size_type) 16, abfd) == 16) | 
|---|
| 1079 | { | 
|---|
| 1080 | if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0) | 
|---|
| 1081 | return FALSE; | 
|---|
| 1082 |  | 
|---|
| 1083 | if (strncmp (nextname, "ARFILENAMES/    ", 16) != 0 && | 
|---|
| 1084 | strncmp (nextname, "//              ", 16) != 0) | 
|---|
| 1085 | { | 
|---|
| 1086 | bfd_ardata (abfd)->extended_names = NULL; | 
|---|
| 1087 | return TRUE; | 
|---|
| 1088 | } | 
|---|
| 1089 |  | 
|---|
| 1090 | namedata = (struct areltdata *) _bfd_read_ar_hdr (abfd); | 
|---|
| 1091 | if (namedata == NULL) | 
|---|
| 1092 | return FALSE; | 
|---|
| 1093 |  | 
|---|
| 1094 | amt = namedata->parsed_size; | 
|---|
| 1095 | bfd_ardata (abfd)->extended_names = bfd_zalloc (abfd, amt); | 
|---|
| 1096 | if (bfd_ardata (abfd)->extended_names == NULL) | 
|---|
| 1097 | { | 
|---|
| 1098 | byebye: | 
|---|
| 1099 | bfd_release (abfd, (PTR) namedata); | 
|---|
| 1100 | return FALSE; | 
|---|
| 1101 | } | 
|---|
| 1102 |  | 
|---|
| 1103 | if (bfd_bread ((PTR) bfd_ardata (abfd)->extended_names, amt, abfd) != amt) | 
|---|
| 1104 | { | 
|---|
| 1105 | if (bfd_get_error () != bfd_error_system_call) | 
|---|
| 1106 | bfd_set_error (bfd_error_malformed_archive); | 
|---|
| 1107 | bfd_release (abfd, (PTR) (bfd_ardata (abfd)->extended_names)); | 
|---|
| 1108 | bfd_ardata (abfd)->extended_names = NULL; | 
|---|
| 1109 | goto byebye; | 
|---|
| 1110 | } | 
|---|
| 1111 |  | 
|---|
| 1112 | /* Since the archive is supposed to be printable if it contains | 
|---|
| 1113 | text, the entries in the list are newline-padded, not null | 
|---|
| 1114 | padded. In SVR4-style archives, the names also have a | 
|---|
| 1115 | trailing '/'.  DOS/NT created archive often have \ in them | 
|---|
| 1116 | We'll fix all problems here..  */ | 
|---|
| 1117 | { | 
|---|
| 1118 | char *temp = bfd_ardata (abfd)->extended_names; | 
|---|
| 1119 | char *limit = temp + namedata->parsed_size; | 
|---|
| 1120 | for (; temp < limit; ++temp) | 
|---|
| 1121 | { | 
|---|
| 1122 | if (*temp == '\012') | 
|---|
| 1123 | temp[temp[-1] == '/' ? -1 : 0] = '\0'; | 
|---|
| 1124 | if (*temp == '\\') | 
|---|
| 1125 | *temp = '/'; | 
|---|
| 1126 | } | 
|---|
| 1127 | } | 
|---|
| 1128 |  | 
|---|
| 1129 | /* Pad to an even boundary if you have to.  */ | 
|---|
| 1130 | bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd); | 
|---|
| 1131 | bfd_ardata (abfd)->first_file_filepos += | 
|---|
| 1132 | (bfd_ardata (abfd)->first_file_filepos) % 2; | 
|---|
| 1133 |  | 
|---|
| 1134 | /* FIXME, we can't release namedata here because it was allocated | 
|---|
| 1135 | below extended_names on the objalloc...  */ | 
|---|
| 1136 | #if 0 | 
|---|
| 1137 | bfd_release (abfd, namedata); | 
|---|
| 1138 | #endif | 
|---|
| 1139 | } | 
|---|
| 1140 | return TRUE; | 
|---|
| 1141 | } | 
|---|
| 1142 |  | 
|---|
| 1143 | #ifdef VMS | 
|---|
| 1144 |  | 
|---|
| 1145 | /* Return a copy of the stuff in the filename between any :]> and a | 
|---|
| 1146 | semicolon.  */ | 
|---|
| 1147 |  | 
|---|
| 1148 | static const char * | 
|---|
| 1149 | normalize (abfd, file) | 
|---|
| 1150 | bfd *abfd; | 
|---|
| 1151 | const char *file; | 
|---|
| 1152 | { | 
|---|
| 1153 | const char *first; | 
|---|
| 1154 | const char *last; | 
|---|
| 1155 | char *copy; | 
|---|
| 1156 |  | 
|---|
| 1157 | first = file + strlen (file) - 1; | 
|---|
| 1158 | last = first + 1; | 
|---|
| 1159 |  | 
|---|
| 1160 | while (first != file) | 
|---|
| 1161 | { | 
|---|
| 1162 | if (*first == ';') | 
|---|
| 1163 | last = first; | 
|---|
| 1164 | if (*first == ':' || *first == ']' || *first == '>') | 
|---|
| 1165 | { | 
|---|
| 1166 | first++; | 
|---|
| 1167 | break; | 
|---|
| 1168 | } | 
|---|
| 1169 | first--; | 
|---|
| 1170 | } | 
|---|
| 1171 |  | 
|---|
| 1172 | copy = (char *) bfd_alloc (abfd, (bfd_size_type) (last - first + 1)); | 
|---|
| 1173 | if (copy == NULL) | 
|---|
| 1174 | return NULL; | 
|---|
| 1175 |  | 
|---|
| 1176 | memcpy (copy, first, last - first); | 
|---|
| 1177 | copy[last - first] = 0; | 
|---|
| 1178 |  | 
|---|
| 1179 | return copy; | 
|---|
| 1180 | } | 
|---|
| 1181 |  | 
|---|
| 1182 | #else | 
|---|
| 1183 | static const char * | 
|---|
| 1184 | normalize (abfd, file) | 
|---|
| 1185 | bfd *abfd ATTRIBUTE_UNUSED; | 
|---|
| 1186 | const char *file; | 
|---|
| 1187 | { | 
|---|
| 1188 | const char *filename = strrchr (file, '/'); | 
|---|
| 1189 |  | 
|---|
| 1190 | #ifdef HAVE_DOS_BASED_FILE_SYSTEM | 
|---|
| 1191 | { | 
|---|
| 1192 | /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */ | 
|---|
| 1193 | char *bslash = strrchr (file, '\\'); | 
|---|
| 1194 | if (filename == NULL || (bslash != NULL && bslash > filename)) | 
|---|
| 1195 | filename = bslash; | 
|---|
| 1196 | if (filename == NULL && file[0] != '\0' && file[1] == ':') | 
|---|
| 1197 | filename = file + 1; | 
|---|
| 1198 | } | 
|---|
| 1199 | #endif | 
|---|
| 1200 | if (filename != (char *) NULL) | 
|---|
| 1201 | filename++; | 
|---|
| 1202 | else | 
|---|
| 1203 | filename = file; | 
|---|
| 1204 | return filename; | 
|---|
| 1205 | } | 
|---|
| 1206 | #endif | 
|---|
| 1207 |  | 
|---|
| 1208 | /* Build a BFD style extended name table.  */ | 
|---|
| 1209 |  | 
|---|
| 1210 | bfd_boolean | 
|---|
| 1211 | _bfd_archive_bsd_construct_extended_name_table (abfd, tabloc, tablen, name) | 
|---|
| 1212 | bfd *abfd; | 
|---|
| 1213 | char **tabloc; | 
|---|
| 1214 | bfd_size_type *tablen; | 
|---|
| 1215 | const char **name; | 
|---|
| 1216 | { | 
|---|
| 1217 | *name = "ARFILENAMES/"; | 
|---|
| 1218 | return _bfd_construct_extended_name_table (abfd, FALSE, tabloc, tablen); | 
|---|
| 1219 | } | 
|---|
| 1220 |  | 
|---|
| 1221 | /* Build an SVR4 style extended name table.  */ | 
|---|
| 1222 |  | 
|---|
| 1223 | bfd_boolean | 
|---|
| 1224 | _bfd_archive_coff_construct_extended_name_table (abfd, tabloc, tablen, name) | 
|---|
| 1225 | bfd *abfd; | 
|---|
| 1226 | char **tabloc; | 
|---|
| 1227 | bfd_size_type *tablen; | 
|---|
| 1228 | const char **name; | 
|---|
| 1229 | { | 
|---|
| 1230 | *name = "//"; | 
|---|
| 1231 | return _bfd_construct_extended_name_table (abfd, TRUE, tabloc, tablen); | 
|---|
| 1232 | } | 
|---|
| 1233 |  | 
|---|
| 1234 | /* Follows archive_head and produces an extended name table if | 
|---|
| 1235 | necessary.  Returns (in tabloc) a pointer to an extended name | 
|---|
| 1236 | table, and in tablen the length of the table.  If it makes an entry | 
|---|
| 1237 | it clobbers the filename so that the element may be written without | 
|---|
| 1238 | further massage.  Returns TRUE if it ran successfully, FALSE if | 
|---|
| 1239 | something went wrong.  A successful return may still involve a | 
|---|
| 1240 | zero-length tablen!  */ | 
|---|
| 1241 |  | 
|---|
| 1242 | bfd_boolean | 
|---|
| 1243 | _bfd_construct_extended_name_table (abfd, trailing_slash, tabloc, tablen) | 
|---|
| 1244 | bfd *abfd; | 
|---|
| 1245 | bfd_boolean trailing_slash; | 
|---|
| 1246 | char **tabloc; | 
|---|
| 1247 | bfd_size_type *tablen; | 
|---|
| 1248 | { | 
|---|
| 1249 | unsigned int maxname = abfd->xvec->ar_max_namelen; | 
|---|
| 1250 | bfd_size_type total_namelen = 0; | 
|---|
| 1251 | bfd *current; | 
|---|
| 1252 | char *strptr; | 
|---|
| 1253 |  | 
|---|
| 1254 | *tablen = 0; | 
|---|
| 1255 |  | 
|---|
| 1256 | /* Figure out how long the table should be.  */ | 
|---|
| 1257 | for (current = abfd->archive_head; current != NULL; current = current->next) | 
|---|
| 1258 | { | 
|---|
| 1259 | const char *normal; | 
|---|
| 1260 | unsigned int thislen; | 
|---|
| 1261 |  | 
|---|
| 1262 | normal = normalize (current, current->filename); | 
|---|
| 1263 | if (normal == NULL) | 
|---|
| 1264 | return FALSE; | 
|---|
| 1265 |  | 
|---|
| 1266 | thislen = strlen (normal); | 
|---|
| 1267 |  | 
|---|
| 1268 | if (thislen > maxname | 
|---|
| 1269 | && (bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0) | 
|---|
| 1270 | thislen = maxname; | 
|---|
| 1271 |  | 
|---|
| 1272 | if (thislen > maxname) | 
|---|
| 1273 | { | 
|---|
| 1274 | /* Add one to leave room for \n.  */ | 
|---|
| 1275 | total_namelen += thislen + 1; | 
|---|
| 1276 | if (trailing_slash) | 
|---|
| 1277 | { | 
|---|
| 1278 | /* Leave room for trailing slash.  */ | 
|---|
| 1279 | ++total_namelen; | 
|---|
| 1280 | } | 
|---|
| 1281 | } | 
|---|
| 1282 | else | 
|---|
| 1283 | { | 
|---|
| 1284 | struct ar_hdr *hdr = arch_hdr (current); | 
|---|
| 1285 | if (strncmp (normal, hdr->ar_name, thislen) != 0 | 
|---|
| 1286 | || (thislen < sizeof hdr->ar_name | 
|---|
| 1287 | && hdr->ar_name[thislen] != ar_padchar (current))) | 
|---|
| 1288 | { | 
|---|
| 1289 | /* Must have been using extended format even though it | 
|---|
| 1290 | didn't need to.  Fix it to use normal format.  */ | 
|---|
| 1291 | memcpy (hdr->ar_name, normal, thislen); | 
|---|
| 1292 | if (thislen < maxname | 
|---|
| 1293 | || (thislen == maxname && thislen < sizeof hdr->ar_name)) | 
|---|
| 1294 | hdr->ar_name[thislen] = ar_padchar (current); | 
|---|
| 1295 | } | 
|---|
| 1296 | } | 
|---|
| 1297 | } | 
|---|
| 1298 |  | 
|---|
| 1299 | if (total_namelen == 0) | 
|---|
| 1300 | return TRUE; | 
|---|
| 1301 |  | 
|---|
| 1302 | *tabloc = bfd_zalloc (abfd, total_namelen); | 
|---|
| 1303 | if (*tabloc == NULL) | 
|---|
| 1304 | return FALSE; | 
|---|
| 1305 |  | 
|---|
| 1306 | *tablen = total_namelen; | 
|---|
| 1307 | strptr = *tabloc; | 
|---|
| 1308 |  | 
|---|
| 1309 | for (current = abfd->archive_head; current != NULL; current = | 
|---|
| 1310 | current->next) | 
|---|
| 1311 | { | 
|---|
| 1312 | const char *normal; | 
|---|
| 1313 | unsigned int thislen; | 
|---|
| 1314 |  | 
|---|
| 1315 | normal = normalize (current, current->filename); | 
|---|
| 1316 | if (normal == NULL) | 
|---|
| 1317 | return FALSE; | 
|---|
| 1318 |  | 
|---|
| 1319 | thislen = strlen (normal); | 
|---|
| 1320 | if (thislen > maxname) | 
|---|
| 1321 | { | 
|---|
| 1322 | /* Works for now; may need to be re-engineered if we | 
|---|
| 1323 | encounter an oddball archive format and want to | 
|---|
| 1324 | generalise this hack.  */ | 
|---|
| 1325 | struct ar_hdr *hdr = arch_hdr (current); | 
|---|
| 1326 | strcpy (strptr, normal); | 
|---|
| 1327 | if (! trailing_slash) | 
|---|
| 1328 | strptr[thislen] = '\012'; | 
|---|
| 1329 | else | 
|---|
| 1330 | { | 
|---|
| 1331 | strptr[thislen] = '/'; | 
|---|
| 1332 | strptr[thislen + 1] = '\012'; | 
|---|
| 1333 | } | 
|---|
| 1334 | hdr->ar_name[0] = ar_padchar (current); | 
|---|
| 1335 | /* We know there will always be enough room (one of the few | 
|---|
| 1336 | cases where you may safely use sprintf).  */ | 
|---|
| 1337 | sprintf ((hdr->ar_name) + 1, "%-d", (unsigned) (strptr - *tabloc)); | 
|---|
| 1338 | /* Kinda Kludgy.  We should just use the returned value of | 
|---|
| 1339 | sprintf but not all implementations get this right.  */ | 
|---|
| 1340 | { | 
|---|
| 1341 | char *temp = hdr->ar_name + 2; | 
|---|
| 1342 | for (; temp < hdr->ar_name + maxname; temp++) | 
|---|
| 1343 | if (*temp == '\0') | 
|---|
| 1344 | *temp = ' '; | 
|---|
| 1345 | } | 
|---|
| 1346 | strptr += thislen + 1; | 
|---|
| 1347 | if (trailing_slash) | 
|---|
| 1348 | ++strptr; | 
|---|
| 1349 | } | 
|---|
| 1350 | } | 
|---|
| 1351 |  | 
|---|
| 1352 | return TRUE; | 
|---|
| 1353 | } | 
|---|
| 1354 |  | 
|---|
| 1355 |  | 
|---|
| 1356 | /** A couple of functions for creating ar_hdrs */ | 
|---|
| 1357 |  | 
|---|
| 1358 | #ifdef HPUX_LARGE_AR_IDS | 
|---|
| 1359 | /* Function to encode large UID/GID values according to HP.  */ | 
|---|
| 1360 |  | 
|---|
| 1361 | static void | 
|---|
| 1362 | hpux_uid_gid_encode (str, id) | 
|---|
| 1363 | char str[6]; | 
|---|
| 1364 | long int id; | 
|---|
| 1365 | { | 
|---|
| 1366 | int cnt; | 
|---|
| 1367 |  | 
|---|
| 1368 | str[5] = '@' + (id & 3); | 
|---|
| 1369 | id >>= 2; | 
|---|
| 1370 |  | 
|---|
| 1371 | for (cnt = 4; cnt >= 0; ++cnt, id >>= 6) | 
|---|
| 1372 | str[cnt] = ' ' + (id & 0x3f); | 
|---|
| 1373 | } | 
|---|
| 1374 | #endif  /* HPUX_LARGE_AR_IDS */ | 
|---|
| 1375 |  | 
|---|
| 1376 | #ifndef HAVE_GETUID | 
|---|
| 1377 | #define getuid() 0 | 
|---|
| 1378 | #endif | 
|---|
| 1379 |  | 
|---|
| 1380 | #ifndef HAVE_GETGID | 
|---|
| 1381 | #define getgid() 0 | 
|---|
| 1382 | #endif | 
|---|
| 1383 |  | 
|---|
| 1384 | /* Takes a filename, returns an arelt_data for it, or NULL if it can't | 
|---|
| 1385 | make one.  The filename must refer to a filename in the filesystem. | 
|---|
| 1386 | The filename field of the ar_hdr will NOT be initialized.  If member | 
|---|
| 1387 | is set, and it's an in-memory bfd, we fake it.  */ | 
|---|
| 1388 |  | 
|---|
| 1389 | static struct areltdata * | 
|---|
| 1390 | bfd_ar_hdr_from_filesystem (abfd, filename, member) | 
|---|
| 1391 | bfd *abfd; | 
|---|
| 1392 | const char *filename; | 
|---|
| 1393 | bfd *member; | 
|---|
| 1394 | { | 
|---|
| 1395 | struct stat status; | 
|---|
| 1396 | struct areltdata *ared; | 
|---|
| 1397 | struct ar_hdr *hdr; | 
|---|
| 1398 | char *temp, *temp1; | 
|---|
| 1399 | bfd_size_type amt; | 
|---|
| 1400 |  | 
|---|
| 1401 | if (member && (member->flags & BFD_IN_MEMORY) != 0) | 
|---|
| 1402 | { | 
|---|
| 1403 | /* Assume we just "made" the member, and fake it.  */ | 
|---|
| 1404 | struct bfd_in_memory *bim = (struct bfd_in_memory *) member->iostream; | 
|---|
| 1405 | time (&status.st_mtime); | 
|---|
| 1406 | status.st_uid = getuid (); | 
|---|
| 1407 | status.st_gid = getgid (); | 
|---|
| 1408 | status.st_mode = 0644; | 
|---|
| 1409 | status.st_size = bim->size; | 
|---|
| 1410 | } | 
|---|
| 1411 | else if (stat (filename, &status) != 0) | 
|---|
| 1412 | { | 
|---|
| 1413 | bfd_set_error (bfd_error_system_call); | 
|---|
| 1414 | return NULL; | 
|---|
| 1415 | } | 
|---|
| 1416 |  | 
|---|
| 1417 | amt = sizeof (struct ar_hdr) + sizeof (struct areltdata); | 
|---|
| 1418 | ared = (struct areltdata *) bfd_zalloc (abfd, amt); | 
|---|
| 1419 | if (ared == NULL) | 
|---|
| 1420 | return NULL; | 
|---|
| 1421 | hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata)); | 
|---|
| 1422 |  | 
|---|
| 1423 | /* ar headers are space padded, not null padded!  */ | 
|---|
| 1424 | memset ((PTR) hdr, ' ', sizeof (struct ar_hdr)); | 
|---|
| 1425 |  | 
|---|
| 1426 | strncpy (hdr->ar_fmag, ARFMAG, 2); | 
|---|
| 1427 |  | 
|---|
| 1428 | /* Goddamned sprintf doesn't permit MAXIMUM field lengths.  */ | 
|---|
| 1429 | sprintf ((hdr->ar_date), "%-12ld", (long) status.st_mtime); | 
|---|
| 1430 | #ifdef HPUX_LARGE_AR_IDS | 
|---|
| 1431 | /* HP has a very "special" way to handle UID/GID's with numeric values | 
|---|
| 1432 | > 99999.  */ | 
|---|
| 1433 | if (status.st_uid > 99999) | 
|---|
| 1434 | hpux_uid_gid_encode (hdr->ar_gid, (long) status.st_uid); | 
|---|
| 1435 | else | 
|---|
| 1436 | #endif | 
|---|
| 1437 | sprintf ((hdr->ar_uid), "%ld", (long) status.st_uid); | 
|---|
| 1438 | #ifdef HPUX_LARGE_AR_IDS | 
|---|
| 1439 | /* HP has a very "special" way to handle UID/GID's with numeric values | 
|---|
| 1440 | > 99999.  */ | 
|---|
| 1441 | if (status.st_gid > 99999) | 
|---|
| 1442 | hpux_uid_gid_encode (hdr->ar_uid, (long) status.st_gid); | 
|---|
| 1443 | else | 
|---|
| 1444 | #endif | 
|---|
| 1445 | sprintf ((hdr->ar_gid), "%ld", (long) status.st_gid); | 
|---|
| 1446 | sprintf ((hdr->ar_mode), "%-8o", (unsigned int) status.st_mode); | 
|---|
| 1447 | sprintf ((hdr->ar_size), "%-10ld", (long) status.st_size); | 
|---|
| 1448 | /* Correct for a lossage in sprintf whereby it null-terminates.  I cannot | 
|---|
| 1449 | understand how these C losers could design such a ramshackle bunch of | 
|---|
| 1450 | IO operations.  */ | 
|---|
| 1451 | temp = (char *) hdr; | 
|---|
| 1452 | temp1 = temp + sizeof (struct ar_hdr) - 2; | 
|---|
| 1453 | for (; temp < temp1; temp++) | 
|---|
| 1454 | { | 
|---|
| 1455 | if (*temp == '\0') | 
|---|
| 1456 | *temp = ' '; | 
|---|
| 1457 | } | 
|---|
| 1458 | strncpy (hdr->ar_fmag, ARFMAG, 2); | 
|---|
| 1459 | ared->parsed_size = status.st_size; | 
|---|
| 1460 | ared->arch_header = (char *) hdr; | 
|---|
| 1461 |  | 
|---|
| 1462 | return ared; | 
|---|
| 1463 | } | 
|---|
| 1464 |  | 
|---|
| 1465 | /* This is magic required by the "ar" program.  Since it's | 
|---|
| 1466 | undocumented, it's undocumented.  You may think that it would take | 
|---|
| 1467 | a strong stomach to write this, and it does, but it takes even a | 
|---|
| 1468 | stronger stomach to try to code around such a thing!  */ | 
|---|
| 1469 |  | 
|---|
| 1470 | struct ar_hdr *bfd_special_undocumented_glue | 
|---|
| 1471 | PARAMS ((bfd *, const char *)); | 
|---|
| 1472 |  | 
|---|
| 1473 | struct ar_hdr * | 
|---|
| 1474 | bfd_special_undocumented_glue (abfd, filename) | 
|---|
| 1475 | bfd *abfd; | 
|---|
| 1476 | const char *filename; | 
|---|
| 1477 | { | 
|---|
| 1478 | struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename, 0); | 
|---|
| 1479 | if (ar_elt == NULL) | 
|---|
| 1480 | return NULL; | 
|---|
| 1481 | return (struct ar_hdr *) ar_elt->arch_header; | 
|---|
| 1482 | } | 
|---|
| 1483 |  | 
|---|
| 1484 | /* Analogous to stat call.  */ | 
|---|
| 1485 |  | 
|---|
| 1486 | int | 
|---|
| 1487 | bfd_generic_stat_arch_elt (abfd, buf) | 
|---|
| 1488 | bfd *abfd; | 
|---|
| 1489 | struct stat *buf; | 
|---|
| 1490 | { | 
|---|
| 1491 | struct ar_hdr *hdr; | 
|---|
| 1492 | char *aloser; | 
|---|
| 1493 |  | 
|---|
| 1494 | if (abfd->arelt_data == NULL) | 
|---|
| 1495 | { | 
|---|
| 1496 | bfd_set_error (bfd_error_invalid_operation); | 
|---|
| 1497 | return -1; | 
|---|
| 1498 | } | 
|---|
| 1499 |  | 
|---|
| 1500 | hdr = arch_hdr (abfd); | 
|---|
| 1501 |  | 
|---|
| 1502 | #define foo(arelt, stelt, size)                         \ | 
|---|
| 1503 | buf->stelt = strtol (hdr->arelt, &aloser, size);      \ | 
|---|
| 1504 | if (aloser == hdr->arelt)                             \ | 
|---|
| 1505 | return -1; | 
|---|
| 1506 |  | 
|---|
| 1507 | /* Some platforms support special notations for large IDs.  */ | 
|---|
| 1508 | #ifdef HPUX_LARGE_AR_IDS | 
|---|
| 1509 | # define foo2(arelt, stelt, size)                                       \ | 
|---|
| 1510 | if (hdr->arelt[5] == ' ')                                             \ | 
|---|
| 1511 | {                                                                   \ | 
|---|
| 1512 | foo (arelt, stelt, size);                                         \ | 
|---|
| 1513 | }                                                                   \ | 
|---|
| 1514 | else                                                                  \ | 
|---|
| 1515 | {                                                                   \ | 
|---|
| 1516 | int cnt;                                                          \ | 
|---|
| 1517 | for (buf->stelt = cnt = 0; cnt < 5; ++cnt)                        \ | 
|---|
| 1518 | {                                                               \ | 
|---|
| 1519 | if (hdr->arelt[cnt] < ' ' || hdr->arelt[cnt] > ' ' + 0x3f)    \ | 
|---|
| 1520 | return -1;                                                  \ | 
|---|
| 1521 | buf->stelt <<= 6;                                             \ | 
|---|
| 1522 | buf->stelt += hdr->arelt[cnt] - ' ';                          \ | 
|---|
| 1523 | }                                                               \ | 
|---|
| 1524 | if (hdr->arelt[5] < '@' || hdr->arelt[5] > '@' + 3)               \ | 
|---|
| 1525 | return -1;                                                      \ | 
|---|
| 1526 | buf->stelt <<= 2;                                                 \ | 
|---|
| 1527 | buf->stelt += hdr->arelt[5] - '@';                                \ | 
|---|
| 1528 | } | 
|---|
| 1529 | #else | 
|---|
| 1530 | # define foo2(arelt, stelt, size) foo (arelt, stelt, size) | 
|---|
| 1531 | #endif | 
|---|
| 1532 |  | 
|---|
| 1533 | foo (ar_date, st_mtime, 10); | 
|---|
| 1534 | foo2 (ar_uid, st_uid, 10); | 
|---|
| 1535 | foo2 (ar_gid, st_gid, 10); | 
|---|
| 1536 | foo (ar_mode, st_mode, 8); | 
|---|
| 1537 |  | 
|---|
| 1538 | buf->st_size = arch_eltdata (abfd)->parsed_size; | 
|---|
| 1539 |  | 
|---|
| 1540 | return 0; | 
|---|
| 1541 | } | 
|---|
| 1542 |  | 
|---|
| 1543 | void | 
|---|
| 1544 | bfd_dont_truncate_arname (abfd, pathname, arhdr) | 
|---|
| 1545 | bfd *abfd; | 
|---|
| 1546 | const char *pathname; | 
|---|
| 1547 | char *arhdr; | 
|---|
| 1548 | { | 
|---|
| 1549 | /* FIXME: This interacts unpleasantly with ar's quick-append option. | 
|---|
| 1550 | Fortunately ic960 users will never use that option.  Fixing this | 
|---|
| 1551 | is very hard; fortunately I know how to do it and will do so once | 
|---|
| 1552 | intel's release is out the door.  */ | 
|---|
| 1553 |  | 
|---|
| 1554 | struct ar_hdr *hdr = (struct ar_hdr *) arhdr; | 
|---|
| 1555 | size_t length; | 
|---|
| 1556 | const char *filename; | 
|---|
| 1557 | size_t maxlen = ar_maxnamelen (abfd); | 
|---|
| 1558 |  | 
|---|
| 1559 | if ((bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0) | 
|---|
| 1560 | { | 
|---|
| 1561 | bfd_bsd_truncate_arname (abfd, pathname, arhdr); | 
|---|
| 1562 | return; | 
|---|
| 1563 | } | 
|---|
| 1564 |  | 
|---|
| 1565 | filename = normalize (abfd, pathname); | 
|---|
| 1566 | if (filename == NULL) | 
|---|
| 1567 | { | 
|---|
| 1568 | /* FIXME */ | 
|---|
| 1569 | abort (); | 
|---|
| 1570 | } | 
|---|
| 1571 |  | 
|---|
| 1572 | length = strlen (filename); | 
|---|
| 1573 |  | 
|---|
| 1574 | if (length <= maxlen) | 
|---|
| 1575 | memcpy (hdr->ar_name, filename, length); | 
|---|
| 1576 |  | 
|---|
| 1577 | /* Add the padding character if there is room for it.  */ | 
|---|
| 1578 | if (length < maxlen | 
|---|
| 1579 | || (length == maxlen && length < sizeof hdr->ar_name)) | 
|---|
| 1580 | (hdr->ar_name)[length] = ar_padchar (abfd); | 
|---|
| 1581 | } | 
|---|
| 1582 |  | 
|---|
| 1583 | void | 
|---|
| 1584 | bfd_bsd_truncate_arname (abfd, pathname, arhdr) | 
|---|
| 1585 | bfd *abfd; | 
|---|
| 1586 | const char *pathname; | 
|---|
| 1587 | char *arhdr; | 
|---|
| 1588 | { | 
|---|
| 1589 | struct ar_hdr *hdr = (struct ar_hdr *) arhdr; | 
|---|
| 1590 | size_t length; | 
|---|
| 1591 | const char *filename = strrchr (pathname, '/'); | 
|---|
| 1592 | size_t maxlen = ar_maxnamelen (abfd); | 
|---|
| 1593 |  | 
|---|
| 1594 | #ifdef HAVE_DOS_BASED_FILE_SYSTEM | 
|---|
| 1595 | { | 
|---|
| 1596 | /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */ | 
|---|
| 1597 | char *bslash = strrchr (pathname, '\\'); | 
|---|
| 1598 | if (filename == NULL || (bslash != NULL && bslash > filename)) | 
|---|
| 1599 | filename = bslash; | 
|---|
| 1600 | if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':') | 
|---|
| 1601 | filename = pathname + 1; | 
|---|
| 1602 | } | 
|---|
| 1603 | #endif | 
|---|
| 1604 |  | 
|---|
| 1605 | if (filename == NULL) | 
|---|
| 1606 | filename = pathname; | 
|---|
| 1607 | else | 
|---|
| 1608 | ++filename; | 
|---|
| 1609 |  | 
|---|
| 1610 | length = strlen (filename); | 
|---|
| 1611 |  | 
|---|
| 1612 | if (length <= maxlen) | 
|---|
| 1613 | memcpy (hdr->ar_name, filename, length); | 
|---|
| 1614 | else | 
|---|
| 1615 | { | 
|---|
| 1616 | /* pathname: meet procrustes */ | 
|---|
| 1617 | memcpy (hdr->ar_name, filename, maxlen); | 
|---|
| 1618 | length = maxlen; | 
|---|
| 1619 | } | 
|---|
| 1620 |  | 
|---|
| 1621 | if (length < maxlen) | 
|---|
| 1622 | (hdr->ar_name)[length] = ar_padchar (abfd); | 
|---|
| 1623 | } | 
|---|
| 1624 |  | 
|---|
| 1625 | /* Store name into ar header.  Truncates the name to fit. | 
|---|
| 1626 | 1> strip pathname to be just the basename. | 
|---|
| 1627 | 2> if it's short enuf to fit, stuff it in. | 
|---|
| 1628 | 3> If it doesn't end with .o, truncate it to fit | 
|---|
| 1629 | 4> truncate it before the .o, append .o, stuff THAT in.  */ | 
|---|
| 1630 |  | 
|---|
| 1631 | /* This is what gnu ar does.  It's better but incompatible with the | 
|---|
| 1632 | bsd ar.  */ | 
|---|
| 1633 |  | 
|---|
| 1634 | void | 
|---|
| 1635 | bfd_gnu_truncate_arname (abfd, pathname, arhdr) | 
|---|
| 1636 | bfd *abfd; | 
|---|
| 1637 | const char *pathname; | 
|---|
| 1638 | char *arhdr; | 
|---|
| 1639 | { | 
|---|
| 1640 | struct ar_hdr *hdr = (struct ar_hdr *) arhdr; | 
|---|
| 1641 | size_t length; | 
|---|
| 1642 | const char *filename = strrchr (pathname, '/'); | 
|---|
| 1643 | size_t maxlen = ar_maxnamelen (abfd); | 
|---|
| 1644 |  | 
|---|
| 1645 | #ifdef HAVE_DOS_BASED_FILE_SYSTEM | 
|---|
| 1646 | { | 
|---|
| 1647 | /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */ | 
|---|
| 1648 | char *bslash = strrchr (pathname, '\\'); | 
|---|
| 1649 | if (filename == NULL || (bslash != NULL && bslash > filename)) | 
|---|
| 1650 | filename = bslash; | 
|---|
| 1651 | if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':') | 
|---|
| 1652 | filename = pathname + 1; | 
|---|
| 1653 | } | 
|---|
| 1654 | #endif | 
|---|
| 1655 |  | 
|---|
| 1656 | if (filename == NULL) | 
|---|
| 1657 | filename = pathname; | 
|---|
| 1658 | else | 
|---|
| 1659 | ++filename; | 
|---|
| 1660 |  | 
|---|
| 1661 | length = strlen (filename); | 
|---|
| 1662 |  | 
|---|
| 1663 | if (length <= maxlen) | 
|---|
| 1664 | memcpy (hdr->ar_name, filename, length); | 
|---|
| 1665 | else | 
|---|
| 1666 | {                           /* pathname: meet procrustes */ | 
|---|
| 1667 | memcpy (hdr->ar_name, filename, maxlen); | 
|---|
| 1668 | if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) | 
|---|
| 1669 | { | 
|---|
| 1670 | hdr->ar_name[maxlen - 2] = '.'; | 
|---|
| 1671 | hdr->ar_name[maxlen - 1] = 'o'; | 
|---|
| 1672 | } | 
|---|
| 1673 | length = maxlen; | 
|---|
| 1674 | } | 
|---|
| 1675 |  | 
|---|
| 1676 | if (length < 16) | 
|---|
| 1677 | (hdr->ar_name)[length] = ar_padchar (abfd); | 
|---|
| 1678 | } | 
|---|
| 1679 |  | 
|---|
| 1680 |  | 
|---|
| 1681 | /* The BFD is open for write and has its format set to bfd_archive.  */ | 
|---|
| 1682 |  | 
|---|
| 1683 | bfd_boolean | 
|---|
| 1684 | _bfd_write_archive_contents (arch) | 
|---|
| 1685 | bfd *arch; | 
|---|
| 1686 | { | 
|---|
| 1687 | bfd *current; | 
|---|
| 1688 | char *etable = NULL; | 
|---|
| 1689 | bfd_size_type elength = 0; | 
|---|
| 1690 | const char *ename = NULL; | 
|---|
| 1691 | bfd_boolean makemap = bfd_has_map (arch); | 
|---|
| 1692 | /* If no .o's, don't bother to make a map.  */ | 
|---|
| 1693 | bfd_boolean hasobjects = FALSE; | 
|---|
| 1694 | bfd_size_type wrote; | 
|---|
| 1695 | unsigned int i; | 
|---|
| 1696 | int tries; | 
|---|
| 1697 |  | 
|---|
| 1698 | /* Verify the viability of all entries; if any of them live in the | 
|---|
| 1699 | filesystem (as opposed to living in an archive open for input) | 
|---|
| 1700 | then construct a fresh ar_hdr for them.  */ | 
|---|
| 1701 | for (current = arch->archive_head; current; current = current->next) | 
|---|
| 1702 | { | 
|---|
| 1703 | /* This check is checking the bfds for the objects we're reading | 
|---|
| 1704 | from (which are usually either an object file or archive on | 
|---|
| 1705 | disk), not the archive entries we're writing to.  We don't | 
|---|
| 1706 | actually create bfds for the archive members, we just copy | 
|---|
| 1707 | them byte-wise when we write out the archive.  */ | 
|---|
| 1708 | if (bfd_write_p (current)) | 
|---|
| 1709 | { | 
|---|
| 1710 | bfd_set_error (bfd_error_invalid_operation); | 
|---|
| 1711 | return FALSE; | 
|---|
| 1712 | } | 
|---|
| 1713 | if (!current->arelt_data) | 
|---|
| 1714 | { | 
|---|
| 1715 | current->arelt_data = | 
|---|
| 1716 | (PTR) bfd_ar_hdr_from_filesystem (arch, current->filename, current); | 
|---|
| 1717 | if (!current->arelt_data) | 
|---|
| 1718 | return FALSE; | 
|---|
| 1719 |  | 
|---|
| 1720 | /* Put in the file name.  */ | 
|---|
| 1721 | BFD_SEND (arch, _bfd_truncate_arname, (arch, | 
|---|
| 1722 | current->filename, | 
|---|
| 1723 | (char *) arch_hdr (current))); | 
|---|
| 1724 | } | 
|---|
| 1725 |  | 
|---|
| 1726 | if (makemap && ! hasobjects) | 
|---|
| 1727 | {                       /* Don't bother if we won't make a map!  */ | 
|---|
| 1728 | if ((bfd_check_format (current, bfd_object)) | 
|---|
| 1729 | #if 0                           /* FIXME -- these are not set correctly */ | 
|---|
| 1730 | && ((bfd_get_file_flags (current) & HAS_SYMS)) | 
|---|
| 1731 | #endif | 
|---|
| 1732 | ) | 
|---|
| 1733 | hasobjects = TRUE; | 
|---|
| 1734 | } | 
|---|
| 1735 | } | 
|---|
| 1736 |  | 
|---|
| 1737 | if (!BFD_SEND (arch, _bfd_construct_extended_name_table, | 
|---|
| 1738 | (arch, &etable, &elength, &ename))) | 
|---|
| 1739 | return FALSE; | 
|---|
| 1740 |  | 
|---|
| 1741 | if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0) | 
|---|
| 1742 | return FALSE; | 
|---|
| 1743 | #ifdef GNU960 | 
|---|
| 1744 | wrote = bfd_bwrite (BFD_GNU960_ARMAG (arch), (bfd_size_type) SARMAG, arch); | 
|---|
| 1745 | #else | 
|---|
| 1746 | wrote = bfd_bwrite (ARMAG, (bfd_size_type) SARMAG, arch); | 
|---|
| 1747 | #endif | 
|---|
| 1748 | if (wrote != SARMAG) | 
|---|
| 1749 | return FALSE; | 
|---|
| 1750 |  | 
|---|
| 1751 | if (makemap && hasobjects) | 
|---|
| 1752 | { | 
|---|
| 1753 | if (! _bfd_compute_and_write_armap (arch, (unsigned int) elength)) | 
|---|
| 1754 | return FALSE; | 
|---|
| 1755 | } | 
|---|
| 1756 |  | 
|---|
| 1757 | if (elength != 0) | 
|---|
| 1758 | { | 
|---|
| 1759 | struct ar_hdr hdr; | 
|---|
| 1760 |  | 
|---|
| 1761 | memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); | 
|---|
| 1762 | strcpy (hdr.ar_name, ename); | 
|---|
| 1763 | /* Round size up to even number in archive header.  */ | 
|---|
| 1764 | sprintf (&(hdr.ar_size[0]), "%-10d", | 
|---|
| 1765 | (int) ((elength + 1) & ~(bfd_size_type) 1)); | 
|---|
| 1766 | strncpy (hdr.ar_fmag, ARFMAG, 2); | 
|---|
| 1767 | for (i = 0; i < sizeof (struct ar_hdr); i++) | 
|---|
| 1768 | if (((char *) (&hdr))[i] == '\0') | 
|---|
| 1769 | (((char *) (&hdr))[i]) = ' '; | 
|---|
| 1770 | if ((bfd_bwrite ((PTR) &hdr, (bfd_size_type) sizeof (struct ar_hdr), arch) | 
|---|
| 1771 | != sizeof (struct ar_hdr)) | 
|---|
| 1772 | || bfd_bwrite (etable, elength, arch) != elength) | 
|---|
| 1773 | return FALSE; | 
|---|
| 1774 | if ((elength % 2) == 1) | 
|---|
| 1775 | { | 
|---|
| 1776 | if (bfd_bwrite ("\012", (bfd_size_type) 1, arch) != 1) | 
|---|
| 1777 | return FALSE; | 
|---|
| 1778 | } | 
|---|
| 1779 | } | 
|---|
| 1780 |  | 
|---|
| 1781 | for (current = arch->archive_head; current; current = current->next) | 
|---|
| 1782 | { | 
|---|
| 1783 | char buffer[DEFAULT_BUFFERSIZE]; | 
|---|
| 1784 | unsigned int remaining = arelt_size (current); | 
|---|
| 1785 | struct ar_hdr *hdr = arch_hdr (current); | 
|---|
| 1786 |  | 
|---|
| 1787 | /* Write ar header.  */ | 
|---|
| 1788 | if (bfd_bwrite ((PTR) hdr, (bfd_size_type) sizeof (*hdr), arch) | 
|---|
| 1789 | != sizeof (*hdr)) | 
|---|
| 1790 | return FALSE; | 
|---|
| 1791 | if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0) | 
|---|
| 1792 | return FALSE; | 
|---|
| 1793 | while (remaining) | 
|---|
| 1794 | { | 
|---|
| 1795 | unsigned int amt = DEFAULT_BUFFERSIZE; | 
|---|
| 1796 | if (amt > remaining) | 
|---|
| 1797 | amt = remaining; | 
|---|
| 1798 | errno = 0; | 
|---|
| 1799 | if (bfd_bread (buffer, (bfd_size_type) amt, current) != amt) | 
|---|
| 1800 | { | 
|---|
| 1801 | if (bfd_get_error () != bfd_error_system_call) | 
|---|
| 1802 | bfd_set_error (bfd_error_malformed_archive); | 
|---|
| 1803 | return FALSE; | 
|---|
| 1804 | } | 
|---|
| 1805 | if (bfd_bwrite (buffer, (bfd_size_type) amt, arch) != amt) | 
|---|
| 1806 | return FALSE; | 
|---|
| 1807 | remaining -= amt; | 
|---|
| 1808 | } | 
|---|
| 1809 | if ((arelt_size (current) % 2) == 1) | 
|---|
| 1810 | { | 
|---|
| 1811 | if (bfd_bwrite ("\012", (bfd_size_type) 1, arch) != 1) | 
|---|
| 1812 | return FALSE; | 
|---|
| 1813 | } | 
|---|
| 1814 | } | 
|---|
| 1815 |  | 
|---|
| 1816 | if (makemap && hasobjects) | 
|---|
| 1817 | { | 
|---|
| 1818 | /* Verify the timestamp in the archive file.  If it would not be | 
|---|
| 1819 | accepted by the linker, rewrite it until it would be.  If | 
|---|
| 1820 | anything odd happens, break out and just return.  (The | 
|---|
| 1821 | Berkeley linker checks the timestamp and refuses to read the | 
|---|
| 1822 | table-of-contents if it is >60 seconds less than the file's | 
|---|
| 1823 | modified-time.  That painful hack requires this painful hack.  */ | 
|---|
| 1824 | tries = 1; | 
|---|
| 1825 | do | 
|---|
| 1826 | { | 
|---|
| 1827 | if (bfd_update_armap_timestamp (arch)) | 
|---|
| 1828 | break; | 
|---|
| 1829 | (*_bfd_error_handler) | 
|---|
| 1830 | (_("Warning: writing archive was slow: rewriting timestamp\n")); | 
|---|
| 1831 | } | 
|---|
| 1832 | while (++tries < 6); | 
|---|
| 1833 | } | 
|---|
| 1834 |  | 
|---|
| 1835 | return TRUE; | 
|---|
| 1836 | } | 
|---|
| 1837 |  | 
|---|
| 1838 |  | 
|---|
| 1839 | /* Note that the namidx for the first symbol is 0.  */ | 
|---|
| 1840 |  | 
|---|
| 1841 | bfd_boolean | 
|---|
| 1842 | _bfd_compute_and_write_armap (arch, elength) | 
|---|
| 1843 | bfd *arch; | 
|---|
| 1844 | unsigned int elength; | 
|---|
| 1845 | { | 
|---|
| 1846 | char *first_name = NULL; | 
|---|
| 1847 | bfd *current; | 
|---|
| 1848 | file_ptr elt_no = 0; | 
|---|
| 1849 | struct orl *map = NULL; | 
|---|
| 1850 | unsigned int orl_max = 1024;          /* fine initial default */ | 
|---|
| 1851 | unsigned int orl_count = 0; | 
|---|
| 1852 | int stridx = 0;               /* string index */ | 
|---|
| 1853 | asymbol **syms = NULL; | 
|---|
| 1854 | long syms_max = 0; | 
|---|
| 1855 | bfd_boolean ret; | 
|---|
| 1856 | bfd_size_type amt; | 
|---|
| 1857 |  | 
|---|
| 1858 | /* Dunno if this is the best place for this info...  */ | 
|---|
| 1859 | if (elength != 0) | 
|---|
| 1860 | elength += sizeof (struct ar_hdr); | 
|---|
| 1861 | elength += elength % 2; | 
|---|
| 1862 |  | 
|---|
| 1863 | amt = (bfd_size_type) orl_max * sizeof (struct orl); | 
|---|
| 1864 | map = (struct orl *) bfd_malloc (amt); | 
|---|
| 1865 | if (map == NULL) | 
|---|
| 1866 | goto error_return; | 
|---|
| 1867 |  | 
|---|
| 1868 | /* We put the symbol names on the arch objalloc, and then discard | 
|---|
| 1869 | them when done.  */ | 
|---|
| 1870 | first_name = bfd_alloc (arch, (bfd_size_type) 1); | 
|---|
| 1871 | if (first_name == NULL) | 
|---|
| 1872 | goto error_return; | 
|---|
| 1873 |  | 
|---|
| 1874 | /* Drop all the files called __.SYMDEF, we're going to make our own.  */ | 
|---|
| 1875 | while (arch->archive_head && | 
|---|
| 1876 | strcmp (arch->archive_head->filename, "__.SYMDEF") == 0) | 
|---|
| 1877 | arch->archive_head = arch->archive_head->next; | 
|---|
| 1878 |  | 
|---|
| 1879 | /* Map over each element.  */ | 
|---|
| 1880 | for (current = arch->archive_head; | 
|---|
| 1881 | current != (bfd *) NULL; | 
|---|
| 1882 | current = current->next, elt_no++) | 
|---|
| 1883 | { | 
|---|
| 1884 | if (bfd_check_format (current, bfd_object) | 
|---|
| 1885 | && (bfd_get_file_flags (current) & HAS_SYMS) != 0) | 
|---|
| 1886 | { | 
|---|
| 1887 | long storage; | 
|---|
| 1888 | long symcount; | 
|---|
| 1889 | long src_count; | 
|---|
| 1890 |  | 
|---|
| 1891 | storage = bfd_get_symtab_upper_bound (current); | 
|---|
| 1892 | if (storage < 0) | 
|---|
| 1893 | goto error_return; | 
|---|
| 1894 |  | 
|---|
| 1895 | if (storage != 0) | 
|---|
| 1896 | { | 
|---|
| 1897 | if (storage > syms_max) | 
|---|
| 1898 | { | 
|---|
| 1899 | if (syms_max > 0) | 
|---|
| 1900 | free (syms); | 
|---|
| 1901 | syms_max = storage; | 
|---|
| 1902 | syms = (asymbol **) bfd_malloc ((bfd_size_type) syms_max); | 
|---|
| 1903 | if (syms == NULL) | 
|---|
| 1904 | goto error_return; | 
|---|
| 1905 | } | 
|---|
| 1906 | symcount = bfd_canonicalize_symtab (current, syms); | 
|---|
| 1907 | if (symcount < 0) | 
|---|
| 1908 | goto error_return; | 
|---|
| 1909 |  | 
|---|
| 1910 | /* Now map over all the symbols, picking out the ones we | 
|---|
| 1911 | want.  */ | 
|---|
| 1912 | for (src_count = 0; src_count < symcount; src_count++) | 
|---|
| 1913 | { | 
|---|
| 1914 | flagword flags = (syms[src_count])->flags; | 
|---|
| 1915 | asection *sec = syms[src_count]->section; | 
|---|
| 1916 |  | 
|---|
| 1917 | if ((flags & BSF_GLOBAL || | 
|---|
| 1918 | flags & BSF_WEAK || | 
|---|
| 1919 | flags & BSF_INDIRECT || | 
|---|
| 1920 | #ifdef EMX | 
|---|
| 1921 | flags & BSF_EMX_IMPORT1 || | 
|---|
| 1922 | #endif /* EMX */ | 
|---|
| 1923 | bfd_is_com_section (sec)) | 
|---|
| 1924 | && ! bfd_is_und_section (sec)) | 
|---|
| 1925 | { | 
|---|
| 1926 | bfd_size_type namelen; | 
|---|
| 1927 | struct orl *new_map; | 
|---|
| 1928 |  | 
|---|
| 1929 | /* This symbol will go into the archive header.  */ | 
|---|
| 1930 | if (orl_count == orl_max) | 
|---|
| 1931 | { | 
|---|
| 1932 | orl_max *= 2; | 
|---|
| 1933 | amt = (bfd_size_type) orl_max * sizeof (struct orl); | 
|---|
| 1934 | new_map = (struct orl *) bfd_realloc (map, amt); | 
|---|
| 1935 | if (new_map == (struct orl *) NULL) | 
|---|
| 1936 | goto error_return; | 
|---|
| 1937 |  | 
|---|
| 1938 | map = new_map; | 
|---|
| 1939 | } | 
|---|
| 1940 |  | 
|---|
| 1941 | namelen = strlen (syms[src_count]->name); | 
|---|
| 1942 | amt = sizeof (char *); | 
|---|
| 1943 | map[orl_count].name = (char **) bfd_alloc (arch, amt); | 
|---|
| 1944 | if (map[orl_count].name == NULL) | 
|---|
| 1945 | goto error_return; | 
|---|
| 1946 | *(map[orl_count].name) = bfd_alloc (arch, namelen + 1); | 
|---|
| 1947 | if (*(map[orl_count].name) == NULL) | 
|---|
| 1948 | goto error_return; | 
|---|
| 1949 | strcpy (*(map[orl_count].name), syms[src_count]->name); | 
|---|
| 1950 | map[orl_count].u.abfd = current; | 
|---|
| 1951 | map[orl_count].namidx = stridx; | 
|---|
| 1952 |  | 
|---|
| 1953 | stridx += namelen + 1; | 
|---|
| 1954 | ++orl_count; | 
|---|
| 1955 | } | 
|---|
| 1956 | } | 
|---|
| 1957 | } | 
|---|
| 1958 |  | 
|---|
| 1959 | /* Now ask the BFD to free up any cached information, so we | 
|---|
| 1960 | don't fill all of memory with symbol tables.  */ | 
|---|
| 1961 | if (! bfd_free_cached_info (current)) | 
|---|
| 1962 | goto error_return; | 
|---|
| 1963 | } | 
|---|
| 1964 | } | 
|---|
| 1965 |  | 
|---|
| 1966 | /* OK, now we have collected all the data, let's write them out.  */ | 
|---|
| 1967 | ret = BFD_SEND (arch, write_armap, | 
|---|
| 1968 | (arch, elength, map, orl_count, stridx)); | 
|---|
| 1969 |  | 
|---|
| 1970 | if (syms_max > 0) | 
|---|
| 1971 | free (syms); | 
|---|
| 1972 | if (map != NULL) | 
|---|
| 1973 | free (map); | 
|---|
| 1974 | if (first_name != NULL) | 
|---|
| 1975 | bfd_release (arch, first_name); | 
|---|
| 1976 |  | 
|---|
| 1977 | return ret; | 
|---|
| 1978 |  | 
|---|
| 1979 | error_return: | 
|---|
| 1980 | if (syms_max > 0) | 
|---|
| 1981 | free (syms); | 
|---|
| 1982 | if (map != NULL) | 
|---|
| 1983 | free (map); | 
|---|
| 1984 | if (first_name != NULL) | 
|---|
| 1985 | bfd_release (arch, first_name); | 
|---|
| 1986 |  | 
|---|
| 1987 | return FALSE; | 
|---|
| 1988 | } | 
|---|
| 1989 |  | 
|---|
| 1990 | bfd_boolean | 
|---|
| 1991 | bsd_write_armap (arch, elength, map, orl_count, stridx) | 
|---|
| 1992 | bfd *arch; | 
|---|
| 1993 | unsigned int elength; | 
|---|
| 1994 | struct orl *map; | 
|---|
| 1995 | unsigned int orl_count; | 
|---|
| 1996 | int stridx; | 
|---|
| 1997 | { | 
|---|
| 1998 | int padit = stridx & 1; | 
|---|
| 1999 | unsigned int ranlibsize = orl_count * BSD_SYMDEF_SIZE; | 
|---|
| 2000 | unsigned int stringsize = stridx + padit; | 
|---|
| 2001 | /* Include 8 bytes to store ranlibsize and stringsize in output.  */ | 
|---|
| 2002 | unsigned int mapsize = ranlibsize + stringsize + 8; | 
|---|
| 2003 | file_ptr firstreal; | 
|---|
| 2004 | bfd *current = arch->archive_head; | 
|---|
| 2005 | bfd *last_elt = current;      /* last element arch seen */ | 
|---|
| 2006 | bfd_byte temp[4]; | 
|---|
| 2007 | unsigned int count; | 
|---|
| 2008 | struct ar_hdr hdr; | 
|---|
| 2009 | struct stat statbuf; | 
|---|
| 2010 | unsigned int i; | 
|---|
| 2011 |  | 
|---|
| 2012 | firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG; | 
|---|
| 2013 |  | 
|---|
| 2014 | stat (arch->filename, &statbuf); | 
|---|
| 2015 | memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); | 
|---|
| 2016 | sprintf (hdr.ar_name, RANLIBMAG); | 
|---|
| 2017 | /* Remember the timestamp, to keep it holy.  But fudge it a little.  */ | 
|---|
| 2018 | bfd_ardata (arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET; | 
|---|
| 2019 | bfd_ardata (arch)->armap_datepos = (SARMAG | 
|---|
| 2020 | + offsetof (struct ar_hdr, ar_date[0])); | 
|---|
| 2021 | sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp); | 
|---|
| 2022 | sprintf (hdr.ar_uid, "%ld", (long) getuid ()); | 
|---|
| 2023 | sprintf (hdr.ar_gid, "%ld", (long) getgid ()); | 
|---|
| 2024 | sprintf (hdr.ar_size, "%-10d", (int) mapsize); | 
|---|
| 2025 | strncpy (hdr.ar_fmag, ARFMAG, 2); | 
|---|
| 2026 | for (i = 0; i < sizeof (struct ar_hdr); i++) | 
|---|
| 2027 | if (((char *) (&hdr))[i] == '\0') | 
|---|
| 2028 | (((char *) (&hdr))[i]) = ' '; | 
|---|
| 2029 | if (bfd_bwrite ((PTR) &hdr, (bfd_size_type) sizeof (struct ar_hdr), arch) | 
|---|
| 2030 | != sizeof (struct ar_hdr)) | 
|---|
| 2031 | return FALSE; | 
|---|
| 2032 | H_PUT_32 (arch, ranlibsize, temp); | 
|---|
| 2033 | if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), arch) != sizeof (temp)) | 
|---|
| 2034 | return FALSE; | 
|---|
| 2035 |  | 
|---|
| 2036 | for (count = 0; count < orl_count; count++) | 
|---|
| 2037 | { | 
|---|
| 2038 | bfd_byte buf[BSD_SYMDEF_SIZE]; | 
|---|
| 2039 |  | 
|---|
| 2040 | if (map[count].u.abfd != last_elt) | 
|---|
| 2041 | { | 
|---|
| 2042 | do | 
|---|
| 2043 | { | 
|---|
| 2044 | firstreal += arelt_size (current) + sizeof (struct ar_hdr); | 
|---|
| 2045 | firstreal += firstreal % 2; | 
|---|
| 2046 | current = current->next; | 
|---|
| 2047 | } | 
|---|
| 2048 | while (current != map[count].u.abfd); | 
|---|
| 2049 | }                       /* if new archive element */ | 
|---|
| 2050 |  | 
|---|
| 2051 | last_elt = current; | 
|---|
| 2052 | H_PUT_32 (arch, map[count].namidx, buf); | 
|---|
| 2053 | H_PUT_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE); | 
|---|
| 2054 | if (bfd_bwrite (buf, (bfd_size_type) BSD_SYMDEF_SIZE, arch) | 
|---|
| 2055 | != BSD_SYMDEF_SIZE) | 
|---|
| 2056 | return FALSE; | 
|---|
| 2057 | } | 
|---|
| 2058 |  | 
|---|
| 2059 | /* Now write the strings themselves.  */ | 
|---|
| 2060 | H_PUT_32 (arch, stringsize, temp); | 
|---|
| 2061 | if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), arch) != sizeof (temp)) | 
|---|
| 2062 | return FALSE; | 
|---|
| 2063 | for (count = 0; count < orl_count; count++) | 
|---|
| 2064 | { | 
|---|
| 2065 | size_t len = strlen (*map[count].name) + 1; | 
|---|
| 2066 |  | 
|---|
| 2067 | if (bfd_bwrite (*map[count].name, (bfd_size_type) len, arch) != len) | 
|---|
| 2068 | return FALSE; | 
|---|
| 2069 | } | 
|---|
| 2070 |  | 
|---|
| 2071 | /* The spec sez this should be a newline.  But in order to be | 
|---|
| 2072 | bug-compatible for sun's ar we use a null.  */ | 
|---|
| 2073 | if (padit) | 
|---|
| 2074 | { | 
|---|
| 2075 | if (bfd_bwrite ("", (bfd_size_type) 1, arch) != 1) | 
|---|
| 2076 | return FALSE; | 
|---|
| 2077 | } | 
|---|
| 2078 |  | 
|---|
| 2079 | return TRUE; | 
|---|
| 2080 | } | 
|---|
| 2081 |  | 
|---|
| 2082 | /* At the end of archive file handling, update the timestamp in the | 
|---|
| 2083 | file, so the linker will accept it. | 
|---|
| 2084 |  | 
|---|
| 2085 | Return TRUE if the timestamp was OK, or an unusual problem happened. | 
|---|
| 2086 | Return FALSE if we updated the timestamp.  */ | 
|---|
| 2087 |  | 
|---|
| 2088 | bfd_boolean | 
|---|
| 2089 | _bfd_archive_bsd_update_armap_timestamp (arch) | 
|---|
| 2090 | bfd *arch; | 
|---|
| 2091 | { | 
|---|
| 2092 | struct stat archstat; | 
|---|
| 2093 | struct ar_hdr hdr; | 
|---|
| 2094 | unsigned int i; | 
|---|
| 2095 |  | 
|---|
| 2096 | /* Flush writes, get last-write timestamp from file, and compare it | 
|---|
| 2097 | to the timestamp IN the file.  */ | 
|---|
| 2098 | bfd_flush (arch); | 
|---|
| 2099 | if (bfd_stat (arch, &archstat) == -1) | 
|---|
| 2100 | { | 
|---|
| 2101 | bfd_perror (_("Reading archive file mod timestamp")); | 
|---|
| 2102 |  | 
|---|
| 2103 | /* Can't read mod time for some reason.  */ | 
|---|
| 2104 | return TRUE; | 
|---|
| 2105 | } | 
|---|
| 2106 | if (archstat.st_mtime <= bfd_ardata (arch)->armap_timestamp) | 
|---|
| 2107 | /* OK by the linker's rules.  */ | 
|---|
| 2108 | return TRUE; | 
|---|
| 2109 |  | 
|---|
| 2110 | /* Update the timestamp.  */ | 
|---|
| 2111 | bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET; | 
|---|
| 2112 |  | 
|---|
| 2113 | /* Prepare an ASCII version suitable for writing.  */ | 
|---|
| 2114 | memset (hdr.ar_date, 0, sizeof (hdr.ar_date)); | 
|---|
| 2115 | sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp); | 
|---|
| 2116 | for (i = 0; i < sizeof (hdr.ar_date); i++) | 
|---|
| 2117 | if (hdr.ar_date[i] == '\0') | 
|---|
| 2118 | (hdr.ar_date)[i] = ' '; | 
|---|
| 2119 |  | 
|---|
| 2120 | /* Write it into the file.  */ | 
|---|
| 2121 | bfd_ardata (arch)->armap_datepos = (SARMAG | 
|---|
| 2122 | + offsetof (struct ar_hdr, ar_date[0])); | 
|---|
| 2123 | if (bfd_seek (arch, bfd_ardata (arch)->armap_datepos, SEEK_SET) != 0 | 
|---|
| 2124 | || (bfd_bwrite (hdr.ar_date, (bfd_size_type) sizeof (hdr.ar_date), arch) | 
|---|
| 2125 | != sizeof (hdr.ar_date))) | 
|---|
| 2126 | { | 
|---|
| 2127 | bfd_perror (_("Writing updated armap timestamp")); | 
|---|
| 2128 |  | 
|---|
| 2129 | /* Some error while writing.  */ | 
|---|
| 2130 | return TRUE; | 
|---|
| 2131 | } | 
|---|
| 2132 |  | 
|---|
| 2133 | /* We updated the timestamp successfully.  */ | 
|---|
| 2134 | return FALSE; | 
|---|
| 2135 | } | 
|---|
| 2136 |  | 
|---|
| 2137 |  | 
|---|
| 2138 | /* A coff armap looks like : | 
|---|
| 2139 | lARMAG | 
|---|
| 2140 | struct ar_hdr with name = '/' | 
|---|
| 2141 | number of symbols | 
|---|
| 2142 | offset of file for symbol 0 | 
|---|
| 2143 | offset of file for symbol 1 | 
|---|
| 2144 |  | 
|---|
| 2145 | offset of file for symbol n-1 | 
|---|
| 2146 | symbol name 0 | 
|---|
| 2147 | symbol name 1 | 
|---|
| 2148 |  | 
|---|
| 2149 | symbol name n-1 | 
|---|
| 2150 | */ | 
|---|
| 2151 |  | 
|---|
| 2152 | bfd_boolean | 
|---|
| 2153 | coff_write_armap (arch, elength, map, symbol_count, stridx) | 
|---|
| 2154 | bfd *arch; | 
|---|
| 2155 | unsigned int elength; | 
|---|
| 2156 | struct orl *map; | 
|---|
| 2157 | unsigned int symbol_count; | 
|---|
| 2158 | int stridx; | 
|---|
| 2159 | { | 
|---|
| 2160 | /* The size of the ranlib is the number of exported symbols in the | 
|---|
| 2161 | archive * the number of bytes in an int, + an int for the count.  */ | 
|---|
| 2162 | unsigned int ranlibsize = (symbol_count * 4) + 4; | 
|---|
| 2163 | unsigned int stringsize = stridx; | 
|---|
| 2164 | unsigned int mapsize = stringsize + ranlibsize; | 
|---|
| 2165 | unsigned int archive_member_file_ptr; | 
|---|
| 2166 | bfd *current = arch->archive_head; | 
|---|
| 2167 | unsigned int count; | 
|---|
| 2168 | struct ar_hdr hdr; | 
|---|
| 2169 | unsigned int i; | 
|---|
| 2170 | int padit = mapsize & 1; | 
|---|
| 2171 |  | 
|---|
| 2172 | if (padit) | 
|---|
| 2173 | mapsize++; | 
|---|
| 2174 |  | 
|---|
| 2175 | /* Work out where the first object file will go in the archive.  */ | 
|---|
| 2176 | archive_member_file_ptr = (mapsize | 
|---|
| 2177 | + elength | 
|---|
| 2178 | + sizeof (struct ar_hdr) | 
|---|
| 2179 | + SARMAG); | 
|---|
| 2180 |  | 
|---|
| 2181 | memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); | 
|---|
| 2182 | hdr.ar_name[0] = '/'; | 
|---|
| 2183 | sprintf (hdr.ar_size, "%-10d", (int) mapsize); | 
|---|
| 2184 | sprintf (hdr.ar_date, "%ld", (long) time (NULL)); | 
|---|
| 2185 | /* This, at least, is what Intel coff sets the values to.  */ | 
|---|
| 2186 | sprintf ((hdr.ar_uid), "%d", 0); | 
|---|
| 2187 | sprintf ((hdr.ar_gid), "%d", 0); | 
|---|
| 2188 | sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0); | 
|---|
| 2189 | strncpy (hdr.ar_fmag, ARFMAG, 2); | 
|---|
| 2190 |  | 
|---|
| 2191 | for (i = 0; i < sizeof (struct ar_hdr); i++) | 
|---|
| 2192 | if (((char *) (&hdr))[i] == '\0') | 
|---|
| 2193 | (((char *) (&hdr))[i]) = ' '; | 
|---|
| 2194 |  | 
|---|
| 2195 | /* Write the ar header for this item and the number of symbols.  */ | 
|---|
| 2196 |  | 
|---|
| 2197 | if (bfd_bwrite ((PTR) &hdr, (bfd_size_type) sizeof (struct ar_hdr), arch) | 
|---|
| 2198 | != sizeof (struct ar_hdr)) | 
|---|
| 2199 | return FALSE; | 
|---|
| 2200 |  | 
|---|
| 2201 | if (!bfd_write_bigendian_4byte_int (arch, symbol_count)) | 
|---|
| 2202 | return FALSE; | 
|---|
| 2203 |  | 
|---|
| 2204 | /* Two passes, first write the file offsets for each symbol - | 
|---|
| 2205 | remembering that each offset is on a two byte boundary.  */ | 
|---|
| 2206 |  | 
|---|
| 2207 | /* Write out the file offset for the file associated with each | 
|---|
| 2208 | symbol, and remember to keep the offsets padded out.  */ | 
|---|
| 2209 |  | 
|---|
| 2210 | current = arch->archive_head; | 
|---|
| 2211 | count = 0; | 
|---|
| 2212 | while (current != (bfd *) NULL && count < symbol_count) | 
|---|
| 2213 | { | 
|---|
| 2214 | /* For each symbol which is used defined in this object, write | 
|---|
| 2215 | out the object file's address in the archive.  */ | 
|---|
| 2216 |  | 
|---|
| 2217 | while (count < symbol_count && map[count].u.abfd == current) | 
|---|
| 2218 | { | 
|---|
| 2219 | if (!bfd_write_bigendian_4byte_int (arch, archive_member_file_ptr)) | 
|---|
| 2220 | return FALSE; | 
|---|
| 2221 | count++; | 
|---|
| 2222 | } | 
|---|
| 2223 | /* Add size of this archive entry.  */ | 
|---|
| 2224 | archive_member_file_ptr += (arelt_size (current) | 
|---|
| 2225 | + sizeof (struct ar_hdr)); | 
|---|
| 2226 | /* Remember aboout the even alignment.  */ | 
|---|
| 2227 | archive_member_file_ptr += archive_member_file_ptr % 2; | 
|---|
| 2228 | current = current->next; | 
|---|
| 2229 | } | 
|---|
| 2230 |  | 
|---|
| 2231 | /* Now write the strings themselves.  */ | 
|---|
| 2232 | for (count = 0; count < symbol_count; count++) | 
|---|
| 2233 | { | 
|---|
| 2234 | size_t len = strlen (*map[count].name) + 1; | 
|---|
| 2235 |  | 
|---|
| 2236 | if (bfd_bwrite (*map[count].name, (bfd_size_type) len, arch) != len) | 
|---|
| 2237 | return FALSE; | 
|---|
| 2238 | } | 
|---|
| 2239 |  | 
|---|
| 2240 | /* The spec sez this should be a newline.  But in order to be | 
|---|
| 2241 | bug-compatible for arc960 we use a null.  */ | 
|---|
| 2242 | if (padit) | 
|---|
| 2243 | { | 
|---|
| 2244 | if (bfd_bwrite ("", (bfd_size_type) 1, arch) != 1) | 
|---|
| 2245 | return FALSE; | 
|---|
| 2246 | } | 
|---|
| 2247 |  | 
|---|
| 2248 | return TRUE; | 
|---|
| 2249 | } | 
|---|