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