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