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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [bfd/] [vms-gsd.c] - Blame information for rev 853

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

Line No. Rev Author Line
1 24 jeremybenn
/* vms-gsd.c -- BFD back-end for VAX (openVMS/VAX) and
2
   EVAX (openVMS/Alpha) files.
3
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 225 jeremybenn
   2007, 2009 Free Software Foundation, Inc.
5 24 jeremybenn
 
6 225 jeremybenn
   GSD record handling functions
7
   EGSD record handling functions
8
 
9
   Go and read the openVMS linker manual (esp. appendix B)
10 24 jeremybenn
   if you don't know what's going on here :-)
11
 
12
   Written by Klaus K"ampf (kkaempf@rmi.de)
13
 
14
   This program is free software; you can redistribute it and/or modify
15
   it under the terms of the GNU General Public License as published by
16
   the Free Software Foundation; either version 3 of the License, or
17
   (at your option) any later version.
18
 
19
   This program is distributed in the hope that it will be useful,
20
   but WITHOUT ANY WARRANTY; without even the implied warranty of
21
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
   GNU General Public License for more details.
23
 
24
   You should have received a copy of the GNU General Public License
25
   along with this program; if not, write to the Free Software
26
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
27
   MA 02110-1301, USA.  */
28
 
29
#include "sysdep.h"
30
#include "bfd.h"
31
#include "bfdlink.h"
32
#include "libbfd.h"
33
 
34
#include "vms.h"
35
 
36
/* Typical sections for vax object files.  */
37
 
38
#define VAX_CODE_NAME           "$CODE"
39
#define VAX_DATA_NAME           "$DATA"
40
#define VAX_ADDRESS_DATA_NAME   "$ADDRESS_DATA"
41
 
42
/* Typical sections for evax object files.  */
43
 
44
#define EVAX_ABS_NAME           "$ABS$"
45
#define EVAX_CODE_NAME          "$CODE$"
46
#define EVAX_LINK_NAME          "$LINK$"
47
#define EVAX_DATA_NAME          "$DATA$"
48
#define EVAX_BSS_NAME           "$BSS$"
49
#define EVAX_READONLYADDR_NAME  "$READONLY_ADDR$"
50
#define EVAX_READONLY_NAME      "$READONLY$"
51
#define EVAX_LITERAL_NAME       "$LITERAL$"
52 225 jeremybenn
#define EVAX_LITERALS_NAME      "$LITERALS"
53 24 jeremybenn
#define EVAX_COMMON_NAME        "$COMMON$"
54
#define EVAX_LOCAL_NAME         "$LOCAL$"
55
 
56
struct sec_flags_struct
57
{
58
  char *name;                   /* Name of section.  */
59
  int vflags_always;
60
  flagword flags_always;        /* Flags we set always.  */
61
  int vflags_hassize;
62
  flagword flags_hassize;       /* Flags we set if the section has a size > 0.  */
63
};
64
 
65
/* These flags are deccrtl/vaxcrtl (openVMS 6.2 VAX) compatible.  */
66
 
67
static struct sec_flags_struct vax_section_flags[] =
68
  {
69
    { VAX_CODE_NAME,
70
      (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD),
71
      (SEC_CODE),
72
      (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD),
73
      (SEC_IN_MEMORY | SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
74
    { VAX_DATA_NAME,
75
      (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT),
76
      (SEC_DATA),
77
      (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT),
78
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
79
    { VAX_ADDRESS_DATA_NAME,
80
      (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD),
81
      (SEC_DATA | SEC_READONLY),
82
      (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD),
83
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
84
    { NULL,
85
      (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_RD | GPS_S_M_WRT),
86
      (SEC_DATA),
87
      (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_RD | GPS_S_M_WRT),
88
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }
89
  };
90
 
91
/* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible.  */
92
 
93
static struct sec_flags_struct evax_section_flags[] =
94
  {
95
    { EVAX_ABS_NAME,
96
      (EGPS_S_V_SHR),
97
      (SEC_DATA),
98
      (EGPS_S_V_SHR),
99
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
100
    { EVAX_CODE_NAME,
101
      (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_EXE),
102
      (SEC_CODE),
103
      (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_EXE),
104
      (SEC_IN_MEMORY | SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
105
    { EVAX_LITERAL_NAME,
106
      (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD | EGPS_S_V_NOMOD),
107
      (SEC_DATA | SEC_READONLY),
108
      (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD),
109
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
110
    { EVAX_LINK_NAME,
111
      (EGPS_S_V_REL | EGPS_S_V_RD),
112
      (SEC_DATA | SEC_READONLY),
113
      (EGPS_S_V_REL | EGPS_S_V_RD),
114
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
115
    { EVAX_DATA_NAME,
116
      (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
117
      (SEC_DATA),
118
      (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
119
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
120
    { EVAX_BSS_NAME,
121
      (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
122
      (SEC_NO_FLAGS),
123
      (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
124
      (SEC_IN_MEMORY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
125
    { EVAX_READONLYADDR_NAME,
126
      (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_RD),
127
      (SEC_DATA | SEC_READONLY),
128
      (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_RD),
129
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
130
    { EVAX_READONLY_NAME,
131
      (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD | EGPS_S_V_NOMOD),
132
      (SEC_DATA | SEC_READONLY),
133
      (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD),
134
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
135
    { EVAX_LOCAL_NAME,
136
      (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
137
      (SEC_DATA),
138
      (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
139
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
140 225 jeremybenn
    { EVAX_LITERALS_NAME,
141
      (EGPS_S_V_PIC | EGPS_S_V_OVR),
142
      (SEC_DATA | SEC_READONLY),
143
      (EGPS_S_V_PIC | EGPS_S_V_OVR),
144
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
145 24 jeremybenn
    { NULL,
146
      (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
147
      (SEC_DATA),
148
      (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
149
      (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }
150
  };
151
 
152
/* Retrieve bfd section flags by name and size.  */
153
 
154
static flagword
155
vms_secflag_by_name (bfd *abfd,
156
                     struct sec_flags_struct *section_flags,
157
                     char *name,
158
                     int hassize)
159
{
160
  int i = 0;
161
 
162
  while (section_flags[i].name != NULL)
163
    {
164
      if ((PRIV (is_vax)?
165
           strcasecmp (name, section_flags[i].name):
166
           strcmp (name, section_flags[i].name)) == 0)
167
        {
168
          if (hassize)
169
            return section_flags[i].flags_hassize;
170
          else
171
            return section_flags[i].flags_always;
172
        }
173
      i++;
174
    }
175
  if (hassize)
176
    return section_flags[i].flags_hassize;
177
  return section_flags[i].flags_always;
178
}
179
 
180
/* Retrieve vms section flags by name and size.  */
181
 
182
static flagword
183
vms_esecflag_by_name (struct sec_flags_struct *section_flags,
184
                      char *name,
185
                      int hassize)
186
{
187
  int i = 0;
188
 
189
  while (section_flags[i].name != NULL)
190
    {
191
      if (strcmp (name, section_flags[i].name) == 0)
192
        {
193
          if (hassize)
194
            return section_flags[i].vflags_hassize;
195
          else
196
            return section_flags[i].vflags_always;
197
        }
198
      i++;
199
    }
200
  if (hassize)
201
    return section_flags[i].vflags_hassize;
202
  return section_flags[i].vflags_always;
203
}
204
 
205
#if VMS_DEBUG
206
 
207
struct flagdescstruct { char *name; flagword value; };
208
 
209 225 jeremybenn
static const struct flagdescstruct gpsflagdesc[] =
210
{
211
  { "PIC", GPS_S_M_PIC },
212
  { "LIB", GPS_S_M_LIB },
213
  { "OVR", GPS_S_M_OVR },
214
  { "REL", GPS_S_M_REL },
215
  { "GBL", GPS_S_M_GBL },
216
  { "SHR", GPS_S_M_SHR },
217
  { "EXE", GPS_S_M_EXE },
218
  { "RD",  GPS_S_M_RD },
219
  { "WRT", GPS_S_M_WRT },
220
  { "VEC", GPS_S_M_VEC },
221
  { "NOMOD", EGPS_S_V_NOMOD },
222
  { "COM", EGPS_S_V_COM },
223
  { NULL, 0 }
224
};
225
 
226
static const struct flagdescstruct gsyflagdesc[] =
227
{
228
  { "WEAK", GSY_S_M_WEAK },
229
  { "DEF",  GSY_S_M_DEF },
230
  { "UNI",  GSY_S_M_UNI },
231
  { "REL",  GSY_S_M_REL },
232
  { "COMM", EGSY_S_V_COMM },
233
  { "VECEP", EGSY_S_V_VECEP },
234
  { "NORM", EGCY_S_V_NORM },
235
  { NULL, 0 }
236
};
237
 
238
static char *flag2str (struct flagdescstruct *, flagword);
239
 
240 24 jeremybenn
/* Convert flag to printable string.  */
241
 
242
static char *
243
flag2str (struct flagdescstruct * flagdesc, flagword flags)
244
{
245
  static char res[64];
246
  int next = 0;
247
 
248
  res[0] = 0;
249
  while (flagdesc->name != NULL)
250
    {
251
      if ((flags & flagdesc->value) != 0)
252
        {
253
          if (next)
254
            strcat (res, ",");
255
          else
256
            next = 1;
257
          strcat (res, flagdesc->name);
258
        }
259
      flagdesc++;
260
    }
261
  return res;
262
}
263
#endif
264
 
265
/* Input routines.  */
266
 
267 225 jeremybenn
static int register_universal_symbol (bfd *abfd, asymbol *symbol,
268
                                      int vms_flags);
269
 
270 24 jeremybenn
/* Process GSD/EGSD record
271
   return 0 on success, -1 on error.  */
272
 
273
int
274
_bfd_vms_slurp_gsd (bfd * abfd, int objtype)
275
{
276
  int gsd_type, gsd_size;
277
  asection *section;
278
  unsigned char *vms_rec;
279
  flagword new_flags, old_flags;
280
  char *name;
281
  asymbol *symbol;
282
  vms_symbol_entry *entry;
283
  unsigned long base_addr;
284
  unsigned long align_addr;
285
  static unsigned int psect_idx = 0;
286
 
287
#if VMS_DEBUG
288
  vms_debug (2, "GSD/EGSD (%d/%x)\n", objtype, objtype);
289
#endif
290
 
291
  switch (objtype)
292
    {
293
    case EOBJ_S_C_EGSD:
294
      PRIV (vms_rec) += 8;      /* Skip type, size, l_temp.  */
295
      PRIV (rec_size) -= 8;
296
      break;
297
    case OBJ_S_C_GSD:
298
      PRIV (vms_rec) += 1;
299
      PRIV (rec_size) -= 1;
300
      break;
301
    default:
302
      return -1;
303
    }
304
 
305
  /* Calculate base address for each section.  */
306
  base_addr = 0L;
307
 
308
  abfd->symcount = 0;
309
 
310
  while (PRIV (rec_size) > 0)
311
    {
312
      vms_rec = PRIV (vms_rec);
313
 
314
      if (objtype == OBJ_S_C_GSD)
315 225 jeremybenn
        gsd_type = vms_rec[0];
316 24 jeremybenn
      else
317
        {
318
          _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size);
319
          gsd_type += EVAX_OFFSET;
320
        }
321
 
322
#if VMS_DEBUG
323
      vms_debug (3, "gsd_type %d\n", gsd_type);
324
#endif
325
 
326
      switch (gsd_type)
327
        {
328
        case GSD_S_C_PSC:
329
          {
330
            /* Program section definition.  */
331
            asection *old_section = 0;
332
 
333
#if VMS_DEBUG
334
            vms_debug (4, "GSD_S_C_PSC\n");
335
#endif
336
            /* If this section isn't a bfd section.  */
337 225 jeremybenn
            if (PRIV (is_vax) && (psect_idx < (abfd->section_count - 1)))
338 24 jeremybenn
              {
339
                /* Check for temporary section from TIR record.  */
340
                if (psect_idx < PRIV (section_count))
341
                  old_section = PRIV (sections)[psect_idx];
342
                else
343
                  old_section = 0;
344
              }
345
 
346
            name = _bfd_vms_save_counted_string (vms_rec + 8);
347
            section = bfd_make_section (abfd, name);
348
            if (!section)
349
              {
350
                (*_bfd_error_handler) (_("bfd_make_section (%s) failed"),
351
                                       name);
352
                return -1;
353
              }
354
            old_flags = bfd_getl16 (vms_rec + 2);
355
            section->size = bfd_getl32 (vms_rec + 4);  /* allocation */
356
            new_flags = vms_secflag_by_name (abfd, vax_section_flags, name,
357
                                             section->size > 0);
358
            if (old_flags & EGPS_S_V_REL)
359
              new_flags |= SEC_RELOC;
360
            if (old_flags & GPS_S_M_OVR)
361
              new_flags |= SEC_IS_COMMON;
362
            if (!bfd_set_section_flags (abfd, section, new_flags))
363
              {
364
                (*_bfd_error_handler)
365
                  (_("bfd_set_section_flags (%s, %x) failed"),
366
                   name, new_flags);
367
                return -1;
368
              }
369
            section->alignment_power = vms_rec[1];
370
            align_addr = (1 << section->alignment_power);
371
            if ((base_addr % align_addr) != 0)
372
              base_addr += (align_addr - (base_addr % align_addr));
373
            section->vma = (bfd_vma)base_addr;
374
            base_addr += section->size;
375
 
376
            /* Global section is common symbol.  */
377
            if (old_flags & GPS_S_M_GBL)
378
              {
379
                entry = _bfd_vms_enter_symbol (abfd, name);
380
                if (entry == NULL)
381
                  {
382
                    bfd_set_error (bfd_error_no_memory);
383
                    return -1;
384
                  }
385
                symbol = entry->symbol;
386
 
387
                symbol->value = 0;
388
                symbol->section = section;
389
                symbol->flags = (BSF_GLOBAL | BSF_SECTION_SYM | BSF_OLD_COMMON);
390
              }
391
 
392
            /* Copy saved contents if old_section set.  */
393
            if (old_section != 0)
394
              {
395
                section->contents = old_section->contents;
396
                if (section->size < old_section->size)
397
                  {
398
                    (*_bfd_error_handler)
399
                      (_("Size mismatch section %s=%lx, %s=%lx"),
400
                       old_section->name,
401
                       (unsigned long) old_section->size,
402
                       section->name,
403
                       (unsigned long) section->size);
404
                    return -1;
405
                  }
406
                else if (section->size > old_section->size)
407
                  {
408
                    section->contents = bfd_realloc (old_section->contents,
409
                                                     section->size);
410
                    if (section->contents == NULL)
411
                      {
412
                        bfd_set_error (bfd_error_no_memory);
413
                        return -1;
414
                      }
415
                  }
416
              }
417
            else
418
              {
419
                section->contents = bfd_zmalloc (section->size);
420
                if (section->contents == NULL)
421
                  {
422
                    bfd_set_error (bfd_error_no_memory);
423
                    return -1;
424
                  }
425
              }
426
#if VMS_DEBUG
427
            vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ",
428
                       section->index, name, old_flags, flag2str (gpsflagdesc, old_flags));
429
            vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
430
                       section->size, section->vma, section->contents);
431
#endif
432
 
433
            gsd_size = vms_rec[8] + 9;
434
 
435
            psect_idx++;
436
          }
437
          break;
438
 
439
        case GSD_S_C_EPM:
440
        case GSD_S_C_EPMW:
441
#if VMS_DEBUG
442
          vms_debug (4, "gsd epm\n");
443
#endif
444
          /* Fall through.  */
445
        case GSD_S_C_SYM:
446
        case GSD_S_C_SYMW:
447
          {
448
            int name_offset = 0, value_offset = 0;
449
 
450
            /* Symbol specification (definition or reference).  */
451
#if VMS_DEBUG
452
            vms_debug (4, "GSD_S_C_SYM(W)\n");
453
#endif
454
            old_flags = bfd_getl16 (vms_rec + 2);
455
            new_flags = BSF_NO_FLAGS;
456
 
457
            if (old_flags & GSY_S_M_WEAK)
458
              new_flags |= BSF_WEAK;
459
 
460
            switch (gsd_type)
461
              {
462
              case GSD_S_C_EPM:
463
                name_offset = 11;
464
                value_offset = 5;
465
                new_flags |= BSF_FUNCTION;
466
                break;
467
              case GSD_S_C_EPMW:
468
                name_offset = 12;
469
                value_offset = 6;
470
                new_flags |= BSF_FUNCTION;
471
                break;
472
              case GSD_S_C_SYM:
473
                if (old_flags & GSY_S_M_DEF)    /* Symbol definition.  */
474
                  name_offset = 9;
475
                else
476
                  name_offset = 4;
477
                value_offset = 5;
478
                break;
479
              case GSD_S_C_SYMW:
480
                if (old_flags & GSY_S_M_DEF)    /* Symbol definition.  */
481
                  name_offset = 10;
482
                else
483
                  name_offset = 5;
484
                value_offset = 6;
485
                break;
486
              }
487
 
488
            /* Save symbol in vms_symbol_table.  */
489
            entry = _bfd_vms_enter_symbol
490
              (abfd, _bfd_vms_save_counted_string (vms_rec + name_offset));
491
            if (entry == NULL)
492
              {
493
                bfd_set_error (bfd_error_no_memory);
494
                return -1;
495
              }
496
            symbol = entry->symbol;
497
 
498
            if (old_flags & GSY_S_M_DEF)
499
              {
500
                /* Symbol definition.  */
501
                int psect;
502
 
503
                symbol->value = bfd_getl32 (vms_rec + value_offset);
504
                if ((gsd_type == GSD_S_C_SYMW)
505
                    || (gsd_type == GSD_S_C_EPMW))
506
                  psect = bfd_getl16 (vms_rec + value_offset - 2);
507
                else
508
                  psect = vms_rec[value_offset-1];
509
 
510 225 jeremybenn
                symbol->section = (asection *)(unsigned long)psect;
511 24 jeremybenn
#if VMS_DEBUG
512 225 jeremybenn
                vms_debug (4, "gsd sym def #%d (%s, %ld, %04x=%s)\n", abfd->symcount,
513
                          symbol->name, (long)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags));
514 24 jeremybenn
#endif
515
              }
516
            else
517
              {
518
                /* Symbol reference.  */
519
#if VMS_DEBUG
520 225 jeremybenn
                vms_debug (4, "gsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount,
521
                           symbol->name, old_flags, flag2str (gsyflagdesc, old_flags));
522 24 jeremybenn
#endif
523 225 jeremybenn
                symbol->section = (asection *)(unsigned long)-1;
524 24 jeremybenn
              }
525
 
526
            gsd_size = vms_rec[name_offset] + name_offset + 1;
527
            symbol->flags = new_flags;
528
          }
529
 
530
          break;
531
 
532
        case GSD_S_C_PRO:
533
        case GSD_S_C_PROW:
534
#if VMS_DEBUG
535
          vms_debug (4, "gsd pro\n");
536
#endif
537
          break;
538
        case GSD_S_C_IDC:
539
#if VMS_DEBUG
540
          vms_debug (4, "gsd idc\n");
541
#endif
542
          break;
543
        case GSD_S_C_ENV:
544
#if VMS_DEBUG
545
          vms_debug (4, "gsd env\n");
546
#endif
547
          break;
548
        case GSD_S_C_LSY:
549
#if VMS_DEBUG
550
          vms_debug (4, "gsd lsy\n");
551
#endif
552
          break;
553
        case GSD_S_C_LEPM:
554
#if VMS_DEBUG
555
          vms_debug (4, "gsd lepm\n");
556
#endif
557
          break;
558
        case GSD_S_C_LPRO:
559
#if VMS_DEBUG
560
          vms_debug (4, "gsd lpro\n");
561
#endif
562
          break;
563
        case GSD_S_C_SPSC:
564
#if VMS_DEBUG
565
          vms_debug (4, "gsd spsc\n");
566
#endif
567
          break;
568
        case GSD_S_C_SYMV:
569
#if VMS_DEBUG
570
          vms_debug (4, "gsd symv\n");
571
#endif
572
          break;
573
        case GSD_S_C_EPMV:
574
#if VMS_DEBUG
575
          vms_debug (4, "gsd epmv\n");
576
#endif
577
          break;
578
        case GSD_S_C_PROV:
579
#if VMS_DEBUG
580
          vms_debug (4, "gsd prov\n");
581
#endif
582
          break;
583
 
584
        case EGSD_S_C_PSC + EVAX_OFFSET:
585
          {
586
            /* Program section definition.  */
587 225 jeremybenn
            name = _bfd_vms_save_counted_string (vms_rec + EGPS_S_B_NAMLNG);
588 24 jeremybenn
            section = bfd_make_section (abfd, name);
589
            if (!section)
590
              return -1;
591 225 jeremybenn
            old_flags = bfd_getl16 (vms_rec + EGPS_S_W_FLAGS);
592
            section->size = bfd_getl32 (vms_rec + EGPS_S_L_ALLOC);
593 24 jeremybenn
            new_flags = vms_secflag_by_name (abfd, evax_section_flags, name,
594
                                             section->size > 0);
595
            if (old_flags & EGPS_S_V_REL)
596
              new_flags |= SEC_RELOC;
597
            if (!bfd_set_section_flags (abfd, section, new_flags))
598
              return -1;
599 225 jeremybenn
            section->alignment_power = vms_rec[EGPS_S_B_ALIGN];
600 24 jeremybenn
            align_addr = (1 << section->alignment_power);
601
            if ((base_addr % align_addr) != 0)
602
              base_addr += (align_addr - (base_addr % align_addr));
603
            section->vma = (bfd_vma)base_addr;
604
            base_addr += section->size;
605
            section->contents = bfd_zmalloc (section->size);
606
            if (section->contents == NULL)
607
              return -1;
608 225 jeremybenn
            section->filepos = (unsigned int)-1;
609 24 jeremybenn
#if VMS_DEBUG
610 225 jeremybenn
            vms_debug (4, "EGSD P-section %d (%s, flags %04x=%s) ",
611
                       section->index, name, old_flags, flag2str(gpsflagdesc, old_flags));
612 24 jeremybenn
            vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
613
                       section->size, section->vma, section->contents);
614
#endif
615
          }
616
          break;
617
 
618
        case EGSD_S_C_SYM + EVAX_OFFSET:
619
          {
620 225 jeremybenn
            /* Global symbol specification (definition or reference).  */
621 24 jeremybenn
            symbol = bfd_make_empty_symbol (abfd);
622
            if (symbol == 0)
623
              return -1;
624
 
625 225 jeremybenn
            old_flags = bfd_getl16 (vms_rec + EGSY_S_W_FLAGS);
626 24 jeremybenn
            new_flags = BSF_NO_FLAGS;
627
 
628
            if (old_flags & EGSY_S_V_WEAK)
629
              new_flags |= BSF_WEAK;
630
 
631 225 jeremybenn
            if (old_flags & EGSY_S_V_DEF)
632 24 jeremybenn
              {
633
                /* Symbol definition.  */
634
                if (old_flags & EGSY_S_V_NORM)
635
                  new_flags |= BSF_FUNCTION;
636 225 jeremybenn
                symbol->name =
637
                  _bfd_vms_save_counted_string (vms_rec + ESDF_S_B_NAMLNG);
638
                symbol->value = bfd_getl64 (vms_rec + ESDF_S_L_VALUE);
639
                symbol->section =
640
                  (asection *)(unsigned long) bfd_getl32 (vms_rec + ESDF_S_L_PSINDX);
641 24 jeremybenn
#if VMS_DEBUG
642 225 jeremybenn
                vms_debug (4, "EGSD sym def #%d (%s, %ld, %04x=%s)\n",
643
                           abfd->symcount, symbol->name, (long)symbol->section,
644
                           old_flags, flag2str (gsyflagdesc, old_flags));
645 24 jeremybenn
#endif
646
              }
647
            else
648
              {
649
                /* Symbol reference.  */
650 225 jeremybenn
                symbol->name =
651
                  _bfd_vms_save_counted_string (vms_rec + ESRF_S_B_NAMLNG);
652 24 jeremybenn
#if VMS_DEBUG
653 225 jeremybenn
                vms_debug (4, "EGSD sym ref #%d (%s, %04x=%s)\n",
654
                           abfd->symcount, symbol->name, old_flags,
655
                           flag2str (gsyflagdesc, old_flags));
656 24 jeremybenn
#endif
657 225 jeremybenn
                symbol->section = (asection *)(unsigned long)-1;
658 24 jeremybenn
              }
659
 
660
            symbol->flags = new_flags;
661
 
662 225 jeremybenn
            /* Register symbol in VMS symbol table.  */
663
            entry = (vms_symbol_entry *) bfd_hash_lookup
664
              (PRIV (vms_symbol_table), symbol->name, TRUE, FALSE);
665
 
666 24 jeremybenn
            if (entry == NULL)
667
              {
668
                bfd_set_error (bfd_error_no_memory);
669
                return -1;
670
              }
671
 
672
            if (entry->symbol != NULL)
673
              {
674
                /* FIXME ?, DEC C generates this.  */
675
#if VMS_DEBUG
676
                vms_debug (4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name);
677
#endif
678
              }
679
            else
680
              {
681
                entry->symbol = symbol;
682
                PRIV (gsd_sym_count)++;
683
                abfd->symcount++;
684
              }
685
          }
686
          break;
687
 
688 225 jeremybenn
        case EGSD_S_C_SYMG + EVAX_OFFSET:
689
          {
690
            /* Universal symbol specification (definition).  */
691
            symbol = bfd_make_empty_symbol (abfd);
692
            if (symbol == 0)
693
              return -1;
694
 
695
            old_flags = bfd_getl16 (vms_rec + EGST_S_W_FLAGS);
696
            new_flags = BSF_NO_FLAGS;
697
 
698
            if (old_flags & EGSY_S_V_WEAK)
699
              new_flags |= BSF_WEAK;
700
 
701
            if (old_flags & EGSY_S_V_DEF) /* symbol definition */
702
              {
703
                if (old_flags & EGSY_S_V_NORM)
704
                  new_flags |= BSF_FUNCTION;
705
 
706
                symbol->name =
707
                  _bfd_vms_save_counted_string (vms_rec + EGST_S_B_NAMLNG);
708
 
709
                /* For BSF_FUNCTION symbols, the entry point is in LP_1
710
                   and the descriptor in LP_2.  For other symbols, the
711
                   unique value is in LP_2.  */
712
                symbol->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_2);
713
 
714
                /* Adding this offset is necessary in order for GDB to
715
                   read the DWARF-2 debug info from shared libraries.  */
716
                if (abfd->flags & DYNAMIC
717
                    && strstr (symbol->name, "$DWARF2.DEBUG") != 0)
718
                  symbol->value += PRIV (symvva);
719
              }
720
            else /* symbol reference */
721
              (*_bfd_error_handler) ("Invalid EGST reference");
722
 
723
            symbol->flags = new_flags;
724
 
725
            if (register_universal_symbol (abfd, symbol, old_flags) < 0)
726
              return -1;
727
 
728
            /* Make a second symbol for the entry point.  */
729
            if (symbol->flags & BSF_FUNCTION)
730
              {
731
                asymbol *en_sym;
732
                char *name = bfd_alloc (abfd, strlen (symbol->name) + 5);
733
 
734
                en_sym = bfd_make_empty_symbol (abfd);
735
                if (en_sym == 0)
736
                  return -1;
737
 
738
                strcpy (name, symbol->name);
739
                strcat (name, "..en");
740
 
741
                en_sym->name = name;
742
                en_sym->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_1);
743
 
744
                if (register_universal_symbol (abfd, en_sym, old_flags) < 0)
745
                  return -1;
746
              }
747
          }
748 24 jeremybenn
          break;
749
 
750 225 jeremybenn
        case EGSD_S_C_IDC + EVAX_OFFSET:
751
          break;
752
 
753 24 jeremybenn
        default:
754 225 jeremybenn
          (*_bfd_error_handler) (_("Unknown GSD/EGSD subtype %d"), gsd_type);
755 24 jeremybenn
          bfd_set_error (bfd_error_bad_value);
756
          return -1;
757
        }
758
 
759
      PRIV (rec_size) -= gsd_size;
760
      PRIV (vms_rec) += gsd_size;
761
    }
762
 
763
  if (abfd->symcount > 0)
764
    abfd->flags |= HAS_SYMS;
765
 
766
  return 0;
767
}
768
 
769 225 jeremybenn
/* Register a universal symbol in the VMS symbol table.  */
770 24 jeremybenn
 
771 225 jeremybenn
static int
772
register_universal_symbol (bfd *abfd, asymbol *symbol, int vms_flags)
773
{
774
  bfd_vma sbase = 0;
775
  asection *s, *sec = NULL;
776
  vms_symbol_entry *entry;
777
 
778
  /* A universal symbol is by definition global...  */
779
  symbol->flags |= BSF_GLOBAL;
780
 
781
  /* ...and dynamic in shared libraries.  */
782
  if (abfd->flags & DYNAMIC)
783
    symbol->flags |= BSF_DYNAMIC;
784
 
785
  /* Find containing section.  */
786
  for (s = abfd->sections; s; s = s->next)
787
    {
788
      if (symbol->value >= s->vma
789
          && s->vma > sbase
790
          && !(s->flags & SEC_COFF_SHARED_LIBRARY)
791
          && (s->size > 0 || !(vms_flags & EGSY_S_V_REL)))
792
        {
793
          sbase = s->vma;
794
          sec = s;
795
        }
796
    }
797
 
798
  symbol->value -= sbase;
799
  symbol->section = sec;
800
 
801
#if VMS_DEBUG
802
  vms_debug (4, "EGST sym def #%d (%s, 0x%llx => 0x%llx, %04x=%s)\n",
803
             abfd->symcount, symbol->name, symbol->value + sbase,
804
             symbol->value, vms_flags,
805
             flag2str(gsyflagdesc, vms_flags));
806
#endif
807
 
808
  entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
809
                                                symbol->name,
810
                                                TRUE, FALSE);
811
 
812
  if (entry == NULL)
813
    {
814
      bfd_set_error (bfd_error_no_memory);
815
      return -1;
816
    }
817
 
818
  if (entry->symbol) /* FIXME: DEC C generates this */
819
    {
820
#if VMS_DEBUG
821
      vms_debug (4, "EGSD_S_C_SYMG: duplicate \"%s\"\n", symbol->name);
822
#endif
823
    }
824
  else
825
    {
826
      entry->symbol = symbol;
827
      PRIV (gsd_sym_count)++;
828
      abfd->symcount++;
829
    }
830
 
831
  return 0;
832
}
833
 
834
/* Set section VMS flags.  */
835
 
836
void
837
bfd_vms_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED,
838
                           asection *sec, flagword flags)
839
{
840
  vms_section_data (sec)->vflags = flags;
841
}
842
 
843 24 jeremybenn
/* Write section and symbol directory of bfd abfd.  */
844
 
845
int
846
_bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED)
847
{
848
  asection *section;
849
  asymbol *symbol;
850
  unsigned int symnum;
851
  int last_index = -1;
852
  char dummy_name[10];
853
  char *sname;
854
  flagword new_flags, old_flags;
855 225 jeremybenn
  int abs_section_index = 0;
856 24 jeremybenn
 
857
#if VMS_DEBUG
858
  vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype);
859
#endif
860
 
861
  /* Output sections.  */
862
  section = abfd->sections;
863
#if VMS_DEBUG
864
  vms_debug (3, "%d sections found\n", abfd->section_count);
865
#endif
866
 
867
  /* Egsd is quadword aligned.  */
868
  _bfd_vms_output_alignment (abfd, 8);
869
 
870
  _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
871
  _bfd_vms_output_long (abfd, 0);
872
  /* Prepare output for subrecords.  */
873
  _bfd_vms_output_push (abfd);
874
 
875
  while (section != 0)
876
    {
877
#if VMS_DEBUG
878
      vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->size);
879
#endif
880
 
881 225 jeremybenn
      /* Don't write out the VMS debug info section since it is in the
882
         ETBT and EDBG sections in etir. */
883
      if (!strcmp (section->name, ".vmsdebug"))
884
        goto done;
885
 
886 24 jeremybenn
      /* 13 bytes egsd, max 31 chars name -> should be 44 bytes.  */
887
      if (_bfd_vms_output_check (abfd, 64) < 0)
888
        {
889
          _bfd_vms_output_pop (abfd);
890
          _bfd_vms_output_end (abfd);
891
          _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
892
          _bfd_vms_output_long (abfd, 0);
893
          /* Prepare output for subrecords.  */
894
          _bfd_vms_output_push (abfd);
895
        }
896
 
897
      /* Create dummy sections to keep consecutive indices.  */
898
      while (section->index - last_index > 1)
899
        {
900
#if VMS_DEBUG
901
          vms_debug (3, "index %d, last %d\n", section->index, last_index);
902
#endif
903
          _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
904
          _bfd_vms_output_short (abfd, 0);
905
          _bfd_vms_output_short (abfd, 0);
906
          _bfd_vms_output_long (abfd, 0);
907
          sprintf (dummy_name, ".DUMMY%02d", last_index);
908
          _bfd_vms_output_counted (abfd, dummy_name);
909
          _bfd_vms_output_flush (abfd);
910
          last_index++;
911
        }
912
 
913
      /* Don't know if this is necessary for the linker but for now it keeps
914
         vms_slurp_gsd happy  */
915
      sname = (char *)section->name;
916
      if (*sname == '.')
917
        {
918
          sname++;
919
          if ((*sname == 't') && (strcmp (sname, "text") == 0))
920
            sname = PRIV (is_vax)?VAX_CODE_NAME:EVAX_CODE_NAME;
921
          else if ((*sname == 'd') && (strcmp (sname, "data") == 0))
922
            sname = PRIV (is_vax)?VAX_DATA_NAME:EVAX_DATA_NAME;
923
          else if ((*sname == 'b') && (strcmp (sname, "bss") == 0))
924
            sname = EVAX_BSS_NAME;
925
          else if ((*sname == 'l') && (strcmp (sname, "link") == 0))
926
            sname = EVAX_LINK_NAME;
927
          else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0))
928
            sname = EVAX_READONLY_NAME;
929
          else if ((*sname == 'l') && (strcmp (sname, "literal") == 0))
930
            sname = EVAX_LITERAL_NAME;
931 225 jeremybenn
          else if ((*sname == 'l') && (strcmp (sname, "literals") == 0))
932
            {
933
              sname = EVAX_LITERALS_NAME;
934
              abs_section_index = section->index;
935
            }
936 24 jeremybenn
          else if ((*sname == 'c') && (strcmp (sname, "comm") == 0))
937
            sname = EVAX_COMMON_NAME;
938
          else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0))
939
            sname = EVAX_LOCAL_NAME;
940
        }
941
      else
942
        sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ);
943
 
944
      _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
945
      _bfd_vms_output_short (abfd, section->alignment_power & 0xff);
946 225 jeremybenn
 
947 24 jeremybenn
      if (bfd_is_com_section (section))
948 225 jeremybenn
        new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD
949
                     | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM);
950 24 jeremybenn
      else
951
        new_flags = vms_esecflag_by_name (evax_section_flags, sname,
952
                                          section->size > 0);
953
 
954 225 jeremybenn
      /* Modify them as directed.  */
955
      if (section->flags & SEC_READONLY)
956
        new_flags &= ~EGPS_S_V_WRT;
957
 
958
      new_flags |= vms_section_data (section)->vflags & 0xffff;
959
      new_flags &=
960
        ~((vms_section_data (section)->vflags >> EGPS_S_V_NO_SHIFT) & 0xffff);
961
 
962
#if VMS_DEBUG
963
      vms_debug (3, "sec flags %x\n", section->flags);
964
      vms_debug (3, "new_flags %x, _raw_size %d\n", new_flags, section->size);
965
#endif
966
 
967 24 jeremybenn
      _bfd_vms_output_short (abfd, new_flags);
968
      _bfd_vms_output_long (abfd, (unsigned long) section->size);
969
      _bfd_vms_output_counted (abfd, sname);
970
      _bfd_vms_output_flush (abfd);
971
 
972
      last_index = section->index;
973 225 jeremybenn
done:
974 24 jeremybenn
      section = section->next;
975
    }
976
 
977
  /* Output symbols.  */
978
#if VMS_DEBUG
979
  vms_debug (3, "%d symbols found\n", abfd->symcount);
980
#endif
981
 
982
  bfd_set_start_address (abfd, (bfd_vma) -1);
983
 
984
  for (symnum = 0; symnum < abfd->symcount; symnum++)
985
    {
986
      char *hash;
987
 
988
      symbol = abfd->outsymbols[symnum];
989
      if (*(symbol->name) == '_')
990
        {
991
          if (strcmp (symbol->name, "__main") == 0)
992
            bfd_set_start_address (abfd, (bfd_vma)symbol->value);
993
        }
994
      old_flags = symbol->flags;
995
 
996
      if (old_flags & BSF_FILE)
997
        continue;
998
 
999 225 jeremybenn
      if ((old_flags & BSF_GLOBAL) == 0             /* Not xdef...  */
1000
          && !bfd_is_und_section (symbol->section) /* and not xref... */
1001
          && !((old_flags & BSF_SECTION_SYM) != 0  /* and not LIB$INITIALIZE.  */
1002
               && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0))
1003
        continue;
1004 24 jeremybenn
 
1005
      /* 13 bytes egsd, max 64 chars name -> should be 77 bytes.  */
1006
      if (_bfd_vms_output_check (abfd, 80) < 0)
1007
        {
1008
          _bfd_vms_output_pop (abfd);
1009
          _bfd_vms_output_end (abfd);
1010
          _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
1011
          _bfd_vms_output_long (abfd, 0);
1012
          /* Prepare output for subrecords.  */
1013
          _bfd_vms_output_push (abfd);
1014
        }
1015
 
1016
      _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1);
1017
 
1018
      /* Data type, alignment.  */
1019
      _bfd_vms_output_short (abfd, 0);
1020
 
1021
      new_flags = 0;
1022
 
1023
      if (old_flags & BSF_WEAK)
1024
        new_flags |= EGSY_S_V_WEAK;
1025 225 jeremybenn
      if (bfd_is_com_section (symbol->section))         /* .comm  */
1026 24 jeremybenn
        new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM);
1027
 
1028
      if (old_flags & BSF_FUNCTION)
1029
        {
1030
          new_flags |= EGSY_S_V_NORM;
1031
          new_flags |= EGSY_S_V_REL;
1032
        }
1033 225 jeremybenn
      if (old_flags & BSF_GLOBAL)
1034 24 jeremybenn
        {
1035
          new_flags |= EGSY_S_V_DEF;
1036
          if (!bfd_is_abs_section (symbol->section))
1037
            new_flags |= EGSY_S_V_REL;
1038
        }
1039
      _bfd_vms_output_short (abfd, new_flags);
1040
 
1041 225 jeremybenn
      if (old_flags & BSF_GLOBAL)
1042 24 jeremybenn
        {
1043
          /* Symbol definition.  */
1044
          uquad code_address = 0;
1045
          unsigned long ca_psindx = 0;
1046
          unsigned long psindx;
1047
 
1048
          if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
1049
            {
1050 225 jeremybenn
              asymbol *sym;
1051
 
1052
              if (bfd_get_flavour (abfd) == bfd_target_evax_flavour)
1053
                sym = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
1054
              else
1055
                sym = (asymbol *)symbol->udata.p;
1056
              code_address = sym->value;
1057
              ca_psindx = sym->section->index;
1058 24 jeremybenn
            }
1059 225 jeremybenn
          if (bfd_is_abs_section (symbol->section))
1060
            psindx = abs_section_index;
1061
          else
1062
            psindx = symbol->section->index;
1063 24 jeremybenn
 
1064
          _bfd_vms_output_quad (abfd, symbol->value);
1065
          _bfd_vms_output_quad (abfd, code_address);
1066
          _bfd_vms_output_long (abfd, ca_psindx);
1067
          _bfd_vms_output_long (abfd, psindx);
1068
        }
1069
      hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ);
1070
      _bfd_vms_output_counted (abfd, hash);
1071
 
1072
      _bfd_vms_output_flush (abfd);
1073
 
1074
    }
1075
 
1076
  _bfd_vms_output_alignment (abfd, 8);
1077
  _bfd_vms_output_pop (abfd);
1078
  _bfd_vms_output_end (abfd);
1079
 
1080
  return 0;
1081
}

powered by: WebSVN 2.1.0

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