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