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