X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fvms-misc.c;h=94a13c736b7c858004e732b71e6045cab6b23611;hb=5b677558bc6c7b2477bb33c709e6017e68e7ae8c;hp=67cc25adc065efa5d593fcdd67fb6348cd0dccf1;hpb=95e34ef763214988cfaaeb51ca9aeb77ab87be3d;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/vms-misc.c b/bfd/vms-misc.c index 67cc25adc0..94a13c736b 100644 --- a/bfd/vms-misc.c +++ b/bfd/vms-misc.c @@ -1,7 +1,6 @@ /* 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, 2009 Free Software Foundation, Inc. + Copyright (C) 1996-2016 Free Software Foundation, Inc. Miscellaneous functions. @@ -33,8 +32,10 @@ #include "safe-ctype.h" #ifdef VMS +#define __NEW_STARLET #include #include +#include #include #define RME$C_SETRFM 0x00000001 #include @@ -346,7 +347,7 @@ _bfd_vms_output_quad (struct vms_rec_wr *recwr, bfd_vma value) /* Output c-string as counted string. */ void -_bfd_vms_output_counted (struct vms_rec_wr *recwr, char *value) +_bfd_vms_output_counted (struct vms_rec_wr *recwr, const char *value) { int len; @@ -364,13 +365,13 @@ _bfd_vms_output_counted (struct vms_rec_wr *recwr, char *value) return; } _bfd_vms_output_byte (recwr, (unsigned int) len & 0xff); - _bfd_vms_output_dump (recwr, (unsigned char *) value, len); + _bfd_vms_output_dump (recwr, (const unsigned char *)value, len); } /* Output character area. */ void -_bfd_vms_output_dump (struct vms_rec_wr *recwr, unsigned char *data, int len) +_bfd_vms_output_dump (struct vms_rec_wr *recwr, const unsigned char *data, int len) { vms_debug2 ((6, "_bfd_vms_output_dump (%d)\n", len)); @@ -400,7 +401,7 @@ _bfd_vms_output_fill (struct vms_rec_wr *recwr, int value, int count) Pure VMS version. */ static void -vms_convert_to_var (char *vms_filename) +vms_convert_to_var (char * vms_filename) { struct FAB fab = cc$rms_fab; @@ -431,8 +432,8 @@ vms_convert_to_var_1 (char *filename, int type) using undocumented system call sys$modify(). Unix filename version. */ -static int -vms_convert_to_var_unix_filename (const char *unix_filename) +int +_bfd_vms_convert_to_var_unix_filename (const char *unix_filename) { if (decc$to_vms (unix_filename, &vms_convert_to_var_1, 0, 1) != 1) return FALSE; @@ -494,19 +495,19 @@ vms_get_module_name (const char *filename, bfd_boolean upcase) fout++; else fout = filename; - + /* Strip UNIX path. */ fptr = strrchr (fout, '/'); if (fptr != NULL) fout = fptr + 1; - + fname = strdup (fout); /* Strip suffix. */ fptr = strrchr (fname, '.'); if (fptr != 0) *fptr = 0; - + /* Convert to upper case and truncate at 31 characters. (VMS object file format restricts module name length to 31). */ fptr = fname; @@ -523,36 +524,109 @@ vms_get_module_name (const char *filename, bfd_boolean upcase) return fname; } -/* Convert a raw VMS time to a unix time. */ +/* Compared to usual UNIX time_t, VMS time has less limits: + - 64 bit (63 bits in fact as the MSB must be 0) + - 100ns granularity + - epoch is Nov 17, 1858. + Here has the constants and the routines used to convert VMS from/to UNIX time. + The conversion routines don't assume 64 bits arithmetic. + + Here we assume that the definition of time_t is the UNIX one, ie integer + type, expressing seconds since the epoch. */ + +/* UNIX time granularity for VMS, ie 1s / 100ns. */ +#define VMS_TIME_FACTOR 10000000 + +/* Number of seconds since VMS epoch of the UNIX epoch. */ +#define VMS_TIME_OFFSET 3506716800U + +/* Convert a VMS time to a unix time. */ time_t vms_time_to_time_t (unsigned int hi, unsigned int lo) { - const unsigned int off = 3506716800U; - const unsigned int factor = 10000000; unsigned int tmp; unsigned int rlo; int i; + time_t res; /* First convert to seconds. */ - tmp = hi % factor; - hi = hi / factor; + tmp = hi % VMS_TIME_FACTOR; + hi = hi / VMS_TIME_FACTOR; rlo = 0; for (i = 0; i < 4; i++) { tmp = (tmp << 8) | (lo >> 24); lo <<= 8; - rlo = (rlo << 8) | (tmp / factor); - tmp %= factor; + rlo = (rlo << 8) | (tmp / VMS_TIME_FACTOR); + tmp %= VMS_TIME_FACTOR; } lo = rlo; /* Return 0 in case of overflow. */ - if (lo > off && hi > 1) + if (hi > 1 + || (hi == 1 && lo >= VMS_TIME_OFFSET)) return 0; - return lo - off; + /* Return 0 in case of underflow. */ + if (hi == 0 && lo < VMS_TIME_OFFSET) + return 0; + + res = lo - VMS_TIME_OFFSET; + if (res <= 0) + return 0; + return res; +} + +/* Convert a time_t to a VMS time. */ + +void +vms_time_t_to_vms_time (time_t ut, unsigned int *hi, unsigned int *lo) +{ + unsigned short val[4]; + unsigned short tmp[4]; + unsigned int carry; + int i; + + /* Put into val. */ + val[0] = ut & 0xffff; + val[1] = (ut >> 16) & 0xffff; + val[2] = sizeof (ut) > 4 ? (ut >> 32) & 0xffff : 0; + val[3] = sizeof (ut) > 4 ? (ut >> 48) & 0xffff : 0; + + /* Add offset. */ + tmp[0] = VMS_TIME_OFFSET & 0xffff; + tmp[1] = VMS_TIME_OFFSET >> 16; + tmp[2] = 0; + tmp[3] = 0; + carry = 0; + for (i = 0; i < 4; i++) + { + carry += tmp[i] + val[i]; + val[i] = carry & 0xffff; + carry = carry >> 16; + } + + /* Multiply by factor, well first by 10000 and then by 1000. */ + carry = 0; + for (i = 0; i < 4; i++) + { + carry += val[i] * 10000; + val[i] = carry & 0xffff; + carry = carry >> 16; + } + carry = 0; + for (i = 0; i < 4; i++) + { + carry += val[i] * 1000; + val[i] = carry & 0xffff; + carry = carry >> 16; + } + + /* Write the result. */ + *lo = val[0] | (val[1] << 16); + *hi = val[2] | (val[3] << 16); } /* Convert a raw (stored in a buffer) VMS time to a unix time. */ @@ -565,3 +639,32 @@ vms_rawtime_to_time_t (unsigned char *buf) return vms_time_to_time_t (hi, lo); } + +void +vms_get_time (unsigned int *hi, unsigned int *lo) +{ +#ifdef VMS + struct _generic_64 t; + + sys$gettim (&t); + *lo = t.gen64$q_quadword; + *hi = t.gen64$q_quadword >> 32; +#else + time_t t; + + time (&t); + vms_time_t_to_vms_time (t, hi, lo); +#endif +} + +/* Get the current time into a raw buffer BUF. */ + +void +vms_raw_get_time (unsigned char *buf) +{ + unsigned int hi, lo; + + vms_get_time (&hi, &lo); + bfd_putl32 (lo, buf + 0); + bfd_putl32 (hi, buf + 4); +}