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