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