2009-08-10 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / bfd / reloc16.c
CommitLineData
252b5132 1/* 8 and 16 bit COFF relocation functions, for BFD.
b34976b6 2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001,
3db64b00 3 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
252b5132
RH
4 Written by Cygnus Support.
5
cd123cb7 6 This file is part of BFD, the Binary File Descriptor library.
252b5132 7
cd123cb7
NC
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
252b5132 12
cd123cb7
NC
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
252b5132 22
252b5132 23
289c596c 24/* Most of this hacked by Steve Chamberlain <sac@cygnus.com>. */
252b5132
RH
25
26/* These routines are used by coff-h8300 and coff-z8k to do
27 relocation.
28
29 FIXME: This code should be rewritten to support the new COFF
30 linker. Basically, they need to deal with COFF relocs rather than
31 BFD generic relocs. They should store the relocs in some location
32 where coff_link_input_bfd can find them (and coff_link_input_bfd
33 should be changed to use this location rather than rereading the
b34976b6 34 file) (unless info->keep_memory is FALSE, in which case they should
252b5132
RH
35 free up the relocs after dealing with them). */
36
252b5132 37#include "sysdep.h"
3db64b00 38#include "bfd.h"
252b5132
RH
39#include "libbfd.h"
40#include "bfdlink.h"
41#include "genlink.h"
42#include "coff/internal.h"
43#include "libcoff.h"
44
45bfd_vma
46bfd_coff_reloc16_get_value (reloc, link_info, input_section)
47 arelent *reloc;
48 struct bfd_link_info *link_info;
49 asection *input_section;
50{
51 bfd_vma value;
52 asymbol *symbol = *(reloc->sym_ptr_ptr);
53 /* A symbol holds a pointer to a section, and an offset from the
54 base of the section. To relocate, we find where the section will
289c596c 55 live in the output and add that in. */
252b5132
RH
56
57 if (bfd_is_und_section (symbol->section)
58 || bfd_is_com_section (symbol->section))
59 {
60 struct bfd_link_hash_entry *h;
61
62 /* The symbol is undefined in this BFD. Look it up in the
63 global linker hash table. FIXME: This should be changed when
64 we convert this stuff to use a specific final_link function
65 and change the interface to bfd_relax_section to not require
66 the generic symbols. */
67 h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info,
68 bfd_asymbol_name (symbol),
b34976b6 69 FALSE, FALSE, TRUE);
252b5132
RH
70 if (h != (struct bfd_link_hash_entry *) NULL
71 && (h->type == bfd_link_hash_defined
72 || h->type == bfd_link_hash_defweak))
73 value = (h->u.def.value
74 + h->u.def.section->output_section->vma
75 + h->u.def.section->output_offset);
76 else if (h != (struct bfd_link_hash_entry *) NULL
77 && h->type == bfd_link_hash_common)
78 value = h->u.c.size;
fc2db3b8
NC
79 else if (h != (struct bfd_link_hash_entry *) NULL
80 && h->type == bfd_link_hash_undefweak)
81 /* This is a GNU extension. */
82 value = 0;
252b5132
RH
83 else
84 {
289c596c
NC
85 if (!((*link_info->callbacks->undefined_symbol)
86 (link_info, bfd_asymbol_name (symbol),
87 input_section->owner, input_section, reloc->address,
b34976b6 88 TRUE)))
252b5132
RH
89 abort ();
90 value = 0;
91 }
92 }
289c596c 93 else
252b5132 94 {
289c596c
NC
95 value = symbol->value
96 + symbol->section->output_offset
97 + symbol->section->output_section->vma;
252b5132 98 }
289c596c
NC
99
100 /* Add the value contained in the relocation. */
252b5132 101 value += reloc->addend;
289c596c 102
252b5132
RH
103 return value;
104}
105
106void
289c596c 107bfd_perform_slip (abfd, slip, input_section, value)
252b5132
RH
108 bfd *abfd;
109 unsigned int slip;
110 asection *input_section;
111 bfd_vma value;
112{
113 asymbol **s;
114
115 s = _bfd_generic_link_get_symbols (abfd);
116 BFD_ASSERT (s != (asymbol **) NULL);
117
118 /* Find all symbols past this point, and make them know
289c596c
NC
119 what's happened. */
120 while (*s)
252b5132
RH
121 {
122 asymbol *p = *s;
289c596c 123 if (p->section == input_section)
252b5132 124 {
289c596c 125 /* This was pointing into this section, so mangle it. */
252b5132
RH
126 if (p->value > value)
127 {
128 p->value -= slip;
129 if (p->udata.p != NULL)
130 {
131 struct generic_link_hash_entry *h;
132
133 h = (struct generic_link_hash_entry *) p->udata.p;
134 BFD_ASSERT (h->root.type == bfd_link_hash_defined
135 || h->root.type == bfd_link_hash_defweak);
136 h->root.u.def.value -= slip;
137 BFD_ASSERT (h->root.u.def.value == p->value);
138 }
139 }
140 }
141 s++;
289c596c 142 }
252b5132
RH
143}
144
b34976b6 145bfd_boolean
dc810e39 146bfd_coff_reloc16_relax_section (abfd, input_section, link_info, again)
252b5132 147 bfd *abfd;
dc810e39 148 asection *input_section;
252b5132 149 struct bfd_link_info *link_info;
b34976b6 150 bfd_boolean *again;
252b5132 151{
289c596c 152 /* Get enough memory to hold the stuff. */
dc810e39
AM
153 bfd *input_bfd = input_section->owner;
154 unsigned *shrinks;
155 unsigned shrink = 0;
252b5132
RH
156 long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
157 arelent **reloc_vector = NULL;
158 long reloc_count;
159
c8a1f254
NS
160 if (link_info->relocatable)
161 (*link_info->callbacks->einfo)
162 (_("%P%F: --relax and -r may not be used together\n"));
163
252b5132
RH
164 /* We only do global relaxation once. It is not safe to do it multiple
165 times (see discussion of the "shrinks" array below). */
b34976b6 166 *again = FALSE;
252b5132
RH
167
168 if (reloc_size < 0)
b34976b6 169 return FALSE;
252b5132 170
dc810e39 171 reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
252b5132 172 if (!reloc_vector && reloc_size > 0)
b34976b6 173 return FALSE;
252b5132 174
289c596c 175 /* Get the relocs and think about them. */
252b5132
RH
176 reloc_count =
177 bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
178 _bfd_generic_link_get_symbols (input_bfd));
179 if (reloc_count < 0)
180 {
181 free (reloc_vector);
b34976b6 182 return FALSE;
252b5132
RH
183 }
184
185 /* The reloc16.c and related relaxing code is very simple, the price
186 for that simplicity is we can only call this function once for
187 each section.
188
189 So, to get the best results within that limitation, we do multiple
190 relaxing passes over each section here. That involves keeping track
191 of the "shrink" at each reloc in the section. This allows us to
192 accurately determine the relative location of two relocs within
193 this section.
194
195 In theory, if we kept the "shrinks" array for each section for the
196 entire link, we could use the generic relaxing code in the linker
197 and get better results, particularly for jsr->bsr and 24->16 bit
198 memory reference relaxations. */
289c596c 199
252b5132
RH
200 if (reloc_count > 0)
201 {
202 int another_pass = 0;
dc810e39 203 bfd_size_type amt;
252b5132 204
c4d5c859 205 /* Allocate and initialize the shrinks array for this section.
7dee875e 206 The last element is used as an accumulator of shrinks. */
dc810e39
AM
207 amt = reloc_count + 1;
208 amt *= sizeof (unsigned);
9bab7074 209 shrinks = (unsigned *) bfd_zmalloc (amt);
252b5132
RH
210
211 /* Loop until nothing changes in this section. */
bc7eab72
KH
212 do
213 {
214 arelent **parent;
215 unsigned int i;
216 long j;
217
218 another_pass = 0;
219
220 for (i = 0, parent = reloc_vector; *parent; parent++, i++)
221 {
222 /* Let the target/machine dependent code examine each reloc
223 in this section and attempt to shrink it. */
224 shrink = bfd_coff_reloc16_estimate (abfd, input_section, *parent,
225 shrinks[i], link_info);
226
227 /* If it shrunk, note it in the shrinks array and set up for
228 another pass. */
229 if (shrink != shrinks[i])
230 {
231 another_pass = 1;
232 for (j = i + 1; j <= reloc_count; j++)
233 shrinks[j] += shrink - shrinks[i];
234 }
235 }
236 }
289c596c 237 while (another_pass);
252b5132 238
c4d5c859 239 shrink = shrinks[reloc_count];
289c596c 240 free ((char *) shrinks);
252b5132
RH
241 }
242
e87a64e1 243 input_section->rawsize = input_section->size;
eea6121a 244 input_section->size -= shrink;
289c596c 245 free ((char *) reloc_vector);
b34976b6 246 return TRUE;
252b5132
RH
247}
248
249bfd_byte *
bc7eab72
KH
250bfd_coff_reloc16_get_relocated_section_contents (in_abfd,
251 link_info,
252 link_order,
253 data,
1049f94e 254 relocatable,
bc7eab72 255 symbols)
252b5132
RH
256 bfd *in_abfd;
257 struct bfd_link_info *link_info;
258 struct bfd_link_order *link_order;
259 bfd_byte *data;
1049f94e 260 bfd_boolean relocatable;
252b5132
RH
261 asymbol **symbols;
262{
289c596c 263 /* Get enough memory to hold the stuff. */
252b5132
RH
264 bfd *input_bfd = link_order->u.indirect.section->owner;
265 asection *input_section = link_order->u.indirect.section;
266 long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
267 arelent **reloc_vector;
268 long reloc_count;
eea6121a 269 bfd_size_type sz;
252b5132
RH
270
271 if (reloc_size < 0)
272 return NULL;
273
1049f94e
AM
274 /* If producing relocatable output, don't bother to relax. */
275 if (relocatable)
252b5132
RH
276 return bfd_generic_get_relocated_section_contents (in_abfd, link_info,
277 link_order,
1049f94e 278 data, relocatable,
252b5132
RH
279 symbols);
280
289c596c 281 /* Read in the section. */
eea6121a
AM
282 sz = input_section->rawsize ? input_section->rawsize : input_section->size;
283 if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
252b5132 284 return NULL;
289c596c 285
dc810e39 286 reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
252b5132
RH
287 if (!reloc_vector && reloc_size != 0)
288 return NULL;
289c596c
NC
289
290 reloc_count = bfd_canonicalize_reloc (input_bfd,
252b5132
RH
291 input_section,
292 reloc_vector,
293 symbols);
294 if (reloc_count < 0)
295 {
296 free (reloc_vector);
297 return NULL;
298 }
289c596c 299
252b5132
RH
300 if (reloc_count > 0)
301 {
302 arelent **parent = reloc_vector;
289c596c 303 arelent *reloc;
252b5132
RH
304 unsigned int dst_address = 0;
305 unsigned int src_address = 0;
306 unsigned int run;
307 unsigned int idx;
289c596c
NC
308
309 /* Find how long a run we can do. */
310 while (dst_address < link_order->size)
252b5132
RH
311 {
312 reloc = *parent;
289c596c 313 if (reloc)
252b5132
RH
314 {
315 /* Note that the relaxing didn't tie up the addresses in the
316 relocation, so we use the original address to work out the
289c596c 317 run of non-relocated data. */
252b5132
RH
318 run = reloc->address - src_address;
319 parent++;
320 }
289c596c 321 else
252b5132
RH
322 {
323 run = link_order->size - dst_address;
324 }
289c596c
NC
325
326 /* Copy the bytes. */
252b5132 327 for (idx = 0; idx < run; idx++)
289c596c
NC
328 data[dst_address++] = data[src_address++];
329
330 /* Now do the relocation. */
331 if (reloc)
252b5132
RH
332 {
333 bfd_coff_reloc16_extra_cases (input_bfd, link_info, link_order,
334 reloc, data, &src_address,
335 &dst_address);
289c596c 336 }
252b5132
RH
337 }
338 }
289c596c 339 free ((char *) reloc_vector);
252b5132
RH
340 return data;
341}
This page took 0.532325 seconds and 4 git commands to generate.