Commit | Line | Data |
---|---|---|
8696b2db | 1 | /* evax-egsd.c -- BFD back-end for ALPHA EVAX (openVMS/Alpha) files. |
980381af | 2 | Copyright 1996, 1997, 1998 Free Software Foundation Inc. |
c3d8e071 ILT |
3 | |
4 | go and read the openVMS linker manual (esp. appendix B) | |
5 | if you don't know what's going on here :-) | |
6 | ||
8696b2db | 7 | Written by Klaus K"ampf (kkaempf@progis.de) |
c3d8e071 ILT |
8 | of proGIS Softwareentwicklung, Aachen, Germany |
9 | ||
10 | This program is free software; you can redistribute it and/or modify | |
11 | it under the terms of the GNU General Public License as published by | |
12 | the Free Software Foundation; either version 2 of the License, or | |
13 | (at your option) any later version. | |
14 | ||
15 | This program is distributed in the hope that it will be useful, | |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | GNU General Public License for more details. | |
19 | ||
20 | You should have received a copy of the GNU General Public License | |
21 | along with this program; if not, write to the Free Software | |
22 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
23 | ||
24 | ||
c3d8e071 ILT |
25 | #include <ctype.h> |
26 | ||
27 | #include "bfd.h" | |
28 | #include "sysdep.h" | |
29 | #include "bfdlink.h" | |
30 | #include "libbfd.h" | |
31 | ||
32 | #include "evax.h" | |
33 | ||
34 | /*-----------------------------------------------------------------------------*/ | |
35 | ||
36 | /* sections every evax object file has */ | |
37 | ||
38 | #define EVAX_ABS_NAME "$ABS$" | |
39 | #define EVAX_CODE_NAME "$CODE$" | |
40 | #define EVAX_LINK_NAME "$LINK$" | |
41 | #define EVAX_DATA_NAME "$DATA$" | |
42 | #define EVAX_BSS_NAME "$BSS$" | |
d5241511 | 43 | #define EVAX_READONLYADDR_NAME "$READONLY_ADDR$" |
c3d8e071 ILT |
44 | #define EVAX_READONLY_NAME "$READONLY$" |
45 | #define EVAX_LITERAL_NAME "$LITERAL$" | |
8696b2db ILT |
46 | #define EVAX_COMMON_NAME "$COMMON$" |
47 | #define EVAX_LOCAL_NAME "$LOCAL$" | |
c3d8e071 ILT |
48 | |
49 | struct sec_flags_struct { | |
50 | char *name; /* name of section */ | |
51 | int eflags_always; | |
52 | flagword flags_always; /* flags we set always */ | |
53 | int eflags_hassize; | |
54 | flagword flags_hassize; /* flags we set if the section has a size > 0 */ | |
55 | }; | |
56 | ||
107dfe12 | 57 | /* These flags are deccrtl/vaxcrtl (openVMS 6.2) compatible */ |
c3d8e071 ILT |
58 | |
59 | static struct sec_flags_struct evax_section_flags[] = { | |
60 | { EVAX_ABS_NAME, | |
61 | (EGPS_S_V_SHR), | |
62 | (SEC_DATA), | |
63 | (EGPS_S_V_SHR), | |
64 | (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, | |
65 | { EVAX_CODE_NAME, | |
66 | (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_EXE), | |
67 | (SEC_CODE), | |
68 | (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_EXE), | |
69 | (SEC_IN_MEMORY|SEC_CODE|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, | |
d5241511 ILT |
70 | { EVAX_LITERAL_NAME, |
71 | (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD|EGPS_S_V_NOMOD), | |
72 | (SEC_DATA|SEC_READONLY), | |
73 | (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD), | |
74 | (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, | |
c3d8e071 ILT |
75 | { EVAX_LINK_NAME, |
76 | (EGPS_S_V_REL|EGPS_S_V_RD), | |
77 | (SEC_DATA|SEC_READONLY), | |
78 | (EGPS_S_V_REL|EGPS_S_V_RD), | |
79 | (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, | |
80 | { EVAX_DATA_NAME, | |
d5241511 | 81 | (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), |
c3d8e071 ILT |
82 | (SEC_DATA), |
83 | (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), | |
84 | (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, | |
85 | { EVAX_BSS_NAME, | |
86 | (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), | |
87 | (SEC_NO_FLAGS), | |
88 | (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), | |
89 | (SEC_IN_MEMORY|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, | |
d5241511 ILT |
90 | { EVAX_READONLYADDR_NAME, |
91 | (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_RD), | |
c3d8e071 | 92 | (SEC_DATA|SEC_READONLY), |
d5241511 | 93 | (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_RD), |
c3d8e071 | 94 | (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, |
d5241511 ILT |
95 | { EVAX_READONLY_NAME, |
96 | (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD|EGPS_S_V_NOMOD), | |
c3d8e071 ILT |
97 | (SEC_DATA|SEC_READONLY), |
98 | (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD), | |
99 | (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, | |
d5241511 ILT |
100 | { EVAX_LOCAL_NAME, |
101 | (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), | |
102 | (SEC_DATA), | |
103 | (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), | |
104 | (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, | |
c3d8e071 ILT |
105 | { NULL, |
106 | (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), | |
107 | (SEC_DATA), | |
108 | (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), | |
109 | (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) } | |
110 | }; | |
111 | ||
112 | /* Retrieve bfd section flags by name and size */ | |
113 | ||
114 | static flagword | |
115 | evax_secflag_by_name(name, size) | |
116 | char *name; | |
117 | int size; | |
118 | { | |
119 | int i = 0; | |
120 | ||
121 | while (evax_section_flags[i].name != NULL) | |
122 | { | |
123 | if (strcmp (name, evax_section_flags[i].name) == 0) | |
124 | { | |
125 | if (size > 0) | |
126 | return evax_section_flags[i].flags_hassize; | |
127 | else | |
128 | return evax_section_flags[i].flags_always; | |
129 | } | |
130 | i++; | |
131 | } | |
132 | if (size > 0) | |
133 | return evax_section_flags[i].flags_hassize; | |
134 | return evax_section_flags[i].flags_always; | |
135 | } | |
136 | ||
137 | ||
138 | /* Retrieve evax section flags by name and size */ | |
139 | ||
140 | static flagword | |
141 | evax_esecflag_by_name(name, size) | |
142 | char *name; | |
143 | int size; | |
144 | { | |
145 | int i = 0; | |
146 | ||
147 | while (evax_section_flags[i].name != NULL) | |
148 | { | |
149 | if (strcmp (name, evax_section_flags[i].name) == 0) | |
150 | { | |
151 | if (size > 0) | |
152 | return evax_section_flags[i].eflags_hassize; | |
153 | else | |
154 | return evax_section_flags[i].eflags_always; | |
155 | } | |
156 | i++; | |
157 | } | |
158 | if (size > 0) | |
159 | return evax_section_flags[i].eflags_hassize; | |
160 | return evax_section_flags[i].eflags_always; | |
161 | } | |
162 | ||
163 | /*-----------------------------------------------------------------------------*/ | |
164 | #if EVAX_DEBUG | |
165 | /* debug */ | |
166 | ||
167 | struct flagdescstruct { char *name; flagword value; }; | |
168 | ||
169 | /* Convert flag to printable string */ | |
170 | ||
171 | static char * | |
172 | flag2str(flagdesc, flags) | |
173 | struct flagdescstruct *flagdesc; | |
174 | flagword flags; | |
175 | { | |
176 | ||
177 | static char res[64]; | |
178 | int next = 0; | |
179 | ||
180 | res[0] = 0; | |
181 | while (flagdesc->name != NULL) | |
182 | { | |
183 | if ((flags & flagdesc->value) != 0) | |
184 | { | |
185 | if (next) | |
186 | strcat(res, ","); | |
187 | else | |
188 | next = 1; | |
189 | strcat (res, flagdesc->name); | |
190 | } | |
191 | flagdesc++; | |
192 | } | |
193 | return res; | |
194 | } | |
195 | #endif | |
196 | ||
197 | /*-----------------------------------------------------------------------------*/ | |
198 | /* input routines */ | |
199 | ||
200 | /* Process EGSD record | |
201 | return 0 on success, -1 on error */ | |
202 | ||
203 | int | |
204 | _bfd_evax_slurp_egsd (abfd) | |
205 | bfd *abfd; | |
206 | { | |
207 | #if EVAX_DEBUG | |
208 | static struct flagdescstruct gpsflagdesc[] = | |
209 | { | |
210 | { "PIC", 0x0001 }, | |
211 | { "LIB", 0x0002 }, | |
212 | { "OVR", 0x0004 }, | |
213 | { "REL", 0x0008 }, | |
214 | { "GBL", 0x0010 }, | |
215 | { "SHR", 0x0020 }, | |
216 | { "EXE", 0x0040 }, | |
217 | { "RD", 0x0080 }, | |
218 | { "WRT", 0x0100 }, | |
219 | { "VEC", 0x0200 }, | |
220 | { "NOMOD", 0x0400 }, | |
221 | { "COM", 0x0800 }, | |
222 | { NULL, 0 } | |
223 | }; | |
224 | ||
225 | static struct flagdescstruct gsyflagdesc[] = | |
226 | { | |
227 | { "WEAK", 0x0001 }, | |
228 | { "DEF", 0x0002 }, | |
229 | { "UNI", 0x0004 }, | |
230 | { "REL", 0x0008 }, | |
231 | { "COMM", 0x0010 }, | |
232 | { "VECEP", 0x0020 }, | |
233 | { "NORM", 0x0040 }, | |
234 | { NULL, 0 } | |
235 | }; | |
236 | #endif | |
237 | ||
238 | int gsd_type, gsd_size; | |
239 | asection *section; | |
240 | unsigned char *evax_rec; | |
241 | flagword new_flags, old_flags; | |
242 | char *name; | |
243 | asymbol *symbol; | |
244 | evax_symbol_entry *entry; | |
245 | unsigned long base_addr; | |
246 | unsigned long align_addr; | |
247 | ||
248 | #if EVAX_DEBUG | |
249 | evax_debug (2, "EGSD\n"); | |
250 | #endif | |
251 | ||
252 | PRIV(evax_rec) += 8; /* skip type, size, l_temp */ | |
253 | PRIV(rec_size) -= 8; | |
254 | ||
255 | /* calculate base address for each section */ | |
256 | base_addr = 0L; | |
257 | ||
258 | abfd->symcount = 0; | |
259 | ||
260 | while (PRIV(rec_size) > 0) | |
261 | { | |
262 | evax_rec = PRIV(evax_rec); | |
263 | _bfd_evax_get_header_values (abfd, evax_rec, &gsd_type, &gsd_size); | |
264 | switch (gsd_type) | |
265 | { | |
266 | case EGSD_S_C_PSC: | |
267 | { | |
268 | /* program section definition */ | |
269 | ||
270 | name = _bfd_evax_save_counted_string ((char *)evax_rec+12); | |
271 | section = bfd_make_section (abfd, name); | |
272 | if (!section) | |
273 | return -1; | |
274 | old_flags = bfd_getl16 (evax_rec + 6); | |
275 | section->_raw_size = bfd_getl32 (evax_rec + 8); /* allocation */ | |
8612a388 | 276 | new_flags = evax_secflag_by_name (name, (int) section->_raw_size); |
c3d8e071 ILT |
277 | if (old_flags & EGPS_S_V_REL) |
278 | new_flags |= SEC_RELOC; | |
279 | if (!bfd_set_section_flags (abfd, section, new_flags)) | |
280 | return -1; | |
281 | section->alignment_power = evax_rec[4]; | |
282 | align_addr = (1 << section->alignment_power); | |
283 | if ((base_addr % align_addr) != 0) | |
284 | base_addr += (align_addr - (base_addr % align_addr)); | |
285 | section->vma = (bfd_vma)base_addr; | |
8612a388 ILT |
286 | base_addr += section->_raw_size; |
287 | section->contents = ((unsigned char *) | |
288 | bfd_malloc (section->_raw_size)); | |
c3d8e071 | 289 | if (section->contents == NULL) |
8612a388 ILT |
290 | return -1; |
291 | memset (section->contents, 0, (size_t) section->_raw_size); | |
292 | section->_cooked_size = section->_raw_size; | |
c3d8e071 ILT |
293 | #if EVAX_DEBUG |
294 | evax_debug(3, "egsd psc %d (%s, flags %04x=%s) ", | |
295 | section->index, name, old_flags, flag2str(gpsflagdesc, old_flags)); | |
296 | evax_debug(3, "%d bytes at 0x%08lx (mem %p)\n", | |
297 | section->_raw_size, section->vma, section->contents); | |
298 | #endif | |
299 | } | |
300 | break; | |
301 | ||
302 | case EGSD_S_C_SYM: | |
303 | { | |
304 | /* symbol specification (definition or reference) */ | |
305 | ||
306 | symbol = _bfd_evax_make_empty_symbol (abfd); | |
307 | if (symbol == 0) | |
308 | return -1; | |
309 | ||
310 | old_flags = bfd_getl16 (evax_rec + 6); | |
311 | new_flags = BSF_NO_FLAGS; | |
312 | ||
313 | if (old_flags & EGSY_S_V_WEAK) | |
314 | new_flags |= BSF_WEAK; | |
315 | ||
316 | if (evax_rec[6] & EGSY_S_V_DEF) /* symbol definition */ | |
317 | { | |
318 | symbol->name = | |
319 | _bfd_evax_save_counted_string ((char *)evax_rec+32); | |
320 | if (old_flags & EGSY_S_V_NORM) | |
321 | { /* proc def */ | |
322 | new_flags |= BSF_FUNCTION; | |
323 | } | |
324 | symbol->value = bfd_getl64 (evax_rec+8); | |
325 | symbol->section = (asection *)((unsigned long) bfd_getl32 (evax_rec+28)); | |
326 | #if EVAX_DEBUG | |
327 | evax_debug(3, "egsd sym def #%d (%s, %d, %04x=%s)\n", abfd->symcount, | |
328 | symbol->name, (int)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags)); | |
329 | #endif | |
330 | } | |
331 | else /* symbol reference */ | |
332 | { | |
c3d8e071 ILT |
333 | symbol->name = |
334 | _bfd_evax_save_counted_string ((char *)evax_rec+8); | |
bf53bd9f ILT |
335 | #if EVAX_DEBUG |
336 | evax_debug(3, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount, | |
337 | symbol->name, old_flags, flag2str(gsyflagdesc, old_flags)); | |
338 | #endif | |
c3d8e071 ILT |
339 | symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); |
340 | } | |
341 | ||
342 | symbol->flags = new_flags; | |
343 | ||
344 | /* save symbol in evax_symbol_table */ | |
345 | ||
346 | entry = (evax_symbol_entry *) bfd_hash_lookup (PRIV(evax_symbol_table), symbol->name, true, false); | |
347 | if (entry == (evax_symbol_entry *)NULL) | |
348 | { | |
349 | bfd_set_error (bfd_error_no_memory); | |
350 | return -1; | |
351 | } | |
352 | if (entry->symbol != (asymbol *)NULL) | |
353 | { /* FIXME ?, DEC C generates this */ | |
354 | #if EVAX_DEBUG | |
355 | evax_debug(3, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name); | |
356 | #endif | |
357 | } | |
358 | else | |
359 | { | |
360 | entry->symbol = symbol; | |
361 | PRIV(egsd_sym_count)++; | |
362 | abfd->symcount++; | |
363 | } | |
364 | } | |
365 | break; | |
366 | ||
367 | case EGSD_S_C_IDC: | |
368 | break; | |
369 | ||
370 | default: | |
53d3ce37 | 371 | (*_bfd_error_handler) (_("unknown egsd subtype %d"), gsd_type); |
c3d8e071 ILT |
372 | bfd_set_error (bfd_error_bad_value); |
373 | return -1; | |
374 | ||
375 | } /* switch */ | |
376 | ||
377 | PRIV(rec_size) -= gsd_size; | |
378 | PRIV(evax_rec) += gsd_size; | |
379 | ||
380 | } /* while (recsize > 0) */ | |
381 | ||
382 | if (abfd->symcount > 0) | |
383 | abfd->flags |= HAS_SYMS; | |
384 | ||
385 | return 0; | |
386 | } | |
387 | ||
388 | /*-----------------------------------------------------------------------------*/ | |
389 | /* output routines */ | |
390 | ||
391 | /* Write section and symbol directory of bfd abfd */ | |
392 | ||
393 | int | |
394 | _bfd_evax_write_egsd (abfd) | |
395 | bfd *abfd; | |
396 | { | |
397 | asection *section; | |
398 | asymbol *symbol; | |
399 | int symnum; | |
400 | int last_index = -1; | |
401 | char dummy_name[10]; | |
402 | char *sname; | |
403 | flagword new_flags, old_flags; | |
c3d8e071 ILT |
404 | char *nptr, *uptr; |
405 | ||
406 | #if EVAX_DEBUG | |
407 | evax_debug (2, "evax_write_egsd(%p)\n", abfd); | |
408 | #endif | |
409 | ||
410 | /* output sections */ | |
411 | ||
412 | section = abfd->sections; | |
413 | #if EVAX_DEBUG | |
414 | evax_debug (3, "%d sections found\n", abfd->section_count); | |
415 | #endif | |
416 | ||
417 | /* egsd is quadword aligned */ | |
418 | ||
419 | _bfd_evax_output_alignment (abfd, 8); | |
420 | ||
421 | _bfd_evax_output_begin (abfd, EOBJ_S_C_EGSD, -1); | |
422 | _bfd_evax_output_long (abfd, 0); | |
423 | _bfd_evax_output_push (abfd); /* prepare output for subrecords */ | |
424 | ||
425 | while (section != 0) | |
426 | { | |
427 | #if EVAX_DEBUG | |
428 | evax_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->_raw_size); | |
429 | #endif | |
430 | ||
431 | /* 13 bytes egsd, max 31 chars name -> should be 44 bytes */ | |
432 | if (_bfd_evax_output_check (abfd, 64) < 0) | |
433 | { | |
434 | _bfd_evax_output_pop (abfd); | |
435 | _bfd_evax_output_end (abfd); | |
436 | _bfd_evax_output_begin (abfd, EOBJ_S_C_EGSD, -1); | |
437 | _bfd_evax_output_long (abfd, 0); | |
438 | _bfd_evax_output_push (abfd); /* prepare output for subrecords */ | |
439 | } | |
440 | ||
441 | /* Create dummy sections to keep consecutive indices */ | |
442 | ||
443 | while (section->index - last_index > 1) | |
444 | { | |
445 | #if EVAX_DEBUG | |
446 | evax_debug (3, "index %d, last %d\n", section->index, last_index); | |
447 | #endif | |
448 | _bfd_evax_output_begin (abfd, EGSD_S_C_PSC, -1); | |
449 | _bfd_evax_output_short (abfd, 0); | |
450 | _bfd_evax_output_short (abfd, 0); | |
451 | _bfd_evax_output_long (abfd, 0); | |
452 | sprintf (dummy_name, ".DUMMY%02d", last_index); | |
453 | _bfd_evax_output_counted (abfd, dummy_name); | |
454 | _bfd_evax_output_flush (abfd); | |
455 | last_index++; | |
456 | } | |
457 | ||
458 | /* Don't know if this is neccesary for the linker but for now it keeps | |
459 | evax_slurp_egsd happy */ | |
460 | ||
461 | sname = (char *)section->name; | |
462 | if (*sname == '.') | |
463 | { | |
464 | sname++; | |
465 | if ((*sname == 't') && (strcmp (sname, "text") == 0)) | |
466 | sname = EVAX_CODE_NAME; | |
467 | else if ((*sname == 'd') && (strcmp (sname, "data") == 0)) | |
468 | sname = EVAX_DATA_NAME; | |
469 | else if ((*sname == 'b') && (strcmp (sname, "bss") == 0)) | |
470 | sname = EVAX_BSS_NAME; | |
471 | else if ((*sname == 'l') && (strcmp (sname, "link") == 0)) | |
472 | sname = EVAX_LINK_NAME; | |
473 | else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0)) | |
474 | sname = EVAX_READONLY_NAME; | |
475 | else if ((*sname == 'l') && (strcmp (sname, "literal") == 0)) | |
476 | sname = EVAX_LITERAL_NAME; | |
8696b2db ILT |
477 | else if ((*sname == 'c') && (strcmp (sname, "comm") == 0)) |
478 | sname = EVAX_COMMON_NAME; | |
479 | else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0)) | |
480 | sname = EVAX_LOCAL_NAME; | |
c3d8e071 | 481 | } |
412222d9 ILT |
482 | else |
483 | sname = _bfd_evax_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ); | |
c3d8e071 ILT |
484 | |
485 | _bfd_evax_output_begin (abfd, EGSD_S_C_PSC, -1); | |
486 | _bfd_evax_output_short (abfd, section->alignment_power & 0xff); | |
412222d9 ILT |
487 | if (bfd_is_com_section (section)) |
488 | { | |
489 | 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); | |
490 | } | |
491 | else | |
492 | { | |
493 | new_flags = evax_esecflag_by_name (sname, section->_raw_size); | |
494 | } | |
495 | _bfd_evax_output_short (abfd, new_flags); | |
c3d8e071 ILT |
496 | _bfd_evax_output_long (abfd, section->_raw_size); |
497 | _bfd_evax_output_counted (abfd, sname); | |
498 | _bfd_evax_output_flush (abfd); | |
499 | ||
500 | last_index = section->index; | |
501 | section = section->next; | |
502 | } | |
503 | ||
504 | /* output symbols */ | |
505 | ||
506 | #if EVAX_DEBUG | |
507 | evax_debug (3, "%d symbols found\n", abfd->symcount); | |
508 | #endif | |
509 | ||
510 | bfd_set_start_address (abfd, (bfd_vma)-1); | |
511 | ||
512 | for (symnum = 0; symnum < abfd->symcount; symnum++) | |
513 | { | |
514 | ||
515 | symbol = abfd->outsymbols[symnum]; | |
516 | if (*(symbol->name) == '_') | |
517 | { | |
518 | if (strcmp (symbol->name, "__main") == 0) | |
519 | bfd_set_start_address (abfd, (bfd_vma)symbol->value); | |
520 | } | |
521 | old_flags = symbol->flags; | |
522 | ||
bf53bd9f ILT |
523 | if (old_flags & BSF_FILE) |
524 | continue; | |
525 | ||
412222d9 | 526 | if (((old_flags & (BSF_GLOBAL|BSF_WEAK)) == 0) /* not xdef */ |
c3d8e071 ILT |
527 | && (!bfd_is_und_section (symbol->section))) /* and not xref */ |
528 | continue; /* dont output */ | |
529 | ||
530 | /* 13 bytes egsd, max 64 chars name -> should be 77 bytes */ | |
531 | ||
532 | if (_bfd_evax_output_check (abfd, 80) < 0) | |
533 | { | |
534 | _bfd_evax_output_pop (abfd); | |
535 | _bfd_evax_output_end (abfd); | |
536 | _bfd_evax_output_begin (abfd, EOBJ_S_C_EGSD, -1); | |
537 | _bfd_evax_output_long (abfd, 0); | |
538 | _bfd_evax_output_push (abfd); /* prepare output for subrecords */ | |
539 | } | |
540 | ||
541 | _bfd_evax_output_begin (abfd, EGSD_S_C_SYM, -1); | |
542 | ||
543 | _bfd_evax_output_short (abfd, 0); /* data type, alignment */ | |
544 | ||
545 | new_flags = 0; | |
412222d9 | 546 | |
c3d8e071 ILT |
547 | if (old_flags & BSF_WEAK) |
548 | new_flags |= EGSY_S_V_WEAK; | |
412222d9 ILT |
549 | if (bfd_is_com_section (symbol->section)) /* .comm */ |
550 | new_flags |= (EGSY_S_V_WEAK|EGSY_S_V_COMM); | |
551 | ||
c3d8e071 ILT |
552 | if (old_flags & BSF_FUNCTION) |
553 | { | |
554 | new_flags |= EGSY_S_V_NORM; | |
555 | new_flags |= EGSY_S_V_REL; | |
556 | } | |
412222d9 | 557 | if (old_flags & (BSF_GLOBAL|BSF_WEAK)) |
c3d8e071 ILT |
558 | { |
559 | new_flags |= EGSY_S_V_DEF; | |
560 | if (!bfd_is_abs_section (symbol->section)) | |
561 | new_flags |= EGSY_S_V_REL; | |
562 | } | |
563 | _bfd_evax_output_short (abfd, new_flags); | |
564 | ||
412222d9 | 565 | if (old_flags & (BSF_GLOBAL|BSF_WEAK)) /* symbol definition */ |
c3d8e071 ILT |
566 | { |
567 | if (old_flags & BSF_FUNCTION) | |
568 | { | |
569 | _bfd_evax_output_quad (abfd, symbol->value); | |
570 | _bfd_evax_output_quad (abfd, | |
571 | ((asymbol *)(symbol->udata.p))->value); | |
572 | _bfd_evax_output_long (abfd, | |
573 | (((asymbol *)(symbol->udata.p)) | |
574 | ->section->index)); | |
575 | _bfd_evax_output_long (abfd, symbol->section->index); | |
576 | } | |
577 | else | |
578 | { | |
579 | _bfd_evax_output_quad (abfd, symbol->value); /* L_VALUE */ | |
580 | _bfd_evax_output_quad (abfd, 0); /* L_CODE_ADDRESS */ | |
581 | _bfd_evax_output_long (abfd, 0); /* L_CA_PSINDX */ | |
412222d9 | 582 | _bfd_evax_output_long (abfd, symbol->section->index);/* L_PSINDX */ |
c3d8e071 ILT |
583 | } |
584 | } | |
412222d9 | 585 | _bfd_evax_output_counted (abfd, _bfd_evax_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ)); |
c3d8e071 ILT |
586 | |
587 | _bfd_evax_output_flush (abfd); | |
588 | ||
589 | } | |
590 | ||
591 | _bfd_evax_output_alignment (abfd, 8); | |
592 | _bfd_evax_output_pop (abfd); | |
593 | _bfd_evax_output_end (abfd); | |
594 | ||
595 | return 0; | |
596 | } |