d93bc72fe84041a37009ef4812bacc12f4861bb3
[deliverable/binutils-gdb.git] / bfd / bfd.c
1 /* -*- C -*- */
2
3 /*** bfd -- binary file diddling routines by Gumby Wallace of Cygnus Support.
4 Every definition in this file should be exported and declared
5 in bfd.c. If you don't want it to be user-visible, put it in
6 libbfd.c!
7 */
8
9 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
10
11 This file is part of BFD, the Binary File Diddler.
12
13 BFD is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 1, or (at your option)
16 any later version.
17
18 BFD is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with BFD; see the file COPYING. If not, write to
25 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26
27 /* $Id$ */
28 #include "sysdep.h"
29 #include "bfd.h"
30 #include "libbfd.h"
31
32 short _bfd_host_big_endian = 0x0100;
33 /* Accessing the above as (*(char*)&_bfd_host_big_endian), will
34 * return 1 if the host is big-endian, 0 otherwise.
35 * (See HOST_IS_BIG_ENDIAN_P in bfd.h.)
36 */
37
38
39
40 \f
41 /** Error handling
42 o - Most functions return nonzero on success (check doc for
43 precise semantics); 0 or NULL on error.
44 o - Internal errors are documented by the value of bfd_error.
45 If that is system_call_error then check errno.
46 o - The easiest way to report this to the user is to use bfd_perror.
47 */
48
49 bfd_ec bfd_error = no_error;
50
51 char *bfd_errmsgs[] = {"No error",
52 "System call error",
53 "Invalid target",
54 "File in wrong format",
55 "Invalid operation",
56 "Memory exhausted",
57 "No symbols",
58 "No relocation info",
59 "No more archived files",
60 "Malformed archive",
61 "Symbol not found",
62 "File format not recognized",
63 "File format is ambiguous",
64 "Section has no contents",
65 "#<Invalid error code>"
66 };
67
68 #if !defined(ANSI_LIBRARIES)
69 char *
70 strerror (code)
71 int code;
72 {
73 extern int sys_nerr;
74 extern char *sys_errlist[];
75
76 return (((code < 0) || (code >= sys_nerr)) ? "(unknown error)" :
77 sys_errlist [code]);
78 }
79 #endif /* not ANSI_LIBRARIES */
80
81 char *
82 bfd_errmsg (error_tag)
83 bfd_ec error_tag;
84 {
85 extern int errno;
86
87 if (error_tag == system_call_error)
88 return strerror (errno);
89
90 if ((((int)error_tag <(int) no_error) ||
91 ((int)error_tag > (int)invalid_error_code)))
92 error_tag = invalid_error_code;/* sanity check */
93
94 return bfd_errmsgs [(int)error_tag];
95 }
96
97 void
98 bfd_perror (message)
99 char *message;
100 {
101 if (bfd_error == system_call_error)
102 perror(message); /* must be system error then... */
103 else {
104 if (message == NULL || *message == '\0')
105 fprintf (stderr, "%s\n", bfd_errmsg (bfd_error));
106 else
107 fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_error));
108 }
109 }
110
111 /* for error messages */
112 char *
113 bfd_format_string (format)
114 bfd_format format;
115 {
116 if (((int)format <(int) bfd_unknown) || ((int)format >=(int) bfd_type_end)) return "invalid";
117
118 switch (format) {
119 case bfd_object: return "object"; /* linker/assember/compiler output */
120 case bfd_archive: return "archive"; /* object archive file */
121 case bfd_core: return "core"; /* core dump */
122 default: return "unknown";
123 }
124 }
125 \f
126 /** Target configurations */
127
128 extern bfd_target *target_vector[];
129
130 /* Returns a pointer to the transfer vector for the object target
131 named target_name. If target_name is NULL, chooses the one in the
132 environment variable GNUTARGET; if that is null or not defined then
133 the first entry in the target list is chosen. Passing in the
134 string "default" or setting the environment variable to "default"
135 will cause the first entry in the target list to be returned. */
136
137 bfd_target *
138 bfd_find_target (target_name)
139 char *target_name;
140 {
141 bfd_target **target;
142 extern char *getenv ();
143 char *targname = (target_name ? target_name : getenv ("GNUTARGET"));
144
145 /* This is safe; the vector cannot be null */
146 if (targname == NULL || !strcmp (targname, "default"))
147 return target_vector[0];
148
149 for (target = &target_vector[0]; *target != NULL; target++) {
150 if (!strcmp (targname, (*target)->name))
151 return *target;
152 }
153
154 bfd_error = invalid_target;
155 return NULL;
156 }
157
158 /* Returns a freshly-consed, NULL-terminated vector of the names of all the
159 valid bfd targets. Do not modify the names */
160
161 char **
162 bfd_target_list ()
163 {
164 int vec_length= 0;
165 bfd_target **target;
166 char **name_list, **name_ptr;
167
168 for (target = &target_vector[0]; *target != NULL; target++)
169 vec_length++;
170
171 name_ptr = name_list = (char **) zalloc ((vec_length + 1) * sizeof (char **));
172
173 if (name_list == NULL) {
174 bfd_error = no_memory;
175 return NULL;
176 }
177
178 for (target = &target_vector[0]; *target != NULL; target++)
179 *(name_ptr++) = (*target)->name;
180
181 return name_list;
182 }
183 \f
184 /** Init a bfd for read of the proper format.
185 */
186
187 /* We should be able to find out if the target was defaulted or user-specified.
188 If the user specified the target explicitly then we should do no search.
189 I guess the best way to do this is to pass an extra argument which specifies
190 the DWIM. */
191
192 /* I have chanegd this always to set the filepos to the origin before
193 guessing. -- Gumby, 14 Februar 1991*/
194
195 boolean
196 bfd_check_format (abfd, format)
197 bfd *abfd;
198 bfd_format format;
199 {
200 #if obsolete
201 file_ptr filepos;
202 #endif
203 bfd_target **target, *save_targ, *right_targ;
204 int match_count;
205
206 if (!bfd_read_p (abfd) ||
207 ((int)(abfd->format) < (int)bfd_unknown) ||
208 ((int)(abfd->format) >= (int)bfd_type_end)) {
209 bfd_error = invalid_operation;
210 return false;
211 }
212
213 if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false;
214
215 /* presume the answer is yes */
216 abfd->format = format;
217
218 #if obsolete
219 filepos = bfd_tell (abfd);
220 #endif
221 bfd_seek (abfd, (file_ptr)0, SEEK_SET); /* instead, rewind! */
222
223
224 right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
225 if (right_targ) {
226 abfd->xvec = right_targ; /* Set the target as returned */
227 return true; /* File position has moved, BTW */
228 }
229
230 /* This isn't a <format> file in the specified or defaulted target type.
231 See if we recognize it for any other target type. (We check them
232 all to make sure it's uniquely recognized.) */
233
234 save_targ = abfd->xvec;
235 match_count = 0;
236 right_targ = 0;
237
238 for (target = target_vector; *target != NULL; target++) {
239 bfd_target *temp;
240
241 abfd->xvec = *target; /* Change BFD's target temporarily */
242 #if obsolete
243 bfd_seek (abfd, filepos, SEEK_SET); /* Restore original file position */
244 #endif
245 bfd_seek (abfd, (file_ptr)0, SEEK_SET);
246 temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
247 if (temp) { /* This format checks out as ok! */
248 right_targ = temp;
249 match_count++;
250 }
251 }
252
253 if (match_count == 1) {
254 abfd->xvec = right_targ; /* Change BFD's target permanently */
255 return true; /* File position has moved, BTW */
256 }
257
258 abfd->xvec = save_targ; /* Restore original target type */
259 abfd->format = bfd_unknown; /* Restore original format */
260 bfd_error = ((match_count == 0) ? file_not_recognized :
261 file_ambiguously_recognized);
262 #if obsolete
263 bfd_seek (abfd, filepos, SEEK_SET); /* Restore original file position */
264 #endif
265 return false;
266 }
267
268 boolean
269 bfd_set_format (abfd, format)
270 bfd *abfd;
271 bfd_format format;
272 {
273 file_ptr filepos;
274
275 if (bfd_read_p (abfd) ||
276 ((int)abfd->format < (int)bfd_unknown) ||
277 ((int)abfd->format >= (int)bfd_type_end)) {
278 bfd_error = invalid_operation;
279 return false;
280 }
281
282 if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false;
283
284 /* presume the answer is yes */
285 abfd->format = format;
286
287 filepos = bfd_tell (abfd);
288
289 if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) {
290 abfd->format = bfd_unknown;
291 bfd_seek (abfd, filepos, SEEK_SET);
292 return false;
293 }
294
295 return true;
296 }
297 \f
298 /* Hack object and core file sections */
299
300 sec_ptr
301 bfd_get_section_by_name (abfd, name)
302 bfd *abfd;
303 char *name;
304 {
305 asection *sect;
306
307 for (sect = abfd->sections; sect != NULL; sect = sect->next)
308 if (!strcmp (sect->name, name)) return sect;
309 return NULL;
310 }
311
312 /* If you try to create a section with a name which is already in use,
313 returns the old section by that name instead. */
314 sec_ptr
315 bfd_make_section (abfd, name)
316 bfd *abfd;
317 char *name;
318 {
319 asection *newsect;
320 asection ** prev = &abfd->sections;
321 asection * sect = abfd->sections;
322
323 if (abfd->output_has_begun) {
324 bfd_error = invalid_operation;
325 return NULL;
326 }
327
328 while (sect) {
329 if (!strcmp(sect->name, name)) return sect;
330 prev = &sect->next;
331 sect = sect->next;
332 }
333
334 newsect = (asection *) zalloc (sizeof (asection));
335 if (newsect == NULL) {
336 bfd_error = no_memory;
337 return NULL;
338 }
339
340 newsect->name = name;
341 newsect->index = abfd->section_count++;
342 newsect->flags = SEC_NO_FLAGS;
343
344 #if ignore /* the compiler doesn't know that zalloc clears the storage */
345 newsect->userdata = 0;
346 newsect->next = (asection *)NULL;
347 newsect->relocation = (arelent *)NULL;
348 newsect->reloc_count = 0;
349 newsect->line_filepos =0;
350 #endif
351 if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) {
352 free (newsect);
353 return NULL;
354 }
355
356 *prev = newsect;
357 return newsect;
358 }
359
360 /* Call operation on each section. Operation gets three args: the bfd,
361 the section, and a void * pointer (whatever the user supplied). */
362
363 /* This is attractive except that without lexical closures its use is hard
364 to make reentrant. */
365 /*VARARGS2*/
366 void
367 bfd_map_over_sections (abfd, operation, user_storage)
368 bfd *abfd;
369 void (*operation)();
370 void *user_storage;
371 {
372 asection *sect;
373 int i = 0;
374
375 for (sect = abfd->sections; sect != NULL; i++, sect = sect->next)
376 (*operation) (abfd, sect, user_storage);
377
378 if (i != abfd->section_count) /* Debugging */
379 abort();
380 }
381
382 boolean
383 bfd_set_section_flags (abfd, section, flags)
384 bfd *abfd;
385 sec_ptr section;
386 flagword flags;
387 {
388 if ((flags & bfd_applicable_section_flags (abfd)) != flags) {
389 bfd_error = invalid_operation;
390 return false;
391 }
392
393 section->flags = flags;
394 return true;
395 }
396
397
398 boolean
399 bfd_set_section_size (abfd, ptr, val)
400 bfd *abfd;
401 sec_ptr ptr;
402 unsigned long val;
403 {
404 /* Once you've started writing to any section you cannot create or change
405 the size of any others. */
406
407 if (abfd->output_has_begun) {
408 bfd_error = invalid_operation;
409 return false;
410 }
411
412 ptr->size = val;
413
414 return true;
415 }
416
417 boolean
418 bfd_set_section_contents (abfd, section, location, offset, count)
419 bfd *abfd;
420 sec_ptr section;
421 void *location;
422 file_ptr offset;
423 int count;
424 {
425 if (!(bfd_get_section_flags(abfd, section) &
426 SEC_HAS_CONTENTS)) {
427 bfd_error = no_contents;
428 return(false);
429 } /* if section has no contents */
430
431 if (BFD_SEND (abfd, _bfd_set_section_contents,
432 (abfd, section, location, offset, count))) {
433 abfd->output_has_begun = true;
434 return true;
435 }
436
437 return false;
438 }
439
440 boolean
441 bfd_get_section_contents (abfd, section, location, offset, count)
442 bfd *abfd;
443 sec_ptr section;
444 void *location;
445 file_ptr offset;
446 int count;
447 {
448 if (section->flags & SEC_CONSTRUCTOR) {
449 memset(location, 0, count);
450 return true;
451 }
452 else {
453 return (BFD_SEND (abfd, _bfd_get_section_contents,
454 (abfd, section, location, offset, count)));
455 }
456 }
457
458 \f
459 /** Some core file info commands */
460
461 /* Returns a read-only string explaining what program was running when
462 it failed. */
463
464 char *
465 bfd_core_file_failing_command (abfd)
466 bfd *abfd;
467 {
468 if (abfd->format != bfd_core) {
469 bfd_error = invalid_operation;
470 return NULL;
471 }
472 return BFD_SEND (abfd, _core_file_failing_command, (abfd));
473 }
474
475 int
476 bfd_core_file_failing_signal (abfd)
477 bfd *abfd;
478 {
479 if (abfd->format != bfd_core) {
480 bfd_error = invalid_operation;
481 return NULL;
482 }
483 return BFD_SEND (abfd, _core_file_failing_signal, (abfd));
484 }
485
486 boolean
487 core_file_matches_executable_p (core_bfd, exec_bfd)
488 bfd *core_bfd, *exec_bfd;
489 {
490 if ((core_bfd->format != bfd_core) || (exec_bfd->format != bfd_object)) {
491 bfd_error = wrong_format;
492 return false;
493 }
494
495 return BFD_SEND (core_bfd, _core_file_matches_executable_p, (core_bfd, exec_bfd));
496 }
497 \f
498 /** Symbols */
499
500 boolean
501 bfd_set_symtab (abfd, location, symcount)
502 bfd *abfd;
503 asymbol **location;
504 unsigned int symcount;
505 {
506 if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) {
507 bfd_error = invalid_operation;
508 return false;
509 }
510
511 bfd_get_outsymbols (abfd) = location;
512 bfd_get_symcount (abfd) = symcount;
513 return true;
514 }
515
516 /* returns the number of octets of storage required */
517 unsigned int
518 get_reloc_upper_bound (abfd, asect)
519 bfd *abfd;
520 sec_ptr asect;
521 {
522 if (abfd->format != bfd_object) {
523 bfd_error = invalid_operation;
524 return 0;
525 }
526
527 return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect));
528 }
529
530 unsigned int
531 bfd_canonicalize_reloc (abfd, asect, location, symbols)
532 bfd *abfd;
533 sec_ptr asect;
534 arelent **location;
535 asymbol **symbols;
536 {
537 if (abfd->format != bfd_object) {
538 bfd_error = invalid_operation;
539 return 0;
540 }
541
542 return BFD_SEND (abfd, _bfd_canonicalize_reloc, (abfd, asect, location, symbols));
543 }
544
545 void
546 bfd_print_symbol_vandf(file, symbol)
547 void *file;
548 asymbol *symbol;
549 {
550 flagword type = symbol->flags;
551 if (symbol->section != (asection *)NULL)
552 {
553 fprintf(file,"%08lx ", symbol->value+symbol->section->vma);
554 }
555 else
556 {
557 fprintf(file,"%08lx ", symbol->value);
558 }
559 fprintf(file,"%c%c%c%c%c%c%c",
560 (type & BSF_LOCAL) ? 'l':' ',
561 (type & BSF_GLOBAL) ? 'g' : ' ',
562 (type & BSF_IMPORT) ? 'i' : ' ',
563 (type & BSF_EXPORT) ? 'e' : ' ',
564 (type & BSF_UNDEFINED) ? 'u' : ' ',
565 (type & BSF_FORT_COMM) ? 'c' : ' ',
566 (type & BSF_DEBUGGING) ? 'd' :' ');
567
568 }
569
570
571 boolean
572 bfd_set_file_flags (abfd, flags)
573 bfd *abfd;
574 flagword flags;
575 {
576 if (abfd->format != bfd_object) {
577 bfd_error = wrong_format;
578 return false;
579 }
580
581 if (bfd_read_p (abfd)) {
582 bfd_error = invalid_operation;
583 return false;
584 }
585
586 if ((flags & bfd_applicable_file_flags (abfd)) != flags) {
587 bfd_error = invalid_operation;
588 return false;
589 }
590
591 bfd_get_file_flags (abfd) = flags;
592 return true;
593 }
594
595
596 void
597 bfd_set_reloc (ignore_abfd, asect, location, count)
598 bfd *ignore_abfd;
599 sec_ptr asect;
600 arelent **location;
601 unsigned int count;
602 {
603 asect->orelocation = location;
604 asect->reloc_count = count;
605 }
606 /*
607 If an output_bfd is supplied to this function the generated image
608 will be relocatable, the relocations are copied to the output file
609 after they have been changed to reflect the new state of the world.
610 There are two ways of reflecting the results of partial linkage in an
611 output file; by modifying the output data in place, and by modifying
612 the relocation record. Some native formats (eg basic a.out and basic
613 coff) have no way of specifying an addend in the relocation type, so
614 the addend has to go in the output data. This is no big deal since in
615 these formats the output data slot will always be big enough for the
616 addend. Complex reloc types with addends were invented to solve just
617 this problem.
618 */
619
620 bfd_reloc_status_enum_type
621 bfd_perform_relocation(abfd,
622 reloc_entry,
623 data,
624 input_section,
625 output_bfd)
626 bfd *abfd;
627 arelent *reloc_entry;
628 void *data;
629 asection *input_section;
630 bfd *output_bfd;
631 {
632 bfd_vma relocation;
633 bfd_reloc_status_enum_type flag = bfd_reloc_ok;
634 bfd_vma relocation_before;
635 bfd_vma mask;
636 bfd_vma target_mask;
637 bfd_vma addr = reloc_entry->address ;
638 bfd_vma output_base = 0;
639 struct rint_struct *howto = reloc_entry->howto;
640 asection *reloc_target_output_section;
641 asection *reloc_target_input_section;
642 asymbol *symbol;
643
644 if (reloc_entry->sym_ptr_ptr) {
645 symbol = *( reloc_entry->sym_ptr_ptr);
646 if ((symbol->flags & BSF_UNDEFINED) && output_bfd == (bfd *)NULL) {
647 flag = bfd_reloc_undefined;
648 }
649 }
650 else {
651 symbol = (asymbol*)NULL;
652 }
653
654 if (howto->special_function) {
655 bfd_reloc_status_enum_type cont;
656 cont = howto->special_function(abfd,
657 reloc_entry,
658 symbol,
659 data,
660 input_section);
661 if (cont != bfd_reloc_continue) return cont;
662 }
663
664 /*
665 Work out which section the relocation is targetted at and the
666 initial relocation command value.
667 */
668
669
670 if (symbol != (asymbol *)NULL){
671 if (symbol->flags & BSF_FORT_COMM) {
672 relocation = 0;
673 }
674 else {
675 relocation = symbol->value;
676 }
677 if (symbol->section != (asection *)NULL)
678 {
679 reloc_target_input_section = symbol->section;
680 }
681 else {
682 reloc_target_input_section = (asection *)NULL;
683 }
684 }
685 else if (reloc_entry->section != (asection *)NULL)
686 {
687 relocation = 0;
688 reloc_target_input_section = reloc_entry->section;
689 }
690 else {
691 relocation = 0;
692 reloc_target_input_section = (asection *)NULL;
693 }
694
695
696 if (reloc_target_input_section != (asection *)NULL) {
697
698 reloc_target_output_section =
699 reloc_target_input_section->output_section;
700
701 if (output_bfd && howto->partial_inplace==false) {
702 output_base = 0;
703 }
704 else {
705 output_base = reloc_target_output_section->vma;
706
707 }
708
709 relocation += output_base + reloc_target_input_section->output_offset;
710 }
711
712 relocation += reloc_entry->addend ;
713
714
715 if(reloc_entry->address > (bfd_vma)(input_section->size))
716 {
717 return bfd_reloc_outofrange;
718 }
719
720
721 if (howto->pc_relative == true)
722 {
723 /*
724 Anything which started out as pc relative should end up that
725 way too
726 */
727
728 relocation -=
729 output_base + input_section->output_offset;
730
731 }
732
733 if (output_bfd!= (bfd *)NULL && howto->partial_inplace == false) {
734 /*
735 This is a partial relocation, and we want to apply the relocation
736 to the reloc entry rather than the raw data. Modify the reloc
737 inplace to reflect what we now know.
738 */
739 reloc_entry->addend = relocation ;
740 reloc_entry->section = reloc_target_input_section;
741 if (reloc_target_input_section != (asection *)NULL) {
742 /* If we know the output section we can forget the symbol */
743 reloc_entry->sym_ptr_ptr = (asymbol**)NULL;
744 }
745 reloc_entry->address +=
746 input_section->output_offset;
747 }
748 else {
749 reloc_entry->addend = 0;
750
751
752 /*
753 Either we are relocating all the way, or we don't want to apply
754 the relocation to the reloc entry (probably because there isn't
755 any room in the output format to describe addends to relocs)
756 */
757 relocation >>= howto->rightshift;
758 if (howto->bitsize == 32) {
759 mask = ~0;
760 }
761 else {
762 mask = (1L << howto->bitsize) - 1 ;
763 mask |= mask - 1; /* FIXME, what is this? */
764 }
765
766 relocation &= mask;
767
768 /* Shift everything up to where it's going to be used */
769
770 relocation <<= howto->bitpos;
771 mask <<= howto->bitpos;
772 target_mask = ~mask;
773
774 /* Wait for the day when all have the mask in them */
775
776 BFD_ASSERT(howto->mask == mask);
777
778
779
780 relocation_before = relocation;
781
782
783 switch (howto->size)
784 {
785 case 0:
786 {
787 char x = bfd_getchar(abfd, (char *)data + addr);
788 relocation += x & mask;
789 bfd_putchar(abfd,
790 ( x & target_mask) | ( relocation & mask),
791 (unsigned char *) data + addr);
792 }
793 break;
794
795 case 1:
796 {
797 short x = bfd_getshort(abfd, (bfd_byte *)data + addr);
798 relocation += x & mask;
799 bfd_putshort(abfd, ( x & target_mask) | (relocation & mask),
800 (unsigned char *)data + addr);
801 }
802 break;
803 case 2:
804 {
805 long x = bfd_getlong(abfd, (bfd_byte *) data + addr);
806 relocation += x & mask;
807 bfd_putlong(abfd, ( x & target_mask) | (relocation & mask),
808 (bfd_byte *)data + addr);
809 }
810 break;
811 case 3:
812 /* Do nothing */
813 break;
814 default:
815 return bfd_reloc_other;
816 }
817
818 /* See if important parts of the relocation were chopped to make
819 it fit into the relocation field. (ie are there any significant
820 bits left over after the masking ? */
821 if ((relocation_before & target_mask) != 0 &&
822 howto->complain_on_overflow == true)
823 {
824 /* Its ok if the bit which fell off is */
825 return bfd_reloc_overflow;
826 }
827 }
828
829 return flag;
830 }
831
832 void
833 bfd_assert(file, line)
834 char *file;
835 int line;
836 {
837 printf("bfd assertion fail %s:%d\n",file,line);
838 }
839
840
841 boolean
842 bfd_set_start_address(abfd, vma)
843 bfd *abfd;
844 bfd_vma vma;
845 {
846 abfd->start_address = vma;
847 return true;
848 }
849
850
851 bfd_vma bfd_log2(x)
852 bfd_vma x;
853 {
854 bfd_vma result = 0;
855 while ( (bfd_vma)(1<< result) < x)
856 result++;
857 return result;
858 }
859
860 /* bfd_get_mtime: Return cached file modification time (e.g. as read
861 from archive header for archive members, or from file system if we have
862 been called before); else determine modify time, cache it, and
863 return it. */
864
865 long
866 bfd_get_mtime (abfd)
867 bfd *abfd;
868 {
869 FILE *fp;
870 struct stat buf;
871
872 if (abfd->mtime_set)
873 return abfd->mtime;
874
875 fp = bfd_cache_lookup (abfd);
876 if (0 != fstat (fileno (fp), &buf))
877 return 0;
878
879 abfd->mtime_set = true;
880 abfd->mtime = buf.st_mtime;
881 return abfd->mtime;
882 }
This page took 0.094082 seconds and 3 git commands to generate.