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