OSDN Git Service

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