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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-binutils/] [binutils-2.19.1/] [bfd/] [vms-misc.c] - Blame information for rev 6

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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