OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [vms-misc.c] - Blame information for rev 148

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.