2009-11-17 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / bfd / vms-gsd.c
CommitLineData
252b5132
RH
1/* vms-gsd.c -- BFD back-end for VAX (openVMS/VAX) and
2 EVAX (openVMS/Alpha) files.
3db64b00 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
0c376465 4 2007, 2009 Free Software Foundation, Inc.
252b5132 5
0c376465
TG
6 GSD record handling functions
7 EGSD record handling functions
8
9 Go and read the openVMS linker manual (esp. appendix B)
252b5132
RH
10 if you don't know what's going on here :-)
11
12 Written by Klaus K"ampf (kkaempf@rmi.de)
13
7920ce38
NC
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
cd123cb7 16 the Free Software Foundation; either version 3 of the License, or
7920ce38 17 (at your option) any later version.
252b5132 18
7920ce38
NC
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
252b5132 23
7920ce38
NC
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
cd123cb7
NC
26 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
27 MA 02110-1301, USA. */
252b5132 28
252b5132 29#include "sysdep.h"
3db64b00 30#include "bfd.h"
252b5132
RH
31#include "bfdlink.h"
32#include "libbfd.h"
33
34#include "vms.h"
35
7920ce38 36/* Typical sections for vax object files. */
252b5132
RH
37
38#define VAX_CODE_NAME "$CODE"
39#define VAX_DATA_NAME "$DATA"
40#define VAX_ADDRESS_DATA_NAME "$ADDRESS_DATA"
41
7920ce38 42/* Typical sections for evax object files. */
252b5132
RH
43
44#define EVAX_ABS_NAME "$ABS$"
45#define EVAX_CODE_NAME "$CODE$"
46#define EVAX_LINK_NAME "$LINK$"
47#define EVAX_DATA_NAME "$DATA$"
48#define EVAX_BSS_NAME "$BSS$"
49#define EVAX_READONLYADDR_NAME "$READONLY_ADDR$"
50#define EVAX_READONLY_NAME "$READONLY$"
51#define EVAX_LITERAL_NAME "$LITERAL$"
0c376465 52#define EVAX_LITERALS_NAME "$LITERALS"
252b5132
RH
53#define EVAX_COMMON_NAME "$COMMON$"
54#define EVAX_LOCAL_NAME "$LOCAL$"
55
7920ce38
NC
56struct sec_flags_struct
57{
58 char *name; /* Name of section. */
252b5132 59 int vflags_always;
7920ce38 60 flagword flags_always; /* Flags we set always. */
252b5132 61 int vflags_hassize;
7920ce38 62 flagword flags_hassize; /* Flags we set if the section has a size > 0. */
252b5132
RH
63};
64
7920ce38 65/* These flags are deccrtl/vaxcrtl (openVMS 6.2 VAX) compatible. */
252b5132 66
7920ce38
NC
67static struct sec_flags_struct vax_section_flags[] =
68 {
69 { VAX_CODE_NAME,
70 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD),
71 (SEC_CODE),
72 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD),
73 (SEC_IN_MEMORY | SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
74 { VAX_DATA_NAME,
75 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT),
76 (SEC_DATA),
77 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT),
78 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
79 { VAX_ADDRESS_DATA_NAME,
80 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD),
81 (SEC_DATA | SEC_READONLY),
82 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD),
83 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
84 { NULL,
85 (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_RD | GPS_S_M_WRT),
86 (SEC_DATA),
87 (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_RD | GPS_S_M_WRT),
88 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }
89 };
90
91/* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible. */
252b5132 92
7920ce38
NC
93static struct sec_flags_struct evax_section_flags[] =
94 {
95 { EVAX_ABS_NAME,
96 (EGPS_S_V_SHR),
97 (SEC_DATA),
98 (EGPS_S_V_SHR),
99 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
100 { EVAX_CODE_NAME,
101 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_EXE),
102 (SEC_CODE),
103 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_EXE),
104 (SEC_IN_MEMORY | SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
105 { EVAX_LITERAL_NAME,
106 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD | EGPS_S_V_NOMOD),
107 (SEC_DATA | SEC_READONLY),
108 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD),
109 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
110 { EVAX_LINK_NAME,
111 (EGPS_S_V_REL | EGPS_S_V_RD),
112 (SEC_DATA | SEC_READONLY),
113 (EGPS_S_V_REL | EGPS_S_V_RD),
114 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
115 { EVAX_DATA_NAME,
116 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
117 (SEC_DATA),
118 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
119 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
120 { EVAX_BSS_NAME,
121 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
122 (SEC_NO_FLAGS),
123 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD),
124 (SEC_IN_MEMORY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
125 { EVAX_READONLYADDR_NAME,
126 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_RD),
127 (SEC_DATA | SEC_READONLY),
128 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_RD),
129 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
130 { EVAX_READONLY_NAME,
131 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD | EGPS_S_V_NOMOD),
132 (SEC_DATA | SEC_READONLY),
133 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD),
134 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
135 { EVAX_LOCAL_NAME,
136 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
137 (SEC_DATA),
138 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
139 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) },
0c376465
TG
140 { EVAX_LITERALS_NAME,
141 (EGPS_S_V_PIC | EGPS_S_V_OVR),
142 (SEC_DATA | SEC_READONLY),
143 (EGPS_S_V_PIC | EGPS_S_V_OVR),
144 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) },
7920ce38
NC
145 { NULL,
146 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
147 (SEC_DATA),
148 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT),
149 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }
150 };
524f76c9 151
7920ce38 152/* Retrieve bfd section flags by name and size. */
252b5132
RH
153
154static flagword
7920ce38
NC
155vms_secflag_by_name (bfd *abfd,
156 struct sec_flags_struct *section_flags,
157 char *name,
158 int hassize)
252b5132
RH
159{
160 int i = 0;
161
162 while (section_flags[i].name != NULL)
163 {
7920ce38
NC
164 if ((PRIV (is_vax)?
165 strcasecmp (name, section_flags[i].name):
166 strcmp (name, section_flags[i].name)) == 0)
252b5132 167 {
dc810e39 168 if (hassize)
252b5132
RH
169 return section_flags[i].flags_hassize;
170 else
171 return section_flags[i].flags_always;
172 }
173 i++;
174 }
dc810e39 175 if (hassize)
252b5132
RH
176 return section_flags[i].flags_hassize;
177 return section_flags[i].flags_always;
178}
179
7920ce38 180/* Retrieve vms section flags by name and size. */
252b5132
RH
181
182static flagword
7920ce38
NC
183vms_esecflag_by_name (struct sec_flags_struct *section_flags,
184 char *name,
185 int hassize)
252b5132
RH
186{
187 int i = 0;
188
189 while (section_flags[i].name != NULL)
190 {
191 if (strcmp (name, section_flags[i].name) == 0)
192 {
dc810e39 193 if (hassize)
252b5132
RH
194 return section_flags[i].vflags_hassize;
195 else
196 return section_flags[i].vflags_always;
197 }
198 i++;
199 }
dc810e39 200 if (hassize)
252b5132
RH
201 return section_flags[i].vflags_hassize;
202 return section_flags[i].vflags_always;
203}
204
252b5132 205#if VMS_DEBUG
252b5132
RH
206
207struct flagdescstruct { char *name; flagword value; };
208
0c376465
TG
209static const struct flagdescstruct gpsflagdesc[] =
210{
211 { "PIC", GPS_S_M_PIC },
212 { "LIB", GPS_S_M_LIB },
213 { "OVR", GPS_S_M_OVR },
214 { "REL", GPS_S_M_REL },
215 { "GBL", GPS_S_M_GBL },
216 { "SHR", GPS_S_M_SHR },
217 { "EXE", GPS_S_M_EXE },
218 { "RD", GPS_S_M_RD },
219 { "WRT", GPS_S_M_WRT },
220 { "VEC", GPS_S_M_VEC },
221 { "NOMOD", EGPS_S_V_NOMOD },
222 { "COM", EGPS_S_V_COM },
223 { NULL, 0 }
224};
225
226static const struct flagdescstruct gsyflagdesc[] =
227{
228 { "WEAK", GSY_S_M_WEAK },
229 { "DEF", GSY_S_M_DEF },
230 { "UNI", GSY_S_M_UNI },
231 { "REL", GSY_S_M_REL },
232 { "COMM", EGSY_S_V_COMM },
233 { "VECEP", EGSY_S_V_VECEP },
234 { "NORM", EGCY_S_V_NORM },
235 { NULL, 0 }
236};
237
238static char *flag2str (struct flagdescstruct *, flagword);
239
7920ce38 240/* Convert flag to printable string. */
252b5132
RH
241
242static char *
7920ce38 243flag2str (struct flagdescstruct * flagdesc, flagword flags)
252b5132 244{
252b5132
RH
245 static char res[64];
246 int next = 0;
247
248 res[0] = 0;
249 while (flagdesc->name != NULL)
250 {
251 if ((flags & flagdesc->value) != 0)
252 {
253 if (next)
7920ce38 254 strcat (res, ",");
252b5132
RH
255 else
256 next = 1;
257 strcat (res, flagdesc->name);
258 }
259 flagdesc++;
260 }
261 return res;
262}
263#endif
264
7920ce38 265/* Input routines. */
252b5132 266
0c376465
TG
267static int register_universal_symbol (bfd *abfd, asymbol *symbol,
268 int vms_flags);
269
252b5132 270/* Process GSD/EGSD record
7920ce38 271 return 0 on success, -1 on error. */
252b5132
RH
272
273int
7920ce38 274_bfd_vms_slurp_gsd (bfd * abfd, int objtype)
252b5132 275{
252b5132
RH
276 int gsd_type, gsd_size;
277 asection *section;
278 unsigned char *vms_rec;
279 flagword new_flags, old_flags;
280 char *name;
281 asymbol *symbol;
282 vms_symbol_entry *entry;
283 unsigned long base_addr;
284 unsigned long align_addr;
5f771d47 285 static unsigned int psect_idx = 0;
252b5132
RH
286
287#if VMS_DEBUG
288 vms_debug (2, "GSD/EGSD (%d/%x)\n", objtype, objtype);
289#endif
290
291 switch (objtype)
292 {
dc810e39 293 case EOBJ_S_C_EGSD:
7920ce38
NC
294 PRIV (vms_rec) += 8; /* Skip type, size, l_temp. */
295 PRIV (rec_size) -= 8;
dc810e39
AM
296 break;
297 case OBJ_S_C_GSD:
7920ce38
NC
298 PRIV (vms_rec) += 1;
299 PRIV (rec_size) -= 1;
dc810e39
AM
300 break;
301 default:
302 return -1;
252b5132
RH
303 }
304
7920ce38 305 /* Calculate base address for each section. */
252b5132
RH
306 base_addr = 0L;
307
308 abfd->symcount = 0;
309
7920ce38 310 while (PRIV (rec_size) > 0)
252b5132 311 {
7920ce38 312 vms_rec = PRIV (vms_rec);
252b5132
RH
313
314 if (objtype == OBJ_S_C_GSD)
0c376465 315 gsd_type = vms_rec[0];
252b5132
RH
316 else
317 {
318 _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size);
319 gsd_type += EVAX_OFFSET;
320 }
321
322#if VMS_DEBUG
7920ce38 323 vms_debug (3, "gsd_type %d\n", gsd_type);
252b5132
RH
324#endif
325
326 switch (gsd_type)
327 {
7920ce38
NC
328 case GSD_S_C_PSC:
329 {
330 /* Program section definition. */
331 asection *old_section = 0;
252b5132
RH
332
333#if VMS_DEBUG
7920ce38 334 vms_debug (4, "GSD_S_C_PSC\n");
252b5132 335#endif
7920ce38 336 /* If this section isn't a bfd section. */
0c376465 337 if (PRIV (is_vax) && (psect_idx < (abfd->section_count - 1)))
7920ce38
NC
338 {
339 /* Check for temporary section from TIR record. */
340 if (psect_idx < PRIV (section_count))
341 old_section = PRIV (sections)[psect_idx];
342 else
343 old_section = 0;
344 }
345
346 name = _bfd_vms_save_counted_string (vms_rec + 8);
347 section = bfd_make_section (abfd, name);
348 if (!section)
349 {
350 (*_bfd_error_handler) (_("bfd_make_section (%s) failed"),
351 name);
352 return -1;
353 }
354 old_flags = bfd_getl16 (vms_rec + 2);
355 section->size = bfd_getl32 (vms_rec + 4); /* allocation */
356 new_flags = vms_secflag_by_name (abfd, vax_section_flags, name,
357 section->size > 0);
358 if (old_flags & EGPS_S_V_REL)
359 new_flags |= SEC_RELOC;
360 if (old_flags & GPS_S_M_OVR)
361 new_flags |= SEC_IS_COMMON;
362 if (!bfd_set_section_flags (abfd, section, new_flags))
363 {
364 (*_bfd_error_handler)
365 (_("bfd_set_section_flags (%s, %x) failed"),
366 name, new_flags);
367 return -1;
368 }
369 section->alignment_power = vms_rec[1];
370 align_addr = (1 << section->alignment_power);
371 if ((base_addr % align_addr) != 0)
372 base_addr += (align_addr - (base_addr % align_addr));
373 section->vma = (bfd_vma)base_addr;
374 base_addr += section->size;
375
376 /* Global section is common symbol. */
7920ce38
NC
377 if (old_flags & GPS_S_M_GBL)
378 {
379 entry = _bfd_vms_enter_symbol (abfd, name);
380 if (entry == NULL)
381 {
382 bfd_set_error (bfd_error_no_memory);
383 return -1;
384 }
385 symbol = entry->symbol;
386
387 symbol->value = 0;
388 symbol->section = section;
389 symbol->flags = (BSF_GLOBAL | BSF_SECTION_SYM | BSF_OLD_COMMON);
390 }
391
392 /* Copy saved contents if old_section set. */
393 if (old_section != 0)
394 {
395 section->contents = old_section->contents;
396 if (section->size < old_section->size)
397 {
398 (*_bfd_error_handler)
399 (_("Size mismatch section %s=%lx, %s=%lx"),
400 old_section->name,
401 (unsigned long) old_section->size,
402 section->name,
403 (unsigned long) section->size);
404 return -1;
405 }
406 else if (section->size > old_section->size)
407 {
408 section->contents = bfd_realloc (old_section->contents,
409 section->size);
410 if (section->contents == NULL)
411 {
412 bfd_set_error (bfd_error_no_memory);
413 return -1;
414 }
415 }
416 }
417 else
418 {
419 section->contents = bfd_zmalloc (section->size);
420 if (section->contents == NULL)
421 {
422 bfd_set_error (bfd_error_no_memory);
423 return -1;
424 }
425 }
252b5132 426#if VMS_DEBUG
7920ce38
NC
427 vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ",
428 section->index, name, old_flags, flag2str (gpsflagdesc, old_flags));
429 vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
430 section->size, section->vma, section->contents);
252b5132
RH
431#endif
432
7920ce38 433 gsd_size = vms_rec[8] + 9;
252b5132 434
7920ce38
NC
435 psect_idx++;
436 }
252b5132
RH
437 break;
438
7920ce38
NC
439 case GSD_S_C_EPM:
440 case GSD_S_C_EPMW:
252b5132 441#if VMS_DEBUG
7920ce38 442 vms_debug (4, "gsd epm\n");
252b5132 443#endif
7920ce38
NC
444 /* Fall through. */
445 case GSD_S_C_SYM:
446 case GSD_S_C_SYMW:
447 {
448 int name_offset = 0, value_offset = 0;
252b5132 449
7920ce38 450 /* Symbol specification (definition or reference). */
252b5132 451#if VMS_DEBUG
7920ce38 452 vms_debug (4, "GSD_S_C_SYM(W)\n");
252b5132 453#endif
7920ce38
NC
454 old_flags = bfd_getl16 (vms_rec + 2);
455 new_flags = BSF_NO_FLAGS;
252b5132 456
7920ce38
NC
457 if (old_flags & GSY_S_M_WEAK)
458 new_flags |= BSF_WEAK;
252b5132 459
7920ce38
NC
460 switch (gsd_type)
461 {
462 case GSD_S_C_EPM:
463 name_offset = 11;
464 value_offset = 5;
465 new_flags |= BSF_FUNCTION;
466 break;
467 case GSD_S_C_EPMW:
468 name_offset = 12;
469 value_offset = 6;
470 new_flags |= BSF_FUNCTION;
471 break;
472 case GSD_S_C_SYM:
473 if (old_flags & GSY_S_M_DEF) /* Symbol definition. */
474 name_offset = 9;
475 else
476 name_offset = 4;
477 value_offset = 5;
478 break;
479 case GSD_S_C_SYMW:
480 if (old_flags & GSY_S_M_DEF) /* Symbol definition. */
481 name_offset = 10;
482 else
483 name_offset = 5;
484 value_offset = 6;
485 break;
486 }
487
488 /* Save symbol in vms_symbol_table. */
489 entry = _bfd_vms_enter_symbol
490 (abfd, _bfd_vms_save_counted_string (vms_rec + name_offset));
491 if (entry == NULL)
492 {
493 bfd_set_error (bfd_error_no_memory);
494 return -1;
495 }
496 symbol = entry->symbol;
497
498 if (old_flags & GSY_S_M_DEF)
499 {
500 /* Symbol definition. */
501 int psect;
502
503 symbol->value = bfd_getl32 (vms_rec + value_offset);
504 if ((gsd_type == GSD_S_C_SYMW)
505 || (gsd_type == GSD_S_C_EPMW))
506 psect = bfd_getl16 (vms_rec + value_offset - 2);
507 else
508 psect = vms_rec[value_offset-1];
509
0c376465 510 symbol->section = (asection *)(unsigned long)psect;
252b5132 511#if VMS_DEBUG
0c376465
TG
512 vms_debug (4, "gsd sym def #%d (%s, %ld, %04x=%s)\n", abfd->symcount,
513 symbol->name, (long)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags));
252b5132 514#endif
7920ce38
NC
515 }
516 else
517 {
518 /* Symbol reference. */
252b5132 519#if VMS_DEBUG
0c376465
TG
520 vms_debug (4, "gsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount,
521 symbol->name, old_flags, flag2str (gsyflagdesc, old_flags));
252b5132 522#endif
0c376465 523 symbol->section = (asection *)(unsigned long)-1;
7920ce38 524 }
252b5132 525
7920ce38
NC
526 gsd_size = vms_rec[name_offset] + name_offset + 1;
527 symbol->flags = new_flags;
528 }
252b5132
RH
529
530 break;
531
7920ce38
NC
532 case GSD_S_C_PRO:
533 case GSD_S_C_PROW:
252b5132 534#if VMS_DEBUG
7920ce38 535 vms_debug (4, "gsd pro\n");
252b5132
RH
536#endif
537 break;
7920ce38 538 case GSD_S_C_IDC:
252b5132 539#if VMS_DEBUG
7920ce38 540 vms_debug (4, "gsd idc\n");
252b5132
RH
541#endif
542 break;
7920ce38 543 case GSD_S_C_ENV:
252b5132 544#if VMS_DEBUG
7920ce38 545 vms_debug (4, "gsd env\n");
252b5132
RH
546#endif
547 break;
7920ce38 548 case GSD_S_C_LSY:
252b5132 549#if VMS_DEBUG
7920ce38 550 vms_debug (4, "gsd lsy\n");
252b5132
RH
551#endif
552 break;
7920ce38 553 case GSD_S_C_LEPM:
252b5132 554#if VMS_DEBUG
7920ce38 555 vms_debug (4, "gsd lepm\n");
252b5132
RH
556#endif
557 break;
7920ce38 558 case GSD_S_C_LPRO:
252b5132 559#if VMS_DEBUG
7920ce38 560 vms_debug (4, "gsd lpro\n");
252b5132
RH
561#endif
562 break;
7920ce38 563 case GSD_S_C_SPSC:
252b5132 564#if VMS_DEBUG
7920ce38 565 vms_debug (4, "gsd spsc\n");
252b5132
RH
566#endif
567 break;
7920ce38 568 case GSD_S_C_SYMV:
252b5132 569#if VMS_DEBUG
7920ce38 570 vms_debug (4, "gsd symv\n");
252b5132
RH
571#endif
572 break;
7920ce38 573 case GSD_S_C_EPMV:
252b5132 574#if VMS_DEBUG
7920ce38 575 vms_debug (4, "gsd epmv\n");
252b5132
RH
576#endif
577 break;
7920ce38 578 case GSD_S_C_PROV:
252b5132 579#if VMS_DEBUG
7920ce38 580 vms_debug (4, "gsd prov\n");
252b5132
RH
581#endif
582 break;
583
584 case EGSD_S_C_PSC + EVAX_OFFSET:
585 {
7920ce38 586 /* Program section definition. */
0c376465 587 name = _bfd_vms_save_counted_string (vms_rec + EGPS_S_B_NAMLNG);
252b5132
RH
588 section = bfd_make_section (abfd, name);
589 if (!section)
590 return -1;
0c376465
TG
591 old_flags = bfd_getl16 (vms_rec + EGPS_S_W_FLAGS);
592 section->size = bfd_getl32 (vms_rec + EGPS_S_L_ALLOC);
dc810e39 593 new_flags = vms_secflag_by_name (abfd, evax_section_flags, name,
eea6121a 594 section->size > 0);
252b5132
RH
595 if (old_flags & EGPS_S_V_REL)
596 new_flags |= SEC_RELOC;
597 if (!bfd_set_section_flags (abfd, section, new_flags))
598 return -1;
0c376465 599 section->alignment_power = vms_rec[EGPS_S_B_ALIGN];
252b5132
RH
600 align_addr = (1 << section->alignment_power);
601 if ((base_addr % align_addr) != 0)
602 base_addr += (align_addr - (base_addr % align_addr));
603 section->vma = (bfd_vma)base_addr;
eea6121a 604 base_addr += section->size;
7920ce38 605 section->contents = bfd_zmalloc (section->size);
252b5132
RH
606 if (section->contents == NULL)
607 return -1;
0c376465 608 section->filepos = (unsigned int)-1;
252b5132 609#if VMS_DEBUG
0c376465
TG
610 vms_debug (4, "EGSD P-section %d (%s, flags %04x=%s) ",
611 section->index, name, old_flags, flag2str(gpsflagdesc, old_flags));
7920ce38 612 vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n",
eea6121a 613 section->size, section->vma, section->contents);
252b5132
RH
614#endif
615 }
616 break;
617
618 case EGSD_S_C_SYM + EVAX_OFFSET:
619 {
0c376465 620 /* Global symbol specification (definition or reference). */
3f3c5c34 621 symbol = bfd_make_empty_symbol (abfd);
252b5132
RH
622 if (symbol == 0)
623 return -1;
624
0c376465 625 old_flags = bfd_getl16 (vms_rec + EGSY_S_W_FLAGS);
252b5132
RH
626 new_flags = BSF_NO_FLAGS;
627
628 if (old_flags & EGSY_S_V_WEAK)
629 new_flags |= BSF_WEAK;
630
0c376465 631 if (old_flags & EGSY_S_V_DEF)
252b5132 632 {
7920ce38 633 /* Symbol definition. */
252b5132 634 if (old_flags & EGSY_S_V_NORM)
7920ce38 635 new_flags |= BSF_FUNCTION;
0c376465
TG
636 symbol->name =
637 _bfd_vms_save_counted_string (vms_rec + ESDF_S_B_NAMLNG);
638 symbol->value = bfd_getl64 (vms_rec + ESDF_S_L_VALUE);
639 symbol->section =
640 (asection *)(unsigned long) bfd_getl32 (vms_rec + ESDF_S_L_PSINDX);
252b5132 641#if VMS_DEBUG
0c376465
TG
642 vms_debug (4, "EGSD sym def #%d (%s, %ld, %04x=%s)\n",
643 abfd->symcount, symbol->name, (long)symbol->section,
644 old_flags, flag2str (gsyflagdesc, old_flags));
252b5132
RH
645#endif
646 }
7920ce38 647 else
252b5132 648 {
7920ce38 649 /* Symbol reference. */
0c376465
TG
650 symbol->name =
651 _bfd_vms_save_counted_string (vms_rec + ESRF_S_B_NAMLNG);
252b5132 652#if VMS_DEBUG
0c376465
TG
653 vms_debug (4, "EGSD sym ref #%d (%s, %04x=%s)\n",
654 abfd->symcount, symbol->name, old_flags,
655 flag2str (gsyflagdesc, old_flags));
252b5132 656#endif
0c376465 657 symbol->section = (asection *)(unsigned long)-1;
252b5132
RH
658 }
659
660 symbol->flags = new_flags;
661
0c376465
TG
662 /* Register symbol in VMS symbol table. */
663 entry = (vms_symbol_entry *) bfd_hash_lookup
664 (PRIV (vms_symbol_table), symbol->name, TRUE, FALSE);
665
7920ce38 666 if (entry == NULL)
252b5132
RH
667 {
668 bfd_set_error (bfd_error_no_memory);
669 return -1;
670 }
7920ce38
NC
671
672 if (entry->symbol != NULL)
673 {
674 /* FIXME ?, DEC C generates this. */
252b5132 675#if VMS_DEBUG
7920ce38 676 vms_debug (4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name);
252b5132
RH
677#endif
678 }
679 else
680 {
681 entry->symbol = symbol;
7920ce38 682 PRIV (gsd_sym_count)++;
252b5132
RH
683 abfd->symcount++;
684 }
685 }
686 break;
687
0c376465
TG
688 case EGSD_S_C_SYMG + EVAX_OFFSET:
689 {
690 /* Universal symbol specification (definition). */
691 symbol = bfd_make_empty_symbol (abfd);
692 if (symbol == 0)
693 return -1;
694
695 old_flags = bfd_getl16 (vms_rec + EGST_S_W_FLAGS);
696 new_flags = BSF_NO_FLAGS;
697
698 if (old_flags & EGSY_S_V_WEAK)
699 new_flags |= BSF_WEAK;
700
701 if (old_flags & EGSY_S_V_DEF) /* symbol definition */
702 {
703 if (old_flags & EGSY_S_V_NORM)
704 new_flags |= BSF_FUNCTION;
705
706 symbol->name =
707 _bfd_vms_save_counted_string (vms_rec + EGST_S_B_NAMLNG);
708
709 /* For BSF_FUNCTION symbols, the entry point is in LP_1
710 and the descriptor in LP_2. For other symbols, the
711 unique value is in LP_2. */
712 symbol->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_2);
713
714 /* Adding this offset is necessary in order for GDB to
715 read the DWARF-2 debug info from shared libraries. */
716 if (abfd->flags & DYNAMIC
717 && strstr (symbol->name, "$DWARF2.DEBUG") != 0)
718 symbol->value += PRIV (symvva);
719 }
720 else /* symbol reference */
721 (*_bfd_error_handler) ("Invalid EGST reference");
722
723 symbol->flags = new_flags;
724
725 if (register_universal_symbol (abfd, symbol, old_flags) < 0)
726 return -1;
727
728 /* Make a second symbol for the entry point. */
729 if (symbol->flags & BSF_FUNCTION)
730 {
731 asymbol *en_sym;
732 char *name = bfd_alloc (abfd, strlen (symbol->name) + 5);
733
734 en_sym = bfd_make_empty_symbol (abfd);
735 if (en_sym == 0)
736 return -1;
737
738 strcpy (name, symbol->name);
739 strcat (name, "..en");
740
741 en_sym->name = name;
742 en_sym->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_1);
743
744 if (register_universal_symbol (abfd, en_sym, old_flags) < 0)
745 return -1;
746 }
747 }
252b5132
RH
748 break;
749
0c376465
TG
750 case EGSD_S_C_IDC + EVAX_OFFSET:
751 break;
752
252b5132 753 default:
0c376465 754 (*_bfd_error_handler) (_("Unknown GSD/EGSD subtype %d"), gsd_type);
252b5132
RH
755 bfd_set_error (bfd_error_bad_value);
756 return -1;
7920ce38 757 }
252b5132 758
7920ce38
NC
759 PRIV (rec_size) -= gsd_size;
760 PRIV (vms_rec) += gsd_size;
761 }
252b5132
RH
762
763 if (abfd->symcount > 0)
764 abfd->flags |= HAS_SYMS;
765
766 return 0;
767}
768
0c376465
TG
769/* Register a universal symbol in the VMS symbol table. */
770
771static int
772register_universal_symbol (bfd *abfd, asymbol *symbol, int vms_flags)
773{
774 bfd_vma sbase = 0;
775 asection *s, *sec = NULL;
776 vms_symbol_entry *entry;
777
778 /* A universal symbol is by definition global... */
779 symbol->flags |= BSF_GLOBAL;
780
781 /* ...and dynamic in shared libraries. */
782 if (abfd->flags & DYNAMIC)
783 symbol->flags |= BSF_DYNAMIC;
784
785 /* Find containing section. */
786 for (s = abfd->sections; s; s = s->next)
787 {
788 if (symbol->value >= s->vma
789 && s->vma > sbase
790 && !(s->flags & SEC_COFF_SHARED_LIBRARY)
791 && (s->size > 0 || !(vms_flags & EGSY_S_V_REL)))
792 {
793 sbase = s->vma;
794 sec = s;
795 }
796 }
797
798 symbol->value -= sbase;
799 symbol->section = sec;
800
801#if VMS_DEBUG
802 vms_debug (4, "EGST sym def #%d (%s, 0x%llx => 0x%llx, %04x=%s)\n",
803 abfd->symcount, symbol->name, symbol->value + sbase,
804 symbol->value, vms_flags,
805 flag2str(gsyflagdesc, vms_flags));
806#endif
807
808 entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
809 symbol->name,
810 TRUE, FALSE);
811
812 if (entry == NULL)
813 {
814 bfd_set_error (bfd_error_no_memory);
815 return -1;
816 }
817
818 if (entry->symbol) /* FIXME: DEC C generates this */
819 {
820#if VMS_DEBUG
821 vms_debug (4, "EGSD_S_C_SYMG: duplicate \"%s\"\n", symbol->name);
822#endif
823 }
824 else
825 {
826 entry->symbol = symbol;
827 PRIV (gsd_sym_count)++;
828 abfd->symcount++;
829 }
830
831 return 0;
832}
833
834/* Set section VMS flags. */
835
836void
837bfd_vms_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED,
838 asection *sec, flagword flags)
839{
840 vms_section_data (sec)->vflags = flags;
841}
252b5132 842
7920ce38 843/* Write section and symbol directory of bfd abfd. */
252b5132
RH
844
845int
7920ce38 846_bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED)
252b5132
RH
847{
848 asection *section;
849 asymbol *symbol;
5f771d47 850 unsigned int symnum;
252b5132
RH
851 int last_index = -1;
852 char dummy_name[10];
853 char *sname;
854 flagword new_flags, old_flags;
0c376465 855 int abs_section_index = 0;
252b5132
RH
856
857#if VMS_DEBUG
858 vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype);
859#endif
860
7920ce38 861 /* Output sections. */
252b5132
RH
862 section = abfd->sections;
863#if VMS_DEBUG
864 vms_debug (3, "%d sections found\n", abfd->section_count);
865#endif
866
7920ce38 867 /* Egsd is quadword aligned. */
252b5132
RH
868 _bfd_vms_output_alignment (abfd, 8);
869
870 _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
871 _bfd_vms_output_long (abfd, 0);
7920ce38
NC
872 /* Prepare output for subrecords. */
873 _bfd_vms_output_push (abfd);
252b5132
RH
874
875 while (section != 0)
876 {
877#if VMS_DEBUG
7920ce38 878 vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->size);
252b5132
RH
879#endif
880
0c376465
TG
881 /* Don't write out the VMS debug info section since it is in the
882 ETBT and EDBG sections in etir. */
883 if (!strcmp (section->name, ".vmsdebug"))
884 goto done;
885
7920ce38 886 /* 13 bytes egsd, max 31 chars name -> should be 44 bytes. */
252b5132
RH
887 if (_bfd_vms_output_check (abfd, 64) < 0)
888 {
889 _bfd_vms_output_pop (abfd);
890 _bfd_vms_output_end (abfd);
891 _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
892 _bfd_vms_output_long (abfd, 0);
7920ce38
NC
893 /* Prepare output for subrecords. */
894 _bfd_vms_output_push (abfd);
252b5132
RH
895 }
896
7920ce38 897 /* Create dummy sections to keep consecutive indices. */
252b5132
RH
898 while (section->index - last_index > 1)
899 {
900#if VMS_DEBUG
901 vms_debug (3, "index %d, last %d\n", section->index, last_index);
902#endif
903 _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
904 _bfd_vms_output_short (abfd, 0);
905 _bfd_vms_output_short (abfd, 0);
906 _bfd_vms_output_long (abfd, 0);
907 sprintf (dummy_name, ".DUMMY%02d", last_index);
908 _bfd_vms_output_counted (abfd, dummy_name);
909 _bfd_vms_output_flush (abfd);
910 last_index++;
911 }
912
7dee875e 913 /* Don't know if this is necessary for the linker but for now it keeps
252b5132 914 vms_slurp_gsd happy */
252b5132
RH
915 sname = (char *)section->name;
916 if (*sname == '.')
917 {
918 sname++;
919 if ((*sname == 't') && (strcmp (sname, "text") == 0))
7920ce38 920 sname = PRIV (is_vax)?VAX_CODE_NAME:EVAX_CODE_NAME;
252b5132 921 else if ((*sname == 'd') && (strcmp (sname, "data") == 0))
7920ce38 922 sname = PRIV (is_vax)?VAX_DATA_NAME:EVAX_DATA_NAME;
252b5132
RH
923 else if ((*sname == 'b') && (strcmp (sname, "bss") == 0))
924 sname = EVAX_BSS_NAME;
925 else if ((*sname == 'l') && (strcmp (sname, "link") == 0))
926 sname = EVAX_LINK_NAME;
927 else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0))
928 sname = EVAX_READONLY_NAME;
929 else if ((*sname == 'l') && (strcmp (sname, "literal") == 0))
930 sname = EVAX_LITERAL_NAME;
0c376465
TG
931 else if ((*sname == 'l') && (strcmp (sname, "literals") == 0))
932 {
933 sname = EVAX_LITERALS_NAME;
934 abs_section_index = section->index;
935 }
252b5132
RH
936 else if ((*sname == 'c') && (strcmp (sname, "comm") == 0))
937 sname = EVAX_COMMON_NAME;
938 else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0))
939 sname = EVAX_LOCAL_NAME;
940 }
941 else
942 sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ);
943
944 _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
945 _bfd_vms_output_short (abfd, section->alignment_power & 0xff);
0c376465 946
252b5132 947 if (bfd_is_com_section (section))
0c376465
TG
948 new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD
949 | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM);
252b5132 950 else
7920ce38
NC
951 new_flags = vms_esecflag_by_name (evax_section_flags, sname,
952 section->size > 0);
953
0c376465
TG
954 /* Modify them as directed. */
955 if (section->flags & SEC_READONLY)
956 new_flags &= ~EGPS_S_V_WRT;
957
958 new_flags |= vms_section_data (section)->vflags & 0xffff;
959 new_flags &=
960 ~((vms_section_data (section)->vflags >> EGPS_S_V_NO_SHIFT) & 0xffff);
961
962#if VMS_DEBUG
963 vms_debug (3, "sec flags %x\n", section->flags);
964 vms_debug (3, "new_flags %x, _raw_size %d\n", new_flags, section->size);
965#endif
966
252b5132 967 _bfd_vms_output_short (abfd, new_flags);
eea6121a 968 _bfd_vms_output_long (abfd, (unsigned long) section->size);
252b5132
RH
969 _bfd_vms_output_counted (abfd, sname);
970 _bfd_vms_output_flush (abfd);
971
972 last_index = section->index;
0c376465 973done:
252b5132
RH
974 section = section->next;
975 }
976
7920ce38 977 /* Output symbols. */
252b5132
RH
978#if VMS_DEBUG
979 vms_debug (3, "%d symbols found\n", abfd->symcount);
980#endif
981
7920ce38 982 bfd_set_start_address (abfd, (bfd_vma) -1);
252b5132
RH
983
984 for (symnum = 0; symnum < abfd->symcount; symnum++)
985 {
dc810e39 986 char *hash;
252b5132
RH
987
988 symbol = abfd->outsymbols[symnum];
989 if (*(symbol->name) == '_')
990 {
991 if (strcmp (symbol->name, "__main") == 0)
992 bfd_set_start_address (abfd, (bfd_vma)symbol->value);
993 }
994 old_flags = symbol->flags;
995
996 if (old_flags & BSF_FILE)
997 continue;
998
0c376465
TG
999 if ((old_flags & BSF_GLOBAL) == 0 /* Not xdef... */
1000 && !bfd_is_und_section (symbol->section) /* and not xref... */
1001 && !((old_flags & BSF_SECTION_SYM) != 0 /* and not LIB$INITIALIZE. */
1002 && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0))
1003 continue;
252b5132 1004
7920ce38 1005 /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. */
252b5132
RH
1006 if (_bfd_vms_output_check (abfd, 80) < 0)
1007 {
1008 _bfd_vms_output_pop (abfd);
1009 _bfd_vms_output_end (abfd);
1010 _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
1011 _bfd_vms_output_long (abfd, 0);
7920ce38
NC
1012 /* Prepare output for subrecords. */
1013 _bfd_vms_output_push (abfd);
252b5132
RH
1014 }
1015
1016 _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1);
1017
7920ce38
NC
1018 /* Data type, alignment. */
1019 _bfd_vms_output_short (abfd, 0);
252b5132
RH
1020
1021 new_flags = 0;
1022
1023 if (old_flags & BSF_WEAK)
1024 new_flags |= EGSY_S_V_WEAK;
0c376465 1025 if (bfd_is_com_section (symbol->section)) /* .comm */
7920ce38 1026 new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM);
252b5132
RH
1027
1028 if (old_flags & BSF_FUNCTION)
1029 {
1030 new_flags |= EGSY_S_V_NORM;
1031 new_flags |= EGSY_S_V_REL;
1032 }
0c376465 1033 if (old_flags & BSF_GLOBAL)
252b5132
RH
1034 {
1035 new_flags |= EGSY_S_V_DEF;
1036 if (!bfd_is_abs_section (symbol->section))
1037 new_flags |= EGSY_S_V_REL;
1038 }
1039 _bfd_vms_output_short (abfd, new_flags);
1040
0c376465 1041 if (old_flags & BSF_GLOBAL)
252b5132 1042 {
7920ce38 1043 /* Symbol definition. */
dc810e39
AM
1044 uquad code_address = 0;
1045 unsigned long ca_psindx = 0;
1046 unsigned long psindx;
1047
89117aab 1048 if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
252b5132 1049 {
0c376465
TG
1050 asymbol *sym;
1051
1052 if (bfd_get_flavour (abfd) == bfd_target_evax_flavour)
1053 sym = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
1054 else
1055 sym = (asymbol *)symbol->udata.p;
1056 code_address = sym->value;
1057 ca_psindx = sym->section->index;
252b5132 1058 }
0c376465
TG
1059 if (bfd_is_abs_section (symbol->section))
1060 psindx = abs_section_index;
1061 else
1062 psindx = symbol->section->index;
dc810e39
AM
1063
1064 _bfd_vms_output_quad (abfd, symbol->value);
1065 _bfd_vms_output_quad (abfd, code_address);
1066 _bfd_vms_output_long (abfd, ca_psindx);
1067 _bfd_vms_output_long (abfd, psindx);
252b5132 1068 }
dc810e39
AM
1069 hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ);
1070 _bfd_vms_output_counted (abfd, hash);
252b5132
RH
1071
1072 _bfd_vms_output_flush (abfd);
1073
1074 }
1075
1076 _bfd_vms_output_alignment (abfd, 8);
1077 _bfd_vms_output_pop (abfd);
558e161f 1078 _bfd_vms_output_end (abfd);
252b5132
RH
1079
1080 return 0;
1081}
This page took 0.619396 seconds and 4 git commands to generate.