b661d7157f7014a3d7cf1729bc7288d5fe61dd86
[deliverable/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 * (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 There are two ways we can see a pcrel instruction. Sometimes
766 the pcrel displacement has been partially calculated, it
767 includes the distance from the start of the section to the
768 instruction in it (eg sun3), and sometimes the field is
769 totally blank - eg m88kbcs.
770 */
771
772
773 relocation -=
774 output_base + input_section->output_offset;
775
776 if (howto->pcrel_offset == true) {
777 relocation -= reloc_entry->address;
778 }
779
780 }
781
782 if (output_bfd!= (bfd *)NULL) {
783 if ( howto->partial_inplace == false) {
784 /*
785 This is a partial relocation, and we want to apply the relocation
786 to the reloc entry rather than the raw data. Modify the reloc
787 inplace to reflect what we now know.
788 */
789 reloc_entry->addend = relocation ;
790 reloc_entry->section = reloc_target_input_section;
791 if (reloc_target_input_section != (asection *)NULL) {
792 /* If we know the output section we can forget the symbol */
793 reloc_entry->sym_ptr_ptr = (asymbol**)NULL;
794 }
795 reloc_entry->address +=
796 input_section->output_offset;
797 return flag;
798 }
799 else
800 {
801 /* This is a partial relocation, but inplace, so modify the
802 reloc record a bit
803 */
804
805 }
806 }
807
808 reloc_entry->addend = 0;
809
810
811 /*
812 Either we are relocating all the way, or we don't want to apply
813 the relocation to the reloc entry (probably because there isn't
814 any room in the output format to describe addends to relocs)
815 */
816 relocation >>= howto->rightshift;
817
818 /* Shift everything up to where it's going to be used */
819
820 relocation <<= howto->bitpos;
821
822
823 /* Wait for the day when all have the mask in them */
824
825
826
827 relocation_before = relocation;
828
829
830 /* What we do:
831 i instruction to be left alone
832 o offset within instruction
833 r relocation offset to apply
834 S src mask
835 D dst mask
836 N ~dst mask
837 A part 1
838 B part 2
839 R result
840
841 Do this:
842 i i i i i o o o o o from bfd_get<size>
843 and S S S S S to get the size offset we want
844 + r r r r r r r r r r to get the final value to place
845 and D D D D D to chop to right size
846 -----------------------
847 A A A A A
848 And this:
849 ... i i i i i o o o o o from bfd_get<size>
850 and N N N N N get instruction
851 -----------------------
852 ... B B B B B
853
854 And then:
855 B B B B B
856 or A A A A A
857 -----------------------
858 R R R R R R R R R R put into bfd_put<size>
859 */
860
861 #define DOIT(x) \
862 x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
863
864 switch (howto->size)
865 {
866 case 0:
867 {
868 char x = bfd_getchar(abfd, (char *)data + addr);
869 DOIT(x);
870 bfd_putchar(abfd,x, (unsigned char *) data + addr);
871 }
872 break;
873
874 case 1:
875 {
876 short x = bfd_getshort(abfd, (bfd_byte *)data + addr);
877 DOIT(x);
878 bfd_putshort(abfd, x, (unsigned char *)data + addr);
879 }
880 break;
881 case 2:
882 {
883 long x = bfd_getlong(abfd, (bfd_byte *) data + addr);
884 DOIT(x);
885 bfd_putlong(abfd,x, (bfd_byte *)data + addr);
886 }
887 break;
888 case 3:
889 /* Do nothing */
890 break;
891 default:
892 return bfd_reloc_other;
893 }
894
895 return flag;
896 }
897
898 void
899 bfd_assert(file, line)
900 char *file;
901 int line;
902 {
903 printf("bfd assertion fail %s:%d\n",file,line);
904 }
905
906
907 boolean
908 bfd_set_start_address(abfd, vma)
909 bfd *abfd;
910 bfd_vma vma;
911 {
912 abfd->start_address = vma;
913 return true;
914 }
915
916
917 bfd_vma bfd_log2(x)
918 bfd_vma x;
919 {
920 bfd_vma result = 0;
921 while ( (bfd_vma)(1<< result) < x)
922 result++;
923 return result;
924 }
925
926 /* bfd_get_mtime: Return cached file modification time (e.g. as read
927 from archive header for archive members, or from file system if we have
928 been called before); else determine modify time, cache it, and
929 return it. */
930
931 long
932 bfd_get_mtime (abfd)
933 bfd *abfd;
934 {
935 FILE *fp;
936 struct stat buf;
937
938 if (abfd->mtime_set)
939 return abfd->mtime;
940
941 fp = bfd_cache_lookup (abfd);
942 if (0 != fstat (fileno (fp), &buf))
943 return 0;
944
945 abfd->mtime_set = true;
946 abfd->mtime = buf.st_mtime;
947 return abfd->mtime;
948 }
This page took 0.048948 seconds and 4 git commands to generate.