1 /* 8 and 16 bit COFF relocation functions, for BFD.
2 Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3 Written by Cygnus Support.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 Most of this hacked by Steve Chamberlain,
26 /* These routines are used by coff-h8300 and coff-z8k to do
34 #include "coff/internal.h"
38 bfd_coff_reloc16_get_value (reloc
, link_info
, input_section
)
40 struct bfd_link_info
*link_info
;
41 asection
*input_section
;
44 asymbol
*symbol
= *(reloc
->sym_ptr_ptr
);
45 /* A symbol holds a pointer to a section, and an offset from the
46 base of the section. To relocate, we find where the section will
47 live in the output and add that in */
49 if (symbol
->section
== &bfd_und_section
)
51 struct bfd_link_hash_entry
*h
;
53 /* The symbol is undefined in this BFD. Look it up in the
54 global linker hash table. FIXME: This should be changed when
55 we convert this stuff to use a specific final_link function
56 and change the interface to bfd_relax_section to not require
57 the generic symbols. */
58 h
= bfd_link_hash_lookup (link_info
->hash
, bfd_asymbol_name (symbol
),
60 if (h
!= (struct bfd_link_hash_entry
*) NULL
61 && h
->type
== bfd_link_hash_defined
)
62 value
= (h
->u
.def
.value
63 + h
->u
.def
.section
->output_section
->vma
64 + h
->u
.def
.section
->output_offset
);
65 else if (h
!= (struct bfd_link_hash_entry
*) NULL
66 && h
->type
== bfd_link_hash_common
)
70 if (! ((*link_info
->callbacks
->undefined_symbol
)
71 (link_info
, bfd_asymbol_name (symbol
),
72 input_section
->owner
, input_section
, reloc
->address
)))
79 value
= symbol
->value
+
80 symbol
->section
->output_offset
+
81 symbol
->section
->output_section
->vma
;
84 /* Add the value contained in the relocation */
85 value
+= reloc
->addend
;
91 bfd_perform_slip(s
, slip
, input_section
, value
)
94 asection
*input_section
;
97 /* Find all symbols past this point, and make them know
102 if (p
->section
== input_section
)
104 /* This was pointing into this section, so mangle it */
105 if (p
->value
> value
)
115 bfd_coff_reloc16_relax_section (abfd
, i
, link_info
, symbols
)
118 struct bfd_link_info
*link_info
;
121 /* Get enough memory to hold the stuff */
122 bfd
*input_bfd
= i
->owner
;
123 asection
*input_section
= i
;
127 bfd_size_type reloc_size
= bfd_get_reloc_upper_bound(input_bfd
,
129 arelent
**reloc_vector
= (arelent
**)bfd_xmalloc(reloc_size
);
131 /* Get the relocs and think about them */
132 if (bfd_canonicalize_reloc(input_bfd
,
138 for (parent
= reloc_vector
; *parent
; parent
++)
140 shrink
= bfd_coff_reloc16_estimate (abfd
, input_section
, symbols
,
141 *parent
, shrink
, link_info
);
145 input_section
->_cooked_size
-= shrink
;
146 free((char *)reloc_vector
);
151 bfd_coff_reloc16_get_relocated_section_contents(in_abfd
,
158 struct bfd_link_info
*link_info
;
159 struct bfd_link_order
*link_order
;
161 boolean relocateable
;
164 /* Get enough memory to hold the stuff */
165 bfd
*input_bfd
= link_order
->u
.indirect
.section
->owner
;
166 asection
*input_section
= link_order
->u
.indirect
.section
;
167 bfd_size_type reloc_size
= bfd_get_reloc_upper_bound(input_bfd
,
169 arelent
**reloc_vector
= (arelent
**)bfd_xmalloc(reloc_size
);
171 /* If producing relocateable output, don't bother to relax. */
173 return bfd_generic_get_relocated_section_contents (in_abfd
, link_info
,
178 /* read in the section */
179 bfd_get_section_contents(input_bfd
,
183 input_section
->_raw_size
);
186 if (bfd_canonicalize_reloc(input_bfd
,
191 arelent
**parent
= reloc_vector
;
196 unsigned int dst_address
= 0;
197 unsigned int src_address
= 0;
201 /* Find how long a run we can do */
202 while (dst_address
< link_order
->size
)
208 /* Note that the relaxing didn't tie up the addresses in the
209 relocation, so we use the original address to work out the
210 run of non-relocated data */
211 run
= reloc
->address
- src_address
;
217 run
= link_order
->size
- dst_address
;
220 for (idx
= 0; idx
< run
; idx
++)
222 data
[dst_address
++] = data
[src_address
++];
225 /* Now do the relocation */
229 bfd_coff_reloc16_extra_cases (in_abfd
, link_info
, link_order
,
230 reloc
, data
, &src_address
,
235 free((char *)reloc_vector
);