daily update
[external/binutils.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, 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
52 struct 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
63 static 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
89 static 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
145 static flagword
146 vms_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
173 static flagword
174 vms_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
198 struct flagdescstruct { char *name; flagword value; };
199
200 /* Convert flag to printable string.  */
201
202 static char *
203 flag2str (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
230 int
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
698 int
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 }