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