~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to binutils/bfd/aout-ns32k.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* BFD back-end for ns32k a.out-ish binaries.
 
2
   Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1998, 2000, 2001
 
3
   Free Software Foundation, Inc.
 
4
   Contributed by Ian Dall (idall@eleceng.adelaide.edu.au).
 
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
#define BYTES_IN_WORD 4
 
23
 
 
24
#include "bfd.h"
 
25
#include "aout/aout64.h"
 
26
#include "ns32k.h"
 
27
 
 
28
/* Do not "beautify" the CONCAT* macro args.  Traditional C will not
 
29
   remove whitespace added here, and thus will fail to concatenate
 
30
   the tokens.  */
 
31
#define MYNS(OP) CONCAT2 (ns32kaout_,OP)
 
32
 
 
33
reloc_howto_type *
 
34
MYNS(bfd_reloc_type_lookup)
 
35
  PARAMS((bfd *abfd AND
 
36
          bfd_reloc_code_real_type code));
 
37
 
 
38
boolean
 
39
MYNS(write_object_contents)
 
40
  PARAMS((bfd *abfd));
 
41
 
 
42
/* Avoid multiple definitions from aoutx if supporting
 
43
   standard a.out format(s) as well as this one.  */
 
44
#define NAME(x,y) CONCAT3 (ns32kaout,_32_,y)
 
45
 
 
46
void bfd_ns32k_arch PARAMS ((void));
 
47
 
 
48
#include "libaout.h"
 
49
 
 
50
#define MY(OP) MYNS(OP)
 
51
 
 
52
#define MY_swap_std_reloc_in MY(swap_std_reloc_in)
 
53
#define MY_swap_std_reloc_out MY(swap_std_reloc_out)
 
54
 
 
55
static void
 
56
MY_swap_std_reloc_in PARAMS ((bfd *abfd, struct reloc_std_external *bytes,
 
57
                              arelent *cache_ptr, asymbol **symbols,
 
58
                              bfd_size_type symcount));
 
59
static void
 
60
MY_swap_std_reloc_out PARAMS ((bfd *abfd, arelent *g,
 
61
                               struct reloc_std_external *natptr));
 
62
reloc_howto_type *
 
63
MY(reloc_howto) PARAMS ((bfd *, struct reloc_std_external *,
 
64
                         int *, int *, int *));
 
65
void
 
66
MY(put_reloc) PARAMS ((bfd *, int, int, bfd_vma, reloc_howto_type *,
 
67
                       struct reloc_std_external *));
 
68
 
 
69
/* The ns32k series is ah, unusual, when it comes to relocation.
 
70
   There are three storage methods for relocateable objects.  There
 
71
   are displacements, immediate operands and ordinary twos complement
 
72
   data. Of these, only the last fits into the standard relocation
 
73
   scheme.  Immediate operands are stored huffman encoded and
 
74
   immediate operands are stored big endian (where as the natural byte
 
75
   order is little endian for this achitecture).
 
76
 
 
77
   Note that the ns32k displacement storage method is orthogonal to
 
78
   whether the relocation is pc relative or not. The "displacement"
 
79
   storage scheme is used for essentially all address constants. The
 
80
   displacement can be relative to zero (absolute displacement),
 
81
   relative to the pc (pc relative), the stack pointer, the frame
 
82
   pointer, the static base register and general purpose register etc.
 
83
 
 
84
   For example:
 
85
 
 
86
   sym1: .long .         # pc relative 2's complement
 
87
   sym1: .long foo       # 2's complement not pc relative
 
88
 
 
89
   self:  movd @self, r0 # pc relative displacement
 
90
          movd foo, r0   # non pc relative displacement
 
91
 
 
92
   self:  movd self, r0  # pc relative immediate
 
93
          movd foo, r0   # non pc relative immediate
 
94
 
 
95
   In addition, for historical reasons the encoding of the relocation types
 
96
   in the a.out format relocation entries is such that even the relocation
 
97
   methods which are standard are not encoded the standard way. */
 
98
 
 
99
reloc_howto_type MY(howto_table)[] =
 
100
  {
 
101
    /* ns32k immediate operands.  */
 
102
    HOWTO (BFD_RELOC_NS32K_IMM_8, 0, 0, 8, false, 0, true,
 
103
           _bfd_ns32k_reloc_imm, "NS32K_IMM_8",
 
104
           true, 0x000000ff,0x000000ff, false),
 
105
    HOWTO (BFD_RELOC_NS32K_IMM_16, 0, 1, 16, false, 0, true,
 
106
           _bfd_ns32k_reloc_imm,  "NS32K_IMM_16",
 
107
           true, 0x0000ffff,0x0000ffff, false),
 
108
    HOWTO (BFD_RELOC_NS32K_IMM_32, 0, 2, 32, false, 0, true,
 
109
           _bfd_ns32k_reloc_imm, "NS32K_IMM_32",
 
110
           true, 0xffffffff,0xffffffff, false),
 
111
    HOWTO (BFD_RELOC_NS32K_IMM_8_PCREL, 0, 0, 8, true, 0, false,
 
112
           _bfd_ns32k_reloc_imm, "PCREL_NS32K_IMM_8",
 
113
           true, 0x000000ff, 0x000000ff, false),
 
114
    HOWTO (BFD_RELOC_NS32K_IMM_16_PCREL, 0, 1, 16, true, 0, false,
 
115
           _bfd_ns32k_reloc_imm, "PCREL_NS32K_IMM_16",
 
116
           true, 0x0000ffff,0x0000ffff, false),
 
117
    HOWTO (BFD_RELOC_NS32K_IMM_32_PCREL, 0, 2, 32, true, 0, false,
 
118
           _bfd_ns32k_reloc_imm, "PCREL_NS32K_IMM_32",
 
119
           true, 0xffffffff,0xffffffff, false),
 
120
 
 
121
    /* ns32k displacements.  */
 
122
    HOWTO (BFD_RELOC_NS32K_DISP_8, 0, 0, 8, false, 0, true,
 
123
           _bfd_ns32k_reloc_disp, "NS32K_DISP_8",
 
124
           true, 0x000000ff,0x000000ff, false),
 
125
    HOWTO (BFD_RELOC_NS32K_DISP_16, 0, 1, 16, false, 0, true,
 
126
           _bfd_ns32k_reloc_disp, "NS32K_DISP_16",
 
127
           true, 0x0000ffff, 0x0000ffff, false),
 
128
    HOWTO (BFD_RELOC_NS32K_DISP_32, 0, 2, 32, false, 0, true,
 
129
           _bfd_ns32k_reloc_disp, "NS32K_DISP_32",
 
130
           true, 0xffffffff, 0xffffffff, false),
 
131
    HOWTO (BFD_RELOC_NS32K_DISP_8_PCREL, 0, 0, 8, true, 0, false,
 
132
           _bfd_ns32k_reloc_disp, "PCREL_NS32K_DISP_8",
 
133
           true, 0x000000ff,0x000000ff, false),
 
134
    HOWTO (BFD_RELOC_NS32K_DISP_16_PCREL, 0, 1, 16, true, 0, false,
 
135
           _bfd_ns32k_reloc_disp, "PCREL_NS32K_DISP_16",
 
136
           true, 0x0000ffff,0x0000ffff, false),
 
137
    HOWTO (BFD_RELOC_NS32K_DISP_32_PCREL, 0, 2, 32, true, 0, false,
 
138
           _bfd_ns32k_reloc_disp, "PCREL_NS32K_DISP_32",
 
139
           true, 0xffffffff,0xffffffff, false),
 
140
 
 
141
    /* Normal 2's complement.  */
 
142
    HOWTO (BFD_RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield,0,
 
143
           "8", true, 0x000000ff,0x000000ff, false),
 
144
    HOWTO (BFD_RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield,0,
 
145
           "16", true, 0x0000ffff,0x0000ffff, false),
 
146
    HOWTO (BFD_RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,
 
147
           "32", true, 0xffffffff,0xffffffff, false),
 
148
    HOWTO (BFD_RELOC_8_PCREL, 0, 0, 8, true, 0, complain_overflow_signed, 0,
 
149
           "PCREL_8", true, 0x000000ff,0x000000ff, false),
 
150
    HOWTO (BFD_RELOC_16_PCREL, 0, 1, 16, true, 0, complain_overflow_signed, 0,
 
151
           "PCREL_16", true, 0x0000ffff,0x0000ffff, false),
 
152
    HOWTO (BFD_RELOC_32_PCREL, 0, 2, 32, true, 0, complain_overflow_signed, 0,
 
153
           "PCREL_32", true, 0xffffffff,0xffffffff, false),
 
154
  };
 
155
 
 
156
#define CTOR_TABLE_RELOC_HOWTO(BFD) (MY(howto_table) + 14)
 
157
 
 
158
#define RELOC_STD_BITS_NS32K_TYPE_BIG 0x06
 
159
#define RELOC_STD_BITS_NS32K_TYPE_LITTLE 0x60
 
160
#define RELOC_STD_BITS_NS32K_TYPE_SH_BIG 1
 
161
#define RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE 5
 
162
 
 
163
reloc_howto_type *
 
164
MY(reloc_howto) (abfd, rel, r_index, r_extern, r_pcrel)
 
165
     bfd *abfd ATTRIBUTE_UNUSED;
 
166
     struct reloc_std_external *rel;
 
167
     int *r_index;
 
168
     int *r_extern;
 
169
     int *r_pcrel;
 
170
{
 
171
  unsigned int r_length;
 
172
  int r_ns32k_type;
 
173
 
 
174
  /*  BFD_ASSERT(bfd_header_little_endian (abfd)); */
 
175
  *r_index =  ((rel->r_index[2] << 16)
 
176
               | (rel->r_index[1] << 8)
 
177
               |  rel->r_index[0] );
 
178
  *r_extern  = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
 
179
  *r_pcrel   = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
 
180
  r_length  =  ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
 
181
                >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
 
182
  r_ns32k_type  =  ((rel->r_type[0] & RELOC_STD_BITS_NS32K_TYPE_LITTLE)
 
183
                    >> RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE);
 
184
  return (MY(howto_table) + r_length + 3 * (*r_pcrel) + 6 * r_ns32k_type);
 
185
}
 
186
 
 
187
#define MY_reloc_howto(BFD, REL, IN, EX, PC) \
 
188
  MY(reloc_howto) (BFD, REL, &IN, &EX, &PC)
 
189
 
 
190
void
 
191
MY(put_reloc) (abfd, r_extern, r_index, value, howto, reloc)
 
192
     bfd *abfd;
 
193
     int r_extern;
 
194
     int r_index;
 
195
     bfd_vma value;
 
196
     reloc_howto_type *howto;
 
197
     struct reloc_std_external *reloc;
 
198
{
 
199
  unsigned int r_length;
 
200
  int r_pcrel;
 
201
  int r_ns32k_type;
 
202
 
 
203
  PUT_WORD (abfd, value, reloc->r_address);
 
204
  r_length = howto->size ;      /* Size as a power of two.  */
 
205
  r_pcrel  = (int) howto->pc_relative; /* Relative to PC?  */
 
206
  r_ns32k_type = (howto - MY(howto_table) )/6;
 
207
 
 
208
  /*  BFD_ASSERT (bfd_header_little_endian (abfd)); */
 
209
  reloc->r_index[2] = r_index >> 16;
 
210
  reloc->r_index[1] = r_index >> 8;
 
211
  reloc->r_index[0] = r_index;
 
212
  reloc->r_type[0] =
 
213
    (r_extern?    RELOC_STD_BITS_EXTERN_LITTLE: 0)
 
214
      | (r_pcrel?     RELOC_STD_BITS_PCREL_LITTLE: 0)
 
215
        | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE)
 
216
          | (r_ns32k_type <<  RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE);
 
217
}
 
218
 
 
219
#define MY_put_reloc(BFD, EXT, IDX, VAL, HOWTO, RELOC) \
 
220
  MY(put_reloc) (BFD, EXT, IDX, VAL, HOWTO, RELOC)
 
221
 
 
222
#define STAT_FOR_EXEC
 
223
 
 
224
#define MY_final_link_relocate _bfd_ns32k_final_link_relocate
 
225
#define MY_relocate_contents _bfd_ns32k_relocate_contents
 
226
 
 
227
#include "aoutx.h"
 
228
 
 
229
reloc_howto_type *
 
230
MY(bfd_reloc_type_lookup) (abfd,code)
 
231
     bfd *abfd;
 
232
     bfd_reloc_code_real_type code;
 
233
{
 
234
 
 
235
#define ENTRY(i,j)      case i: return &MY(howto_table)[j]
 
236
 
 
237
  int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE;
 
238
 
 
239
  BFD_ASSERT(ext == 0);
 
240
  if (code == BFD_RELOC_CTOR)
 
241
    switch (bfd_get_arch_info (abfd)->bits_per_address)
 
242
      {
 
243
      case 32:
 
244
        code = BFD_RELOC_32;
 
245
        break;
 
246
      default:
 
247
        break;
 
248
      }
 
249
  switch (code)
 
250
    {
 
251
      ENTRY(BFD_RELOC_NS32K_IMM_8, 0);
 
252
      ENTRY(BFD_RELOC_NS32K_IMM_16, 1);
 
253
      ENTRY(BFD_RELOC_NS32K_IMM_32, 2);
 
254
      ENTRY(BFD_RELOC_NS32K_IMM_8_PCREL, 3);
 
255
      ENTRY(BFD_RELOC_NS32K_IMM_16_PCREL, 4);
 
256
      ENTRY(BFD_RELOC_NS32K_IMM_32_PCREL, 5);
 
257
      ENTRY(BFD_RELOC_NS32K_DISP_8, 6);
 
258
      ENTRY(BFD_RELOC_NS32K_DISP_16, 7);
 
259
      ENTRY(BFD_RELOC_NS32K_DISP_32, 8);
 
260
      ENTRY(BFD_RELOC_NS32K_DISP_8_PCREL, 9);
 
261
      ENTRY(BFD_RELOC_NS32K_DISP_16_PCREL, 10);
 
262
      ENTRY(BFD_RELOC_NS32K_DISP_32_PCREL, 11);
 
263
      ENTRY(BFD_RELOC_8, 12);
 
264
      ENTRY(BFD_RELOC_16, 13);
 
265
      ENTRY(BFD_RELOC_32, 14);
 
266
      ENTRY(BFD_RELOC_8_PCREL, 15);
 
267
      ENTRY(BFD_RELOC_16_PCREL, 16);
 
268
      ENTRY(BFD_RELOC_32_PCREL, 17);
 
269
    default:
 
270
      return (reloc_howto_type *) NULL;
 
271
    }
 
272
#undef ENTRY
 
273
}
 
274
 
 
275
static void
 
276
MY_swap_std_reloc_in (abfd, bytes, cache_ptr, symbols, symcount)
 
277
     bfd *abfd;
 
278
     struct reloc_std_external *bytes;
 
279
     arelent *cache_ptr;
 
280
     asymbol **symbols;
 
281
     bfd_size_type symcount ATTRIBUTE_UNUSED;
 
282
{
 
283
  int r_index;
 
284
  int r_extern;
 
285
  int r_pcrel;
 
286
  struct aoutdata  *su = &(abfd->tdata.aout_data->a);
 
287
 
 
288
  cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
 
289
 
 
290
  /* Now the fun stuff.  */
 
291
  cache_ptr->howto = MY_reloc_howto(abfd, bytes, r_index, r_extern, r_pcrel);
 
292
 
 
293
  MOVE_ADDRESS (0);
 
294
}
 
295
 
 
296
static void
 
297
MY_swap_std_reloc_out (abfd, g, natptr)
 
298
     bfd *abfd;
 
299
     arelent *g;
 
300
     struct reloc_std_external *natptr;
 
301
{
 
302
  int r_index;
 
303
  asymbol *sym = *(g->sym_ptr_ptr);
 
304
  int r_extern;
 
305
  unsigned int r_addend;
 
306
  asection *output_section = sym->section->output_section;
 
307
 
 
308
  r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
 
309
 
 
310
  /* Name was clobbered by aout_write_syms to be symbol index.  */
 
311
 
 
312
  /* If this relocation is relative to a symbol then set the
 
313
     r_index to the symbols index, and the r_extern bit.
 
314
 
 
315
     Absolute symbols can come in in two ways, either as an offset
 
316
     from the abs section, or as a symbol which has an abs value.
 
317
     Check for that here.  */
 
318
  if (bfd_is_com_section (output_section)
 
319
      || output_section == &bfd_abs_section
 
320
      || output_section == &bfd_und_section)
 
321
    {
 
322
      if (bfd_abs_section.symbol == sym)
 
323
        {
 
324
          /* Whoops, looked like an abs symbol, but is really an offset
 
325
             from the abs section.  */
 
326
          r_index = 0;
 
327
          r_extern = 0;
 
328
        }
 
329
      else
 
330
        {
 
331
          /* Fill in symbol.  */
 
332
          r_extern = 1;
 
333
#undef KEEPIT
 
334
#define KEEPIT udata.i
 
335
          r_index =  (*(g->sym_ptr_ptr))->KEEPIT;
 
336
#undef KEEPIT
 
337
        }
 
338
    }
 
339
  else
 
340
    {
 
341
      /* Just an ordinary section.  */
 
342
      r_extern = 0;
 
343
      r_index  = output_section->target_index;
 
344
    }
 
345
 
 
346
  MY_put_reloc (abfd, r_extern, r_index, g->address, g->howto, natptr);
 
347
}
 
348
 
 
349
bfd_reloc_status_type
 
350
_bfd_ns32k_relocate_contents (howto, input_bfd, relocation, location)
 
351
     reloc_howto_type *howto;
 
352
     bfd *input_bfd;
 
353
     bfd_vma relocation;
 
354
     bfd_byte *location;
 
355
{
 
356
  int r_ns32k_type = (howto - MY(howto_table)) / 6;
 
357
  bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
 
358
  int (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
 
359
 
 
360
  switch (r_ns32k_type)
 
361
    {
 
362
    case 0:
 
363
      get_data = _bfd_ns32k_get_immediate;
 
364
      put_data = _bfd_ns32k_put_immediate;
 
365
      break;
 
366
    case 1:
 
367
      get_data = _bfd_ns32k_get_displacement;
 
368
      put_data = _bfd_ns32k_put_displacement;
 
369
      break;
 
370
    case 2:
 
371
      return _bfd_relocate_contents (howto, input_bfd, relocation,
 
372
                                    location);
 
373
      /* NOT REACHED */
 
374
      break;
 
375
    default:
 
376
      return bfd_reloc_notsupported;
 
377
    }
 
378
  return _bfd_do_ns32k_reloc_contents (howto, input_bfd, relocation,
 
379
                                       location, get_data, put_data);
 
380
}