Merge devo/bfd with GDB's bfd.
[binutils-gdb.git] / bfd / bfd.c
1 /* -*- C -*- */
2
3 /*** bfd -- binary file diddling routines by Gumby Wallace of Cygnus Support.
4 Every definition in this file should be exported and declared
5 in bfd.c. If you don't want it to be user-visible, put it in
6 libbfd.c!
7 */
8
9 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
10
11 This file is part of BFD, the Binary File Diddler.
12
13 BFD is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 1, or (at your option)
16 any later version.
17
18 BFD is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with BFD; see the file COPYING. If not, write to
25 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26
27 /* $Id$ */
28 #include "sysdep.h"
29 #include "bfd.h"
30 #include "libbfd.h"
31
32 short _bfd_host_big_endian = 0x0100;
33 /* Accessing the above as (*(char*)&_bfd_host_big_endian), will
34 return 1 if the host is big-endian, 0 otherwise.
35 (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 relocation_before;
652 bfd_vma addr = reloc_entry->address ;
653 bfd_vma output_base = 0;
654 reloc_howto_type *howto = reloc_entry->howto;
655 asection *reloc_target_output_section;
656 asection *reloc_target_input_section;
657 asymbol *symbol;
658
659 if (reloc_entry->sym_ptr_ptr) {
660 symbol = *( reloc_entry->sym_ptr_ptr);
661 if ((symbol->flags & BSF_UNDEFINED) && output_bfd == (bfd *)NULL) {
662 flag = bfd_reloc_undefined;
663 }
664 }
665 else {
666 symbol = (asymbol*)NULL;
667 }
668
669 if (howto->special_function){
670 bfd_reloc_status_enum_type cont;
671 cont = howto->special_function(abfd,
672 reloc_entry,
673 symbol,
674 data,
675 input_section);
676 if (cont != bfd_reloc_continue) return cont;
677 }
678
679 /*
680 Work out which section the relocation is targetted at and the
681 initial relocation command value.
682 */
683
684
685 if (symbol != (asymbol *)NULL){
686 if (symbol->flags & BSF_FORT_COMM) {
687 relocation = 0;
688 }
689 else {
690 relocation = symbol->value;
691 }
692 if (symbol->section != (asection *)NULL)
693 {
694 reloc_target_input_section = symbol->section;
695 }
696 else {
697 reloc_target_input_section = (asection *)NULL;
698 }
699 }
700 else if (reloc_entry->section != (asection *)NULL)
701 {
702 relocation = 0;
703 reloc_target_input_section = reloc_entry->section;
704 }
705 else {
706 relocation = 0;
707 reloc_target_input_section = (asection *)NULL;
708 }
709
710
711 if (reloc_target_input_section != (asection *)NULL) {
712
713 reloc_target_output_section =
714 reloc_target_input_section->output_section;
715
716 if (output_bfd && howto->partial_inplace==false) {
717 output_base = 0;
718 }
719 else {
720 output_base = reloc_target_output_section->vma;
721
722 }
723
724 relocation += output_base + reloc_target_input_section->output_offset;
725 }
726
727 relocation += reloc_entry->addend ;
728
729
730 if(reloc_entry->address > (bfd_vma)(input_section->size))
731 {
732 return bfd_reloc_outofrange;
733 }
734
735
736 if (howto->pc_relative == true)
737 {
738 /*
739 Anything which started out as pc relative should end up that
740 way too.
741
742 There are two ways we can see a pcrel instruction. Sometimes
743 the pcrel displacement has been partially calculated, it
744 includes the distance from the start of the section to the
745 instruction in it (eg sun3), and sometimes the field is
746 totally blank - eg m88kbcs.
747 */
748
749
750 relocation -=
751 output_base + input_section->output_offset;
752
753 if (howto->pcrel_offset == true) {
754 relocation -= reloc_entry->address;
755 }
756
757 }
758
759 if (output_bfd!= (bfd *)NULL) {
760 if ( howto->partial_inplace == false) {
761 /*
762 This is a partial relocation, and we want to apply the relocation
763 to the reloc entry rather than the raw data. Modify the reloc
764 inplace to reflect what we now know.
765 */
766 reloc_entry->addend = relocation ;
767 reloc_entry->section = reloc_target_input_section;
768 if (reloc_target_input_section != (asection *)NULL) {
769 /* If we know the output section we can forget the symbol */
770 reloc_entry->sym_ptr_ptr = (asymbol**)NULL;
771 }
772 reloc_entry->address +=
773 input_section->output_offset;
774 return flag;
775 }
776 else
777 {
778 /* This is a partial relocation, but inplace, so modify the
779 reloc record a bit
780 */
781
782 }
783 }
784
785 reloc_entry->addend = 0;
786
787
788 /*
789 Either we are relocating all the way, or we don't want to apply
790 the relocation to the reloc entry (probably because there isn't
791 any room in the output format to describe addends to relocs)
792 */
793 relocation >>= howto->rightshift;
794
795 /* Shift everything up to where it's going to be used */
796
797 relocation <<= howto->bitpos;
798
799
800 /* Wait for the day when all have the mask in them */
801
802
803
804 relocation_before = relocation;
805
806
807 /* What we do:
808 i instruction to be left alone
809 o offset within instruction
810 r relocation offset to apply
811 S src mask
812 D dst mask
813 N ~dst mask
814 A part 1
815 B part 2
816 R result
817
818 Do this:
819 i i i i i o o o o o from bfd_get<size>
820 and S S S S S to get the size offset we want
821 + r r r r r r r r r r to get the final value to place
822 and D D D D D to chop to right size
823 -----------------------
824 A A A A A
825 And this:
826 ... i i i i i o o o o o from bfd_get<size>
827 and N N N N N get instruction
828 -----------------------
829 ... B B B B B
830
831 And then:
832 B B B B B
833 or A A A A A
834 -----------------------
835 R R R R R R R R R R put into bfd_put<size>
836 */
837
838 #define DOIT(x) \
839 x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
840
841 switch (howto->size)
842 {
843 case 0:
844 {
845 char x = bfd_getchar(abfd, (char *)data + addr);
846 DOIT(x);
847 bfd_putchar(abfd,x, (unsigned char *) data + addr);
848 }
849 break;
850
851 case 1:
852 {
853 short x = bfd_getshort(abfd, (bfd_byte *)data + addr);
854 DOIT(x);
855 bfd_putshort(abfd, x, (unsigned char *)data + addr);
856 }
857 break;
858 case 2:
859 {
860 long x = bfd_getlong(abfd, (bfd_byte *) data + addr);
861 DOIT(x);
862 bfd_putlong(abfd,x, (bfd_byte *)data + addr);
863 }
864 break;
865 case 3:
866 /* Do nothing */
867 break;
868 default:
869 return bfd_reloc_other;
870 }
871
872 return flag;
873 }
874
875 void
876 bfd_assert(file, line)
877 char *file;
878 int line;
879 {
880 printf("bfd assertion fail %s:%d\n",file,line);
881 }
882
883
884 boolean
885 bfd_set_start_address(abfd, vma)
886 bfd *abfd;
887 bfd_vma vma;
888 {
889 abfd->start_address = vma;
890 return true;
891 }
892
893
894 bfd_vma bfd_log2(x)
895 bfd_vma x;
896 {
897 bfd_vma result = 0;
898 while ( (bfd_vma)(1<< result) < x)
899 result++;
900 return result;
901 }
902
903 /* bfd_get_mtime: Return cached file modification time (e.g. as read
904 from archive header for archive members, or from file system if we have
905 been called before); else determine modify time, cache it, and
906 return it. */
907
908 long
909 bfd_get_mtime (abfd)
910 bfd *abfd;
911 {
912 FILE *fp;
913 struct stat buf;
914
915 if (abfd->mtime_set)
916 return abfd->mtime;
917
918 fp = bfd_cache_lookup (abfd);
919 if (0 != fstat (fileno (fp), &buf))
920 return 0;
921
922 abfd->mtime_set = true;
923 abfd->mtime = buf.st_mtime;
924 return abfd->mtime;
925 }