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