]>
Commit | Line | Data |
---|---|---|
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 ([email protected]) | |
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 |
56 | struct 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 |
67 | static 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 |
93 | static 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 | |
154 | static flagword | |
7920ce38 NC |
155 | vms_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 | |
182 | static flagword | |
7920ce38 NC |
183 | vms_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 | |
207 | struct flagdescstruct { char *name; flagword value; }; | |
208 | ||
0c376465 TG |
209 | static 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 | ||
226 | static 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 | ||
238 | static char *flag2str (struct flagdescstruct *, flagword); | |
239 | ||
7920ce38 | 240 | /* Convert flag to printable string. */ |
252b5132 RH |
241 | |
242 | static char * | |
7920ce38 | 243 | flag2str (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 |
267 | static 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 | |
273 | int | |
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 | ||
771 | static int | |
772 | register_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 | ||
836 | void | |
837 | bfd_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 | |
845 | int | |
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 | 973 | done: |
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 | } |