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