2009-02-23 Tristan Gingold <gingold@adacore.com>

* vms.h: Update copyright year, fix comments, reorder declarations.
	(_bfd_save_vms_section): Remove the prototype.
	(EGPS_S_V_NO_SHIFT): New constant.
	(bfd_vms_set_section_flags): New prototype.
	(EGPS_S_B_ALIGN, EGPS_S_W_FLAGS, EGPS_S_L_ALLOC, EGPS_S_B_NAMLNG): New
	constants.
	(EGSY_S_W_FLAGS): Ditto.
	(EGSY_S_V_QUAD_VAL): Ditto.
	(ESDF_S_L_VALUE, ESDF_S_L_PSINDX, ESDF_S_B_NAMLNG): Ditto.
	(EGST_S_W_FLAGS, EGST_S_Q_LP_1, EGST_S_Q_LP_2, EGST_S_L_PSINDX,
	EGST_S_B_NAMLNG): Ditto.
	(ESRF_S_B_NAMLNG): Ditto.
	(ETIR_S_C_HEADER_SIZE): Ditto.
	(EGPS_S_V_ALLOC_64BIT): Ditto.
	(DST_S_C_EPILOG): Ditto.
	(DST_S_C_SRC_SETLNUM_L, DST_S_C_SRC_SETLNUM_W) : Ditto.
	(DST_S_C_SRC_INCRLNUM_B): Ditto.
	(DST_S_B_PCLINE_UNSBYTE, DST_S_W_PCLINE_UNSWORD): Ditto.
	(DST_S_L_PCLINE_UNSLONG): Ditto.
	(DST_S_B_MODBEG_NAME, DST_S_L_RTNBEG_ADDRESS) : Ditto
	(DST_S_B_RTNBEG_NAME, DST_S_L_RTNEND_SIZE): Ditto
	(DST_S_C_SOURCE_HEADER_SIZE): Ditto.
	(DST_S_B_SRC_DF_LENGTH, DST_S_W_SRC_DF_FILEID): Ditto.
	(DST_S_B_SRC_DF_FILENAME, DST_S_B_SRC_UNSBYTE): Ditto.
	(DST_S_B_SRC_UNSBYTE): Ditto.
	(DST_S_W_SRC_UNSWORD, DST_S_L_SRC_UNSLONG): Ditto.
	Add prototypes.
	(vms_section, vms_reloc): Remove types.
	(hdr_struc): Replaced by ...
	(hdr_struct): ... new type.
	(EMH_S_W_HDRTYP, EMH_S_B_STRLVL, EMH_S_L_ARCH1): New constants.
	(EMH_S_L_ARCH2, EMH_S_L_RECSIZ, EMH_S_B_NAMLNG): Ditto.
	(EMH_DATE_LENGTH): Ditto.
	(eom_struc): Replaced by ...
	(eom_struct): ... new type.
	(EEOM_S_L_TOTAL_LPS, EEOM_S_W_COMCOD, EEOM_S_B_TFRFLG): New constants.
	(EEOM_S_L_PSINDX, EEOM_S_L_TFRADR): Ditto.
	(EIHD_S_K_MAJORID, EIHD_S_K_MINORID, EIHD_S_K_EXE): Ditto.
	(EIHD_S_L_SIZE, EIHD_S_L_ISDOFF, EIHD_S_L_SYMDBGOFF): Ditto.
	(EIHD_S_Q_SYMVVA, EIHD_S_L_IMGTYPE): Ditto.
	(EISD_S_L_EISDSIZE, EISD_S_L_SECSIZE, EISD_S_Q_VIR_ADDR): Ditto.
	(EISD_S_L_FLAGS, EISD_S_L_VBN, EISD_S_R_CONTROL): Ditto.
	(EISD_S_L_IDENT, EISD_S_T_GBLNAM): Ditto.
	(EISD_S_M_GBL, EISD_S_M_CRF, EISD_S_M_DZRO, EISD_S_M_WRT): Ditto.
	(EISD_S_M_INITALCODE, EISD_S_M_BASED, EISD_S_M_FIXUPVEC): Ditto.
	(EISD_S_M_RESIDENT, EISD_S_M_VECTOR, EISD_S_M_PROTECT): Ditto.
	(EISD_S_M_LASTCLU, EISD_S_M_EXE, EISD_S_M_NONSHRADR): Ditto.
	(EISD_S_M_QUAD_LENGTH, EISD_S_M_ALLOC_64BIT): Ditto.
	(EIHS_S_L_DSTVBN, EIHS_S_L_DSTSIZE, EIHS_S_L_GSTVBN): Ditto.
	(EIHS_S_L_GSTSIZE, EIHS_S_L_DMTVBN, EIHS_S_L_DMTBYTES): Ditto.
	(DBG_S_L_DMT_MODBEG, DBG_S_L_DST_SIZE): Ditto.
	(DBG_S_W_DMT_PSECT_COUNT, DBG_S_C_DMT_HEADER_SIZE): Ditto.
	(DBG_S_L_DMT_PSECT_START, DBG_S_L_DMT_PSECT_LENGTH)
	(DBG_S_C_DMT_PSECT_SIZE): Ditto.
	(enum file_type_enum): New type.
	(struct location_struct): Removed.
	(struct fileinfo, struct srecinfo, struct lineinfo): New types.
	(struct funcinfo, struct module): Ditto.
	(struct vms_private_data_struct): Update fields.
	(struct vms_section_data_struct): New type.

	* vms.c: Update copyright year, fix comments,
	Fix includes for DECC, add prototypes.
	(vms_initialize): Use bfd_alloc instead of bfd_zalloc and remove
	some initializers.
	Use flavour to set is_vax, location_stack is removed.
	(struct pair): Declare.
	(fill_section_ptr): Initialize variables at declaration.
	Add guard to set SECTION_SYM flag, handlde und section.
	(vms_fixup_sections): Use struct pair for fill_section_ptr argument.
	(_bfd_vms_slurp_object_records): New function, replaces previous
	vms_object_p.
	(vms_slurp_module): New function.
	(vms_slurp_image): Ditto.
	(vms_object_p): Complete rewrite.
	(vms_mkobject): Use is_vax field to slect architecture.
	(free_reloc_stream): New function.
	(vms_convert_to_var): Ditto.
	(vms_convert_to_var_1): Ditto.
	(vms_convert_to_var_unix_filename): Ditto.
	(vms_close_and_cleanup): Call free_reloc_stream, convert file to
	VAR format on VMS.
	(vms_new_section_hook): Set alignment to 0, allocate private data.
	(vms_get_section_contents): Load content.
	(vms_get_symbol_info): Handle undefined section.
	(vms_find_nearest_line): Handle.
	(alloc_reloc_stream): New function.
	(vms_slurp_reloc_table): Ditto.
	(vms_get_reloc_upper_bound): Make it real.
	(vms_canonicalize_reloc): Do the real work.
	(alpha_howto_table): Add ALPHA_R_NOP, ALPHA_R_BSR, ALPHA_R_LDA,
	ALPHA_R_BOH.
	(vms_bfd_reloc_type_lookup): Handle NOP, BSR, LDA and BOH.
	(vms_set_arch_mach): Check arch.
	(vms_set_section_contents): Copy the content after allocation.
	(vms_alpha_vec): Update object flags.

	* vms-tir.c: Update copyright year, fix comments,
	add prototypes for new functions.
	(dst_define_location): New function.
	(dst_restore_location): New function.
	(dst_retrieve_location): New function.
	(dst_check_allocation): New function.
	(image_dump): Call dst_check_allocation.
	(image_write_b): Ditto.
	(image_write_w): Ditto.
	(image_write_l): Ditto.
	(image_write_q): Ditto.
	(cmd_name): Handle STA_LW, STA_QW, STO_OFF, STO_IMM, STO_IMMR, STO_LW,
	STO_QW, OPR_ADD, CTL_SETRB, STC_LP_PSB, CTL_DFLOC, CTL_STLOC,
	CTL_STKDL.
	Call error handler instead of abort if name is not known.
	(etir_sta): Add quarter_relocs argument and set it.
	Fix cast.
	(etir_sto): Ditto.
	(etir_opr): Ditto, return FALSE in case of error.
	(etir_ctl): Add quarter_relocs argument and set it, fix cast.
	Fix CTL_DFLOC, CTL_STLOC, CTL_STKDL.
	(etir_stc): Add quarter_relocs argument and set it, fix cast.
	Fix STC_LP, STC_LP_PSB, STC_GBL and STC_CGA.
	Handle STC_LP_PSB, STC_BSR_GBL, STC_LDA_GBL, STC_BOH_GBL.
	Move STC_NOP_PS, STC_BSR_PS, STC_LDA_PS, STC_BOH_PS, STC_NBH_PS.
	Return FALSE in case of error.
	(tir_sta): Change sign of psect.
	(tir_ctl): Ditto.
	(tir_cmd): Fix cast. Makes tir_table static const.
	(etir_cmd): Add quarter_relocs argument, makes etir_table const,
	add argument to explain.
	(analyze_etir): Initialize maxptr, add quarter_relocs
	declaration, move some declarations into inner scopes.
	Handle quarter_relocs and STO_IMM.
	(_bfd_vms_slurp_tir): Use constant instead of hard-coded values.
	(_bfd_vms_slurp_relocs): New function.
	(_bfd_vms_decode_relocs): New function.
	(sto_imm): Rewritten.
	(start_first_etbt_record): New function.
	(start_another_etbt_record): Ditto.
	(etir_output_check): Ditto.
	(defer_reloc_p): Ditto.
	(_bfd_vms_write_tir): Remove nextoffset, convert a while-loop to
	a for-loop.  Correctly deals with contents, deals with .vmsdebug,
	rewritte relocations handling.
	(_bfd_vms_write_tbt): Removed.
	(_bfd_vms_write_dbg): Ditto.

	* vms-misc.c: Update copyright year, Fix comments.
	(_bfd_vms_get_header_values): Use 'size' instead of 'length'.
	(maybe_adjust_record_pointer_for_object): New function.
	(_bfd_vms_get_first_record): New function, replaces ...
	(_bfd_vms_get_record): ..  removed.
	(_bfd_vms_get_object_record): New function.
	(_bfd_vms_get_object_record): New function.
	(vms_get_remaining_object_record): New function, replaces ...
	(_bfd_vms_get_next_record): ... removed.
	(add_new_contents): Removed.
	(_bfd_save_vms_section): Removed.
	(_bfd_get_vms_section): Removed.
	(_bfd_vms_output_flush): Write in VAR format.
	(new_symbol): Don't make UND section.

	* vms-hdr.c: Update copyright year, update list of record handled.
	(_bfd_vms_slurp_hdr): rec_length renamed to rec_size.
	(_bfd_vms_write_hdr): Strip vms and unix patches,
	add comments, truncate module name at 31 characters,
	use constants instead of hard-coded value,
	write BFD version instead of a fixed string.
	(_bfd_vms_slurp_ihd): New function.
	(_bfd_vms_slurp_isd): Ditto.
	(_bfd_vms_slurp_ihs): Ditto.
	(new_module): Ditto.
	(parse_module): Ditto
	(build_module_list): Ditto.
	(module_find_nearest_line): Ditto.
	(_bfd_vms_find_nearest_dst_line): Ditto.
	(vms_slurp_debug): Ditto.
	(_bfd_vms_slurp_dbg): Ditto.
	(_bfd_vms_slurp_tbt): Ditto.
	(_bfd_vms_write_dbg): Ditto.
	(_bfd_vms_write_tbt): Ditto.

	* vms-gsd.c: Update copyright year, update list of records handled.
	(EVAX_LITERALS_NAME): New macro.
	(evax_section_flags): Add an entry for EVAX_LITERALS_NAME.
	(gpsflagdesc, gsyflagdesc): Moved out of _bfd_vms_slurp_gsd.
	(register_universal_symbol): New function and prototype.
	(_bfd_vms_slurp_gsd): Fix indentations and casts,
	improve debug messages,
	use constants instead of hard-coded value,
	fix missing endianness conversion,
	handle global symbol (SYMG).
	(bfd_vms_set_section_flags): New function.
	(_bfd_vms_write_gsd): Don't write .vmsdebug section,
	handle section literals,
	fix indentation,
	handle section bfd and vms flags,
	don't output LIB$INITIALIZE symbol,
	fix handling of weak symbols,
	fix evax vs vax procedure descriptor,
	handle absolute symbols.

	* reloc.c (BFD_RELOC_ALPHA_NOP, BFD_RELOC_ALPHA_BSR,
	BFD_RELOC_ALPHA_LDA, BFD_RELOC_ALPHA_BOH): New relocations.

	* makefile.vms (DEFS): Fix flags for VMS.

	* bfdio.c (real_fopen): Handle multiple VMS fopen attributes.

	* bfd-in2.h: Regenerated.
	* libbfd.h: Regenerated.
This commit is contained in:
Tristan Gingold
2009-02-23 09:28:43 +00:00
parent 6f43c46f4b
commit 0c37646508
12 changed files with 4076 additions and 1286 deletions

View File

@@ -1,7 +1,9 @@
/* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
/* vms-misc.c -- BFD back-end for VMS/VAX (openVMS/VAX) and
EVAX (openVMS/Alpha) files.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2007, 2008 Free Software Foundation, Inc.
2007, 2008, 2009 Free Software Foundation, Inc.
Miscellaneous functions.
Written by Klaus K"ampf (kkaempf@rmi.de)
@@ -30,22 +32,29 @@
#include "libbfd.h"
#include "vms.h"
#define MIN(a,b) ((a) < (b) ? (a) : (b))
static int hash_string PARAMS ((const char *));
static asymbol *new_symbol PARAMS ((bfd *, char *));
static void maybe_adjust_record_pointer_for_object PARAMS ((bfd *));
static int vms_get_remaining_object_record PARAMS ((bfd *, int ));
static int vms_get_remaining_image_record PARAMS ((bfd *, int ));
#if VMS_DEBUG
/* Debug functions. */
/* Debug function for all vms extensions
evaluates environment variable VMS_DEBUG for a
numerical value on the first call
all error levels below this value are printed
/* Debug function for all vms extensions evaluates environment
variable VMS_DEBUG for a numerical value on the first call all
error levels below this value are printed:
levels:
Levels:
1 toplevel bfd calls (functions from the bfd vector)
2 functions called by bfd calls
...
9 almost everything
level is also indentation level. Indentation is performed
Level is also indentation level. Indentation is performed
if level > 0. */
void
@@ -167,22 +176,23 @@ _bfd_vms_hash_newfunc (struct bfd_hash_entry *entry,
/* Object file input functions. */
/* Return type and length from record header (buf) on Alpha. */
/* Return type and size from record header (buf) on Alpha. */
void
_bfd_vms_get_header_values (bfd * abfd ATTRIBUTE_UNUSED,
unsigned char *buf,
int *type,
int *length)
int *size)
{
if (type != 0)
if (type)
*type = bfd_getl16 (buf);
buf += 2;
if (length != 0)
*length = bfd_getl16 (buf);
if (size)
*size = bfd_getl16 (buf+2);
#if VMS_DEBUG
vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
vms_debug (10, "_bfd_vms_get_header_values type %x, size %x\n",
type ? *type : 0, size ? *size : 0);
#endif
}
@@ -193,237 +203,341 @@ _bfd_vms_get_header_values (bfd * abfd ATTRIBUTE_UNUSED,
The openVMS object file has 'variable length' which means that
read() returns data in chunks of (hopefully) correct and expected
size. The linker (and other tools on vms) depend on that. Unix doesn't
know about 'formatted' files, so reading and writing such an object
file in a unix environment is not trivial.
size. The linker (and other tools on VMS) depend on that. Unix
doesn't know about 'formatted' files, so reading and writing such
an object file in a Unix environment is not trivial.
With the tool 'file' (available on all vms ftp sites), one
can view and change the attributes of a file. Changing from
With the tool 'file' (available on all VMS FTP sites), one
can view and change the attributes of a file. Changing from
'variable length' to 'fixed length, 512 bytes' reveals the
record length at the first 2 bytes of every record. The same
happens during the transfer of object files from vms to unix,
at least with ucx, dec's implementation of tcp/ip.
record size at the first 2 bytes of every record. The same
happens during the transfer of object files from VMS to Unix,
at least with UCX, the DEC implementation of TCP/IP.
The vms format repeats the length at bytes 2 & 3 of every record.
The VMS format repeats the size at bytes 2 & 3 of every record.
On the first call (file_format == FF_UNKNOWN) we check if
the first and the third byte pair (!) of the record match.
If they do it's an object file in an unix environment or with
wrong attributes (FF_FOREIGN), else we should be in a vms
If they do it's an object file in an Unix environment or with
wrong attributes (FF_FOREIGN), else we should be in a VMS
environment where read() returns the record size (FF_NATIVE).
Reading is always done in 2 steps.
First just the record header is read and the length extracted
by get_header_values,
then the read buffer is adjusted and the remaining bytes are
read in.
Reading is always done in 2 steps:
1. first just the record header is read and the size extracted,
2. then the read buffer is adjusted and the remaining bytes are
read in.
All file i/o is always done on even file positions. */
All file I/O is done on even file positions. */
#define VMS_OBJECT_ADJUSTMENT 2
static void
maybe_adjust_record_pointer_for_object (bfd *abfd)
{
/* Set the file format once for all on the first invocation. */
if (PRIV (file_format) == FF_UNKNOWN)
{
if (PRIV (vms_rec)[0] == PRIV (vms_rec)[4]
&& PRIV (vms_rec)[1] == PRIV (vms_rec)[5])
PRIV (file_format) = FF_FOREIGN;
else
PRIV (file_format) = FF_NATIVE;
}
/* The adjustment is needed only in an Unix environment. */
if (PRIV (file_format) == FF_FOREIGN)
PRIV (vms_rec) += VMS_OBJECT_ADJUSTMENT;
}
/* Get first record from file and return the file type. */
int
_bfd_vms_get_record (bfd * abfd)
_bfd_vms_get_first_record (bfd *abfd)
{
int test_len, test_start, remaining;
unsigned char *vms_buf;
unsigned int test_len;
#if VMS_DEBUG
vms_debug (8, "_bfd_vms_get_record\n");
vms_debug (8, "_bfd_vms_get_first_record\n");
#endif
/* Minimum is 6 bytes on Alpha
(2 bytes length, 2 bytes record id, 2 bytes length repeated)
On the VAX there's no length information in the record
so start with OBJ_S_C_MAXRECSIZ. */
if (PRIV (is_vax))
test_len = 0;
else
/* Minimum is 6 bytes for objects (2 bytes size, 2 bytes record id,
2 bytes size repeated) and 12 bytes for images (4 bytes major id,
4 bytes minor id, 4 bytes length). */
test_len = 12;
/* Size the main buffer. */
if (PRIV (buf_size) == 0)
{
bfd_size_type amt;
if (PRIV (is_vax))
{
amt = OBJ_S_C_MAXRECSIZ;
PRIV (file_format) = FF_VAX;
}
else
amt = 6;
PRIV (vms_buf) = bfd_malloc (amt);
/* On VAX there's no size information in the record, so
start with OBJ_S_C_MAXRECSIZ. */
bfd_size_type amt = (test_len ? test_len : OBJ_S_C_MAXRECSIZ);
PRIV (vms_buf) = (unsigned char *) bfd_malloc (amt);
PRIV (buf_size) = amt;
}
vms_buf = PRIV (vms_buf);
/* Initialize the record pointer. */
PRIV (vms_rec) = PRIV (vms_buf);
if (vms_buf == 0)
return -1;
switch (PRIV (file_format))
/* We only support modules on VAX. */
if (PRIV (is_vax))
{
case FF_UNKNOWN:
case FF_FOREIGN:
test_len = 6; /* Probe 6 bytes. */
test_start = 2; /* Where the record starts. */
break;
if (vms_get_remaining_object_record (abfd, test_len) <= 0)
return FT_UNKNOWN;
case FF_NATIVE:
test_len = 4;
test_start = 0;
break;
#if VMS_DEBUG
vms_debug (2, "file type is VAX module\n");
#endif
default:
case FF_VAX:
test_len = 0;
test_start = 0;
break;
return FT_MODULE;
}
/* Skip odd alignment byte. */
if (bfd_tell (abfd) & 1)
{
if (bfd_bread (PRIV (vms_buf), (bfd_size_type) 1, abfd) != 1)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
}
}
/* Read the record header on Alpha. */
if ((test_len != 0)
&& (bfd_bread (PRIV (vms_buf), (bfd_size_type) test_len, abfd)
!= (bfd_size_type) test_len))
if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
return FT_UNKNOWN;
}
/* Check file format on first call. */
if (PRIV (file_format) == FF_UNKNOWN)
{ /* Record length repeats ? */
if (vms_buf[0] == vms_buf[4]
&& vms_buf[1] == vms_buf[5])
{
PRIV (file_format) = FF_FOREIGN; /* Y: foreign environment. */
test_start = 2;
}
else
{
PRIV (file_format) = FF_NATIVE; /* N: native environment. */
test_start = 0;
}
/* Is it an image? */
if ((bfd_getl32 (PRIV (vms_rec)) == EIHD_S_K_MAJORID)
&& (bfd_getl32 (PRIV (vms_rec) + 4) == EIHD_S_K_MINORID))
{
if (vms_get_remaining_image_record (abfd, test_len) <= 0)
return FT_UNKNOWN;
#if VMS_DEBUG
vms_debug (2, "file type is image\n");
#endif
return FT_IMAGE;
}
/* Assume it's a module and adjust record pointer if necessary. */
maybe_adjust_record_pointer_for_object (abfd);
/* But is it really a module? */
if (bfd_getl16 (PRIV (vms_rec)) <= EOBJ_S_C_MAXRECTYP
&& bfd_getl16 (PRIV (vms_rec) + 2) <= EOBJ_S_C_MAXRECSIZ)
{
if (vms_get_remaining_object_record (abfd, test_len) <= 0)
return FT_UNKNOWN;
#if VMS_DEBUG
vms_debug (2, "file type is module\n");
#endif
return FT_MODULE;
}
#if VMS_DEBUG
vms_debug (2, "file type is unknown\n");
#endif
return FT_UNKNOWN;
}
/* Implement step #1 of the object record reading procedure.
Return the record type or -1 on failure. */
int
_bfd_vms_get_object_record (bfd *abfd)
{
unsigned int test_len;
int type;
#if VMS_DEBUG
vms_debug (8, "_bfd_vms_get_obj_record\n");
#endif
if (PRIV (is_vax))
test_len = 0;
else
{
/* See _bfd_vms_get_first_record. */
test_len = 6;
/* Skip odd alignment byte. */
if (bfd_tell (abfd) & 1)
{
if (bfd_bread (PRIV (vms_buf), 1, abfd) != 1)
{
bfd_set_error (bfd_error_file_truncated);
return -1;
}
}
/* Read the record header */
if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
{
bfd_set_error (bfd_error_file_truncated);
return -1;
}
/* Reset the record pointer. */
PRIV (vms_rec) = PRIV (vms_buf);
maybe_adjust_record_pointer_for_object (abfd);
}
if (vms_get_remaining_object_record (abfd, test_len) <= 0)
return -1;
if (PRIV (is_vax))
type = PRIV (vms_rec) [0];
else
type = bfd_getl16 (PRIV (vms_rec));
#if VMS_DEBUG
vms_debug (8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n",
PRIV (vms_rec), PRIV (rec_size), type);
#endif
return type;
}
/* Implement step #2 of the object record reading procedure.
Return the size of the record or 0 on failure. */
static int
vms_get_remaining_object_record (bfd *abfd, int read_so_far)
{
#if VMS_DEBUG
vms_debug (8, "vms_get_remaining_obj_record\n");
#endif
if (PRIV (is_vax))
{
PRIV (rec_length) = bfd_bread (vms_buf, (bfd_size_type) PRIV (buf_size),
abfd);
if (PRIV (rec_length) <= 0)
if (read_so_far != 0)
abort ();
PRIV (rec_size) = bfd_bread (PRIV (vms_buf), PRIV (buf_size), abfd);
if (PRIV (rec_size) <= 0)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
}
PRIV (vms_rec) = vms_buf;
/* Reset the record pointer. */
PRIV (vms_rec) = PRIV (vms_buf);
}
else
{
/* Alpha. */
/* Extract vms record length. */
unsigned int to_read;
_bfd_vms_get_header_values (abfd, vms_buf + test_start, NULL,
& PRIV (rec_length));
/* Extract record size. */
PRIV (rec_size) = bfd_getl16 (PRIV (vms_rec) + 2);
if (PRIV (rec_length) <= 0)
if (PRIV (rec_size) <= 0)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
}
/* That's what the linker manual says. */
if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ)
if (PRIV (rec_size) > EOBJ_S_C_MAXRECSIZ)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
}
/* Adjust the buffer. */
/* Take into account object adjustment. */
to_read = PRIV (rec_size);
if (PRIV (file_format) == FF_FOREIGN)
to_read += VMS_OBJECT_ADJUSTMENT;
if (PRIV (rec_length) > PRIV (buf_size))
/* Adjust the buffer. */
if (to_read > PRIV (buf_size))
{
PRIV (vms_buf) = bfd_realloc_or_free (vms_buf,
(bfd_size_type) PRIV (rec_length));
vms_buf = PRIV (vms_buf);
if (vms_buf == 0)
return -1;
PRIV (buf_size) = PRIV (rec_length);
PRIV (vms_buf)
= (unsigned char *) bfd_realloc (PRIV (vms_buf), to_read);
if (PRIV (vms_buf) == NULL)
return 0;
PRIV (buf_size) = to_read;
}
/* Read the remaining record. */
remaining = PRIV (rec_length) - test_len + test_start;
to_read -= read_so_far;
#if VMS_DEBUG
vms_debug (10, "bfd_bread remaining %d\n", remaining);
vms_debug (8, "vms_get_remaining_obj_record: to_read %d\n", to_read);
#endif
if (bfd_bread (vms_buf + test_len, (bfd_size_type) remaining, abfd) !=
(bfd_size_type) remaining)
if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
}
PRIV (vms_rec) = vms_buf + test_start;
/* Reset the record pointer. */
PRIV (vms_rec) = PRIV (vms_buf);
maybe_adjust_record_pointer_for_object (abfd);
}
#if VMS_DEBUG
vms_debug (11, "bfd_bread rec_length %d\n", PRIV (rec_length));
vms_debug (8, "vms_get_remaining_obj_record: size %d\n", PRIV (rec_size));
#endif
return PRIV (rec_length);
return PRIV (rec_size);
}
/* Get next vms record from file
update vms_rec and rec_length to new (remaining) values. */
/* Implement step #2 of the record reading procedure for images.
Return the size of the record or 0 on failure. */
int
_bfd_vms_next_record (bfd * abfd)
static int
vms_get_remaining_image_record (bfd *abfd, int read_so_far)
{
#if VMS_DEBUG
vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
PRIV (rec_length), PRIV (rec_size));
#endif
unsigned int to_read;
int remaining;
if (PRIV (rec_length) > 0)
PRIV (vms_rec) += PRIV (rec_size);
else
/* Extract record size. */
PRIV (rec_size) = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE);
if (PRIV (rec_size) > PRIV (buf_size))
{
if (_bfd_vms_get_record (abfd) <= 0)
return -1;
PRIV (vms_buf) = bfd_realloc (PRIV (vms_buf), PRIV (rec_size));
if (PRIV (vms_buf) == NULL)
{
bfd_set_error (bfd_error_no_memory);
return 0;
}
PRIV (buf_size) = PRIV (rec_size);
}
if (!PRIV (vms_rec) || !PRIV (vms_buf)
|| PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
return -1;
/* Read the remaining record. */
remaining = PRIV (rec_size) - read_so_far;
to_read = MIN (VMS_BLOCK_SIZE - read_so_far, remaining);
if (PRIV (is_vax))
while (remaining > 0)
{
PRIV (rec_type) = *(PRIV (vms_rec));
PRIV (rec_size) = PRIV (rec_length);
if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
{
bfd_set_error (bfd_error_file_truncated);
return 0;
}
read_so_far += to_read;
remaining -= to_read;
/* Eat trailing 0xff's. */
if (remaining > 0)
while (PRIV (vms_buf) [read_so_far - 1] == 0xff)
read_so_far--;
to_read = MIN (VMS_BLOCK_SIZE, remaining);
}
else
_bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type),
&PRIV (rec_size));
PRIV (rec_length) -= PRIV (rec_size);
/* Reset the record pointer. */
PRIV (vms_rec) = PRIV (vms_buf);
#if VMS_DEBUG
vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length),
PRIV (rec_type));
#endif
return PRIV (rec_type);
return PRIV (rec_size);
}
/* Copy sized string (string with fixed length) to new allocated area
size is string length (size of record) */
/* Copy sized string (string with fixed size) to new allocated area
size is string size (size of record) */
char *
_bfd_vms_save_sized_string (unsigned char *str, int size)
@@ -438,8 +552,8 @@ _bfd_vms_save_sized_string (unsigned char *str, int size)
return newstr;
}
/* Copy counted string (string with length at first byte) to new allocated area
ptr points to length byte on entry */
/* Copy counted string (string with size at first byte) to new allocated area
ptr points to size byte on entry */
char *
_bfd_vms_save_counted_string (unsigned char *ptr)
@@ -501,83 +615,12 @@ _bfd_vms_pop (bfd * abfd, int *psect)
return value;
}
/* Object file output functions. */
/* GAS tends to write sections in little chunks (bfd_set_section_contents)
which we can't use directly. So we save the little chunks in linked
lists (one per section) and write them later. */
/* Add a new vms_section structure to vms_section_table
- forward chaining -. */
static vms_section *
add_new_contents (bfd * abfd, sec_ptr section)
{
vms_section *sptr, *newptr;
sptr = PRIV (vms_section_table)[section->index];
if (sptr != NULL)
return sptr;
newptr = bfd_alloc (abfd, (bfd_size_type) sizeof (vms_section));
if (newptr == NULL)
return NULL;
newptr->contents = bfd_alloc (abfd, section->size);
if (newptr->contents == NULL)
return NULL;
newptr->offset = 0;
newptr->size = section->size;
newptr->next = 0;
PRIV (vms_section_table)[section->index] = newptr;
return newptr;
}
/* Save section data & offset to a vms_section structure
vms_section_table[] holds the vms_section chain. */
bfd_boolean
_bfd_save_vms_section (bfd * abfd,
sec_ptr section,
const void * data,
file_ptr offset,
bfd_size_type count)
{
vms_section *sptr;
if (section->index >= VMS_SECTION_COUNT)
{
bfd_set_error (bfd_error_nonrepresentable_section);
return FALSE;
}
if (count == (bfd_size_type)0)
return TRUE;
sptr = add_new_contents (abfd, section);
if (sptr == NULL)
return FALSE;
memcpy (sptr->contents + offset, data, (size_t) count);
return TRUE;
}
/* Get vms_section pointer to saved contents for section # index */
vms_section *
_bfd_get_vms_section (bfd * abfd, int index)
{
if (index >= VMS_SECTION_COUNT)
{
bfd_set_error (bfd_error_nonrepresentable_section);
return NULL;
}
return PRIV (vms_section_table)[index];
}
/* Object output routines. */
/* Begin new record or record header
write 2 bytes rectype
write 2 bytes record length (filled in at flush)
write 2 bytes header type (ommitted if rechead == -1). */
write 2 bytes header type (ommitted if rechead == -1). */
void
_bfd_vms_output_begin (bfd * abfd, int rectype, int rechead)
@@ -691,18 +734,11 @@ _bfd_vms_output_flush (bfd * abfd)
if (PRIV (push_level) == 0)
{
if (0
#ifndef VMS
/* Write length first, see FF_FOREIGN in the input routines. */
|| fwrite (PRIV (output_buf) + 2, 2, 1,
(FILE *) abfd->iostream) != 1
#endif
|| (real_size != 0
&& fwrite (PRIV (output_buf), (size_t) real_size, 1,
(FILE *) abfd->iostream) != 1))
/* FIXME: Return error status. */
abort ();
/* File is open in undefined (UDF) format on VMS, but ultimately will be
converted to variable length (VAR) format. VAR format has a length
word first which must be explicitly output in UDF format. */
bfd_bwrite (PRIV (output_buf) + 2, 2, abfd);
bfd_bwrite (PRIV (output_buf), (size_t) real_size, abfd);
PRIV (output_size) = 0;
}
else
@@ -948,7 +984,7 @@ new_symbol (bfd * abfd, char *name)
if (symbol == 0)
return symbol;
symbol->name = name;
symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
symbol->section = (asection *)(unsigned long)-1;
return symbol;
}