]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/vms-misc.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / bfd / vms-misc.c
CommitLineData
0c376465 1/* vms-misc.c -- BFD back-end for VMS/VAX (openVMS/VAX) and
252b5132 2 EVAX (openVMS/Alpha) files.
82704155 3 Copyright (C) 1996-2019 Free Software Foundation, Inc.
0c376465
TG
4
5 Miscellaneous functions.
252b5132
RH
6
7 Written by Klaus K"ampf (kkaempf@rmi.de)
8
7920ce38
NC
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
cd123cb7 11 the Free Software Foundation; either version 3 of the License, or
7920ce38 12 (at your option) any later version.
252b5132 13
7920ce38
NC
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
252b5132 18
7920ce38
NC
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
cd123cb7
NC
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
252b5132 23
252b5132
RH
24#if __STDC__
25#include <stdarg.h>
26#endif
27
252b5132 28#include "sysdep.h"
3db64b00 29#include "bfd.h"
252b5132
RH
30#include "bfdlink.h"
31#include "libbfd.h"
4b544b64 32#include "safe-ctype.h"
252b5132 33
95e34ef7 34#ifdef VMS
953b49ed 35#define __NEW_STARLET
95e34ef7
TG
36#include <rms.h>
37#include <unixlib.h>
953b49ed 38#include <gen64def.h>
95e34ef7
TG
39#include <starlet.h>
40#define RME$C_SETRFM 0x00000001
41#include <unistd.h>
42#endif
43#include <time.h>
0c376465 44
95e34ef7
TG
45#include "vms.h"
46#include "vms/emh.h"
0c376465 47
252b5132 48#if VMS_DEBUG
7920ce38 49/* Debug functions. */
252b5132 50
0c376465
TG
51/* Debug function for all vms extensions evaluates environment
52 variable VMS_DEBUG for a numerical value on the first call all
53 error levels below this value are printed:
558e161f 54
0c376465 55 Levels:
252b5132
RH
56 1 toplevel bfd calls (functions from the bfd vector)
57 2 functions called by bfd calls
58 ...
59 9 almost everything
60
0c376465 61 Level is also indentation level. Indentation is performed
7920ce38 62 if level > 0. */
252b5132 63
252b5132
RH
64void
65_bfd_vms_debug (int level, char *format, ...)
66{
67 static int min_level = -1;
68 static FILE *output = NULL;
69 char *eptr;
70 va_list args;
7920ce38 71 int abslvl = (level > 0) ? level : - level;
252b5132
RH
72
73 if (min_level == -1)
74 {
7920ce38 75 if ((eptr = getenv ("VMS_DEBUG")) != NULL)
252b5132 76 {
7920ce38 77 min_level = atoi (eptr);
252b5132
RH
78 output = stderr;
79 }
80 else
81 min_level = 0;
82 }
83 if (output == NULL)
84 return;
85 if (abslvl > min_level)
86 return;
87
95e34ef7 88 while (--level > 0)
558e161f 89 fprintf (output, " ");
7920ce38 90 va_start (args, format);
558e161f 91 vfprintf (output, format, args);
7920ce38
NC
92 fflush (output);
93 va_end (args);
252b5132
RH
94}
95
7920ce38
NC
96/* A debug function
97 hex dump 'size' bytes starting at 'ptr'. */
252b5132
RH
98
99void
95e34ef7 100_bfd_hexdump (int level, unsigned char *ptr, int size, int offset)
252b5132
RH
101{
102 unsigned char *lptr = ptr;
103 int count = 0;
104 long start = offset;
105
106 while (size-- > 0)
107 {
95e34ef7 108 if ((count % 16) == 0)
252b5132
RH
109 vms_debug (level, "%08lx:", start);
110 vms_debug (-level, " %02x", *ptr++);
111 count++;
112 start++;
113 if (size == 0)
114 {
95e34ef7 115 while ((count % 16) != 0)
252b5132
RH
116 {
117 vms_debug (-level, " ");
118 count++;
119 }
120 }
95e34ef7 121 if ((count % 16) == 0)
252b5132
RH
122 {
123 vms_debug (-level, " ");
124 while (lptr < ptr)
125 {
95e34ef7 126 vms_debug (-level, "%c", (*lptr < 32) ? '.' : *lptr);
252b5132
RH
127 lptr++;
128 }
129 vms_debug (-level, "\n");
130 }
131 }
95e34ef7 132 if ((count % 16) != 0)
252b5132 133 vms_debug (-level, "\n");
252b5132
RH
134}
135#endif
252b5132 136\f
0c376465 137
8bdf0be1
NC
138/* Copy sized string (string with fixed size) to new allocated area.
139 Size is string size (size of record). */
252b5132
RH
140
141char *
7adc0a81 142_bfd_vms_save_sized_string (unsigned char *str, unsigned int size)
252b5132 143{
dc810e39 144 char *newstr = bfd_malloc ((bfd_size_type) size + 1);
252b5132
RH
145
146 if (newstr == NULL)
7920ce38 147 return NULL;
95e34ef7 148 memcpy (newstr, (char *) str, (size_t) size);
252b5132
RH
149 newstr[size] = 0;
150
151 return newstr;
152}
153
8bdf0be1
NC
154/* Copy counted string (string with size at first byte) to new allocated area.
155 PTR points to size byte on entry. */
252b5132
RH
156
157char *
7adc0a81 158_bfd_vms_save_counted_string (unsigned char *ptr, unsigned int maxlen)
252b5132 159{
7adc0a81 160 unsigned int len = *ptr++;
252b5132 161
7adc0a81
NC
162 if (len > maxlen)
163 return NULL;
252b5132
RH
164 return _bfd_vms_save_sized_string (ptr, len);
165}
252b5132 166\f
95e34ef7 167/* Object output routines. */
252b5132 168
95e34ef7
TG
169/* Begin new record.
170 Write 2 bytes rectype and 2 bytes record length. */
252b5132
RH
171
172void
95e34ef7 173_bfd_vms_output_begin (struct vms_rec_wr *recwr, int rectype)
252b5132 174{
95e34ef7 175 vms_debug2 ((6, "_bfd_vms_output_begin (type %d)\n", rectype));
252b5132 176
95e34ef7
TG
177 /* Record must have been closed. */
178 BFD_ASSERT (recwr->size == 0);
252b5132 179
95e34ef7 180 _bfd_vms_output_short (recwr, (unsigned int) rectype);
252b5132 181
95e34ef7
TG
182 /* Placeholder for length. */
183 _bfd_vms_output_short (recwr, 0);
252b5132 184}
252b5132 185
95e34ef7
TG
186/* Begin new sub-record.
187 Write 2 bytes rectype, and 2 bytes record length. */
252b5132
RH
188
189void
95e34ef7 190_bfd_vms_output_begin_subrec (struct vms_rec_wr *recwr, int rectype)
252b5132 191{
95e34ef7 192 vms_debug2 ((6, "_bfd_vms_output_begin_subrec (type %d)\n", rectype));
252b5132 193
95e34ef7
TG
194 /* Subrecord must have been closed. */
195 BFD_ASSERT (recwr->subrec_offset == 0);
252b5132 196
95e34ef7
TG
197 /* Save start of subrecord offset. */
198 recwr->subrec_offset = recwr->size;
252b5132 199
95e34ef7
TG
200 /* Subrecord type. */
201 _bfd_vms_output_short (recwr, (unsigned int) rectype);
252b5132 202
7920ce38 203 /* Placeholder for length. */
95e34ef7 204 _bfd_vms_output_short (recwr, 0);
252b5132
RH
205}
206
7920ce38 207/* Set record/subrecord alignment. */
252b5132
RH
208
209void
95e34ef7 210_bfd_vms_output_alignment (struct vms_rec_wr *recwr, int alignto)
252b5132 211{
95e34ef7
TG
212 vms_debug2 ((6, "_bfd_vms_output_alignment (%d)\n", alignto));
213 recwr->align = alignto;
252b5132
RH
214}
215
95e34ef7
TG
216/* Align the size of the current record (whose length is LENGTH).
217 Warning: this obviously changes the record (and the possible subrecord)
218 length. */
252b5132 219
95e34ef7
TG
220static void
221_bfd_vms_output_align (struct vms_rec_wr *recwr, unsigned int length)
252b5132 222{
95e34ef7
TG
223 unsigned int real_size = recwr->size;
224 unsigned int aligncount;
252b5132 225
95e34ef7
TG
226 /* Pad with 0 if alignment is required. */
227 aligncount = (recwr->align - (length % recwr->align)) % recwr->align;
228 vms_debug2 ((6, "align: adding %d bytes\n", aligncount));
229 while (aligncount-- > 0)
230 recwr->buf[real_size++] = 0;
252b5132 231
95e34ef7 232 recwr->size = real_size;
252b5132
RH
233}
234
95e34ef7 235/* Ends current sub-record. Set length field. */
252b5132
RH
236
237void
95e34ef7 238_bfd_vms_output_end_subrec (struct vms_rec_wr *recwr)
252b5132 239{
95e34ef7 240 int real_size = recwr->size;
252b5132
RH
241 int length;
242
95e34ef7
TG
243 /* Subrecord must be open. */
244 BFD_ASSERT (recwr->subrec_offset != 0);
252b5132 245
95e34ef7 246 length = real_size - recwr->subrec_offset;
252b5132
RH
247
248 if (length == 0)
249 return;
252b5132 250
95e34ef7 251 _bfd_vms_output_align (recwr, length);
252b5132 252
7920ce38 253 /* Put length to buffer. */
95e34ef7 254 bfd_putl16 ((bfd_vma) (recwr->size - recwr->subrec_offset),
07d6d2b8 255 recwr->buf + recwr->subrec_offset + 2);
252b5132 256
95e34ef7
TG
257 /* Close the subrecord. */
258 recwr->subrec_offset = 0;
252b5132
RH
259}
260
95e34ef7 261/* Ends current record (and write it). */
252b5132
RH
262
263void
95e34ef7 264_bfd_vms_output_end (bfd *abfd, struct vms_rec_wr *recwr)
252b5132 265{
95e34ef7 266 vms_debug2 ((6, "_bfd_vms_output_end (size %u)\n", recwr->size));
252b5132 267
95e34ef7
TG
268 /* Subrecord must have been closed. */
269 BFD_ASSERT (recwr->subrec_offset == 0);
252b5132 270
95e34ef7
TG
271 if (recwr->size == 0)
272 return;
252b5132 273
95e34ef7
TG
274 _bfd_vms_output_align (recwr, recwr->size);
275
276 /* Write the length word. */
277 bfd_putl16 ((bfd_vma) recwr->size, recwr->buf + 2);
278
279 /* File is open in undefined (UDF) format on VMS, but ultimately will be
280 converted to variable length (VAR) format. VAR format has a length
281 word first which must be explicitly output in UDF format. */
282 /* So, first the length word. */
283 bfd_bwrite (recwr->buf + 2, 2, abfd);
284
285 /* Align. */
286 if (recwr->size & 1)
287 recwr->buf[recwr->size++] = 0;
288
289 /* Then the record. */
290 bfd_bwrite (recwr->buf, (size_t) recwr->size, abfd);
291
292 recwr->size = 0;
293}
294
295/* Check remaining buffer size. Return what's left. */
252b5132
RH
296
297int
95e34ef7 298_bfd_vms_output_check (struct vms_rec_wr *recwr, int size)
252b5132 299{
95e34ef7 300 vms_debug2 ((6, "_bfd_vms_output_check (%d)\n", size));
252b5132 301
95e34ef7 302 return (MAX_OUTREC_SIZE - (recwr->size + size + MIN_OUTREC_LUFT));
252b5132
RH
303}
304
7920ce38 305/* Output byte (8 bit) value. */
252b5132
RH
306
307void
95e34ef7 308_bfd_vms_output_byte (struct vms_rec_wr *recwr, unsigned int value)
252b5132 309{
95e34ef7 310 vms_debug2 ((6, "_bfd_vms_output_byte (%02x)\n", value));
252b5132 311
95e34ef7
TG
312 *(recwr->buf + recwr->size) = value;
313 recwr->size += 1;
252b5132
RH
314}
315
7920ce38 316/* Output short (16 bit) value. */
252b5132
RH
317
318void
95e34ef7 319_bfd_vms_output_short (struct vms_rec_wr *recwr, unsigned int value)
252b5132 320{
95e34ef7 321 vms_debug2 ((6, "_bfd_vms_output_short (%04x)\n", value));
252b5132 322
95e34ef7
TG
323 bfd_putl16 ((bfd_vma) value & 0xffff, recwr->buf + recwr->size);
324 recwr->size += 2;
252b5132
RH
325}
326
7920ce38 327/* Output long (32 bit) value. */
252b5132
RH
328
329void
95e34ef7 330_bfd_vms_output_long (struct vms_rec_wr *recwr, unsigned long value)
252b5132 331{
95e34ef7 332 vms_debug2 ((6, "_bfd_vms_output_long (%08lx)\n", value));
252b5132 333
95e34ef7
TG
334 bfd_putl32 ((bfd_vma) value, recwr->buf + recwr->size);
335 recwr->size += 4;
252b5132
RH
336}
337
7920ce38 338/* Output quad (64 bit) value. */
252b5132
RH
339
340void
95e34ef7 341_bfd_vms_output_quad (struct vms_rec_wr *recwr, bfd_vma value)
252b5132 342{
95e34ef7 343 vms_debug2 ((6, "_bfd_vms_output_quad (%08lx)\n", (unsigned long)value));
252b5132 344
95e34ef7
TG
345 bfd_putl64 (value, recwr->buf + recwr->size);
346 recwr->size += 8;
252b5132
RH
347}
348
7920ce38 349/* Output c-string as counted string. */
252b5132
RH
350
351void
81bb31c0 352_bfd_vms_output_counted (struct vms_rec_wr *recwr, const char *value)
252b5132 353{
7920ce38 354 int len;
252b5132 355
95e34ef7 356 vms_debug2 ((6, "_bfd_vms_output_counted (%s)\n", value));
252b5132
RH
357
358 len = strlen (value);
359 if (len == 0)
360 {
4eca0228 361 _bfd_error_handler (_("_bfd_vms_output_counted called with zero bytes"));
252b5132
RH
362 return;
363 }
364 if (len > 255)
365 {
4eca0228 366 _bfd_error_handler (_("_bfd_vms_output_counted called with too many bytes"));
252b5132
RH
367 return;
368 }
95e34ef7 369 _bfd_vms_output_byte (recwr, (unsigned int) len & 0xff);
81bb31c0 370 _bfd_vms_output_dump (recwr, (const unsigned char *)value, len);
252b5132
RH
371}
372
7920ce38 373/* Output character area. */
252b5132
RH
374
375void
81bb31c0 376_bfd_vms_output_dump (struct vms_rec_wr *recwr, const unsigned char *data, int len)
252b5132 377{
95e34ef7 378 vms_debug2 ((6, "_bfd_vms_output_dump (%d)\n", len));
252b5132 379
95e34ef7 380 if (len == 0)
252b5132
RH
381 return;
382
95e34ef7
TG
383 memcpy (recwr->buf + recwr->size, data, (size_t) len);
384 recwr->size += len;
252b5132
RH
385}
386
7920ce38 387/* Output count bytes of value. */
252b5132
RH
388
389void
95e34ef7 390_bfd_vms_output_fill (struct vms_rec_wr *recwr, int value, int count)
252b5132 391{
95e34ef7 392 vms_debug2 ((6, "_bfd_vms_output_fill (val %02x times %d)\n", value, count));
252b5132
RH
393
394 if (count == 0)
395 return;
95e34ef7
TG
396 memset (recwr->buf + recwr->size, value, (size_t) count);
397 recwr->size += count;
252b5132
RH
398}
399
95e34ef7
TG
400#ifdef VMS
401/* Convert the file to variable record length format. This is done
402 using undocumented system call sys$modify().
403 Pure VMS version. */
252b5132 404
bfea910e
TG
405static void
406vms_convert_to_var (char * vms_filename)
252b5132 407{
95e34ef7 408 struct FAB fab = cc$rms_fab;
252b5132 409
95e34ef7
TG
410 fab.fab$l_fna = vms_filename;
411 fab.fab$b_fns = strlen (vms_filename);
412 fab.fab$b_fac = FAB$M_PUT;
413 fab.fab$l_fop = FAB$M_ESC;
414 fab.fab$l_ctx = RME$C_SETRFM;
252b5132 415
95e34ef7 416 sys$open (&fab);
252b5132 417
95e34ef7 418 fab.fab$b_rfm = FAB$C_VAR;
252b5132 419
95e34ef7
TG
420 sys$modify (&fab);
421 sys$close (&fab);
252b5132
RH
422}
423
95e34ef7
TG
424static int
425vms_convert_to_var_1 (char *filename, int type)
252b5132 426{
95e34ef7
TG
427 if (type != DECC$K_FILE)
428 return FALSE;
429 vms_convert_to_var (filename);
430 return TRUE;
252b5132
RH
431}
432
95e34ef7
TG
433/* Convert the file to variable record length format. This is done
434 using undocumented system call sys$modify().
435 Unix filename version. */
252b5132 436
bfea910e
TG
437int
438_bfd_vms_convert_to_var_unix_filename (const char *unix_filename)
252b5132 439{
95e34ef7
TG
440 if (decc$to_vms (unix_filename, &vms_convert_to_var_1, 0, 1) != 1)
441 return FALSE;
442 return TRUE;
443}
444#endif /* VMS */
445
446/* Manufacture a VMS like time on a unix based system.
447 stolen from obj-vms.c. */
448
449unsigned char *
450get_vms_time_string (void)
451{
452 static unsigned char tbuf[18];
453#ifndef VMS
454 char *pnt;
455 time_t timeb;
456
457 time (& timeb);
458 pnt = ctime (&timeb);
459 pnt[3] = 0;
460 pnt[7] = 0;
461 pnt[10] = 0;
462 pnt[16] = 0;
463 pnt[24] = 0;
464 sprintf ((char *) tbuf, "%2s-%3s-%s %s",
465 pnt + 8, pnt + 4, pnt + 20, pnt + 11);
466#else
467 struct
468 {
469 int Size;
470 unsigned char *Ptr;
471 } Descriptor;
472 Descriptor.Size = 17;
473 Descriptor.Ptr = tbuf;
474 SYS$ASCTIM (0, &Descriptor, 0, 0);
475#endif /* not VMS */
476
477 vms_debug2 ((6, "vmstimestring:'%s'\n", tbuf));
478
479 return tbuf;
252b5132 480}
4b544b64
TG
481
482/* Create module name from filename (ie, extract the basename and convert it
483 in upper cases). Works on both VMS and UNIX pathes.
484 The result has to be free(). */
485
486char *
487vms_get_module_name (const char *filename, bfd_boolean upcase)
488{
489 char *fname, *fptr;
490 const char *fout;
491
492 /* Strip VMS path. */
493 fout = strrchr (filename, ']');
494 if (fout == NULL)
495 fout = strchr (filename, ':');
496 if (fout != NULL)
497 fout++;
498 else
499 fout = filename;
953b49ed 500
4b544b64
TG
501 /* Strip UNIX path. */
502 fptr = strrchr (fout, '/');
503 if (fptr != NULL)
504 fout = fptr + 1;
953b49ed 505
4b544b64
TG
506 fname = strdup (fout);
507
508 /* Strip suffix. */
509 fptr = strrchr (fname, '.');
510 if (fptr != 0)
511 *fptr = 0;
953b49ed 512
4b544b64
TG
513 /* Convert to upper case and truncate at 31 characters.
514 (VMS object file format restricts module name length to 31). */
515 fptr = fname;
516 for (fptr = fname; *fptr != 0; fptr++)
517 {
518 if (*fptr == ';' || (fptr - fname) >= 31)
07d6d2b8
AM
519 {
520 *fptr = 0;
521 break;
522 }
4b544b64 523 if (upcase)
07d6d2b8 524 *fptr = TOUPPER (*fptr);
4b544b64
TG
525 }
526 return fname;
527}
528
953b49ed
TG
529/* Compared to usual UNIX time_t, VMS time has less limits:
530 - 64 bit (63 bits in fact as the MSB must be 0)
531 - 100ns granularity
532 - epoch is Nov 17, 1858.
533 Here has the constants and the routines used to convert VMS from/to UNIX time.
62a35308
TG
534 The conversion routines don't assume 64 bits arithmetic.
535
536 Here we assume that the definition of time_t is the UNIX one, ie integer
537 type, expressing seconds since the epoch. */
953b49ed
TG
538
539/* UNIX time granularity for VMS, ie 1s / 100ns. */
540#define VMS_TIME_FACTOR 10000000
541
542/* Number of seconds since VMS epoch of the UNIX epoch. */
543#define VMS_TIME_OFFSET 3506716800U
544
545/* Convert a VMS time to a unix time. */
4b544b64
TG
546
547time_t
548vms_time_to_time_t (unsigned int hi, unsigned int lo)
549{
4b544b64
TG
550 unsigned int tmp;
551 unsigned int rlo;
552 int i;
62a35308 553 time_t res;
4b544b64
TG
554
555 /* First convert to seconds. */
953b49ed
TG
556 tmp = hi % VMS_TIME_FACTOR;
557 hi = hi / VMS_TIME_FACTOR;
4b544b64
TG
558 rlo = 0;
559 for (i = 0; i < 4; i++)
560 {
561 tmp = (tmp << 8) | (lo >> 24);
562 lo <<= 8;
563
953b49ed
TG
564 rlo = (rlo << 8) | (tmp / VMS_TIME_FACTOR);
565 tmp %= VMS_TIME_FACTOR;
4b544b64
TG
566 }
567 lo = rlo;
568
569 /* Return 0 in case of overflow. */
62a35308
TG
570 if (hi > 1
571 || (hi == 1 && lo >= VMS_TIME_OFFSET))
953b49ed
TG
572 return 0;
573
574 /* Return 0 in case of underflow. */
62a35308 575 if (hi == 0 && lo < VMS_TIME_OFFSET)
4b544b64
TG
576 return 0;
577
62a35308
TG
578 res = lo - VMS_TIME_OFFSET;
579 if (res <= 0)
580 return 0;
581 return res;
953b49ed
TG
582}
583
584/* Convert a time_t to a VMS time. */
585
586void
587vms_time_t_to_vms_time (time_t ut, unsigned int *hi, unsigned int *lo)
588{
589 unsigned short val[4];
590 unsigned short tmp[4];
591 unsigned int carry;
592 int i;
593
594 /* Put into val. */
595 val[0] = ut & 0xffff;
596 val[1] = (ut >> 16) & 0xffff;
81c5c866
JK
597 val[2] = sizeof (ut) > 4 ? (ut >> 32) & 0xffff : 0;
598 val[3] = sizeof (ut) > 4 ? (ut >> 48) & 0xffff : 0;
953b49ed
TG
599
600 /* Add offset. */
601 tmp[0] = VMS_TIME_OFFSET & 0xffff;
602 tmp[1] = VMS_TIME_OFFSET >> 16;
603 tmp[2] = 0;
604 tmp[3] = 0;
605 carry = 0;
606 for (i = 0; i < 4; i++)
607 {
608 carry += tmp[i] + val[i];
609 val[i] = carry & 0xffff;
610 carry = carry >> 16;
611 }
612
613 /* Multiply by factor, well first by 10000 and then by 1000. */
614 carry = 0;
615 for (i = 0; i < 4; i++)
616 {
617 carry += val[i] * 10000;
618 val[i] = carry & 0xffff;
619 carry = carry >> 16;
620 }
621 carry = 0;
622 for (i = 0; i < 4; i++)
623 {
624 carry += val[i] * 1000;
625 val[i] = carry & 0xffff;
626 carry = carry >> 16;
627 }
628
629 /* Write the result. */
630 *lo = val[0] | (val[1] << 16);
631 *hi = val[2] | (val[3] << 16);
4b544b64
TG
632}
633
634/* Convert a raw (stored in a buffer) VMS time to a unix time. */
635
636time_t
637vms_rawtime_to_time_t (unsigned char *buf)
638{
639 unsigned int hi = bfd_getl32 (buf + 4);
640 unsigned int lo = bfd_getl32 (buf + 0);
641
642 return vms_time_to_time_t (hi, lo);
643}
953b49ed
TG
644
645void
646vms_get_time (unsigned int *hi, unsigned int *lo)
647{
648#ifdef VMS
649 struct _generic_64 t;
650
651 sys$gettim (&t);
652 *lo = t.gen64$q_quadword;
653 *hi = t.gen64$q_quadword >> 32;
654#else
655 time_t t;
656
657 time (&t);
658 vms_time_t_to_vms_time (t, hi, lo);
659#endif
660}
661
662/* Get the current time into a raw buffer BUF. */
663
664void
665vms_raw_get_time (unsigned char *buf)
666{
667 unsigned int hi, lo;
668
669 vms_get_time (&hi, &lo);
670 bfd_putl32 (lo, buf + 0);
671 bfd_putl32 (hi, buf + 4);
672}