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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [bfd/] [reloc16.c] - Blame information for rev 1772

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

Line No. Rev Author Line
1 104 markom
/* 8 and 16 bit COFF relocation functions, for BFD.
2
   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1998
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
/*
23
Most of this hacked by  Steve Chamberlain,
24
                        sac@cygnus.com
25
*/
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 "bfd.h"
39
#include "sysdep.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 (reloc, link_info, input_section)
48
     arelent *reloc;
49
     struct bfd_link_info *link_info;
50
     asection *input_section;
51
{
52
  bfd_vma value;
53
  asymbol *symbol = *(reloc->sym_ptr_ptr);
54
  /* A symbol holds a pointer to a section, and an offset from the
55
     base of the section.  To relocate, we find where the section will
56
     live in the output and add that in */
57
 
58
  if (bfd_is_und_section (symbol->section)
59
      || bfd_is_com_section (symbol->section))
60
    {
61
      struct bfd_link_hash_entry *h;
62
 
63
      /* The symbol is undefined in this BFD.  Look it up in the
64
         global linker hash table.  FIXME: This should be changed when
65
         we convert this stuff to use a specific final_link function
66
         and change the interface to bfd_relax_section to not require
67
         the generic symbols.  */
68
      h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info,
69
                                        bfd_asymbol_name (symbol),
70
                                        false, false, true);
71
      if (h != (struct bfd_link_hash_entry *) NULL
72
          && (h->type == bfd_link_hash_defined
73
              || h->type == bfd_link_hash_defweak))
74
        value = (h->u.def.value
75
                 + h->u.def.section->output_section->vma
76
                 + h->u.def.section->output_offset);
77
      else if (h != (struct bfd_link_hash_entry *) NULL
78
               && h->type == bfd_link_hash_common)
79
        value = h->u.c.size;
80
      else
81
        {
82
          if (! ((*link_info->callbacks->undefined_symbol)
83
                 (link_info, bfd_asymbol_name (symbol),
84
                  input_section->owner, input_section, reloc->address,
85
                  true)))
86
            abort ();
87
          value = 0;
88
        }
89
    }
90
  else
91
    {
92
      value = symbol->value +
93
        symbol->section->output_offset +
94
          symbol->section->output_section->vma;
95
    }
96
 
97
  /* Add the value contained in the relocation */
98
  value += reloc->addend;
99
 
100
  return value;
101
}
102
 
103
void
104
bfd_perform_slip(abfd, slip, input_section, value)
105
     bfd *abfd;
106
     unsigned int slip;
107
     asection *input_section;
108
     bfd_vma value;
109
{
110
  asymbol **s;
111
 
112
  s = _bfd_generic_link_get_symbols (abfd);
113
  BFD_ASSERT (s != (asymbol **) NULL);
114
 
115
  /* Find all symbols past this point, and make them know
116
     what's happened */
117
  while (*s)
118
    {
119
      asymbol *p = *s;
120
      if (p->section == input_section)
121
        {
122
          /* This was pointing into this section, so mangle it */
123
          if (p->value > value)
124
            {
125
              p->value -= slip;
126
              if (p->udata.p != NULL)
127
                {
128
                  struct generic_link_hash_entry *h;
129
 
130
                  h = (struct generic_link_hash_entry *) p->udata.p;
131
                  BFD_ASSERT (h->root.type == bfd_link_hash_defined
132
                              || h->root.type == bfd_link_hash_defweak);
133
                  h->root.u.def.value -= slip;
134
                  BFD_ASSERT (h->root.u.def.value == p->value);
135
                }
136
            }
137
        }
138
      s++;
139
    }
140
}
141
 
142
boolean
143
bfd_coff_reloc16_relax_section (abfd, i, link_info, again)
144
     bfd *abfd;
145
     asection *i;
146
     struct bfd_link_info *link_info;
147
     boolean *again;
148
{
149
  /* Get enough memory to hold the stuff */
150
  bfd *input_bfd = i->owner;
151
  asection *input_section = i;
152
  int *shrinks;
153
  int 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
  /* We only do global relaxation once.  It is not safe to do it multiple
159
     times (see discussion of the "shrinks" array below).  */
160
  *again = false;
161
 
162
  if (reloc_size < 0)
163
    return false;
164
 
165
  reloc_vector = (arelent **) bfd_malloc (reloc_size);
166
  if (!reloc_vector && reloc_size > 0)
167
    return false;
168
 
169
  /* Get the relocs and think about them */
170
  reloc_count =
171
    bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
172
                            _bfd_generic_link_get_symbols (input_bfd));
173
  if (reloc_count < 0)
174
    {
175
      free (reloc_vector);
176
      return false;
177
    }
178
 
179
  /* The reloc16.c and related relaxing code is very simple, the price
180
     for that simplicity is we can only call this function once for
181
     each section.
182
 
183
     So, to get the best results within that limitation, we do multiple
184
     relaxing passes over each section here.  That involves keeping track
185
     of the "shrink" at each reloc in the section.  This allows us to
186
     accurately determine the relative location of two relocs within
187
     this section.
188
 
189
     In theory, if we kept the "shrinks" array for each section for the
190
     entire link, we could use the generic relaxing code in the linker
191
     and get better results, particularly for jsr->bsr and 24->16 bit
192
     memory reference relaxations.  */
193
 
194
  if (reloc_count > 0)
195
    {
196
      int another_pass = 0;
197
 
198
      /* Allocate and initialize the shrinks array for this section.
199
         The last element is used as an accumlator of shrinks.  */
200
      shrinks = (int *) bfd_malloc ((reloc_count + 1) * sizeof (int));
201
      memset (shrinks, 0, (reloc_count + 1) * sizeof (int));
202
 
203
      /* Loop until nothing changes in this section.  */
204
      do {
205
        arelent **parent;
206
        unsigned int i;
207
        long j;
208
 
209
        another_pass = 0;
210
 
211
        for (i = 0, parent = reloc_vector; *parent; parent++, i++)
212
          {
213
            /* Let the target/machine dependent code examine each reloc
214
               in this section and attempt to shrink it.  */
215
            shrink = bfd_coff_reloc16_estimate (abfd, input_section, *parent,
216
                                                shrinks[i], link_info);
217
 
218
            /* If it shrunk, note it in the shrinks array and set up for
219
               another pass.  */
220
            if (shrink != shrinks[i])
221
              {
222
                another_pass = 1;
223
                for (j = i + 1; j <= reloc_count; j++)
224
                  shrinks[j] += shrink - shrinks[i];
225
              }
226
          }
227
 
228
      } while (another_pass);
229
 
230
      shrink = shrinks[reloc_count];
231
      free((char *)shrinks);
232
    }
233
 
234
  input_section->_cooked_size -= shrink;
235
  free((char *)reloc_vector);
236
  return true;
237
}
238
 
239
bfd_byte *
240
bfd_coff_reloc16_get_relocated_section_contents(in_abfd,
241
                                                link_info,
242
                                                link_order,
243
                                                data,
244
                                                relocateable,
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
     boolean relocateable;
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
 
260
  if (reloc_size < 0)
261
    return NULL;
262
 
263
  /* If producing relocateable output, don't bother to relax.  */
264
  if (relocateable)
265
    return bfd_generic_get_relocated_section_contents (in_abfd, link_info,
266
                                                       link_order,
267
                                                       data, relocateable,
268
                                                       symbols);
269
 
270
  /* read in the section */
271
  if (! bfd_get_section_contents(input_bfd,
272
                                 input_section,
273
                                 data,
274
                                 0,
275
                                 input_section->_raw_size))
276
    return NULL;
277
 
278
 
279
  reloc_vector = (arelent **) bfd_malloc((size_t) 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
          /* Copy the bytes */
319
          for (idx = 0; idx < run; idx++)
320
            {
321
              data[dst_address++] = data[src_address++];
322
            }
323
 
324
          /* Now do the relocation */
325
 
326
          if (reloc)
327
            {
328
              bfd_coff_reloc16_extra_cases (input_bfd, link_info, link_order,
329
                                            reloc, data, &src_address,
330
                                            &dst_address);
331
            }
332
        }
333
    }
334
  free((char *)reloc_vector);
335
  return data;
336
}
337
 

powered by: WebSVN 2.1.0

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