source: branches/libc-0.6/src/binutils/bfd/vms-misc.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 24.2 KB
Line 
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
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, 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
33static vms_section *add_new_contents PARAMS ((bfd *, sec_ptr));
34static int hash_string PARAMS ((const char *));
35static 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__
57void
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
93void
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
131void
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
176/* hash functions
177
178 These are needed when reading an object file. */
179
180/* allocate new vms_hash_entry
181 keep the symbol name and a pointer to the bfd symbol in the table */
182
183struct bfd_hash_entry *
184_bfd_vms_hash_newfunc (entry, table, string)
185 struct bfd_hash_entry *entry;
186 struct bfd_hash_table *table;
187 const char *string;
188{
189 vms_symbol_entry *ret;
190
191#if VMS_DEBUG
192 vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string);
193#endif
194
195 if (entry == (struct bfd_hash_entry *)NULL)
196 {
197 ret = (vms_symbol_entry *)
198 bfd_hash_allocate (table, sizeof (vms_symbol_entry));
199 if (ret == (vms_symbol_entry *) NULL)
200 {
201 bfd_set_error (bfd_error_no_memory);
202 return (struct bfd_hash_entry *)NULL;
203 }
204 entry = (struct bfd_hash_entry *) ret;
205 }
206
207 /* Call the allocation method of the base class. */
208
209 ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
210#if VMS_DEBUG
211 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
212#endif
213
214 ret->symbol = (asymbol *)NULL;
215
216 return (struct bfd_hash_entry *)ret;
217}
218
219
220/* object file input functions */
221
222/* Return type and length from record header (buf) on Alpha. */
223
224void
225_bfd_vms_get_header_values (abfd, buf, type, length)
226 bfd *abfd ATTRIBUTE_UNUSED;
227 unsigned char *buf;
228 int *type;
229 int *length;
230{
231 if (type != 0)
232 *type = bfd_getl16 (buf);
233 buf += 2;
234 if (length != 0)
235 *length = bfd_getl16 (buf);
236
237#if VMS_DEBUG
238 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
239#endif
240
241 return;
242}
243
244/* Get next record from object file to vms_buf
245 set PRIV(buf_size) and return it
246
247 this is a little tricky since it should be portable.
248
249 the openVMS object file has 'variable length' which means that
250 read() returns data in chunks of (hopefully) correct and expected
251 size. The linker (and other tools on vms) depend on that. Unix doesn't
252 know about 'formatted' files, so reading and writing such an object
253 file in a unix environment is not trivial.
254
255 With the tool 'file' (available on all vms ftp sites), one
256 can view and change the attributes of a file. Changing from
257 'variable length' to 'fixed length, 512 bytes' reveals the
258 record length at the first 2 bytes of every record. The same
259 happens during the transfer of object files from vms to unix,
260 at least with ucx, dec's implementation of tcp/ip.
261
262 The vms format repeats the length at bytes 2 & 3 of every record.
263
264 On the first call (file_format == FF_UNKNOWN) we check if
265 the first and the third byte pair (!) of the record match.
266 If they do it's an object file in an unix environment or with
267 wrong attributes (FF_FOREIGN), else we should be in a vms
268 environment where read() returns the record size (FF_NATIVE).
269
270 reading is always done in 2 steps.
271 first just the record header is read and the length extracted
272 by get_header_values
273 then the read buffer is adjusted and the remaining bytes are
274 read in.
275
276 all file i/o is always done on even file positions */
277
278int
279_bfd_vms_get_record (abfd)
280 bfd *abfd;
281{
282 int test_len, test_start, remaining;
283 unsigned char *vms_buf;
284
285#if VMS_DEBUG
286 vms_debug (8, "_bfd_vms_get_record\n");
287#endif
288
289 /* minimum is 6 bytes on Alpha
290 (2 bytes length, 2 bytes record id, 2 bytes length repeated)
291
292 on VAX there's no length information in the record
293 so start with OBJ_S_C_MAXRECSIZ */
294
295 if (PRIV (buf_size) == 0)
296 {
297 bfd_size_type amt;
298
299 if (PRIV (is_vax))
300 {
301 amt = OBJ_S_C_MAXRECSIZ;
302 PRIV (file_format) = FF_VAX;
303 }
304 else
305 amt = 6;
306 PRIV (vms_buf) = (unsigned char *) bfd_malloc (amt);
307 PRIV (buf_size) = amt;
308 }
309
310 vms_buf = PRIV (vms_buf);
311
312 if (vms_buf == 0)
313 return -1;
314
315 switch (PRIV (file_format))
316 {
317 case FF_UNKNOWN:
318 case FF_FOREIGN:
319 test_len = 6; /* probe 6 bytes */
320 test_start = 2; /* where the record starts */
321 break;
322
323 case FF_NATIVE:
324 test_len = 4;
325 test_start = 0;
326 break;
327
328 default:
329 case FF_VAX:
330 test_len = 0;
331 test_start = 0;
332 break;
333 }
334
335 /* skip odd alignment byte */
336
337 if (bfd_tell (abfd) & 1)
338 {
339 if (bfd_bread (PRIV (vms_buf), (bfd_size_type) 1, abfd) != 1)
340 {
341 bfd_set_error (bfd_error_file_truncated);
342 return 0;
343 }
344 }
345
346 /* read the record header on Alpha. */
347
348 if ((test_len != 0)
349 && (bfd_bread (PRIV (vms_buf), (bfd_size_type) test_len, abfd)
350 != (bfd_size_type) test_len))
351 {
352 bfd_set_error (bfd_error_file_truncated);
353 return 0;
354 }
355
356 /* check file format on first call */
357
358 if (PRIV (file_format) == FF_UNKNOWN)
359 { /* record length repeats ? */
360 if (vms_buf[0] == vms_buf[4]
361 && vms_buf[1] == vms_buf[5])
362 {
363 PRIV (file_format) = FF_FOREIGN; /* Y: foreign environment */
364 test_start = 2;
365 }
366 else
367 {
368 PRIV (file_format) = FF_NATIVE; /* N: native environment */
369 test_start = 0;
370 }
371 }
372
373 if (PRIV (is_vax))
374 {
375 PRIV (rec_length) = bfd_bread (vms_buf, (bfd_size_type) PRIV (buf_size),
376 abfd);
377 if (PRIV (rec_length) <= 0)
378 {
379 bfd_set_error (bfd_error_file_truncated);
380 return 0;
381 }
382 PRIV (vms_rec) = vms_buf;
383 }
384 else /* Alpha */
385 {
386 /* extract vms record length */
387
388 _bfd_vms_get_header_values (abfd, vms_buf + test_start, NULL,
389 &PRIV (rec_length));
390
391 if (PRIV (rec_length) <= 0)
392 {
393 bfd_set_error (bfd_error_file_truncated);
394 return 0;
395 }
396
397 /* that's what the linker manual says */
398
399 if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ)
400 {
401 bfd_set_error (bfd_error_file_truncated);
402 return 0;
403 }
404
405 /* adjust the buffer */
406
407 if (PRIV (rec_length) > PRIV (buf_size))
408 {
409 PRIV (vms_buf) = ((unsigned char *)
410 bfd_realloc (vms_buf,
411 (bfd_size_type) PRIV (rec_length)));
412 vms_buf = PRIV (vms_buf);
413 if (vms_buf == 0)
414 return -1;
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
444int
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
489/* Copy sized string (string with fixed length) to new allocated area
490 size is string length (size of record) */
491
492char *
493_bfd_vms_save_sized_string (str, size)
494 unsigned char *str;
495 int size;
496{
497 char *newstr = bfd_malloc ((bfd_size_type) size + 1);
498
499 if (newstr == NULL)
500 return 0;
501 strncpy (newstr, (char *) str, (size_t) size);
502 newstr[size] = 0;
503
504 return newstr;
505}
506
507/* Copy counted string (string with length at first byte) to new allocated area
508 ptr points to length byte on entry */
509
510char *
511_bfd_vms_save_counted_string (ptr)
512 unsigned char *ptr;
513{
514 int len = *ptr++;
515
516 return _bfd_vms_save_sized_string (ptr, len);
517}
518
519
520/* stack routines for vms ETIR commands */
521
522/* Push value and section index */
523
524void
525_bfd_vms_push (abfd, val, psect)
526 bfd *abfd;
527 uquad val;
528 int psect;
529{
530 static int last_psect;
531
532#if VMS_DEBUG
533 vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV (stackptr));
534#endif
535
536 if (psect >= 0)
537 last_psect = psect;
538
539 PRIV (stack[PRIV (stackptr)]).value = val;
540 PRIV (stack[PRIV (stackptr)]).psect = last_psect;
541 PRIV (stackptr)++;
542 if (PRIV (stackptr) >= STACKSIZE)
543 {
544 bfd_set_error (bfd_error_bad_value);
545 (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
546 exit (1);
547 }
548 return;
549}
550
551/* Pop value and section index */
552
553uquad
554_bfd_vms_pop (abfd, psect)
555 bfd *abfd;
556 int *psect;
557{
558 uquad value;
559
560 if (PRIV (stackptr) == 0)
561 {
562 bfd_set_error (bfd_error_bad_value);
563 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
564 exit (1);
565 }
566 PRIV (stackptr)--;
567 value = PRIV (stack[PRIV (stackptr)]).value;
568 if ((psect != NULL) && (PRIV (stack[PRIV (stackptr)]).psect >= 0))
569 *psect = PRIV (stack[PRIV (stackptr)]).psect;
570
571#if VMS_DEBUG
572 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect);
573#endif
574
575 return value;
576}
577
578
579/* object file output functions */
580
581/* GAS tends to write sections in little chunks (bfd_set_section_contents)
582 which we can't use directly. So we save the little chunks in linked
583 lists (one per section) and write them later. */
584
585/* Add a new vms_section structure to vms_section_table
586 - forward chaining - */
587
588static vms_section *
589add_new_contents (abfd, section)
590 bfd *abfd;
591 sec_ptr section;
592{
593 vms_section *sptr, *newptr;
594
595 sptr = PRIV (vms_section_table)[section->index];
596 if (sptr != NULL)
597 return sptr;
598
599 newptr = (vms_section *) bfd_alloc (abfd,
600 (bfd_size_type) sizeof (vms_section));
601 if (newptr == (vms_section *) NULL)
602 return NULL;
603 newptr->contents = (unsigned char *) bfd_alloc (abfd, section->_raw_size);
604 if (newptr->contents == (unsigned char *) NULL)
605 return NULL;
606 newptr->offset = 0;
607 newptr->size = section->_raw_size;
608 newptr->next = 0;
609 PRIV (vms_section_table)[section->index] = newptr;
610 return newptr;
611}
612
613/* Save section data & offset to a vms_section structure
614 vms_section_table[] holds the vms_section chain. */
615
616bfd_boolean
617_bfd_save_vms_section (abfd, section, data, offset, count)
618 bfd *abfd;
619 sec_ptr section;
620 PTR data;
621 file_ptr offset;
622 bfd_size_type count;
623{
624 vms_section *sptr;
625
626 if (section->index >= VMS_SECTION_COUNT)
627 {
628 bfd_set_error (bfd_error_nonrepresentable_section);
629 return FALSE;
630 }
631 if (count == (bfd_size_type)0)
632 return TRUE;
633 sptr = add_new_contents (abfd, section);
634 if (sptr == NULL)
635 return FALSE;
636 memcpy (sptr->contents + offset, data, (size_t) count);
637
638 return TRUE;
639}
640
641/* Get vms_section pointer to saved contents for section # index */
642
643vms_section *
644_bfd_get_vms_section (abfd, index)
645 bfd *abfd;
646 int index;
647{
648 if (index >= VMS_SECTION_COUNT)
649 {
650 bfd_set_error (bfd_error_nonrepresentable_section);
651 return NULL;
652 }
653 return PRIV (vms_section_table)[index];
654}
655
656
657/* Object output routines */
658
659/* Begin new record or record header
660 write 2 bytes rectype
661 write 2 bytes record length (filled in at flush)
662 write 2 bytes header type (ommitted if rechead == -1) */
663
664void
665_bfd_vms_output_begin (abfd, rectype, rechead)
666 bfd *abfd;
667 int rectype;
668 int rechead;
669{
670#if VMS_DEBUG
671 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
672 rechead);
673#endif
674
675 _bfd_vms_output_short (abfd, (unsigned int) rectype);
676
677 /* save current output position to fill in lenght later */
678
679 if (PRIV (push_level) > 0)
680 PRIV (length_pos) = PRIV (output_size);
681
682#if VMS_DEBUG
683 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
684 PRIV (length_pos));
685#endif
686
687 _bfd_vms_output_short (abfd, 0); /* placeholder for length */
688
689 if (rechead != -1)
690 _bfd_vms_output_short (abfd, (unsigned int) rechead);
691
692 return;
693}
694
695/* Set record/subrecord alignment */
696
697void
698_bfd_vms_output_alignment (abfd, alignto)
699 bfd *abfd;
700 int alignto;
701{
702#if VMS_DEBUG
703 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
704#endif
705
706 PRIV (output_alignment) = alignto;
707 return;
708}
709
710/* Prepare for subrecord fields */
711
712void
713_bfd_vms_output_push (abfd)
714 bfd *abfd;
715{
716#if VMS_DEBUG
717 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV (output_size));
718#endif
719
720 PRIV (push_level)++;
721 PRIV (pushed_size) = PRIV (output_size);
722 return;
723}
724
725/* End of subrecord fields */
726
727void
728_bfd_vms_output_pop (abfd)
729 bfd *abfd;
730{
731#if VMS_DEBUG
732 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV (pushed_size));
733#endif
734
735 _bfd_vms_output_flush (abfd);
736 PRIV (length_pos) = 2;
737
738#if VMS_DEBUG
739 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos));
740#endif
741
742 PRIV (pushed_size) = 0;
743 PRIV (push_level)--;
744 return;
745}
746
747/* Flush unwritten output, ends current record */
748
749void
750_bfd_vms_output_flush (abfd)
751 bfd *abfd;
752{
753 int real_size = PRIV (output_size);
754 int aligncount;
755 int length;
756
757#if VMS_DEBUG
758 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
759 real_size, PRIV (pushed_size), PRIV (length_pos));
760#endif
761
762 if (PRIV (push_level) > 0)
763 length = real_size - PRIV (pushed_size);
764 else
765 length = real_size;
766
767 if (length == 0)
768 return;
769 aligncount = (PRIV (output_alignment)
770 - (length % PRIV (output_alignment))) % PRIV (output_alignment);
771
772#if VMS_DEBUG
773 vms_debug (6, "align: adding %d bytes\n", aligncount);
774#endif
775
776 while (aligncount-- > 0)
777 {
778 PRIV (output_buf)[real_size++] = 0;
779#if 0
780 /* this is why I *love* vms: inconsistency :-}
781 alignment is added to the subrecord length
782 but not to the record length */
783 if (PRIV (push_level) > 0)
784#endif
785 length++;
786 }
787
788 /* put length to buffer */
789 PRIV (output_size) = PRIV (length_pos);
790 _bfd_vms_output_short (abfd, (unsigned int) length);
791
792 if (PRIV (push_level) == 0)
793 {
794#ifndef VMS
795 /* write length first, see FF_FOREIGN in the input routines */
796 fwrite (PRIV (output_buf) + 2, 2, 1, (FILE *) abfd->iostream);
797#endif
798 fwrite (PRIV (output_buf), (size_t) real_size, 1,
799 (FILE *) abfd->iostream);
800
801 PRIV (output_size) = 0;
802 }
803 else
804 {
805 PRIV (output_size) = real_size;
806 PRIV (pushed_size) = PRIV (output_size);
807 }
808
809 return;
810}
811
812/* End record output */
813
814void
815_bfd_vms_output_end (abfd)
816 bfd *abfd;
817{
818#if VMS_DEBUG
819 vms_debug (6, "_bfd_vms_output_end\n");
820#endif
821
822 _bfd_vms_output_flush (abfd);
823
824 return;
825}
826
827/* check remaining buffer size
828
829 return what's left. */
830
831int
832_bfd_vms_output_check (abfd, size)
833 bfd *abfd;
834 int size;
835{
836#if VMS_DEBUG
837 vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
838#endif
839
840 return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
841}
842
843/* Output byte (8 bit) value */
844
845void
846_bfd_vms_output_byte (abfd, value)
847 bfd *abfd;
848 unsigned int value;
849{
850#if VMS_DEBUG
851 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
852#endif
853
854 bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
855 PRIV (output_size) += 1;
856 return;
857}
858
859/* Output short (16 bit) value */
860
861void
862_bfd_vms_output_short (abfd, value)
863 bfd *abfd;
864 unsigned int value;
865{
866#if VMS_DEBUG
867 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
868#endif
869
870 bfd_put_16 (abfd, (bfd_vma) value & 0xffff,
871 PRIV (output_buf) + PRIV (output_size));
872 PRIV (output_size) += 2;
873 return;
874}
875
876/* Output long (32 bit) value */
877
878void
879_bfd_vms_output_long (abfd, value)
880 bfd *abfd;
881 unsigned long value;
882{
883#if VMS_DEBUG
884 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
885#endif
886
887 bfd_put_32 (abfd, (bfd_vma) value, PRIV (output_buf) + PRIV (output_size));
888 PRIV (output_size) += 4;
889 return;
890}
891
892/* Output quad (64 bit) value */
893
894void
895_bfd_vms_output_quad (abfd, value)
896 bfd *abfd;
897 uquad value;
898{
899#if VMS_DEBUG
900 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
901#endif
902
903 bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
904 PRIV (output_size) += 8;
905 return;
906}
907
908/* Output c-string as counted string */
909
910void
911_bfd_vms_output_counted (abfd, value)
912 bfd *abfd;
913 char *value;
914{
915int len;
916
917#if VMS_DEBUG
918 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
919#endif
920
921 len = strlen (value);
922 if (len == 0)
923 {
924 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
925 return;
926 }
927 if (len > 255)
928 {
929 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
930 return;
931 }
932 _bfd_vms_output_byte (abfd, (unsigned int) len & 0xff);
933 _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
934}
935
936/* Output character area */
937
938void
939_bfd_vms_output_dump (abfd, data, length)
940 bfd *abfd;
941 unsigned char *data;
942 int length;
943{
944#if VMS_DEBUG
945 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
946#endif
947
948 if (length == 0)
949 return;
950
951 memcpy (PRIV (output_buf) + PRIV (output_size), data, (size_t) length);
952 PRIV (output_size) += length;
953
954 return;
955}
956
957/* Output count bytes of value */
958
959void
960_bfd_vms_output_fill (abfd, value, count)
961 bfd *abfd;
962 int value;
963 int count;
964{
965#if VMS_DEBUG
966 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
967#endif
968
969 if (count == 0)
970 return;
971 memset (PRIV (output_buf) + PRIV (output_size), value, (size_t) count);
972 PRIV (output_size) += count;
973
974 return;
975}
976
977/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
978
979static int
980hash_string (ptr)
981 const char *ptr;
982{
983 register const unsigned char *p = (unsigned char *) ptr;
984 register const unsigned char *end = p + strlen (ptr);
985 register unsigned char c;
986 register int hash = 0;
987
988 while (p != end)
989 {
990 c = *p++;
991 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
992 }
993 return hash;
994}
995
996/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
997
998char *
999_bfd_vms_length_hash_symbol (abfd, in, maxlen)
1000 bfd *abfd;
1001 const char *in;
1002 int maxlen;
1003{
1004 long int result;
1005 int in_len;
1006 char *new_name;
1007 const char *old_name;
1008 int i;
1009 static char outbuf[EOBJ_S_C_SYMSIZ+1];
1010 char *out = outbuf;
1011
1012#if VMS_DEBUG
1013 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1014#endif
1015
1016 if (maxlen > EOBJ_S_C_SYMSIZ)
1017 maxlen = EOBJ_S_C_SYMSIZ;
1018
1019 new_name = out; /* save this for later. */
1020
1021 /* We may need to truncate the symbol, save the hash for later. */
1022
1023 in_len = strlen (in);
1024
1025 result = (in_len > maxlen) ? hash_string (in) : 0;
1026
1027 old_name = in;
1028
1029 /* Do the length checking. */
1030
1031 if (in_len <= maxlen)
1032 {
1033 i = in_len;
1034 }
1035 else
1036 {
1037 if (PRIV (flag_hash_long_names))
1038 i = maxlen-9;
1039 else
1040 i = maxlen;
1041 }
1042
1043 strncpy (out, in, (size_t) i);
1044 in += i;
1045 out += i;
1046
1047 if ((in_len > maxlen)
1048 && PRIV (flag_hash_long_names))
1049 sprintf (out, "_%08lx", result);
1050 else
1051 *out = 0;
1052
1053#if VMS_DEBUG
1054 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1055#endif
1056
1057 if (in_len > maxlen
1058 && PRIV (flag_hash_long_names)
1059 && PRIV (flag_show_after_trunc))
1060 printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1061
1062 return outbuf;
1063}
1064
1065/* Allocate and initialize a new symbol. */
1066
1067static asymbol *
1068new_symbol (abfd, name)
1069 bfd *abfd;
1070 char *name;
1071{
1072 asymbol *symbol;
1073
1074#if VMS_DEBUG
1075 _bfd_vms_debug (7, "new_symbol %s\n", name);
1076#endif
1077
1078 symbol = bfd_make_empty_symbol (abfd);
1079 if (symbol == 0)
1080 return symbol;
1081 symbol->name = name;
1082 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1083
1084 return symbol;
1085}
1086
1087/* Allocate and enter a new private symbol. */
1088
1089vms_symbol_entry *
1090_bfd_vms_enter_symbol (abfd, name)
1091 bfd *abfd;
1092 char *name;
1093{
1094 vms_symbol_entry *entry;
1095
1096#if VMS_DEBUG
1097 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1098#endif
1099
1100 entry = (vms_symbol_entry *)
1101 bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE);
1102 if (entry == 0)
1103 {
1104#if VMS_DEBUG
1105 _bfd_vms_debug (8, "creating hash entry for %s\n", name);
1106#endif
1107 entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
1108 name, TRUE, FALSE);
1109 if (entry != 0)
1110 {
1111 asymbol *symbol;
1112 symbol = new_symbol (abfd, name);
1113 if (symbol != 0)
1114 {
1115 entry->symbol = symbol;
1116 PRIV (gsd_sym_count)++;
1117 abfd->symcount++;
1118 }
1119 else
1120 entry = 0;
1121 }
1122 else
1123 (*_bfd_error_handler) (_("failed to enter %s"), name);
1124 }
1125 else
1126 {
1127#if VMS_DEBUG
1128 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1129#endif
1130 }
1131
1132#if VMS_DEBUG
1133 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1134#endif
1135 return entry;
1136}
Note: See TracBrowser for help on using the repository browser.