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