* bfd/elflink.c (_bfd_elf_merge_symbol): Tighten up the test for early
[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 206
771deb08 207struct flagdescstruct { const char *name; flagword value; };
252b5132 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 },
771deb08 234 { "NORM", EGSY_S_V_NORM },
0c376465
TG
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;
91d6fa6a
NC
732
733 name = bfd_alloc (abfd, strlen (symbol->name) + 5);
0c376465
TG
734
735 en_sym = bfd_make_empty_symbol (abfd);
736 if (en_sym == 0)
737 return -1;
738
739 strcpy (name, symbol->name);
740 strcat (name, "..en");
741
742 en_sym->name = name;
743 en_sym->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_1);
744
745 if (register_universal_symbol (abfd, en_sym, old_flags) < 0)
746 return -1;
747 }
748 }
252b5132
RH
749 break;
750
0c376465
TG
751 case EGSD_S_C_IDC + EVAX_OFFSET:
752 break;
753
252b5132 754 default:
0c376465 755 (*_bfd_error_handler) (_("Unknown GSD/EGSD subtype %d"), gsd_type);
252b5132
RH
756 bfd_set_error (bfd_error_bad_value);
757 return -1;
7920ce38 758 }
252b5132 759
7920ce38
NC
760 PRIV (rec_size) -= gsd_size;
761 PRIV (vms_rec) += gsd_size;
762 }
252b5132
RH
763
764 if (abfd->symcount > 0)
765 abfd->flags |= HAS_SYMS;
766
767 return 0;
768}
769
0c376465
TG
770/* Register a universal symbol in the VMS symbol table. */
771
772static int
773register_universal_symbol (bfd *abfd, asymbol *symbol, int vms_flags)
774{
775 bfd_vma sbase = 0;
776 asection *s, *sec = NULL;
777 vms_symbol_entry *entry;
778
779 /* A universal symbol is by definition global... */
780 symbol->flags |= BSF_GLOBAL;
781
782 /* ...and dynamic in shared libraries. */
783 if (abfd->flags & DYNAMIC)
784 symbol->flags |= BSF_DYNAMIC;
785
786 /* Find containing section. */
787 for (s = abfd->sections; s; s = s->next)
788 {
789 if (symbol->value >= s->vma
790 && s->vma > sbase
791 && !(s->flags & SEC_COFF_SHARED_LIBRARY)
792 && (s->size > 0 || !(vms_flags & EGSY_S_V_REL)))
793 {
794 sbase = s->vma;
795 sec = s;
796 }
797 }
798
799 symbol->value -= sbase;
800 symbol->section = sec;
801
802#if VMS_DEBUG
803 vms_debug (4, "EGST sym def #%d (%s, 0x%llx => 0x%llx, %04x=%s)\n",
804 abfd->symcount, symbol->name, symbol->value + sbase,
805 symbol->value, vms_flags,
806 flag2str(gsyflagdesc, vms_flags));
807#endif
808
809 entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table),
810 symbol->name,
811 TRUE, FALSE);
812
813 if (entry == NULL)
814 {
815 bfd_set_error (bfd_error_no_memory);
816 return -1;
817 }
818
819 if (entry->symbol) /* FIXME: DEC C generates this */
820 {
821#if VMS_DEBUG
822 vms_debug (4, "EGSD_S_C_SYMG: duplicate \"%s\"\n", symbol->name);
823#endif
824 }
825 else
826 {
827 entry->symbol = symbol;
828 PRIV (gsd_sym_count)++;
829 abfd->symcount++;
830 }
831
832 return 0;
833}
834
835/* Set section VMS flags. */
836
837void
838bfd_vms_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED,
839 asection *sec, flagword flags)
840{
841 vms_section_data (sec)->vflags = flags;
842}
252b5132 843
7920ce38 844/* Write section and symbol directory of bfd abfd. */
252b5132
RH
845
846int
7920ce38 847_bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED)
252b5132
RH
848{
849 asection *section;
850 asymbol *symbol;
5f771d47 851 unsigned int symnum;
252b5132
RH
852 int last_index = -1;
853 char dummy_name[10];
854 char *sname;
855 flagword new_flags, old_flags;
0c376465 856 int abs_section_index = 0;
252b5132
RH
857
858#if VMS_DEBUG
859 vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype);
860#endif
861
7920ce38 862 /* Output sections. */
252b5132
RH
863 section = abfd->sections;
864#if VMS_DEBUG
865 vms_debug (3, "%d sections found\n", abfd->section_count);
866#endif
867
7920ce38 868 /* Egsd is quadword aligned. */
252b5132
RH
869 _bfd_vms_output_alignment (abfd, 8);
870
871 _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
872 _bfd_vms_output_long (abfd, 0);
7920ce38
NC
873 /* Prepare output for subrecords. */
874 _bfd_vms_output_push (abfd);
252b5132
RH
875
876 while (section != 0)
877 {
878#if VMS_DEBUG
7920ce38 879 vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->size);
252b5132
RH
880#endif
881
0c376465
TG
882 /* Don't write out the VMS debug info section since it is in the
883 ETBT and EDBG sections in etir. */
884 if (!strcmp (section->name, ".vmsdebug"))
885 goto done;
886
7920ce38 887 /* 13 bytes egsd, max 31 chars name -> should be 44 bytes. */
252b5132
RH
888 if (_bfd_vms_output_check (abfd, 64) < 0)
889 {
890 _bfd_vms_output_pop (abfd);
891 _bfd_vms_output_end (abfd);
892 _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
893 _bfd_vms_output_long (abfd, 0);
7920ce38
NC
894 /* Prepare output for subrecords. */
895 _bfd_vms_output_push (abfd);
252b5132
RH
896 }
897
7920ce38 898 /* Create dummy sections to keep consecutive indices. */
252b5132
RH
899 while (section->index - last_index > 1)
900 {
901#if VMS_DEBUG
902 vms_debug (3, "index %d, last %d\n", section->index, last_index);
903#endif
904 _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
905 _bfd_vms_output_short (abfd, 0);
906 _bfd_vms_output_short (abfd, 0);
907 _bfd_vms_output_long (abfd, 0);
908 sprintf (dummy_name, ".DUMMY%02d", last_index);
909 _bfd_vms_output_counted (abfd, dummy_name);
910 _bfd_vms_output_flush (abfd);
911 last_index++;
912 }
913
7dee875e 914 /* Don't know if this is necessary for the linker but for now it keeps
252b5132 915 vms_slurp_gsd happy */
252b5132
RH
916 sname = (char *)section->name;
917 if (*sname == '.')
918 {
919 sname++;
920 if ((*sname == 't') && (strcmp (sname, "text") == 0))
7920ce38 921 sname = PRIV (is_vax)?VAX_CODE_NAME:EVAX_CODE_NAME;
252b5132 922 else if ((*sname == 'd') && (strcmp (sname, "data") == 0))
7920ce38 923 sname = PRIV (is_vax)?VAX_DATA_NAME:EVAX_DATA_NAME;
252b5132
RH
924 else if ((*sname == 'b') && (strcmp (sname, "bss") == 0))
925 sname = EVAX_BSS_NAME;
926 else if ((*sname == 'l') && (strcmp (sname, "link") == 0))
927 sname = EVAX_LINK_NAME;
928 else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0))
929 sname = EVAX_READONLY_NAME;
930 else if ((*sname == 'l') && (strcmp (sname, "literal") == 0))
931 sname = EVAX_LITERAL_NAME;
0c376465
TG
932 else if ((*sname == 'l') && (strcmp (sname, "literals") == 0))
933 {
934 sname = EVAX_LITERALS_NAME;
935 abs_section_index = section->index;
936 }
252b5132
RH
937 else if ((*sname == 'c') && (strcmp (sname, "comm") == 0))
938 sname = EVAX_COMMON_NAME;
939 else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0))
940 sname = EVAX_LOCAL_NAME;
941 }
942 else
943 sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ);
944
945 _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1);
946 _bfd_vms_output_short (abfd, section->alignment_power & 0xff);
0c376465 947
252b5132 948 if (bfd_is_com_section (section))
0c376465
TG
949 new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD
950 | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM);
252b5132 951 else
7920ce38
NC
952 new_flags = vms_esecflag_by_name (evax_section_flags, sname,
953 section->size > 0);
954
0c376465
TG
955 /* Modify them as directed. */
956 if (section->flags & SEC_READONLY)
957 new_flags &= ~EGPS_S_V_WRT;
958
959 new_flags |= vms_section_data (section)->vflags & 0xffff;
960 new_flags &=
961 ~((vms_section_data (section)->vflags >> EGPS_S_V_NO_SHIFT) & 0xffff);
962
963#if VMS_DEBUG
964 vms_debug (3, "sec flags %x\n", section->flags);
965 vms_debug (3, "new_flags %x, _raw_size %d\n", new_flags, section->size);
966#endif
967
252b5132 968 _bfd_vms_output_short (abfd, new_flags);
eea6121a 969 _bfd_vms_output_long (abfd, (unsigned long) section->size);
252b5132
RH
970 _bfd_vms_output_counted (abfd, sname);
971 _bfd_vms_output_flush (abfd);
972
973 last_index = section->index;
0c376465 974done:
252b5132
RH
975 section = section->next;
976 }
977
7920ce38 978 /* Output symbols. */
252b5132
RH
979#if VMS_DEBUG
980 vms_debug (3, "%d symbols found\n", abfd->symcount);
981#endif
982
7920ce38 983 bfd_set_start_address (abfd, (bfd_vma) -1);
252b5132
RH
984
985 for (symnum = 0; symnum < abfd->symcount; symnum++)
986 {
dc810e39 987 char *hash;
252b5132
RH
988
989 symbol = abfd->outsymbols[symnum];
990 if (*(symbol->name) == '_')
991 {
992 if (strcmp (symbol->name, "__main") == 0)
993 bfd_set_start_address (abfd, (bfd_vma)symbol->value);
994 }
995 old_flags = symbol->flags;
996
997 if (old_flags & BSF_FILE)
998 continue;
999
0c376465
TG
1000 if ((old_flags & BSF_GLOBAL) == 0 /* Not xdef... */
1001 && !bfd_is_und_section (symbol->section) /* and not xref... */
1002 && !((old_flags & BSF_SECTION_SYM) != 0 /* and not LIB$INITIALIZE. */
1003 && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0))
1004 continue;
252b5132 1005
7920ce38 1006 /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. */
252b5132
RH
1007 if (_bfd_vms_output_check (abfd, 80) < 0)
1008 {
1009 _bfd_vms_output_pop (abfd);
1010 _bfd_vms_output_end (abfd);
1011 _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1);
1012 _bfd_vms_output_long (abfd, 0);
7920ce38
NC
1013 /* Prepare output for subrecords. */
1014 _bfd_vms_output_push (abfd);
252b5132
RH
1015 }
1016
1017 _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1);
1018
7920ce38
NC
1019 /* Data type, alignment. */
1020 _bfd_vms_output_short (abfd, 0);
252b5132
RH
1021
1022 new_flags = 0;
1023
1024 if (old_flags & BSF_WEAK)
1025 new_flags |= EGSY_S_V_WEAK;
0c376465 1026 if (bfd_is_com_section (symbol->section)) /* .comm */
7920ce38 1027 new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM);
252b5132
RH
1028
1029 if (old_flags & BSF_FUNCTION)
1030 {
1031 new_flags |= EGSY_S_V_NORM;
1032 new_flags |= EGSY_S_V_REL;
1033 }
0c376465 1034 if (old_flags & BSF_GLOBAL)
252b5132
RH
1035 {
1036 new_flags |= EGSY_S_V_DEF;
1037 if (!bfd_is_abs_section (symbol->section))
1038 new_flags |= EGSY_S_V_REL;
1039 }
1040 _bfd_vms_output_short (abfd, new_flags);
1041
0c376465 1042 if (old_flags & BSF_GLOBAL)
252b5132 1043 {
7920ce38 1044 /* Symbol definition. */
dc810e39
AM
1045 uquad code_address = 0;
1046 unsigned long ca_psindx = 0;
1047 unsigned long psindx;
1048
89117aab 1049 if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
252b5132 1050 {
0c376465
TG
1051 asymbol *sym;
1052
1053 if (bfd_get_flavour (abfd) == bfd_target_evax_flavour)
1054 sym = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
1055 else
1056 sym = (asymbol *)symbol->udata.p;
1057 code_address = sym->value;
1058 ca_psindx = sym->section->index;
252b5132 1059 }
0c376465
TG
1060 if (bfd_is_abs_section (symbol->section))
1061 psindx = abs_section_index;
1062 else
1063 psindx = symbol->section->index;
dc810e39
AM
1064
1065 _bfd_vms_output_quad (abfd, symbol->value);
1066 _bfd_vms_output_quad (abfd, code_address);
1067 _bfd_vms_output_long (abfd, ca_psindx);
1068 _bfd_vms_output_long (abfd, psindx);
252b5132 1069 }
dc810e39
AM
1070 hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ);
1071 _bfd_vms_output_counted (abfd, hash);
252b5132
RH
1072
1073 _bfd_vms_output_flush (abfd);
1074
1075 }
1076
1077 _bfd_vms_output_alignment (abfd, 8);
1078 _bfd_vms_output_pop (abfd);
558e161f 1079 _bfd_vms_output_end (abfd);
252b5132
RH
1080
1081 return 0;
1082}
This page took 0.777163 seconds and 4 git commands to generate.