*** empty log message ***
[deliverable/binutils-gdb.git] / bfd / archive.c
CommitLineData
4a81b561
DHW
1/*** archive.c -- an attempt at combining the machine-independent parts of
2 archives */
3
4/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
5
6This file is part of BFD, the Binary File Diddler.
7
8BFD is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 1, or (at your option)
11any later version.
12
13BFD is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with BFD; see the file COPYING. If not, write to
20the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22
23/* Assumes:
24 o - all archive elements start on an even boundary, newline padded;
25 o - all arch headers are char *;
26 o - all arch headers are the same size (across architectures).
27*/
28
29/* $Id$
30 * $Log$
0452b5aa
SC
31 * Revision 1.2 1991/04/03 22:09:43 steve
32 * Various noise
33 *
34 * Revision 1.1.1.1 1991/03/21 21:10:42 gumby
35 * Back from Intel with Steve
36 *
37 * Revision 1.1 1991/03/21 21:10:42 gumby
4a81b561
DHW
38 * Initial revision
39 *
40 * Revision 1.3 1991/03/16 05:55:25 rich
41 * pop
42 *
43 * Revision 1.2 1991/03/15 18:15:50 rich
44 * *** empty log message ***
45 *
46 * Revision 1.7 1991/03/08 04:18:02 rich
47 * *** empty log message ***
48 *
49 * Revision 1.6 1991/03/07 21:55:31 sac
50 * Added primitive file caching, a file open only for input and
51 * less than BFD_INCORE_FILE_SIZE will be malloced and read in
52 * only once.
53 *
54 * Revision 1.5 1991/03/05 16:31:12 sac
55 * lint
56 *
57 */
58
59
60#include "sysdep.h"
61#include "bfd.h"
62#include "libbfd.h"
63#include "ar.h"
64#include "ranlib.h"
65
66/* We keep a cache of archive filepointers to archive elements to
67 speed up searching the archive by filepos. We only add an entry to
68 the cache when we actually read one. We also don't sort the cache;
69 it's short enough to search linearly.
70 Note that the pointers here point to the front of the ar_hdr, not
71 to the front of the contents!
72*/
73struct ar_cache {
74 file_ptr ptr;
75 bfd* arelt;
76 struct ar_cache *next;
77};
78
79#define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
80#define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
81
82#define arch_hdr(bfd) ((struct ar_hdr *) \
83 (((struct areltdata *)((bfd)->arelt_data))->arch_header))
84
85\f
86
87boolean
88_bfd_generic_mkarchive (abfd)
89 bfd *abfd;
90{
91 abfd->tdata =(void *) zalloc (sizeof (struct artdata));
92
93 if (abfd->tdata == NULL) {
94 bfd_error = no_memory;
95 return false;
96 }
97bfd_ardata(abfd)->cache = 0;
98 return true;
99}
100
101symindex
102bfd_get_next_mapent (abfd, prev, entry)
103 bfd *abfd;
104 symindex prev;
105 carsym **entry;
106{
107 if (!bfd_has_map (abfd)) {
108 bfd_error = invalid_operation;
109 return BFD_NO_MORE_SYMBOLS;
110 }
111
112 if (prev == BFD_NO_MORE_SYMBOLS) prev = 0;
113 else if (++prev >= (symindex)(bfd_ardata (abfd)->symdef_count))
114 return BFD_NO_MORE_SYMBOLS;
115
116 *entry = (bfd_ardata (abfd)->symdefs + prev);
117 return prev;
118}
119
120
121/* To be called by backends only */
122bfd *
123_bfd_create_empty_archive_element_shell (obfd)
124 bfd *obfd;
125{
126 bfd *nbfd;
127
128 nbfd = new_bfd_contained_in(obfd);
129 if (nbfd == NULL) {
130 bfd_error = no_memory;
131 return NULL;
132 }
133 return nbfd;
134}
135
136boolean
137bfd_set_archive_head (output_archive, new_head)
138 bfd *output_archive, *new_head;
139{
140
141 output_archive->archive_head = new_head;
142 return true;
143}
144
145bfd *
146look_for_bfd_in_cache (arch_bfd, filepos)
147 bfd *arch_bfd;
148 file_ptr filepos;
149{
150 struct ar_cache *current;
151
152 for (current = bfd_ardata (arch_bfd)->cache; current != NULL;
153 current = current->next)
154 if (current->ptr == filepos) return current->arelt;
155
156 return NULL;
157}
158
159/* Kind of stupid to call cons for each one, but we don't do too many */
160boolean
161add_bfd_to_cache (arch_bfd, filepos, new_elt)
162 bfd *arch_bfd, *new_elt;
163 file_ptr filepos;
164{
165 struct ar_cache *new_cache = ((struct ar_cache *)
166 zalloc (sizeof (struct ar_cache)));
167
168 if (new_cache == NULL) {
169 bfd_error = no_memory;
170 return false;
171 }
172
173 new_cache->ptr = filepos;
174 new_cache->arelt = new_elt;
175 new_cache->next = (struct ar_cache *)NULL;
176 if (bfd_ardata (arch_bfd)->cache == NULL)
177 bfd_ardata (arch_bfd)->cache = new_cache;
178 else {
179 struct ar_cache *current = bfd_ardata (arch_bfd)->cache;
180
181 for (; current->next != NULL; current = current->next);
182 current->next = new_cache;
183 }
184
185 return true;
186}
187
188\f
189
190/* The name begins with space. Hence the rest of the name is an index into
191 the string table. */
192
193char *
194get_extended_arelt_filename (arch, name)
195 bfd *arch;
196 char *name;
197{
198 extern int errno;
199 unsigned long index = 0;
200
201 /* Should extract string so that I can guarantee not to overflow into
202 the next region, but I"m too lazy. */
203 errno = 0;
204 index = strtol (name, NULL, 10);
205 if (errno != 0) {
206 bfd_error = malformed_archive;
207 return NULL;
208 }
209
210 return bfd_ardata (arch)->extended_names + index;
211}
212
213/* This functions reads an arch header and returns an areltdata pointer, or
214 NULL on error.
215
216 Presumes the file pointer is already in the right place (ie pointing
217 to the ar_hdr in the file). Moves the file pointer; on success it
218 should be pointing to the front of the file contents; on failure it
219 could have been moved arbitrarily.
220*/
221
222struct areltdata *
223snarf_ar_hdr (abfd)
224 bfd *abfd;
225{
226 extern int errno;
227 struct ar_hdr hdr;
228 char *hdrp = (char *) &hdr;
229 unsigned int parsed_size;
230 struct areltdata *ared;
231 char *filename = NULL;
232 unsigned int namelen = 0;
233 unsigned int allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
234 char *allocptr;
235
236 if (bfd_read ((void *)hdrp, 1, sizeof (struct ar_hdr), abfd)
237 != sizeof (struct ar_hdr)) {
238 bfd_error = no_more_archived_files;
239 return NULL;
240 }
241 if (strncmp ((hdr.ar_fmag), ARFMAG, 2)) {
242 bfd_error = malformed_archive;
243 return NULL;
244 }
245
246 errno = 0;
247 parsed_size = strtol (hdr.ar_size, NULL, 10);
248 if (errno != 0) {
249 bfd_error = malformed_archive;
250 return NULL;
251 }
252
253 /* extract the filename from the archive */
254 if (hdr.ar_name[0] == ' ' && bfd_ardata (abfd)->extended_names != NULL) {
255 filename = get_extended_arelt_filename (abfd, hdr.ar_name);
256 if (filename == NULL) {
257 bfd_error = malformed_archive;
258 return NULL;
259 }
260 }
261 else
262 {
263 /* We judge the end of the name by looking for a space or a
264 padchar */
265
266 namelen = 0;
267
0452b5aa 268 while (namelen < (unsigned)ar_maxnamelen(abfd) &&
4a81b561
DHW
269 ( hdr.ar_name[namelen] != 0 &&
270 hdr.ar_name[namelen] != ' ' &&
271 hdr.ar_name[namelen] != ar_padchar(abfd))) {
272 namelen++;
273 }
274
275 allocsize += namelen + 1;
276 }
277
278 allocptr = zalloc (allocsize);
279 if (allocptr == NULL) {
280 bfd_error = no_memory;
281 return NULL;
282 }
283
284 ared = (struct areltdata *) allocptr;
285
286 ared->arch_header = allocptr + sizeof (struct areltdata);
287 memcpy ((char *) ared->arch_header, &hdr, sizeof (struct ar_hdr));
288 ared->parsed_size = parsed_size;
289
290 if (filename != NULL) ared->filename = filename;
291 else {
292 ared->filename = allocptr + (sizeof (struct areltdata) +
293 sizeof (struct ar_hdr));
294 if (namelen)
295 memcpy (ared->filename, hdr.ar_name, namelen);
296 ared->filename[namelen] = '\0';
297 }
298
299 return ared;
300}
301\f
302bfd *
303get_elt_at_filepos (archive, filepos)
304 bfd *archive;
305 file_ptr filepos;
306{
307 struct areltdata *new_areldata;
308 bfd *n_nfd;
309
310 n_nfd = look_for_bfd_in_cache (archive, filepos);
311 if (n_nfd) return n_nfd;
312
313 if (0 > bfd_seek (archive, filepos, SEEK_SET)) {
314 bfd_error = system_call_error;
315 return NULL;
316 }
317
318 if ((new_areldata = snarf_ar_hdr (archive)) == NULL) return NULL;
319
320 n_nfd = _bfd_create_empty_archive_element_shell (archive);
321 if (n_nfd == NULL) {
322 free (new_areldata);
323 return NULL;
324 }
325 n_nfd->origin = bfd_tell (archive);
326 n_nfd->arelt_data = (void *) new_areldata;
327 n_nfd->filename = new_areldata->filename;
328
329 if (add_bfd_to_cache (archive, filepos, n_nfd))
330 return n_nfd;
331
332 /* huh? */
333 free (new_areldata);
334 free (n_nfd);
335 return NULL;
336}
337
338bfd *
339bfd_get_elt_at_index (abfd, index)
340 bfd *abfd;
341 int index;
342{
343 bfd *result =
344 get_elt_at_filepos
345 (abfd, (bfd_ardata (abfd)->symdefs + index)->file_offset);
346 return result;
347}
348
349/* If you've got an archive, call this to read each subfile. */
350bfd *
351bfd_openr_next_archived_file (archive, last_file)
352 bfd *archive, *last_file;
353{
354
355 if ((bfd_get_format (archive) != bfd_archive) ||
356 (archive->direction == write_direction)) {
357 bfd_error = invalid_operation;
358 return NULL;
359 }
360
361
362 return BFD_SEND (archive,
363 openr_next_archived_file,
364 (archive,
365 last_file));
366
367}
368
369bfd *bfd_generic_openr_next_archived_file(archive, last_file)
370 bfd *archive;
371 bfd *last_file;
372{
373 file_ptr filestart;
374
375 if (!last_file)
376 filestart = bfd_ardata (archive)->first_file_filepos;
377 else {
378 unsigned int size = arelt_size(last_file);
379 filestart = last_file->origin +size + size %2;
380}
381
382
383
384 return get_elt_at_filepos (archive, filestart);
385}
386\f
387
388bfd_target *
389bfd_generic_archive_p (abfd)
390 bfd *abfd;
391{
392 char armag[SARMAG+1];
393
394 if (bfd_read ((void *)armag, 1, SARMAG, abfd) != SARMAG) {
395 bfd_error = wrong_format;
396 return 0;
397 }
398
399 if (strncmp (armag, ARMAG, SARMAG)) return 0;
400
401 bfd_set_ardata(abfd, (struct artdata *) zalloc (sizeof (struct artdata)));
402
403 if (bfd_ardata (abfd) == NULL) {
404 bfd_error = no_memory;
405 return 0;
406 }
407
408 bfd_ardata (abfd)->first_file_filepos = SARMAG;
409
410 if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))) {
411 free (bfd_ardata (abfd));
412 abfd->tdata = NULL;
413 return 0;
414 }
415
416 /* armap could be left ungc'd! FIXME -- potential storage leak */
417 if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) {
418 free (bfd_ardata (abfd));
419 abfd->tdata = NULL;
420 return 0;
421 }
422
423 return abfd->xvec;
424}
425
426/* Returns false on error, true otherwise */
427boolean
428bfd_slurp_bsd_armap (abfd)
429 bfd *abfd;
430{
431 struct areltdata *mapdata;
432 char nextname[17];
433 unsigned int counter = 0;
434 int *raw_armap, *rbase;
435 struct artdata *ardata = bfd_ardata (abfd);
436 char *stringbase;
437
438 if (bfd_read ((void *)nextname, 1, 16, abfd) == 16) {
439 /* The archive has at least 16 bytes in it */
440 bfd_seek (abfd, -16L, SEEK_CUR);
441
442 if (strncmp (nextname, "__.SYMDEF ", 16)) {
443 bfd_has_map (abfd) = false;
444 return true;
445 }
446
447 mapdata = snarf_ar_hdr (abfd);
448 if (mapdata == NULL) return false;
449
450 raw_armap = (int *) zalloc (mapdata->parsed_size);
451 if (raw_armap == NULL) {
452 bfd_error = no_memory;
453 byebye:
454 free (mapdata);
455 return false;
456 }
457
458 if (bfd_read ((void *)raw_armap, 1, mapdata->parsed_size, abfd) !=
459 mapdata->parsed_size) {
460 bfd_error = malformed_archive;
461 free (raw_armap);
462 goto byebye;
463 }
464
465 ardata->symdef_count = *(raw_armap) / sizeof (struct symdef);
466 ardata->cache = 0;
467 rbase = raw_armap+1;
468 ardata->symdefs = (carsym *) rbase;
469 stringbase = ((char *) (ardata->symdefs + ardata->symdef_count)) + 4;
470
471 for (;counter < (unsigned)( ardata->symdef_count); counter++) {
472 struct symdef *sym = ((struct symdef *) rbase) + counter;
473 sym->s.name = sym->s.string_offset + stringbase;
474 }
475
476 ardata->first_file_filepos = bfd_tell (abfd);
477 /* Pad to an even boundary if you have to */
478 ardata->first_file_filepos += (ardata-> first_file_filepos) %2;
479 free (mapdata);
480 bfd_has_map (abfd) = true;
481 }
482 return true;
483}
484
485/* Returns false on error, true otherwise */
486boolean
487bfd_slurp_coff_armap (abfd)
488 bfd *abfd;
489{
490 struct areltdata *mapdata;
491 char nextname;
492 int *raw_armap, *rawptr;
493 struct artdata *ardata = bfd_ardata (abfd);
494 char *stringbase;
495 unsigned int stringsize;
496 carsym *carsyms;
497
498 if (bfd_read ((void *)&nextname, 1, 1, abfd) != 1) {
499 bfd_has_map(abfd) = false;
500 return true;
501 }
502
503 if (nextname != '/') {
504 /* Actually I think this is an error for a COFF archive */
505 bfd_has_map (abfd) = false;
506 return true;
507 }
508
509 bfd_seek (abfd, -1L, SEEK_CUR);
510 mapdata = snarf_ar_hdr (abfd);
511 if (mapdata == NULL) return false;
512
513 raw_armap = (int *) zalloc (mapdata->parsed_size);
514 if (raw_armap == NULL) {
515 bfd_error = no_memory;
516 byebye:
517 free (mapdata);
518 return false;
519 }
520
521 if (bfd_read ((void *)raw_armap, 1, mapdata->parsed_size, abfd) !=
522 mapdata->parsed_size) {
523 bfd_error = malformed_archive;
524 oops:
525 free (raw_armap);
526 goto byebye;
527 }
528
529 /* The coff armap must be read sequentially. So we construct a bsd-style
530 one in core all at once, for simplicity. */
531
532 stringsize = mapdata->parsed_size - (4 * (*raw_armap)) - 4;
533
534 {
535 unsigned int nsymz = *raw_armap;
536 unsigned int carsym_size = (nsymz * sizeof (carsym));
537 unsigned int ptrsize = (4 * nsymz);
538 unsigned int i;
539 ardata->symdefs = (carsym *) zalloc (carsym_size + stringsize + 1);
540 if (ardata->symdefs == NULL) {
541 bfd_error = no_memory;
542 goto oops;
543 }
544 carsyms = ardata->symdefs;
545
546 stringbase = ((char *) ardata->symdefs) + carsym_size;
547 memcpy (stringbase, (char*)raw_armap + ptrsize + 4, stringsize);
548
549
550 /* OK, build the carsyms */
551 for (i = 0; i < nsymz; i++)
552 {
553 rawptr = raw_armap + i + 1;
554 carsyms->file_offset = *rawptr;
555 carsyms->name = stringbase;
556 for (; *(stringbase++););
557 carsyms++;
558 }
559 *stringbase = 0;
560 }
561 ardata->symdef_count = *raw_armap;
562 ardata->first_file_filepos = bfd_tell (abfd);
563 /* Pad to an even boundary if you have to */
564 ardata->first_file_filepos += (ardata->first_file_filepos) %2;
565 free (raw_armap);
566 free (mapdata);
567 bfd_has_map (abfd) = true;
568 return true;
569}
570
571\f
572/** Extended name table.
573
574 Normally archives support only 14-character filenames. Intel has extended
575 the format: longer names are stored in a special element (the first in the
576 archive, or second if there is an armap); the name in the ar_hdr is replaced
577 by <space><index into filename element>. Index is the P.R. of an int (radix:
578 8). */
579
580/* Returns false on error, true otherwise */
581boolean
582_bfd_slurp_extended_name_table (abfd)
583 bfd *abfd;
584{
585 char nextname[17];
586 struct areltdata *namedata;
587
588 if (bfd_read ((void *)nextname, 1, 16, abfd) == 16) {
589
590 bfd_seek (abfd, -16L, SEEK_CUR);
591
592 if (strncmp (nextname, "ARFILENAMES/ ", 16)) {
593 bfd_ardata (abfd)->extended_names = NULL;
594 return true;
595 }
596
597 namedata = snarf_ar_hdr (abfd);
598 if (namedata == NULL) return false;
599
600
601 bfd_ardata (abfd)->extended_names = zalloc (namedata->parsed_size);
602 if (bfd_ardata (abfd)->extended_names == NULL) {
603 bfd_error = no_memory;
604 byebye:
605 free (namedata);
606 return false;
607 }
608
609 if (bfd_read ((void*)bfd_ardata (abfd)->extended_names, 1,
610 namedata->parsed_size, abfd) != namedata->parsed_size) {
611 bfd_error = malformed_archive;
612 free (bfd_ardata (abfd)->extended_names);
613 bfd_ardata (abfd)->extended_names = NULL;
614 goto byebye;
615 }
616
617 /* Pad to an even boundary if you have to */
618 bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
619 bfd_ardata (abfd)->first_file_filepos +=
620 (bfd_ardata (abfd)->first_file_filepos) %2;
621
622 free (namedata);
623}
624 return true;
625}
626
627static
628char *normalize(file)
629char *file;
630{
631 char * filename = strrchr(file, '/');
632 if (filename != (char *)NULL) {
633 filename ++;
634 }
635 else {
636 filename = file;
637 }
638return filename;
639}
640
641/* Follows archive_head and produces an extended name table if necessary.
642 Returns (in tabloc) a pointer to an extended name table, and in tablen
643 the length of the table. If it makes an entry it clobbers the filename
644 so that the element may be written without further massage.
645 Returns true if it ran successfully, false if something went wrong.
646 A successful return may still involve a zero-length tablen!
647 */
648boolean
649bfd_construct_extended_name_table (abfd, tabloc, tablen)
650 bfd *abfd;
651 char **tabloc;
652 unsigned int *tablen;
653{
654 unsigned int maxname = abfd->xvec->ar_max_namelen;
655 unsigned int total_namelen = 0;
656 bfd *current;
657 char *strptr;
658
659 *tablen = 0;
660
661 /* Figure out how long the table should be */
662 for (current = abfd->archive_head; current != NULL; current = current->next){
663 unsigned int thislen = strlen (normalize(current->filename));
664 if (thislen > maxname) total_namelen += thislen + 1; /* leave room for \0 */
665 }
666
667 if (total_namelen == 0) return true;
668
669 *tabloc = zalloc (total_namelen);
670 if (*tabloc == NULL) {
671 bfd_error = no_memory;
672 return false;
673 }
674
675 *tablen = total_namelen;
676 strptr = *tabloc;
677
678 for (current = abfd->archive_head; current != NULL; current =
679 current->next) {
680 char *normal =normalize( current->filename);
681 unsigned int thislen = strlen (normal);
682 if (thislen > maxname) {
683 strcpy (strptr, normal);
684 current->filename[0] = ' ';
685 /* We know there will always be enough room (one of the few cases
686 where you may safely use sprintf). */
687 sprintf ((current->filename) + 1, "-%o", (unsigned) (strptr - *tabloc));
688
689 strptr += thislen + 1;
690 }
691 }
692
693 return true;
694}
695\f
696/** A couple of functions for creating ar_hdrs */
697
698/* Takes a filename, returns an arelt_data for it, or NULL if it can't make one.
699 The filename must refer to a filename in the filesystem.
700 The filename field of the ar_hdr will NOT be initialized
701*/
702
703struct areltdata *
704bfd_ar_hdr_from_filesystem (filename)
705 char *filename;
706{
707 struct stat status;
708 struct areltdata *ared;
709 struct ar_hdr *hdr;
710 char *temp, *temp1;
711
712
713 if (stat (filename, &status) != 0) {
714 bfd_error = system_call_error;
715 return NULL;
716 }
717
718 ared = (struct areltdata *) zalloc (sizeof (struct ar_hdr) +
719 sizeof (struct areltdata));
720 if (ared == NULL) {
721 bfd_error = no_memory;
722 return NULL;
723 }
724 hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
725
726 /* ar headers are space padded, not null padded! */
727 temp = (char *) hdr;
728 temp1 = temp + sizeof (struct ar_hdr) - 2;
729 for (; temp < temp1; *(temp++) = ' ');
730 strncpy (hdr->ar_fmag, ARFMAG, 2);
731
732 /* Goddamned sprintf doesn't permit MAXIMUM field lengths */
733 sprintf ((hdr->ar_date), "%-12ld", status.st_mtime);
734 sprintf ((hdr->ar_uid), "%d", status.st_uid);
735 sprintf ((hdr->ar_gid), "%d", status.st_gid);
736 sprintf ((hdr->ar_mode), "%-8o", (unsigned) status.st_mode);
737 sprintf ((hdr->ar_size), "%-10ld", status.st_size);
738 /* Correct for a lossage in sprintf whereby it null-terminates. I cannot
739 understand how these C losers could design such a ramshackle bunch of
740 IO operations */
741 temp = (char *) hdr;
742 temp1 = temp + sizeof (struct ar_hdr) - 2;
743 for (; temp < temp1; temp++) {
744 if (*temp == '\0') *temp = ' ';
745 }
746 strncpy (hdr->ar_fmag, ARFMAG, 2);
747 ared->parsed_size = status.st_size;
748 ared->arch_header = (char *) hdr;
749
750 return ared;
751}
752
753struct ar_hdr *
754bfd_special_undocumented_glue (filename)
755 char *filename;
756{
757
758 return (struct ar_hdr *) bfd_ar_hdr_from_filesystem (filename) -> arch_header;
759}
760
761
762/* Analogous to stat call */
763int
764bfd_generic_stat_arch_elt (abfd, buf)
765 bfd *abfd;
766 struct stat *buf;
767{
768 struct ar_hdr *hdr;
769 char *aloser;
770
771 if (abfd->arelt_data == NULL) {
772 bfd_error = invalid_operation;
773 return -1;
774 }
775
776 hdr = arch_hdr (abfd);
777
778#define foo(arelt, stelt, size) \
779 buf->stelt = strtol (hdr->arelt, &aloser, size); \
780 if (aloser == hdr->arelt) return -1;
781
782 foo (ar_date, st_mtime, 10);
783 foo (ar_uid, st_uid, 10);
784 foo (ar_gid, st_gid, 10);
785 foo (ar_mode, st_mode, 8);
786 foo (ar_size, st_size, 10);
787
788 return 0;
789}
790
791/* Don't do anything -- it'll be taken care of later */
792void
793bfd_dont_truncate_arname (ignore_abfd, ignore_filename, ignore_arhdr)
794 bfd *ignore_abfd;
795 char *ignore_filename;
796 char *ignore_arhdr;
797{
798 /* FIXME -- Actually this is incorrect. If the name is short we
799 should insert into the header; only if it is long should we do
800 nothing.
801
802 Anyway, this interacts unpleasantly with ar's quick-append option,
803 for now just be compatible with the old system */
804
805 return;
806}
807
808void
809bfd_bsd_truncate_arname (abfd, pathname, arhdr)
810 bfd *abfd;
811 char *pathname;
812 char *arhdr;
813{
814 struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
815 int length;
816 char *filename = strrchr (pathname, '/');
817 int maxlen = ar_maxnamelen (abfd);
818
819
820 if (filename == NULL)
821 filename = pathname;
822 else
823 ++filename;
824
825 length = strlen (filename);
826
827 if (length <= maxlen)
828 memcpy (hdr->ar_name, filename, length);
829 else {
830 /* pathname: meet procrustes */
831 memcpy (hdr->ar_name, filename, maxlen);
832 length = maxlen;
833 }
834
835 if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);
836}
837
838/* Store name into ar header. Truncates the name to fit.
839 1> strip pathname to be just the basename.
840 2> if it's short enuf to fit, stuff it in.
841 3> If it doesn't end with .o, truncate it to fit
842 4> truncate it before the .o, append .o, stuff THAT in.
843*/
844
845/* This is what gnu ar does. It's better but incompatible with the bsd ar. */
846void
847bfd_gnu_truncate_arname (abfd, pathname, arhdr)
848 bfd *abfd;
849 char *pathname;
850 char *arhdr;
851{
852 struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
853 int length;
854 char *filename = strrchr (pathname, '/');
855 int maxlen = ar_maxnamelen (abfd);
856
857 if (filename == NULL)
858 filename = pathname;
859 else
860 ++filename;
861
862 length = strlen (filename);
863
864 if (length <= maxlen)
865 memcpy (hdr->ar_name, filename, length);
866 else { /* pathname: meet procrustes */
867 memcpy (hdr->ar_name, filename, maxlen);
868 if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) {
869 hdr->ar_name[maxlen - 2] = '.';
870 hdr->ar_name[maxlen - 1] = 'o';
871 }
872 length = maxlen;
873 }
874
875 if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);
876}
877\f
878
879PROTO (boolean, compute_and_write_armap, (bfd *arch, unsigned int elength));
880
881/* The bfd is open for write and has its format set to bfd_archive */
882boolean
883_bfd_write_archive_contents (arch)
884 bfd *arch;
885{
886 bfd *current;
887 char *etable = NULL;
888 unsigned int elength = 0;
889 boolean makemap = bfd_has_map (arch);
890 boolean hasobjects = false; /* if no .o's, don't bother to make a map */
891 unsigned int i;
892
893
894 /* Verify the viability of all entries; if any of them live in the
895 filesystem (as opposed to living in an archive open for input)
896 then construct a fresh ar_hdr for them.
897 */
898 for (current = arch->archive_head; current; current = current->next) {
899 if (bfd_write_p (current)) {
900 bfd_error = invalid_operation;
901 return false;
902 }
903 if (!current->arelt_data) {
904 current->arelt_data =
905 (void *) bfd_ar_hdr_from_filesystem (current->filename);
906 if (!current->arelt_data) return false;
907
908 /* Put in the file name */
909
910 BFD_SEND (arch, _bfd_truncate_arname,(arch,
911 current->filename,
0452b5aa 912 (char *) arch_hdr(current)));
4a81b561
DHW
913
914
915 }
916
917 if (makemap) { /* don't bother if we won't make a map! */
918 if ((bfd_check_format (current, bfd_object))
919#if 0 /* FIXME -- these are not set correctly */
920 && ((bfd_get_file_flags (current) & HAS_SYMS))
921#endif
922 )
923 hasobjects = true;
924 }
925 }
926
927 if (!bfd_construct_extended_name_table (arch, &etable, &elength))
928 return false;
929
930 bfd_seek (arch, 0, SEEK_SET);
931 bfd_write (ARMAG, 1, SARMAG, arch);
932
933 if (makemap && hasobjects) {
934
935 if (compute_and_write_armap (arch, elength) != true) {
936 if (etable) free (etable);
937 return false;
938 }
939 }
940
941 if (elength != 0) {
942 struct ar_hdr hdr;
943
944 memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
945 sprintf (&(hdr.ar_name[0]), "ARFILENAMES/");
946 sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength);
947 hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
948 for (i = 0; i < sizeof (struct ar_hdr); i++)
949 if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
950 bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
951 bfd_write (etable, 1, elength, arch);
952 if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch);
953 if (etable) free (etable);
954 }
955
956 for (current = arch->archive_head; current; current = current->next) {
957 char buffer[DEFAULT_BUFFERSIZE];
958 unsigned int remaining = arelt_size (current);
959 struct ar_hdr *hdr = arch_hdr(current);
960 /* write ar header */
961
962 if (bfd_write (hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {
963 syserr:
964 bfd_error = system_call_error;
965 return false;
966 }
967 if (bfd_seek (current, 0L, SEEK_SET) != 0L) goto syserr;
0452b5aa
SC
968 while (remaining)
969 {
970 unsigned int amt = DEFAULT_BUFFERSIZE;
971 if (amt > remaining) {
972 amt = remaining;
973 }
974 if (bfd_read (buffer, amt, 1, current) != amt) goto syserr;
975 if (bfd_write (buffer, amt, 1, arch) != amt) goto syserr;
976 remaining -= amt;
977 }
4a81b561
DHW
978 if ((arelt_size (current) % 2) == 1) bfd_write ("\n", 1, 1, arch);
979 }
980return true;
981}
982\f
983/* Note that the namidx for the first symbol is 0 */
984
985
986
987boolean
988compute_and_write_armap (arch, elength)
989 bfd *arch;
990 unsigned int elength;
991{
992 bfd *current;
993 file_ptr elt_no = 0;
994 struct orl *map;
995 int orl_max = 15000; /* fine initial default */
996 int orl_count = 0;
997 int stridx = 0; /* string index */
998
999 /* Dunno if this is the best place for this info... */
1000 if (elength != 0) elength += sizeof (struct ar_hdr);
1001 elength += elength %2 ;
1002
1003 map = (struct orl *) zalloc (orl_max * sizeof (struct orl));
1004 if (map == NULL) {
1005 bfd_error = no_memory;
1006 return false;
1007 }
1008
1009 /* Map over each element */
1010 for (current = arch->archive_head;
1011 current != (bfd *)NULL;
1012 current = current->next, elt_no++)
1013 {
0452b5aa
SC
1014 if ((bfd_check_format (current, bfd_object) == true)
1015 && ((bfd_get_file_flags (current) & HAS_SYMS))) {
1016 asymbol **syms;
1017 unsigned int storage;
1018 unsigned int symcount;
1019 unsigned int src_count;
1020
1021 storage = get_symtab_upper_bound (current);
1022 if (storage != 0) {
1023
1024 syms = (asymbol **) zalloc (storage);
1025 if (syms == NULL) {
1026 bfd_error = no_memory; /* FIXME -- memory leak */
1027 return false;
1028 }
1029 symcount = bfd_canonicalize_symtab (current, syms);
1030
1031
1032 /* Now map over all the symbols, picking out the ones we want */
1033 for (src_count = 0; src_count <symcount; src_count++) {
1034 flagword flags = (syms[src_count])->flags;
1035 if ((flags & BSF_GLOBAL) ||
1036 (flags & BSF_FORT_COMM)) {
1037
1038 /* This symbol will go into the archive header */
1039 if (orl_count == orl_max)
1040 {
1041 orl_max *= 2;
1042 map = (struct orl *) realloc ((char *) map,
1043 orl_max * sizeof (struct orl));
1044 }
1045
1046 (map[orl_count]).name = &((syms[src_count])->name);
1047 (map[orl_count]).pos = elt_no;
1048 (map[orl_count]).namidx = stridx;
1049
1050 stridx += strlen ((syms[src_count])->name) + 1;
1051 ++orl_count;
1052 }
1053 }
4a81b561 1054 }
4a81b561
DHW
1055 }
1056 }
4a81b561
DHW
1057 /* OK, now we have collected all the data, let's write them out */
1058 if (!BFD_SEND (arch, write_armap,
1059 (arch, elength, map, orl_count, stridx))) {
1060 free (map);
1061 return false;
1062 }
1063
1064 free (map);
1065 return true;
1066}
1067
1068\f
1069 /* FIXME -- have to byte-swap this */
1070
1071boolean
1072bsd_write_armap (arch, elength, map, orl_count, stridx)
1073 bfd *arch;
1074 unsigned int elength;
1075 struct orl *map;
1076 int orl_count;
1077 int stridx;
1078{
1079 unsigned int ranlibsize = (orl_count * sizeof (struct ranlib)) + 4;
1080 unsigned int stringsize = stridx + 4;
1081 unsigned int mapsize = stringsize + ranlibsize;
1082 file_ptr firstreal;
1083 bfd *current = arch->archive_head;
1084 int last_eltno = 0; /* last element arch seen */
1085 int temp;
1086 int count;
1087 struct ar_hdr hdr;
1088 struct stat statbuf;
1089 unsigned int i;
1090 int padit = mapsize & 1;
1091
1092 if (padit) mapsize ++;
1093
1094 firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
1095
1096 fstat (arch->iostream, &statbuf); /* FIXME -- descriptor must be open! */
1097 memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
1098 sprintf (hdr.ar_name, "__.SYMDEF");
1099 sprintf (hdr.ar_size, "%-10d", (int) mapsize);
1100 sprintf (hdr.ar_date, "%ld", statbuf.st_mtime);
1101 hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
1102 for (i = 0; i < sizeof (struct ar_hdr); i++)
1103 if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
1104 bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
1105
1106 temp = orl_count /* + 4 */;
1107 bfd_write (&temp, 1, sizeof (temp), arch);
1108
1109 for (count = 0; count < orl_count; count++) {
1110 struct symdef outs;
1111 struct symdef *outp = &outs;
1112
1113 if ((map[count]).pos != last_eltno) {
1114 firstreal += arelt_size (current) + sizeof (struct ar_hdr);
1115 firstreal += firstreal % 2;
1116 last_eltno = (map[count]).pos;
1117 current = current->next;
1118 }
1119
1120 outs.s.string_offset = ((map[count]).namidx) +4;
1121 outs.file_offset = firstreal;
1122 bfd_write ((char *)outp, 1, sizeof (outs), arch);
1123 }
1124
1125 /* now write the strings themselves */
1126 temp = stridx + 4;
1127 bfd_write (&temp, 1, sizeof (temp), arch);
1128 for (count = 0; count < orl_count; count++)
1129 bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch);
1130
1131 /* The spec sez this should be a newline. But in order to be
1132 bug-compatible for sun's ar we use a null. */
1133 if (padit)
1134 bfd_write("\0",1,1,arch);
1135
1136 return true;
1137}
1138\f
1139
1140/* A coff armap looks like :
1141 ARMAG
1142 struct ar_hdr with name = '/'
1143 number of symbols
1144 offset of file for symbol 0
1145 offset of file for symbol 1
1146 ..
1147 offset of file for symbol n-1
1148 symbol name 0
1149 symbol name 1
1150 ..
1151 symbol name n-1
1152
1153*/
1154
1155boolean
1156coff_write_armap (arch, elength, map, orl_count, stridx)
1157 bfd *arch;
1158 unsigned int elength;
1159 struct orl *map;
1160 int orl_count;
1161 int stridx;
1162{
1163 unsigned int ranlibsize = (orl_count * 4) + 4;
1164 unsigned int stringsize = stridx;
1165 unsigned int mapsize = stringsize + ranlibsize;
1166 file_ptr archive_member_file_ptr;
1167 bfd *current = arch->archive_head;
1168 int last_eltno = 0; /* last element arch seen */
1169 int count;
1170 struct ar_hdr hdr;
1171 struct stat statbuf;
1172 unsigned int i;
1173 int padit = mapsize & 1;
1174
1175 if (padit) mapsize ++;
1176
1177 archive_member_file_ptr =
1178 mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
1179
1180 fstat (arch->iostream, &statbuf); /* FIXME -- descriptor must be open! */
1181 memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
1182 hdr.ar_name[0] = '/';
1183 sprintf (hdr.ar_size, "%-10d", (int) mapsize);
1184 sprintf (hdr.ar_date, "%ld", statbuf.st_mtime);
1185 hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
1186
1187 for (i = 0; i < sizeof (struct ar_hdr); i++)
1188 if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
1189
1190 /* Write the ar header for this item and the number of symbols */
1191
1192 bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
1193 bfd_write (&orl_count, 1, sizeof (orl_count), arch);
1194
1195 /* Two passes, first write the file offsets for each symbol -
1196 remembering that each offset is on a two byte boundary
1197 */
1198
1199 for (count = 0; count < orl_count; count++) {
1200 while ((map[count]).pos != last_eltno) {
1201 /* If this is the first time we've seen a ref to this archive
1202 then remember it's size */
1203 archive_member_file_ptr +=
1204 arelt_size (current) + sizeof (struct ar_hdr);
1205 archive_member_file_ptr += archive_member_file_ptr % 2;
1206 current = current->next;
1207 last_eltno++;
1208 }
1209 bfd_write (&archive_member_file_ptr,
1210 1,
1211 sizeof (archive_member_file_ptr),
1212 arch);
1213 }
1214
1215 /* now write the strings themselves */
1216 for (count = 0; count < orl_count; count++) {
1217 bfd_write (*((map[count]).name),
1218 1,
1219 strlen (*((map[count]).name))+1, arch);
1220
1221 }
1222 /* The spec sez this should be a newline. But in order to be
1223 bug-compatible for arc960 we use a null. */
1224 if (padit)
1225 bfd_write("\0",1,1,arch);
1226
1227 return true;
1228}
This page took 0.065009 seconds and 4 git commands to generate.