133965Sjdp/* 8 and 16 bit COFF relocation functions, for BFD.
2130561Sobrien   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001,
3218822Sdim   2002, 2003, 2004, 2007 Free Software Foundation, Inc.
433965Sjdp   Written by Cygnus Support.
533965Sjdp
633965SjdpThis file is part of BFD, the Binary File Descriptor library.
733965Sjdp
833965SjdpThis program is free software; you can redistribute it and/or modify
933965Sjdpit under the terms of the GNU General Public License as published by
1033965Sjdpthe Free Software Foundation; either version 2 of the License, or
1133965Sjdp(at your option) any later version.
1233965Sjdp
1333965SjdpThis program is distributed in the hope that it will be useful,
1433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1633965SjdpGNU General Public License for more details.
1733965Sjdp
1833965SjdpYou should have received a copy of the GNU General Public License
1933965Sjdpalong with this program; if not, write to the Free Software
20218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2133965Sjdp
2277298Sobrien/* Most of this hacked by Steve Chamberlain <sac@cygnus.com>.  */
2333965Sjdp
2433965Sjdp/* These routines are used by coff-h8300 and coff-z8k to do
2533965Sjdp   relocation.
2633965Sjdp
2733965Sjdp   FIXME: This code should be rewritten to support the new COFF
2833965Sjdp   linker.  Basically, they need to deal with COFF relocs rather than
2933965Sjdp   BFD generic relocs.  They should store the relocs in some location
3033965Sjdp   where coff_link_input_bfd can find them (and coff_link_input_bfd
3133965Sjdp   should be changed to use this location rather than rereading the
32130561Sobrien   file) (unless info->keep_memory is FALSE, in which case they should
3333965Sjdp   free up the relocs after dealing with them).  */
3433965Sjdp
35218822Sdim#include "sysdep.h"
3633965Sjdp#include "bfd.h"
3733965Sjdp#include "libbfd.h"
3833965Sjdp#include "bfdlink.h"
3933965Sjdp#include "genlink.h"
4033965Sjdp#include "coff/internal.h"
4133965Sjdp#include "libcoff.h"
4233965Sjdp
4333965Sjdpbfd_vma
4433965Sjdpbfd_coff_reloc16_get_value (reloc, link_info, input_section)
4533965Sjdp     arelent *reloc;
4633965Sjdp     struct bfd_link_info *link_info;
4733965Sjdp     asection *input_section;
4833965Sjdp{
4933965Sjdp  bfd_vma value;
5033965Sjdp  asymbol *symbol = *(reloc->sym_ptr_ptr);
5133965Sjdp  /* A symbol holds a pointer to a section, and an offset from the
5233965Sjdp     base of the section.  To relocate, we find where the section will
5377298Sobrien     live in the output and add that in.  */
5433965Sjdp
5533965Sjdp  if (bfd_is_und_section (symbol->section)
5633965Sjdp      || bfd_is_com_section (symbol->section))
5733965Sjdp    {
5833965Sjdp      struct bfd_link_hash_entry *h;
5933965Sjdp
6033965Sjdp      /* The symbol is undefined in this BFD.  Look it up in the
6133965Sjdp	 global linker hash table.  FIXME: This should be changed when
6233965Sjdp	 we convert this stuff to use a specific final_link function
6333965Sjdp	 and change the interface to bfd_relax_section to not require
6433965Sjdp	 the generic symbols.  */
6533965Sjdp      h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info,
6633965Sjdp					bfd_asymbol_name (symbol),
67130561Sobrien					FALSE, FALSE, TRUE);
6833965Sjdp      if (h != (struct bfd_link_hash_entry *) NULL
6933965Sjdp	  && (h->type == bfd_link_hash_defined
7033965Sjdp	      || h->type == bfd_link_hash_defweak))
7133965Sjdp	value = (h->u.def.value
7233965Sjdp		 + h->u.def.section->output_section->vma
7333965Sjdp		 + h->u.def.section->output_offset);
7433965Sjdp      else if (h != (struct bfd_link_hash_entry *) NULL
7533965Sjdp	       && h->type == bfd_link_hash_common)
7633965Sjdp	value = h->u.c.size;
7733965Sjdp      else
7833965Sjdp	{
7977298Sobrien	  if (!((*link_info->callbacks->undefined_symbol)
8077298Sobrien		(link_info, bfd_asymbol_name (symbol),
8177298Sobrien		 input_section->owner, input_section, reloc->address,
82130561Sobrien		 TRUE)))
8333965Sjdp	    abort ();
8433965Sjdp	  value = 0;
8533965Sjdp	}
8633965Sjdp    }
8777298Sobrien  else
8833965Sjdp    {
8977298Sobrien      value = symbol->value
9077298Sobrien	+ symbol->section->output_offset
9177298Sobrien	+ symbol->section->output_section->vma;
9233965Sjdp    }
9377298Sobrien
9477298Sobrien  /* Add the value contained in the relocation.  */
9533965Sjdp  value += reloc->addend;
9677298Sobrien
9733965Sjdp  return value;
9833965Sjdp}
9933965Sjdp
10033965Sjdpvoid
10177298Sobrienbfd_perform_slip (abfd, slip, input_section, value)
10233965Sjdp     bfd *abfd;
10333965Sjdp     unsigned int slip;
10433965Sjdp     asection *input_section;
10533965Sjdp     bfd_vma value;
10633965Sjdp{
10733965Sjdp  asymbol **s;
10833965Sjdp
10933965Sjdp  s = _bfd_generic_link_get_symbols (abfd);
11033965Sjdp  BFD_ASSERT (s != (asymbol **) NULL);
11133965Sjdp
11233965Sjdp  /* Find all symbols past this point, and make them know
11377298Sobrien     what's happened.  */
11477298Sobrien  while (*s)
11533965Sjdp    {
11633965Sjdp      asymbol *p = *s;
11777298Sobrien      if (p->section == input_section)
11833965Sjdp	{
11977298Sobrien	  /* This was pointing into this section, so mangle it.  */
12033965Sjdp	  if (p->value > value)
12133965Sjdp	    {
12233965Sjdp	      p->value -= slip;
12333965Sjdp	      if (p->udata.p != NULL)
12433965Sjdp		{
12533965Sjdp		  struct generic_link_hash_entry *h;
12633965Sjdp
12733965Sjdp		  h = (struct generic_link_hash_entry *) p->udata.p;
12833965Sjdp		  BFD_ASSERT (h->root.type == bfd_link_hash_defined
12933965Sjdp			      || h->root.type == bfd_link_hash_defweak);
13033965Sjdp		  h->root.u.def.value -= slip;
13133965Sjdp		  BFD_ASSERT (h->root.u.def.value == p->value);
13233965Sjdp		}
13333965Sjdp	    }
13433965Sjdp	}
13533965Sjdp      s++;
13677298Sobrien    }
13733965Sjdp}
13833965Sjdp
139130561Sobrienbfd_boolean
14089857Sobrienbfd_coff_reloc16_relax_section (abfd, input_section, link_info, again)
14133965Sjdp     bfd *abfd;
14289857Sobrien     asection *input_section;
14333965Sjdp     struct bfd_link_info *link_info;
144130561Sobrien     bfd_boolean *again;
14533965Sjdp{
14677298Sobrien  /* Get enough memory to hold the stuff.  */
14789857Sobrien  bfd *input_bfd = input_section->owner;
14889857Sobrien  unsigned *shrinks;
14989857Sobrien  unsigned shrink = 0;
15033965Sjdp  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
15133965Sjdp  arelent **reloc_vector = NULL;
15233965Sjdp  long reloc_count;
15333965Sjdp
15433965Sjdp  /* We only do global relaxation once.  It is not safe to do it multiple
15533965Sjdp     times (see discussion of the "shrinks" array below).  */
156130561Sobrien  *again = FALSE;
15733965Sjdp
15833965Sjdp  if (reloc_size < 0)
159130561Sobrien    return FALSE;
16033965Sjdp
16189857Sobrien  reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
16233965Sjdp  if (!reloc_vector && reloc_size > 0)
163130561Sobrien    return FALSE;
16433965Sjdp
16577298Sobrien  /* Get the relocs and think about them.  */
16633965Sjdp  reloc_count =
16733965Sjdp    bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
16833965Sjdp			    _bfd_generic_link_get_symbols (input_bfd));
16933965Sjdp  if (reloc_count < 0)
17033965Sjdp    {
17133965Sjdp      free (reloc_vector);
172130561Sobrien      return FALSE;
17333965Sjdp    }
17433965Sjdp
17533965Sjdp  /* The reloc16.c and related relaxing code is very simple, the price
17633965Sjdp     for that simplicity is we can only call this function once for
17733965Sjdp     each section.
17833965Sjdp
17933965Sjdp     So, to get the best results within that limitation, we do multiple
18033965Sjdp     relaxing passes over each section here.  That involves keeping track
18133965Sjdp     of the "shrink" at each reloc in the section.  This allows us to
18233965Sjdp     accurately determine the relative location of two relocs within
18333965Sjdp     this section.
18433965Sjdp
18533965Sjdp     In theory, if we kept the "shrinks" array for each section for the
18633965Sjdp     entire link, we could use the generic relaxing code in the linker
18733965Sjdp     and get better results, particularly for jsr->bsr and 24->16 bit
18833965Sjdp     memory reference relaxations.  */
18977298Sobrien
19033965Sjdp  if (reloc_count > 0)
19133965Sjdp    {
19233965Sjdp      int another_pass = 0;
19389857Sobrien      bfd_size_type amt;
19433965Sjdp
19560484Sobrien      /* Allocate and initialize the shrinks array for this section.
196130561Sobrien	 The last element is used as an accumulator of shrinks.  */
19789857Sobrien      amt = reloc_count + 1;
19889857Sobrien      amt *= sizeof (unsigned);
199104834Sobrien      shrinks = (unsigned *) bfd_zmalloc (amt);
20033965Sjdp
20133965Sjdp      /* Loop until nothing changes in this section.  */
202130561Sobrien      do
203130561Sobrien	{
204130561Sobrien	  arelent **parent;
205130561Sobrien	  unsigned int i;
206130561Sobrien	  long j;
20733965Sjdp
208130561Sobrien	  another_pass = 0;
20933965Sjdp
210130561Sobrien	  for (i = 0, parent = reloc_vector; *parent; parent++, i++)
211130561Sobrien	    {
212130561Sobrien	      /* Let the target/machine dependent code examine each reloc
213130561Sobrien		 in this section and attempt to shrink it.  */
214130561Sobrien	      shrink = bfd_coff_reloc16_estimate (abfd, input_section, *parent,
215130561Sobrien						  shrinks[i], link_info);
21633965Sjdp
217130561Sobrien	      /* If it shrunk, note it in the shrinks array and set up for
218130561Sobrien		 another pass.  */
219130561Sobrien	      if (shrink != shrinks[i])
220130561Sobrien		{
221130561Sobrien		  another_pass = 1;
222130561Sobrien		  for (j = i + 1; j <= reloc_count; j++)
223130561Sobrien		    shrinks[j] += shrink - shrinks[i];
224130561Sobrien		}
225130561Sobrien	    }
226130561Sobrien	}
22777298Sobrien      while (another_pass);
22833965Sjdp
22960484Sobrien      shrink = shrinks[reloc_count];
23077298Sobrien      free ((char *) shrinks);
23133965Sjdp    }
23233965Sjdp
233218822Sdim  input_section->rawsize = input_section->size;
234218822Sdim  input_section->size -= shrink;
23577298Sobrien  free ((char *) reloc_vector);
236130561Sobrien  return TRUE;
23733965Sjdp}
23833965Sjdp
23933965Sjdpbfd_byte *
240130561Sobrienbfd_coff_reloc16_get_relocated_section_contents (in_abfd,
241130561Sobrien						 link_info,
242130561Sobrien						 link_order,
243130561Sobrien						 data,
244130561Sobrien						 relocatable,
245130561Sobrien						 symbols)
24633965Sjdp     bfd *in_abfd;
24733965Sjdp     struct bfd_link_info *link_info;
24833965Sjdp     struct bfd_link_order *link_order;
24933965Sjdp     bfd_byte *data;
250130561Sobrien     bfd_boolean relocatable;
25133965Sjdp     asymbol **symbols;
25233965Sjdp{
25377298Sobrien  /* Get enough memory to hold the stuff.  */
25433965Sjdp  bfd *input_bfd = link_order->u.indirect.section->owner;
25533965Sjdp  asection *input_section = link_order->u.indirect.section;
25633965Sjdp  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
25733965Sjdp  arelent **reloc_vector;
25833965Sjdp  long reloc_count;
259218822Sdim  bfd_size_type sz;
26033965Sjdp
26133965Sjdp  if (reloc_size < 0)
26233965Sjdp    return NULL;
26333965Sjdp
264130561Sobrien  /* If producing relocatable output, don't bother to relax.  */
265130561Sobrien  if (relocatable)
26633965Sjdp    return bfd_generic_get_relocated_section_contents (in_abfd, link_info,
26733965Sjdp						       link_order,
268130561Sobrien						       data, relocatable,
26933965Sjdp						       symbols);
27033965Sjdp
27177298Sobrien  /* Read in the section.  */
272218822Sdim  sz = input_section->rawsize ? input_section->rawsize : input_section->size;
273218822Sdim  if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
27433965Sjdp    return NULL;
27577298Sobrien
27689857Sobrien  reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
27733965Sjdp  if (!reloc_vector && reloc_size != 0)
27833965Sjdp    return NULL;
27977298Sobrien
28077298Sobrien  reloc_count = bfd_canonicalize_reloc (input_bfd,
28133965Sjdp					input_section,
28233965Sjdp					reloc_vector,
28333965Sjdp					symbols);
28433965Sjdp  if (reloc_count < 0)
28533965Sjdp    {
28633965Sjdp      free (reloc_vector);
28733965Sjdp      return NULL;
28833965Sjdp    }
28977298Sobrien
29033965Sjdp  if (reloc_count > 0)
29133965Sjdp    {
29233965Sjdp      arelent **parent = reloc_vector;
29377298Sobrien      arelent *reloc;
29433965Sjdp      unsigned int dst_address = 0;
29533965Sjdp      unsigned int src_address = 0;
29633965Sjdp      unsigned int run;
29733965Sjdp      unsigned int idx;
29877298Sobrien
29977298Sobrien      /* Find how long a run we can do.  */
30077298Sobrien      while (dst_address < link_order->size)
30133965Sjdp	{
30233965Sjdp	  reloc = *parent;
30377298Sobrien	  if (reloc)
30433965Sjdp	    {
30533965Sjdp	      /* Note that the relaxing didn't tie up the addresses in the
30633965Sjdp		 relocation, so we use the original address to work out the
30777298Sobrien		 run of non-relocated data.  */
30833965Sjdp	      run = reloc->address - src_address;
30933965Sjdp	      parent++;
31033965Sjdp	    }
31177298Sobrien	  else
31233965Sjdp	    {
31333965Sjdp	      run = link_order->size - dst_address;
31433965Sjdp	    }
31577298Sobrien
31677298Sobrien	  /* Copy the bytes.  */
31733965Sjdp	  for (idx = 0; idx < run; idx++)
31877298Sobrien	    data[dst_address++] = data[src_address++];
31977298Sobrien
32077298Sobrien	  /* Now do the relocation.  */
32177298Sobrien	  if (reloc)
32233965Sjdp	    {
32333965Sjdp	      bfd_coff_reloc16_extra_cases (input_bfd, link_info, link_order,
32433965Sjdp					    reloc, data, &src_address,
32533965Sjdp					    &dst_address);
32677298Sobrien	    }
32733965Sjdp	}
32833965Sjdp    }
32977298Sobrien  free ((char *) reloc_vector);
33033965Sjdp  return data;
33133965Sjdp}
332