Document new --unwind option to readelf.
[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
0007625f
L
458 if (!PRIV(vms_rec) || !PRIV(vms_buf)
459 || PRIV(vms_rec) >= (PRIV(vms_buf) + PRIV(buf_size)))
63e39178
L
460 return -1;
461
252b5132
RH
462 if (PRIV(is_vax))
463 {
464 PRIV(rec_type) = *(PRIV(vms_rec));
465 PRIV(rec_size) = PRIV(rec_length);
466 }
467 else
468 {
469 _bfd_vms_get_header_values (abfd, PRIV(vms_rec), &PRIV(rec_type),
470 &PRIV(rec_size));
471 }
472 PRIV(rec_length) -= PRIV(rec_size);
473
474#if VMS_DEBUG
475 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
476 PRIV(vms_rec), PRIV(rec_size), PRIV(rec_length),
477 PRIV(rec_type));
478#endif
479
480 return PRIV(rec_type);
481}
482
252b5132
RH
483\f
484/* Copy sized string (string with fixed length) to new allocated area
485 size is string length (size of record) */
486
487char *
488_bfd_vms_save_sized_string (str, size)
489 unsigned char *str;
490 int size;
491{
492 char *newstr = bfd_malloc (size + 1);
493
494 if (newstr == NULL)
495 return 0;
496 strncpy (newstr, (char *)str, size);
497 newstr[size] = 0;
498
499 return newstr;
500}
501
502/* Copy counted string (string with length at first byte) to new allocated area
503 ptr points to length byte on entry */
504
505char *
506_bfd_vms_save_counted_string (ptr)
507 unsigned char *ptr;
508{
509 int len = *ptr++;
510
511 return _bfd_vms_save_sized_string (ptr, len);
512}
513
514\f
515/* stack routines for vms ETIR commands */
516
517/* Push value and section index */
518
519void
520_bfd_vms_push (abfd, val, psect)
521 bfd *abfd;
522 uquad val;
523 int psect;
524{
525 static int last_psect;
526
527#if VMS_DEBUG
528 vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV(stackptr));
529#endif
530
531 if (psect >= 0)
532 last_psect = psect;
533
534 PRIV(stack[PRIV(stackptr)]).value = val;
535 PRIV(stack[PRIV(stackptr)]).psect = last_psect;
536 PRIV(stackptr)++;
537 if (PRIV(stackptr) >= STACKSIZE)
538 {
539 bfd_set_error (bfd_error_bad_value);
540 (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV(stackptr));
541 exit (1);
542 }
543 return;
544}
545
252b5132
RH
546/* Pop value and section index */
547
548uquad
549_bfd_vms_pop (abfd, psect)
550 bfd *abfd;
551 int *psect;
552{
553 uquad value;
554
555 if (PRIV(stackptr) == 0)
556 {
557 bfd_set_error (bfd_error_bad_value);
558 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
559 exit (1);
560 }
561 PRIV(stackptr)--;
562 value = PRIV(stack[PRIV(stackptr)]).value;
563 if ((psect != NULL) && (PRIV(stack[PRIV(stackptr)]).psect >= 0))
564 *psect = PRIV(stack[PRIV(stackptr)]).psect;
565
566#if VMS_DEBUG
567 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV(stack[PRIV(stackptr)]).psect);
568#endif
569
570 return value;
571}
572
573\f
574/* object file output functions */
575
576/* GAS tends to write sections in little chunks (bfd_set_section_contents)
577 which we can't use directly. So we save the little chunks in linked
578 lists (one per section) and write them later. */
579
580/* Add a new vms_section structure to vms_section_table
581 - forward chaining - */
582
583static vms_section *
584add_new_contents (abfd, section)
585 bfd *abfd;
586 sec_ptr section;
587{
588 vms_section *sptr, *newptr;
589
590 sptr = PRIV(vms_section_table)[section->index];
591 if (sptr != NULL)
592 return sptr;
593
594 newptr = (vms_section *) bfd_malloc (sizeof (vms_section));
595 if (newptr == (vms_section *) NULL)
596 return NULL;
597 newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
598 if (newptr->contents == (unsigned char *)NULL)
599 return NULL;
600 newptr->offset = 0;
601 newptr->size = section->_raw_size;
602 newptr->next = 0;
603 PRIV(vms_section_table)[section->index] = newptr;
604 return newptr;
605}
606
252b5132
RH
607/* Save section data & offset to an vms_section structure
608 vms_section_table[] holds the vms_section chain */
609
610boolean
611_bfd_save_vms_section (abfd, section, data, offset, count)
612 bfd *abfd;
613 sec_ptr section;
614 PTR data;
615 file_ptr offset;
616 bfd_size_type count;
617{
618 vms_section *sptr;
619
620 if (section->index >= VMS_SECTION_COUNT)
621 {
622 bfd_set_error (bfd_error_nonrepresentable_section);
623 return false;
624 }
625 if (count == (bfd_size_type)0)
626 return true;
627 sptr = add_new_contents (abfd, section);
628 if (sptr == NULL)
629 return false;
630 memcpy (sptr->contents + offset, data, (size_t) count);
631
632 return true;
633}
634
252b5132
RH
635/* Get vms_section pointer to saved contents for section # index */
636
637vms_section *
638_bfd_get_vms_section (abfd, index)
639 bfd *abfd;
640 int index;
641{
642 if (index >= VMS_SECTION_COUNT)
643 {
644 bfd_set_error (bfd_error_nonrepresentable_section);
645 return NULL;
646 }
647 return PRIV(vms_section_table)[index];
648}
649
650\f
651/* Object output routines */
652
653/* Begin new record or record header
654 write 2 bytes rectype
655 write 2 bytes record length (filled in at flush)
656 write 2 bytes header type (ommitted if rechead == -1) */
657
658void
659_bfd_vms_output_begin (abfd, rectype, rechead)
660 bfd *abfd;
661 int rectype;
662 int rechead;
663{
664#if VMS_DEBUG
665 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
666 rechead);
667#endif
668
669 _bfd_vms_output_short (abfd,rectype);
670
671 /* save current output position to fill in lenght later */
672
673 if (PRIV(push_level) > 0)
674 PRIV(length_pos) = PRIV(output_size);
675
676#if VMS_DEBUG
677 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
678 PRIV(length_pos));
679#endif
680
681 _bfd_vms_output_short (abfd,0); /* placeholder for length */
682
683 if (rechead != -1)
684 _bfd_vms_output_short (abfd,rechead);
685
686 return;
687}
688
252b5132
RH
689/* Set record/subrecord alignment */
690
691void
692_bfd_vms_output_alignment (abfd, alignto)
693 bfd *abfd;
694 int alignto;
695{
696#if VMS_DEBUG
697 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
698#endif
699
700 PRIV(output_alignment) = alignto;
701 return;
702}
703
252b5132
RH
704/* Prepare for subrecord fields */
705
706void
707_bfd_vms_output_push (abfd)
708 bfd *abfd;
709{
710#if VMS_DEBUG
711 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV(output_size));
712#endif
713
714 PRIV(push_level)++;
715 PRIV(pushed_size) = PRIV(output_size);
716 return;
717}
718
252b5132
RH
719/* End of subrecord fields */
720
721void
722_bfd_vms_output_pop (abfd)
723 bfd *abfd;
724{
725#if VMS_DEBUG
726 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV(pushed_size));
727#endif
728
729 _bfd_vms_output_flush (abfd);
730 PRIV(length_pos) = 2;
731
732#if VMS_DEBUG
733 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV(length_pos));
734#endif
735
736 PRIV(pushed_size) = 0;
737 PRIV(push_level)--;
738 return;
739}
740
252b5132
RH
741/* Flush unwritten output, ends current record */
742
743void
744_bfd_vms_output_flush (abfd)
745 bfd *abfd;
746{
747 int real_size = PRIV(output_size);
748 int aligncount;
749 int length;
750
751#if VMS_DEBUG
752 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
753 real_size, PRIV(pushed_size), PRIV(length_pos));
754#endif
755
756 if (PRIV(push_level) > 0)
757 length = real_size - PRIV(pushed_size);
758 else
759 length = real_size;
760
761 if (length == 0)
762 return;
763 aligncount = (PRIV(output_alignment)
764 - (length % PRIV(output_alignment))) % PRIV(output_alignment);
765
766#if VMS_DEBUG
767 vms_debug (6, "align: adding %d bytes\n", aligncount);
768#endif
769
558e161f 770 while (aligncount-- > 0)
252b5132
RH
771 {
772 PRIV(output_buf)[real_size++] = 0;
773#if 0
774 /* this is why I *love* vms: inconsistency :-}
775 alignment is added to the subrecord length
776 but not to the record length */
777 if (PRIV(push_level) > 0)
778#endif
779 length++;
780 }
781
782 /* put length to buffer */
783 PRIV(output_size) = PRIV(length_pos);
784 _bfd_vms_output_short (abfd, (unsigned int)length);
785
786 if (PRIV(push_level) == 0)
787 {
788#ifndef VMS
789 /* write length first, see FF_FOREIGN in the input routines */
790 fwrite (PRIV(output_buf)+2, 2, 1, (FILE *)abfd->iostream);
791#endif
792 fwrite (PRIV(output_buf), real_size, 1, (FILE *)abfd->iostream);
793
794 PRIV(output_size) = 0;
795 }
796 else
797 {
798 PRIV(output_size) = real_size;
799 PRIV(pushed_size) = PRIV(output_size);
800 }
801
802 return;
803}
804
252b5132
RH
805/* End record output */
806
807void
808_bfd_vms_output_end (abfd)
809 bfd *abfd;
810{
811#if VMS_DEBUG
812 vms_debug (6, "_bfd_vms_output_end\n");
813#endif
814
815 _bfd_vms_output_flush (abfd);
816
817 return;
818}
819
252b5132
RH
820/* check remaining buffer size
821
822 return what's left. */
823
824int
825_bfd_vms_output_check (abfd, size)
826 bfd *abfd;
827 int size;
828{
829#if VMS_DEBUG
830 vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
831#endif
832
833 return (MAX_OUTREC_SIZE - (PRIV(output_size) + size + MIN_OUTREC_LUFT));
834}
835
252b5132
RH
836/* Output byte (8 bit) value */
837
838void
839_bfd_vms_output_byte (abfd, value)
840 bfd *abfd;
841 unsigned int value;
842{
843#if VMS_DEBUG
844 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
845#endif
846
847 bfd_put_8 (abfd, value & 0xff, PRIV(output_buf) + PRIV(output_size));
848 PRIV(output_size) += 1;
849 return;
850}
851
252b5132
RH
852/* Output short (16 bit) value */
853
854void
855_bfd_vms_output_short (abfd, value)
856 bfd *abfd;
857 unsigned int value;
858{
859#if VMS_DEBUG
860 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
861#endif
862
863 bfd_put_16 (abfd, value & 0xffff, PRIV(output_buf) + PRIV(output_size));
864 PRIV(output_size) += 2;
865 return;
866}
867
252b5132
RH
868/* Output long (32 bit) value */
869
870void
871_bfd_vms_output_long (abfd, value)
872 bfd *abfd;
873 unsigned long value;
874{
875#if VMS_DEBUG
876 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
877#endif
878
879 bfd_put_32 (abfd, value, PRIV(output_buf) + PRIV(output_size));
880 PRIV(output_size) += 4;
881 return;
882}
883
252b5132
RH
884/* Output quad (64 bit) value */
885
886void
887_bfd_vms_output_quad (abfd, value)
888 bfd *abfd;
889 uquad value;
890{
891#if VMS_DEBUG
892 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
893#endif
894
895 bfd_put_64(abfd, value, PRIV(output_buf) + PRIV(output_size));
896 PRIV(output_size) += 8;
897 return;
898}
899
252b5132
RH
900/* Output c-string as counted string */
901
902void
903_bfd_vms_output_counted (abfd, value)
904 bfd *abfd;
905 char *value;
906{
907int len;
908
909#if VMS_DEBUG
910 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
911#endif
912
913 len = strlen (value);
914 if (len == 0)
915 {
916 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
917 return;
918 }
919 if (len > 255)
920 {
921 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
922 return;
923 }
924 _bfd_vms_output_byte (abfd, len & 0xff);
925 _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
926}
927
252b5132
RH
928/* Output character area */
929
930void
931_bfd_vms_output_dump (abfd, data, length)
932 bfd *abfd;
933 unsigned char *data;
934 int length;
935{
936#if VMS_DEBUG
937 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
938#endif
939
940 if (length == 0)
941 return;
942
943 memcpy (PRIV(output_buf) + PRIV(output_size), data, length);
944 PRIV(output_size) += length;
945
946 return;
947}
948
252b5132
RH
949/* Output count bytes of value */
950
951void
952_bfd_vms_output_fill (abfd, value, count)
953 bfd *abfd;
954 int value;
955 int count;
956{
957#if VMS_DEBUG
958 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
959#endif
960
961 if (count == 0)
962 return;
963 memset (PRIV(output_buf) + PRIV(output_size), value, count);
964 PRIV(output_size) += count;
965
966 return;
967}
968
969/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
970
971static int
972hash_string (ptr)
973 const char *ptr;
974{
975 register const unsigned char *p = (unsigned char *) ptr;
976 register const unsigned char *end = p + strlen (ptr);
977 register unsigned char c;
978 register int hash = 0;
979
980 while (p != end)
981 {
982 c = *p++;
983 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
984 }
985 return hash;
986}
987
988/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
989
990char *
991_bfd_vms_length_hash_symbol (abfd, in, maxlen)
992 bfd *abfd;
993 const char *in;
994 int maxlen;
995{
252b5132
RH
996 long int result;
997 int in_len;
252b5132
RH
998 char *new_name;
999 const char *old_name;
1000 int i;
1001 static char outbuf[EOBJ_S_C_SYMSIZ+1];
1002 char *out = outbuf;
1003
1004#if VMS_DEBUG
1005 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1006#endif
1007
1008 if (maxlen > EOBJ_S_C_SYMSIZ)
1009 maxlen = EOBJ_S_C_SYMSIZ;
1010
1011 new_name = out; /* save this for later. */
1012
1013 /* We may need to truncate the symbol, save the hash for later. */
1014
1015 in_len = strlen (in);
1016
1017 result = (in_len > maxlen) ? hash_string (in) : 0;
1018
1019 old_name = in;
1020
1021 /* Do the length checking. */
1022
1023 if (in_len <= maxlen)
1024 {
1025 i = in_len;
1026 }
1027 else
1028 {
1029 if (PRIV(flag_hash_long_names))
1030 i = maxlen-9;
1031 else
1032 i = maxlen;
1033 }
1034
1035 strncpy (out, in, i);
1036 in += i;
1037 out += i;
1038
1039 if ((in_len > maxlen)
1040 && PRIV(flag_hash_long_names))
e049a0de 1041 sprintf (out, "_%08lx", result);
252b5132
RH
1042 else
1043 *out = 0;
1044
1045#if VMS_DEBUG
1046 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1047#endif
1048
1049 if (in_len > maxlen
1050 && PRIV(flag_hash_long_names)
1051 && PRIV(flag_show_after_trunc))
1052 printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1053
1054 return outbuf;
1055}
1056
252b5132
RH
1057/* Allocate and initialize a new symbol. */
1058
1059static asymbol *
1060new_symbol (abfd, name)
1061 bfd *abfd;
1062 char *name;
1063{
1064 asymbol *symbol;
1065
1066#if VMS_DEBUG
1067 _bfd_vms_debug (7, "new_symbol %s\n", name);
1068#endif
1069
1070 symbol = _bfd_vms_make_empty_symbol (abfd);
1071 if (symbol == 0)
1072 return symbol;
1073 symbol->name = name;
1074 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1075
1076 return symbol;
1077}
1078
252b5132
RH
1079/* Allocate and enter a new private symbol. */
1080
1081vms_symbol_entry *
1082_bfd_vms_enter_symbol (abfd, name)
1083 bfd *abfd;
1084 char *name;
1085{
1086 vms_symbol_entry *entry;
1087
1088#if VMS_DEBUG
1089 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1090#endif
1091
1092 entry = (vms_symbol_entry *)
1093 bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false);
1094 if (entry == 0)
1095 {
1096#if VMS_DEBUG
1097 _bfd_vms_debug (8, "creating hash entry for %s\n", name);
1098#endif
1099 entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, true, false);
1100 if (entry != 0)
1101 {
1102 asymbol *symbol;
1103 symbol = new_symbol (abfd, name);
1104 if (symbol != 0)
1105 {
1106 entry->symbol = symbol;
1107 PRIV(gsd_sym_count)++;
1108 abfd->symcount++;
1109 }
1110 else
1111 entry = 0;
1112 }
1113 else
1114 (*_bfd_error_handler) (_("failed to enter %s"), name);
1115 }
1116 else
1117 {
1118#if VMS_DEBUG
1119 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1120#endif
1121 }
1122
1123#if VMS_DEBUG
1124 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1125#endif
1126 return entry;
1127}
This page took 0.112764 seconds and 4 git commands to generate.