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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [mipsbsd.c] - Blame information for rev 78

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

Line No. Rev Author Line
1 14 khays
/* BFD backend for MIPS BSD (a.out) binaries.
2
   Copyright 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3
   2005, 2007, 2009 Free Software Foundation, Inc.
4
   Written by Ralph Campbell.
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
 
24
/* #define ENTRY_CAN_BE_ZERO */
25
#define N_HEADER_IN_TEXT(x) 1
26
#define N_TXTADDR(x) \
27
    (N_MAGIC(x) != ZMAGIC ? (x).a_entry :       /* object file or NMAGIC */\
28
            TEXT_START_ADDR + EXEC_BYTES_SIZE   /* no padding */\
29
    )
30
#define N_DATADDR(x) (N_TXTADDR(x)+N_TXTSIZE(x))
31
#define TEXT_START_ADDR 4096
32
#define TARGET_PAGE_SIZE 4096
33
#define SEGMENT_SIZE TARGET_PAGE_SIZE
34
#define DEFAULT_ARCH bfd_arch_mips
35
#define MACHTYPE_OK(mtype) ((mtype) == M_UNKNOWN \
36
                            || (mtype) == M_MIPS1 || (mtype) == M_MIPS2)
37
#define MY_symbol_leading_char '\0'
38
 
39
/* Do not "beautify" the CONCAT* macro args.  Traditional C will not
40
   remove whitespace added here, and thus will fail to concatenate
41
   the tokens.  */
42
#define MY(OP) CONCAT2 (mipsbsd_,OP)
43
 
44
#include "sysdep.h"
45
#include "bfd.h"
46
#include "libbfd.h"
47
#include "libaout.h"
48
 
49
#define SET_ARCH_MACH(ABFD, EXEC) \
50
  MY(set_arch_mach) (ABFD, N_MACHTYPE (EXEC)); \
51
  MY(choose_reloc_size) (ABFD);
52
static void MY(set_arch_mach) PARAMS ((bfd *abfd, unsigned long machtype));
53
static void MY(choose_reloc_size) PARAMS ((bfd *abfd));
54
 
55
#define MY_write_object_contents MY(write_object_contents)
56
static bfd_boolean MY(write_object_contents) PARAMS ((bfd *abfd));
57
 
58
/* We can't use MY(x) here because it leads to a recursive call to CONCAT2
59
   when expanded inside JUMP_TABLE.  */
60
#define MY_bfd_reloc_type_lookup mipsbsd_reloc_type_lookup
61
#define MY_bfd_reloc_name_lookup mipsbsd_reloc_name_lookup
62
#define MY_canonicalize_reloc mipsbsd_canonicalize_reloc
63
 
64
#define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
65
#define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
66
#define MY_final_link_callback unused
67
#define MY_bfd_final_link _bfd_generic_final_link
68
 
69
#define MY_backend_data &MY(backend_data)
70
#define MY_BFD_TARGET
71
 
72
#include "aout-target.h"
73
 
74
static bfd_reloc_status_type mips_fix_jmp_addr
75
  PARAMS ((bfd *, arelent *, struct bfd_symbol *, PTR, asection *,
76
           bfd *, char **));
77
 
78
long MY(canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
79
 
80
static void
81
MY(set_arch_mach) (abfd, machtype)
82
     bfd *abfd;
83
     unsigned long machtype;
84
{
85
  enum bfd_architecture arch;
86
  unsigned int machine;
87
 
88
  /* Determine the architecture and machine type of the object file.  */
89
  switch (machtype)
90
    {
91
    case M_MIPS1:
92
      arch = bfd_arch_mips;
93
      machine = bfd_mach_mips3000;
94
      break;
95
 
96
    case M_MIPS2:
97
      arch = bfd_arch_mips;
98
      machine = bfd_mach_mips4000;
99
      break;
100
 
101
    default:
102
      arch = bfd_arch_obscure;
103
      machine = 0;
104
      break;
105
    }
106
 
107
  bfd_set_arch_mach (abfd, arch, machine);
108
}
109
 
110
/* Determine the size of a relocation entry, based on the architecture */
111
static void
112
MY (choose_reloc_size) (abfd)
113
     bfd *abfd;
114
{
115
  switch (bfd_get_arch (abfd))
116
    {
117
    case bfd_arch_sparc:
118
    case bfd_arch_mips:
119
      obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
120
      break;
121
    default:
122
      obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
123
      break;
124
    }
125
}
126
 
127
/* Write an object file in BSD a.out format.
128
  Section contents have already been written.  We write the
129
  file header, symbols, and relocation.  */
130
 
131
static bfd_boolean
132
MY (write_object_contents) (abfd)
133
     bfd *abfd;
134
{
135
  struct external_exec exec_bytes;
136
  struct internal_exec *execp = exec_hdr (abfd);
137
 
138
  /* Magic number, maestro, please!  */
139
  switch (bfd_get_arch (abfd))
140
    {
141
    case bfd_arch_m68k:
142
      switch (bfd_get_mach (abfd))
143
        {
144
        case bfd_mach_m68010:
145
          N_SET_MACHTYPE (*execp, M_68010);
146
          break;
147
        default:
148
        case bfd_mach_m68020:
149
          N_SET_MACHTYPE (*execp, M_68020);
150
          break;
151
        }
152
      break;
153
    case bfd_arch_sparc:
154
      N_SET_MACHTYPE (*execp, M_SPARC);
155
      break;
156
    case bfd_arch_i386:
157
      N_SET_MACHTYPE (*execp, M_386);
158
      break;
159
    case bfd_arch_mips:
160
      switch (bfd_get_mach (abfd))
161
        {
162
        case bfd_mach_mips4000:
163
        case bfd_mach_mips6000:
164
          N_SET_MACHTYPE (*execp, M_MIPS2);
165
          break;
166
        default:
167
          N_SET_MACHTYPE (*execp, M_MIPS1);
168
          break;
169
        }
170
      break;
171
    default:
172
      N_SET_MACHTYPE (*execp, M_UNKNOWN);
173
    }
174
 
175
  MY (choose_reloc_size) (abfd);
176
 
177
  WRITE_HEADERS (abfd, execp);
178
 
179
  return TRUE;
180
}
181
 
182
/* MIPS relocation types.  */
183
#define MIPS_RELOC_32           0
184
#define MIPS_RELOC_JMP          1
185
#define MIPS_RELOC_WDISP16      2
186
#define MIPS_RELOC_HI16         3
187
#define MIPS_RELOC_HI16_S       4
188
#define MIPS_RELOC_LO16         5
189
 
190
/* This is only called when performing a BFD_RELOC_MIPS_JMP relocation.
191
   The jump destination address is formed from the upper 4 bits of the
192
   "current" program counter concatenated with the jump instruction's
193
   26 bit field and two trailing zeros.
194
   If the destination address is not in the same segment as the "current"
195
   program counter, then we need to signal an error.  */
196
 
197
static bfd_reloc_status_type
198
mips_fix_jmp_addr (abfd, reloc_entry, symbol, data, input_section, output_bfd,
199
                   error_message)
200
     bfd *abfd ATTRIBUTE_UNUSED;
201
     arelent *reloc_entry;
202
     struct bfd_symbol *symbol;
203
     PTR data ATTRIBUTE_UNUSED;
204
     asection *input_section;
205
     bfd *output_bfd;
206
     char **error_message ATTRIBUTE_UNUSED;
207
{
208
  bfd_vma relocation, pc;
209
 
210
  /* If this is a partial relocation, just continue.  */
211
  if (output_bfd != (bfd *)NULL)
212
    return bfd_reloc_continue;
213
 
214
  /* If this is an undefined symbol, return error */
215
  if (bfd_is_und_section (symbol->section)
216
      && (symbol->flags & BSF_WEAK) == 0)
217
    return bfd_reloc_undefined;
218
 
219
  /* Work out which section the relocation is targeted at and the
220
     initial relocation command value.  */
221
  if (bfd_is_com_section (symbol->section))
222
    relocation = 0;
223
  else
224
    relocation = symbol->value;
225
 
226
  relocation += symbol->section->output_section->vma;
227
  relocation += symbol->section->output_offset;
228
  relocation += reloc_entry->addend;
229
 
230
  pc = input_section->output_section->vma + input_section->output_offset +
231
    reloc_entry->address + 4;
232
 
233
  if ((relocation & 0xF0000000) != (pc & 0xF0000000))
234
    return bfd_reloc_overflow;
235
 
236
  return bfd_reloc_continue;
237
}
238
 
239
/* This is only called when performing a BFD_RELOC_HI16_S relocation.
240
   We need to see if bit 15 is set in the result. If it is, we add
241
   0x10000 and continue normally. This will compensate for the sign extension
242
   when the low bits are added at run time.  */
243
 
244
static bfd_reloc_status_type
245
mips_fix_hi16_s PARAMS ((bfd *, arelent *, asymbol *, PTR,
246
                         asection *, bfd *, char **));
247
 
248
static bfd_reloc_status_type
249
mips_fix_hi16_s (abfd, reloc_entry, symbol, data, input_section,
250
                 output_bfd, error_message)
251
     bfd *abfd ATTRIBUTE_UNUSED;
252
     arelent *reloc_entry;
253
     asymbol *symbol;
254
     PTR data ATTRIBUTE_UNUSED;
255
     asection *input_section ATTRIBUTE_UNUSED;
256
     bfd *output_bfd;
257
     char **error_message ATTRIBUTE_UNUSED;
258
{
259
  bfd_vma relocation;
260
 
261
  /* If this is a partial relocation, just continue.  */
262
  if (output_bfd != (bfd *)NULL)
263
    return bfd_reloc_continue;
264
 
265
  /* If this is an undefined symbol, return error.  */
266
  if (bfd_is_und_section (symbol->section)
267
      && (symbol->flags & BSF_WEAK) == 0)
268
    return bfd_reloc_undefined;
269
 
270
  /* Work out which section the relocation is targeted at and the
271
     initial relocation command value.  */
272
  if (bfd_is_com_section (symbol->section))
273
    relocation = 0;
274
  else
275
    relocation = symbol->value;
276
 
277
  relocation += symbol->section->output_section->vma;
278
  relocation += symbol->section->output_offset;
279
  relocation += reloc_entry->addend;
280
 
281
  if (relocation & 0x8000)
282
    reloc_entry->addend += 0x10000;
283
 
284
  return bfd_reloc_continue;
285
}
286
 
287
static reloc_howto_type mips_howto_table_ext[] = {
288
  {MIPS_RELOC_32,      0, 2, 32, FALSE, 0,  complain_overflow_bitfield, 0,
289
        "32",       FALSE, 0, 0xffffffff, FALSE},
290
  {MIPS_RELOC_JMP,     2, 2, 26, FALSE, 0, complain_overflow_dont,
291
        mips_fix_jmp_addr,
292
        "MIPS_JMP", FALSE, 0, 0x03ffffff, FALSE},
293
  {MIPS_RELOC_WDISP16, 2, 2, 16, TRUE,  0, complain_overflow_signed, 0,
294
        "WDISP16",  FALSE, 0, 0x0000ffff, FALSE},
295
  {MIPS_RELOC_HI16,   16, 2, 16, FALSE, 0, complain_overflow_bitfield, 0,
296
        "HI16",     FALSE, 0, 0x0000ffff, FALSE},
297
  {MIPS_RELOC_HI16_S, 16, 2, 16, FALSE, 0, complain_overflow_bitfield,
298
        mips_fix_hi16_s,
299
        "HI16_S",   FALSE, 0, 0x0000ffff, FALSE},
300
  {MIPS_RELOC_LO16,    0, 2, 16, FALSE, 0, complain_overflow_dont, 0,
301
        "LO16",     FALSE, 0, 0x0000ffff, FALSE},
302
};
303
 
304
static reloc_howto_type *
305
MY(reloc_type_lookup) (bfd *abfd, bfd_reloc_code_real_type code)
306
{
307
 
308
  if (bfd_get_arch (abfd) != bfd_arch_mips)
309
    return 0;
310
 
311
  switch (code)
312
    {
313
    case BFD_RELOC_CTOR:
314
    case BFD_RELOC_32:
315
      return (&mips_howto_table_ext[MIPS_RELOC_32]);
316
    case BFD_RELOC_MIPS_JMP:
317
      return (&mips_howto_table_ext[MIPS_RELOC_JMP]);
318
    case BFD_RELOC_16_PCREL_S2:
319
      return (&mips_howto_table_ext[MIPS_RELOC_WDISP16]);
320
    case BFD_RELOC_HI16:
321
      return (&mips_howto_table_ext[MIPS_RELOC_HI16]);
322
    case BFD_RELOC_HI16_S:
323
      return (&mips_howto_table_ext[MIPS_RELOC_HI16_S]);
324
    case BFD_RELOC_LO16:
325
      return (&mips_howto_table_ext[MIPS_RELOC_LO16]);
326
    default:
327
      return 0;
328
    }
329
}
330
 
331
static reloc_howto_type *
332
MY(reloc_name_lookup) (bfd *abfd ATTRIBUTE_UNUSED,
333
                             const char *r_name)
334
{
335
  unsigned int i;
336
 
337
  for (i = 0;
338
       i < sizeof (mips_howto_table_ext) / sizeof (mips_howto_table_ext[0]);
339
       i++)
340
    if (mips_howto_table_ext[i].name != NULL
341
        && strcasecmp (mips_howto_table_ext[i].name, r_name) == 0)
342
      return &mips_howto_table_ext[i];
343
 
344
  return NULL;
345
}
346
 
347
/* This is just like the standard aoutx.h version but we need to do our
348
   own mapping of external reloc type values to howto entries.  */
349
long
350
MY(canonicalize_reloc) (abfd, section, relptr, symbols)
351
      bfd *abfd;
352
      sec_ptr section;
353
      arelent **relptr;
354
      asymbol **symbols;
355
{
356
  arelent *tblptr = section->relocation;
357
  unsigned int count, c;
358
  extern reloc_howto_type NAME(aout,ext_howto_table)[];
359
 
360
  /* If we have already read in the relocation table, return the values.  */
361
  if (section->flags & SEC_CONSTRUCTOR)
362
    {
363
      arelent_chain *chain = section->constructor_chain;
364
 
365
      for (count = 0; count < section->reloc_count; count++)
366
        {
367
          *relptr++ = &chain->relent;
368
          chain = chain->next;
369
        }
370
      *relptr = 0;
371
      return section->reloc_count;
372
    }
373
 
374
  if (tblptr && section->reloc_count)
375
    {
376
      for (count = 0; count++ < section->reloc_count;)
377
        *relptr++ = tblptr++;
378
      *relptr = 0;
379
      return section->reloc_count;
380
    }
381
 
382
  if (!NAME(aout,slurp_reloc_table) (abfd, section, symbols))
383
    return -1;
384
  tblptr = section->relocation;
385
 
386
  /* fix up howto entries.  */
387
  for (count = 0; count++ < section->reloc_count;)
388
    {
389
      c = tblptr->howto - NAME(aout,ext_howto_table);
390
      tblptr->howto = &mips_howto_table_ext[c];
391
 
392
      *relptr++ = tblptr++;
393
    }
394
  *relptr = 0;
395
  return section->reloc_count;
396
}
397
 
398
static const struct aout_backend_data MY(backend_data) = {
399
  0,                             /* zmagic contiguous */
400
  1,                            /* text incl header */
401
  0,                             /* entry is text address */
402
  0,                             /* exec_hdr_flags */
403
  TARGET_PAGE_SIZE,                     /* text vma */
404
  MY_set_sizes,
405
  0,                             /* text size includes exec header */
406
  0,                             /* add_dynamic_symbols */
407
  0,                             /* add_one_symbol */
408
  0,                             /* link_dynamic_object */
409
  0,                             /* write_dynamic_symbol */
410
  0,                             /* check_dynamic_reloc */
411
 
412
};
413
 
414
extern const bfd_target aout_mips_big_vec;
415
 
416
const bfd_target aout_mips_little_vec =
417
  {
418
    "a.out-mips-little",                /* name */
419
    bfd_target_aout_flavour,
420
    BFD_ENDIAN_LITTLE,          /* target byte order (little) */
421
    BFD_ENDIAN_LITTLE,          /* target headers byte order (little) */
422
    (HAS_RELOC | EXEC_P |               /* object flags */
423
     HAS_LINENO | HAS_DEBUG |
424
     HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
425
    (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
426
    MY_symbol_leading_char,
427
    ' ',                                /* ar_pad_char */
428
    15,                         /* ar_max_namelen */
429
    bfd_getl64, bfd_getl_signed_64, bfd_putl64,
430
    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
431
    bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
432
    bfd_getl64, bfd_getl_signed_64, bfd_putl64,
433
    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
434
    bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
435
    {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
436
     bfd_generic_archive_p, MY_core_file_p},
437
    {bfd_false, MY_mkobject,    /* bfd_set_format */
438
     _bfd_generic_mkarchive, bfd_false},
439
    {bfd_false, MY_write_object_contents, /* bfd_write_contents */
440
     _bfd_write_archive_contents, bfd_false},
441
 
442
    BFD_JUMP_TABLE_GENERIC (MY),
443
    BFD_JUMP_TABLE_COPY (MY),
444
    BFD_JUMP_TABLE_CORE (MY),
445
    BFD_JUMP_TABLE_ARCHIVE (MY),
446
    BFD_JUMP_TABLE_SYMBOLS (MY),
447
    BFD_JUMP_TABLE_RELOCS (MY),
448
    BFD_JUMP_TABLE_WRITE (MY),
449
    BFD_JUMP_TABLE_LINK (MY),
450
    BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
451
 
452
    & aout_mips_big_vec,
453
 
454
    (PTR) MY_backend_data
455
  };
456
 
457
const bfd_target aout_mips_big_vec =
458
  {
459
    "a.out-mips-big",           /* name */
460
    bfd_target_aout_flavour,
461
    BFD_ENDIAN_BIG,             /* target byte order (big) */
462
    BFD_ENDIAN_BIG,             /* target headers byte order (big) */
463
    (HAS_RELOC | EXEC_P |               /* object flags */
464
     HAS_LINENO | HAS_DEBUG |
465
     HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
466
    (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
467
    MY_symbol_leading_char,
468
    ' ',                                /* ar_pad_char */
469
    15,                         /* ar_max_namelen */
470
    bfd_getb64, bfd_getb_signed_64, bfd_putb64,
471
    bfd_getb32, bfd_getb_signed_32, bfd_putb32,
472
    bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
473
    bfd_getb64, bfd_getb_signed_64, bfd_putb64,
474
    bfd_getb32, bfd_getb_signed_32, bfd_putb32,
475
    bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
476
    {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
477
     bfd_generic_archive_p, MY_core_file_p},
478
    {bfd_false, MY_mkobject,    /* bfd_set_format */
479
     _bfd_generic_mkarchive, bfd_false},
480
    {bfd_false, MY_write_object_contents, /* bfd_write_contents */
481
     _bfd_write_archive_contents, bfd_false},
482
 
483
    BFD_JUMP_TABLE_GENERIC (MY),
484
    BFD_JUMP_TABLE_COPY (MY),
485
    BFD_JUMP_TABLE_CORE (MY),
486
    BFD_JUMP_TABLE_ARCHIVE (MY),
487
    BFD_JUMP_TABLE_SYMBOLS (MY),
488
    BFD_JUMP_TABLE_RELOCS (MY),
489
    BFD_JUMP_TABLE_WRITE (MY),
490
    BFD_JUMP_TABLE_LINK (MY),
491
    BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
492
 
493
    & aout_mips_little_vec,
494
 
495
    (PTR) MY_backend_data
496
  };

powered by: WebSVN 2.1.0

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