This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.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 }