Back to index

cell-binutils  2.17cvs20070401
vms-gsd.c
Go to the documentation of this file.
00001 /* vms-gsd.c -- BFD back-end for VAX (openVMS/VAX) and
00002    EVAX (openVMS/Alpha) files.
00003    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
00004    Free Software Foundation, Inc.
00005 
00006    go and read the openVMS linker manual (esp. appendix B)
00007    if you don't know what's going on here :-)
00008 
00009    Written by Klaus K"ampf (kkaempf@rmi.de)
00010 
00011    This program is free software; you can redistribute it and/or modify
00012    it under the terms of the GNU General Public License as published by
00013    the Free Software Foundation; either version 2 of the License, or
00014    (at your option) any later version.
00015 
00016    This program is distributed in the hope that it will be useful,
00017    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019    GNU General Public License for more details.
00020 
00021    You should have received a copy of the GNU General Public License
00022    along with this program; if not, write to the Free Software
00023    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00024 
00025 #include "bfd.h"
00026 #include "sysdep.h"
00027 #include "bfdlink.h"
00028 #include "libbfd.h"
00029 
00030 #include "vms.h"
00031 
00032 /* Typical sections for vax object files.  */
00033 
00034 #define VAX_CODE_NAME              "$CODE"
00035 #define VAX_DATA_NAME              "$DATA"
00036 #define VAX_ADDRESS_DATA_NAME      "$ADDRESS_DATA"
00037 
00038 /* Typical sections for evax object files.  */
00039 
00040 #define EVAX_ABS_NAME              "$ABS$"
00041 #define EVAX_CODE_NAME             "$CODE$"
00042 #define EVAX_LINK_NAME             "$LINK$"
00043 #define EVAX_DATA_NAME             "$DATA$"
00044 #define EVAX_BSS_NAME              "$BSS$"
00045 #define EVAX_READONLYADDR_NAME     "$READONLY_ADDR$"
00046 #define EVAX_READONLY_NAME  "$READONLY$"
00047 #define EVAX_LITERAL_NAME   "$LITERAL$"
00048 #define EVAX_COMMON_NAME    "$COMMON$"
00049 #define EVAX_LOCAL_NAME            "$LOCAL$"
00050 
00051 struct sec_flags_struct
00052 {
00053   char *name;               /* Name of section.  */
00054   int vflags_always;
00055   flagword flags_always;    /* Flags we set always.  */
00056   int vflags_hassize;
00057   flagword flags_hassize;   /* Flags we set if the section has a size > 0.  */
00058 };
00059 
00060 /* These flags are deccrtl/vaxcrtl (openVMS 6.2 VAX) compatible.  */
00061 
00062 static struct sec_flags_struct vax_section_flags[] =
00063   {
00064     { VAX_CODE_NAME,
00065       (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD),
00066       (SEC_CODE),
00067       (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD),
00068       (SEC_IN_MEMORY | SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
00069     { VAX_DATA_NAME,
00070       (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT),
00071       (SEC_DATA),
00072       (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT),
00073       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
00074     { VAX_ADDRESS_DATA_NAME,
00075       (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD),
00076       (SEC_DATA | SEC_READONLY),
00077       (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD),
00078       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
00079     { NULL,
00080       (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_RD | GPS_S_M_WRT),
00081       (SEC_DATA),
00082       (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_RD | GPS_S_M_WRT),
00083       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }
00084   };
00085 
00086 /* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible.  */
00087 
00088 static struct sec_flags_struct evax_section_flags[] =
00089   {
00090     { EVAX_ABS_NAME,
00091       (EGPS_S_V_SHR),
00092       (SEC_DATA),
00093       (EGPS_S_V_SHR),
00094       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
00095     { EVAX_CODE_NAME,
00096       (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_EXE),
00097       (SEC_CODE),
00098       (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_EXE),
00099       (SEC_IN_MEMORY | SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
00100     { EVAX_LITERAL_NAME,
00101       (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD | EGPS_S_V_NOMOD),
00102       (SEC_DATA | SEC_READONLY),
00103       (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD),
00104       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
00105     { EVAX_LINK_NAME,
00106       (EGPS_S_V_REL | EGPS_S_V_RD),
00107       (SEC_DATA | SEC_READONLY),
00108       (EGPS_S_V_REL | EGPS_S_V_RD),
00109       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
00110     { EVAX_DATA_NAME,
00111       (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
00112       (SEC_DATA),
00113       (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
00114       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
00115     { EVAX_BSS_NAME,
00116       (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
00117       (SEC_NO_FLAGS),
00118       (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
00119       (SEC_IN_MEMORY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
00120     { EVAX_READONLYADDR_NAME,
00121       (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_RD),
00122       (SEC_DATA | SEC_READONLY),
00123       (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_RD),
00124       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
00125     { EVAX_READONLY_NAME,
00126       (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD | EGPS_S_V_NOMOD),
00127       (SEC_DATA | SEC_READONLY),
00128       (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD),
00129       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
00130     { EVAX_LOCAL_NAME,
00131       (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
00132       (SEC_DATA),
00133       (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
00134       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
00135     { NULL,
00136       (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
00137       (SEC_DATA),
00138       (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
00139       (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }
00140   };
00141 
00142 /* Retrieve bfd section flags by name and size.  */
00143 
00144 static flagword
00145 vms_secflag_by_name (bfd *abfd,
00146                    struct sec_flags_struct *section_flags,
00147                    char *name,
00148                    int hassize)
00149 {
00150   int i = 0;
00151 
00152   while (section_flags[i].name != NULL)
00153     {
00154       if ((PRIV (is_vax)?
00155           strcasecmp (name, section_flags[i].name):
00156           strcmp (name, section_flags[i].name)) == 0)
00157        {
00158          if (hassize)
00159            return section_flags[i].flags_hassize;
00160          else
00161            return section_flags[i].flags_always;
00162        }
00163       i++;
00164     }
00165   if (hassize)
00166     return section_flags[i].flags_hassize;
00167   return section_flags[i].flags_always;
00168 }
00169 
00170 /* Retrieve vms section flags by name and size.  */
00171 
00172 static flagword
00173 vms_esecflag_by_name (struct sec_flags_struct *section_flags,
00174                     char *name,
00175                     int hassize)
00176 {
00177   int i = 0;
00178 
00179   while (section_flags[i].name != NULL)
00180     {
00181       if (strcmp (name, section_flags[i].name) == 0)
00182        {
00183          if (hassize)
00184            return section_flags[i].vflags_hassize;
00185          else
00186            return section_flags[i].vflags_always;
00187        }
00188       i++;
00189     }
00190   if (hassize)
00191     return section_flags[i].vflags_hassize;
00192   return section_flags[i].vflags_always;
00193 }
00194 
00195 #if VMS_DEBUG
00196 
00197 struct flagdescstruct { char *name; flagword value; };
00198 
00199 /* Convert flag to printable string.  */
00200 
00201 static char *
00202 flag2str (struct flagdescstruct * flagdesc, flagword flags)
00203 {
00204   static char res[64];
00205   int next = 0;
00206 
00207   res[0] = 0;
00208   while (flagdesc->name != NULL)
00209     {
00210       if ((flags & flagdesc->value) != 0)
00211        {
00212          if (next)
00213            strcat (res, ",");
00214          else
00215            next = 1;
00216          strcat (res, flagdesc->name);
00217        }
00218       flagdesc++;
00219     }
00220   return res;
00221 }
00222 #endif
00223 
00224 /* Input routines.  */
00225 
00226 /* Process GSD/EGSD record
00227    return 0 on success, -1 on error.  */
00228 
00229 int
00230 _bfd_vms_slurp_gsd (bfd * abfd, int objtype)
00231 {
00232 #if VMS_DEBUG
00233   static struct flagdescstruct gpsflagdesc[] =
00234     {
00235       { "PIC", 0x0001 },
00236       { "LIB", 0x0002 },
00237       { "OVR", 0x0004 },
00238       { "REL", 0x0008 },
00239       { "GBL", 0x0010 },
00240       { "SHR", 0x0020 },
00241       { "EXE", 0x0040 },
00242       { "RD",  0x0080 },
00243       { "WRT", 0x0100 },
00244       { "VEC", 0x0200 },
00245       { "NOMOD", 0x0400 },
00246       { "COM", 0x0800 },
00247       { NULL, 0 }
00248     };
00249 
00250   static struct flagdescstruct gsyflagdesc[] =
00251     {
00252       { "WEAK", 0x0001 },
00253       { "DEF",  0x0002 },
00254       { "UNI",  0x0004 },
00255       { "REL",  0x0008 },
00256       { "COMM", 0x0010 },
00257       { "VECEP", 0x0020 },
00258       { "NORM", 0x0040 },
00259       { NULL, 0 }
00260     };
00261 #endif
00262 
00263   int gsd_type, gsd_size;
00264   asection *section;
00265   unsigned char *vms_rec;
00266   flagword new_flags, old_flags;
00267   char *name;
00268   asymbol *symbol;
00269   vms_symbol_entry *entry;
00270   unsigned long base_addr;
00271   unsigned long align_addr;
00272   static unsigned int psect_idx = 0;
00273 
00274 #if VMS_DEBUG
00275   vms_debug (2, "GSD/EGSD (%d/%x)\n", objtype, objtype);
00276 #endif
00277 
00278   switch (objtype)
00279     {
00280     case EOBJ_S_C_EGSD:
00281       PRIV (vms_rec) += 8;  /* Skip type, size, l_temp.  */
00282       PRIV (rec_size) -= 8;
00283       break;
00284     case OBJ_S_C_GSD:
00285       PRIV (vms_rec) += 1;
00286       PRIV (rec_size) -= 1;
00287       break;
00288     default:
00289       return -1;
00290     }
00291 
00292   /* Calculate base address for each section.  */
00293   base_addr = 0L;
00294 
00295   abfd->symcount = 0;
00296 
00297   while (PRIV (rec_size) > 0)
00298     {
00299       vms_rec = PRIV (vms_rec);
00300 
00301       if (objtype == OBJ_S_C_GSD)
00302        gsd_type = *vms_rec;
00303       else
00304        {
00305          _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size);
00306          gsd_type += EVAX_OFFSET;
00307        }
00308 
00309 #if VMS_DEBUG
00310       vms_debug (3, "gsd_type %d\n", gsd_type);
00311 #endif
00312 
00313       switch (gsd_type)
00314        {
00315        case GSD_S_C_PSC:
00316          {
00317            /* Program section definition.  */
00318            asection *old_section = 0;
00319 
00320 #if VMS_DEBUG
00321            vms_debug (4, "GSD_S_C_PSC\n");
00322 #endif
00323            /* If this section isn't a bfd section.  */
00324            if (PRIV (is_vax) && (psect_idx < (abfd->section_count-1)))
00325              {
00326               /* Check for temporary section from TIR record.  */
00327               if (psect_idx < PRIV (section_count))
00328                 old_section = PRIV (sections)[psect_idx];
00329               else
00330                 old_section = 0;
00331              }
00332 
00333            name = _bfd_vms_save_counted_string (vms_rec + 8);
00334            section = bfd_make_section (abfd, name);
00335            if (!section)
00336              {
00337               (*_bfd_error_handler) (_("bfd_make_section (%s) failed"),
00338                                    name);
00339               return -1;
00340              }
00341            old_flags = bfd_getl16 (vms_rec + 2);
00342            section->size = bfd_getl32 (vms_rec + 4);  /* allocation */
00343            new_flags = vms_secflag_by_name (abfd, vax_section_flags, name,
00344                                         section->size > 0);
00345            if (old_flags & EGPS_S_V_REL)
00346              new_flags |= SEC_RELOC;
00347            if (old_flags & GPS_S_M_OVR)
00348              new_flags |= SEC_IS_COMMON;
00349            if (!bfd_set_section_flags (abfd, section, new_flags))
00350              {
00351               (*_bfd_error_handler)
00352                 (_("bfd_set_section_flags (%s, %x) failed"),
00353                  name, new_flags);
00354               return -1;
00355              }
00356            section->alignment_power = vms_rec[1];
00357            align_addr = (1 << section->alignment_power);
00358            if ((base_addr % align_addr) != 0)
00359              base_addr += (align_addr - (base_addr % align_addr));
00360            section->vma = (bfd_vma)base_addr;
00361            base_addr += section->size;
00362 
00363            /* Global section is common symbol.  */
00364 
00365            if (old_flags & GPS_S_M_GBL)
00366              {
00367               entry = _bfd_vms_enter_symbol (abfd, name);
00368               if (entry == NULL)
00369                 {
00370                   bfd_set_error (bfd_error_no_memory);
00371                   return -1;
00372                 }
00373               symbol = entry->symbol;
00374 
00375               symbol->value = 0;
00376               symbol->section = section;
00377               symbol->flags = (BSF_GLOBAL | BSF_SECTION_SYM | BSF_OLD_COMMON);
00378              }
00379 
00380            /* Copy saved contents if old_section set.  */
00381            if (old_section != 0)
00382              {
00383               section->contents = old_section->contents;
00384               if (section->size < old_section->size)
00385                 {
00386                   (*_bfd_error_handler)
00387                     (_("Size mismatch section %s=%lx, %s=%lx"),
00388                      old_section->name,
00389                      (unsigned long) old_section->size,
00390                      section->name,
00391                      (unsigned long) section->size);
00392                   return -1;
00393                 }
00394               else if (section->size > old_section->size)
00395                 {
00396                   section->contents = bfd_realloc (old_section->contents,
00397                                                section->size);
00398                   if (section->contents == NULL)
00399                     {
00400                      bfd_set_error (bfd_error_no_memory);
00401                      return -1;
00402                     }
00403                 }
00404              }
00405            else
00406              {
00407               section->contents = bfd_zmalloc (section->size);
00408               if (section->contents == NULL)
00409                 {
00410                   bfd_set_error (bfd_error_no_memory);
00411                   return -1;
00412                 }
00413              }
00414 #if VMS_DEBUG
00415            vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ",
00416                      section->index, name, old_flags, flag2str (gpsflagdesc, old_flags));
00417            vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
00418                      section->size, section->vma, section->contents);
00419 #endif
00420 
00421            gsd_size = vms_rec[8] + 9;
00422 
00423            psect_idx++;
00424          }
00425          break;
00426 
00427        case GSD_S_C_EPM:
00428        case GSD_S_C_EPMW:
00429 #if VMS_DEBUG
00430          vms_debug (4, "gsd epm\n");
00431 #endif
00432          /* Fall through.  */
00433        case GSD_S_C_SYM:
00434        case GSD_S_C_SYMW:
00435          {
00436            int name_offset = 0, value_offset = 0;
00437 
00438            /* Symbol specification (definition or reference).  */
00439 #if VMS_DEBUG
00440            vms_debug (4, "GSD_S_C_SYM(W)\n");
00441 #endif
00442            old_flags = bfd_getl16 (vms_rec + 2);
00443            new_flags = BSF_NO_FLAGS;
00444 
00445            if (old_flags & GSY_S_M_WEAK)
00446              new_flags |= BSF_WEAK;
00447 
00448            switch (gsd_type)
00449              {
00450              case GSD_S_C_EPM:
00451               name_offset = 11;
00452               value_offset = 5;
00453               new_flags |= BSF_FUNCTION;
00454               break;
00455              case GSD_S_C_EPMW:
00456               name_offset = 12;
00457               value_offset = 6;
00458               new_flags |= BSF_FUNCTION;
00459               break;
00460              case GSD_S_C_SYM:
00461               if (old_flags & GSY_S_M_DEF)       /* Symbol definition.  */
00462                 name_offset = 9;
00463               else
00464                 name_offset = 4;
00465               value_offset = 5;
00466               break;
00467              case GSD_S_C_SYMW:
00468               if (old_flags & GSY_S_M_DEF)       /* Symbol definition.  */
00469                 name_offset = 10;
00470               else
00471                 name_offset = 5;
00472               value_offset = 6;
00473               break;
00474              }
00475 
00476            /* Save symbol in vms_symbol_table.  */
00477            entry = _bfd_vms_enter_symbol
00478              (abfd, _bfd_vms_save_counted_string (vms_rec + name_offset));
00479            if (entry == NULL)
00480              {
00481               bfd_set_error (bfd_error_no_memory);
00482               return -1;
00483              }
00484            symbol = entry->symbol;
00485 
00486            if (old_flags & GSY_S_M_DEF)
00487              {
00488               /* Symbol definition.  */
00489               int psect;
00490 
00491               symbol->value = bfd_getl32 (vms_rec + value_offset);
00492               if ((gsd_type == GSD_S_C_SYMW)
00493                   || (gsd_type == GSD_S_C_EPMW))
00494                 psect = bfd_getl16 (vms_rec + value_offset - 2);
00495               else
00496                 psect = vms_rec[value_offset-1];
00497 
00498               symbol->section = (asection *) (size_t) psect;
00499 #if VMS_DEBUG
00500               vms_debug (4, "gsd sym def #%d (%s, %d [%p], %04x=%s)\n", abfd->symcount,
00501                         symbol->name, (int)symbol->section, symbol->section, old_flags, flag2str (gsyflagdesc, old_flags));
00502 #endif
00503              }
00504            else
00505              {
00506               /* Symbol reference.  */
00507               symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
00508 #if VMS_DEBUG
00509               vms_debug (4, "gsd sym ref #%d (%s, %s [%p], %04x=%s)\n",
00510                         abfd->symcount, symbol->name, symbol->section->name,
00511                         symbol->section, old_flags, flag2str (gsyflagdesc, old_flags));
00512 #endif
00513              }
00514 
00515            gsd_size = vms_rec[name_offset] + name_offset + 1;
00516            symbol->flags = new_flags;
00517          }
00518 
00519          break;
00520 
00521        case GSD_S_C_PRO:
00522        case GSD_S_C_PROW:
00523 #if VMS_DEBUG
00524          vms_debug (4, "gsd pro\n");
00525 #endif
00526          break;
00527        case GSD_S_C_IDC:
00528 #if VMS_DEBUG
00529          vms_debug (4, "gsd idc\n");
00530 #endif
00531          break;
00532        case GSD_S_C_ENV:
00533 #if VMS_DEBUG
00534          vms_debug (4, "gsd env\n");
00535 #endif
00536          break;
00537        case GSD_S_C_LSY:
00538 #if VMS_DEBUG
00539          vms_debug (4, "gsd lsy\n");
00540 #endif
00541          break;
00542        case GSD_S_C_LEPM:
00543 #if VMS_DEBUG
00544          vms_debug (4, "gsd lepm\n");
00545 #endif
00546          break;
00547        case GSD_S_C_LPRO:
00548 #if VMS_DEBUG
00549          vms_debug (4, "gsd lpro\n");
00550 #endif
00551          break;
00552        case GSD_S_C_SPSC:
00553 #if VMS_DEBUG
00554          vms_debug (4, "gsd spsc\n");
00555 #endif
00556          break;
00557        case GSD_S_C_SYMV:
00558 #if VMS_DEBUG
00559          vms_debug (4, "gsd symv\n");
00560 #endif
00561          break;
00562        case GSD_S_C_EPMV:
00563 #if VMS_DEBUG
00564          vms_debug (4, "gsd epmv\n");
00565 #endif
00566          break;
00567        case GSD_S_C_PROV:
00568 #if VMS_DEBUG
00569          vms_debug (4, "gsd prov\n");
00570 #endif
00571          break;
00572 
00573        case EGSD_S_C_PSC + EVAX_OFFSET:
00574          {
00575            /* Program section definition.  */
00576            name = _bfd_vms_save_counted_string (vms_rec + 12);
00577            section = bfd_make_section (abfd, name);
00578            if (!section)
00579              return -1;
00580            old_flags = bfd_getl16 (vms_rec + 6);
00581            section->size = bfd_getl32 (vms_rec + 8);    /* Allocation.  */
00582            new_flags = vms_secflag_by_name (abfd, evax_section_flags, name,
00583                                         section->size > 0);
00584            if (old_flags & EGPS_S_V_REL)
00585              new_flags |= SEC_RELOC;
00586            if (!bfd_set_section_flags (abfd, section, new_flags))
00587              return -1;
00588            section->alignment_power = vms_rec[4];
00589            align_addr = (1 << section->alignment_power);
00590            if ((base_addr % align_addr) != 0)
00591              base_addr += (align_addr - (base_addr % align_addr));
00592            section->vma = (bfd_vma)base_addr;
00593            base_addr += section->size;
00594            section->contents = bfd_zmalloc (section->size);
00595            if (section->contents == NULL)
00596              return -1;
00597 #if VMS_DEBUG
00598            vms_debug (4, "egsd psc %d (%s, flags %04x=%s) ",
00599                      section->index, name, old_flags, flag2str (gpsflagdesc, old_flags));
00600            vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
00601                      section->size, section->vma, section->contents);
00602 #endif
00603          }
00604          break;
00605 
00606        case EGSD_S_C_SYM + EVAX_OFFSET:
00607          {
00608            /* Symbol specification (definition or reference).  */
00609            symbol = bfd_make_empty_symbol (abfd);
00610            if (symbol == 0)
00611              return -1;
00612 
00613            old_flags = bfd_getl16 (vms_rec + 6);
00614            new_flags = BSF_NO_FLAGS;
00615 
00616            if (old_flags & EGSY_S_V_WEAK)
00617              new_flags |= BSF_WEAK;
00618 
00619            if (vms_rec[6] & EGSY_S_V_DEF)
00620              {
00621               /* Symbol definition.  */
00622               symbol->name = _bfd_vms_save_counted_string (vms_rec + 32);
00623               if (old_flags & EGSY_S_V_NORM)
00624                 /* Proc def.  */
00625                 new_flags |= BSF_FUNCTION;
00626 
00627               symbol->value = bfd_getl64 (vms_rec + 8);
00628               symbol->section = (asection *) ((unsigned long) bfd_getl32 (vms_rec + 28));
00629 #if VMS_DEBUG
00630               vms_debug (4, "egsd sym def #%d (%s, %d, %04x=%s)\n", abfd->symcount,
00631                         symbol->name, (int) symbol->section, old_flags,
00632                         flag2str (gsyflagdesc, old_flags));
00633 #endif
00634              }
00635            else
00636              {
00637               /* Symbol reference.  */
00638               symbol->name = _bfd_vms_save_counted_string (vms_rec + 8);
00639 #if VMS_DEBUG
00640               vms_debug (4, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount,
00641                        symbol->name, old_flags, flag2str (gsyflagdesc, old_flags));
00642 #endif
00643               symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
00644              }
00645 
00646            symbol->flags = new_flags;
00647 
00648            /* Save symbol in vms_symbol_table.  */
00649            entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
00650                                                    symbol->name,
00651                                                    TRUE, FALSE);
00652            if (entry == NULL)
00653              {
00654               bfd_set_error (bfd_error_no_memory);
00655               return -1;
00656              }
00657 
00658            if (entry->symbol != NULL)
00659              {
00660               /* FIXME ?, DEC C generates this.  */
00661 #if VMS_DEBUG
00662               vms_debug (4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name);
00663 #endif
00664              }
00665            else
00666              {
00667               entry->symbol = symbol;
00668               PRIV (gsd_sym_count)++;
00669               abfd->symcount++;
00670              }
00671          }
00672          break;
00673 
00674        case EGSD_S_C_IDC + EVAX_OFFSET:
00675          break;
00676 
00677        default:
00678          (*_bfd_error_handler) (_("unknown gsd/egsd subtype %d"), gsd_type);
00679          bfd_set_error (bfd_error_bad_value);
00680          return -1;
00681        }
00682 
00683       PRIV (rec_size) -= gsd_size;
00684       PRIV (vms_rec) += gsd_size;
00685     }
00686 
00687   if (abfd->symcount > 0)
00688     abfd->flags |= HAS_SYMS;
00689 
00690   return 0;
00691 }
00692 
00693 /* Output routines.  */
00694 
00695 /* Write section and symbol directory of bfd abfd.  */
00696 
00697 int
00698 _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED)
00699 {
00700   asection *section;
00701   asymbol *symbol;
00702   unsigned int symnum;
00703   int last_index = -1;
00704   char dummy_name[10];
00705   char *sname;
00706   flagword new_flags, old_flags;
00707 
00708 #if VMS_DEBUG
00709   vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype);
00710 #endif
00711 
00712   /* Output sections.  */
00713   section = abfd->sections;
00714 #if VMS_DEBUG
00715   vms_debug (3, "%d sections found\n", abfd->section_count);
00716 #endif
00717 
00718   /* Egsd is quadword aligned.  */
00719   _bfd_vms_output_alignment (abfd, 8);
00720 
00721   _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
00722   _bfd_vms_output_long (abfd, 0);
00723   /* Prepare output for subrecords.  */
00724   _bfd_vms_output_push (abfd);
00725 
00726   while (section != 0)
00727     {
00728 #if VMS_DEBUG
00729       vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->size);
00730 #endif
00731 
00732       /* 13 bytes egsd, max 31 chars name -> should be 44 bytes.  */
00733       if (_bfd_vms_output_check (abfd, 64) < 0)
00734        {
00735          _bfd_vms_output_pop (abfd);
00736          _bfd_vms_output_end (abfd);
00737          _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
00738          _bfd_vms_output_long (abfd, 0);
00739          /* Prepare output for subrecords.  */
00740          _bfd_vms_output_push (abfd);
00741        }
00742 
00743       /* Create dummy sections to keep consecutive indices.  */
00744       while (section->index - last_index > 1)
00745        {
00746 #if VMS_DEBUG
00747          vms_debug (3, "index %d, last %d\n", section->index, last_index);
00748 #endif
00749          _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
00750          _bfd_vms_output_short (abfd, 0);
00751          _bfd_vms_output_short (abfd, 0);
00752          _bfd_vms_output_long (abfd, 0);
00753          sprintf (dummy_name, ".DUMMY%02d", last_index);
00754          _bfd_vms_output_counted (abfd, dummy_name);
00755          _bfd_vms_output_flush (abfd);
00756          last_index++;
00757        }
00758 
00759       /* Don't know if this is necessary for the linker but for now it keeps
00760         vms_slurp_gsd happy  */
00761       sname = (char *)section->name;
00762       if (*sname == '.')
00763        {
00764          sname++;
00765          if ((*sname == 't') && (strcmp (sname, "text") == 0))
00766            sname = PRIV (is_vax)?VAX_CODE_NAME:EVAX_CODE_NAME;
00767          else if ((*sname == 'd') && (strcmp (sname, "data") == 0))
00768            sname = PRIV (is_vax)?VAX_DATA_NAME:EVAX_DATA_NAME;
00769          else if ((*sname == 'b') && (strcmp (sname, "bss") == 0))
00770            sname = EVAX_BSS_NAME;
00771          else if ((*sname == 'l') && (strcmp (sname, "link") == 0))
00772            sname = EVAX_LINK_NAME;
00773          else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0))
00774            sname = EVAX_READONLY_NAME;
00775          else if ((*sname == 'l') && (strcmp (sname, "literal") == 0))
00776            sname = EVAX_LITERAL_NAME;
00777          else if ((*sname == 'c') && (strcmp (sname, "comm") == 0))
00778            sname = EVAX_COMMON_NAME;
00779          else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0))
00780            sname = EVAX_LOCAL_NAME;
00781        }
00782       else
00783        sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ);
00784 
00785       _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
00786       _bfd_vms_output_short (abfd, section->alignment_power & 0xff);
00787       if (bfd_is_com_section (section))
00788        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);
00789       else
00790        new_flags = vms_esecflag_by_name (evax_section_flags, sname,
00791                                      section->size > 0);
00792 
00793       _bfd_vms_output_short (abfd, new_flags);
00794       _bfd_vms_output_long (abfd, (unsigned long) section->size);
00795       _bfd_vms_output_counted (abfd, sname);
00796       _bfd_vms_output_flush (abfd);
00797 
00798       last_index = section->index;
00799       section = section->next;
00800     }
00801 
00802   /* Output symbols.  */
00803 #if VMS_DEBUG
00804   vms_debug (3, "%d symbols found\n", abfd->symcount);
00805 #endif
00806 
00807   bfd_set_start_address (abfd, (bfd_vma) -1);
00808 
00809   for (symnum = 0; symnum < abfd->symcount; symnum++)
00810     {
00811       char *hash;
00812 
00813       symbol = abfd->outsymbols[symnum];
00814       if (*(symbol->name) == '_')
00815        {
00816          if (strcmp (symbol->name, "__main") == 0)
00817            bfd_set_start_address (abfd, (bfd_vma)symbol->value);
00818        }
00819       old_flags = symbol->flags;
00820 
00821       if (old_flags & BSF_FILE)
00822        continue;
00823 
00824       if (((old_flags & (BSF_GLOBAL | BSF_WEAK)) == 0)  /* Not xdef...  */
00825          && (!bfd_is_und_section (symbol->section)))    /* ...and not xref.  */
00826        continue;                                 /* Dont output.  */
00827 
00828       /* 13 bytes egsd, max 64 chars name -> should be 77 bytes.  */
00829       if (_bfd_vms_output_check (abfd, 80) < 0)
00830        {
00831          _bfd_vms_output_pop (abfd);
00832          _bfd_vms_output_end (abfd);
00833          _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
00834          _bfd_vms_output_long (abfd, 0);
00835          /* Prepare output for subrecords.  */
00836          _bfd_vms_output_push (abfd);
00837        }
00838 
00839       _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1);
00840 
00841       /* Data type, alignment.  */
00842       _bfd_vms_output_short (abfd, 0);
00843 
00844       new_flags = 0;
00845 
00846       if (old_flags & BSF_WEAK)
00847        new_flags |= EGSY_S_V_WEAK;
00848       if (bfd_is_com_section (symbol->section))
00849        new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM);
00850 
00851       if (old_flags & BSF_FUNCTION)
00852        {
00853          new_flags |= EGSY_S_V_NORM;
00854          new_flags |= EGSY_S_V_REL;
00855        }
00856       if (old_flags & (BSF_GLOBAL | BSF_WEAK))
00857        {
00858          new_flags |= EGSY_S_V_DEF;
00859          if (!bfd_is_abs_section (symbol->section))
00860            new_flags |= EGSY_S_V_REL;
00861        }
00862       _bfd_vms_output_short (abfd, new_flags);
00863 
00864       if (old_flags & (BSF_GLOBAL | BSF_WEAK))
00865        {
00866          /* Symbol definition.  */
00867          uquad code_address = 0;
00868          unsigned long ca_psindx = 0;
00869          unsigned long psindx;
00870 
00871          if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
00872            {
00873              code_address = ((asymbol *) (symbol->udata.p))->value;
00874              ca_psindx = ((asymbol *) (symbol->udata.p))->section->index;
00875            }
00876          psindx = symbol->section->index;
00877 
00878          _bfd_vms_output_quad (abfd, symbol->value);
00879          _bfd_vms_output_quad (abfd, code_address);
00880          _bfd_vms_output_long (abfd, ca_psindx);
00881          _bfd_vms_output_long (abfd, psindx);
00882        }
00883       hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ);
00884       _bfd_vms_output_counted (abfd, hash);
00885 
00886       _bfd_vms_output_flush (abfd);
00887 
00888     }
00889 
00890   _bfd_vms_output_alignment (abfd, 8);
00891   _bfd_vms_output_pop (abfd);
00892   _bfd_vms_output_end (abfd);
00893 
00894   return 0;
00895 }