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