00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 #include "bfd.h"
00135 #include "sysdep.h"
00136 #include "libbfd.h"
00137 #include "aout/ar.h"
00138 #include "aout/ranlib.h"
00139 #include "safe-ctype.h"
00140
00141 #ifndef errno
00142 extern int errno;
00143 #endif
00144
00145
00146
00147
00148
00149
00150
00151 struct ar_cache {
00152 file_ptr ptr;
00153 bfd *arelt;
00154 struct ar_cache *next;
00155 };
00156
00157 #define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
00158 #define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
00159
00160 #define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
00161 #define arch_hdr(bfd) ((struct ar_hdr *) arch_eltdata(bfd)->arch_header)
00162
00163
00164 bfd_boolean
00165 _bfd_generic_mkarchive (bfd *abfd)
00166 {
00167 bfd_size_type amt = sizeof (struct artdata);
00168
00169 abfd->tdata.aout_ar_data = bfd_zalloc (abfd, amt);
00170 if (bfd_ardata (abfd) == NULL)
00171 return FALSE;
00172
00173 bfd_ardata (abfd)->cache = NULL;
00174 bfd_ardata (abfd)->archive_head = NULL;
00175 bfd_ardata (abfd)->symdefs = NULL;
00176 bfd_ardata (abfd)->extended_names = NULL;
00177 bfd_ardata (abfd)->tdata = NULL;
00178
00179 return TRUE;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 symindex
00205 bfd_get_next_mapent (bfd *abfd, symindex prev, carsym **entry)
00206 {
00207 if (!bfd_has_map (abfd))
00208 {
00209 bfd_set_error (bfd_error_invalid_operation);
00210 return BFD_NO_MORE_SYMBOLS;
00211 }
00212
00213 if (prev == BFD_NO_MORE_SYMBOLS)
00214 prev = 0;
00215 else
00216 ++prev;
00217 if (prev >= bfd_ardata (abfd)->symdef_count)
00218 return BFD_NO_MORE_SYMBOLS;
00219
00220 *entry = (bfd_ardata (abfd)->symdefs + prev);
00221 return prev;
00222 }
00223
00224
00225
00226 bfd *
00227 _bfd_create_empty_archive_element_shell (bfd *obfd)
00228 {
00229 return _bfd_new_bfd_contained_in (obfd);
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 bfd_boolean
00245 bfd_set_archive_head (bfd *output_archive, bfd *new_head)
00246 {
00247 output_archive->archive_head = new_head;
00248 return TRUE;
00249 }
00250
00251 bfd *
00252 _bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos)
00253 {
00254 struct ar_cache *current;
00255
00256 for (current = bfd_ardata (arch_bfd)->cache; current != NULL;
00257 current = current->next)
00258 if (current->ptr == filepos)
00259 return current->arelt;
00260
00261 return NULL;
00262 }
00263
00264
00265
00266 bfd_boolean
00267 _bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt)
00268 {
00269 bfd_size_type amt = sizeof (struct ar_cache);
00270
00271 struct ar_cache *new_cache = bfd_zalloc (arch_bfd, amt);
00272 if (new_cache == NULL)
00273 return FALSE;
00274
00275 new_cache->ptr = filepos;
00276 new_cache->arelt = new_elt;
00277 new_cache->next = NULL;
00278 if (bfd_ardata (arch_bfd)->cache == NULL)
00279 bfd_ardata (arch_bfd)->cache = new_cache;
00280 else
00281 {
00282 struct ar_cache *current = bfd_ardata (arch_bfd)->cache;
00283
00284 while (current->next != NULL)
00285 current = current->next;
00286 current->next = new_cache;
00287 }
00288
00289 return TRUE;
00290 }
00291
00292
00293
00294
00295 static char *
00296 get_extended_arelt_filename (bfd *arch, const char *name)
00297 {
00298 unsigned long index = 0;
00299
00300
00301
00302 errno = 0;
00303
00304 index = strtol (name + 1, NULL, 10);
00305 if (errno != 0)
00306 {
00307 bfd_set_error (bfd_error_malformed_archive);
00308 return NULL;
00309 }
00310
00311 return bfd_ardata (arch)->extended_names + index;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 void *
00323 _bfd_generic_read_ar_hdr (bfd *abfd)
00324 {
00325 return _bfd_generic_read_ar_hdr_mag (abfd, NULL);
00326 }
00327
00328
00329
00330
00331 void *
00332 _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
00333 {
00334 struct ar_hdr hdr;
00335 char *hdrp = (char *) &hdr;
00336 size_t parsed_size;
00337 struct areltdata *ared;
00338 char *filename = NULL;
00339 bfd_size_type namelen = 0;
00340 bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
00341 char *allocptr = 0;
00342
00343 if (bfd_bread (hdrp, sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr))
00344 {
00345 if (bfd_get_error () != bfd_error_system_call)
00346 bfd_set_error (bfd_error_no_more_archived_files);
00347 return NULL;
00348 }
00349 if (strncmp (hdr.ar_fmag, ARFMAG, 2) != 0
00350 && (mag == NULL
00351 || strncmp (hdr.ar_fmag, mag, 2) != 0))
00352 {
00353 bfd_set_error (bfd_error_malformed_archive);
00354 return NULL;
00355 }
00356
00357 errno = 0;
00358 parsed_size = strtol (hdr.ar_size, NULL, 10);
00359 if (errno != 0)
00360 {
00361 bfd_set_error (bfd_error_malformed_archive);
00362 return NULL;
00363 }
00364
00365
00366
00367
00368 if ((hdr.ar_name[0] == '/'
00369 || (hdr.ar_name[0] == ' '
00370 && memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL))
00371 && bfd_ardata (abfd)->extended_names != NULL)
00372 {
00373 filename = get_extended_arelt_filename (abfd, hdr.ar_name);
00374 if (filename == NULL)
00375 {
00376 bfd_set_error (bfd_error_malformed_archive);
00377 return NULL;
00378 }
00379 }
00380
00381
00382 else if (hdr.ar_name[0] == '#'
00383 && hdr.ar_name[1] == '1'
00384 && hdr.ar_name[2] == '/'
00385 && ISDIGIT (hdr.ar_name[3]))
00386 {
00387
00388 namelen = atoi (&hdr.ar_name[3]);
00389 allocsize += namelen + 1;
00390 parsed_size -= namelen;
00391
00392 allocptr = bfd_zalloc (abfd, allocsize);
00393 if (allocptr == NULL)
00394 return NULL;
00395 filename = (allocptr
00396 + sizeof (struct areltdata)
00397 + sizeof (struct ar_hdr));
00398 if (bfd_bread (filename, namelen, abfd) != namelen)
00399 {
00400 if (bfd_get_error () != bfd_error_system_call)
00401 bfd_set_error (bfd_error_no_more_archived_files);
00402 return NULL;
00403 }
00404 filename[namelen] = '\0';
00405 }
00406 else
00407 {
00408
00409
00410
00411
00412 char *e;
00413 e = memchr (hdr.ar_name, '\0', ar_maxnamelen (abfd));
00414 if (e == NULL)
00415 {
00416 e = memchr (hdr.ar_name, '/', ar_maxnamelen (abfd));
00417 if (e == NULL)
00418 e = memchr (hdr.ar_name, ' ', ar_maxnamelen (abfd));
00419 }
00420
00421 if (e != NULL)
00422 namelen = e - hdr.ar_name;
00423 else
00424 {
00425
00426
00427 namelen = ar_maxnamelen (abfd);
00428 }
00429
00430 allocsize += namelen + 1;
00431 }
00432
00433 if (!allocptr)
00434 {
00435 allocptr = bfd_zalloc (abfd, allocsize);
00436 if (allocptr == NULL)
00437 return NULL;
00438 }
00439
00440 ared = (struct areltdata *) allocptr;
00441
00442 ared->arch_header = allocptr + sizeof (struct areltdata);
00443 memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr));
00444 ared->parsed_size = parsed_size;
00445
00446 if (filename != NULL)
00447 ared->filename = filename;
00448 else
00449 {
00450 ared->filename = allocptr + (sizeof (struct areltdata) +
00451 sizeof (struct ar_hdr));
00452 if (namelen)
00453 memcpy (ared->filename, hdr.ar_name, namelen);
00454 ared->filename[namelen] = '\0';
00455 }
00456
00457 return ared;
00458 }
00459
00460
00461
00462
00463
00464 bfd *
00465 _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
00466 {
00467 struct areltdata *new_areldata;
00468 bfd *n_nfd;
00469
00470 if (archive->my_archive)
00471 {
00472 filepos += archive->origin;
00473 archive = archive->my_archive;
00474 }
00475
00476 n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
00477 if (n_nfd)
00478 return n_nfd;
00479
00480 if (0 > bfd_seek (archive, filepos, SEEK_SET))
00481 return NULL;
00482
00483 if ((new_areldata = _bfd_read_ar_hdr (archive)) == NULL)
00484 return NULL;
00485
00486 n_nfd = _bfd_create_empty_archive_element_shell (archive);
00487 if (n_nfd == NULL)
00488 {
00489 bfd_release (archive, new_areldata);
00490 return NULL;
00491 }
00492
00493 n_nfd->origin = bfd_tell (archive);
00494 n_nfd->arelt_data = new_areldata;
00495 n_nfd->filename = new_areldata->filename;
00496
00497 if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
00498 return n_nfd;
00499
00500
00501 bfd_release (archive, n_nfd);
00502 bfd_release (archive, new_areldata);
00503 return NULL;
00504 }
00505
00506
00507
00508
00509 bfd *
00510 _bfd_generic_get_elt_at_index (bfd *abfd, symindex index)
00511 {
00512 carsym *entry;
00513
00514 entry = bfd_ardata (abfd)->symdefs + index;
00515 return _bfd_get_elt_at_filepos (abfd, entry->file_offset);
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 bfd *
00535 bfd_openr_next_archived_file (bfd *archive, bfd *last_file)
00536 {
00537 if ((bfd_get_format (archive) != bfd_archive) ||
00538 (archive->direction == write_direction))
00539 {
00540 bfd_set_error (bfd_error_invalid_operation);
00541 return NULL;
00542 }
00543
00544 return BFD_SEND (archive,
00545 openr_next_archived_file, (archive, last_file));
00546 }
00547
00548 bfd *
00549 bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
00550 {
00551 file_ptr filestart;
00552
00553 if (!last_file)
00554 filestart = bfd_ardata (archive)->first_file_filepos;
00555 else
00556 {
00557 unsigned int size = arelt_size (last_file);
00558 filestart = last_file->origin + size;
00559 if (archive->my_archive)
00560 filestart -= archive->origin;
00561
00562
00563
00564 filestart += filestart % 2;
00565 }
00566
00567 return _bfd_get_elt_at_filepos (archive, filestart);
00568 }
00569
00570 const bfd_target *
00571 bfd_generic_archive_p (bfd *abfd)
00572 {
00573 struct artdata *tdata_hold;
00574 char armag[SARMAG + 1];
00575 bfd_size_type amt;
00576
00577 if (bfd_bread (armag, SARMAG, abfd) != SARMAG)
00578 {
00579 if (bfd_get_error () != bfd_error_system_call)
00580 bfd_set_error (bfd_error_wrong_format);
00581 return NULL;
00582 }
00583
00584 if (strncmp (armag, ARMAG, SARMAG) != 0 &&
00585 strncmp (armag, ARMAGB, SARMAG) != 0)
00586 return 0;
00587
00588 tdata_hold = bfd_ardata (abfd);
00589
00590 amt = sizeof (struct artdata);
00591 bfd_ardata (abfd) = bfd_zalloc (abfd, amt);
00592 if (bfd_ardata (abfd) == NULL)
00593 {
00594 bfd_ardata (abfd) = tdata_hold;
00595 return NULL;
00596 }
00597
00598 bfd_ardata (abfd)->first_file_filepos = SARMAG;
00599 bfd_ardata (abfd)->cache = NULL;
00600 bfd_ardata (abfd)->archive_head = NULL;
00601 bfd_ardata (abfd)->symdefs = NULL;
00602 bfd_ardata (abfd)->extended_names = NULL;
00603 bfd_ardata (abfd)->tdata = NULL;
00604
00605 if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))
00606 || !BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd)))
00607 {
00608 if (bfd_get_error () != bfd_error_system_call)
00609 bfd_set_error (bfd_error_wrong_format);
00610 bfd_release (abfd, bfd_ardata (abfd));
00611 bfd_ardata (abfd) = tdata_hold;
00612 return NULL;
00613 }
00614
00615 if (bfd_has_map (abfd))
00616 {
00617 bfd *first;
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 first = bfd_openr_next_archived_file (abfd, NULL);
00631 if (first != NULL)
00632 {
00633 bfd_boolean fail;
00634
00635 first->target_defaulted = FALSE;
00636 fail = FALSE;
00637 if (bfd_check_format (first, bfd_object)
00638 && first->xvec != abfd->xvec)
00639 {
00640 bfd_set_error (bfd_error_wrong_object_format);
00641 bfd_ardata (abfd) = tdata_hold;
00642 return NULL;
00643 }
00644
00645 }
00646 }
00647
00648 return abfd->xvec;
00649 }
00650
00651
00652
00653
00654
00655
00656
00657 #define BSD_SYMDEF_SIZE 8
00658
00659
00660 #define BSD_SYMDEF_OFFSET_SIZE 4
00661
00662
00663 #define BSD_SYMDEF_COUNT_SIZE 4
00664
00665
00666 #define BSD_STRING_COUNT_SIZE 4
00667
00668
00669
00670 static bfd_boolean
00671 do_slurp_bsd_armap (bfd *abfd)
00672 {
00673 struct areltdata *mapdata;
00674 unsigned int counter;
00675 bfd_byte *raw_armap, *rbase;
00676 struct artdata *ardata = bfd_ardata (abfd);
00677 char *stringbase;
00678 bfd_size_type parsed_size, amt;
00679 carsym *set;
00680
00681 mapdata = _bfd_read_ar_hdr (abfd);
00682 if (mapdata == NULL)
00683 return FALSE;
00684 parsed_size = mapdata->parsed_size;
00685 bfd_release (abfd, mapdata);
00686
00687 raw_armap = bfd_zalloc (abfd, parsed_size);
00688 if (raw_armap == NULL)
00689 return FALSE;
00690
00691 if (bfd_bread (raw_armap, parsed_size, abfd) != parsed_size)
00692 {
00693 if (bfd_get_error () != bfd_error_system_call)
00694 bfd_set_error (bfd_error_malformed_archive);
00695 byebye:
00696 bfd_release (abfd, raw_armap);
00697 return FALSE;
00698 }
00699
00700 ardata->symdef_count = H_GET_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE;
00701
00702 if (ardata->symdef_count * BSD_SYMDEF_SIZE >
00703 parsed_size - BSD_SYMDEF_COUNT_SIZE)
00704 {
00705
00706 bfd_set_error (bfd_error_wrong_format);
00707 goto byebye;
00708 }
00709
00710 ardata->cache = 0;
00711 rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE;
00712 stringbase = ((char *) rbase
00713 + ardata->symdef_count * BSD_SYMDEF_SIZE
00714 + BSD_STRING_COUNT_SIZE);
00715 amt = ardata->symdef_count * sizeof (carsym);
00716 ardata->symdefs = bfd_alloc (abfd, amt);
00717 if (!ardata->symdefs)
00718 return FALSE;
00719
00720 for (counter = 0, set = ardata->symdefs;
00721 counter < ardata->symdef_count;
00722 counter++, set++, rbase += BSD_SYMDEF_SIZE)
00723 {
00724 set->name = H_GET_32 (abfd, rbase) + stringbase;
00725 set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
00726 }
00727
00728 ardata->first_file_filepos = bfd_tell (abfd);
00729
00730 ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
00731
00732
00733
00734 bfd_has_map (abfd) = TRUE;
00735 return TRUE;
00736 }
00737
00738
00739
00740 static bfd_boolean
00741 do_slurp_coff_armap (bfd *abfd)
00742 {
00743 struct areltdata *mapdata;
00744 int *raw_armap, *rawptr;
00745 struct artdata *ardata = bfd_ardata (abfd);
00746 char *stringbase;
00747 bfd_size_type stringsize;
00748 unsigned int parsed_size;
00749 carsym *carsyms;
00750 bfd_size_type nsymz;
00751 bfd_vma (*swap) (const void *);
00752 char int_buf[sizeof (long)];
00753 bfd_size_type carsym_size, ptrsize;
00754 unsigned int i;
00755
00756 mapdata = _bfd_read_ar_hdr (abfd);
00757 if (mapdata == NULL)
00758 return FALSE;
00759 parsed_size = mapdata->parsed_size;
00760 bfd_release (abfd, mapdata);
00761
00762 if (bfd_bread (int_buf, 4, abfd) != 4)
00763 {
00764 if (bfd_get_error () != bfd_error_system_call)
00765 bfd_set_error (bfd_error_malformed_archive);
00766 return FALSE;
00767 }
00768
00769
00770 swap = bfd_getb32;
00771 nsymz = bfd_getb32 (int_buf);
00772 stringsize = parsed_size - (4 * nsymz) - 4;
00773
00774
00775
00776
00777
00778
00779 if (stringsize > 0xfffff
00780 && bfd_get_arch (abfd) == bfd_arch_i960
00781 && bfd_get_flavour (abfd) == bfd_target_coff_flavour)
00782 {
00783
00784 nsymz = bfd_getl32 (int_buf);
00785 stringsize = parsed_size - (4 * nsymz) - 4;
00786 swap = bfd_getl32;
00787 }
00788
00789
00790
00791
00792 carsym_size = (nsymz * sizeof (carsym));
00793 ptrsize = (4 * nsymz);
00794
00795 ardata->symdefs = bfd_zalloc (abfd, carsym_size + stringsize + 1);
00796 if (ardata->symdefs == NULL)
00797 return FALSE;
00798 carsyms = ardata->symdefs;
00799 stringbase = ((char *) ardata->symdefs) + carsym_size;
00800
00801
00802 raw_armap = bfd_alloc (abfd, ptrsize);
00803 if (raw_armap == NULL)
00804 goto release_symdefs;
00805 if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
00806 || (bfd_bread (stringbase, stringsize, abfd) != stringsize))
00807 {
00808 if (bfd_get_error () != bfd_error_system_call)
00809 bfd_set_error (bfd_error_malformed_archive);
00810 goto release_raw_armap;
00811 }
00812
00813
00814 for (i = 0; i < nsymz; i++)
00815 {
00816 rawptr = raw_armap + i;
00817 carsyms->file_offset = swap ((bfd_byte *) rawptr);
00818 carsyms->name = stringbase;
00819 stringbase += strlen (stringbase) + 1;
00820 carsyms++;
00821 }
00822 *stringbase = 0;
00823
00824 ardata->symdef_count = nsymz;
00825 ardata->first_file_filepos = bfd_tell (abfd);
00826
00827 ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
00828
00829 bfd_has_map (abfd) = TRUE;
00830 bfd_release (abfd, raw_armap);
00831
00832
00833 {
00834 struct areltdata *tmp;
00835
00836 bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET);
00837 tmp = _bfd_read_ar_hdr (abfd);
00838 if (tmp != NULL)
00839 {
00840 if (tmp->arch_header[0] == '/'
00841 && tmp->arch_header[1] == ' ')
00842 {
00843 ardata->first_file_filepos +=
00844 (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1;
00845 }
00846 bfd_release (abfd, tmp);
00847 }
00848 }
00849
00850 return TRUE;
00851
00852 release_raw_armap:
00853 bfd_release (abfd, raw_armap);
00854 release_symdefs:
00855 bfd_release (abfd, (ardata)->symdefs);
00856 return FALSE;
00857 }
00858
00859
00860
00861
00862 bfd_boolean
00863 bfd_slurp_armap (bfd *abfd)
00864 {
00865 char nextname[17];
00866 int i = bfd_bread (nextname, 16, abfd);
00867
00868 if (i == 0)
00869 return TRUE;
00870 if (i != 16)
00871 return FALSE;
00872
00873 if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
00874 return FALSE;
00875
00876 if (!strncmp (nextname, "__.SYMDEF ", 16)
00877 || !strncmp (nextname, "__.SYMDEF/ ", 16))
00878 return do_slurp_bsd_armap (abfd);
00879 else if (!strncmp (nextname, "/ ", 16))
00880 return do_slurp_coff_armap (abfd);
00881 else if (!strncmp (nextname, "/SYM64/ ", 16))
00882 {
00883
00884 #ifdef BFD64
00885 extern bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
00886 return bfd_elf64_archive_slurp_armap (abfd);
00887 #else
00888 bfd_set_error (bfd_error_wrong_format);
00889 return FALSE;
00890 #endif
00891 }
00892
00893 bfd_has_map (abfd) = FALSE;
00894 return TRUE;
00895 }
00896
00897
00898
00899
00900
00901
00902 #define HPUX_SYMDEF_COUNT_SIZE 2
00903
00904 bfd_boolean
00905 bfd_slurp_bsd_armap_f2 (bfd *abfd)
00906 {
00907 struct areltdata *mapdata;
00908 char nextname[17];
00909 unsigned int counter;
00910 bfd_byte *raw_armap, *rbase;
00911 struct artdata *ardata = bfd_ardata (abfd);
00912 char *stringbase;
00913 unsigned int stringsize;
00914 bfd_size_type amt;
00915 carsym *set;
00916 int i = bfd_bread (nextname, 16, abfd);
00917
00918 if (i == 0)
00919 return TRUE;
00920 if (i != 16)
00921 return FALSE;
00922
00923
00924 if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
00925 return FALSE;
00926
00927 if (!strncmp (nextname, "__.SYMDEF ", 16)
00928 || !strncmp (nextname, "__.SYMDEF/ ", 16))
00929 return do_slurp_bsd_armap (abfd);
00930
00931 if (strncmp (nextname, "/ ", 16))
00932 {
00933 bfd_has_map (abfd) = FALSE;
00934 return TRUE;
00935 }
00936
00937 mapdata = _bfd_read_ar_hdr (abfd);
00938 if (mapdata == NULL)
00939 return FALSE;
00940
00941 amt = mapdata->parsed_size;
00942 raw_armap = bfd_zalloc (abfd, amt);
00943 if (raw_armap == NULL)
00944 {
00945 byebye:
00946 bfd_release (abfd, mapdata);
00947 return FALSE;
00948 }
00949
00950 if (bfd_bread (raw_armap, amt, abfd) != amt)
00951 {
00952 if (bfd_get_error () != bfd_error_system_call)
00953 bfd_set_error (bfd_error_malformed_archive);
00954 byebyebye:
00955 bfd_release (abfd, raw_armap);
00956 goto byebye;
00957 }
00958
00959 ardata->symdef_count = H_GET_16 (abfd, raw_armap);
00960
00961 if (ardata->symdef_count * BSD_SYMDEF_SIZE
00962 > mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE)
00963 {
00964
00965 bfd_set_error (bfd_error_wrong_format);
00966 goto byebyebye;
00967 }
00968
00969 ardata->cache = 0;
00970
00971 stringsize = H_GET_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE);
00972
00973 stringbase = ((char *) raw_armap
00974 + HPUX_SYMDEF_COUNT_SIZE
00975 + BSD_STRING_COUNT_SIZE);
00976 rbase = (bfd_byte *) stringbase + stringsize;
00977 amt = ardata->symdef_count * BSD_SYMDEF_SIZE;
00978 ardata->symdefs = bfd_alloc (abfd, amt);
00979 if (!ardata->symdefs)
00980 return FALSE;
00981
00982 for (counter = 0, set = ardata->symdefs;
00983 counter < ardata->symdef_count;
00984 counter++, set++, rbase += BSD_SYMDEF_SIZE)
00985 {
00986 set->name = H_GET_32 (abfd, rbase) + stringbase;
00987 set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
00988 }
00989
00990 ardata->first_file_filepos = bfd_tell (abfd);
00991
00992 ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
00993
00994
00995
00996 bfd_has_map (abfd) = TRUE;
00997 return TRUE;
00998 }
00999
01010
01011
01012 bfd_boolean
01013 _bfd_slurp_extended_name_table (bfd *abfd)
01014 {
01015 char nextname[17];
01016 struct areltdata *namedata;
01017 bfd_size_type amt;
01018
01019
01020
01021 bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET);
01022 if (bfd_bread (nextname, 16, abfd) == 16)
01023 {
01024 if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
01025 return FALSE;
01026
01027 if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 &&
01028 strncmp (nextname, "// ", 16) != 0)
01029 {
01030 bfd_ardata (abfd)->extended_names = NULL;
01031 return TRUE;
01032 }
01033
01034 namedata = _bfd_read_ar_hdr (abfd);
01035 if (namedata == NULL)
01036 return FALSE;
01037
01038 amt = namedata->parsed_size;
01039 bfd_ardata (abfd)->extended_names = bfd_zalloc (abfd, amt);
01040 if (bfd_ardata (abfd)->extended_names == NULL)
01041 {
01042 byebye:
01043 bfd_release (abfd, namedata);
01044 return FALSE;
01045 }
01046
01047 if (bfd_bread (bfd_ardata (abfd)->extended_names, amt, abfd) != amt)
01048 {
01049 if (bfd_get_error () != bfd_error_system_call)
01050 bfd_set_error (bfd_error_malformed_archive);
01051 bfd_release (abfd, (bfd_ardata (abfd)->extended_names));
01052 bfd_ardata (abfd)->extended_names = NULL;
01053 goto byebye;
01054 }
01055
01056
01057
01058
01059
01060
01061 {
01062 char *temp = bfd_ardata (abfd)->extended_names;
01063 char *limit = temp + namedata->parsed_size;
01064 for (; temp < limit; ++temp)
01065 {
01066 if (*temp == '\012')
01067 temp[temp[-1] == '/' ? -1 : 0] = '\0';
01068 if (*temp == '\\')
01069 *temp = '/';
01070 }
01071 }
01072
01073
01074 bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
01075 bfd_ardata (abfd)->first_file_filepos +=
01076 (bfd_ardata (abfd)->first_file_filepos) % 2;
01077
01078
01079
01080 }
01081 return TRUE;
01082 }
01083
01084 #ifdef VMS
01085
01086
01087
01088
01089 static const char *
01090 normalize (bfd *abfd, const char *file)
01091 {
01092 const char *first;
01093 const char *last;
01094 char *copy;
01095
01096 first = file + strlen (file) - 1;
01097 last = first + 1;
01098
01099 while (first != file)
01100 {
01101 if (*first == ';')
01102 last = first;
01103 if (*first == ':' || *first == ']' || *first == '>')
01104 {
01105 first++;
01106 break;
01107 }
01108 first--;
01109 }
01110
01111 copy = bfd_alloc (abfd, last - first + 1);
01112 if (copy == NULL)
01113 return NULL;
01114
01115 memcpy (copy, first, last - first);
01116 copy[last - first] = 0;
01117
01118 return copy;
01119 }
01120
01121 #else
01122 static const char *
01123 normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
01124 {
01125 const char *filename = strrchr (file, '/');
01126
01127 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
01128 {
01129
01130 char *bslash = strrchr (file, '\\');
01131 if (filename == NULL || (bslash != NULL && bslash > filename))
01132 filename = bslash;
01133 if (filename == NULL && file[0] != '\0' && file[1] == ':')
01134 filename = file + 1;
01135 }
01136 #endif
01137 if (filename != NULL)
01138 filename++;
01139 else
01140 filename = file;
01141 return filename;
01142 }
01143 #endif
01144
01145
01146
01147 bfd_boolean
01148 _bfd_archive_bsd_construct_extended_name_table (bfd *abfd,
01149 char **tabloc,
01150 bfd_size_type *tablen,
01151 const char **name)
01152 {
01153 *name = "ARFILENAMES/";
01154 return _bfd_construct_extended_name_table (abfd, FALSE, tabloc, tablen);
01155 }
01156
01157
01158
01159 bfd_boolean
01160 _bfd_archive_coff_construct_extended_name_table (bfd *abfd,
01161 char **tabloc,
01162 bfd_size_type *tablen,
01163 const char **name)
01164 {
01165 *name = "//";
01166 return _bfd_construct_extended_name_table (abfd, TRUE, tabloc, tablen);
01167 }
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177 bfd_boolean
01178 _bfd_construct_extended_name_table (bfd *abfd,
01179 bfd_boolean trailing_slash,
01180 char **tabloc,
01181 bfd_size_type *tablen)
01182 {
01183 unsigned int maxname = abfd->xvec->ar_max_namelen;
01184 bfd_size_type total_namelen = 0;
01185 bfd *current;
01186 char *strptr;
01187
01188 *tablen = 0;
01189
01190
01191 for (current = abfd->archive_head; current != NULL; current = current->next)
01192 {
01193 const char *normal;
01194 unsigned int thislen;
01195
01196 normal = normalize (current, current->filename);
01197 if (normal == NULL)
01198 return FALSE;
01199
01200 thislen = strlen (normal);
01201
01202 if (thislen > maxname
01203 && (bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
01204 thislen = maxname;
01205
01206 if (thislen > maxname)
01207 {
01208
01209 total_namelen += thislen + 1;
01210 if (trailing_slash)
01211 {
01212
01213 ++total_namelen;
01214 }
01215 }
01216 else
01217 {
01218 struct ar_hdr *hdr = arch_hdr (current);
01219 if (strncmp (normal, hdr->ar_name, thislen) != 0
01220 || (thislen < sizeof hdr->ar_name
01221 && hdr->ar_name[thislen] != ar_padchar (current)))
01222 {
01223
01224
01225 memcpy (hdr->ar_name, normal, thislen);
01226 if (thislen < maxname
01227 || (thislen == maxname && thislen < sizeof hdr->ar_name))
01228 hdr->ar_name[thislen] = ar_padchar (current);
01229 }
01230 }
01231 }
01232
01233 if (total_namelen == 0)
01234 return TRUE;
01235
01236 *tabloc = bfd_zalloc (abfd, total_namelen);
01237 if (*tabloc == NULL)
01238 return FALSE;
01239
01240 *tablen = total_namelen;
01241 strptr = *tabloc;
01242
01243 for (current = abfd->archive_head; current != NULL; current =
01244 current->next)
01245 {
01246 const char *normal;
01247 unsigned int thislen;
01248
01249 normal = normalize (current, current->filename);
01250 if (normal == NULL)
01251 return FALSE;
01252
01253 thislen = strlen (normal);
01254 if (thislen > maxname)
01255 {
01256
01257
01258
01259 struct ar_hdr *hdr = arch_hdr (current);
01260 strcpy (strptr, normal);
01261 if (! trailing_slash)
01262 strptr[thislen] = '\012';
01263 else
01264 {
01265 strptr[thislen] = '/';
01266 strptr[thislen + 1] = '\012';
01267 }
01268 hdr->ar_name[0] = ar_padchar (current);
01269
01270
01271 sprintf ((hdr->ar_name) + 1, "%-d", (unsigned) (strptr - *tabloc));
01272
01273
01274 {
01275 char *temp = hdr->ar_name + 2;
01276 for (; temp < hdr->ar_name + maxname; temp++)
01277 if (*temp == '\0')
01278 *temp = ' ';
01279 }
01280 strptr += thislen + 1;
01281 if (trailing_slash)
01282 ++strptr;
01283 }
01284 }
01285
01286 return TRUE;
01287 }
01288
01289
01290
01291 #ifdef HPUX_LARGE_AR_IDS
01292
01293
01294 static void
01295 hpux_uid_gid_encode (char str[6], long int id)
01296 {
01297 int cnt;
01298
01299 str[5] = '@' + (id & 3);
01300 id >>= 2;
01301
01302 for (cnt = 4; cnt >= 0; ++cnt, id >>= 6)
01303 str[cnt] = ' ' + (id & 0x3f);
01304 }
01305 #endif
01306
01307 #ifndef HAVE_GETUID
01308 #define getuid() 0
01309 #endif
01310
01311 #ifndef HAVE_GETGID
01312 #define getgid() 0
01313 #endif
01314
01315
01316
01317
01318
01319
01320 static struct areltdata *
01321 bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member)
01322 {
01323 struct stat status;
01324 struct areltdata *ared;
01325 struct ar_hdr *hdr;
01326 char *temp, *temp1;
01327 bfd_size_type amt;
01328
01329 if (member && (member->flags & BFD_IN_MEMORY) != 0)
01330 {
01331
01332 struct bfd_in_memory *bim = member->iostream;
01333 time (&status.st_mtime);
01334 status.st_uid = getuid ();
01335 status.st_gid = getgid ();
01336 status.st_mode = 0644;
01337 status.st_size = bim->size;
01338 }
01339 else if (stat (filename, &status) != 0)
01340 {
01341 bfd_set_error (bfd_error_system_call);
01342 return NULL;
01343 }
01344
01345 amt = sizeof (struct ar_hdr) + sizeof (struct areltdata);
01346 ared = bfd_zalloc (abfd, amt);
01347 if (ared == NULL)
01348 return NULL;
01349 hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
01350
01351
01352 memset (hdr, ' ', sizeof (struct ar_hdr));
01353
01354 strncpy (hdr->ar_fmag, ARFMAG, 2);
01355
01356
01357 sprintf ((hdr->ar_date), "%-12ld", (long) status.st_mtime);
01358 #ifdef HPUX_LARGE_AR_IDS
01359
01360
01361 if (status.st_uid > 99999)
01362 hpux_uid_gid_encode (hdr->ar_gid, (long) status.st_uid);
01363 else
01364 #endif
01365 sprintf ((hdr->ar_uid), "%ld", (long) status.st_uid);
01366 #ifdef HPUX_LARGE_AR_IDS
01367
01368
01369 if (status.st_gid > 99999)
01370 hpux_uid_gid_encode (hdr->ar_uid, (long) status.st_gid);
01371 else
01372 #endif
01373 sprintf ((hdr->ar_gid), "%ld", (long) status.st_gid);
01374 sprintf ((hdr->ar_mode), "%-8o", (unsigned int) status.st_mode);
01375 sprintf ((hdr->ar_size), "%-10ld", (long) status.st_size);
01376
01377
01378
01379 temp = (char *) hdr;
01380 temp1 = temp + sizeof (struct ar_hdr) - 2;
01381 for (; temp < temp1; temp++)
01382 {
01383 if (*temp == '\0')
01384 *temp = ' ';
01385 }
01386 strncpy (hdr->ar_fmag, ARFMAG, 2);
01387 ared->parsed_size = status.st_size;
01388 ared->arch_header = (char *) hdr;
01389
01390 return ared;
01391 }
01392
01393
01394
01395
01396
01397
01398 struct ar_hdr *bfd_special_undocumented_glue (bfd *, const char *);
01399
01400 struct ar_hdr *
01401 bfd_special_undocumented_glue (bfd *abfd, const char *filename)
01402 {
01403 struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename, 0);
01404 if (ar_elt == NULL)
01405 return NULL;
01406 return (struct ar_hdr *) ar_elt->arch_header;
01407 }
01408
01409
01410
01411 int
01412 bfd_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
01413 {
01414 struct ar_hdr *hdr;
01415 char *aloser;
01416
01417 if (abfd->arelt_data == NULL)
01418 {
01419 bfd_set_error (bfd_error_invalid_operation);
01420 return -1;
01421 }
01422
01423 hdr = arch_hdr (abfd);
01424
01425 #define foo(arelt, stelt, size) \
01426 buf->stelt = strtol (hdr->arelt, &aloser, size); \
01427 if (aloser == hdr->arelt) \
01428 return -1;
01429
01430
01431 #ifdef HPUX_LARGE_AR_IDS
01432 # define foo2(arelt, stelt, size) \
01433 if (hdr->arelt[5] == ' ') \
01434 { \
01435 foo (arelt, stelt, size); \
01436 } \
01437 else \
01438 { \
01439 int cnt; \
01440 for (buf->stelt = cnt = 0; cnt < 5; ++cnt) \
01441 { \
01442 if (hdr->arelt[cnt] < ' ' || hdr->arelt[cnt] > ' ' + 0x3f) \
01443 return -1; \
01444 buf->stelt <<= 6; \
01445 buf->stelt += hdr->arelt[cnt] - ' '; \
01446 } \
01447 if (hdr->arelt[5] < '@' || hdr->arelt[5] > '@' + 3) \
01448 return -1; \
01449 buf->stelt <<= 2; \
01450 buf->stelt += hdr->arelt[5] - '@'; \
01451 }
01452 #else
01453 # define foo2(arelt, stelt, size) foo (arelt, stelt, size)
01454 #endif
01455
01456 foo (ar_date, st_mtime, 10);
01457 foo2 (ar_uid, st_uid, 10);
01458 foo2 (ar_gid, st_gid, 10);
01459 foo (ar_mode, st_mode, 8);
01460
01461 buf->st_size = arch_eltdata (abfd)->parsed_size;
01462
01463 return 0;
01464 }
01465
01466 void
01467 bfd_dont_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
01468 {
01469
01470
01471
01472
01473
01474 struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
01475 size_t length;
01476 const char *filename;
01477 size_t maxlen = ar_maxnamelen (abfd);
01478
01479 if ((bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
01480 {
01481 bfd_bsd_truncate_arname (abfd, pathname, arhdr);
01482 return;
01483 }
01484
01485 filename = normalize (abfd, pathname);
01486 if (filename == NULL)
01487 {
01488
01489 abort ();
01490 }
01491
01492 length = strlen (filename);
01493
01494 if (length <= maxlen)
01495 memcpy (hdr->ar_name, filename, length);
01496
01497
01498 if (length < maxlen
01499 || (length == maxlen && length < sizeof hdr->ar_name))
01500 (hdr->ar_name)[length] = ar_padchar (abfd);
01501 }
01502
01503 void
01504 bfd_bsd_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
01505 {
01506 struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
01507 size_t length;
01508 const char *filename = strrchr (pathname, '/');
01509 size_t maxlen = ar_maxnamelen (abfd);
01510
01511 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
01512 {
01513
01514 char *bslash = strrchr (pathname, '\\');
01515 if (filename == NULL || (bslash != NULL && bslash > filename))
01516 filename = bslash;
01517 if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':')
01518 filename = pathname + 1;
01519 }
01520 #endif
01521
01522 if (filename == NULL)
01523 filename = pathname;
01524 else
01525 ++filename;
01526
01527 length = strlen (filename);
01528
01529 if (length <= maxlen)
01530 memcpy (hdr->ar_name, filename, length);
01531 else
01532 {
01533
01534 memcpy (hdr->ar_name, filename, maxlen);
01535 length = maxlen;
01536 }
01537
01538 if (length < maxlen)
01539 (hdr->ar_name)[length] = ar_padchar (abfd);
01540 }
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551 void
01552 bfd_gnu_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
01553 {
01554 struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
01555 size_t length;
01556 const char *filename = strrchr (pathname, '/');
01557 size_t maxlen = ar_maxnamelen (abfd);
01558
01559 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
01560 {
01561
01562 char *bslash = strrchr (pathname, '\\');
01563 if (filename == NULL || (bslash != NULL && bslash > filename))
01564 filename = bslash;
01565 if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':')
01566 filename = pathname + 1;
01567 }
01568 #endif
01569
01570 if (filename == NULL)
01571 filename = pathname;
01572 else
01573 ++filename;
01574
01575 length = strlen (filename);
01576
01577 if (length <= maxlen)
01578 memcpy (hdr->ar_name, filename, length);
01579 else
01580 {
01581 memcpy (hdr->ar_name, filename, maxlen);
01582 if ((filename[length - 2] == '.') && (filename[length - 1] == 'o'))
01583 {
01584 hdr->ar_name[maxlen - 2] = '.';
01585 hdr->ar_name[maxlen - 1] = 'o';
01586 }
01587 length = maxlen;
01588 }
01589
01590 if (length < 16)
01591 (hdr->ar_name)[length] = ar_padchar (abfd);
01592 }
01593
01594
01595
01596 bfd_boolean
01597 _bfd_write_archive_contents (bfd *arch)
01598 {
01599 bfd *current;
01600 char *etable = NULL;
01601 bfd_size_type elength = 0;
01602 const char *ename = NULL;
01603 bfd_boolean makemap = bfd_has_map (arch);
01604
01605 bfd_boolean hasobjects = FALSE;
01606 bfd_size_type wrote;
01607 unsigned int i;
01608 int tries;
01609
01610
01611
01612
01613 for (current = arch->archive_head; current; current = current->next)
01614 {
01615
01616
01617
01618
01619
01620 if (bfd_write_p (current))
01621 {
01622 bfd_set_error (bfd_error_invalid_operation);
01623 return FALSE;
01624 }
01625 if (!current->arelt_data)
01626 {
01627 current->arelt_data =
01628 bfd_ar_hdr_from_filesystem (arch, current->filename, current);
01629 if (!current->arelt_data)
01630 return FALSE;
01631
01632
01633 BFD_SEND (arch, _bfd_truncate_arname,
01634 (arch, current->filename, (char *) arch_hdr (current)));
01635 }
01636
01637 if (makemap && ! hasobjects)
01638 {
01639 if ((bfd_check_format (current, bfd_object)))
01640 hasobjects = TRUE;
01641 }
01642 }
01643
01644 if (!BFD_SEND (arch, _bfd_construct_extended_name_table,
01645 (arch, &etable, &elength, &ename)))
01646 return FALSE;
01647
01648 if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0)
01649 return FALSE;
01650 wrote = bfd_bwrite (ARMAG, SARMAG, arch);
01651 if (wrote != SARMAG)
01652 return FALSE;
01653
01654 if (makemap && hasobjects)
01655 {
01656 if (! _bfd_compute_and_write_armap (arch, (unsigned int) elength))
01657 return FALSE;
01658 }
01659
01660 if (elength != 0)
01661 {
01662 struct ar_hdr hdr;
01663
01664 memset (&hdr, 0, sizeof (struct ar_hdr));
01665 strcpy (hdr.ar_name, ename);
01666
01667 sprintf (&(hdr.ar_size[0]), "%-10d",
01668 (int) ((elength + 1) & ~(bfd_size_type) 1));
01669 strncpy (hdr.ar_fmag, ARFMAG, 2);
01670 for (i = 0; i < sizeof (struct ar_hdr); i++)
01671 if (((char *) (&hdr))[i] == '\0')
01672 (((char *) (&hdr))[i]) = ' ';
01673 if ((bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
01674 != sizeof (struct ar_hdr))
01675 || bfd_bwrite (etable, elength, arch) != elength)
01676 return FALSE;
01677 if ((elength % 2) == 1)
01678 {
01679 if (bfd_bwrite ("\012", 1, arch) != 1)
01680 return FALSE;
01681 }
01682 }
01683
01684 for (current = arch->archive_head; current; current = current->next)
01685 {
01686 char buffer[DEFAULT_BUFFERSIZE];
01687 unsigned int remaining = arelt_size (current);
01688 struct ar_hdr *hdr = arch_hdr (current);
01689
01690
01691 if (bfd_bwrite (hdr, sizeof (*hdr), arch)
01692 != sizeof (*hdr))
01693 return FALSE;
01694 if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0)
01695 return FALSE;
01696 while (remaining)
01697 {
01698 unsigned int amt = DEFAULT_BUFFERSIZE;
01699 if (amt > remaining)
01700 amt = remaining;
01701 errno = 0;
01702 if (bfd_bread (buffer, amt, current) != amt)
01703 {
01704 if (bfd_get_error () != bfd_error_system_call)
01705 bfd_set_error (bfd_error_malformed_archive);
01706 return FALSE;
01707 }
01708 if (bfd_bwrite (buffer, amt, arch) != amt)
01709 return FALSE;
01710 remaining -= amt;
01711 }
01712 if ((arelt_size (current) % 2) == 1)
01713 {
01714 if (bfd_bwrite ("\012", 1, arch) != 1)
01715 return FALSE;
01716 }
01717 }
01718
01719 if (makemap && hasobjects)
01720 {
01721
01722
01723
01724
01725
01726
01727 tries = 1;
01728 do
01729 {
01730 if (bfd_update_armap_timestamp (arch))
01731 break;
01732 (*_bfd_error_handler)
01733 (_("Warning: writing archive was slow: rewriting timestamp\n"));
01734 }
01735 while (++tries < 6);
01736 }
01737
01738 return TRUE;
01739 }
01740
01741
01742
01743 bfd_boolean
01744 _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
01745 {
01746 char *first_name = NULL;
01747 bfd *current;
01748 file_ptr elt_no = 0;
01749 struct orl *map = NULL;
01750 unsigned int orl_max = 1024;
01751 unsigned int orl_count = 0;
01752 int stridx = 0;
01753 asymbol **syms = NULL;
01754 long syms_max = 0;
01755 bfd_boolean ret;
01756 bfd_size_type amt;
01757
01758
01759 if (elength != 0)
01760 elength += sizeof (struct ar_hdr);
01761 elength += elength % 2;
01762
01763 amt = orl_max * sizeof (struct orl);
01764 map = bfd_malloc (amt);
01765 if (map == NULL)
01766 goto error_return;
01767
01768
01769
01770 first_name = bfd_alloc (arch, 1);
01771 if (first_name == NULL)
01772 goto error_return;
01773
01774
01775 while (arch->archive_head &&
01776 strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
01777 arch->archive_head = arch->archive_head->next;
01778
01779
01780 for (current = arch->archive_head;
01781 current != NULL;
01782 current = current->next, elt_no++)
01783 {
01784 if (bfd_check_format (current, bfd_object)
01785 && (bfd_get_file_flags (current) & HAS_SYMS) != 0)
01786 {
01787 long storage;
01788 long symcount;
01789 long src_count;
01790
01791 storage = bfd_get_symtab_upper_bound (current);
01792 if (storage < 0)
01793 goto error_return;
01794
01795 if (storage != 0)
01796 {
01797 if (storage > syms_max)
01798 {
01799 if (syms_max > 0)
01800 free (syms);
01801 syms_max = storage;
01802 syms = bfd_malloc (syms_max);
01803 if (syms == NULL)
01804 goto error_return;
01805 }
01806 symcount = bfd_canonicalize_symtab (current, syms);
01807 if (symcount < 0)
01808 goto error_return;
01809
01810
01811
01812 for (src_count = 0; src_count < symcount; src_count++)
01813 {
01814 flagword flags = (syms[src_count])->flags;
01815 asection *sec = syms[src_count]->section;
01816
01817 if ((flags & BSF_GLOBAL ||
01818 flags & BSF_WEAK ||
01819 flags & BSF_INDIRECT ||
01820 bfd_is_com_section (sec))
01821 && ! bfd_is_und_section (sec))
01822 {
01823 bfd_size_type namelen;
01824 struct orl *new_map;
01825
01826
01827 if (orl_count == orl_max)
01828 {
01829 orl_max *= 2;
01830 amt = orl_max * sizeof (struct orl);
01831 new_map = bfd_realloc (map, amt);
01832 if (new_map == NULL)
01833 goto error_return;
01834
01835 map = new_map;
01836 }
01837
01838 namelen = strlen (syms[src_count]->name);
01839 amt = sizeof (char *);
01840 map[orl_count].name = bfd_alloc (arch, amt);
01841 if (map[orl_count].name == NULL)
01842 goto error_return;
01843 *(map[orl_count].name) = bfd_alloc (arch, namelen + 1);
01844 if (*(map[orl_count].name) == NULL)
01845 goto error_return;
01846 strcpy (*(map[orl_count].name), syms[src_count]->name);
01847 map[orl_count].u.abfd = current;
01848 map[orl_count].namidx = stridx;
01849
01850 stridx += namelen + 1;
01851 ++orl_count;
01852 }
01853 }
01854 }
01855
01856
01857
01858 if (! bfd_free_cached_info (current))
01859 goto error_return;
01860 }
01861 }
01862
01863
01864 ret = BFD_SEND (arch, write_armap,
01865 (arch, elength, map, orl_count, stridx));
01866
01867 if (syms_max > 0)
01868 free (syms);
01869 if (map != NULL)
01870 free (map);
01871 if (first_name != NULL)
01872 bfd_release (arch, first_name);
01873
01874 return ret;
01875
01876 error_return:
01877 if (syms_max > 0)
01878 free (syms);
01879 if (map != NULL)
01880 free (map);
01881 if (first_name != NULL)
01882 bfd_release (arch, first_name);
01883
01884 return FALSE;
01885 }
01886
01887 bfd_boolean
01888 bsd_write_armap (bfd *arch,
01889 unsigned int elength,
01890 struct orl *map,
01891 unsigned int orl_count,
01892 int stridx)
01893 {
01894 int padit = stridx & 1;
01895 unsigned int ranlibsize = orl_count * BSD_SYMDEF_SIZE;
01896 unsigned int stringsize = stridx + padit;
01897
01898 unsigned int mapsize = ranlibsize + stringsize + 8;
01899 file_ptr firstreal;
01900 bfd *current = arch->archive_head;
01901 bfd *last_elt = current;
01902 bfd_byte temp[4];
01903 unsigned int count;
01904 struct ar_hdr hdr;
01905 struct stat statbuf;
01906 unsigned int i;
01907
01908 firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
01909
01910 stat (arch->filename, &statbuf);
01911 memset (&hdr, 0, sizeof (struct ar_hdr));
01912 sprintf (hdr.ar_name, RANLIBMAG);
01913
01914 bfd_ardata (arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET;
01915 bfd_ardata (arch)->armap_datepos = (SARMAG
01916 + offsetof (struct ar_hdr, ar_date[0]));
01917 sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp);
01918 sprintf (hdr.ar_uid, "%ld", (long) getuid ());
01919 sprintf (hdr.ar_gid, "%ld", (long) getgid ());
01920 sprintf (hdr.ar_size, "%-10d", (int) mapsize);
01921 strncpy (hdr.ar_fmag, ARFMAG, 2);
01922 for (i = 0; i < sizeof (struct ar_hdr); i++)
01923 if (((char *) (&hdr))[i] == '\0')
01924 (((char *) (&hdr))[i]) = ' ';
01925 if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
01926 != sizeof (struct ar_hdr))
01927 return FALSE;
01928 H_PUT_32 (arch, ranlibsize, temp);
01929 if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
01930 return FALSE;
01931
01932 for (count = 0; count < orl_count; count++)
01933 {
01934 bfd_byte buf[BSD_SYMDEF_SIZE];
01935
01936 if (map[count].u.abfd != last_elt)
01937 {
01938 do
01939 {
01940 firstreal += arelt_size (current) + sizeof (struct ar_hdr);
01941 firstreal += firstreal % 2;
01942 current = current->next;
01943 }
01944 while (current != map[count].u.abfd);
01945 }
01946
01947 last_elt = current;
01948 H_PUT_32 (arch, map[count].namidx, buf);
01949 H_PUT_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE);
01950 if (bfd_bwrite (buf, BSD_SYMDEF_SIZE, arch)
01951 != BSD_SYMDEF_SIZE)
01952 return FALSE;
01953 }
01954
01955
01956 H_PUT_32 (arch, stringsize, temp);
01957 if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
01958 return FALSE;
01959 for (count = 0; count < orl_count; count++)
01960 {
01961 size_t len = strlen (*map[count].name) + 1;
01962
01963 if (bfd_bwrite (*map[count].name, len, arch) != len)
01964 return FALSE;
01965 }
01966
01967
01968
01969 if (padit)
01970 {
01971 if (bfd_bwrite ("", 1, arch) != 1)
01972 return FALSE;
01973 }
01974
01975 return TRUE;
01976 }
01977
01978
01979
01980
01981
01982
01983
01984 bfd_boolean
01985 _bfd_archive_bsd_update_armap_timestamp (bfd *arch)
01986 {
01987 struct stat archstat;
01988 struct ar_hdr hdr;
01989 unsigned int i;
01990
01991
01992
01993 bfd_flush (arch);
01994 if (bfd_stat (arch, &archstat) == -1)
01995 {
01996 bfd_perror (_("Reading archive file mod timestamp"));
01997
01998
01999 return TRUE;
02000 }
02001 if (archstat.st_mtime <= bfd_ardata (arch)->armap_timestamp)
02002
02003 return TRUE;
02004
02005
02006 bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET;
02007
02008
02009 memset (hdr.ar_date, 0, sizeof (hdr.ar_date));
02010 sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp);
02011 for (i = 0; i < sizeof (hdr.ar_date); i++)
02012 if (hdr.ar_date[i] == '\0')
02013 (hdr.ar_date)[i] = ' ';
02014
02015
02016 bfd_ardata (arch)->armap_datepos = (SARMAG
02017 + offsetof (struct ar_hdr, ar_date[0]));
02018 if (bfd_seek (arch, bfd_ardata (arch)->armap_datepos, SEEK_SET) != 0
02019 || (bfd_bwrite (hdr.ar_date, sizeof (hdr.ar_date), arch)
02020 != sizeof (hdr.ar_date)))
02021 {
02022 bfd_perror (_("Writing updated armap timestamp"));
02023
02024
02025 return TRUE;
02026 }
02027
02028
02029 return FALSE;
02030 }
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045 bfd_boolean
02046 coff_write_armap (bfd *arch,
02047 unsigned int elength,
02048 struct orl *map,
02049 unsigned int symbol_count,
02050 int stridx)
02051 {
02052
02053
02054 unsigned int ranlibsize = (symbol_count * 4) + 4;
02055 unsigned int stringsize = stridx;
02056 unsigned int mapsize = stringsize + ranlibsize;
02057 unsigned int archive_member_file_ptr;
02058 bfd *current = arch->archive_head;
02059 unsigned int count;
02060 struct ar_hdr hdr;
02061 unsigned int i;
02062 int padit = mapsize & 1;
02063
02064 if (padit)
02065 mapsize++;
02066
02067
02068 archive_member_file_ptr = (mapsize
02069 + elength
02070 + sizeof (struct ar_hdr)
02071 + SARMAG);
02072
02073 memset (&hdr, 0, sizeof (struct ar_hdr));
02074 hdr.ar_name[0] = '/';
02075 sprintf (hdr.ar_size, "%-10d", (int) mapsize);
02076 sprintf (hdr.ar_date, "%ld", (long) time (NULL));
02077
02078 sprintf ((hdr.ar_uid), "%d", 0);
02079 sprintf ((hdr.ar_gid), "%d", 0);
02080 sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0);
02081 strncpy (hdr.ar_fmag, ARFMAG, 2);
02082
02083 for (i = 0; i < sizeof (struct ar_hdr); i++)
02084 if (((char *) (&hdr))[i] == '\0')
02085 (((char *) (&hdr))[i]) = ' ';
02086
02087
02088 if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
02089 != sizeof (struct ar_hdr))
02090 return FALSE;
02091
02092 if (!bfd_write_bigendian_4byte_int (arch, symbol_count))
02093 return FALSE;
02094
02095
02096
02097
02098
02099
02100
02101 current = arch->archive_head;
02102 count = 0;
02103 while (current != NULL && count < symbol_count)
02104 {
02105
02106
02107
02108 while (count < symbol_count && map[count].u.abfd == current)
02109 {
02110 if (!bfd_write_bigendian_4byte_int (arch, archive_member_file_ptr))
02111 return FALSE;
02112 count++;
02113 }
02114
02115 archive_member_file_ptr += arelt_size (current) + sizeof (struct ar_hdr);
02116
02117 archive_member_file_ptr += archive_member_file_ptr % 2;
02118 current = current->next;
02119 }
02120
02121
02122 for (count = 0; count < symbol_count; count++)
02123 {
02124 size_t len = strlen (*map[count].name) + 1;
02125
02126 if (bfd_bwrite (*map[count].name, len, arch) != len)
02127 return FALSE;
02128 }
02129
02130
02131
02132 if (padit)
02133 {
02134 if (bfd_bwrite ("", 1, arch) != 1)
02135 return FALSE;
02136 }
02137
02138 return TRUE;
02139 }