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