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