OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [bfd/] [reloc16.c] - Blame information for rev 1783

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* 8 and 16 bit COFF relocation functions, for BFD.
2
   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001
3
   Free Software Foundation, Inc.
4
   Written by Cygnus Support.
5
 
6
This file is part of BFD, the Binary File Descriptor library.
7
 
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 2 of the License, or
11
(at your option) any later version.
12
 
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "bfd.h"
36
#include "sysdep.h"
37
#include "libbfd.h"
38
#include "bfdlink.h"
39
#include "genlink.h"
40
#include "coff/internal.h"
41
#include "libcoff.h"
42
 
43
bfd_vma
44
bfd_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
 
100
void
101
bfd_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
 
139
boolean
140
bfd_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
     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 accumlator 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
        arelent **parent;
204
        unsigned int i;
205
        long j;
206
 
207
        another_pass = 0;
208
 
209
        for (i = 0, parent = reloc_vector; *parent; parent++, i++)
210
          {
211
            /* Let the target/machine dependent code examine each reloc
212
               in this section and attempt to shrink it.  */
213
            shrink = bfd_coff_reloc16_estimate (abfd, input_section, *parent,
214
                                                shrinks[i], link_info);
215
 
216
            /* If it shrunk, note it in the shrinks array and set up for
217
               another pass.  */
218
            if (shrink != shrinks[i])
219
              {
220
                another_pass = 1;
221
                for (j = i + 1; j <= reloc_count; j++)
222
                  shrinks[j] += shrink - shrinks[i];
223
              }
224
          }
225
      }
226
      while (another_pass);
227
 
228
      shrink = shrinks[reloc_count];
229
      free ((char *) shrinks);
230
    }
231
 
232
  input_section->_cooked_size -= shrink;
233
  free ((char *) reloc_vector);
234
  return true;
235
}
236
 
237
bfd_byte *
238
bfd_coff_reloc16_get_relocated_section_contents(in_abfd,
239
                                                link_info,
240
                                                link_order,
241
                                                data,
242
                                                relocateable,
243
                                                symbols)
244
     bfd *in_abfd;
245
     struct bfd_link_info *link_info;
246
     struct bfd_link_order *link_order;
247
     bfd_byte *data;
248
     boolean relocateable;
249
     asymbol **symbols;
250
{
251
  /* Get enough memory to hold the stuff.  */
252
  bfd *input_bfd = link_order->u.indirect.section->owner;
253
  asection *input_section = link_order->u.indirect.section;
254
  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
255
  arelent **reloc_vector;
256
  long reloc_count;
257
 
258
  if (reloc_size < 0)
259
    return NULL;
260
 
261
  /* If producing relocateable output, don't bother to relax.  */
262
  if (relocateable)
263
    return bfd_generic_get_relocated_section_contents (in_abfd, link_info,
264
                                                       link_order,
265
                                                       data, relocateable,
266
                                                       symbols);
267
 
268
  /* Read in the section.  */
269
  if (!bfd_get_section_contents(input_bfd,
270
                                input_section,
271
                                data,
272
                                (bfd_vma) 0,
273
                                input_section->_raw_size))
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.