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