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