~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to binutils/bfd/vms-misc.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

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