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