source: trunk/src/binutils/bfd/vms-misc.c@ 10

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

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 23.9 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
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
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__
53void
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
89void
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/* a debug function
125 hex dump 'size' bytes starting at 'ptr' */
126
127void
128_bfd_hexdump (level, ptr, size, offset)
129 int level;
130 unsigned char *ptr;
131 int size;
132 int offset;
133{
134 unsigned char *lptr = ptr;
135 int count = 0;
136 long start = offset;
137
138 while (size-- > 0)
139 {
140 if ((count%16) == 0)
141 vms_debug (level, "%08lx:", start);
142 vms_debug (-level, " %02x", *ptr++);
143 count++;
144 start++;
145 if (size == 0)
146 {
147 while ((count%16) != 0)
148 {
149 vms_debug (-level, " ");
150 count++;
151 }
152 }
153 if ((count%16) == 0)
154 {
155 vms_debug (-level, " ");
156 while (lptr < ptr)
157 {
158 vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
159 lptr++;
160 }
161 vms_debug (-level, "\n");
162 }
163 }
164 if ((count%16) != 0)
165 vms_debug (-level, "\n");
166
167 return;
168}
169#endif
170
171
172/* hash functions
173
174 These are needed when reading an object file. */
175
176/* allocate new vms_hash_entry
177 keep the symbol name and a pointer to the bfd symbol in the table */
178
179struct bfd_hash_entry *
180_bfd_vms_hash_newfunc (entry, table, string)
181 struct bfd_hash_entry *entry;
182 struct bfd_hash_table *table;
183 const char *string;
184{
185 vms_symbol_entry *ret;
186
187#if VMS_DEBUG
188 vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string);
189#endif
190
191 if (entry == (struct bfd_hash_entry *)NULL)
192 {
193 ret = (vms_symbol_entry *)
194 bfd_hash_allocate (table, sizeof (vms_symbol_entry));
195 if (ret == (vms_symbol_entry *) NULL)
196 {
197 bfd_set_error (bfd_error_no_memory);
198 return (struct bfd_hash_entry *)NULL;
199 }
200 entry = (struct bfd_hash_entry *) ret;
201 }
202
203 /* Call the allocation method of the base class. */
204
205 ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
206#if VMS_DEBUG
207 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
208#endif
209
210 ret->symbol = (asymbol *)NULL;
211
212 return (struct bfd_hash_entry *)ret;
213}
214
215
216/* object file input functions */
217
218/* Return type and length from record header (buf) on Alpha. */
219
220void
221_bfd_vms_get_header_values (abfd, buf, type, length)
222 bfd *abfd ATTRIBUTE_UNUSED;
223 unsigned char *buf;
224 int *type;
225 int *length;
226{
227 if (type != 0)
228 *type = bfd_getl16 (buf);
229 buf += 2;
230 if (length != 0)
231 *length = bfd_getl16 (buf);
232
233#if VMS_DEBUG
234 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
235#endif
236
237 return;
238}
239
240/* Get next record from object file to vms_buf
241 set PRIV(buf_size) and return it
242
243 this is a little tricky since it should be portable.
244
245 the openVMS object file has 'variable length' which means that
246 read() returns data in chunks of (hopefully) correct and expected
247 size. The linker (and other tools on vms) depend on that. Unix doesn't
248 know about 'formatted' files, so reading and writing such an object
249 file in a unix environment is not trivial.
250
251 With the tool 'file' (available on all vms ftp sites), one
252 can view and change the attributes of a file. Changing from
253 'variable length' to 'fixed length, 512 bytes' reveals the
254 record length at the first 2 bytes of every record. The same
255 happens during the transfer of object files from vms to unix,
256 at least with ucx, dec's implementation of tcp/ip.
257
258 The vms format repeats the length at bytes 2 & 3 of every record.
259
260 On the first call (file_format == FF_UNKNOWN) we check if
261 the first and the third byte pair (!) of the record match.
262 If they do it's an object file in an unix environment or with
263 wrong attributes (FF_FOREIGN), else we should be in a vms
264 environment where read() returns the record size (FF_NATIVE).
265
266 reading is always done in 2 steps.
267 first just the record header is read and the length extracted
268 by get_header_values
269 then the read buffer is adjusted and the remaining bytes are
270 read in.
271
272 all file i/o is always done on even file positions */
273
274int
275_bfd_vms_get_record (abfd)
276 bfd *abfd;
277{
278 int test_len, test_start, remaining;
279 unsigned char *vms_buf;
280
281#if VMS_DEBUG
282 vms_debug (8, "_bfd_vms_get_record\n");
283#endif
284
285 /* minimum is 6 bytes on Alpha
286 (2 bytes length, 2 bytes record id, 2 bytes length repeated)
287
288 on VAX there's no length information in the record
289 so start with OBJ_S_C_MAXRECSIZ */
290
291 if (PRIV (buf_size) == 0)
292 {
293 if (PRIV (is_vax))
294 {
295 PRIV (vms_buf) = (unsigned char *) malloc (OBJ_S_C_MAXRECSIZ);
296 PRIV (buf_size) = OBJ_S_C_MAXRECSIZ;
297 PRIV (file_format) = FF_VAX;
298 }
299 else
300 PRIV (vms_buf) = (unsigned char *) malloc (6);
301 }
302
303 vms_buf = PRIV (vms_buf);
304
305 if (vms_buf == 0)
306 {
307 bfd_set_error (bfd_error_no_memory);
308 return -1;
309 }
310
311 switch (PRIV (file_format))
312 {
313 case FF_UNKNOWN:
314 case FF_FOREIGN:
315 test_len = 6; /* probe 6 bytes */
316 test_start = 2; /* where the record starts */
317 break;
318
319 case FF_NATIVE:
320 test_len = 4;
321 test_start = 0;
322 break;
323
324 default:
325 case FF_VAX:
326 test_len = 0;
327 test_start = 0;
328 break;
329 }
330
331 /* skip odd alignment byte */
332
333 if (bfd_tell (abfd) & 1)
334 {
335 if (bfd_read (PRIV (vms_buf), 1, 1, abfd) != 1)
336 {
337 bfd_set_error (bfd_error_file_truncated);
338 return 0;
339 }
340 }
341
342 /* read the record header on Alpha. */
343
344 if ((test_len != 0)
345 && (bfd_read (PRIV (vms_buf), 1, test_len, abfd)
346 != (bfd_size_type) test_len))
347 {
348 bfd_set_error (bfd_error_file_truncated);
349 return 0;
350 }
351
352 /* check file format on first call */
353
354 if (PRIV (file_format) == FF_UNKNOWN)
355 { /* record length repeats ? */
356 if ( (vms_buf[0] == vms_buf[4])
357 && (vms_buf[1] == vms_buf[5]))
358 {
359 PRIV (file_format) = FF_FOREIGN; /* Y: foreign environment */
360 test_start = 2;
361 }
362 else
363 {
364 PRIV (file_format) = FF_NATIVE; /* N: native environment */
365 test_start = 0;
366 }
367 }
368
369 if (PRIV (is_vax))
370 {
371 PRIV (rec_length) = bfd_read (vms_buf, 1, PRIV (buf_size), abfd);
372 if (PRIV (rec_length) <= 0)
373 {
374 bfd_set_error (bfd_error_file_truncated);
375 return 0;
376 }
377 PRIV (vms_rec) = vms_buf;
378 }
379 else /* Alpha */
380 {
381 /* extract vms record length */
382
383 _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL,
384 &PRIV (rec_length));
385
386 if (PRIV (rec_length) <= 0)
387 {
388 bfd_set_error (bfd_error_file_truncated);
389 return 0;
390 }
391
392 /* that's what the linker manual says */
393
394 if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ)
395 {
396 bfd_set_error (bfd_error_file_truncated);
397 return 0;
398 }
399
400 /* adjust the buffer */
401
402 if (PRIV (rec_length) > PRIV (buf_size))
403 {
404 PRIV (vms_buf) = (unsigned char *) realloc (vms_buf, PRIV (rec_length));
405 vms_buf = PRIV (vms_buf);
406 if (vms_buf == 0)
407 {
408 bfd_set_error (bfd_error_no_memory);
409 return -1;
410 }
411 PRIV (buf_size) = PRIV (rec_length);
412 }
413
414 /* read the remaining record */
415
416 remaining = PRIV (rec_length) - test_len + test_start;
417
418#if VMS_DEBUG
419 vms_debug (10, "bfd_read remaining %d\n", remaining);
420#endif
421 if (bfd_read (vms_buf + test_len, 1, remaining, abfd) !=
422 (bfd_size_type) remaining)
423 {
424 bfd_set_error (bfd_error_file_truncated);
425 return 0;
426 }
427 PRIV (vms_rec) = vms_buf + test_start;
428 }
429
430#if VMS_DEBUG
431 vms_debug (11, "bfd_read rec_length %d\n", PRIV (rec_length));
432#endif
433
434 return PRIV (rec_length);
435}
436
437/* get next vms record from file
438 update vms_rec and rec_length to new (remaining) values */
439
440int
441_bfd_vms_next_record (abfd)
442 bfd *abfd;
443{
444#if VMS_DEBUG
445 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
446 PRIV (rec_length), PRIV (rec_size));
447#endif
448
449 if (PRIV (rec_length) > 0)
450 {
451 PRIV (vms_rec) += PRIV (rec_size);
452 }
453 else
454 {
455 if (_bfd_vms_get_record (abfd) <= 0)
456 return -1;
457 }
458
459 if (!PRIV (vms_rec) || !PRIV (vms_buf)
460 || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
461 return -1;
462
463 if (PRIV (is_vax))
464 {
465 PRIV (rec_type) = *(PRIV (vms_rec));
466 PRIV (rec_size) = PRIV (rec_length);
467 }
468 else
469 {
470 _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type),
471 &PRIV (rec_size));
472 }
473 PRIV (rec_length) -= PRIV (rec_size);
474
475#if VMS_DEBUG
476 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
477 PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length),
478 PRIV (rec_type));
479#endif
480
481 return PRIV (rec_type);
482}
483
484
485/* Copy sized string (string with fixed length) to new allocated area
486 size is string length (size of record) */
487
488char *
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
506char *
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
516/* stack routines for vms ETIR commands */
517
518/* Push value and section index */
519
520void
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
549uquad
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
574
575/* object file output functions */
576
577/* GAS tends to write sections in little chunks (bfd_set_section_contents)
578 which we can't use directly. So we save the little chunks in linked
579 lists (one per section) and write them later. */
580
581/* Add a new vms_section structure to vms_section_table
582 - forward chaining - */
583
584static vms_section *
585add_new_contents (abfd, section)
586 bfd *abfd;
587 sec_ptr section;
588{
589 vms_section *sptr, *newptr;
590
591 sptr = PRIV (vms_section_table)[section->index];
592 if (sptr != NULL)
593 return sptr;
594
595 newptr = (vms_section *) bfd_malloc (sizeof (vms_section));
596 if (newptr == (vms_section *) NULL)
597 return NULL;
598 newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
599 if (newptr->contents == (unsigned char *)NULL)
600 return NULL;
601 newptr->offset = 0;
602 newptr->size = section->_raw_size;
603 newptr->next = 0;
604 PRIV (vms_section_table)[section->index] = newptr;
605 return newptr;
606}
607
608/* Save section data & offset to an vms_section structure
609 vms_section_table[] holds the vms_section chain */
610
611boolean
612_bfd_save_vms_section (abfd, section, data, offset, count)
613 bfd *abfd;
614 sec_ptr section;
615 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
638vms_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
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
659void
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,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,rechead);
686
687 return;
688}
689
690/* Set record/subrecord alignment */
691
692void
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
707void
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
722void
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
744void
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), real_size, 1, (FILE *)abfd->iostream);
794
795 PRIV (output_size) = 0;
796 }
797 else
798 {
799 PRIV (output_size) = real_size;
800 PRIV (pushed_size) = PRIV (output_size);
801 }
802
803 return;
804}
805
806/* End record output */
807
808void
809_bfd_vms_output_end (abfd)
810 bfd *abfd;
811{
812#if VMS_DEBUG
813 vms_debug (6, "_bfd_vms_output_end\n");
814#endif
815
816 _bfd_vms_output_flush (abfd);
817
818 return;
819}
820
821/* check remaining buffer size
822
823 return what's left. */
824
825int
826_bfd_vms_output_check (abfd, size)
827 bfd *abfd;
828 int size;
829{
830#if VMS_DEBUG
831 vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
832#endif
833
834 return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
835}
836
837/* Output byte (8 bit) value */
838
839void
840_bfd_vms_output_byte (abfd, value)
841 bfd *abfd;
842 unsigned int value;
843{
844#if VMS_DEBUG
845 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
846#endif
847
848 bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
849 PRIV (output_size) += 1;
850 return;
851}
852
853/* Output short (16 bit) value */
854
855void
856_bfd_vms_output_short (abfd, value)
857 bfd *abfd;
858 unsigned int value;
859{
860#if VMS_DEBUG
861 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
862#endif
863
864 bfd_put_16 (abfd, value & 0xffff, PRIV (output_buf) + PRIV (output_size));
865 PRIV (output_size) += 2;
866 return;
867}
868
869/* Output long (32 bit) value */
870
871void
872_bfd_vms_output_long (abfd, value)
873 bfd *abfd;
874 unsigned long value;
875{
876#if VMS_DEBUG
877 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
878#endif
879
880 bfd_put_32 (abfd, value, PRIV (output_buf) + PRIV (output_size));
881 PRIV (output_size) += 4;
882 return;
883}
884
885/* Output quad (64 bit) value */
886
887void
888_bfd_vms_output_quad (abfd, value)
889 bfd *abfd;
890 uquad value;
891{
892#if VMS_DEBUG
893 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
894#endif
895
896 bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
897 PRIV (output_size) += 8;
898 return;
899}
900
901/* Output c-string as counted string */
902
903void
904_bfd_vms_output_counted (abfd, value)
905 bfd *abfd;
906 char *value;
907{
908int len;
909
910#if VMS_DEBUG
911 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
912#endif
913
914 len = strlen (value);
915 if (len == 0)
916 {
917 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
918 return;
919 }
920 if (len > 255)
921 {
922 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
923 return;
924 }
925 _bfd_vms_output_byte (abfd, len & 0xff);
926 _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
927}
928
929/* Output character area */
930
931void
932_bfd_vms_output_dump (abfd, data, length)
933 bfd *abfd;
934 unsigned char *data;
935 int length;
936{
937#if VMS_DEBUG
938 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
939#endif
940
941 if (length == 0)
942 return;
943
944 memcpy (PRIV (output_buf) + PRIV (output_size), data, length);
945 PRIV (output_size) += length;
946
947 return;
948}
949
950/* Output count bytes of value */
951
952void
953_bfd_vms_output_fill (abfd, value, count)
954 bfd *abfd;
955 int value;
956 int count;
957{
958#if VMS_DEBUG
959 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
960#endif
961
962 if (count == 0)
963 return;
964 memset (PRIV (output_buf) + PRIV (output_size), value, count);
965 PRIV (output_size) += count;
966
967 return;
968}
969
970/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
971
972static int
973hash_string (ptr)
974 const char *ptr;
975{
976 register const unsigned char *p = (unsigned char *) ptr;
977 register const unsigned char *end = p + strlen (ptr);
978 register unsigned char c;
979 register int hash = 0;
980
981 while (p != end)
982 {
983 c = *p++;
984 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
985 }
986 return hash;
987}
988
989/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
990
991char *
992_bfd_vms_length_hash_symbol (abfd, in, maxlen)
993 bfd *abfd;
994 const char *in;
995 int maxlen;
996{
997 long int result;
998 int in_len;
999 char *new_name;
1000 const char *old_name;
1001 int i;
1002 static char outbuf[EOBJ_S_C_SYMSIZ+1];
1003 char *out = outbuf;
1004
1005#if VMS_DEBUG
1006 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1007#endif
1008
1009 if (maxlen > EOBJ_S_C_SYMSIZ)
1010 maxlen = EOBJ_S_C_SYMSIZ;
1011
1012 new_name = out; /* save this for later. */
1013
1014 /* We may need to truncate the symbol, save the hash for later. */
1015
1016 in_len = strlen (in);
1017
1018 result = (in_len > maxlen) ? hash_string (in) : 0;
1019
1020 old_name = in;
1021
1022 /* Do the length checking. */
1023
1024 if (in_len <= maxlen)
1025 {
1026 i = in_len;
1027 }
1028 else
1029 {
1030 if (PRIV (flag_hash_long_names))
1031 i = maxlen-9;
1032 else
1033 i = maxlen;
1034 }
1035
1036 strncpy (out, in, i);
1037 in += i;
1038 out += i;
1039
1040 if ((in_len > maxlen)
1041 && PRIV (flag_hash_long_names))
1042 sprintf (out, "_%08lx", result);
1043 else
1044 *out = 0;
1045
1046#if VMS_DEBUG
1047 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1048#endif
1049
1050 if (in_len > maxlen
1051 && PRIV (flag_hash_long_names)
1052 && PRIV (flag_show_after_trunc))
1053 printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1054
1055 return outbuf;
1056}
1057
1058/* Allocate and initialize a new symbol. */
1059
1060static asymbol *
1061new_symbol (abfd, name)
1062 bfd *abfd;
1063 char *name;
1064{
1065 asymbol *symbol;
1066
1067#if VMS_DEBUG
1068 _bfd_vms_debug (7, "new_symbol %s\n", name);
1069#endif
1070
1071 symbol = _bfd_vms_make_empty_symbol (abfd);
1072 if (symbol == 0)
1073 return symbol;
1074 symbol->name = name;
1075 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1076
1077 return symbol;
1078}
1079
1080/* Allocate and enter a new private symbol. */
1081
1082vms_symbol_entry *
1083_bfd_vms_enter_symbol (abfd, name)
1084 bfd *abfd;
1085 char *name;
1086{
1087 vms_symbol_entry *entry;
1088
1089#if VMS_DEBUG
1090 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1091#endif
1092
1093 entry = (vms_symbol_entry *)
1094 bfd_hash_lookup (PRIV (vms_symbol_table), name, false, false);
1095 if (entry == 0)
1096 {
1097#if VMS_DEBUG
1098 _bfd_vms_debug (8, "creating hash entry for %s\n", name);
1099#endif
1100 entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV (vms_symbol_table), name, true, false);
1101 if (entry != 0)
1102 {
1103 asymbol *symbol;
1104 symbol = new_symbol (abfd, name);
1105 if (symbol != 0)
1106 {
1107 entry->symbol = symbol;
1108 PRIV (gsd_sym_count)++;
1109 abfd->symcount++;
1110 }
1111 else
1112 entry = 0;
1113 }
1114 else
1115 (*_bfd_error_handler) (_("failed to enter %s"), name);
1116 }
1117 else
1118 {
1119#if VMS_DEBUG
1120 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1121#endif
1122 }
1123
1124#if VMS_DEBUG
1125 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1126#endif
1127 return entry;
1128}
Note: See TracBrowser for help on using the repository browser.