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