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