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