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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [bfd/] [oasys.c] - Blame information for rev 252

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

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

powered by: WebSVN 2.1.0

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