Back to index

cell-binutils  2.17cvs20070401
vms-hdr.c
Go to the documentation of this file.
00001 /* vms-hdr.c -- BFD back-end for VMS/VAX (openVMS/VAX) and
00002    EVAX (openVMS/Alpha) files.
00003    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006
00004    Free Software Foundation, Inc.
00005 
00006    HDR record handling functions
00007    EMH record handling functions
00008    and
00009    EOM record handling functions
00010    EEOM record handling functions
00011 
00012    Written by Klaus K"ampf (kkaempf@rmi.de)
00013 
00014    This program is free software; you can redistribute it and/or modify
00015    it under the terms of the GNU General Public License as published by
00016    the Free Software Foundation; either version 2 of the License, or
00017    (at your option) any later version.
00018 
00019    This program is distributed in the hope that it will be useful,
00020    but WITHOUT ANY WARRANTY; without even the implied warranty of
00021    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022    GNU General Public License for more details.
00023 
00024    You should have received a copy of the GNU General Public License
00025    along with this program; if not, write to the Free Software
00026    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00027 
00028 #include "bfd.h"
00029 #include "bfdver.h"
00030 #include "sysdep.h"
00031 #include "bfdlink.h"
00032 #include "safe-ctype.h"
00033 #include "libbfd.h"
00034 
00035 #include "vms.h"
00036 
00037 #ifdef HAVE_ALLOCA_H
00038 #include <alloca.h>
00039 #endif
00040 
00041 /* Read & process emh record
00042    return 0 on success, -1 on error.  */
00043 
00044 int
00045 _bfd_vms_slurp_hdr (bfd *abfd, int objtype)
00046 {
00047   unsigned char *ptr;
00048   unsigned char *vms_rec;
00049   int subtype;
00050 
00051   vms_rec = PRIV(vms_rec);
00052 
00053 #if VMS_DEBUG
00054   vms_debug(2, "HDR/EMH\n");
00055 #endif
00056 
00057   switch (objtype)
00058     {
00059     case OBJ_S_C_HDR:
00060       subtype = vms_rec[1];
00061       break;
00062     case EOBJ_S_C_EMH:
00063       subtype = bfd_getl16 (vms_rec + 4) + EVAX_OFFSET;
00064       break;
00065     default:
00066       subtype = -1;
00067     }
00068 
00069 #if VMS_DEBUG
00070   vms_debug(3, "subtype %d\n", subtype);
00071 #endif
00072 
00073   switch (subtype)
00074     {
00075     case MHD_S_C_MHD:
00076       /* Module header.  */
00077       PRIV (hdr_data).hdr_b_strlvl = vms_rec[2];
00078       PRIV (hdr_data).hdr_l_recsiz = bfd_getl16 (vms_rec + 3);
00079       PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 5);
00080       ptr = vms_rec + 5 + vms_rec[5] + 1;
00081       PRIV (hdr_data).hdr_t_version = _bfd_vms_save_counted_string (ptr);
00082       ptr += *ptr + 1;
00083       PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
00084       break;
00085 
00086     case MHD_S_C_LNM:
00087       PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
00088       break;
00089 
00090     case MHD_S_C_SRC:
00091       PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
00092       break;
00093 
00094     case MHD_S_C_TTL:
00095       PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
00096       break;
00097 
00098     case EMH_S_C_MHD + EVAX_OFFSET:
00099       /* Module header.  */
00100       PRIV (hdr_data).hdr_b_strlvl = vms_rec[6];
00101       PRIV (hdr_data).hdr_l_arch1  = bfd_getl32 (vms_rec + 8);
00102       PRIV (hdr_data).hdr_l_arch2  = bfd_getl32 (vms_rec + 12);
00103       PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16);
00104       PRIV (hdr_data).hdr_t_name   = _bfd_vms_save_counted_string (vms_rec + 20);
00105       ptr = vms_rec + 20 + vms_rec[20] + 1;
00106       PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr);
00107       ptr += *ptr + 1;
00108       PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
00109       break;
00110 
00111     case EMH_S_C_LNM + EVAX_OFFSET:
00112       PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6));
00113       break;
00114 
00115     case EMH_S_C_SRC + EVAX_OFFSET:
00116       PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6));
00117       break;
00118 
00119     case EMH_S_C_TTL + EVAX_OFFSET:
00120       PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6));
00121       break;
00122 
00123     case MHD_S_C_CPR:
00124     case MHD_S_C_MTC:
00125     case MHD_S_C_GTX:
00126     case EMH_S_C_CPR + EVAX_OFFSET:
00127     case EMH_S_C_MTC + EVAX_OFFSET:
00128     case EMH_S_C_GTX + EVAX_OFFSET:
00129       break;
00130 
00131     default:
00132       bfd_set_error (bfd_error_wrong_format);
00133       return -1;
00134     }
00135 
00136   return 0;
00137 }
00138 
00139 /* Output routines.  */
00140 
00141 /* Manufacture a VMS like time on a unix based system.
00142    stolen from obj-vms.c.  */
00143 
00144 static unsigned char *
00145 get_vms_time_string (void)
00146 {
00147   static unsigned char tbuf[18];
00148 #ifndef VMS
00149 #include <time.h>
00150 
00151   char *pnt;
00152   time_t timeb;
00153 
00154   time (& timeb);
00155   pnt = ctime (&timeb);
00156   pnt[3] = 0;
00157   pnt[7] = 0;
00158   pnt[10] = 0;
00159   pnt[16] = 0;
00160   pnt[24] = 0;
00161   sprintf ((char *) tbuf, "%2s-%3s-%s %s",
00162           pnt + 8, pnt + 4, pnt + 20, pnt + 11);
00163 #else
00164 #include <starlet.h>
00165   struct
00166   {
00167     int Size;
00168     unsigned char *Ptr;
00169   } Descriptor;
00170   Descriptor.Size = 17;
00171   Descriptor.Ptr = tbuf;
00172   SYS$ASCTIM (0, &Descriptor, 0, 0);
00173 #endif /* not VMS */
00174 
00175 #if VMS_DEBUG
00176   vms_debug (6, "vmstimestring:'%s'\n", tbuf);
00177 #endif
00178 
00179   return tbuf;
00180 }
00181 
00182 /* Write object header for bfd abfd.  */
00183 
00184 int
00185 _bfd_vms_write_hdr (bfd *abfd, int objtype)
00186 {
00187   asymbol *symbol;
00188   unsigned int symnum;
00189   int had_case = 0;
00190   int had_file = 0;
00191 
00192 #if VMS_DEBUG
00193   vms_debug (2, "vms_write_hdr (%p)\n", abfd);
00194 #endif
00195 
00196   _bfd_vms_output_alignment (abfd, 2);
00197 
00198   /* MHD.  */
00199   if (objtype != OBJ_S_C_HDR)
00200     {
00201       _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_MHD);
00202       _bfd_vms_output_short (abfd, EOBJ_S_C_STRLVL);
00203       _bfd_vms_output_long (abfd, 0);
00204       _bfd_vms_output_long (abfd, 0);
00205       _bfd_vms_output_long (abfd, MAX_OUTREC_SIZE);
00206     }
00207 
00208   if (bfd_get_filename (abfd) != 0)
00209     {
00210       /* Strip path and suffix information.  */
00211       char *fname, *fout, *fptr;
00212 
00213       fptr = bfd_get_filename (abfd);
00214       fname = alloca (strlen (fptr) + 1);
00215       strcpy (fname, fptr);
00216       fout = strrchr (fname, ']');
00217       if (fout == 0)
00218        fout = strchr (fname, ':');
00219       if (fout != 0)
00220        fout++;
00221       else
00222        fout = fname;
00223 
00224       /* Strip .obj suffix.  */
00225       fptr = strrchr (fname, '.');
00226       if ((fptr != 0)
00227          && (strcasecmp (fptr, ".OBJ") == 0))
00228        *fptr = 0;
00229 
00230       fptr = fout;
00231       while (*fptr != 0)
00232        {
00233          *fptr = TOUPPER (*fptr);
00234          fptr++;
00235          if ((*fptr == ';')
00236             || ((fptr - fout) > 31))
00237            *fptr = 0;
00238        }
00239       _bfd_vms_output_counted (abfd, fout);
00240     }
00241   else
00242     _bfd_vms_output_counted (abfd, "NONAME");
00243 
00244   _bfd_vms_output_counted (abfd, BFD_VERSION_STRING);
00245   _bfd_vms_output_dump (abfd, get_vms_time_string (), 17);
00246   _bfd_vms_output_fill (abfd, 0, 17);
00247   _bfd_vms_output_flush (abfd);
00248 
00249   /* LMN.  */
00250   _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_LNM);
00251   _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("GAS proGIS"));
00252   _bfd_vms_output_flush (abfd);
00253 
00254   /* SRC.  */
00255   _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_SRC);
00256 
00257   for (symnum = 0; symnum < abfd->symcount; symnum++)
00258     {
00259       symbol = abfd->outsymbols[symnum];
00260 
00261       if (symbol->flags & BSF_FILE)
00262        {
00263          if (CONST_STRNEQ ((char *)symbol->name, "<CASE:"))
00264            {
00265              PRIV (flag_hash_long_names) = symbol->name[6] - '0';
00266              PRIV (flag_show_after_trunc) = symbol->name[7] - '0';
00267 
00268              if (had_file)
00269               break;
00270              had_case = 1;
00271              continue;
00272            }
00273 
00274          _bfd_vms_output_dump (abfd, (unsigned char *) symbol->name,
00275                             (int) strlen (symbol->name));
00276          if (had_case)
00277            break;
00278          had_file = 1;
00279        }
00280     }
00281 
00282   if (symnum == abfd->symcount)
00283     _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("noname"));
00284 
00285   _bfd_vms_output_flush (abfd);
00286 
00287   /* TTL.  */
00288   _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_TTL);
00289   _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("TTL"));
00290   _bfd_vms_output_flush (abfd);
00291 
00292   /* CPR.  */
00293   _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_CPR);
00294   _bfd_vms_output_dump (abfd,
00295                       (unsigned char *)"GNU BFD ported by Klaus Kämpf 1994-1996",
00296                       39);
00297   _bfd_vms_output_flush (abfd);
00298 
00299   return 0;
00300 }
00301 
00302 /* Process EOM/EEOM record
00303    return 0 on success, -1 on error.  */
00304 
00305 int
00306 _bfd_vms_slurp_eom (bfd *abfd, int objtype)
00307 {
00308   unsigned char *vms_rec;
00309 
00310 #if VMS_DEBUG
00311   vms_debug(2, "EOM/EEOM\n");
00312 #endif
00313 
00314   vms_rec = PRIV (vms_rec);
00315 
00316   if ((objtype == OBJ_S_C_EOM)
00317      || (objtype == OBJ_S_C_EOMW))
00318     {
00319     }
00320   else
00321     {
00322       PRIV (eom_data).eom_l_total_lps = bfd_getl32 (vms_rec + 4);
00323       PRIV (eom_data).eom_b_comcod = *(vms_rec + 8);
00324 
00325       if (PRIV (eom_data).eom_b_comcod > 1)
00326        {
00327          (*_bfd_error_handler) (_("Object module NOT error-free !\n"));
00328          bfd_set_error (bfd_error_bad_value);
00329          return -1;
00330        }
00331       PRIV (eom_data).eom_has_transfer = FALSE;
00332       if (PRIV (rec_size) > 10)
00333        {
00334           PRIV (eom_data).eom_has_transfer = TRUE;
00335           PRIV (eom_data).eom_b_tfrflg = *(vms_rec + 9);
00336           PRIV (eom_data).eom_l_psindx = bfd_getl32 (vms_rec + 12);
00337           PRIV (eom_data).eom_l_tfradr = bfd_getl32 (vms_rec + 16);
00338 
00339           abfd->start_address = PRIV (eom_data).eom_l_tfradr;
00340        }
00341     }
00342   return 0;
00343 }
00344 
00345 /* Write eom record for bfd abfd.  */
00346 
00347 int
00348 _bfd_vms_write_eom (bfd *abfd, int objtype)
00349 {
00350 #if VMS_DEBUG
00351   vms_debug (2, "vms_write_eom (%p, %d)\n", abfd, objtype);
00352 #endif
00353 
00354   _bfd_vms_output_begin (abfd, objtype, -1);
00355   _bfd_vms_output_long (abfd, (unsigned long) (PRIV (vms_linkage_index) >> 1));
00356   _bfd_vms_output_byte (abfd, 0);  /* Completion code.  */
00357   _bfd_vms_output_byte (abfd, 0);  /* Fill byte.  */
00358 
00359   if (bfd_get_start_address (abfd) != (bfd_vma)-1)
00360     {
00361       asection *section;
00362 
00363       section = bfd_get_section_by_name (abfd, ".link");
00364       if (section == 0)
00365        {
00366          bfd_set_error (bfd_error_nonrepresentable_section);
00367          return -1;
00368        }
00369       _bfd_vms_output_short (abfd, 0);
00370       _bfd_vms_output_long (abfd, (unsigned long) (section->index));
00371       _bfd_vms_output_long (abfd,
00372                           (unsigned long) bfd_get_start_address (abfd));
00373       _bfd_vms_output_long (abfd, 0);
00374     }
00375 
00376   _bfd_vms_output_end (abfd);
00377   return 0;
00378 }