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