binutils-gdb/bfd/vms-hdr.c

379 lines
9.4 KiB
C
Raw Blame History

/* vms-hdr.c -- BFD back-end for VMS/VAX (openVMS/VAX) and
EVAX (openVMS/Alpha) files.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006
Free Software Foundation, Inc.
HDR record handling functions
EMH record handling functions
and
EOM record handling functions
EEOM record handling functions
Written by Klaus K"ampf (kkaempf@rmi.de)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "bfd.h"
#include "bfdver.h"
#include "sysdep.h"
#include "bfdlink.h"
#include "safe-ctype.h"
#include "libbfd.h"
#include "vms.h"
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
/* Read & process emh record
return 0 on success, -1 on error. */
int
_bfd_vms_slurp_hdr (bfd *abfd, int objtype)
{
unsigned char *ptr;
unsigned char *vms_rec;
int subtype;
vms_rec = PRIV(vms_rec);
#if VMS_DEBUG
vms_debug(2, "HDR/EMH\n");
#endif
switch (objtype)
{
case OBJ_S_C_HDR:
subtype = vms_rec[1];
break;
case EOBJ_S_C_EMH:
subtype = bfd_getl16 (vms_rec + 4) + EVAX_OFFSET;
break;
default:
subtype = -1;
}
#if VMS_DEBUG
vms_debug(3, "subtype %d\n", subtype);
#endif
switch (subtype)
{
case MHD_S_C_MHD:
/* Module header. */
PRIV (hdr_data).hdr_b_strlvl = vms_rec[2];
PRIV (hdr_data).hdr_l_recsiz = bfd_getl16 (vms_rec + 3);
PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 5);
ptr = vms_rec + 5 + vms_rec[5] + 1;
PRIV (hdr_data).hdr_t_version = _bfd_vms_save_counted_string (ptr);
ptr += *ptr + 1;
PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
break;
case MHD_S_C_LNM:
PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
break;
case MHD_S_C_SRC:
PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
break;
case MHD_S_C_TTL:
PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2));
break;
case EMH_S_C_MHD + EVAX_OFFSET:
/* Module header. */
PRIV (hdr_data).hdr_b_strlvl = vms_rec[6];
PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8);
PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12);
PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16);
PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 20);
ptr = vms_rec + 20 + vms_rec[20] + 1;
PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr);
ptr += *ptr + 1;
PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
break;
case EMH_S_C_LNM + EVAX_OFFSET:
PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6));
break;
case EMH_S_C_SRC + EVAX_OFFSET:
PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6));
break;
case EMH_S_C_TTL + EVAX_OFFSET:
PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6));
break;
case MHD_S_C_CPR:
case MHD_S_C_MTC:
case MHD_S_C_GTX:
case EMH_S_C_CPR + EVAX_OFFSET:
case EMH_S_C_MTC + EVAX_OFFSET:
case EMH_S_C_GTX + EVAX_OFFSET:
break;
default:
bfd_set_error (bfd_error_wrong_format);
return -1;
}
return 0;
}
/* Output routines. */
/* Manufacture a VMS like time on a unix based system.
stolen from obj-vms.c. */
static unsigned char *
get_vms_time_string (void)
{
static unsigned char tbuf[18];
#ifndef VMS
#include <time.h>
char *pnt;
time_t timeb;
time (& timeb);
pnt = ctime (&timeb);
pnt[3] = 0;
pnt[7] = 0;
pnt[10] = 0;
pnt[16] = 0;
pnt[24] = 0;
sprintf ((char *) tbuf, "%2s-%3s-%s %s",
pnt + 8, pnt + 4, pnt + 20, pnt + 11);
#else
#include <starlet.h>
struct
{
int Size;
unsigned char *Ptr;
} Descriptor;
Descriptor.Size = 17;
Descriptor.Ptr = tbuf;
SYS$ASCTIM (0, &Descriptor, 0, 0);
#endif /* not VMS */
#if VMS_DEBUG
vms_debug (6, "vmstimestring:'%s'\n", tbuf);
#endif
return tbuf;
}
/* Write object header for bfd abfd. */
int
_bfd_vms_write_hdr (bfd *abfd, int objtype)
{
asymbol *symbol;
unsigned int symnum;
int had_case = 0;
int had_file = 0;
#if VMS_DEBUG
vms_debug (2, "vms_write_hdr (%p)\n", abfd);
#endif
_bfd_vms_output_alignment (abfd, 2);
/* MHD. */
if (objtype != OBJ_S_C_HDR)
{
_bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_MHD);
_bfd_vms_output_short (abfd, EOBJ_S_C_STRLVL);
_bfd_vms_output_long (abfd, 0);
_bfd_vms_output_long (abfd, 0);
_bfd_vms_output_long (abfd, MAX_OUTREC_SIZE);
}
if (bfd_get_filename (abfd) != 0)
{
/* Strip path and suffix information. */
char *fname, *fout, *fptr;
fptr = bfd_get_filename (abfd);
fname = alloca (strlen (fptr) + 1);
strcpy (fname, fptr);
fout = strrchr (fname, ']');
if (fout == 0)
fout = strchr (fname, ':');
if (fout != 0)
fout++;
else
fout = fname;
/* Strip .obj suffix. */
fptr = strrchr (fname, '.');
if ((fptr != 0)
&& (strcasecmp (fptr, ".OBJ") == 0))
*fptr = 0;
fptr = fout;
while (*fptr != 0)
{
*fptr = TOUPPER (*fptr);
fptr++;
if ((*fptr == ';')
|| ((fptr - fout) > 31))
*fptr = 0;
}
_bfd_vms_output_counted (abfd, fout);
}
else
_bfd_vms_output_counted (abfd, "NONAME");
_bfd_vms_output_counted (abfd, BFD_VERSION_STRING);
_bfd_vms_output_dump (abfd, get_vms_time_string (), 17);
_bfd_vms_output_fill (abfd, 0, 17);
_bfd_vms_output_flush (abfd);
/* LMN. */
_bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_LNM);
_bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("GAS proGIS"));
_bfd_vms_output_flush (abfd);
/* SRC. */
_bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_SRC);
for (symnum = 0; symnum < abfd->symcount; symnum++)
{
symbol = abfd->outsymbols[symnum];
if (symbol->flags & BSF_FILE)
{
if (CONST_STRNEQ ((char *)symbol->name, "<CASE:"))
{
PRIV (flag_hash_long_names) = symbol->name[6] - '0';
PRIV (flag_show_after_trunc) = symbol->name[7] - '0';
if (had_file)
break;
had_case = 1;
continue;
}
_bfd_vms_output_dump (abfd, (unsigned char *) symbol->name,
(int) strlen (symbol->name));
if (had_case)
break;
had_file = 1;
}
}
if (symnum == abfd->symcount)
_bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("noname"));
_bfd_vms_output_flush (abfd);
/* TTL. */
_bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_TTL);
_bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("TTL"));
_bfd_vms_output_flush (abfd);
/* CPR. */
_bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_CPR);
_bfd_vms_output_dump (abfd,
(unsigned char *)"GNU BFD ported by Klaus K<>mpf 1994-1996",
39);
_bfd_vms_output_flush (abfd);
return 0;
}
/* Process EOM/EEOM record
return 0 on success, -1 on error. */
int
_bfd_vms_slurp_eom (bfd *abfd, int objtype)
{
unsigned char *vms_rec;
#if VMS_DEBUG
vms_debug(2, "EOM/EEOM\n");
#endif
vms_rec = PRIV (vms_rec);
if ((objtype == OBJ_S_C_EOM)
|| (objtype == OBJ_S_C_EOMW))
{
}
else
{
PRIV (eom_data).eom_l_total_lps = bfd_getl32 (vms_rec + 4);
PRIV (eom_data).eom_b_comcod = *(vms_rec + 8);
if (PRIV (eom_data).eom_b_comcod > 1)
{
(*_bfd_error_handler) (_("Object module NOT error-free !\n"));
bfd_set_error (bfd_error_bad_value);
return -1;
}
PRIV (eom_data).eom_has_transfer = FALSE;
if (PRIV (rec_size) > 10)
{
PRIV (eom_data).eom_has_transfer = TRUE;
PRIV (eom_data).eom_b_tfrflg = *(vms_rec + 9);
PRIV (eom_data).eom_l_psindx = bfd_getl32 (vms_rec + 12);
PRIV (eom_data).eom_l_tfradr = bfd_getl32 (vms_rec + 16);
abfd->start_address = PRIV (eom_data).eom_l_tfradr;
}
}
return 0;
}
/* Write eom record for bfd abfd. */
int
_bfd_vms_write_eom (bfd *abfd, int objtype)
{
#if VMS_DEBUG
vms_debug (2, "vms_write_eom (%p, %d)\n", abfd, objtype);
#endif
_bfd_vms_output_begin (abfd, objtype, -1);
_bfd_vms_output_long (abfd, (unsigned long) (PRIV (vms_linkage_index) >> 1));
_bfd_vms_output_byte (abfd, 0); /* Completion code. */
_bfd_vms_output_byte (abfd, 0); /* Fill byte. */
if (bfd_get_start_address (abfd) != (bfd_vma)-1)
{
asection *section;
section = bfd_get_section_by_name (abfd, ".link");
if (section == 0)
{
bfd_set_error (bfd_error_nonrepresentable_section);
return -1;
}
_bfd_vms_output_short (abfd, 0);
_bfd_vms_output_long (abfd, (unsigned long) (section->index));
_bfd_vms_output_long (abfd,
(unsigned long) bfd_get_start_address (abfd));
_bfd_vms_output_long (abfd, 0);
}
_bfd_vms_output_end (abfd);
return 0;
}