1 |
/* 8 and 16 bit COFF relocation functions, for BFD. |
/* 8 and 16 bit COFF relocation functions, for BFD. |
2 |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001 |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001, |
3 |
Free Software Foundation, Inc. |
2002, 2003, 2004 Free Software Foundation, Inc. |
4 |
Written by Cygnus Support. |
Written by Cygnus Support. |
5 |
|
|
6 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
29 |
BFD generic relocs. They should store the relocs in some location |
BFD generic relocs. They should store the relocs in some location |
30 |
where coff_link_input_bfd can find them (and coff_link_input_bfd |
where coff_link_input_bfd can find them (and coff_link_input_bfd |
31 |
should be changed to use this location rather than rereading the |
should be changed to use this location rather than rereading the |
32 |
file) (unless info->keep_memory is false, in which case they should |
file) (unless info->keep_memory is FALSE, in which case they should |
33 |
free up the relocs after dealing with them). */ |
free up the relocs after dealing with them). */ |
34 |
|
|
35 |
#include "bfd.h" |
#include "bfd.h" |
64 |
the generic symbols. */ |
the generic symbols. */ |
65 |
h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info, |
h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info, |
66 |
bfd_asymbol_name (symbol), |
bfd_asymbol_name (symbol), |
67 |
false, false, true); |
FALSE, FALSE, TRUE); |
68 |
if (h != (struct bfd_link_hash_entry *) NULL |
if (h != (struct bfd_link_hash_entry *) NULL |
69 |
&& (h->type == bfd_link_hash_defined |
&& (h->type == bfd_link_hash_defined |
70 |
|| h->type == bfd_link_hash_defweak)) |
|| h->type == bfd_link_hash_defweak)) |
79 |
if (!((*link_info->callbacks->undefined_symbol) |
if (!((*link_info->callbacks->undefined_symbol) |
80 |
(link_info, bfd_asymbol_name (symbol), |
(link_info, bfd_asymbol_name (symbol), |
81 |
input_section->owner, input_section, reloc->address, |
input_section->owner, input_section, reloc->address, |
82 |
true))) |
TRUE))) |
83 |
abort (); |
abort (); |
84 |
value = 0; |
value = 0; |
85 |
} |
} |
136 |
} |
} |
137 |
} |
} |
138 |
|
|
139 |
boolean |
bfd_boolean |
140 |
bfd_coff_reloc16_relax_section (abfd, input_section, link_info, again) |
bfd_coff_reloc16_relax_section (abfd, input_section, link_info, again) |
141 |
bfd *abfd; |
bfd *abfd; |
142 |
asection *input_section; |
asection *input_section; |
143 |
struct bfd_link_info *link_info; |
struct bfd_link_info *link_info; |
144 |
boolean *again; |
bfd_boolean *again; |
145 |
{ |
{ |
146 |
/* Get enough memory to hold the stuff. */ |
/* Get enough memory to hold the stuff. */ |
147 |
bfd *input_bfd = input_section->owner; |
bfd *input_bfd = input_section->owner; |
153 |
|
|
154 |
/* We only do global relaxation once. It is not safe to do it multiple |
/* We only do global relaxation once. It is not safe to do it multiple |
155 |
times (see discussion of the "shrinks" array below). */ |
times (see discussion of the "shrinks" array below). */ |
156 |
*again = false; |
*again = FALSE; |
157 |
|
|
158 |
if (reloc_size < 0) |
if (reloc_size < 0) |
159 |
return false; |
return FALSE; |
160 |
|
|
161 |
reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size); |
reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size); |
162 |
if (!reloc_vector && reloc_size > 0) |
if (!reloc_vector && reloc_size > 0) |
163 |
return false; |
return FALSE; |
164 |
|
|
165 |
/* Get the relocs and think about them. */ |
/* Get the relocs and think about them. */ |
166 |
reloc_count = |
reloc_count = |
169 |
if (reloc_count < 0) |
if (reloc_count < 0) |
170 |
{ |
{ |
171 |
free (reloc_vector); |
free (reloc_vector); |
172 |
return false; |
return FALSE; |
173 |
} |
} |
174 |
|
|
175 |
/* The reloc16.c and related relaxing code is very simple, the price |
/* The reloc16.c and related relaxing code is very simple, the price |
193 |
bfd_size_type amt; |
bfd_size_type amt; |
194 |
|
|
195 |
/* Allocate and initialize the shrinks array for this section. |
/* Allocate and initialize the shrinks array for this section. |
196 |
The last element is used as an accumlator of shrinks. */ |
The last element is used as an accumulator of shrinks. */ |
197 |
amt = reloc_count + 1; |
amt = reloc_count + 1; |
198 |
amt *= sizeof (unsigned); |
amt *= sizeof (unsigned); |
199 |
shrinks = (unsigned *) bfd_zmalloc (amt); |
shrinks = (unsigned *) bfd_zmalloc (amt); |
200 |
|
|
201 |
/* Loop until nothing changes in this section. */ |
/* Loop until nothing changes in this section. */ |
202 |
do { |
do |
203 |
arelent **parent; |
{ |
204 |
unsigned int i; |
arelent **parent; |
205 |
long j; |
unsigned int i; |
206 |
|
long j; |
207 |
another_pass = 0; |
|
208 |
|
another_pass = 0; |
209 |
for (i = 0, parent = reloc_vector; *parent; parent++, i++) |
|
210 |
{ |
for (i = 0, parent = reloc_vector; *parent; parent++, i++) |
211 |
/* Let the target/machine dependent code examine each reloc |
{ |
212 |
in this section and attempt to shrink it. */ |
/* Let the target/machine dependent code examine each reloc |
213 |
shrink = bfd_coff_reloc16_estimate (abfd, input_section, *parent, |
in this section and attempt to shrink it. */ |
214 |
shrinks[i], link_info); |
shrink = bfd_coff_reloc16_estimate (abfd, input_section, *parent, |
215 |
|
shrinks[i], link_info); |
216 |
/* If it shrunk, note it in the shrinks array and set up for |
|
217 |
another pass. */ |
/* If it shrunk, note it in the shrinks array and set up for |
218 |
if (shrink != shrinks[i]) |
another pass. */ |
219 |
{ |
if (shrink != shrinks[i]) |
220 |
another_pass = 1; |
{ |
221 |
for (j = i + 1; j <= reloc_count; j++) |
another_pass = 1; |
222 |
shrinks[j] += shrink - shrinks[i]; |
for (j = i + 1; j <= reloc_count; j++) |
223 |
} |
shrinks[j] += shrink - shrinks[i]; |
224 |
} |
} |
225 |
} |
} |
226 |
|
} |
227 |
while (another_pass); |
while (another_pass); |
228 |
|
|
229 |
shrink = shrinks[reloc_count]; |
shrink = shrinks[reloc_count]; |
230 |
free ((char *) shrinks); |
free ((char *) shrinks); |
231 |
} |
} |
232 |
|
|
233 |
input_section->_cooked_size -= shrink; |
input_section->rawsize = input_section->size; |
234 |
|
input_section->size -= shrink; |
235 |
free ((char *) reloc_vector); |
free ((char *) reloc_vector); |
236 |
return true; |
return TRUE; |
237 |
} |
} |
238 |
|
|
239 |
bfd_byte * |
bfd_byte * |
240 |
bfd_coff_reloc16_get_relocated_section_contents(in_abfd, |
bfd_coff_reloc16_get_relocated_section_contents (in_abfd, |
241 |
link_info, |
link_info, |
242 |
link_order, |
link_order, |
243 |
data, |
data, |
244 |
relocateable, |
relocatable, |
245 |
symbols) |
symbols) |
246 |
bfd *in_abfd; |
bfd *in_abfd; |
247 |
struct bfd_link_info *link_info; |
struct bfd_link_info *link_info; |
248 |
struct bfd_link_order *link_order; |
struct bfd_link_order *link_order; |
249 |
bfd_byte *data; |
bfd_byte *data; |
250 |
boolean relocateable; |
bfd_boolean relocatable; |
251 |
asymbol **symbols; |
asymbol **symbols; |
252 |
{ |
{ |
253 |
/* Get enough memory to hold the stuff. */ |
/* Get enough memory to hold the stuff. */ |
256 |
long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); |
long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); |
257 |
arelent **reloc_vector; |
arelent **reloc_vector; |
258 |
long reloc_count; |
long reloc_count; |
259 |
|
bfd_size_type sz; |
260 |
|
|
261 |
if (reloc_size < 0) |
if (reloc_size < 0) |
262 |
return NULL; |
return NULL; |
263 |
|
|
264 |
/* If producing relocateable output, don't bother to relax. */ |
/* If producing relocatable output, don't bother to relax. */ |
265 |
if (relocateable) |
if (relocatable) |
266 |
return bfd_generic_get_relocated_section_contents (in_abfd, link_info, |
return bfd_generic_get_relocated_section_contents (in_abfd, link_info, |
267 |
link_order, |
link_order, |
268 |
data, relocateable, |
data, relocatable, |
269 |
symbols); |
symbols); |
270 |
|
|
271 |
/* Read in the section. */ |
/* Read in the section. */ |
272 |
if (!bfd_get_section_contents(input_bfd, |
sz = input_section->rawsize ? input_section->rawsize : input_section->size; |
273 |
input_section, |
if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz)) |
|
data, |
|
|
(bfd_vma) 0, |
|
|
input_section->_raw_size)) |
|
274 |
return NULL; |
return NULL; |
275 |
|
|
276 |
reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size); |
reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size); |