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