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