rebuild
[deliverable/binutils-gdb.git] / bfd / vms-misc.c
CommitLineData
0dc4c667
ILT
1/* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
2 EVAX (openVMS/Alpha) files.
980381af 3 Copyright 1996, 1997, 1998 Free Software Foundation, Inc.
8696b2db 4
0dc4c667 5 Written by Klaus K"ampf (kkaempf@rmi.de)
c3d8e071
ILT
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
21
22#if __STDC__
23#include <stdarg.h>
24#endif
c3d8e071
ILT
25
26#include "bfd.h"
27#include "sysdep.h"
28#include "bfdlink.h"
29#include "libbfd.h"
30
0dc4c667 31#include "vms.h"
c3d8e071
ILT
32
33/*-----------------------------------------------------------------------------*/
0dc4c667 34#if VMS_DEBUG
c3d8e071
ILT
35/* debug functions */
36
0dc4c667
ILT
37/* debug function for all vms extensions
38 evaluates environment variable VMS_DEBUG for a
c3d8e071
ILT
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__
53void
0dc4c667 54_bfd_vms_debug (int level, char *format, ...)
c3d8e071
ILT
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 {
0dc4c667 64 if ((eptr = getenv("VMS_DEBUG")) != NULL)
c3d8e071
ILT
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
89void
0dc4c667 90_bfd_vms_debug (level, format, a1, a2, a3, a4, a5, a6)
c3d8e071
ILT
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 {
0dc4c667 102 if ((eptr = getenv("VMS_DEBUG")) != NULL)
c3d8e071
ILT
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
128void
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)
0dc4c667
ILT
142 vms_debug (level, "%08lx:", start);
143 vms_debug (-level, " %02x", *ptr++);
c3d8e071
ILT
144 count++;
145 start++;
146 if (size == 0)
147 {
148 while ((count%16) != 0)
149 {
0dc4c667 150 vms_debug (-level, " ");
c3d8e071
ILT
151 count++;
152 }
153 }
154 if ((count%16) == 0)
155 {
0dc4c667 156 vms_debug (-level, " ");
c3d8e071
ILT
157 while (lptr < ptr)
158 {
0dc4c667 159 vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
c3d8e071
ILT
160 lptr++;
161 }
0dc4c667 162 vms_debug (-level, "\n");
c3d8e071
ILT
163 }
164 }
165 if ((count%16) != 0)
0dc4c667 166 vms_debug (-level, "\n");
c3d8e071
ILT
167
168 return;
169}
170#endif
171
172\f
173/* hash functions
174
175 These are needed when reading an object file. */
176
0dc4c667 177/* allocate new vms_hash_entry
c3d8e071
ILT
178 keep the symbol name and a pointer to the bfd symbol in the table */
179
180struct bfd_hash_entry *
0dc4c667 181_bfd_vms_hash_newfunc (entry, table, string)
c3d8e071
ILT
182 struct bfd_hash_entry *entry;
183 struct bfd_hash_table *table;
184 const char *string;
185{
0dc4c667 186 vms_symbol_entry *ret;
c3d8e071 187
0dc4c667
ILT
188#if VMS_DEBUG
189 vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string);
c3d8e071
ILT
190#endif
191
0dc4c667 192 if (entry == (struct bfd_hash_entry *)NULL)
c3d8e071 193 {
0dc4c667
ILT
194 ret = (vms_symbol_entry *)
195 bfd_hash_allocate (table, sizeof (vms_symbol_entry));
196 if (ret == (vms_symbol_entry *) NULL)
197 {
198 bfd_set_error (bfd_error_no_memory);
199 return (struct bfd_hash_entry *)NULL;
200 }
c3d8e071 201 }
0dc4c667
ILT
202
203 /* Call the allocation method of the base class. */
204
205 ret = (vms_symbol_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *)ret, table, string);
206#if VMS_DEBUG
207 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
208#endif
c3d8e071
ILT
209
210 ret->symbol = (asymbol *)NULL;
211
212 return (struct bfd_hash_entry *)ret;
213}
214
215\f
216/* object file input functions */
217
0dc4c667 218/* Return type and length from record header (buf) on Alpha. */
c3d8e071
ILT
219
220void
0dc4c667 221_bfd_vms_get_header_values (abfd, buf, type, length)
c3d8e071
ILT
222 bfd *abfd;
223 unsigned char *buf;
224 int *type;
225 int *length;
226{
227 if (type != 0)
228 *type = bfd_getl16 (buf);
229 buf += 2;
230 if (length != 0)
231 *length = bfd_getl16 (buf);
232
0dc4c667
ILT
233#if VMS_DEBUG
234 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
235#endif
236
237
c3d8e071
ILT
238 return;
239}
240
241
0dc4c667 242/* Get next record from object file to vms_buf
c3d8e071
ILT
243 set PRIV(buf_size) and return it
244
245 this is a little tricky since it should be portable.
246
0dc4c667 247 the openVMS object file has 'variable length' which means that
c3d8e071
ILT
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.
252
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.
259
0dc4c667 260 The vms format repeats the length at bytes 2 & 3 of every record.
c3d8e071
ILT
261
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).
267
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.
273
274 all file i/o is always done on even file positions */
275
276int
0dc4c667 277_bfd_vms_get_record (abfd)
c3d8e071
ILT
278 bfd *abfd;
279{
280 int test_len, test_start, remaining;
0dc4c667 281 unsigned char *vms_buf;
c3d8e071 282
0dc4c667
ILT
283#if VMS_DEBUG
284 vms_debug (8, "_bfd_vms_get_record\n");
c3d8e071
ILT
285#endif
286
0dc4c667
ILT
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 */
c3d8e071
ILT
292
293 if (PRIV(buf_size) == 0)
294 {
0dc4c667
ILT
295 if (PRIV(is_vax))
296 {
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;
300 }
301 else
302 PRIV(vms_buf) = (unsigned char *) malloc (6);
c3d8e071
ILT
303 }
304
0dc4c667 305 vms_buf = PRIV(vms_buf);
c3d8e071 306
0dc4c667 307 if (vms_buf == 0)
c3d8e071 308 {
c3d8e071
ILT
309 bfd_set_error (bfd_error_no_memory);
310 return -1;
311 }
312
313 switch (PRIV(file_format))
314 {
315 case FF_UNKNOWN:
316 case FF_FOREIGN:
0dc4c667
ILT
317 test_len = 6; /* probe 6 bytes */
318 test_start = 2; /* where the record starts */
c3d8e071
ILT
319 break;
320
321 case FF_NATIVE:
322 test_len = 4;
323 test_start = 0;
324 break;
0dc4c667
ILT
325
326 case FF_VAX:
327 test_len = 0;
328 test_start = 0;
329 break;
c3d8e071
ILT
330 }
331
332 /* skip odd alignment byte */
0dc4c667
ILT
333
334 if (bfd_tell (abfd) & 1)
c3d8e071 335 {
0dc4c667 336 if (bfd_read (PRIV(vms_buf), 1, 1, abfd) != 1)
c3d8e071 337 {
0dc4c667
ILT
338 bfd_set_error (bfd_error_file_truncated);
339 return 0;
c3d8e071 340 }
c3d8e071 341 }
c3d8e071 342
0dc4c667
ILT
343 /* read the record header on Alpha. */
344
345 if ((test_len != 0)
346 && (bfd_read (PRIV(vms_buf), 1, test_len, abfd) != test_len))
c3d8e071 347 {
c3d8e071
ILT
348 bfd_set_error (bfd_error_file_truncated);
349 return 0;
350 }
351
352 /* check file format on first call */
353
354 if (PRIV(file_format) == FF_UNKNOWN)
355 { /* record length repeats ? */
0dc4c667
ILT
356 if ( (vms_buf[0] == vms_buf[4])
357 && (vms_buf[1] == vms_buf[5]))
c3d8e071
ILT
358 {
359 PRIV(file_format) = FF_FOREIGN; /* Y: foreign environment */
360 test_start = 2;
361 }
362 else
363 {
364 PRIV(file_format) = FF_NATIVE; /* N: native environment */
365 test_start = 0;
366 }
c3d8e071
ILT
367 }
368
0dc4c667 369 if (PRIV(is_vax))
c3d8e071 370 {
0dc4c667
ILT
371 PRIV(rec_length) = bfd_read (vms_buf, 1, PRIV(buf_size), abfd);
372 if (PRIV(rec_length) <= 0)
373 {
374 bfd_set_error (bfd_error_file_truncated);
375 return 0;
376 }
377 PRIV(vms_rec) = vms_buf;
c3d8e071 378 }
0dc4c667
ILT
379 else /* Alpha */
380 {
381 /* extract vms record length */
c3d8e071 382
0dc4c667
ILT
383 _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL,
384 &PRIV(rec_length));
c3d8e071 385
0dc4c667
ILT
386 if (PRIV(rec_length) <= 0)
387 {
388 bfd_set_error (bfd_error_file_truncated);
389 return 0;
390 }
c3d8e071 391
0dc4c667 392 /* that's what the linker manual says */
c3d8e071 393
0dc4c667 394 if (PRIV(rec_length) > EOBJ_S_C_MAXRECSIZ)
c3d8e071 395 {
0dc4c667
ILT
396 bfd_set_error (bfd_error_file_truncated);
397 return 0;
c3d8e071 398 }
c3d8e071 399
0dc4c667
ILT
400 /* adjust the buffer */
401
402 if (PRIV(rec_length) > PRIV(buf_size))
403 {
404 PRIV(vms_buf) = (unsigned char *) realloc (vms_buf, PRIV(rec_length));
405 vms_buf = PRIV(vms_buf);
406 if (vms_buf == 0)
407 {
408 bfd_set_error (bfd_error_no_memory);
409 return -1;
410 }
411 PRIV(buf_size) = PRIV(rec_length);
412 }
c3d8e071 413
0dc4c667 414 /* read the remaining record */
c3d8e071 415
0dc4c667
ILT
416 remaining = PRIV(rec_length) - test_len + test_start;
417
418#if VMS_DEBUG
419 vms_debug (10, "bfd_read remaining %d\n", remaining);
c3d8e071 420#endif
0dc4c667
ILT
421 if (bfd_read (vms_buf + test_len, 1, remaining, abfd) != remaining)
422 {
423 bfd_set_error (bfd_error_file_truncated);
424 return 0;
425 }
426 PRIV(vms_rec) = vms_buf + test_start;
c3d8e071
ILT
427 }
428
0dc4c667
ILT
429#if VMS_DEBUG
430 vms_debug (11, "bfd_read rec_length %d\n", PRIV(rec_length));
431#endif
c3d8e071
ILT
432
433 return PRIV(rec_length);
434}
435
436
0dc4c667
ILT
437/* get next vms record from file
438 update vms_rec and rec_length to new (remaining) values */
c3d8e071
ILT
439
440int
0dc4c667 441_bfd_vms_next_record (abfd)
c3d8e071
ILT
442 bfd *abfd;
443{
0dc4c667
ILT
444#if VMS_DEBUG
445 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
c3d8e071
ILT
446 PRIV(rec_length), PRIV(rec_size));
447#endif
448
449 if (PRIV(rec_length) > 0)
450 {
0dc4c667 451 PRIV(vms_rec) += PRIV(rec_size);
c3d8e071
ILT
452 }
453 else
454 {
0dc4c667 455 if (_bfd_vms_get_record (abfd) <= 0)
c3d8e071
ILT
456 return -1;
457 }
0dc4c667
ILT
458
459 if (PRIV(is_vax))
460 {
461 PRIV(rec_type) = *(PRIV(vms_rec));
462 PRIV(rec_size) = PRIV(rec_length);
463 }
464 else
465 {
466 _bfd_vms_get_header_values (abfd, PRIV(vms_rec), &PRIV(rec_type),
467 &PRIV(rec_size));
468 }
c3d8e071
ILT
469 PRIV(rec_length) -= PRIV(rec_size);
470
0dc4c667
ILT
471#if VMS_DEBUG
472 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
473 PRIV(vms_rec), PRIV(rec_size), PRIV(rec_length),
c3d8e071
ILT
474 PRIV(rec_type));
475#endif
476
477 return PRIV(rec_type);
478}
479
480
481\f
482/* Copy sized string (string with fixed length) to new allocated area
483 size is string length (size of record) */
484
485char *
0dc4c667
ILT
486_bfd_vms_save_sized_string (str, size)
487 unsigned char *str;
c3d8e071
ILT
488 int size;
489{
490 char *newstr = bfd_malloc (size + 1);
491
492 if (newstr == NULL)
493 return 0;
0dc4c667 494 strncpy (newstr, (char *)str, size);
c3d8e071
ILT
495 newstr[size] = 0;
496
497 return newstr;
498}
499
500/* Copy counted string (string with length at first byte) to new allocated area
501 ptr points to length byte on entry */
502
503char *
0dc4c667
ILT
504_bfd_vms_save_counted_string (ptr)
505 unsigned char *ptr;
c3d8e071
ILT
506{
507 int len = *ptr++;
508
0dc4c667 509 return _bfd_vms_save_sized_string (ptr, len);
c3d8e071
ILT
510}
511
512\f
0dc4c667 513/* stack routines for vms ETIR commands */
c3d8e071
ILT
514
515/* Push value and section index */
516
517void
0dc4c667 518_bfd_vms_push (abfd, val, psect)
c3d8e071
ILT
519 bfd *abfd;
520 uquad val;
521 int psect;
522{
523 static int last_psect;
524
0dc4c667
ILT
525#if VMS_DEBUG
526 vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV(stackptr));
c3d8e071
ILT
527#endif
528
529 if (psect >= 0)
530 last_psect = psect;
531
532 PRIV(stack[PRIV(stackptr)]).value = val;
533 PRIV(stack[PRIV(stackptr)]).psect = last_psect;
534 PRIV(stackptr)++;
535 if (PRIV(stackptr) >= STACKSIZE)
536 {
537 bfd_set_error (bfd_error_bad_value);
0dc4c667
ILT
538 (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV(stackptr));
539 exit (1);
c3d8e071
ILT
540 }
541 return;
542}
543
544
545/* Pop value and section index */
546
547uquad
0dc4c667 548_bfd_vms_pop (abfd, psect)
c3d8e071
ILT
549 bfd *abfd;
550 int *psect;
551{
552 uquad value;
553
554 if (PRIV(stackptr) == 0)
555 {
556 bfd_set_error (bfd_error_bad_value);
0dc4c667
ILT
557 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
558 exit (1);
c3d8e071
ILT
559 }
560 PRIV(stackptr)--;
561 value = PRIV(stack[PRIV(stackptr)]).value;
562 if ((psect != NULL) && (PRIV(stack[PRIV(stackptr)]).psect >= 0))
563 *psect = PRIV(stack[PRIV(stackptr)]).psect;
564
0dc4c667
ILT
565#if VMS_DEBUG
566 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV(stack[PRIV(stackptr)]).psect);
c3d8e071
ILT
567#endif
568
569 return value;
570}
571
572\f
573/* object file output functions */
574
575/* GAS tends to write sections in little chunks (bfd_set_section_contents)
576 which we can't use directly. So we save the little chunks in linked
577 lists (one per section) and write them later. */
578
0dc4c667 579/* Add a new vms_section structure to vms_section_table
c3d8e071
ILT
580 - forward chaining - */
581
0dc4c667 582static vms_section *
c3d8e071
ILT
583add_new_contents (abfd, section)
584 bfd *abfd;
585 sec_ptr section;
586{
0dc4c667 587 vms_section *sptr, *newptr;
c3d8e071 588
0dc4c667 589 sptr = PRIV(vms_section_table)[section->index];
8612a388
ILT
590 if (sptr != NULL)
591 return sptr;
592
0dc4c667
ILT
593 newptr = (vms_section *) bfd_malloc (sizeof (vms_section));
594 if (newptr == (vms_section *) NULL)
8612a388 595 return NULL;
bf53bd9f 596 newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
8612a388
ILT
597 if (newptr->contents == (unsigned char *)NULL)
598 return NULL;
599 newptr->offset = 0;
600 newptr->size = section->_raw_size;
601 newptr->next = 0;
0dc4c667 602 PRIV(vms_section_table)[section->index] = newptr;
c3d8e071
ILT
603 return newptr;
604}
605
606
0dc4c667
ILT
607/* Save section data & offset to an vms_section structure
608 vms_section_table[] holds the vms_section chain */
c3d8e071
ILT
609
610boolean
0dc4c667 611_bfd_save_vms_section (abfd, section, data, offset, count)
c3d8e071
ILT
612 bfd *abfd;
613 sec_ptr section;
614 PTR data;
615 file_ptr offset;
616 bfd_size_type count;
617{
0dc4c667 618 vms_section *sptr;
c3d8e071 619
0dc4c667 620 if (section->index >= VMS_SECTION_COUNT)
c3d8e071
ILT
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;
8612a388 630 memcpy (sptr->contents + offset, data, (size_t) count);
c3d8e071
ILT
631
632 return true;
633}
634
635
0dc4c667 636/* Get vms_section pointer to saved contents for section # index */
c3d8e071 637
0dc4c667
ILT
638vms_section *
639_bfd_get_vms_section (abfd, index)
c3d8e071
ILT
640 bfd *abfd;
641 int index;
642{
0dc4c667 643 if (index >= VMS_SECTION_COUNT)
c3d8e071
ILT
644 {
645 bfd_set_error (bfd_error_nonrepresentable_section);
646 return NULL;
647 }
0dc4c667 648 return PRIV(vms_section_table)[index];
c3d8e071
ILT
649}
650
651\f
652/* Object output routines */
653
654/* Begin new record or record header
655 write 2 bytes rectype
656 write 2 bytes record length (filled in at flush)
657 write 2 bytes header type (ommitted if rechead == -1) */
658
659void
0dc4c667 660_bfd_vms_output_begin (abfd, rectype, rechead)
c3d8e071
ILT
661 bfd *abfd;
662 int rectype;
663 int rechead;
664{
0dc4c667
ILT
665#if VMS_DEBUG
666 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
c3d8e071
ILT
667 rechead);
668#endif
669
0dc4c667 670 _bfd_vms_output_short (abfd,rectype);
c3d8e071
ILT
671
672 /* save current output position to fill in lenght later */
673
674 if (PRIV(push_level) > 0)
675 PRIV(length_pos) = PRIV(output_size);
676
0dc4c667
ILT
677#if VMS_DEBUG
678 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
c3d8e071
ILT
679 PRIV(length_pos));
680#endif
681
0dc4c667 682 _bfd_vms_output_short (abfd,0); /* placeholder for length */
c3d8e071
ILT
683
684 if (rechead != -1)
0dc4c667 685 _bfd_vms_output_short (abfd,rechead);
c3d8e071
ILT
686
687 return;
688}
689
690
691/* Set record/subrecord alignment */
692
693void
0dc4c667 694_bfd_vms_output_alignment (abfd, alignto)
c3d8e071
ILT
695 bfd *abfd;
696 int alignto;
697{
0dc4c667
ILT
698#if VMS_DEBUG
699 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
c3d8e071
ILT
700#endif
701
702 PRIV(output_alignment) = alignto;
703 return;
704}
705
706
707/* Prepare for subrecord fields */
708
709void
0dc4c667 710_bfd_vms_output_push (abfd)
c3d8e071
ILT
711 bfd *abfd;
712{
0dc4c667
ILT
713#if VMS_DEBUG
714 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV(output_size));
c3d8e071
ILT
715#endif
716
717 PRIV(push_level)++;
718 PRIV(pushed_size) = PRIV(output_size);
719 return;
720}
721
722
723/* End of subrecord fields */
724
725void
0dc4c667 726_bfd_vms_output_pop (abfd)
c3d8e071
ILT
727 bfd *abfd;
728{
0dc4c667
ILT
729#if VMS_DEBUG
730 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV(pushed_size));
c3d8e071
ILT
731#endif
732
0dc4c667 733 _bfd_vms_output_flush (abfd);
c3d8e071
ILT
734 PRIV(length_pos) = 2;
735
0dc4c667
ILT
736#if VMS_DEBUG
737 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV(length_pos));
c3d8e071
ILT
738#endif
739
740 PRIV(pushed_size) = 0;
741 PRIV(push_level)--;
742 return;
743}
744
745
746/* Flush unwritten output, ends current record */
747
748void
0dc4c667 749_bfd_vms_output_flush (abfd)
c3d8e071
ILT
750 bfd *abfd;
751{
752 int real_size = PRIV(output_size);
753 int aligncount;
754 int length;
755
0dc4c667
ILT
756#if VMS_DEBUG
757 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
c3d8e071
ILT
758 real_size, PRIV(pushed_size), PRIV(length_pos));
759#endif
760
761 if (PRIV(push_level) > 0)
762 length = real_size - PRIV(pushed_size);
763 else
764 length = real_size;
765
766 if (length == 0)
767 return;
768 aligncount = (PRIV(output_alignment)
769 - (length % PRIV(output_alignment))) % PRIV(output_alignment);
770
0dc4c667
ILT
771#if VMS_DEBUG
772 vms_debug (6, "align: adding %d bytes\n", aligncount);
c3d8e071
ILT
773#endif
774
775 while(aligncount-- > 0)
776 {
777 PRIV(output_buf)[real_size++] = 0;
778#if 0
779 /* this is why I *love* vms: inconsistency :-}
780 alignment is added to the subrecord length
781 but not to the record length */
782 if (PRIV(push_level) > 0)
783#endif
784 length++;
785 }
786
787 /* put length to buffer */
788 PRIV(output_size) = PRIV(length_pos);
0dc4c667 789 _bfd_vms_output_short (abfd, (unsigned int)length);
c3d8e071
ILT
790
791 if (PRIV(push_level) == 0)
792 {
793#ifndef VMS
794 /* write length first, see FF_FOREIGN in the input routines */
795 fwrite (PRIV(output_buf)+2, 2, 1, (FILE *)abfd->iostream);
796#endif
797 fwrite (PRIV(output_buf), real_size, 1, (FILE *)abfd->iostream);
798
799 PRIV(output_size) = 0;
800 }
801 else
802 {
803 PRIV(output_size) = real_size;
804 PRIV(pushed_size) = PRIV(output_size);
805 }
806
807 return;
808}
809
810
811/* End record output */
812
813void
0dc4c667 814_bfd_vms_output_end (abfd)
c3d8e071
ILT
815 bfd *abfd;
816{
0dc4c667
ILT
817#if VMS_DEBUG
818 vms_debug (6, "_bfd_vms_output_end\n");
c3d8e071
ILT
819#endif
820
0dc4c667 821 _bfd_vms_output_flush (abfd);
c3d8e071
ILT
822
823 return;
824}
825
826
827/* check remaining buffer size
828
829 return what's left. */
830
831int
0dc4c667 832_bfd_vms_output_check (abfd, size)
c3d8e071
ILT
833 bfd *abfd;
834 int size;
835{
0dc4c667
ILT
836#if VMS_DEBUG
837 vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
c3d8e071
ILT
838#endif
839
840 return (MAX_OUTREC_SIZE - (PRIV(output_size) + size + MIN_OUTREC_LUFT));
841}
842
843
844/* Output byte (8 bit) value */
845
846void
0dc4c667 847_bfd_vms_output_byte (abfd, value)
c3d8e071
ILT
848 bfd *abfd;
849 unsigned int value;
850{
0dc4c667
ILT
851#if VMS_DEBUG
852 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
c3d8e071
ILT
853#endif
854
855 bfd_put_8 (abfd, value & 0xff, PRIV(output_buf) + PRIV(output_size));
856 PRIV(output_size) += 1;
857 return;
858}
859
860
861/* Output short (16 bit) value */
862
863void
0dc4c667 864_bfd_vms_output_short (abfd, value)
c3d8e071
ILT
865 bfd *abfd;
866 unsigned int value;
867{
0dc4c667
ILT
868#if VMS_DEBUG
869 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
c3d8e071
ILT
870#endif
871
872 bfd_put_16 (abfd, value & 0xffff, PRIV(output_buf) + PRIV(output_size));
873 PRIV(output_size) += 2;
874 return;
875}
876
877
878/* Output long (32 bit) value */
879
880void
0dc4c667 881_bfd_vms_output_long (abfd, value)
c3d8e071
ILT
882 bfd *abfd;
883 unsigned long value;
884{
0dc4c667
ILT
885#if VMS_DEBUG
886 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
c3d8e071
ILT
887#endif
888
889 bfd_put_32 (abfd, value, PRIV(output_buf) + PRIV(output_size));
890 PRIV(output_size) += 4;
891 return;
892}
893
894
895/* Output quad (64 bit) value */
896
897void
0dc4c667 898_bfd_vms_output_quad (abfd, value)
c3d8e071
ILT
899 bfd *abfd;
900 uquad value;
901{
0dc4c667
ILT
902#if VMS_DEBUG
903 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
c3d8e071
ILT
904#endif
905
906 bfd_put_64(abfd, value, PRIV(output_buf) + PRIV(output_size));
907 PRIV(output_size) += 8;
908 return;
909}
910
911
912/* Output c-string as counted string */
913
914void
0dc4c667 915_bfd_vms_output_counted (abfd, value)
c3d8e071
ILT
916 bfd *abfd;
917 char *value;
918{
919int len;
920
0dc4c667
ILT
921#if VMS_DEBUG
922 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
c3d8e071
ILT
923#endif
924
925 len = strlen (value);
926 if (len == 0)
927 {
0dc4c667 928 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
c3d8e071
ILT
929 return;
930 }
931 if (len > 255)
932 {
0dc4c667 933 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
c3d8e071
ILT
934 return;
935 }
0dc4c667
ILT
936 _bfd_vms_output_byte (abfd, len & 0xff);
937 _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
c3d8e071
ILT
938}
939
940
941/* Output character area */
942
943void
0dc4c667 944_bfd_vms_output_dump (abfd, data, length)
c3d8e071
ILT
945 bfd *abfd;
946 unsigned char *data;
947 int length;
948{
0dc4c667
ILT
949#if VMS_DEBUG
950 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
c3d8e071
ILT
951#endif
952
953 if (length == 0)
954 return;
955
956 memcpy (PRIV(output_buf) + PRIV(output_size), data, length);
957 PRIV(output_size) += length;
958
959 return;
960}
961
962
963/* Output count bytes of value */
964
965void
0dc4c667 966_bfd_vms_output_fill (abfd, value, count)
c3d8e071
ILT
967 bfd *abfd;
968 int value;
969 int count;
970{
0dc4c667
ILT
971#if VMS_DEBUG
972 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
c3d8e071
ILT
973#endif
974
975 if (count == 0)
976 return;
977 memset (PRIV(output_buf) + PRIV(output_size), value, count);
978 PRIV(output_size) += count;
979
980 return;
981}
982
bf53bd9f 983/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
c3d8e071 984
bf53bd9f
ILT
985static int
986hash_string (ptr)
987 const char *ptr;
988{
989 register const unsigned char *p = (unsigned char *) ptr;
990 register const unsigned char *end = p + strlen (ptr);
991 register unsigned char c;
992 register int hash = 0;
c3d8e071 993
bf53bd9f
ILT
994 while (p != end)
995 {
996 c = *p++;
997 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
998 }
999 return hash;
1000}
1001
412222d9 1002/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
8696b2db 1003
c3d8e071 1004char *
0dc4c667 1005_bfd_vms_length_hash_symbol (abfd, in, maxlen)
bf53bd9f
ILT
1006 bfd *abfd;
1007 const char *in;
412222d9 1008 int maxlen;
c3d8e071 1009{
bf53bd9f
ILT
1010 long int init;
1011 long int result;
8696b2db 1012 int in_len;
bf53bd9f
ILT
1013 char *pnt = 0;
1014 char *new_name;
1015 const char *old_name;
1016 int i;
412222d9 1017 static char outbuf[EOBJ_S_C_SYMSIZ+1];
bf53bd9f 1018 char *out = outbuf;
c3d8e071 1019
0dc4c667
ILT
1020#if VMS_DEBUG
1021 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
bf53bd9f
ILT
1022#endif
1023
412222d9
ILT
1024 if (maxlen > EOBJ_S_C_SYMSIZ)
1025 maxlen = EOBJ_S_C_SYMSIZ;
1026
bf53bd9f
ILT
1027 new_name = out; /* save this for later. */
1028
1029 /* We may need to truncate the symbol, save the hash for later. */
1030
8696b2db 1031 in_len = strlen (in);
bf53bd9f 1032
412222d9 1033 result = (in_len > maxlen) ? hash_string (in) : 0;
bf53bd9f 1034
8696b2db 1035 old_name = in;
c3d8e071 1036
8696b2db 1037 /* Do the length checking. */
bf53bd9f 1038
412222d9
ILT
1039 if (in_len <= maxlen)
1040 {
1041 i = in_len;
1042 }
1043 else
1044 {
1045 if (PRIV(flag_hash_long_names))
1046 i = maxlen-9;
bf53bd9f 1047 else
412222d9
ILT
1048 i = maxlen;
1049 }
bf53bd9f 1050
8696b2db
ILT
1051 strncpy (out, in, i);
1052 in += i;
1053 out += i;
1054
412222d9 1055 if ((in_len > maxlen)
8696b2db
ILT
1056 && PRIV(flag_hash_long_names))
1057 sprintf (out, "_%08x", result);
1058 else
412222d9 1059 *out = 0;
c3d8e071 1060
0dc4c667
ILT
1061#if VMS_DEBUG
1062 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
c3d8e071
ILT
1063#endif
1064
412222d9 1065 if (in_len > maxlen
bf53bd9f
ILT
1066 && PRIV(flag_hash_long_names)
1067 && PRIV(flag_show_after_trunc))
53d3ce37 1068 printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
bf53bd9f
ILT
1069
1070 return outbuf;
c3d8e071 1071}
bf53bd9f 1072
0dc4c667
ILT
1073
1074/* Allocate and initialize a new symbol. */
1075
1076static asymbol *
1077new_symbol (abfd, name)
1078 bfd *abfd;
1079 char *name;
1080{
1081 asymbol *symbol;
1082
1083#if VMS_DEBUG
1084 _bfd_vms_debug (7, "new_symbol %s\n", name);
1085#endif
1086
1087 symbol = _bfd_vms_make_empty_symbol (abfd);
1088 if (symbol == 0)
1089 return symbol;
1090 symbol->name = name;
1091 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1092
1093 return symbol;
1094}
1095
1096
1097/* Allocate and enter a new private symbol. */
1098
1099vms_symbol_entry *
1100_bfd_vms_enter_symbol (abfd, name)
1101 bfd *abfd;
1102 char *name;
1103{
1104 vms_symbol_entry *entry;
1105
1106#if VMS_DEBUG
1107 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1108#endif
1109
1110 entry = (vms_symbol_entry *)
1111 bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false);
1112 if (entry == 0)
1113 {
1114#if VMS_DEBUG
1115 _bfd_vms_debug (8, "creating hash entry for %s\n", name);
1116#endif
1117 entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, true, false);
1118 if (entry != 0)
1119 {
1120 asymbol *symbol;
1121 symbol = new_symbol (abfd, name);
1122 if (symbol != 0)
1123 {
1124 entry->symbol = symbol;
1125 PRIV(gsd_sym_count)++;
1126 abfd->symcount++;
1127 }
1128 else
1129 entry = 0;
1130 }
1131 else
1132 (*_bfd_error_handler) (_("failed to enter %s"), name);
1133 }
1134 else
1135 {
1136#if VMS_DEBUG
1137 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1138#endif
1139 }
1140
1141#if VMS_DEBUG
1142 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1143#endif
1144 return entry;
1145}
This page took 0.137509 seconds and 4 git commands to generate.