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