Synchronise with master FSF GCC sources
[deliverable/binutils-gdb.git] / bfd / vms-misc.c
CommitLineData
252b5132
RH
1/* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
2 EVAX (openVMS/Alpha) files.
e049a0de 3 Copyright 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
252b5132
RH
4
5 Written by Klaus K"ampf (kkaempf@rmi.de)
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, 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__
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
125/* a debug function
126 hex dump 'size' bytes starting at 'ptr' */
127
128void
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
180struct 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 }
015985c9 201 entry = (struct bfd_hash_entry *) ret;
252b5132
RH
202 }
203
204 /* Call the allocation method of the base class. */
205
015985c9 206 ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
252b5132
RH
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
221void
222_bfd_vms_get_header_values (abfd, buf, type, length)
5f771d47 223 bfd *abfd ATTRIBUTE_UNUSED;
252b5132
RH
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
277int
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 {
02b89dce
NC
316 case FF_UNKNOWN:
317 case FF_FOREIGN:
318 test_len = 6; /* probe 6 bytes */
319 test_start = 2; /* where the record starts */
252b5132 320 break;
02b89dce
NC
321
322 case FF_NATIVE:
323 test_len = 4;
324 test_start = 0;
252b5132 325 break;
02b89dce
NC
326
327 default:
328 case FF_VAX:
329 test_len = 0;
330 test_start = 0;
252b5132 331 break;
02b89dce 332 }
252b5132
RH
333
334 /* skip odd alignment byte */
335
336 if (bfd_tell (abfd) & 1)
337 {
338 if (bfd_read (PRIV(vms_buf), 1, 1, abfd) != 1)
339 {
340 bfd_set_error (bfd_error_file_truncated);
341 return 0;
342 }
343 }
344
345 /* read the record header on Alpha. */
346
347 if ((test_len != 0)
5f771d47
ILT
348 && (bfd_read (PRIV(vms_buf), 1, test_len, abfd)
349 != (bfd_size_type) test_len))
252b5132
RH
350 {
351 bfd_set_error (bfd_error_file_truncated);
352 return 0;
353 }
354
355 /* check file format on first call */
356
357 if (PRIV(file_format) == FF_UNKNOWN)
358 { /* record length repeats ? */
359 if ( (vms_buf[0] == vms_buf[4])
360 && (vms_buf[1] == vms_buf[5]))
361 {
362 PRIV(file_format) = FF_FOREIGN; /* Y: foreign environment */
363 test_start = 2;
364 }
365 else
366 {
367 PRIV(file_format) = FF_NATIVE; /* N: native environment */
368 test_start = 0;
369 }
370 }
371
372 if (PRIV(is_vax))
373 {
374 PRIV(rec_length) = bfd_read (vms_buf, 1, PRIV(buf_size), 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 *) realloc (vms_buf, PRIV(rec_length));
408 vms_buf = PRIV(vms_buf);
409 if (vms_buf == 0)
410 {
411 bfd_set_error (bfd_error_no_memory);
412 return -1;
413 }
414 PRIV(buf_size) = PRIV(rec_length);
415 }
416
417 /* read the remaining record */
418
419 remaining = PRIV(rec_length) - test_len + test_start;
420
421#if VMS_DEBUG
422 vms_debug (10, "bfd_read remaining %d\n", remaining);
423#endif
5f771d47
ILT
424 if (bfd_read (vms_buf + test_len, 1, remaining, abfd) !=
425 (bfd_size_type) remaining)
252b5132
RH
426 {
427 bfd_set_error (bfd_error_file_truncated);
428 return 0;
429 }
430 PRIV(vms_rec) = vms_buf + test_start;
431 }
432
433#if VMS_DEBUG
434 vms_debug (11, "bfd_read rec_length %d\n", PRIV(rec_length));
435#endif
436
437 return PRIV(rec_length);
438}
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
63e39178
L
463 if (!PRIV(vms_rec))
464 return -1;
465
252b5132
RH
466 if (PRIV(is_vax))
467 {
468 PRIV(rec_type) = *(PRIV(vms_rec));
469 PRIV(rec_size) = PRIV(rec_length);
470 }
471 else
472 {
473 _bfd_vms_get_header_values (abfd, PRIV(vms_rec), &PRIV(rec_type),
474 &PRIV(rec_size));
475 }
476 PRIV(rec_length) -= PRIV(rec_size);
477
478#if VMS_DEBUG
479 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
480 PRIV(vms_rec), PRIV(rec_size), PRIV(rec_length),
481 PRIV(rec_type));
482#endif
483
484 return PRIV(rec_type);
485}
486
487
488\f
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 (size + 1);
498
499 if (newstr == NULL)
500 return 0;
501 strncpy (newstr, (char *)str, 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\f
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
552/* Pop value and section index */
553
554uquad
555_bfd_vms_pop (abfd, psect)
556 bfd *abfd;
557 int *psect;
558{
559 uquad value;
560
561 if (PRIV(stackptr) == 0)
562 {
563 bfd_set_error (bfd_error_bad_value);
564 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
565 exit (1);
566 }
567 PRIV(stackptr)--;
568 value = PRIV(stack[PRIV(stackptr)]).value;
569 if ((psect != NULL) && (PRIV(stack[PRIV(stackptr)]).psect >= 0))
570 *psect = PRIV(stack[PRIV(stackptr)]).psect;
571
572#if VMS_DEBUG
573 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV(stack[PRIV(stackptr)]).psect);
574#endif
575
576 return value;
577}
578
579\f
580/* object file output functions */
581
582/* GAS tends to write sections in little chunks (bfd_set_section_contents)
583 which we can't use directly. So we save the little chunks in linked
584 lists (one per section) and write them later. */
585
586/* Add a new vms_section structure to vms_section_table
587 - forward chaining - */
588
589static vms_section *
590add_new_contents (abfd, section)
591 bfd *abfd;
592 sec_ptr section;
593{
594 vms_section *sptr, *newptr;
595
596 sptr = PRIV(vms_section_table)[section->index];
597 if (sptr != NULL)
598 return sptr;
599
600 newptr = (vms_section *) bfd_malloc (sizeof (vms_section));
601 if (newptr == (vms_section *) NULL)
602 return NULL;
603 newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)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
614/* Save section data & offset to an vms_section structure
615 vms_section_table[] holds the vms_section chain */
616
617boolean
618_bfd_save_vms_section (abfd, section, data, offset, count)
619 bfd *abfd;
620 sec_ptr section;
621 PTR data;
622 file_ptr offset;
623 bfd_size_type count;
624{
625 vms_section *sptr;
626
627 if (section->index >= VMS_SECTION_COUNT)
628 {
629 bfd_set_error (bfd_error_nonrepresentable_section);
630 return false;
631 }
632 if (count == (bfd_size_type)0)
633 return true;
634 sptr = add_new_contents (abfd, section);
635 if (sptr == NULL)
636 return false;
637 memcpy (sptr->contents + offset, data, (size_t) count);
638
639 return true;
640}
641
642
643/* Get vms_section pointer to saved contents for section # index */
644
645vms_section *
646_bfd_get_vms_section (abfd, index)
647 bfd *abfd;
648 int index;
649{
650 if (index >= VMS_SECTION_COUNT)
651 {
652 bfd_set_error (bfd_error_nonrepresentable_section);
653 return NULL;
654 }
655 return PRIV(vms_section_table)[index];
656}
657
658\f
659/* Object output routines */
660
661/* Begin new record or record header
662 write 2 bytes rectype
663 write 2 bytes record length (filled in at flush)
664 write 2 bytes header type (ommitted if rechead == -1) */
665
666void
667_bfd_vms_output_begin (abfd, rectype, rechead)
668 bfd *abfd;
669 int rectype;
670 int rechead;
671{
672#if VMS_DEBUG
673 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
674 rechead);
675#endif
676
677 _bfd_vms_output_short (abfd,rectype);
678
679 /* save current output position to fill in lenght later */
680
681 if (PRIV(push_level) > 0)
682 PRIV(length_pos) = PRIV(output_size);
683
684#if VMS_DEBUG
685 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
686 PRIV(length_pos));
687#endif
688
689 _bfd_vms_output_short (abfd,0); /* placeholder for length */
690
691 if (rechead != -1)
692 _bfd_vms_output_short (abfd,rechead);
693
694 return;
695}
696
697
698/* Set record/subrecord alignment */
699
700void
701_bfd_vms_output_alignment (abfd, alignto)
702 bfd *abfd;
703 int alignto;
704{
705#if VMS_DEBUG
706 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
707#endif
708
709 PRIV(output_alignment) = alignto;
710 return;
711}
712
713
714/* Prepare for subrecord fields */
715
716void
717_bfd_vms_output_push (abfd)
718 bfd *abfd;
719{
720#if VMS_DEBUG
721 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV(output_size));
722#endif
723
724 PRIV(push_level)++;
725 PRIV(pushed_size) = PRIV(output_size);
726 return;
727}
728
729
730/* End of subrecord fields */
731
732void
733_bfd_vms_output_pop (abfd)
734 bfd *abfd;
735{
736#if VMS_DEBUG
737 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV(pushed_size));
738#endif
739
740 _bfd_vms_output_flush (abfd);
741 PRIV(length_pos) = 2;
742
743#if VMS_DEBUG
744 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV(length_pos));
745#endif
746
747 PRIV(pushed_size) = 0;
748 PRIV(push_level)--;
749 return;
750}
751
752
753/* Flush unwritten output, ends current record */
754
755void
756_bfd_vms_output_flush (abfd)
757 bfd *abfd;
758{
759 int real_size = PRIV(output_size);
760 int aligncount;
761 int length;
762
763#if VMS_DEBUG
764 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
765 real_size, PRIV(pushed_size), PRIV(length_pos));
766#endif
767
768 if (PRIV(push_level) > 0)
769 length = real_size - PRIV(pushed_size);
770 else
771 length = real_size;
772
773 if (length == 0)
774 return;
775 aligncount = (PRIV(output_alignment)
776 - (length % PRIV(output_alignment))) % PRIV(output_alignment);
777
778#if VMS_DEBUG
779 vms_debug (6, "align: adding %d bytes\n", aligncount);
780#endif
781
782 while(aligncount-- > 0)
783 {
784 PRIV(output_buf)[real_size++] = 0;
785#if 0
786 /* this is why I *love* vms: inconsistency :-}
787 alignment is added to the subrecord length
788 but not to the record length */
789 if (PRIV(push_level) > 0)
790#endif
791 length++;
792 }
793
794 /* put length to buffer */
795 PRIV(output_size) = PRIV(length_pos);
796 _bfd_vms_output_short (abfd, (unsigned int)length);
797
798 if (PRIV(push_level) == 0)
799 {
800#ifndef VMS
801 /* write length first, see FF_FOREIGN in the input routines */
802 fwrite (PRIV(output_buf)+2, 2, 1, (FILE *)abfd->iostream);
803#endif
804 fwrite (PRIV(output_buf), real_size, 1, (FILE *)abfd->iostream);
805
806 PRIV(output_size) = 0;
807 }
808 else
809 {
810 PRIV(output_size) = real_size;
811 PRIV(pushed_size) = PRIV(output_size);
812 }
813
814 return;
815}
816
817
818/* End record output */
819
820void
821_bfd_vms_output_end (abfd)
822 bfd *abfd;
823{
824#if VMS_DEBUG
825 vms_debug (6, "_bfd_vms_output_end\n");
826#endif
827
828 _bfd_vms_output_flush (abfd);
829
830 return;
831}
832
833
834/* check remaining buffer size
835
836 return what's left. */
837
838int
839_bfd_vms_output_check (abfd, size)
840 bfd *abfd;
841 int size;
842{
843#if VMS_DEBUG
844 vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
845#endif
846
847 return (MAX_OUTREC_SIZE - (PRIV(output_size) + size + MIN_OUTREC_LUFT));
848}
849
850
851/* Output byte (8 bit) value */
852
853void
854_bfd_vms_output_byte (abfd, value)
855 bfd *abfd;
856 unsigned int value;
857{
858#if VMS_DEBUG
859 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
860#endif
861
862 bfd_put_8 (abfd, value & 0xff, PRIV(output_buf) + PRIV(output_size));
863 PRIV(output_size) += 1;
864 return;
865}
866
867
868/* Output short (16 bit) value */
869
870void
871_bfd_vms_output_short (abfd, value)
872 bfd *abfd;
873 unsigned int value;
874{
875#if VMS_DEBUG
876 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
877#endif
878
879 bfd_put_16 (abfd, value & 0xffff, PRIV(output_buf) + PRIV(output_size));
880 PRIV(output_size) += 2;
881 return;
882}
883
884
885/* Output long (32 bit) value */
886
887void
888_bfd_vms_output_long (abfd, value)
889 bfd *abfd;
890 unsigned long value;
891{
892#if VMS_DEBUG
893 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
894#endif
895
896 bfd_put_32 (abfd, value, PRIV(output_buf) + PRIV(output_size));
897 PRIV(output_size) += 4;
898 return;
899}
900
901
902/* Output quad (64 bit) value */
903
904void
905_bfd_vms_output_quad (abfd, value)
906 bfd *abfd;
907 uquad value;
908{
909#if VMS_DEBUG
910 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
911#endif
912
913 bfd_put_64(abfd, value, PRIV(output_buf) + PRIV(output_size));
914 PRIV(output_size) += 8;
915 return;
916}
917
918
919/* Output c-string as counted string */
920
921void
922_bfd_vms_output_counted (abfd, value)
923 bfd *abfd;
924 char *value;
925{
926int len;
927
928#if VMS_DEBUG
929 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
930#endif
931
932 len = strlen (value);
933 if (len == 0)
934 {
935 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
936 return;
937 }
938 if (len > 255)
939 {
940 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
941 return;
942 }
943 _bfd_vms_output_byte (abfd, len & 0xff);
944 _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
945}
946
947
948/* Output character area */
949
950void
951_bfd_vms_output_dump (abfd, data, length)
952 bfd *abfd;
953 unsigned char *data;
954 int length;
955{
956#if VMS_DEBUG
957 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
958#endif
959
960 if (length == 0)
961 return;
962
963 memcpy (PRIV(output_buf) + PRIV(output_size), data, length);
964 PRIV(output_size) += length;
965
966 return;
967}
968
969
970/* Output count bytes of value */
971
972void
973_bfd_vms_output_fill (abfd, value, count)
974 bfd *abfd;
975 int value;
976 int count;
977{
978#if VMS_DEBUG
979 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
980#endif
981
982 if (count == 0)
983 return;
984 memset (PRIV(output_buf) + PRIV(output_size), value, count);
985 PRIV(output_size) += count;
986
987 return;
988}
989
990/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
991
992static int
993hash_string (ptr)
994 const char *ptr;
995{
996 register const unsigned char *p = (unsigned char *) ptr;
997 register const unsigned char *end = p + strlen (ptr);
998 register unsigned char c;
999 register int hash = 0;
1000
1001 while (p != end)
1002 {
1003 c = *p++;
1004 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
1005 }
1006 return hash;
1007}
1008
1009/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
1010
1011char *
1012_bfd_vms_length_hash_symbol (abfd, in, maxlen)
1013 bfd *abfd;
1014 const char *in;
1015 int maxlen;
1016{
252b5132
RH
1017 long int result;
1018 int in_len;
252b5132
RH
1019 char *new_name;
1020 const char *old_name;
1021 int i;
1022 static char outbuf[EOBJ_S_C_SYMSIZ+1];
1023 char *out = outbuf;
1024
1025#if VMS_DEBUG
1026 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1027#endif
1028
1029 if (maxlen > EOBJ_S_C_SYMSIZ)
1030 maxlen = EOBJ_S_C_SYMSIZ;
1031
1032 new_name = out; /* save this for later. */
1033
1034 /* We may need to truncate the symbol, save the hash for later. */
1035
1036 in_len = strlen (in);
1037
1038 result = (in_len > maxlen) ? hash_string (in) : 0;
1039
1040 old_name = in;
1041
1042 /* Do the length checking. */
1043
1044 if (in_len <= maxlen)
1045 {
1046 i = in_len;
1047 }
1048 else
1049 {
1050 if (PRIV(flag_hash_long_names))
1051 i = maxlen-9;
1052 else
1053 i = maxlen;
1054 }
1055
1056 strncpy (out, in, i);
1057 in += i;
1058 out += i;
1059
1060 if ((in_len > maxlen)
1061 && PRIV(flag_hash_long_names))
e049a0de 1062 sprintf (out, "_%08lx", result);
252b5132
RH
1063 else
1064 *out = 0;
1065
1066#if VMS_DEBUG
1067 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1068#endif
1069
1070 if (in_len > maxlen
1071 && PRIV(flag_hash_long_names)
1072 && PRIV(flag_show_after_trunc))
1073 printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1074
1075 return outbuf;
1076}
1077
1078
1079/* Allocate and initialize a new symbol. */
1080
1081static asymbol *
1082new_symbol (abfd, name)
1083 bfd *abfd;
1084 char *name;
1085{
1086 asymbol *symbol;
1087
1088#if VMS_DEBUG
1089 _bfd_vms_debug (7, "new_symbol %s\n", name);
1090#endif
1091
1092 symbol = _bfd_vms_make_empty_symbol (abfd);
1093 if (symbol == 0)
1094 return symbol;
1095 symbol->name = name;
1096 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1097
1098 return symbol;
1099}
1100
1101
1102/* Allocate and enter a new private symbol. */
1103
1104vms_symbol_entry *
1105_bfd_vms_enter_symbol (abfd, name)
1106 bfd *abfd;
1107 char *name;
1108{
1109 vms_symbol_entry *entry;
1110
1111#if VMS_DEBUG
1112 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1113#endif
1114
1115 entry = (vms_symbol_entry *)
1116 bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false);
1117 if (entry == 0)
1118 {
1119#if VMS_DEBUG
1120 _bfd_vms_debug (8, "creating hash entry for %s\n", name);
1121#endif
1122 entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, true, false);
1123 if (entry != 0)
1124 {
1125 asymbol *symbol;
1126 symbol = new_symbol (abfd, name);
1127 if (symbol != 0)
1128 {
1129 entry->symbol = symbol;
1130 PRIV(gsd_sym_count)++;
1131 abfd->symcount++;
1132 }
1133 else
1134 entry = 0;
1135 }
1136 else
1137 (*_bfd_error_handler) (_("failed to enter %s"), name);
1138 }
1139 else
1140 {
1141#if VMS_DEBUG
1142 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1143#endif
1144 }
1145
1146#if VMS_DEBUG
1147 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1148#endif
1149 return entry;
1150}
This page took 0.111046 seconds and 4 git commands to generate.