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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [oasys.c] - Blame information for rev 287

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

Line No. Rev Author Line
1 14 khays
/* BFD back-end for oasys objects.
2
   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001,
3 148 khays
   2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011
4 14 khays
   Free Software Foundation, Inc.
5
   Written by Steve Chamberlain of Cygnus Support, <sac@cygnus.com>.
6
 
7
   This file is part of BFD, the Binary File Descriptor library.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22
   MA 02110-1301, USA.  */
23
 
24
#define UNDERSCORE_HACK 1
25
#include "sysdep.h"
26
#include "bfd.h"
27
#include "safe-ctype.h"
28
#include "libbfd.h"
29
#include "oasys.h"
30
#include "liboasys.h"
31
 
32
/* Read in all the section data and relocation stuff too.  */
33
 
34
static bfd_boolean
35
oasys_read_record (bfd *abfd, oasys_record_union_type *record)
36
{
37
  bfd_size_type amt = sizeof (record->header);
38
 
39
  if (bfd_bread ((void *) record, amt, abfd) != amt)
40
    return FALSE;
41
 
42
  amt = record->header.length - sizeof (record->header);
43
  if ((long) amt <= 0)
44
    return TRUE;
45
  if (bfd_bread ((void *) ((char *) record + sizeof (record->header)), amt, abfd)
46
      != amt)
47
    return FALSE;
48
  return TRUE;
49
}
50
 
51
static size_t
52
oasys_string_length (oasys_record_union_type *record)
53
{
54
  return record->header.length
55
    - ((char *) record->symbol.name - (char *) record);
56
}
57
 
58
/* Slurp the symbol table by reading in all the records at the start file
59
   till we get to the first section record.
60
 
61
   We'll sort the symbolss into  two lists, defined and undefined. The
62
   undefined symbols will be placed into the table according to their
63
   refno.
64
 
65
   We do this by placing all undefined symbols at the front of the table
66
   moving in, and the defined symbols at the end of the table moving back.  */
67
 
68
static bfd_boolean
69
oasys_slurp_symbol_table (bfd *const abfd)
70
{
71
  oasys_record_union_type record;
72
  oasys_data_type *data = OASYS_DATA (abfd);
73
  bfd_boolean loop = TRUE;
74
  asymbol *dest_defined;
75
  asymbol *dest;
76
  char *string_ptr;
77
  bfd_size_type amt;
78
 
79
  if (data->symbols != NULL)
80
    return TRUE;
81
 
82
  /* Buy enough memory for all the symbols and all the names.  */
83
  amt = abfd->symcount;
84
  amt *= sizeof (asymbol);
85
  data->symbols = bfd_alloc (abfd, amt);
86
 
87
  amt = data->symbol_string_length;
88
#ifdef UNDERSCORE_HACK
89
  /* Buy 1 more char for each symbol to keep the underscore in.  */
90
  amt += abfd->symcount;
91
#endif
92
  data->strings = bfd_alloc (abfd, amt);
93
 
94
  if (!data->symbols || !data->strings)
95
    return FALSE;
96
 
97
  dest_defined = data->symbols + abfd->symcount - 1;
98
 
99
  string_ptr = data->strings;
100
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
101
    return FALSE;
102
  while (loop)
103
    {
104
      if (! oasys_read_record (abfd, &record))
105
        return FALSE;
106
 
107
      switch (record.header.type)
108
        {
109
        case oasys_record_is_header_enum:
110
          break;
111
        case oasys_record_is_local_enum:
112
        case oasys_record_is_symbol_enum:
113
          {
114
            int flag = record.header.type == (int) oasys_record_is_local_enum ?
115
            (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT);
116
 
117
            size_t length = oasys_string_length (&record);
118
            switch (record.symbol.relb & RELOCATION_TYPE_BITS)
119
              {
120
              case RELOCATION_TYPE_ABS:
121
                dest = dest_defined--;
122
                dest->section = bfd_abs_section_ptr;
123
                dest->flags = 0;
124
 
125
                break;
126
              case RELOCATION_TYPE_REL:
127
                dest = dest_defined--;
128
                dest->section =
129
                  OASYS_DATA (abfd)->sections[record.symbol.relb &
130
                                              RELOCATION_SECT_BITS];
131
                if (record.header.type == (int) oasys_record_is_local_enum)
132
                  {
133
                    dest->flags = BSF_LOCAL;
134
                    if (dest->section == (asection *) (~0))
135
                      {
136
                        /* It seems that sometimes internal symbols are tied up, but
137
                       still get output, even though there is no
138
                       section */
139
                        dest->section = 0;
140
                      }
141
                  }
142
                else
143
                  dest->flags = flag;
144
                break;
145
              case RELOCATION_TYPE_UND:
146
                dest = data->symbols + H_GET_16 (abfd, record.symbol.refno);
147
                dest->section = bfd_und_section_ptr;
148
                break;
149
              case RELOCATION_TYPE_COM:
150
                dest = dest_defined--;
151
                dest->name = string_ptr;
152
                dest->the_bfd = abfd;
153
                dest->section = bfd_com_section_ptr;
154
                break;
155
              default:
156
                dest = dest_defined--;
157
                BFD_ASSERT (FALSE);
158
                break;
159
              }
160
            dest->name = string_ptr;
161
            dest->the_bfd = abfd;
162
            dest->udata.p = NULL;
163
            dest->value = H_GET_32 (abfd, record.symbol.value);
164
 
165
#ifdef UNDERSCORE_HACK
166
            if (record.symbol.name[0] != '_')
167
              {
168
                string_ptr[0] = '_';
169
                string_ptr++;
170
              }
171
#endif
172
            memcpy (string_ptr, record.symbol.name, length);
173
 
174
            string_ptr[length] = 0;
175
            string_ptr += length + 1;
176
          }
177
          break;
178
        default:
179
          loop = FALSE;
180
        }
181
    }
182
  return TRUE;
183
}
184
 
185
static long
186
oasys_get_symtab_upper_bound (bfd *const abfd)
187
{
188
  if (! oasys_slurp_symbol_table (abfd))
189
    return -1;
190
 
191
  return (abfd->symcount + 1) * (sizeof (oasys_symbol_type *));
192
}
193
 
194
extern const bfd_target oasys_vec;
195
 
196
static long
197
oasys_canonicalize_symtab (bfd *abfd, asymbol **location)
198
{
199
  asymbol *symbase;
200
  unsigned int counter;
201
 
202
  if (! oasys_slurp_symbol_table (abfd))
203
    return -1;
204
 
205
  symbase = OASYS_DATA (abfd)->symbols;
206
  for (counter = 0; counter < abfd->symcount; counter++)
207
    *(location++) = symbase++;
208
 
209
  *location = 0;
210
  return abfd->symcount;
211
}
212
 
213
/* Archive stuff.  */
214
 
215
static const bfd_target *
216
oasys_archive_p (bfd *abfd)
217
{
218
  oasys_archive_header_type header;
219
  oasys_extarchive_header_type header_ext;
220
  unsigned int i;
221
  file_ptr filepos;
222
  bfd_size_type amt;
223
 
224
  amt = sizeof (header_ext);
225
  if (bfd_seek (abfd, (file_ptr) 0, 0) != 0
226
      || bfd_bread ((void *) &header_ext, amt, abfd) != amt)
227
    {
228
      if (bfd_get_error () != bfd_error_system_call)
229
        bfd_set_error (bfd_error_wrong_format);
230
      return NULL;
231
    }
232
 
233
  header.version = H_GET_32 (abfd, header_ext.version);
234
  header.mod_count = H_GET_32 (abfd, header_ext.mod_count);
235
  header.mod_tbl_offset = H_GET_32 (abfd, header_ext.mod_tbl_offset);
236
  header.sym_tbl_size = H_GET_32 (abfd, header_ext.sym_tbl_size);
237
  header.sym_count = H_GET_32 (abfd, header_ext.sym_count);
238
  header.sym_tbl_offset = H_GET_32 (abfd, header_ext.sym_tbl_offset);
239
  header.xref_count = H_GET_32 (abfd, header_ext.xref_count);
240
  header.xref_lst_offset = H_GET_32 (abfd, header_ext.xref_lst_offset);
241
 
242
  /* There isn't a magic number in an Oasys archive, so the best we
243
     can do to verify reasonableness is to make sure that the values in
244
     the header are too weird.  */
245
 
246
  if (header.version > 10000
247
      || header.mod_count > 10000
248
      || header.sym_count > 100000
249
      || header.xref_count > 100000)
250
    return NULL;
251
 
252
  /* That all worked, let's buy the space for the header and read in
253
     the headers.  */
254
  {
255
    oasys_ar_data_type *ar;
256
    oasys_module_info_type *module;
257
    oasys_module_table_type record;
258
 
259
    amt = sizeof (oasys_ar_data_type);
260
    ar = bfd_alloc (abfd, amt);
261
 
262
    amt = header.mod_count;
263
    amt *= sizeof (oasys_module_info_type);
264
    module = bfd_alloc (abfd, amt);
265
 
266
    if (!ar || !module)
267
      return NULL;
268
 
269
    abfd->tdata.oasys_ar_data = ar;
270
    ar->module = module;
271
    ar->module_count = header.mod_count;
272
 
273
    filepos = header.mod_tbl_offset;
274
    for (i = 0; i < header.mod_count; i++)
275
      {
276
        if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
277
          return NULL;
278
 
279
        /* There are two ways of specifying the archive header.  */
280
          {
281
            oasys_extmodule_table_type_b_type record_ext;
282
 
283
            amt = sizeof (record_ext);
284
            if (bfd_bread ((void *) &record_ext, amt, abfd) != amt)
285
              return NULL;
286
 
287
            record.mod_size = H_GET_32 (abfd, record_ext.mod_size);
288
            record.file_offset = H_GET_32 (abfd, record_ext.file_offset);
289
 
290
            record.dep_count = H_GET_32 (abfd, record_ext.dep_count);
291
            record.depee_count = H_GET_32 (abfd, record_ext.depee_count);
292
            record.sect_count = H_GET_32 (abfd, record_ext.sect_count);
293
            record.module_name_size = H_GET_32 (abfd,
294
                                                record_ext.mod_name_length);
295
 
296
            amt = record.module_name_size;
297
            module[i].name = bfd_alloc (abfd, amt + 1);
298
            if (!module[i].name)
299
              return NULL;
300
            if (bfd_bread ((void *) module[i].name, amt, abfd) != amt)
301
              return NULL;
302
            module[i].name[record.module_name_size] = 0;
303
            filepos += (sizeof (record_ext)
304
                        + record.dep_count * 4
305
                        + record.module_name_size + 1);
306
          }
307
 
308
        module[i].size = record.mod_size;
309
        module[i].pos = record.file_offset;
310
        module[i].abfd = 0;
311
      }
312
  }
313
  return abfd->xvec;
314
}
315
 
316
static bfd_boolean
317
oasys_mkobject (bfd *abfd)
318
{
319
  bfd_size_type amt = sizeof (oasys_data_type);
320
 
321
  abfd->tdata.oasys_obj_data = bfd_alloc (abfd, amt);
322
 
323
  return abfd->tdata.oasys_obj_data != NULL;
324
}
325
 
326
/* The howto table is build using the top two bits of a reloc byte to
327
   index into it. The bits are PCREL,WORD/LONG.  */
328
 
329
static reloc_howto_type howto_table[] =
330
{
331
 
332
  HOWTO (0, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16",   TRUE, 0x0000ffff, 0x0000ffff, FALSE),
333
  HOWTO (0, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs32",   TRUE, 0xffffffff, 0xffffffff, FALSE),
334
  HOWTO (0, 0, 1, 16, TRUE,  0, complain_overflow_signed,   0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
335
  HOWTO (0, 0, 2, 32, TRUE,  0, complain_overflow_signed,   0, "pcrel32", TRUE, 0xffffffff, 0xffffffff, FALSE)
336
};
337
 
338
/* Read in all the section data and relocation stuff too.  */
339
 
340
static bfd_boolean
341
oasys_slurp_section_data (bfd *const abfd)
342
{
343
  oasys_record_union_type record;
344
  oasys_data_type *data = OASYS_DATA (abfd);
345
  bfd_boolean loop = TRUE;
346
  oasys_per_section_type *per;
347
  asection *s;
348
  bfd_size_type amt;
349
 
350
  /* See if the data has been slurped already.  */
351
  for (s = abfd->sections; s != NULL; s = s->next)
352
    {
353
      per = oasys_per_section (s);
354
      if (per->initialized)
355
        return TRUE;
356
    }
357
 
358
  if (data->first_data_record == 0)
359
    return TRUE;
360
 
361
  if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0)
362
    return FALSE;
363
 
364
  while (loop)
365
    {
366
      if (! oasys_read_record (abfd, &record))
367
        return FALSE;
368
 
369
      switch (record.header.type)
370
        {
371
        case oasys_record_is_header_enum:
372
          break;
373
        case oasys_record_is_data_enum:
374
          {
375
            bfd_byte *src = record.data.data;
376
            bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length;
377
            bfd_byte *dst_ptr;
378
            bfd_byte *dst_base_ptr;
379
            unsigned int relbit;
380
            unsigned int count;
381
            asection *section =
382
            data->sections[record.data.relb & RELOCATION_SECT_BITS];
383
            bfd_vma dst_offset;
384
 
385
            per = oasys_per_section (section);
386
 
387
            if (! per->initialized)
388
              {
389
                arelent **relpp;
390
 
391
                per->data = bfd_zalloc (abfd, section->size);
392
                if (!per->data)
393
                  return FALSE;
394
                relpp = &section->relocation;
395
                per->reloc_tail_ptr = (oasys_reloc_type **) relpp;
396
                per->had_vma = FALSE;
397
                per->initialized = TRUE;
398
                section->reloc_count = 0;
399
                section->flags = SEC_ALLOC;
400
              }
401
 
402
            dst_offset = H_GET_32 (abfd, record.data.addr);
403
            if (! per->had_vma)
404
              {
405
                /* Take the first vma we see as the base.  */
406
                section->vma = dst_offset;
407
                per->had_vma = TRUE;
408
              }
409
 
410
            dst_offset -= section->vma;
411
 
412
            dst_base_ptr = oasys_per_section (section)->data;
413
            dst_ptr = oasys_per_section (section)->data +
414
              dst_offset;
415
 
416
            if (src < end_src)
417
              section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
418
 
419
            while (src < end_src)
420
              {
421
                unsigned char mod_byte = *src++;
422
                size_t gap = end_src - src;
423
 
424
                count = 8;
425
                if (mod_byte == 0 && gap >= 8)
426
                  {
427
                    dst_ptr[0] = src[0];
428
                    dst_ptr[1] = src[1];
429
                    dst_ptr[2] = src[2];
430
                    dst_ptr[3] = src[3];
431
                    dst_ptr[4] = src[4];
432
                    dst_ptr[5] = src[5];
433
                    dst_ptr[6] = src[6];
434
                    dst_ptr[7] = src[7];
435
                    dst_ptr += 8;
436
                    src += 8;
437
                  }
438
                else
439
                  {
440
                    for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
441
                      {
442
                        if (relbit & mod_byte)
443
                          {
444
                            unsigned char reloc = *src;
445
                            /* This item needs to be relocated.  */
446
                            switch (reloc & RELOCATION_TYPE_BITS)
447
                              {
448
                              case RELOCATION_TYPE_ABS:
449
                                break;
450
 
451
                              case RELOCATION_TYPE_REL:
452
                                {
453
                                  /* Relocate the item relative to the section.  */
454
                                  oasys_reloc_type *r;
455
 
456
                                  amt = sizeof (oasys_reloc_type);
457
                                  r = bfd_alloc (abfd, amt);
458
                                  if (!r)
459
                                    return FALSE;
460
                                  *(per->reloc_tail_ptr) = r;
461
                                  per->reloc_tail_ptr = &r->next;
462
                                  r->next = NULL;
463
                                  /* Reference to undefined symbol.  */
464
                                  src++;
465
                                  /* There is no symbol.  */
466
                                  r->symbol = 0;
467
                                  /* Work out the howto.  */
468
                                  abort ();
469
                                  r->relent.address = dst_ptr - dst_base_ptr;
470
                                  r->relent.howto = &howto_table[reloc >> 6];
471
                                  r->relent.sym_ptr_ptr = NULL;
472
                                  section->reloc_count++;
473
 
474
                                  /* Fake up the data to look like
475
                                     it's got the -ve pc in it, this
476
                                     makes it much easier to convert
477
                                     into other formats.  This is done
478
                                     by hitting the addend.  */
479
                                  if (r->relent.howto->pc_relative)
480
                                    r->relent.addend -= dst_ptr - dst_base_ptr;
481
                                }
482
                                break;
483
 
484
                              case RELOCATION_TYPE_UND:
485
                                {
486
                                  oasys_reloc_type *r;
487
 
488
                                  amt = sizeof (oasys_reloc_type);
489
                                  r = bfd_alloc (abfd, amt);
490
                                  if (!r)
491
                                    return FALSE;
492
                                  *(per->reloc_tail_ptr) = r;
493
                                  per->reloc_tail_ptr = &r->next;
494
                                  r->next = NULL;
495
                                  /* Reference to undefined symbol.  */
496
                                  src++;
497
                                  /* Get symbol number.  */
498
                                  r->symbol = (src[0] << 8) | src[1];
499
                                  /* Work out the howto.  */
500
                                  abort ();
501
 
502
                                  r->relent.addend = 0;
503
                                  r->relent.address = dst_ptr - dst_base_ptr;
504
                                  r->relent.howto = &howto_table[reloc >> 6];
505
                                  r->relent.sym_ptr_ptr = NULL;
506
                                  section->reloc_count++;
507
 
508
                                  src += 2;
509
                                  /* Fake up the data to look like
510
                                     it's got the -ve pc in it, this
511
                                     makes it much easier to convert
512
                                     into other formats.  This is done
513
                                     by hitting the addend.  */
514
                                  if (r->relent.howto->pc_relative)
515
                                    r->relent.addend -= dst_ptr - dst_base_ptr;
516
                                }
517
                                break;
518
                              case RELOCATION_TYPE_COM:
519
                                BFD_FAIL ();
520
                              }
521
                          }
522
                        *dst_ptr++ = *src++;
523
                      }
524
                  }
525
              }
526
          }
527
          break;
528
        case oasys_record_is_local_enum:
529
        case oasys_record_is_symbol_enum:
530
        case oasys_record_is_section_enum:
531
          break;
532
        default:
533
          loop = FALSE;
534
        }
535
    }
536
 
537
  return TRUE;
538
 
539
}
540
 
541
#define MAX_SECS 16
542
 
543
static const bfd_target *
544
oasys_object_p (bfd *abfd)
545
{
546
  oasys_data_type *oasys;
547
  oasys_data_type *save = OASYS_DATA (abfd);
548
  bfd_boolean loop = TRUE;
549
  bfd_boolean had_usefull = FALSE;
550
 
551
  abfd->tdata.oasys_obj_data = 0;
552
  oasys_mkobject (abfd);
553
  oasys = OASYS_DATA (abfd);
554
  memset ((void *) oasys->sections, 0xff, sizeof (oasys->sections));
555
 
556
  /* Point to the start of the file.  */
557
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
558
    goto fail;
559
  oasys->symbol_string_length = 0;
560
 
561
  /* Inspect the records, but only keep the section info -
562
     remember the size of the symbols.  */
563
  oasys->first_data_record = 0;
564
  while (loop)
565
    {
566
      oasys_record_union_type record;
567
      if (! oasys_read_record (abfd, &record))
568
        goto fail;
569
      if ((size_t) record.header.length < (size_t) sizeof (record.header))
570
        goto fail;
571
 
572
      switch ((oasys_record_enum_type) (record.header.type))
573
        {
574
        case oasys_record_is_header_enum:
575
          had_usefull = TRUE;
576
          break;
577
        case oasys_record_is_symbol_enum:
578
        case oasys_record_is_local_enum:
579
          /* Count symbols and remember their size for a future malloc.  */
580
          abfd->symcount++;
581
          oasys->symbol_string_length += 1 + oasys_string_length (&record);
582
          had_usefull = TRUE;
583
          break;
584
        case oasys_record_is_section_enum:
585
          {
586
            asection *s;
587
            char *buffer;
588
            unsigned int section_number;
589
 
590
            if (record.section.header.length != sizeof (record.section))
591
              goto fail;
592
 
593
            buffer = bfd_alloc (abfd, (bfd_size_type) 3);
594
            if (!buffer)
595
              goto fail;
596
            section_number = record.section.relb & RELOCATION_SECT_BITS;
597
            sprintf (buffer, "%u", section_number);
598
            s = bfd_make_section (abfd, buffer);
599
            oasys->sections[section_number] = s;
600
            switch (record.section.relb & RELOCATION_TYPE_BITS)
601
              {
602
              case RELOCATION_TYPE_ABS:
603
              case RELOCATION_TYPE_REL:
604
                break;
605
              case RELOCATION_TYPE_UND:
606
              case RELOCATION_TYPE_COM:
607
                BFD_FAIL ();
608
              }
609
 
610
            s->size = H_GET_32 (abfd, record.section.value);
611
            s->vma = H_GET_32 (abfd, record.section.vma);
612
            s->flags = 0;
613
            had_usefull = TRUE;
614
          }
615
          break;
616
        case oasys_record_is_data_enum:
617
          oasys->first_data_record = bfd_tell (abfd) - record.header.length;
618
        case oasys_record_is_debug_enum:
619
        case oasys_record_is_module_enum:
620
        case oasys_record_is_named_section_enum:
621
        case oasys_record_is_end_enum:
622
          if (! had_usefull)
623
            goto fail;
624
          loop = FALSE;
625
          break;
626
        default:
627
          goto fail;
628
        }
629
    }
630
  oasys->symbols = NULL;
631
 
632
  /* Oasys support several architectures, but I can't see a simple way
633
     to discover which one is in a particular file - we'll guess.  */
634
  bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
635
  if (abfd->symcount != 0)
636
    abfd->flags |= HAS_SYMS;
637
 
638
  /* We don't know if a section has data until we've read it.  */
639
  oasys_slurp_section_data (abfd);
640
 
641
  return abfd->xvec;
642
 
643
fail:
644
  (void) bfd_release (abfd, oasys);
645
  abfd->tdata.oasys_obj_data = save;
646
  return NULL;
647
}
648
 
649
 
650
static void
651
oasys_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
652
                       asymbol *symbol,
653
                       symbol_info *ret)
654
{
655
  bfd_symbol_info (symbol, ret);
656
 
657
  if (!symbol->section)
658
    ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
659
}
660
 
661
static void
662
oasys_print_symbol (bfd *abfd, void * afile, asymbol *symbol, bfd_print_symbol_type how)
663
{
664
  FILE *file = (FILE *) afile;
665
 
666
  switch (how)
667
    {
668
    case bfd_print_symbol_name:
669
    case bfd_print_symbol_more:
670
      fprintf (file, "%s", symbol->name);
671
      break;
672
    case bfd_print_symbol_all:
673
      {
674
        const char *section_name = symbol->section == NULL ?
675
        (const char *) "*abs" : symbol->section->name;
676
 
677
        bfd_print_symbol_vandf (abfd, (void *) file, symbol);
678
 
679
        fprintf (file, " %-5s %s",
680
                 section_name,
681
                 symbol->name);
682
      }
683
      break;
684
    }
685
}
686
 
687
static bfd_boolean
688
oasys_new_section_hook (bfd *abfd, asection *newsect)
689
{
690
  if (!newsect->used_by_bfd)
691
    {
692
      newsect->used_by_bfd
693
        = bfd_alloc (abfd, (bfd_size_type) sizeof (oasys_per_section_type));
694
      if (!newsect->used_by_bfd)
695
        return FALSE;
696
    }
697
  oasys_per_section (newsect)->data = NULL;
698
  oasys_per_section (newsect)->section = newsect;
699
  oasys_per_section (newsect)->offset = 0;
700
  oasys_per_section (newsect)->initialized = FALSE;
701
  newsect->alignment_power = 1;
702
 
703
  /* Turn the section string into an index.  */
704
  sscanf (newsect->name, "%u", &newsect->target_index);
705
 
706
  return _bfd_generic_new_section_hook (abfd, newsect);
707
}
708
 
709
 
710
static long
711
oasys_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
712
{
713
  if (! oasys_slurp_section_data (abfd))
714
    return -1;
715
  return (asect->reloc_count + 1) * sizeof (arelent *);
716
}
717
 
718
static bfd_boolean
719
oasys_get_section_contents (bfd *abfd,
720
                            sec_ptr section,
721
                            void * location,
722
                            file_ptr offset,
723
                            bfd_size_type count)
724
{
725
  oasys_per_section_type *p = oasys_per_section (section);
726
 
727
  oasys_slurp_section_data (abfd);
728
 
729
  if (! p->initialized)
730
    (void) memset (location, 0, (size_t) count);
731
  else
732
    (void) memcpy (location, (void *) (p->data + offset), (size_t) count);
733
 
734
  return TRUE;
735
}
736
 
737
static long
738
oasys_canonicalize_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
739
                          sec_ptr section,
740
                          arelent **relptr,
741
                          asymbol **symbols ATTRIBUTE_UNUSED)
742
{
743
  unsigned int reloc_count = 0;
744
  oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
745
 
746
  if (src != NULL)
747
    abort ();
748
 
749
  *relptr = NULL;
750
  return section->reloc_count = reloc_count;
751
}
752
 
753
 
754
/* Writing.  */
755
 
756
/* Calculate the checksum and write one record.  */
757
 
758
static bfd_boolean
759
oasys_write_record (bfd *abfd,
760
                    oasys_record_enum_type type,
761
                    oasys_record_union_type *record,
762
                    size_t size)
763
{
764
  int checksum;
765
  size_t i;
766
  unsigned char *ptr;
767
 
768
  record->header.length = size;
769
  record->header.type = (int) type;
770
  record->header.check_sum = 0;
771
  record->header.fill = 0;
772
  ptr = (unsigned char *) &record->pad[0];
773
  checksum = 0;
774
  for (i = 0; i < size; i++)
775
    checksum += *ptr++;
776
  record->header.check_sum = 0xff & (-checksum);
777
  if (bfd_bwrite ((void *) record, (bfd_size_type) size, abfd) != size)
778
    return FALSE;
779
  return TRUE;
780
}
781
 
782
 
783
/* Write out all the symbols.  */
784
 
785
static bfd_boolean
786
oasys_write_syms (bfd *abfd)
787
{
788
  unsigned int count;
789
  asymbol **generic = bfd_get_outsymbols (abfd);
790
  unsigned int sym_index = 0;
791
 
792
  for (count = 0; count < bfd_get_symcount (abfd); count++)
793
    {
794
      oasys_symbol_record_type symbol;
795
      asymbol *const g = generic[count];
796
      const char *src = g->name;
797
      char *dst = symbol.name;
798
      unsigned int l = 0;
799
 
800
      if (bfd_is_com_section (g->section))
801
        {
802
          symbol.relb = RELOCATION_TYPE_COM;
803
          H_PUT_16 (abfd, sym_index, symbol.refno);
804
          sym_index++;
805
        }
806
      else if (bfd_is_abs_section (g->section))
807
        {
808
          symbol.relb = RELOCATION_TYPE_ABS;
809
          H_PUT_16 (abfd, 0, symbol.refno);
810
        }
811
      else if (bfd_is_und_section (g->section))
812
        {
813
          symbol.relb = RELOCATION_TYPE_UND;
814
          H_PUT_16 (abfd, sym_index, symbol.refno);
815
          /* Overload the value field with the output sym_index number */
816
          sym_index++;
817
        }
818
      else if (g->flags & BSF_DEBUGGING)
819
        /* Throw it away.  */
820
        continue;
821
      else
822
        {
823
          if (g->section == NULL)
824
            /* Sometime, the oasys tools give out a symbol with illegal
825
               bits in it, we'll output it in the same broken way.  */
826
            symbol.relb = RELOCATION_TYPE_REL | 0;
827
          else
828
            symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
829
 
830
          H_PUT_16 (abfd, 0, symbol.refno);
831
        }
832
 
833
#ifdef UNDERSCORE_HACK
834
      if (src[l] == '_')
835
        dst[l++] = '.';
836
#endif
837
      while (src[l])
838
        {
839
          dst[l] = src[l];
840
          l++;
841
        }
842
 
843
      H_PUT_32 (abfd, g->value, symbol.value);
844
 
845
      if (g->flags & BSF_LOCAL)
846
        {
847
          if (! oasys_write_record (abfd,
848
                                    oasys_record_is_local_enum,
849
                                    (oasys_record_union_type *) & symbol,
850
                                    offsetof (oasys_symbol_record_type,
851
                                              name[0]) + l))
852
            return FALSE;
853
        }
854
      else
855
        {
856
          if (! oasys_write_record (abfd,
857
                                    oasys_record_is_symbol_enum,
858
                                    (oasys_record_union_type *) & symbol,
859
                                    offsetof (oasys_symbol_record_type,
860
                                              name[0]) + l))
861
            return FALSE;
862
        }
863
      g->value = sym_index - 1;
864
    }
865
 
866
  return TRUE;
867
}
868
 
869
/* Write a section header for each section.  */
870
 
871
static bfd_boolean
872
oasys_write_sections (bfd *abfd)
873
{
874
  asection *s;
875
  static oasys_section_record_type out;
876
 
877
  for (s = abfd->sections; s != NULL; s = s->next)
878
    {
879
      if (!ISDIGIT (s->name[0]))
880
        {
881
          (*_bfd_error_handler)
882
            (_("%s: can not represent section `%s' in oasys"),
883
             bfd_get_filename (abfd), s->name);
884
          bfd_set_error (bfd_error_nonrepresentable_section);
885
          return FALSE;
886
        }
887
      out.relb = RELOCATION_TYPE_REL | s->target_index;
888
      H_PUT_32 (abfd, s->size, out.value);
889
      H_PUT_32 (abfd, s->vma, out.vma);
890
 
891
      if (! oasys_write_record (abfd,
892
                                oasys_record_is_section_enum,
893
                                (oasys_record_union_type *) & out,
894
                                sizeof (out)))
895
        return FALSE;
896
    }
897
  return TRUE;
898
}
899
 
900
static bfd_boolean
901
oasys_write_header (bfd *abfd)
902
{
903
  /* Create and write the header.  */
904
  oasys_header_record_type r;
905
  size_t length = strlen (abfd->filename);
906
 
907
  if (length > (size_t) sizeof (r.module_name))
908
    length = sizeof (r.module_name);
909 166 khays
  else if (length < (size_t) sizeof (r.module_name))
910
    (void) memset (r.module_name + length, ' ',
911
                   sizeof (r.module_name) - length);
912 14 khays
 
913
  (void) memcpy (r.module_name, abfd->filename, length);
914
 
915
  r.version_number = OASYS_VERSION_NUMBER;
916
  r.rev_number = OASYS_REV_NUMBER;
917
 
918
  return oasys_write_record (abfd, oasys_record_is_header_enum,
919
                             (oasys_record_union_type *) & r,
920
                             offsetof (oasys_header_record_type,
921
                                       description[0]));
922
}
923
 
924
static bfd_boolean
925
oasys_write_end (bfd *abfd)
926
{
927
  oasys_end_record_type end;
928
  unsigned char null = 0;
929
 
930
  end.relb = RELOCATION_TYPE_ABS;
931
  H_PUT_32 (abfd, abfd->start_address, end.entry);
932
  H_PUT_16 (abfd, 0, end.fill);
933
  end.zero = 0;
934
  if (! oasys_write_record (abfd,
935
                            oasys_record_is_end_enum,
936
                            (oasys_record_union_type *) & end,
937
                            sizeof (end)))
938
    return FALSE;
939
 
940
  return bfd_bwrite ((void *) &null, (bfd_size_type) 1, abfd) == 1;
941
}
942
 
943
static int
944
comp (const void * ap, const void * bp)
945
{
946
  arelent *a = *((arelent **) ap);
947
  arelent *b = *((arelent **) bp);
948
 
949
  return a->address - b->address;
950
}
951
 
952
static bfd_boolean
953
oasys_write_data (bfd *abfd)
954
{
955
  asection *s;
956
 
957
  for (s = abfd->sections; s != NULL; s = s->next)
958
    {
959
      if (s->flags & SEC_LOAD)
960
        {
961
          bfd_byte *raw_data = oasys_per_section (s)->data;
962
          oasys_data_record_type processed_data;
963
          bfd_size_type current_byte_index = 0;
964
          unsigned int relocs_to_go = s->reloc_count;
965
          arelent **p = s->orelocation;
966
 
967
          if (s->reloc_count != 0)
968
            /* Sort the reloc records so it's easy to insert the relocs into the
969
               data.  */
970
            qsort (s->orelocation, s->reloc_count, sizeof (arelent **), comp);
971
 
972
          current_byte_index = 0;
973
          processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
974
 
975
          while (current_byte_index < s->size)
976
            {
977
              /* Scan forwards by eight bytes or however much is left and see if
978
               there are any relocations going on.  */
979
              bfd_byte *mod = &processed_data.data[0];
980
              bfd_byte *dst = &processed_data.data[1];
981
 
982
              unsigned int i = 0;
983
              *mod = 0;
984
 
985
              H_PUT_32 (abfd, s->vma + current_byte_index,
986
                        processed_data.addr);
987
 
988
              /* Don't start a relocation unless you're sure you can finish it
989
                 within the same data record.  The worst case relocation is a
990
                 4-byte relocatable value which is split across two modification
991
                 bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
992
                 1 modification byte + 2 data = 8 bytes total).  That's where
993
                 the magic number 8 comes from.  */
994
              while (current_byte_index < s->size && dst <=
995
                     & processed_data.data[sizeof (processed_data.data) - 8])
996
                {
997
                  if (relocs_to_go != 0)
998
                    {
999
                      arelent *r = *p;
1000
 
1001
                      /* There is a relocation, is it for this byte ?  */
1002
                      if (r->address == current_byte_index)
1003
                        abort ();
1004
                    }
1005
 
1006
                  /* If this is coming from an unloadable section then copy
1007
                     zeros.  */
1008
                  if (raw_data == NULL)
1009
                    *dst++ = 0;
1010
                  else
1011
                    *dst++ = *raw_data++;
1012
 
1013
                  if (++i >= 8)
1014
                    {
1015
                      i = 0;
1016
                      mod = dst++;
1017
                      *mod = 0;
1018
                    }
1019
                  current_byte_index++;
1020
                }
1021
 
1022
              /* Don't write a useless null modification byte.  */
1023
              if (dst == mod + 1)
1024
                --dst;
1025
 
1026
              if (! (oasys_write_record
1027
                     (abfd, oasys_record_is_data_enum,
1028
                      ((oasys_record_union_type *) &processed_data),
1029
                      (size_t) (dst - (bfd_byte *) &processed_data))))
1030
                return FALSE;
1031
            }
1032
        }
1033
    }
1034
 
1035
  return TRUE;
1036
}
1037
 
1038
static bfd_boolean
1039
oasys_write_object_contents (bfd *abfd)
1040
{
1041
  if (! oasys_write_header (abfd))
1042
    return FALSE;
1043
  if (! oasys_write_syms (abfd))
1044
    return FALSE;
1045
  if (! oasys_write_sections (abfd))
1046
    return FALSE;
1047
  if (! oasys_write_data (abfd))
1048
    return FALSE;
1049
  if (! oasys_write_end (abfd))
1050
    return FALSE;
1051
  return TRUE;
1052
}
1053
 
1054
/* Set section contents is complicated with OASYS since the format is
1055
   not a byte image, but a record stream.  */
1056
 
1057
static bfd_boolean
1058
oasys_set_section_contents (bfd *abfd,
1059
                            sec_ptr section,
1060
                            const void * location,
1061
                            file_ptr offset,
1062
                            bfd_size_type count)
1063
{
1064
  if (count != 0)
1065
    {
1066
      if (oasys_per_section (section)->data == NULL)
1067
        {
1068
          oasys_per_section (section)->data = bfd_alloc (abfd, section->size);
1069
          if (!oasys_per_section (section)->data)
1070
            return FALSE;
1071
        }
1072
      (void) memcpy ((void *) (oasys_per_section (section)->data + offset),
1073
                     location, (size_t) count);
1074
    }
1075
  return TRUE;
1076
}
1077
 
1078
 
1079
 
1080
/* Native-level interface to symbols.  */
1081
 
1082
/* We read the symbols into a buffer, which is discarded when this
1083
   function exits.  We read the strings into a buffer large enough to
1084
   hold them all plus all the cached symbol entries.  */
1085
 
1086
static asymbol *
1087
oasys_make_empty_symbol (bfd *abfd)
1088
{
1089
  bfd_size_type amt = sizeof (oasys_symbol_type);
1090
  oasys_symbol_type *new_symbol_type = bfd_zalloc (abfd, amt);
1091
 
1092
  if (!new_symbol_type)
1093
    return NULL;
1094
  new_symbol_type->symbol.the_bfd = abfd;
1095
  return &new_symbol_type->symbol;
1096
}
1097
 
1098
/* User should have checked the file flags; perhaps we should return
1099
   BFD_NO_MORE_SYMBOLS if there are none?  */
1100
 
1101
static bfd *
1102
oasys_openr_next_archived_file (bfd *arch, bfd *prev)
1103
{
1104
  oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
1105
  oasys_module_info_type *p;
1106
 
1107
  /* Take the next one from the arch state, or reset.  */
1108
  if (prev == NULL)
1109
    /* Reset the index - the first two entries are bogus.  */
1110
    ar->module_index = 0;
1111
 
1112
  p = ar->module + ar->module_index;
1113
  ar->module_index++;
1114
 
1115
  if (ar->module_index <= ar->module_count)
1116
    {
1117
      if (p->abfd == NULL)
1118
        {
1119
          p->abfd = _bfd_create_empty_archive_element_shell (arch);
1120
          p->abfd->origin = p->pos;
1121
          p->abfd->filename = p->name;
1122
 
1123
          /* Fixup a pointer to this element for the member.  */
1124
          p->abfd->arelt_data = (void *) p;
1125
        }
1126
      return p->abfd;
1127
    }
1128
 
1129
  bfd_set_error (bfd_error_no_more_archived_files);
1130
  return NULL;
1131
}
1132
 
1133
static bfd_boolean
1134
oasys_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED,
1135
                         asection *section ATTRIBUTE_UNUSED,
1136
                         asymbol **symbols ATTRIBUTE_UNUSED,
1137
                         bfd_vma offset ATTRIBUTE_UNUSED,
1138
                         const char **filename_ptr ATTRIBUTE_UNUSED,
1139
                         const char **functionname_ptr ATTRIBUTE_UNUSED,
1140
                         unsigned int *line_ptr ATTRIBUTE_UNUSED)
1141
{
1142
  return FALSE;
1143
}
1144
 
1145
static bfd_boolean
1146
oasys_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED,
1147
                         const char **filename_ptr ATTRIBUTE_UNUSED,
1148
                         const char **functionname_ptr ATTRIBUTE_UNUSED,
1149
                         unsigned int *line_ptr ATTRIBUTE_UNUSED)
1150
{
1151
  return FALSE;
1152
}
1153
 
1154
static int
1155
oasys_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
1156
{
1157
  oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1158
 
1159
  if (mod == NULL)
1160
    {
1161
      bfd_set_error (bfd_error_invalid_operation);
1162
      return -1;
1163
    }
1164
 
1165
  buf->st_size = mod->size;
1166
  buf->st_mode = 0666;
1167
  return 0;
1168
}
1169
 
1170
static int
1171
oasys_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
1172
                      struct bfd_link_info *info ATTRIBUTE_UNUSED)
1173
{
1174
  return 0;
1175
}
1176
 
1177
#define oasys_close_and_cleanup                    _bfd_generic_close_and_cleanup
1178
#define oasys_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
1179
#define oasys_slurp_armap                          bfd_true
1180
#define oasys_slurp_extended_name_table            bfd_true
1181
#define oasys_construct_extended_name_table        ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_true)
1182
#define oasys_truncate_arname                      bfd_dont_truncate_arname
1183
#define oasys_write_armap                          ((bfd_boolean (*) (bfd *, unsigned int, struct orl *, unsigned int, int)) bfd_true)
1184
#define oasys_read_ar_hdr                          bfd_nullvoidptr
1185
#define oasys_write_ar_hdr ((bfd_boolean (*) (bfd *, bfd *)) bfd_false)
1186
#define oasys_get_elt_at_index                     _bfd_generic_get_elt_at_index
1187
#define oasys_update_armap_timestamp               bfd_true
1188
#define oasys_bfd_is_local_label_name              bfd_generic_is_local_label_name
1189
#define oasys_bfd_is_target_special_symbol         ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
1190
#define oasys_get_lineno                           _bfd_nosymbols_get_lineno
1191
#define oasys_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
1192
#define oasys_read_minisymbols                     _bfd_generic_read_minisymbols
1193
#define oasys_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
1194
#define oasys_bfd_reloc_type_lookup                _bfd_norelocs_bfd_reloc_type_lookup
1195
#define oasys_bfd_reloc_name_lookup          _bfd_norelocs_bfd_reloc_name_lookup
1196
#define oasys_set_arch_mach                        bfd_default_set_arch_mach
1197
#define oasys_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
1198
#define oasys_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
1199
#define oasys_bfd_relax_section                    bfd_generic_relax_section
1200
#define oasys_bfd_gc_sections                      bfd_generic_gc_sections
1201 161 khays
#define oasys_bfd_lookup_section_flags             bfd_generic_lookup_section_flags
1202 14 khays
#define oasys_bfd_merge_sections                   bfd_generic_merge_sections
1203
#define oasys_bfd_is_group_section                 bfd_generic_is_group_section
1204
#define oasys_bfd_discard_group                    bfd_generic_discard_group
1205
#define oasys_section_already_linked               _bfd_generic_section_already_linked
1206
#define oasys_bfd_define_common_symbol             bfd_generic_define_common_symbol
1207
#define oasys_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
1208
#define oasys_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
1209
#define oasys_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
1210
#define oasys_bfd_link_just_syms                   _bfd_generic_link_just_syms
1211
#define oasys_bfd_copy_link_hash_symbol_type \
1212
  _bfd_generic_copy_link_hash_symbol_type
1213
#define oasys_bfd_final_link                       _bfd_generic_final_link
1214
#define oasys_bfd_link_split_section               _bfd_generic_link_split_section
1215
 
1216
const bfd_target oasys_vec =
1217
{
1218
  "oasys",                      /* Name.  */
1219
  bfd_target_oasys_flavour,
1220
  BFD_ENDIAN_BIG,               /* Target byte order.  */
1221
  BFD_ENDIAN_BIG,               /* Target headers byte order.  */
1222
  (HAS_RELOC | EXEC_P |         /* Object flags.  */
1223
   HAS_LINENO | HAS_DEBUG |
1224
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1225
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1226
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
1227
  0,                             /* Leading underscore.  */
1228
  ' ',                          /* AR_pad_char.  */
1229
  16,                           /* AR_max_namelen.  */
1230 148 khays
  0,                             /* match priority.  */
1231 14 khays
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1232
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1233
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Data.  */
1234
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1235
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1236
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Headers.  */
1237
 
1238
  {_bfd_dummy_target,
1239
   oasys_object_p,              /* bfd_check_format.  */
1240
   oasys_archive_p,
1241
   _bfd_dummy_target,
1242
  },
1243
  {                             /* bfd_set_format.  */
1244
    bfd_false,
1245
    oasys_mkobject,
1246
    _bfd_generic_mkarchive,
1247
    bfd_false
1248
  },
1249
  {                             /* bfd_write_contents.  */
1250
    bfd_false,
1251
    oasys_write_object_contents,
1252
    _bfd_write_archive_contents,
1253
    bfd_false,
1254
  },
1255
 
1256
  BFD_JUMP_TABLE_GENERIC (oasys),
1257
  BFD_JUMP_TABLE_COPY (_bfd_generic),
1258
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1259
  BFD_JUMP_TABLE_ARCHIVE (oasys),
1260
  BFD_JUMP_TABLE_SYMBOLS (oasys),
1261
  BFD_JUMP_TABLE_RELOCS (oasys),
1262
  BFD_JUMP_TABLE_WRITE (oasys),
1263
  BFD_JUMP_TABLE_LINK (oasys),
1264
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1265
 
1266
  NULL,
1267
 
1268
  NULL
1269
};

powered by: WebSVN 2.1.0

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