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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [bfd/] [vms-misc.c] - Blame information for rev 252

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

Line No. Rev Author Line
1 205 julius
/* 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  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
 
34
#include "vms.h"
35
 
36
#define MIN(a,b) ((a) < (b) ? (a) : (b))
37
 
38
static int hash_string PARAMS ((const char *));
39
static asymbol *new_symbol PARAMS ((bfd *, char *));
40
static void maybe_adjust_record_pointer_for_object PARAMS ((bfd *));
41
static int vms_get_remaining_object_record PARAMS ((bfd *, int ));
42
static int vms_get_remaining_image_record PARAMS ((bfd *, int ));
43
 
44
#if VMS_DEBUG
45
/* Debug functions.  */
46
 
47
/* Debug function for all vms extensions evaluates environment
48
   variable VMS_DEBUG for a numerical value on the first call all
49
   error levels below this value are printed:
50
 
51
   Levels:
52
   1    toplevel bfd calls (functions from the bfd vector)
53
   2    functions called by bfd calls
54
   ...
55
   9    almost everything
56
 
57
   Level is also indentation level. Indentation is performed
58
   if level > 0.  */
59
 
60
void
61
_bfd_vms_debug (int level, char *format, ...)
62
{
63
  static int min_level = -1;
64
  static FILE *output = NULL;
65
  char *eptr;
66
  va_list args;
67
  int abslvl = (level > 0) ? level : - level;
68
 
69
  if (min_level == -1)
70
    {
71
      if ((eptr = getenv ("VMS_DEBUG")) != NULL)
72
        {
73
          min_level = atoi (eptr);
74
          output = stderr;
75
        }
76
      else
77
        min_level = 0;
78
    }
79
  if (output == NULL)
80
    return;
81
  if (abslvl > min_level)
82
    return;
83
 
84
  while (--level>0)
85
    fprintf (output, " ");
86
  va_start (args, format);
87
  vfprintf (output, format, args);
88
  fflush (output);
89
  va_end (args);
90
}
91
 
92
/* A debug function
93
   hex dump 'size' bytes starting at 'ptr'.  */
94
 
95
void
96
_bfd_hexdump (int level,
97
              unsigned char *ptr,
98
              int size,
99
              int offset)
100
{
101
  unsigned char *lptr = ptr;
102
  int count = 0;
103
  long start = offset;
104
 
105
  while (size-- > 0)
106
    {
107
      if ((count%16) == 0)
108
        vms_debug (level, "%08lx:", start);
109
      vms_debug (-level, " %02x", *ptr++);
110
      count++;
111
      start++;
112
      if (size == 0)
113
        {
114
          while ((count%16) != 0)
115
            {
116
              vms_debug (-level, "   ");
117
              count++;
118
            }
119
        }
120
      if ((count%16) == 0)
121
        {
122
          vms_debug (-level, " ");
123
          while (lptr < ptr)
124
            {
125
              vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
126
              lptr++;
127
            }
128
          vms_debug (-level, "\n");
129
        }
130
    }
131
  if ((count%16) != 0)
132
    vms_debug (-level, "\n");
133
}
134
#endif
135
 
136
/* Hash functions
137
 
138
   These are needed when reading an object file.  */
139
 
140
/* Allocate new vms_hash_entry
141
   keep the symbol name and a pointer to the bfd symbol in the table.  */
142
 
143
struct bfd_hash_entry *
144
_bfd_vms_hash_newfunc (struct bfd_hash_entry *entry,
145
                       struct bfd_hash_table *table,
146
                       const char *string)
147
{
148
  vms_symbol_entry *ret;
149
 
150
#if VMS_DEBUG
151
  vms_debug (5, "_bfd_vms_hash_newfunc (%p, %p, %s)\n", entry, table, string);
152
#endif
153
 
154
  if (entry == NULL)
155
    {
156
      ret = (vms_symbol_entry *)
157
              bfd_hash_allocate (table, sizeof (vms_symbol_entry));
158
      if (ret ==  NULL)
159
        {
160
          bfd_set_error (bfd_error_no_memory);
161
          return NULL;
162
        }
163
      entry = (struct bfd_hash_entry *) ret;
164
    }
165
 
166
  /* Call the allocation method of the base class.  */
167
  ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
168
#if VMS_DEBUG
169
  vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
170
#endif
171
 
172
  ret->symbol = NULL;
173
 
174
  return (struct bfd_hash_entry *)ret;
175
}
176
 
177
/* Object file input functions.  */
178
 
179
/* Return type and size from record header (buf) on Alpha.  */
180
 
181
void
182
_bfd_vms_get_header_values (bfd * abfd ATTRIBUTE_UNUSED,
183
                            unsigned char *buf,
184
                            int *type,
185
                            int *size)
186
{
187
  if (type)
188
    *type = bfd_getl16 (buf);
189
 
190
  if (size)
191
    *size = bfd_getl16 (buf+2);
192
 
193
#if VMS_DEBUG
194
  vms_debug (10, "_bfd_vms_get_header_values type %x, size %x\n",
195
             type ? *type : 0, size ? *size : 0);
196
#endif
197
}
198
 
199
/* Get next record from object file to vms_buf.
200
   Set PRIV(buf_size) and return it
201
 
202
   This is a little tricky since it should be portable.
203
 
204
   The openVMS object file has 'variable length' which means that
205
   read() returns data in chunks of (hopefully) correct and expected
206
   size.  The linker (and other tools on VMS) depend on that. Unix
207
   doesn't know about 'formatted' files, so reading and writing such
208
   an object file in a Unix environment is not trivial.
209
 
210
   With the tool 'file' (available on all VMS FTP sites), one
211
   can view and change the attributes of a file.  Changing from
212
   'variable length' to 'fixed length, 512 bytes' reveals the
213
   record size at the first 2 bytes of every record.  The same
214
   happens during the transfer of object files from VMS to Unix,
215
   at least with UCX, the DEC implementation of TCP/IP.
216
 
217
   The VMS format repeats the size at bytes 2 & 3 of every record.
218
 
219
   On the first call (file_format == FF_UNKNOWN) we check if
220
   the first and the third byte pair (!) of the record match.
221
   If they do it's an object file in an Unix environment or with
222
   wrong attributes (FF_FOREIGN), else we should be in a VMS
223
   environment where read() returns the record size (FF_NATIVE).
224
 
225
   Reading is always done in 2 steps:
226
    1. first just the record header is read and the size extracted,
227
    2. then the read buffer is adjusted and the remaining bytes are
228
       read in.
229
 
230
   All file I/O is done on even file positions.  */
231
 
232
#define VMS_OBJECT_ADJUSTMENT  2
233
 
234
static void
235
maybe_adjust_record_pointer_for_object (bfd *abfd)
236
{
237
  /* Set the file format once for all on the first invocation.  */
238
  if (PRIV (file_format) == FF_UNKNOWN)
239
    {
240
      if (PRIV (vms_rec)[0] == PRIV (vms_rec)[4]
241
          && PRIV (vms_rec)[1] == PRIV (vms_rec)[5])
242
        PRIV (file_format) = FF_FOREIGN;
243
      else
244
        PRIV (file_format) = FF_NATIVE;
245
    }
246
 
247
  /* The adjustment is needed only in an Unix environment.  */
248
  if (PRIV (file_format) == FF_FOREIGN)
249
    PRIV (vms_rec) += VMS_OBJECT_ADJUSTMENT;
250
}
251
 
252
/* Get first record from file and return the file type.  */
253
 
254
int
255
_bfd_vms_get_first_record (bfd *abfd)
256
{
257
  unsigned int test_len;
258
 
259
#if VMS_DEBUG
260
  vms_debug (8, "_bfd_vms_get_first_record\n");
261
#endif
262
 
263
  if (PRIV (is_vax))
264
    test_len = 0;
265
  else
266
    /* Minimum is 6 bytes for objects (2 bytes size, 2 bytes record id,
267
       2 bytes size repeated) and 12 bytes for images (4 bytes major id,
268
       4 bytes minor id, 4 bytes length).  */
269
    test_len = 12;
270
 
271
  /* Size the main buffer.  */
272
  if (PRIV (buf_size) == 0)
273
    {
274
      /* On VAX there's no size information in the record, so
275
         start with OBJ_S_C_MAXRECSIZ.  */
276
      bfd_size_type amt = (test_len ? test_len : OBJ_S_C_MAXRECSIZ);
277
      PRIV (vms_buf) = (unsigned char *) bfd_malloc (amt);
278
      PRIV (buf_size) = amt;
279
    }
280
 
281
  /* Initialize the record pointer.  */
282
  PRIV (vms_rec) = PRIV (vms_buf);
283
 
284
  /* We only support modules on VAX.  */
285
  if (PRIV (is_vax))
286
    {
287
      if (vms_get_remaining_object_record (abfd, test_len) <= 0)
288
        return FT_UNKNOWN;
289
 
290
#if VMS_DEBUG
291
      vms_debug (2, "file type is VAX module\n");
292
#endif
293
 
294
      return FT_MODULE;
295
    }
296
 
297
  if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
298
    {
299
      bfd_set_error (bfd_error_file_truncated);
300
      return FT_UNKNOWN;
301
    }
302
 
303
  /* Is it an image?  */
304
  if ((bfd_getl32 (PRIV (vms_rec)) == EIHD_S_K_MAJORID)
305
      && (bfd_getl32 (PRIV (vms_rec) + 4) == EIHD_S_K_MINORID))
306
    {
307
      if (vms_get_remaining_image_record (abfd, test_len) <= 0)
308
        return FT_UNKNOWN;
309
 
310
#if VMS_DEBUG
311
      vms_debug (2, "file type is image\n");
312
#endif
313
 
314
      return FT_IMAGE;
315
    }
316
 
317
  /* Assume it's a module and adjust record pointer if necessary.  */
318
  maybe_adjust_record_pointer_for_object (abfd);
319
 
320
  /* But is it really a module?  */
321
  if (bfd_getl16 (PRIV (vms_rec)) <= EOBJ_S_C_MAXRECTYP
322
      && bfd_getl16 (PRIV (vms_rec) + 2) <= EOBJ_S_C_MAXRECSIZ)
323
    {
324
      if (vms_get_remaining_object_record (abfd, test_len) <= 0)
325
        return FT_UNKNOWN;
326
 
327
#if VMS_DEBUG
328
      vms_debug (2, "file type is module\n");
329
#endif
330
 
331
      return FT_MODULE;
332
    }
333
 
334
#if VMS_DEBUG
335
  vms_debug (2, "file type is unknown\n");
336
#endif
337
 
338
  return FT_UNKNOWN;
339
}
340
 
341
/* Implement step #1 of the object record reading procedure.
342
   Return the record type or -1 on failure.  */
343
 
344
int
345
_bfd_vms_get_object_record (bfd *abfd)
346
{
347
  unsigned int test_len;
348
  int type;
349
 
350
#if VMS_DEBUG
351
  vms_debug (8, "_bfd_vms_get_obj_record\n");
352
#endif
353
 
354
  if (PRIV (is_vax))
355
    test_len = 0;
356
  else
357
    {
358
      /* See _bfd_vms_get_first_record.  */
359
      test_len = 6;
360
 
361
      /* Skip odd alignment byte.  */
362
      if (bfd_tell (abfd) & 1)
363
        {
364
          if (bfd_bread (PRIV (vms_buf), 1, abfd) != 1)
365
            {
366
              bfd_set_error (bfd_error_file_truncated);
367
              return -1;
368
            }
369
        }
370
 
371
      /* Read the record header  */
372
      if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len)
373
        {
374
          bfd_set_error (bfd_error_file_truncated);
375
          return -1;
376
        }
377
 
378
      /* Reset the record pointer.  */
379
      PRIV (vms_rec) = PRIV (vms_buf);
380
      maybe_adjust_record_pointer_for_object (abfd);
381
    }
382
 
383
  if (vms_get_remaining_object_record (abfd, test_len) <= 0)
384
    return -1;
385
 
386
  if (PRIV (is_vax))
387
    type = PRIV (vms_rec) [0];
388
  else
389
    type = bfd_getl16 (PRIV (vms_rec));
390
 
391
#if VMS_DEBUG
392
  vms_debug (8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n",
393
              PRIV (vms_rec), PRIV (rec_size), type);
394
#endif
395
 
396
  return type;
397
}
398
 
399
/* Implement step #2 of the object record reading procedure.
400
   Return the size of the record or 0 on failure.  */
401
 
402
static int
403
vms_get_remaining_object_record (bfd *abfd, int read_so_far)
404
{
405
#if VMS_DEBUG
406
  vms_debug (8, "vms_get_remaining_obj_record\n");
407
#endif
408
 
409
  if (PRIV (is_vax))
410
    {
411
      if (read_so_far != 0)
412
        abort ();
413
 
414
      PRIV (rec_size) = bfd_bread (PRIV (vms_buf), PRIV (buf_size), abfd);
415
 
416
      if (PRIV (rec_size) <= 0)
417
        {
418
          bfd_set_error (bfd_error_file_truncated);
419
          return 0;
420
        }
421
 
422
      /* Reset the record pointer.  */
423
      PRIV (vms_rec) = PRIV (vms_buf);
424
    }
425
  else
426
    {
427
      unsigned int to_read;
428
 
429
      /* Extract record size.  */
430
      PRIV (rec_size) = bfd_getl16 (PRIV (vms_rec) + 2);
431
 
432
      if (PRIV (rec_size) <= 0)
433
        {
434
          bfd_set_error (bfd_error_file_truncated);
435
          return 0;
436
        }
437
 
438
      /* That's what the linker manual says.  */
439
      if (PRIV (rec_size) > EOBJ_S_C_MAXRECSIZ)
440
        {
441
          bfd_set_error (bfd_error_file_truncated);
442
          return 0;
443
        }
444
 
445
      /* Take into account object adjustment.  */
446
      to_read = PRIV (rec_size);
447
      if (PRIV (file_format) == FF_FOREIGN)
448
        to_read += VMS_OBJECT_ADJUSTMENT;
449
 
450
      /* Adjust the buffer.  */
451
      if (to_read > PRIV (buf_size))
452
        {
453
          PRIV (vms_buf)
454
            = (unsigned char *) bfd_realloc (PRIV (vms_buf), to_read);
455
          if (PRIV (vms_buf) == NULL)
456
            return 0;
457
          PRIV (buf_size) = to_read;
458
        }
459
 
460
      /* Read the remaining record.  */
461
      to_read -= read_so_far;
462
 
463
#if VMS_DEBUG
464
      vms_debug (8, "vms_get_remaining_obj_record: to_read %d\n", to_read);
465
#endif
466
 
467
      if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
468
        {
469
          bfd_set_error (bfd_error_file_truncated);
470
          return 0;
471
        }
472
 
473
      /* Reset the record pointer.  */
474
      PRIV (vms_rec) = PRIV (vms_buf);
475
      maybe_adjust_record_pointer_for_object (abfd);
476
    }
477
 
478
#if VMS_DEBUG
479
  vms_debug (8, "vms_get_remaining_obj_record: size %d\n", PRIV (rec_size));
480
#endif
481
 
482
  return PRIV (rec_size);
483
}
484
 
485
/* Implement step #2 of the record reading procedure for images.
486
   Return the size of the record or 0 on failure.  */
487
 
488
static int
489
vms_get_remaining_image_record (bfd *abfd, int read_so_far)
490
{
491
  unsigned int to_read;
492
  int remaining;
493
 
494
  /* Extract record size.  */
495
  PRIV (rec_size) = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE);
496
 
497
  if (PRIV (rec_size) > PRIV (buf_size))
498
    {
499
      PRIV (vms_buf) = bfd_realloc (PRIV (vms_buf), PRIV (rec_size));
500
 
501
      if (PRIV (vms_buf) == NULL)
502
        {
503
          bfd_set_error (bfd_error_no_memory);
504
          return 0;
505
        }
506
 
507
      PRIV (buf_size) = PRIV (rec_size);
508
    }
509
 
510
  /* Read the remaining record.  */
511
  remaining = PRIV (rec_size) - read_so_far;
512
  to_read = MIN (VMS_BLOCK_SIZE - read_so_far, remaining);
513
 
514
  while (remaining > 0)
515
    {
516
      if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read)
517
        {
518
          bfd_set_error (bfd_error_file_truncated);
519
          return 0;
520
        }
521
 
522
      read_so_far += to_read;
523
      remaining -= to_read;
524
 
525
      /* Eat trailing 0xff's.  */
526
      if (remaining > 0)
527
        while (PRIV (vms_buf) [read_so_far - 1] == 0xff)
528
          read_so_far--;
529
 
530
      to_read = MIN (VMS_BLOCK_SIZE, remaining);
531
    }
532
 
533
  /* Reset the record pointer.  */
534
  PRIV (vms_rec) = PRIV (vms_buf);
535
 
536
  return PRIV (rec_size);
537
}
538
 
539
/* Copy sized string (string with fixed size) to new allocated area
540
   size is string size (size of record)  */
541
 
542
char *
543
_bfd_vms_save_sized_string (unsigned char *str, int size)
544
{
545
  char *newstr = bfd_malloc ((bfd_size_type) size + 1);
546
 
547
  if (newstr == NULL)
548
    return NULL;
549
  strncpy (newstr, (char *) str, (size_t) size);
550
  newstr[size] = 0;
551
 
552
  return newstr;
553
}
554
 
555
/* Copy counted string (string with size at first byte) to new allocated area
556
   ptr points to size byte on entry  */
557
 
558
char *
559
_bfd_vms_save_counted_string (unsigned char *ptr)
560
{
561
  int len = *ptr++;
562
 
563
  return _bfd_vms_save_sized_string (ptr, len);
564
}
565
 
566
/* Stack routines for vms ETIR commands.  */
567
 
568
/* Push value and section index.  */
569
 
570
void
571
_bfd_vms_push (bfd * abfd, uquad val, int psect)
572
{
573
  static int last_psect;
574
 
575
#if VMS_DEBUG
576
  vms_debug (4, "<push %016lx (%d) at %d>\n", val, psect, PRIV (stackptr));
577
#endif
578
 
579
  if (psect >= 0)
580
    last_psect = psect;
581
 
582
  PRIV (stack[PRIV (stackptr)]).value = val;
583
  PRIV (stack[PRIV (stackptr)]).psect = last_psect;
584
  PRIV (stackptr)++;
585
  if (PRIV (stackptr) >= STACKSIZE)
586
    {
587
      bfd_set_error (bfd_error_bad_value);
588
      (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
589
      exit (1);
590
    }
591
}
592
 
593
/* Pop value and section index.  */
594
 
595
uquad
596
_bfd_vms_pop (bfd * abfd, int *psect)
597
{
598
  uquad value;
599
 
600
  if (PRIV (stackptr) == 0)
601
    {
602
      bfd_set_error (bfd_error_bad_value);
603
      (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
604
      exit (1);
605
    }
606
  PRIV (stackptr)--;
607
  value = PRIV (stack[PRIV (stackptr)]).value;
608
  if ((psect != NULL) && (PRIV (stack[PRIV (stackptr)]).psect >= 0))
609
    *psect = PRIV (stack[PRIV (stackptr)]).psect;
610
 
611
#if VMS_DEBUG
612
  vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect);
613
#endif
614
 
615
  return value;
616
}
617
 
618
/* Object output routines.   */
619
 
620
/* Begin new record or record header
621
   write 2 bytes rectype
622
   write 2 bytes record length (filled in at flush)
623
   write 2 bytes header type (ommitted if rechead == -1).  */
624
 
625
void
626
_bfd_vms_output_begin (bfd * abfd, int rectype, int rechead)
627
{
628
#if VMS_DEBUG
629
  vms_debug (6, "_bfd_vms_output_begin (type %d, head %d)\n", rectype,
630
              rechead);
631
#endif
632
 
633
  _bfd_vms_output_short (abfd, (unsigned int) rectype);
634
 
635
  /* Save current output position to fill in length later.   */
636
 
637
  if (PRIV (push_level) > 0)
638
    PRIV (length_pos) = PRIV (output_size);
639
 
640
#if VMS_DEBUG
641
  vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
642
              PRIV (length_pos));
643
#endif
644
 
645
  /* Placeholder for length.  */
646
  _bfd_vms_output_short (abfd, 0);
647
 
648
  if (rechead != -1)
649
    _bfd_vms_output_short (abfd, (unsigned int) rechead);
650
}
651
 
652
/* Set record/subrecord alignment.   */
653
 
654
void
655
_bfd_vms_output_alignment (bfd * abfd, int alignto)
656
{
657
#if VMS_DEBUG
658
  vms_debug (6, "_bfd_vms_output_alignment (%d)\n", alignto);
659
#endif
660
 
661
  PRIV (output_alignment) = alignto;
662
}
663
 
664
/* Prepare for subrecord fields.  */
665
 
666
void
667
_bfd_vms_output_push (bfd * abfd)
668
{
669
#if VMS_DEBUG
670
  vms_debug (6, "vms_output_push (pushed_size = %d)\n", PRIV (output_size));
671
#endif
672
 
673
  PRIV (push_level)++;
674
  PRIV (pushed_size) = PRIV (output_size);
675
}
676
 
677
/* End of subrecord fields.   */
678
 
679
void
680
_bfd_vms_output_pop (bfd * abfd)
681
{
682
#if VMS_DEBUG
683
  vms_debug (6, "vms_output_pop (pushed_size = %d)\n", PRIV (pushed_size));
684
#endif
685
 
686
  _bfd_vms_output_flush (abfd);
687
  PRIV (length_pos) = 2;
688
 
689
#if VMS_DEBUG
690
  vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos));
691
#endif
692
 
693
  PRIV (pushed_size) = 0;
694
  PRIV (push_level)--;
695
}
696
 
697
/* Flush unwritten output, ends current record.  */
698
 
699
void
700
_bfd_vms_output_flush (bfd * abfd)
701
{
702
  int real_size = PRIV (output_size);
703
  int aligncount;
704
  int length;
705
 
706
#if VMS_DEBUG
707
  vms_debug (6, "_bfd_vms_output_flush (real_size = %d, pushed_size %d at lenpos %d)\n",
708
              real_size, PRIV (pushed_size), PRIV (length_pos));
709
#endif
710
 
711
  if (PRIV (push_level) > 0)
712
    length = real_size - PRIV (pushed_size);
713
  else
714
    length = real_size;
715
 
716
  if (length == 0)
717
    return;
718
  aligncount = (PRIV (output_alignment)
719
                - (length % PRIV (output_alignment))) % PRIV (output_alignment);
720
 
721
#if VMS_DEBUG
722
  vms_debug (6, "align: adding %d bytes\n", aligncount);
723
#endif
724
 
725
  while (aligncount-- > 0)
726
    {
727
      PRIV (output_buf)[real_size++] = 0;
728
      length++;
729
    }
730
 
731
  /* Put length to buffer.  */
732
  PRIV (output_size) = PRIV (length_pos);
733
  _bfd_vms_output_short (abfd, (unsigned int) length);
734
 
735
  if (PRIV (push_level) == 0)
736
    {
737
      /* File is open in undefined (UDF) format on VMS, but ultimately will be
738
         converted to variable length (VAR) format.  VAR format has a length
739
         word first which must be explicitly output in UDF format.  */
740
      bfd_bwrite (PRIV (output_buf) + 2, 2, abfd);
741
      bfd_bwrite (PRIV (output_buf), (size_t) real_size, abfd);
742
      PRIV (output_size) = 0;
743
    }
744
  else
745
    {
746
      PRIV (output_size) = real_size;
747
      PRIV (pushed_size) = PRIV (output_size);
748
    }
749
}
750
 
751
/* End record output.   */
752
 
753
void
754
_bfd_vms_output_end (bfd * abfd)
755
{
756
#if VMS_DEBUG
757
  vms_debug (6, "_bfd_vms_output_end\n");
758
#endif
759
 
760
  _bfd_vms_output_flush (abfd);
761
}
762
 
763
/* Check remaining buffer size
764
 
765
   Return what's left.  */
766
 
767
int
768
_bfd_vms_output_check (bfd * abfd, int size)
769
{
770
#if VMS_DEBUG
771
  vms_debug (6, "_bfd_vms_output_check (%d)\n", size);
772
#endif
773
 
774
  return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
775
}
776
 
777
/* Output byte (8 bit) value.  */
778
 
779
void
780
_bfd_vms_output_byte (bfd * abfd, unsigned int value)
781
{
782
#if VMS_DEBUG
783
  vms_debug (6, "_bfd_vms_output_byte (%02x)\n", value);
784
#endif
785
 
786
  bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
787
  PRIV (output_size) += 1;
788
}
789
 
790
/* Output short (16 bit) value.  */
791
 
792
void
793
_bfd_vms_output_short (bfd * abfd, unsigned int value)
794
{
795
#if VMS_DEBUG
796
  vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
797
#endif
798
 
799
  bfd_put_16 (abfd, (bfd_vma) value & 0xffff,
800
              PRIV (output_buf) + PRIV (output_size));
801
  PRIV (output_size) += 2;
802
}
803
 
804
/* Output long (32 bit) value.  */
805
 
806
void
807
_bfd_vms_output_long (bfd * abfd, unsigned long value)
808
{
809
#if VMS_DEBUG
810
  vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
811
#endif
812
 
813
  bfd_put_32 (abfd, (bfd_vma) value, PRIV (output_buf) + PRIV (output_size));
814
  PRIV (output_size) += 4;
815
}
816
 
817
/* Output quad (64 bit) value.  */
818
 
819
void
820
_bfd_vms_output_quad (bfd * abfd, uquad value)
821
{
822
#if VMS_DEBUG
823
  vms_debug (6, "_bfd_vms_output_quad (%016lx)\n", value);
824
#endif
825
 
826
  bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
827
  PRIV (output_size) += 8;
828
}
829
 
830
/* Output c-string as counted string.  */
831
 
832
void
833
_bfd_vms_output_counted (bfd * abfd, char *value)
834
{
835
  int len;
836
 
837
#if VMS_DEBUG
838
  vms_debug (6, "_bfd_vms_output_counted (%s)\n", value);
839
#endif
840
 
841
  len = strlen (value);
842
  if (len == 0)
843
    {
844
      (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
845
      return;
846
    }
847
  if (len > 255)
848
    {
849
      (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
850
      return;
851
    }
852
  _bfd_vms_output_byte (abfd, (unsigned int) len & 0xff);
853
  _bfd_vms_output_dump (abfd, (unsigned char *) value, len);
854
}
855
 
856
/* Output character area.  */
857
 
858
void
859
_bfd_vms_output_dump (bfd * abfd,
860
                      unsigned char *data,
861
                      int length)
862
{
863
#if VMS_DEBUG
864
  vms_debug (6, "_bfd_vms_output_dump (%d)\n", length);
865
#endif
866
 
867
  if (length == 0)
868
    return;
869
 
870
  memcpy (PRIV (output_buf) + PRIV (output_size), data, (size_t) length);
871
  PRIV (output_size) += length;
872
}
873
 
874
/* Output count bytes of value.  */
875
 
876
void
877
_bfd_vms_output_fill (bfd * abfd,
878
                      int value,
879
                      int count)
880
{
881
#if VMS_DEBUG
882
  vms_debug (6, "_bfd_vms_output_fill (val %02x times %d)\n", value, count);
883
#endif
884
 
885
  if (count == 0)
886
    return;
887
  memset (PRIV (output_buf) + PRIV (output_size), value, (size_t) count);
888
  PRIV (output_size) += count;
889
}
890
 
891
/* This hash routine borrowed from GNU-EMACS, and strengthened slightly.  ERY.  */
892
 
893
static int
894
hash_string (const char *ptr)
895
{
896
  const unsigned char *p = (unsigned char *) ptr;
897
  const unsigned char *end = p + strlen (ptr);
898
  unsigned char c;
899
  int hash = 0;
900
 
901
  while (p != end)
902
    {
903
      c = *p++;
904
      hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
905
    }
906
  return hash;
907
}
908
 
909
/* Generate a length-hashed VMS symbol name (limited to maxlen chars).  */
910
 
911
char *
912
_bfd_vms_length_hash_symbol (bfd * abfd, const char *in, int maxlen)
913
{
914
  unsigned long result;
915
  int in_len;
916
  char *new_name;
917
  const char *old_name;
918
  int i;
919
  static char outbuf[EOBJ_S_C_SYMSIZ+1];
920
  char *out = outbuf;
921
 
922
#if VMS_DEBUG
923
  vms_debug (4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
924
#endif
925
 
926
  if (maxlen > EOBJ_S_C_SYMSIZ)
927
    maxlen = EOBJ_S_C_SYMSIZ;
928
 
929
  /* Save this for later.  */
930
  new_name = out;
931
 
932
  /* We may need to truncate the symbol, save the hash for later.  */
933
  in_len = strlen (in);
934
 
935
  result = (in_len > maxlen) ? hash_string (in) : 0;
936
 
937
  old_name = in;
938
 
939
  /* Do the length checking.  */
940
  if (in_len <= maxlen)
941
    i = in_len;
942
  else
943
    {
944
      if (PRIV (flag_hash_long_names))
945
        i = maxlen-9;
946
      else
947
        i = maxlen;
948
    }
949
 
950
  strncpy (out, in, (size_t) i);
951
  in += i;
952
  out += i;
953
 
954
  if ((in_len > maxlen)
955
      && PRIV (flag_hash_long_names))
956
    sprintf (out, "_%08lx", result);
957
  else
958
    *out = 0;
959
 
960
#if VMS_DEBUG
961
  vms_debug (4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
962
#endif
963
 
964
  if (in_len > maxlen
965
        && PRIV (flag_hash_long_names)
966
        && PRIV (flag_show_after_trunc))
967
    printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
968
 
969
  return outbuf;
970
}
971
 
972
/* Allocate and initialize a new symbol.  */
973
 
974
static asymbol *
975
new_symbol (bfd * abfd, char *name)
976
{
977
  asymbol *symbol;
978
 
979
#if VMS_DEBUG
980
  _bfd_vms_debug (7,  "new_symbol %s\n", name);
981
#endif
982
 
983
  symbol = bfd_make_empty_symbol (abfd);
984
  if (symbol == 0)
985
    return symbol;
986
  symbol->name = name;
987
  symbol->section = (asection *)(unsigned long)-1;
988
 
989
  return symbol;
990
}
991
 
992
/* Allocate and enter a new private symbol.  */
993
 
994
vms_symbol_entry *
995
_bfd_vms_enter_symbol (bfd * abfd, char *name)
996
{
997
  vms_symbol_entry *entry;
998
 
999
#if VMS_DEBUG
1000
  _bfd_vms_debug (6,  "_bfd_vms_enter_symbol %s\n", name);
1001
#endif
1002
 
1003
  entry = (vms_symbol_entry *)
1004
          bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE);
1005
  if (entry == 0)
1006
    {
1007
#if VMS_DEBUG
1008
      _bfd_vms_debug (8,  "creating hash entry for %s\n", name);
1009
#endif
1010
      entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
1011
                                                    name, TRUE, FALSE);
1012
      if (entry != 0)
1013
        {
1014
          asymbol *symbol;
1015
          symbol = new_symbol (abfd, name);
1016
          if (symbol != 0)
1017
            {
1018
              entry->symbol = symbol;
1019
              PRIV (gsd_sym_count)++;
1020
              abfd->symcount++;
1021
            }
1022
          else
1023
            entry = 0;
1024
        }
1025
      else
1026
        (*_bfd_error_handler) (_("failed to enter %s"), name);
1027
    }
1028
  else
1029
    {
1030
#if VMS_DEBUG
1031
      _bfd_vms_debug (8,  "found hash entry for %s\n", name);
1032
#endif
1033
    }
1034
 
1035
#if VMS_DEBUG
1036
  _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1037
#endif
1038
  return entry;
1039
}

powered by: WebSVN 2.1.0

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