* aout-arm.c, aout-target.h, aoutx.h, archive.c, armnetbsd.c,
[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, 2000, 2001, 2002, 2003, 2004
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 indentation 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 \f
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 \f
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 bfd_size_type amt;
296
297 if (PRIV (is_vax))
298 {
299 amt = OBJ_S_C_MAXRECSIZ;
300 PRIV (file_format) = FF_VAX;
301 }
302 else
303 amt = 6;
304 PRIV (vms_buf) = (unsigned char *) bfd_malloc (amt);
305 PRIV (buf_size) = amt;
306 }
307
308 vms_buf = PRIV (vms_buf);
309
310 if (vms_buf == 0)
311 return -1;
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 bfd_realloc (vms_buf,
409 (bfd_size_type) PRIV (rec_length)));
410 vms_buf = PRIV (vms_buf);
411 if (vms_buf == 0)
412 return -1;
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_bread remaining %d\n", remaining);
422 #endif
423 if (bfd_bread (vms_buf + test_len, (bfd_size_type) 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_bread rec_length %d\n", PRIV (rec_length));
434 #endif
435
436 return PRIV (rec_length);
437 }
438
439 /* get next vms record from file
440 update vms_rec and rec_length to new (remaining) values */
441
442 int
443 _bfd_vms_next_record (abfd)
444 bfd *abfd;
445 {
446 #if VMS_DEBUG
447 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
448 PRIV (rec_length), PRIV (rec_size));
449 #endif
450
451 if (PRIV (rec_length) > 0)
452 {
453 PRIV (vms_rec) += PRIV (rec_size);
454 }
455 else
456 {
457 if (_bfd_vms_get_record (abfd) <= 0)
458 return -1;
459 }
460
461 if (!PRIV (vms_rec) || !PRIV (vms_buf)
462 || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
463 return -1;
464
465 if (PRIV (is_vax))
466 {
467 PRIV (rec_type) = *(PRIV (vms_rec));
468 PRIV (rec_size) = PRIV (rec_length);
469 }
470 else
471 {
472 _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type),
473 &PRIV (rec_size));
474 }
475 PRIV (rec_length) -= PRIV (rec_size);
476
477 #if VMS_DEBUG
478 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
479 PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length),
480 PRIV (rec_type));
481 #endif
482
483 return PRIV (rec_type);
484 }
485 \f
486 /* Copy sized string (string with fixed length) to new allocated area
487 size is string length (size of record) */
488
489 char *
490 _bfd_vms_save_sized_string (str, size)
491 unsigned char *str;
492 int size;
493 {
494 char *newstr = bfd_malloc ((bfd_size_type) size + 1);
495
496 if (newstr == NULL)
497 return 0;
498 strncpy (newstr, (char *) str, (size_t) size);
499 newstr[size] = 0;
500
501 return newstr;
502 }
503
504 /* Copy counted string (string with length at first byte) to new allocated area
505 ptr points to length byte on entry */
506
507 char *
508 _bfd_vms_save_counted_string (ptr)
509 unsigned char *ptr;
510 {
511 int len = *ptr++;
512
513 return _bfd_vms_save_sized_string (ptr, len);
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 /* Pop value and section index */
548
549 uquad
550 _bfd_vms_pop (abfd, psect)
551 bfd *abfd;
552 int *psect;
553 {
554 uquad value;
555
556 if (PRIV (stackptr) == 0)
557 {
558 bfd_set_error (bfd_error_bad_value);
559 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
560 exit (1);
561 }
562 PRIV (stackptr)--;
563 value = PRIV (stack[PRIV (stackptr)]).value;
564 if ((psect != NULL) && (PRIV (stack[PRIV (stackptr)]).psect >= 0))
565 *psect = PRIV (stack[PRIV (stackptr)]).psect;
566
567 #if VMS_DEBUG
568 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect);
569 #endif
570
571 return value;
572 }
573 \f
574 /* object file output functions */
575
576 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
577 which we can't use directly. So we save the little chunks in linked
578 lists (one per section) and write them later. */
579
580 /* Add a new vms_section structure to vms_section_table
581 - forward chaining - */
582
583 static vms_section *
584 add_new_contents (abfd, section)
585 bfd *abfd;
586 sec_ptr section;
587 {
588 vms_section *sptr, *newptr;
589
590 sptr = PRIV (vms_section_table)[section->index];
591 if (sptr != NULL)
592 return sptr;
593
594 newptr = (vms_section *) bfd_alloc (abfd,
595 (bfd_size_type) sizeof (vms_section));
596 if (newptr == (vms_section *) NULL)
597 return NULL;
598 newptr->contents = (unsigned char *) bfd_alloc (abfd, section->size);
599 if (newptr->contents == (unsigned char *) NULL)
600 return NULL;
601 newptr->offset = 0;
602 newptr->size = section->size;
603 newptr->next = 0;
604 PRIV (vms_section_table)[section->index] = newptr;
605 return newptr;
606 }
607
608 /* Save section data & offset to a vms_section structure
609 vms_section_table[] holds the vms_section chain. */
610
611 bfd_boolean
612 _bfd_save_vms_section (abfd, section, data, offset, count)
613 bfd *abfd;
614 sec_ptr section;
615 const PTR data;
616 file_ptr offset;
617 bfd_size_type count;
618 {
619 vms_section *sptr;
620
621 if (section->index >= VMS_SECTION_COUNT)
622 {
623 bfd_set_error (bfd_error_nonrepresentable_section);
624 return FALSE;
625 }
626 if (count == (bfd_size_type)0)
627 return TRUE;
628 sptr = add_new_contents (abfd, section);
629 if (sptr == NULL)
630 return FALSE;
631 memcpy (sptr->contents + offset, data, (size_t) count);
632
633 return TRUE;
634 }
635
636 /* Get vms_section pointer to saved contents for section # index */
637
638 vms_section *
639 _bfd_get_vms_section (abfd, index)
640 bfd *abfd;
641 int index;
642 {
643 if (index >= VMS_SECTION_COUNT)
644 {
645 bfd_set_error (bfd_error_nonrepresentable_section);
646 return NULL;
647 }
648 return PRIV (vms_section_table)[index];
649 }
650 \f
651 /* Object output routines */
652
653 /* Begin new record or record header
654 write 2 bytes rectype
655 write 2 bytes record length (filled in at flush)
656 write 2 bytes header type (ommitted if rechead == -1) */
657
658 void
659 _bfd_vms_output_begin (abfd, rectype, rechead)
660 bfd *abfd;
661 int rectype;
662 int rechead;
663 {
664 #if VMS_DEBUG
665 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
666 rechead);
667 #endif
668
669 _bfd_vms_output_short (abfd, (unsigned int) rectype);
670
671 /* save current output position to fill in length later */
672
673 if (PRIV (push_level) > 0)
674 PRIV (length_pos) = PRIV (output_size);
675
676 #if VMS_DEBUG
677 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
678 PRIV (length_pos));
679 #endif
680
681 _bfd_vms_output_short (abfd, 0); /* placeholder for length */
682
683 if (rechead != -1)
684 _bfd_vms_output_short (abfd, (unsigned int) rechead);
685
686 return;
687 }
688
689 /* Set record/subrecord alignment */
690
691 void
692 _bfd_vms_output_alignment (abfd, alignto)
693 bfd *abfd;
694 int alignto;
695 {
696 #if VMS_DEBUG
697 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
698 #endif
699
700 PRIV (output_alignment) = alignto;
701 return;
702 }
703
704 /* Prepare for subrecord fields */
705
706 void
707 _bfd_vms_output_push (abfd)
708 bfd *abfd;
709 {
710 #if VMS_DEBUG
711 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV (output_size));
712 #endif
713
714 PRIV (push_level)++;
715 PRIV (pushed_size) = PRIV (output_size);
716 return;
717 }
718
719 /* End of subrecord fields */
720
721 void
722 _bfd_vms_output_pop (abfd)
723 bfd *abfd;
724 {
725 #if VMS_DEBUG
726 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV (pushed_size));
727 #endif
728
729 _bfd_vms_output_flush (abfd);
730 PRIV (length_pos) = 2;
731
732 #if VMS_DEBUG
733 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos));
734 #endif
735
736 PRIV (pushed_size) = 0;
737 PRIV (push_level)--;
738 return;
739 }
740
741 /* Flush unwritten output, ends current record */
742
743 void
744 _bfd_vms_output_flush (abfd)
745 bfd *abfd;
746 {
747 int real_size = PRIV (output_size);
748 int aligncount;
749 int length;
750
751 #if VMS_DEBUG
752 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
753 real_size, PRIV (pushed_size), PRIV (length_pos));
754 #endif
755
756 if (PRIV (push_level) > 0)
757 length = real_size - PRIV (pushed_size);
758 else
759 length = real_size;
760
761 if (length == 0)
762 return;
763 aligncount = (PRIV (output_alignment)
764 - (length % PRIV (output_alignment))) % PRIV (output_alignment);
765
766 #if VMS_DEBUG
767 vms_debug (6, "align: adding %d bytes\n", aligncount);
768 #endif
769
770 while (aligncount-- > 0)
771 {
772 PRIV (output_buf)[real_size++] = 0;
773 length++;
774 }
775
776 /* put length to buffer */
777 PRIV (output_size) = PRIV (length_pos);
778 _bfd_vms_output_short (abfd, (unsigned int) length);
779
780 if (PRIV (push_level) == 0)
781 {
782 #ifndef VMS
783 /* write length first, see FF_FOREIGN in the input routines */
784 fwrite (PRIV (output_buf) + 2, 2, 1, (FILE *) abfd->iostream);
785 #endif
786 fwrite (PRIV (output_buf), (size_t) real_size, 1,
787 (FILE *) abfd->iostream);
788
789 PRIV (output_size) = 0;
790 }
791 else
792 {
793 PRIV (output_size) = real_size;
794 PRIV (pushed_size) = PRIV (output_size);
795 }
796
797 return;
798 }
799
800 /* End record output */
801
802 void
803 _bfd_vms_output_end (abfd)
804 bfd *abfd;
805 {
806 #if VMS_DEBUG
807 vms_debug (6, "_bfd_vms_output_end\n");
808 #endif
809
810 _bfd_vms_output_flush (abfd);
811
812 return;
813 }
814
815 /* check remaining buffer size
816
817 return what's left. */
818
819 int
820 _bfd_vms_output_check (abfd, size)
821 bfd *abfd;
822 int size;
823 {
824 #if VMS_DEBUG
825 vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
826 #endif
827
828 return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
829 }
830
831 /* Output byte (8 bit) value */
832
833 void
834 _bfd_vms_output_byte (abfd, value)
835 bfd *abfd;
836 unsigned int value;
837 {
838 #if VMS_DEBUG
839 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
840 #endif
841
842 bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
843 PRIV (output_size) += 1;
844 return;
845 }
846
847 /* Output short (16 bit) value */
848
849 void
850 _bfd_vms_output_short (abfd, value)
851 bfd *abfd;
852 unsigned int value;
853 {
854 #if VMS_DEBUG
855 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
856 #endif
857
858 bfd_put_16 (abfd, (bfd_vma) value & 0xffff,
859 PRIV (output_buf) + PRIV (output_size));
860 PRIV (output_size) += 2;
861 return;
862 }
863
864 /* Output long (32 bit) value */
865
866 void
867 _bfd_vms_output_long (abfd, value)
868 bfd *abfd;
869 unsigned long value;
870 {
871 #if VMS_DEBUG
872 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
873 #endif
874
875 bfd_put_32 (abfd, (bfd_vma) value, PRIV (output_buf) + PRIV (output_size));
876 PRIV (output_size) += 4;
877 return;
878 }
879
880 /* Output quad (64 bit) value */
881
882 void
883 _bfd_vms_output_quad (abfd, value)
884 bfd *abfd;
885 uquad value;
886 {
887 #if VMS_DEBUG
888 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
889 #endif
890
891 bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
892 PRIV (output_size) += 8;
893 return;
894 }
895
896 /* Output c-string as counted string */
897
898 void
899 _bfd_vms_output_counted (abfd, value)
900 bfd *abfd;
901 char *value;
902 {
903 int len;
904
905 #if VMS_DEBUG
906 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
907 #endif
908
909 len = strlen (value);
910 if (len == 0)
911 {
912 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
913 return;
914 }
915 if (len > 255)
916 {
917 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
918 return;
919 }
920 _bfd_vms_output_byte (abfd, (unsigned int) len & 0xff);
921 _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
922 }
923
924 /* Output character area */
925
926 void
927 _bfd_vms_output_dump (abfd, data, length)
928 bfd *abfd;
929 unsigned char *data;
930 int length;
931 {
932 #if VMS_DEBUG
933 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
934 #endif
935
936 if (length == 0)
937 return;
938
939 memcpy (PRIV (output_buf) + PRIV (output_size), data, (size_t) length);
940 PRIV (output_size) += length;
941
942 return;
943 }
944
945 /* Output count bytes of value */
946
947 void
948 _bfd_vms_output_fill (abfd, value, count)
949 bfd *abfd;
950 int value;
951 int count;
952 {
953 #if VMS_DEBUG
954 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
955 #endif
956
957 if (count == 0)
958 return;
959 memset (PRIV (output_buf) + PRIV (output_size), value, (size_t) count);
960 PRIV (output_size) += count;
961
962 return;
963 }
964
965 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
966
967 static int
968 hash_string (ptr)
969 const char *ptr;
970 {
971 register const unsigned char *p = (unsigned char *) ptr;
972 register const unsigned char *end = p + strlen (ptr);
973 register unsigned char c;
974 register int hash = 0;
975
976 while (p != end)
977 {
978 c = *p++;
979 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
980 }
981 return hash;
982 }
983
984 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
985
986 char *
987 _bfd_vms_length_hash_symbol (abfd, in, maxlen)
988 bfd *abfd;
989 const char *in;
990 int maxlen;
991 {
992 long int result;
993 int in_len;
994 char *new_name;
995 const char *old_name;
996 int i;
997 static char outbuf[EOBJ_S_C_SYMSIZ+1];
998 char *out = outbuf;
999
1000 #if VMS_DEBUG
1001 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1002 #endif
1003
1004 if (maxlen > EOBJ_S_C_SYMSIZ)
1005 maxlen = EOBJ_S_C_SYMSIZ;
1006
1007 new_name = out; /* save this for later. */
1008
1009 /* We may need to truncate the symbol, save the hash for later. */
1010
1011 in_len = strlen (in);
1012
1013 result = (in_len > maxlen) ? hash_string (in) : 0;
1014
1015 old_name = in;
1016
1017 /* Do the length checking. */
1018
1019 if (in_len <= maxlen)
1020 {
1021 i = in_len;
1022 }
1023 else
1024 {
1025 if (PRIV (flag_hash_long_names))
1026 i = maxlen-9;
1027 else
1028 i = maxlen;
1029 }
1030
1031 strncpy (out, in, (size_t) i);
1032 in += i;
1033 out += i;
1034
1035 if ((in_len > maxlen)
1036 && PRIV (flag_hash_long_names))
1037 sprintf (out, "_%08lx", result);
1038 else
1039 *out = 0;
1040
1041 #if VMS_DEBUG
1042 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1043 #endif
1044
1045 if (in_len > maxlen
1046 && PRIV (flag_hash_long_names)
1047 && PRIV (flag_show_after_trunc))
1048 printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1049
1050 return outbuf;
1051 }
1052
1053 /* Allocate and initialize a new symbol. */
1054
1055 static asymbol *
1056 new_symbol (abfd, name)
1057 bfd *abfd;
1058 char *name;
1059 {
1060 asymbol *symbol;
1061
1062 #if VMS_DEBUG
1063 _bfd_vms_debug (7, "new_symbol %s\n", name);
1064 #endif
1065
1066 symbol = bfd_make_empty_symbol (abfd);
1067 if (symbol == 0)
1068 return symbol;
1069 symbol->name = name;
1070 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1071
1072 return symbol;
1073 }
1074
1075 /* Allocate and enter a new private symbol. */
1076
1077 vms_symbol_entry *
1078 _bfd_vms_enter_symbol (abfd, name)
1079 bfd *abfd;
1080 char *name;
1081 {
1082 vms_symbol_entry *entry;
1083
1084 #if VMS_DEBUG
1085 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1086 #endif
1087
1088 entry = (vms_symbol_entry *)
1089 bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE);
1090 if (entry == 0)
1091 {
1092 #if VMS_DEBUG
1093 _bfd_vms_debug (8, "creating hash entry for %s\n", name);
1094 #endif
1095 entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
1096 name, TRUE, FALSE);
1097 if (entry != 0)
1098 {
1099 asymbol *symbol;
1100 symbol = new_symbol (abfd, name);
1101 if (symbol != 0)
1102 {
1103 entry->symbol = symbol;
1104 PRIV (gsd_sym_count)++;
1105 abfd->symcount++;
1106 }
1107 else
1108 entry = 0;
1109 }
1110 else
1111 (*_bfd_error_handler) (_("failed to enter %s"), name);
1112 }
1113 else
1114 {
1115 #if VMS_DEBUG
1116 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1117 #endif
1118 }
1119
1120 #if VMS_DEBUG
1121 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1122 #endif
1123 return entry;
1124 }
This page took 0.054169 seconds and 4 git commands to generate.