* elflink.h (NAME(bfd_elf,size_dynamic_sections)): Change type of
[deliverable/binutils-gdb.git] / bfd / evax-misc.c
1 /* evax-misc.c -- Miscellaneous functions for ALPHA EVAX (openVMS/AXP) files.
2 Copyright 1996 Free Software Foundation, Inc.
3 Written by Klaus Kämpf (kkaempf@progis.de)
4 of proGIS Softwareentwicklung, Aachen, Germany
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20
21 #if __STDC__
22 #include <stdarg.h>
23 #endif
24 #include <stdio.h>
25
26 #include "bfd.h"
27 #include "sysdep.h"
28 #include "bfdlink.h"
29 #include "libbfd.h"
30
31 #include "evax.h"
32
33 /*-----------------------------------------------------------------------------*/
34 #if EVAX_DEBUG
35 /* debug functions */
36
37 /* debug function for all evax extensions
38 evaluates environment variable EVAX_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__
53 void
54 _bfd_evax_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("EVAX_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
89 void
90 _bfd_evax_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("EVAX_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
128 void
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 evax_debug (level, "%08lx:", start);
143 evax_debug (-level, " %02x", *ptr++);
144 count++;
145 start++;
146 if (size == 0)
147 {
148 while ((count%16) != 0)
149 {
150 evax_debug (-level, " ");
151 count++;
152 }
153 }
154 if ((count%16) == 0)
155 {
156 evax_debug (-level, " ");
157 while (lptr < ptr)
158 {
159 evax_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
160 lptr++;
161 }
162 evax_debug (-level, "\n");
163 }
164 }
165 if ((count%16) != 0)
166 evax_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 evax_hash_entry
178 keep the symbol name and a pointer to the bfd symbol in the table */
179
180 struct bfd_hash_entry *
181 _bfd_evax_hash_newfunc (entry, table, string)
182 struct bfd_hash_entry *entry;
183 struct bfd_hash_table *table;
184 const char *string;
185 {
186 evax_symbol_entry *ret = (evax_symbol_entry *)entry;
187
188 #if EVAX_DEBUG
189 evax_debug (5, "_bfd_evax_hash_newfunc(%p, %p, %s)\n", entry, table, string);
190 #endif
191
192 if (ret == (evax_symbol_entry *)NULL)
193 ret = ((evax_symbol_entry *) bfd_hash_allocate (table, sizeof (evax_symbol_entry)));
194 if (ret == (evax_symbol_entry *)NULL)
195 {
196 bfd_set_error (bfd_error_no_memory);
197 return (struct bfd_hash_entry *)NULL;
198 }
199 ret = (evax_symbol_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *)ret, table, string);
200
201 ret->symbol = (asymbol *)NULL;
202
203 return (struct bfd_hash_entry *)ret;
204 }
205
206 \f
207 /* object file input functions */
208
209 /* Return type and length from record header (buf) */
210
211 void
212 _bfd_evax_get_header_values (abfd, buf, type, length)
213 bfd *abfd;
214 unsigned char *buf;
215 int *type;
216 int *length;
217 {
218 if (type != 0)
219 *type = bfd_getl16 (buf);
220 buf += 2;
221 if (length != 0)
222 *length = bfd_getl16 (buf);
223
224 return;
225 }
226
227
228 /* Get next record from object file to evax_buf
229 set PRIV(buf_size) and return it
230
231 this is a little tricky since it should be portable.
232
233 the openVMS/AXP object file has 'variable length' which means that
234 read() returns data in chunks of (hopefully) correct and expected
235 size. The linker (and other tools on vms) depend on that. Unix doesn't
236 know about 'formatted' files, so reading and writing such an object
237 file in a unix environment is not trivial.
238
239 With the tool 'file' (available on all vms ftp sites), one
240 can view and change the attributes of a file. Changing from
241 'variable length' to 'fixed length, 512 bytes' reveals the
242 record length at the first 2 bytes of every record. The same
243 happens during the transfer of object files from vms to unix,
244 at least with ucx, dec's implementation of tcp/ip.
245
246 The EVAX format repeats the length at bytes 2 & 3 of every record.
247
248 On the first call (file_format == FF_UNKNOWN) we check if
249 the first and the third byte pair (!) of the record match.
250 If they do it's an object file in an unix environment or with
251 wrong attributes (FF_FOREIGN), else we should be in a vms
252 environment where read() returns the record size (FF_NATIVE).
253
254 reading is always done in 2 steps.
255 first just the record header is read and the length extracted
256 by get_header_values
257 then the read buffer is adjusted and the remaining bytes are
258 read in.
259
260 all file i/o is always done on even file positions */
261
262 int
263 _bfd_evax_get_record (abfd)
264 bfd *abfd;
265 {
266 int test_len, test_start, remaining;
267 unsigned char *evax_buf;
268
269 #if EVAX_DEBUG
270 evax_debug (8, "_bfd_evax_get_record\n");
271 #endif
272
273 /* minimum is 6 bytes
274 (2 bytes length, 2 bytes record id, 2 bytes length repeated) */
275
276 if (PRIV(buf_size) == 0)
277 {
278 PRIV(evax_buf) = (unsigned char *) malloc (6);
279 #if EVAX_DEBUG
280 evax_debug (9, "PRIV(evax_buf) %p\n", PRIV(evax_buf));
281 #endif
282 }
283
284 evax_buf = PRIV(evax_buf);
285
286 if (evax_buf == 0)
287 {
288 #if EVAX_DEBUG
289 evax_debug (9, "can't alloc evax_buf\n");
290 #endif
291 bfd_set_error (bfd_error_no_memory);
292 return -1;
293 }
294
295 switch (PRIV(file_format))
296 {
297 case FF_UNKNOWN:
298 case FF_FOREIGN:
299 test_len = 6; /* probe 6 bytes */
300 test_start = 2; /* where the record starts */
301 break;
302
303 case FF_NATIVE:
304 test_len = 4;
305 test_start = 0;
306 break;
307 }
308
309 /* skip odd alignment byte */
310 #if 0
311 if (PRIV(file_format) == FF_FOREIGN)
312 {
313 #endif
314 if (bfd_tell (abfd) & 1)
315 {
316 #if EVAX_DEBUG
317 evax_debug (10, "skip odd\n");
318 #endif
319 if (bfd_read (PRIV(evax_buf), 1, 1, abfd) != 1)
320 {
321 #if EVAX_DEBUG
322 evax_debug (9, "skip odd failed\n");
323 #endif
324 bfd_set_error (bfd_error_file_truncated);
325 return 0;
326 }
327 }
328 #if 0
329 }
330 #endif
331 /* read the record header */
332
333 if (bfd_read (PRIV(evax_buf), 1, test_len, abfd) != test_len)
334 {
335 #if EVAX_DEBUG
336 evax_debug (9, "can't bfd_read test %d bytes\n", test_len);
337 #endif
338 bfd_set_error (bfd_error_file_truncated);
339 return 0;
340 }
341
342 /* check file format on first call */
343
344 if (PRIV(file_format) == FF_UNKNOWN)
345 { /* record length repeats ? */
346 if ( (evax_buf[0] == evax_buf[4])
347 && (evax_buf[1] == evax_buf[5]))
348 {
349 PRIV(file_format) = FF_FOREIGN; /* Y: foreign environment */
350 test_start = 2;
351 }
352 else
353 {
354 PRIV(file_format) = FF_NATIVE; /* N: native environment */
355 test_start = 0;
356 }
357 #if EVAX_DEBUG
358 evax_debug (10, "File format is %s\n", (PRIV(file_format) == FF_FOREIGN)?"foreign":"native");
359 #endif
360 }
361
362 /* extract evax record length */
363
364 _bfd_evax_get_header_values (abfd, evax_buf+test_start, NULL,
365 &PRIV(rec_length));
366
367 if (PRIV(rec_length) <= 0)
368 {
369 bfd_set_error (bfd_error_file_truncated);
370 return 0;
371 }
372
373 /* that's what the linker manual says */
374
375 if (PRIV(rec_length) > EOBJ_S_C_MAXRECSIZ)
376 {
377 bfd_set_error (bfd_error_file_truncated);
378 return 0;
379 }
380
381 /* adjust the buffer */
382
383 if (PRIV(rec_length) > PRIV(buf_size))
384 {
385 PRIV(evax_buf) = (unsigned char *) realloc (evax_buf, PRIV(rec_length));
386 #if EVAX_DEBUG
387 evax_debug (3, "adjusted the buffer (%p) from %d to %d\n", PRIV(evax_buf), PRIV(buf_size), PRIV(rec_length));
388 #endif
389 evax_buf = PRIV(evax_buf);
390 if (evax_buf == 0)
391 {
392 #if EVAX_DEBUG
393 evax_debug (9, "can't realloc evax_buf to %d bytes\n", PRIV(rec_length));
394 #endif
395 bfd_set_error (bfd_error_no_memory);
396 return -1;
397 }
398 PRIV(buf_size) = PRIV(rec_length);
399 }
400
401 /* read the remaining record */
402
403 remaining = PRIV(rec_length) - test_len + test_start;
404
405 if (bfd_read (evax_buf + test_len, 1, remaining, abfd) != remaining)
406 {
407 #if EVAX_DEBUG
408 evax_debug (9, "can't bfd_read remaining %d bytes\n", remaining);
409 #endif
410 bfd_set_error (bfd_error_file_truncated);
411 return 0;
412 }
413
414 PRIV(evax_rec) = evax_buf + test_start;
415
416 return PRIV(rec_length);
417 }
418
419
420 /* get next EVAX record from file
421 update evax_rec and rec_length to new (remaining) values */
422
423 int
424 _bfd_evax_next_record (abfd)
425 bfd *abfd;
426 {
427 #if EVAX_DEBUG
428 evax_debug (8, "_bfd_evax_next_record (len %d, size %d)\n",
429 PRIV(rec_length), PRIV(rec_size));
430 #endif
431
432 if (PRIV(rec_length) > 0)
433 {
434 PRIV(evax_rec) += PRIV(rec_size);
435 }
436 else
437 {
438 if (_bfd_evax_get_record (abfd) <= 0)
439 return -1;
440 }
441 _bfd_evax_get_header_values (abfd, PRIV(evax_rec), &PRIV(rec_type),
442 &PRIV(rec_size));
443 PRIV(rec_length) -= PRIV(rec_size);
444
445 #if EVAX_DEBUG
446 evax_debug (8, "_bfd_evax_next_record: rec %p, size %d, length %d, type %d\n",
447 PRIV(evax_rec), PRIV(rec_size), PRIV(rec_length),
448 PRIV(rec_type));
449 #endif
450
451 return PRIV(rec_type);
452 }
453
454
455 \f
456 /* Copy sized string (string with fixed length) to new allocated area
457 size is string length (size of record) */
458
459 char *
460 _bfd_evax_save_sized_string (str, size)
461 char *str;
462 int size;
463 {
464 char *newstr = bfd_malloc (size + 1);
465
466 if (newstr == NULL)
467 return 0;
468 strncpy (newstr, str, size);
469 newstr[size] = 0;
470
471 return newstr;
472 }
473
474 /* Copy counted string (string with length at first byte) to new allocated area
475 ptr points to length byte on entry */
476
477 char *
478 _bfd_evax_save_counted_string (ptr)
479 char *ptr;
480 {
481 int len = *ptr++;
482
483 return _bfd_evax_save_sized_string (ptr, len);
484 }
485
486 \f
487 /* stack routines for EVAX ETIR commands */
488
489 /* Push value and section index */
490
491 void
492 _bfd_evax_push (abfd, val, psect)
493 bfd *abfd;
494 uquad val;
495 int psect;
496 {
497 static int last_psect;
498
499 #if EVAX_DEBUG
500 evax_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV(stackptr));
501 #endif
502
503 if (psect >= 0)
504 last_psect = psect;
505
506 PRIV(stack[PRIV(stackptr)]).value = val;
507 PRIV(stack[PRIV(stackptr)]).psect = last_psect;
508 PRIV(stackptr)++;
509 if (PRIV(stackptr) >= STACKSIZE)
510 {
511 bfd_set_error (bfd_error_bad_value);
512 exit(1);
513 }
514 return;
515 }
516
517
518 /* Pop value and section index */
519
520 uquad
521 _bfd_evax_pop (abfd, psect)
522 bfd *abfd;
523 int *psect;
524 {
525 uquad value;
526
527 if (PRIV(stackptr) == 0)
528 {
529 bfd_set_error (bfd_error_bad_value);
530 exit(1);
531 }
532 PRIV(stackptr)--;
533 value = PRIV(stack[PRIV(stackptr)]).value;
534 if ((psect != NULL) && (PRIV(stack[PRIV(stackptr)]).psect >= 0))
535 *psect = PRIV(stack[PRIV(stackptr)]).psect;
536
537 #if EVAX_DEBUG
538 evax_debug (4, "<pop %016lx(%d)>\n", value, PRIV(stack[PRIV(stackptr)]).psect);
539 #endif
540
541 return value;
542 }
543
544 \f
545 /* object file output functions */
546
547 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
548 which we can't use directly. So we save the little chunks in linked
549 lists (one per section) and write them later. */
550
551 /* Add a new evax_section structure to evax_section_table
552 - forward chaining - */
553
554 static evax_section *
555 add_new_contents (abfd, section)
556 bfd *abfd;
557 sec_ptr section;
558 {
559 evax_section *sptr, *newptr;
560
561 sptr = PRIV(evax_section_table)[section->index];
562 if (sptr != NULL)
563 return sptr;
564
565 newptr = (evax_section *) bfd_malloc (sizeof (evax_section));
566 if (newptr == (evax_section *) NULL)
567 return NULL;
568 newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
569 if (newptr->contents == (unsigned char *)NULL)
570 return NULL;
571 newptr->offset = 0;
572 newptr->size = section->_raw_size;
573 newptr->next = 0;
574 PRIV(evax_section_table)[section->index] = newptr;
575 return newptr;
576 }
577
578
579 /* Save section data & offset to an evax_section structure
580 evax_section_table[] holds the evax_section chain */
581
582 boolean
583 _bfd_save_evax_section (abfd, section, data, offset, count)
584 bfd *abfd;
585 sec_ptr section;
586 PTR data;
587 file_ptr offset;
588 bfd_size_type count;
589 {
590 evax_section *sptr;
591
592 if (section->index >= EVAX_SECTION_COUNT)
593 {
594 bfd_set_error (bfd_error_nonrepresentable_section);
595 return false;
596 }
597 if (count == (bfd_size_type)0)
598 return true;
599 sptr = add_new_contents (abfd, section);
600 if (sptr == NULL)
601 return false;
602 memcpy (sptr->contents + offset, data, (size_t) count);
603
604 return true;
605 }
606
607
608 /* Get evax_section pointer to saved contents for section # index */
609
610 evax_section *
611 _bfd_get_evax_section (abfd, index)
612 bfd *abfd;
613 int index;
614 {
615 if (index >= EVAX_SECTION_COUNT)
616 {
617 bfd_set_error (bfd_error_nonrepresentable_section);
618 return NULL;
619 }
620 return PRIV(evax_section_table)[index];
621 }
622
623 \f
624 /* Object output routines */
625
626 /* Begin new record or record header
627 write 2 bytes rectype
628 write 2 bytes record length (filled in at flush)
629 write 2 bytes header type (ommitted if rechead == -1) */
630
631 void
632 _bfd_evax_output_begin (abfd, rectype, rechead)
633 bfd *abfd;
634 int rectype;
635 int rechead;
636 {
637 #if EVAX_DEBUG
638 evax_debug (6, "_bfd_evax_output_begin(type %d, head %d)\n", rectype,
639 rechead);
640 #endif
641
642 _bfd_evax_output_short (abfd,rectype);
643
644 /* save current output position to fill in lenght later */
645
646 if (PRIV(push_level) > 0)
647 PRIV(length_pos) = PRIV(output_size);
648
649 #if EVAX_DEBUG
650 evax_debug (6, "_bfd_evax_output_begin: length_pos = %d\n",
651 PRIV(length_pos));
652 #endif
653
654 _bfd_evax_output_short (abfd,0); /* placeholder for length */
655
656 if (rechead != -1)
657 _bfd_evax_output_short (abfd,rechead);
658
659 return;
660 }
661
662
663 /* Set record/subrecord alignment */
664
665 void
666 _bfd_evax_output_alignment (abfd, alignto)
667 bfd *abfd;
668 int alignto;
669 {
670 #if EVAX_DEBUG
671 evax_debug (6, "_bfd_evax_output_alignment(%d)\n", alignto);
672 #endif
673
674 PRIV(output_alignment) = alignto;
675 return;
676 }
677
678
679 /* Prepare for subrecord fields */
680
681 void
682 _bfd_evax_output_push (abfd)
683 bfd *abfd;
684 {
685 #if EVAX_DEBUG
686 evax_debug (6, "evax_output_push(pushed_size = %d)\n", PRIV(output_size));
687 #endif
688
689 PRIV(push_level)++;
690 PRIV(pushed_size) = PRIV(output_size);
691 return;
692 }
693
694
695 /* End of subrecord fields */
696
697 void
698 _bfd_evax_output_pop (abfd)
699 bfd *abfd;
700 {
701 #if EVAX_DEBUG
702 evax_debug (6, "evax_output_pop(pushed_size = %d)\n", PRIV(pushed_size));
703 #endif
704
705 _bfd_evax_output_flush (abfd);
706 PRIV(length_pos) = 2;
707
708 #if EVAX_DEBUG
709 evax_debug (6, "evax_output_pop: length_pos = %d\n", PRIV(length_pos));
710 #endif
711
712 PRIV(pushed_size) = 0;
713 PRIV(push_level)--;
714 return;
715 }
716
717
718 /* Flush unwritten output, ends current record */
719
720 void
721 _bfd_evax_output_flush (abfd)
722 bfd *abfd;
723 {
724 int real_size = PRIV(output_size);
725 int aligncount;
726 int length;
727
728 #if EVAX_DEBUG
729 evax_debug (6, "_bfd_evax_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
730 real_size, PRIV(pushed_size), PRIV(length_pos));
731 #endif
732
733 if (PRIV(push_level) > 0)
734 length = real_size - PRIV(pushed_size);
735 else
736 length = real_size;
737
738 if (length == 0)
739 return;
740 aligncount = (PRIV(output_alignment)
741 - (length % PRIV(output_alignment))) % PRIV(output_alignment);
742
743 #if EVAX_DEBUG
744 evax_debug (6, "align: adding %d bytes\n", aligncount);
745 #endif
746
747 while(aligncount-- > 0)
748 {
749 PRIV(output_buf)[real_size++] = 0;
750 #if 0
751 /* this is why I *love* vms: inconsistency :-}
752 alignment is added to the subrecord length
753 but not to the record length */
754 if (PRIV(push_level) > 0)
755 #endif
756 length++;
757 }
758
759 /* put length to buffer */
760 PRIV(output_size) = PRIV(length_pos);
761 _bfd_evax_output_short (abfd, (unsigned int)length);
762
763 if (PRIV(push_level) == 0)
764 {
765 #ifndef VMS
766 /* write length first, see FF_FOREIGN in the input routines */
767 fwrite (PRIV(output_buf)+2, 2, 1, (FILE *)abfd->iostream);
768 #endif
769 fwrite (PRIV(output_buf), real_size, 1, (FILE *)abfd->iostream);
770
771 PRIV(output_size) = 0;
772 }
773 else
774 {
775 PRIV(output_size) = real_size;
776 PRIV(pushed_size) = PRIV(output_size);
777 }
778
779 return;
780 }
781
782
783 /* End record output */
784
785 void
786 _bfd_evax_output_end (abfd)
787 bfd *abfd;
788 {
789 #if EVAX_DEBUG
790 evax_debug (6, "_bfd_evax_output_end\n");
791 #endif
792
793 _bfd_evax_output_flush (abfd);
794
795 return;
796 }
797
798
799 /* check remaining buffer size
800
801 return what's left. */
802
803 int
804 _bfd_evax_output_check (abfd, size)
805 bfd *abfd;
806 int size;
807 {
808 #if EVAX_DEBUG
809 evax_debug (6, "_bfd_evax_output_check(%d)\n", size);
810 #endif
811
812 return (MAX_OUTREC_SIZE - (PRIV(output_size) + size + MIN_OUTREC_LUFT));
813 }
814
815
816 /* Output byte (8 bit) value */
817
818 void
819 _bfd_evax_output_byte (abfd, value)
820 bfd *abfd;
821 unsigned int value;
822 {
823 #if EVAX_DEBUG
824 evax_debug (6, "_bfd_evax_output_byte(%02x)\n", value);
825 #endif
826
827 bfd_put_8 (abfd, value & 0xff, PRIV(output_buf) + PRIV(output_size));
828 PRIV(output_size) += 1;
829 return;
830 }
831
832
833 /* Output short (16 bit) value */
834
835 void
836 _bfd_evax_output_short (abfd, value)
837 bfd *abfd;
838 unsigned int value;
839 {
840 #if EVAX_DEBUG
841 evax_debug (6, "_bfd_evax_output_short (%04x)\n", value);
842 #endif
843
844 bfd_put_16 (abfd, value & 0xffff, PRIV(output_buf) + PRIV(output_size));
845 PRIV(output_size) += 2;
846 return;
847 }
848
849
850 /* Output long (32 bit) value */
851
852 void
853 _bfd_evax_output_long (abfd, value)
854 bfd *abfd;
855 unsigned long value;
856 {
857 #if EVAX_DEBUG
858 evax_debug (6, "_bfd_evax_output_long (%08lx)\n", value);
859 #endif
860
861 bfd_put_32 (abfd, value, PRIV(output_buf) + PRIV(output_size));
862 PRIV(output_size) += 4;
863 return;
864 }
865
866
867 /* Output quad (64 bit) value */
868
869 void
870 _bfd_evax_output_quad (abfd, value)
871 bfd *abfd;
872 uquad value;
873 {
874 #if EVAX_DEBUG
875 evax_debug (6, "_bfd_evax_output_quad(%016lx)\n", value);
876 #endif
877
878 bfd_put_64(abfd, value, PRIV(output_buf) + PRIV(output_size));
879 PRIV(output_size) += 8;
880 return;
881 }
882
883
884 /* Output c-string as counted string */
885
886 void
887 _bfd_evax_output_counted (abfd, value)
888 bfd *abfd;
889 char *value;
890 {
891 int len;
892
893 #if EVAX_DEBUG
894 evax_debug (6, "_bfd_evax_output_counted(%s)\n", value);
895 #endif
896
897 len = strlen (value);
898 if (len == 0)
899 {
900 (*_bfd_error_handler) ("_bfd_evax_output_counted called with zero bytes");
901 return;
902 }
903 if (len > 255)
904 {
905 (*_bfd_error_handler) ("_bfd_evax_output_counted called with too many bytes");
906 return;
907 }
908 _bfd_evax_output_byte (abfd, len & 0xff);
909 _bfd_evax_output_dump (abfd, (unsigned char *)value, len);
910 }
911
912
913 /* Output character area */
914
915 void
916 _bfd_evax_output_dump (abfd, data, length)
917 bfd *abfd;
918 unsigned char *data;
919 int length;
920 {
921 #if EVAX_DEBUG
922 evax_debug (6, "_bfd_evax_output_dump(%d)\n", length);
923 #endif
924
925 if (length == 0)
926 return;
927
928 memcpy (PRIV(output_buf) + PRIV(output_size), data, length);
929 PRIV(output_size) += length;
930
931 return;
932 }
933
934
935 /* Output count bytes of value */
936
937 void
938 _bfd_evax_output_fill (abfd, value, count)
939 bfd *abfd;
940 int value;
941 int count;
942 {
943 #if EVAX_DEBUG
944 evax_debug (6, "_bfd_evax_output_fill(val %02x times %d)\n", value, count);
945 #endif
946
947 if (count == 0)
948 return;
949 memset (PRIV(output_buf) + PRIV(output_size), value, count);
950 PRIV(output_size) += count;
951
952 return;
953 }
954
955 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
956
957 static int
958 hash_string (ptr)
959 const char *ptr;
960 {
961 register const unsigned char *p = (unsigned char *) ptr;
962 register const unsigned char *end = p + strlen (ptr);
963 register unsigned char c;
964 register int hash = 0;
965
966 while (p != end)
967 {
968 c = *p++;
969 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
970 }
971 return hash;
972 }
973
974 /* Generate a Case-Hacked VMS symbol name (limited to 64 chars). */
975 char *
976 _bfd_evax_case_hack_symbol (abfd, in)
977 bfd *abfd;
978 const char *in;
979 {
980 long int init;
981 long int result;
982 char *pnt = 0;
983 char *new_name;
984 const char *old_name;
985 int i;
986 int destructor = 0; /*hack to allow for case sens in a destructor*/
987 int truncate = 0;
988 int case_hack_bits = 0;
989 int saw_dollar = 0;
990 static char hex_table[16] =
991 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
992
993 static char outbuf[65];
994 char *out = outbuf;
995
996 #if EVAX_DEBUG
997 evax_debug(4, "_bfd_evax_case_hack_symbol \"%s\"\n", in);
998 #endif
999
1000 #if 0
1001 /* Kill any leading "_". */ /* Why ? FIXME ! */
1002
1003 if ((in[0] == '_') && ((in[1] > '9') || (in[1] < '0')))
1004 in++;
1005 #endif
1006
1007 new_name = out; /* save this for later. */
1008
1009 /* We may need to truncate the symbol, save the hash for later. */
1010
1011 result = (strlen (in) > 56) ? hash_string (in) : 0;
1012
1013 old_name = in;
1014
1015 /* Do the case conversion. */
1016
1017 i = 56; /* Maximum of 56 chars */
1018
1019 while (*in && (--i >= 0))
1020 {
1021 case_hack_bits <<= 1;
1022 if (*in == '$')
1023 saw_dollar = 1;
1024 if ((destructor == 1) && (i == 54))
1025 saw_dollar = 0;
1026 switch (PRIV(vms_name_mapping))
1027 {
1028 case 0:
1029 if (isupper (*in)) {
1030 *out++ = *in++;
1031 case_hack_bits |= 1;
1032 } else {
1033 *out++ = islower (*in) ? toupper (*in++) : *in++;
1034 }
1035 break;
1036 case 3: *out++ = *in++;
1037 break;
1038 case 2:
1039 if (islower (*in)) {
1040 *out++ = *in++;
1041 } else {
1042 *out++ = isupper (*in) ? tolower (*in++) : *in++;
1043 }
1044 break;
1045 }
1046 }
1047
1048 /* if we saw a dollar sign, we don't do case hacking. */
1049
1050 if (PRIV(flag_no_hash_mixed_case) || saw_dollar)
1051 case_hack_bits = 0;
1052
1053 /* if we have more than 56 characters and everything is lowercase
1054 we can insert the full 64 characters. */
1055
1056 if (*in)
1057 {
1058 /* We have more than 56 characters
1059 If we must add the case hack, then we have truncated the str. */
1060 pnt = out;
1061 truncate = 1;
1062 if (case_hack_bits == 0)
1063 {
1064 /* And so far they are all lower case:
1065 Check up to 8 more characters
1066 and ensure that they are lowercase. */
1067
1068 for (i = 0; (in[i] != 0) && (i < 8); i++)
1069 if (isupper (in[i]) && !saw_dollar && !PRIV(flag_no_hash_mixed_case))
1070 break;
1071
1072 if (in[i] == 0)
1073 truncate = 0;
1074
1075 if ((i == 8) || (in[i] == 0))
1076 {
1077 /* They are: Copy up to 64 characters
1078 to the output string. */
1079
1080 i = 8;
1081 while ((--i >= 0) && (*in))
1082 {
1083 switch (PRIV(vms_name_mapping))
1084 {
1085 case 0:
1086 *out++ = islower (*in) ? toupper (*in++) : *in++;
1087 break;
1088 case 3:
1089 *out++ = *in++;
1090 break;
1091 case 2:
1092 *out++ = isupper (*in) ? tolower (*in++) : *in++;
1093 break;
1094 }
1095 }
1096 }
1097 }
1098 }
1099
1100 /* If there were any uppercase characters in the name we
1101 take on the case hacking string. */
1102
1103 /* Old behavior for regular GNU-C compiler */
1104
1105 if (!PRIV(flag_hash_long_names))
1106 truncate = 0;
1107
1108 if ((case_hack_bits != 0) || (truncate == 1))
1109 {
1110 if (truncate == 0)
1111 {
1112 *out++ = '_';
1113 for (i = 0; i < 6; i++)
1114 {
1115 *out++ = hex_table[case_hack_bits & 0xf];
1116 case_hack_bits >>= 4;
1117 }
1118 *out++ = 'X';
1119 }
1120 else
1121 {
1122 out = pnt; /* Cut back to 56 characters maximum */
1123 *out++ = '_';
1124 for (i = 0; i < 7; i++)
1125 {
1126 init = result & 0x01f;
1127 *out++ = (init < 10) ? ('0' + init) : ('A' + init - 10);
1128 result = result >> 5;
1129 }
1130 }
1131 }
1132
1133 *out = 0;
1134
1135 #if EVAX_DEBUG
1136 evax_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1137 #endif
1138
1139 if (truncate == 1
1140 && PRIV(flag_hash_long_names)
1141 && PRIV(flag_show_after_trunc))
1142 printf ("Symbol %s replaced by %s\n", old_name, new_name);
1143
1144 return outbuf;
1145 }
1146
This page took 0.094506 seconds and 4 git commands to generate.