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