* aout-adobe.c, aoutf1.h, archive.c, bout.c, coff-rs6000.c,
[platform/upstream/binutils.git] / bfd / oasys.c
1 /* bfd backend for oasys objects.
2    Copyright (C) 1990-1991 Free Software Foundation, Inc.
3    Written by Steve Chamberlain of Cygnus Support <steve@cygnus.com>.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #define UNDERSCORE_HACK 1
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "oasys.h"
26 #include "liboasys.h"
27
28 /* XXX - FIXME.  offsetof belongs in the system-specific files in
29    ../include/sys. */
30 /* Define offsetof for those systems which lack it */
31
32 #ifndef offsetof
33 #define offsetof(type, identifier) (size_t) &(((type *) 0)->identifier) 
34 #endif
35
36 /* Read in all the section data and relocation stuff too */
37 PROTO(static boolean,oasys_slurp_section_data,(bfd *CONST abfd));
38
39 static void 
40 DEFUN(oasys_read_record,(abfd, record),
41       bfd *CONST abfd AND 
42       oasys_record_union_type *record)
43 {
44
45   bfd_read((PTR)record, 1, sizeof(record->header), abfd);
46
47   if ((size_t) record->header.length <= (size_t) sizeof (record->header))
48     return;
49   bfd_read((PTR)(((char *)record )+ sizeof(record->header)),
50            1, record->header.length - sizeof(record->header),
51            abfd);
52 }
53 static size_t
54 DEFUN(oasys_string_length,(record),
55       oasys_record_union_type *record)
56 {
57 return  record->header.length
58         - ((char *)record->symbol.name - (char *)record);
59 }
60
61 /*****************************************************************************/
62
63 /*
64
65 Slurp the symbol table by reading in all the records at the start file
66 till we get to the first section record.
67
68 We'll sort the symbolss into  two lists, defined and undefined. The
69 undefined symbols will be placed into the table according to their
70 refno. 
71
72 We do this by placing all undefined symbols at the front of the table
73 moving in, and the defined symbols at the end of the table moving back.
74
75 */
76
77 static boolean
78 DEFUN(oasys_slurp_symbol_table,(abfd),
79     bfd * CONST abfd)
80 {
81   oasys_record_union_type record;
82   oasys_data_type *data = OASYS_DATA(abfd);
83   boolean loop = true;
84   asymbol *dest_defined;
85   asymbol *dest;
86   char *string_ptr;
87
88
89   if (data->symbols != (asymbol *)NULL) {
90     return true;
91   }
92   /* Buy enough memory for all the symbols and all the names */
93   data->symbols = 
94     (asymbol *)bfd_alloc(abfd, sizeof(asymbol) * abfd->symcount);
95 #ifdef UNDERSCORE_HACK
96   /* buy 1 more char for each symbol to keep the underscore in*/
97   data->strings = bfd_alloc(abfd, data->symbol_string_length +
98                             abfd->symcount);
99 #else
100   data->strings = bfd_alloc(abfd, data->symbol_string_length);
101 #endif
102
103
104   dest_defined = data->symbols + abfd->symcount -1;
105
106   string_ptr = data->strings;
107   bfd_seek(abfd, (file_ptr)0, SEEK_SET);
108   while (loop) {
109
110     oasys_read_record(abfd, &record);
111     switch (record.header.type) {
112     case oasys_record_is_header_enum:
113       break;
114     case oasys_record_is_local_enum:
115     case oasys_record_is_symbol_enum:
116         {
117           int     flag = record.header.type == (int)oasys_record_is_local_enum ?
118             (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT);
119
120
121           size_t length = oasys_string_length(&record);
122           switch (record.symbol.relb & RELOCATION_TYPE_BITS) {
123           case RELOCATION_TYPE_ABS:
124             dest = dest_defined--;
125             dest->section = &bfd_abs_section;
126             dest->flags =  0;
127             
128             break;
129           case RELOCATION_TYPE_REL:
130             dest = dest_defined--;
131             dest->section =
132               OASYS_DATA(abfd)->sections[record.symbol.relb &
133                                          RELOCATION_SECT_BITS];
134             if (record.header.type == (int)oasys_record_is_local_enum) 
135                 {
136                   dest->flags = BSF_LOCAL;
137                   if (dest->section ==(asection *)(~0)) {
138                     /* It seems that sometimes internal symbols are tied up, but
139                        still get output, even though there is no
140                        section */
141                     dest->section = 0;
142                   }
143                 }
144             else {
145
146               dest->flags = flag;
147             }
148             break;
149           case RELOCATION_TYPE_UND:
150             dest = data->symbols + bfd_h_get_16(abfd, (bfd_byte *)&record.symbol.refno[0]);
151             dest->section = &bfd_und_section;
152             break;
153           case RELOCATION_TYPE_COM:
154             dest = dest_defined--;
155             dest->name = string_ptr;
156             dest->the_bfd = abfd;
157
158             dest->section = &bfd_com_section;
159
160             break;
161           default:
162             dest = dest_defined--;
163             BFD_ASSERT(0);
164             break;
165           }
166           dest->name = string_ptr;
167           dest->the_bfd = abfd;
168           dest->udata = (PTR)NULL;
169           dest->value = bfd_h_get_32(abfd, (bfd_byte *)&record.symbol.value[0]);
170
171 #ifdef UNDERSCORE_HACK
172           if (record.symbol.name[0] != '_') {
173             string_ptr[0] = '_';
174             string_ptr++;
175           }
176 #endif
177           memcpy(string_ptr, record.symbol.name, length);
178
179
180           string_ptr[length] =0;
181           string_ptr += length +1;
182         }
183       break;
184     default:
185       loop = false;
186     }
187   }
188   return true;
189 }
190
191 static unsigned int
192 DEFUN(oasys_get_symtab_upper_bound,(abfd),
193      bfd *CONST abfd)
194 {
195   oasys_slurp_symbol_table (abfd);
196
197   return    (abfd->symcount+1) * (sizeof (oasys_symbol_type *));
198 }
199
200 /* 
201 */
202
203 extern bfd_target oasys_vec;
204
205 unsigned int
206 DEFUN(oasys_get_symtab,(abfd, location),
207       bfd *abfd AND
208       asymbol **location)
209 {
210   asymbol *symbase ;
211   unsigned int counter ;
212   if (oasys_slurp_symbol_table(abfd) == false) {
213     return 0;
214   }
215   symbase = OASYS_DATA(abfd)->symbols;
216   for (counter = 0; counter < abfd->symcount; counter++) {
217     *(location++) = symbase++;
218   }
219   *location = 0;
220   return abfd->symcount;
221 }
222
223 /***********************************************************************
224 *  archive stuff 
225 */
226
227 static bfd_target *
228 DEFUN(oasys_archive_p,(abfd),
229       bfd *abfd)
230 {
231   oasys_archive_header_type header;
232   oasys_extarchive_header_type header_ext;
233   unsigned int i;
234   file_ptr filepos;  
235   bfd_seek(abfd, (file_ptr) 0, false);
236
237   
238   bfd_read((PTR)&header_ext, 1, sizeof(header_ext), abfd);
239
240
241   header.version = bfd_h_get_32(abfd, (bfd_byte *)header_ext.version);
242   header.mod_count = bfd_h_get_32(abfd, (bfd_byte *)header_ext.mod_count);
243   header.mod_tbl_offset = bfd_h_get_32(abfd, (bfd_byte *)header_ext.mod_tbl_offset);
244   header.sym_tbl_size = bfd_h_get_32(abfd, (bfd_byte *)header_ext.sym_tbl_size);
245   header.sym_count = bfd_h_get_32(abfd, (bfd_byte *)header_ext.sym_count);
246   header.sym_tbl_offset = bfd_h_get_32(abfd, (bfd_byte *)header_ext.sym_tbl_offset);
247   header.xref_count = bfd_h_get_32(abfd, (bfd_byte *)header_ext.xref_count);
248   header.xref_lst_offset = bfd_h_get_32(abfd, (bfd_byte *)header_ext.xref_lst_offset);
249
250   /*
251     There isn't a magic number in an Oasys archive, so the best we
252     can do to verify reasnableness is to make sure that the values in
253     the header are too weird
254     */
255
256   if (header.version>10000 ||
257       header.mod_count>10000 ||
258       header.sym_count>100000 ||
259       header.xref_count > 100000) return (bfd_target *)NULL;
260
261   /*
262     That all worked, lets buy the space for the header and read in
263     the headers.
264     */
265     {
266       oasys_ar_data_type *ar =
267         (oasys_ar_data_type*) bfd_alloc(abfd, sizeof(oasys_ar_data_type));
268
269
270       oasys_module_info_type *module = 
271         (oasys_module_info_type*)
272           bfd_alloc(abfd, sizeof(oasys_module_info_type) * header.mod_count);
273
274
275       oasys_module_table_type record;
276
277
278       abfd->tdata.oasys_ar_data = ar;
279       ar->module = module;
280       ar->module_count = header.mod_count;
281
282
283       filepos = header.mod_tbl_offset;
284       for (i = 0; i < header.mod_count; i++) {
285         bfd_seek(abfd, filepos, SEEK_SET);
286
287         /* There are two ways of specifying the archive header */
288
289         if (0) {
290           oasys_extmodule_table_type_a_type record_ext;
291           bfd_read((PTR)&record_ext, 1, sizeof(record_ext), abfd);
292         
293           record.mod_size = bfd_h_get_32(abfd, (bfd_byte *)record_ext.mod_size);
294           record.file_offset = bfd_h_get_32(abfd,
295                                          (bfd_byte *)   record_ext.file_offset);
296
297           record.dep_count = bfd_h_get_32(abfd, (bfd_byte *)record_ext.dep_count);
298           record.depee_count = bfd_h_get_32(abfd,(bfd_byte *) record_ext.depee_count);
299           record.sect_count = bfd_h_get_32(abfd, (bfd_byte *) record_ext.sect_count);
300
301
302           module[i].name = bfd_alloc(abfd,33);
303
304           memcpy(module[i].name, record_ext.mod_name, 33);
305           filepos +=
306             sizeof(record_ext) + 
307               record.dep_count * 4 +
308                 record.depee_count * 4 +
309                   record.sect_count * 8 + 187;
310         }
311         else {
312           oasys_extmodule_table_type_b_type record_ext;
313           bfd_read((PTR)&record_ext, 1, sizeof(record_ext), abfd);
314         
315           record.mod_size = bfd_h_get_32(abfd, (bfd_byte *) record_ext.mod_size);
316           record.file_offset = bfd_h_get_32(abfd,
317                                             (bfd_byte *)record_ext.file_offset);
318
319           record.dep_count = bfd_h_get_32(abfd, (bfd_byte *) record_ext.dep_count);
320           record.depee_count = bfd_h_get_32(abfd, (bfd_byte *) record_ext.depee_count);
321           record.sect_count = bfd_h_get_32(abfd, (bfd_byte *) record_ext.sect_count);
322           record.module_name_size = bfd_h_get_32(abfd, (bfd_byte *) record_ext.mod_name_length);
323
324           module[i].name = bfd_alloc(abfd,record.module_name_size + 1);
325           bfd_read((PTR)module[i].name, 1, record.module_name_size, abfd);
326           module[i].name[record.module_name_size] = 0;
327           filepos +=
328             sizeof(record_ext) + 
329               record.dep_count * 4 +
330                 record.module_name_size + 1;
331
332         }
333
334
335         module[i].size = record.mod_size;
336         module[i].pos = record.file_offset;
337         module[i].abfd = 0;
338       }
339       
340     }
341   return abfd->xvec;
342 }
343
344 static boolean
345 DEFUN(oasys_mkobject,(abfd),
346       bfd *abfd)
347 {
348
349   abfd->tdata.oasys_obj_data =    (oasys_data_type*)bfd_alloc(abfd, sizeof(oasys_data_type));
350   return true;
351 }
352
353 #define MAX_SECS 16
354 static bfd_target *
355 DEFUN(oasys_object_p,(abfd),
356       bfd *abfd)
357 {
358   oasys_data_type *oasys;
359   oasys_data_type *save = OASYS_DATA(abfd);
360   boolean loop = true;
361   boolean had_usefull = false;
362
363   abfd->tdata.oasys_obj_data = 0;
364   oasys_mkobject(abfd);
365   oasys = OASYS_DATA(abfd);
366   memset((PTR)oasys->sections, 0xff, sizeof(oasys->sections));
367     
368   /* Point to the start of the file */
369   bfd_seek(abfd, (file_ptr)0, SEEK_SET);
370   oasys->symbol_string_length = 0;
371   /* Inspect the records, but only keep the section info -
372      remember the size of the symbols
373      */
374   oasys->first_data_record = 0;
375   while (loop) {
376     oasys_record_union_type record;
377     oasys_read_record(abfd, &record);
378     if ((size_t)record.header.length < (size_t)sizeof(record.header))
379       goto fail;
380
381
382     switch ((oasys_record_enum_type)(record.header.type)) {
383     case oasys_record_is_header_enum:
384       had_usefull = true;
385       break;
386     case oasys_record_is_symbol_enum:
387     case oasys_record_is_local_enum:
388       /* Count symbols and remember their size for a future malloc   */
389       abfd->symcount++;
390       oasys->symbol_string_length += 1 + oasys_string_length(&record);
391       had_usefull = true;
392       break;
393     case oasys_record_is_section_enum:
394         {
395           asection *s;
396           char *buffer;
397           unsigned int section_number;
398           if (record.section.header.length != sizeof(record.section))
399               {
400                 goto fail;
401               }
402           buffer = bfd_alloc(abfd, 3);
403           section_number= record.section.relb & RELOCATION_SECT_BITS;
404           sprintf(buffer,"%u", section_number);
405           s = bfd_make_section(abfd,buffer);
406           oasys->sections[section_number] = s;
407           switch (record.section.relb & RELOCATION_TYPE_BITS) {
408           case RELOCATION_TYPE_ABS:
409           case RELOCATION_TYPE_REL:
410             break;
411           case RELOCATION_TYPE_UND:
412           case RELOCATION_TYPE_COM:
413             BFD_FAIL();
414           }
415
416           s->_raw_size  = bfd_h_get_32(abfd, (bfd_byte *) & record.section.value[0]) ;
417           s->vma = bfd_h_get_32(abfd, (bfd_byte *)&record.section.vma[0]);
418           s->flags= 0;
419           had_usefull = true;
420         }
421       break;
422     case oasys_record_is_data_enum:
423       oasys->first_data_record = bfd_tell(abfd) - record.header.length;
424     case oasys_record_is_debug_enum:
425     case oasys_record_is_module_enum:
426     case oasys_record_is_named_section_enum:
427     case oasys_record_is_end_enum:
428       if (had_usefull == false) goto fail;
429       loop = false;
430       break;
431     default:
432       goto fail;
433     }
434   }
435   oasys->symbols = (asymbol *)NULL;
436   /* 
437     Oasys support several architectures, but I can't see a simple way
438     to discover which one is in a particular file - we'll guess 
439     */
440   bfd_default_set_arch_mach(abfd, bfd_arch_m68k, 0);
441   if (abfd->symcount != 0) {
442     abfd->flags |= HAS_SYMS;
443   }
444
445   /* 
446     We don't know if a section has data until we've read it..
447     */
448
449   oasys_slurp_section_data(abfd);
450
451
452   return abfd->xvec;
453
454  fail:
455   (void)  bfd_release(abfd, oasys);
456   abfd->tdata.oasys_obj_data = save;
457   return (bfd_target *)NULL;
458 }
459
460
461 static void 
462 DEFUN(oasys_print_symbol,(ignore_abfd, afile, symbol, how),
463       bfd *ignore_abfd AND
464       PTR afile AND
465       asymbol *symbol AND
466       bfd_print_symbol_type how)
467 {
468   FILE *file = (FILE *)afile;
469
470   switch (how) {
471   case bfd_print_symbol_name:
472   case bfd_print_symbol_more:
473     fprintf(file,"%s", symbol->name);
474     break;
475   case bfd_print_symbol_all:
476   case bfd_print_symbol_nm:
477     {
478       CONST char *section_name = symbol->section == (asection *)NULL ?
479         (CONST char *) "*abs" : symbol->section->name;
480
481       bfd_print_symbol_vandf((PTR)file,symbol);
482
483       fprintf(file," %-5s %s",
484               section_name,
485               symbol->name);
486     }
487     break;
488   }
489 }
490 /*
491  The howto table is build using the top two bits of a reloc byte to
492  index into it. The bits are PCREL,WORD/LONG
493 */
494 static reloc_howto_type howto_table[]= 
495 {
496
497 HOWTO(  0, 0,  1,   16, false,0,   true,true,0,"abs16",true,0x0000ffff, 0x0000ffff,false),
498 HOWTO(  0, 0,  2,   32, false,0,   true,true,0,"abs32",true,0xffffffff, 0xffffffff,false),
499 HOWTO(  0, 0,  1,   16, true,0,   true,true,0,"pcrel16",true,0x0000ffff, 0x0000ffff,false),
500 HOWTO(  0, 0,  2,   32, true,0,   true,true,0,"pcrel32",true,0xffffffff, 0xffffffff,false)
501 };
502
503 /* Read in all the section data and relocation stuff too */
504 static boolean 
505 DEFUN(oasys_slurp_section_data,(abfd),
506   bfd *CONST abfd)
507 {
508   oasys_record_union_type record;
509   oasys_data_type *data = OASYS_DATA(abfd);
510   boolean loop = true;
511
512   oasys_per_section_type *per ;
513
514   asection *s;
515
516   /* See if the data has been slurped already .. */
517   for (s = abfd->sections; s != (asection *)NULL; s= s->next) {
518     per =  oasys_per_section(s);
519     if (per->initialized == true) 
520       return true;
521   }
522
523   if (data->first_data_record == 0)  return true;
524
525   bfd_seek(abfd, data->first_data_record, SEEK_SET);
526   while (loop) {
527     oasys_read_record(abfd, &record);
528     switch (record.header.type) 
529         {
530         case oasys_record_is_header_enum:
531           break;
532         case oasys_record_is_data_enum:
533             {
534
535               uint8e_type *src = record.data.data;
536               uint8e_type *end_src = ((uint8e_type *)&record) +
537                 record.header.length;
538               unsigned int relbit;
539               bfd_byte *dst_ptr ;
540               bfd_byte *dst_base_ptr ;
541               unsigned int count;
542               asection *  section =
543                 data->sections[record.data.relb & RELOCATION_SECT_BITS];
544               bfd_vma dst_offset ;
545               per =  oasys_per_section(section);
546
547
548               if (per->initialized == false) 
549                   {
550                     per->data = (bfd_byte *) bfd_zalloc(abfd, section->_raw_size);
551                     per->reloc_tail_ptr = (oasys_reloc_type **)&(section->relocation);
552                     per->had_vma = false;
553                     per->initialized = true;
554                     section->reloc_count = 0;
555                     section->flags = SEC_ALLOC;
556                   }
557
558               dst_offset = bfd_h_get_32(abfd, record.data.addr) ;
559               if (per->had_vma == false) {
560                 /* Take the first vma we see as the base */
561
562                 section->vma = dst_offset;
563                 per->had_vma = true;
564               }
565
566
567               dst_offset -=   section->vma;
568
569
570               dst_base_ptr = oasys_per_section(section)->data;
571               dst_ptr = oasys_per_section(section)->data +
572                 dst_offset;
573
574               if (src < end_src) {
575                 section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
576               }
577               while (src < end_src) {
578                 uint8e_type mod_byte = *src++;
579                 uint32_type gap = end_src - src;
580                 
581                 count = 8;
582                 if (mod_byte == 0 && gap >= 8) {
583                   dst_ptr[0] = src[0];
584                   dst_ptr[1] = src[1];
585                   dst_ptr[2] = src[2];
586                   dst_ptr[3] = src[3];
587                   dst_ptr[4] = src[4];
588                   dst_ptr[5] = src[5];
589                   dst_ptr[6] = src[6];
590                   dst_ptr[7] = src[7];
591                   dst_ptr+= 8;
592                   src += 8;
593                 }
594                 else {
595                   for (relbit = 1; count-- != 0 && src < end_src; relbit <<=1) 
596                       {
597                         if (relbit & mod_byte) 
598                             {
599                               uint8e_type reloc = *src;
600                               /* This item needs to be relocated */
601                               switch (reloc & RELOCATION_TYPE_BITS) {
602                               case RELOCATION_TYPE_ABS:
603
604                                 break;
605
606                               case RELOCATION_TYPE_REL: 
607                                   {
608                                     /* Relocate the item relative to the section */
609                                     oasys_reloc_type *r =
610                                       (oasys_reloc_type *)
611                                         bfd_alloc(abfd,
612                                                   sizeof(oasys_reloc_type));
613                                     *(per->reloc_tail_ptr) = r;
614                                     per->reloc_tail_ptr = &r->next;
615                                     r->next= (oasys_reloc_type *)NULL;
616                                     /* Reference to undefined symbol */
617                                     src++;
618                                     /* There is no symbol */
619                                     r->symbol = 0;
620                                     /* Work out the howto */
621                                     abort();
622 #if 0
623                                     r->relent.section =
624                                       data->sections[reloc &
625                                                      RELOCATION_SECT_BITS];
626
627                                     r->relent.addend = -
628                                      r->relent.section->vma;
629 #endif
630                                     r->relent.address = dst_ptr - dst_base_ptr;
631                                     r->relent.howto = &howto_table[reloc>>6];
632                                     r->relent.sym_ptr_ptr = (asymbol **)NULL;
633                                     section->reloc_count++;
634
635                                     /* Fake up the data to look like it's got the -ve pc in it, this makes
636                                        it much easier to convert into other formats. This is done by
637                                        hitting the addend.
638                                        */
639                                     if (r->relent.howto->pc_relative == true) {
640                                       r->relent.addend -= dst_ptr - dst_base_ptr;
641                                     }
642
643
644                                   }
645                                 break;
646
647
648                               case RELOCATION_TYPE_UND:
649                                   { 
650                                     oasys_reloc_type *r =
651                                       (oasys_reloc_type *)
652                                         bfd_alloc(abfd,
653                                                   sizeof(oasys_reloc_type));
654                                     *(per->reloc_tail_ptr) = r;
655                                     per->reloc_tail_ptr = &r->next;
656                                     r->next= (oasys_reloc_type *)NULL;
657                                     /* Reference to undefined symbol */
658                                     src++;
659                                     /* Get symbol number */
660                                     r->symbol = (src[0]<<8) | src[1];
661                                     /* Work out the howto */
662                                     abort();
663                                     
664 #if 0
665                                     r->relent.section = (asection
666                                                          *)NULL;
667 #endif
668                                     r->relent.addend = 0;
669                                     r->relent.address = dst_ptr - dst_base_ptr;
670                                     r->relent.howto = &howto_table[reloc>>6];
671                                     r->relent.sym_ptr_ptr = (asymbol **)NULL;
672                                     section->reloc_count++;
673
674                                     src+=2;
675                                     /* Fake up the data to look like it's got the -ve pc in it, this makes
676                                        it much easier to convert into other formats. This is done by
677                                        hitting the addend.
678                                        */
679                                     if (r->relent.howto->pc_relative == true) {
680                                       r->relent.addend -= dst_ptr - dst_base_ptr;
681                                     }
682
683                                 
684
685                                   }
686                                 break;
687                               case RELOCATION_TYPE_COM:
688                                 BFD_FAIL();
689                               }
690                             }
691                         *dst_ptr++ = *src++;
692                       }
693                 }
694               }   
695             }
696           break;
697         case oasys_record_is_local_enum:
698         case oasys_record_is_symbol_enum:
699         case oasys_record_is_section_enum:
700           break;
701         default:
702           loop = false;
703         }
704   }
705
706   return true;
707
708 }
709
710
711
712 bfd_error_vector_type bfd_error_vector;
713
714 static boolean
715 DEFUN(oasys_new_section_hook,(abfd, newsect),
716       bfd *abfd AND
717       asection *newsect)
718 {
719   newsect->used_by_bfd = (PTR)
720     bfd_alloc(abfd, sizeof(oasys_per_section_type));
721   oasys_per_section( newsect)->data = (bfd_byte *)NULL;
722   oasys_per_section(newsect)->section = newsect;
723   oasys_per_section(newsect)->offset  = 0;
724   oasys_per_section(newsect)->initialized = false;
725   newsect->alignment_power = 1;
726   /* Turn the section string into an index */
727
728   sscanf(newsect->name,"%u", &newsect->target_index);
729
730   return true;
731 }
732
733
734 static unsigned int
735 DEFUN(oasys_get_reloc_upper_bound, (abfd, asect),
736       bfd *abfd AND
737       sec_ptr asect)
738 {
739   oasys_slurp_section_data(abfd);
740   return (asect->reloc_count+1) * sizeof(arelent *);
741 }
742
743 static boolean
744 DEFUN(oasys_get_section_contents,(abfd, section, location, offset, count),
745       bfd *abfd AND
746       sec_ptr section AND
747       PTR location AND
748       file_ptr offset AND
749       bfd_size_type count)
750 {
751   oasys_per_section_type *p = (oasys_per_section_type *) section->used_by_bfd;
752   oasys_slurp_section_data(abfd);
753   if (p->initialized == false) 
754       {
755         (void) memset(location, 0, (int)count);
756       }
757   else 
758       {
759         (void) memcpy(location,(PTR)( p->data + offset), (int)count);
760       }
761   return true;
762 }
763
764
765 unsigned int
766 DEFUN(oasys_canonicalize_reloc,(ignore_abfd, section, relptr, symbols),
767       bfd *ignore_abfd AND
768       sec_ptr section AND
769       arelent **relptr AND
770       asymbol **symbols)
771 {
772   unsigned int reloc_count = 0;
773   oasys_reloc_type *src = (oasys_reloc_type *)(section->relocation);
774   while (src != (oasys_reloc_type *)NULL) {
775       abort();
776       
777 #if 0
778     if (src->relent.section == (asection *)NULL) 
779         {
780           src->relent.sym_ptr_ptr = symbols + src->symbol;
781         }
782 #endif
783
784     *relptr ++ = &src->relent;
785     src = src->next;
786     reloc_count++;
787   }
788   *relptr = (arelent *)NULL;
789   return section->reloc_count = reloc_count;
790 }
791
792
793
794
795 /* Writing */
796
797
798 /* Calculate the checksum and write one record */
799 static void 
800 DEFUN(oasys_write_record,(abfd, type, record, size),
801       bfd *CONST abfd AND
802       CONST oasys_record_enum_type type AND
803       oasys_record_union_type *record AND
804       CONST size_t size)
805 {
806   int checksum;
807   size_t i;
808   uint8e_type *ptr;
809   record->header.length = size;
810   record->header.type = (int)type;
811   record->header.check_sum = 0;
812   record->header.fill = 0;
813   ptr = &record->pad[0];
814   checksum = 0;
815   for (i = 0; i < size; i++) {
816     checksum += *ptr++;
817   }
818   record->header.check_sum = 0xff & (- checksum);
819   bfd_write((PTR)record, 1, size, abfd);
820 }
821
822
823 /* Write out all the symbols */
824 static void 
825 DEFUN(oasys_write_syms, (abfd),
826       bfd * CONST abfd)
827 {
828   unsigned int count;
829   asymbol **generic = bfd_get_outsymbols(abfd);
830   unsigned int index = 0;
831   for (count = 0; count < bfd_get_symcount(abfd); count++) {
832
833     oasys_symbol_record_type symbol;
834     asymbol * CONST g = generic[count];
835
836     CONST    char *src = g->name;
837     char *dst = symbol.name;
838     unsigned int l = 0;
839
840     if (g->section == & bfd_com_section) {
841       symbol.relb = RELOCATION_TYPE_COM;
842       bfd_h_put_16(abfd, index, (uint8e_type *)(&symbol.refno[0]));
843       index++;
844     }
845     else if (g->section == & bfd_abs_section) {
846       symbol.relb = RELOCATION_TYPE_ABS;
847       bfd_h_put_16(abfd, 0, (uint8e_type *)(&symbol.refno[0]));
848
849     }
850     else if (g->section == &bfd_und_section) {
851       symbol.relb = RELOCATION_TYPE_UND ;
852       bfd_h_put_16(abfd, index, (uint8e_type *)(&symbol.refno[0]));
853       /* Overload the value field with the output index number */
854       index++;
855     }
856     else if (g->flags & BSF_DEBUGGING) {
857       /* throw it away */
858       continue;
859     }
860     else {
861       if (g->section == (asection *)NULL) {
862         /* Sometime, the oasys tools give out a symbol with illegal
863            bits in it, we'll output it in the same broken way */
864         
865         symbol.relb = RELOCATION_TYPE_REL | 0;
866       }
867       else {
868         symbol.relb = RELOCATION_TYPE_REL |g->section->output_section->target_index;
869       }
870       bfd_h_put_16(abfd, 0, (uint8e_type *)(&symbol.refno[0]));
871     }
872 #ifdef UNDERSCORE_HACK
873     if (src[l] == '_')
874       dst[l++] = '.';
875 #endif
876     while (src[l]) {
877       dst[l] = src[l];
878       l++;
879     }
880
881     bfd_h_put_32(abfd, g->value, (bfd_byte*) symbol.value);
882
883       
884     if (g->flags & BSF_LOCAL) {
885       oasys_write_record(abfd,  
886                          oasys_record_is_local_enum,
887                          (oasys_record_union_type *) &symbol,
888                          offsetof(oasys_symbol_record_type, name[0]) + l);
889     }
890     else {
891       oasys_write_record(abfd,  
892                          oasys_record_is_symbol_enum,
893                          (oasys_record_union_type *) &symbol,
894                          offsetof(oasys_symbol_record_type, name[0]) + l);
895     }
896     g->value = index-1;
897   }
898 }
899
900
901   /* Write a section header for each section */
902 static void 
903 DEFUN(oasys_write_sections, (abfd),
904       bfd *CONST abfd)
905 {
906   asection *s;
907   static  oasys_section_record_type out = {0};
908
909   for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
910     if (!isdigit(s->name[0])) 
911         {
912           bfd_error_vector.nonrepresentable_section(abfd,
913                                                     s->name);
914         }
915     out.relb = RELOCATION_TYPE_REL | s->target_index;
916     bfd_h_put_32(abfd, s->_cooked_size, (bfd_byte *) out.value);
917     bfd_h_put_32(abfd, s->vma, (bfd_byte *) out.vma);
918
919     oasys_write_record(abfd,
920                        oasys_record_is_section_enum,
921                        (oasys_record_union_type *) &out,
922                        sizeof(out));
923   }
924 }
925
926 static void
927 DEFUN(oasys_write_header, (abfd),
928       bfd *CONST abfd)
929 {
930   /* Create and write the header */
931   oasys_header_record_type r;
932   size_t length = strlen(abfd->filename);
933   if (length > (size_t)sizeof(r.module_name)) {
934     length = sizeof(r.module_name);
935   }
936
937   (void)memcpy(r.module_name,
938                abfd->filename,
939                length);
940   (void)memset(r.module_name + length,
941                ' ',
942                sizeof(r.module_name) - length);
943
944   r.version_number = OASYS_VERSION_NUMBER;
945   r.rev_number = OASYS_REV_NUMBER;
946   oasys_write_record(abfd,
947                      oasys_record_is_header_enum,
948                      (oasys_record_union_type *)&r,
949                      offsetof(oasys_header_record_type, description[0]));
950
951
952
953 }
954
955 static void
956 DEFUN(oasys_write_end,(abfd),
957       bfd *CONST abfd)
958 {
959   oasys_end_record_type end;
960   uint8e_type null = 0;
961   end.relb = RELOCATION_TYPE_ABS;
962   bfd_h_put_32(abfd, abfd->start_address, (bfd_byte *)end.entry); 
963   bfd_h_put_16(abfd, 0, (bfd_byte *)end.fill);
964   end.zero =0;
965   oasys_write_record(abfd,
966                      oasys_record_is_end_enum,
967                      (oasys_record_union_type *)&end,
968                      sizeof(end));
969   bfd_write((PTR)&null, 1, 1, abfd);
970 }
971
972 static int 
973 DEFUN(comp,(ap, bp),
974    CONST PTR ap AND
975    CONST PTR bp)
976 {
977   arelent *a = *((arelent **)ap);
978   arelent *b = *((arelent **)bp);
979   return a->address - b->address;
980 }
981
982 /*
983  Writing data..
984  
985 */
986 static void
987 DEFUN(oasys_write_data, (abfd),
988       bfd *CONST abfd)
989 {
990   asection *s;
991   for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
992     if (s->flags & SEC_LOAD) {
993       uint8e_type *raw_data = oasys_per_section(s)->data;
994       oasys_data_record_type processed_data;
995       bfd_size_type current_byte_index = 0;
996       unsigned int relocs_to_go = s->reloc_count;
997       arelent **p = s->orelocation;
998       if (s->reloc_count != 0) {
999 /* Sort the reloc records so it's easy to insert the relocs into the
1000            data */
1001     
1002         qsort(s->orelocation,
1003               s->reloc_count,
1004               sizeof(arelent **),
1005               comp);
1006       }
1007       current_byte_index = 0;
1008       processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
1009
1010       while (current_byte_index < s->_cooked_size) 
1011           {
1012             /* Scan forwards by eight bytes or however much is left and see if
1013                there are any relocations going on */
1014             uint8e_type *mod = &processed_data.data[0];
1015             uint8e_type *dst = &processed_data.data[1];
1016
1017             unsigned int i;
1018             *mod = 0;
1019
1020
1021             bfd_h_put_32(abfd, s->vma + current_byte_index,
1022                          processed_data.addr);
1023
1024             /* Don't start a relocation unless you're sure you can finish it
1025                within the same data record.  The worst case relocation is a
1026                4-byte relocatable value which is split across two modification
1027                bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
1028                1 modification byte + 2 data = 8 bytes total).  That's where
1029                the magic number 8 comes from.
1030             */
1031             while (current_byte_index < s->_raw_size && dst <=
1032                 (uint8e_type*)&processed_data.data[sizeof(processed_data.data)-8]) {
1033             
1034
1035                 if (relocs_to_go != 0) {        
1036                   arelent *r = *p;
1037                   reloc_howto_type *CONST how=r->howto;
1038                   /* There is a relocation, is it for this byte ? */
1039                   if (r->address == current_byte_index) {
1040                     uint8e_type rel_byte;
1041                     p++;
1042                     relocs_to_go--;
1043
1044                     *mod |= (1<<i);
1045                     if(how->pc_relative) {
1046                       rel_byte = 0x80;
1047
1048                       /* Also patch the raw data so that it doesn't have
1049                          the -ve stuff any more */
1050                       if (how->size != 2) {
1051                         bfd_put_16(abfd, 
1052                                    bfd_get_16(abfd,raw_data) +
1053                                    current_byte_index, raw_data);
1054                       }
1055
1056                       else {
1057                         bfd_put_32(abfd, 
1058                                    bfd_get_32(abfd,raw_data) +
1059                                    current_byte_index, raw_data);
1060                       }
1061                     }
1062                     else {
1063                       rel_byte = 0;
1064                     }
1065                     if (how->size ==2) {
1066                       rel_byte |= 0x40;
1067                     }
1068                   
1069                     /* Is this a section relative relocation, or a symbol
1070                        relative relocation ? */
1071                     abort();
1072         
1073 #if 0
1074                     if (r->section != (asection*)NULL) 
1075                         {
1076                           /* The relent has a section attached, so it must be section
1077                              relative */
1078                           rel_byte |= RELOCATION_TYPE_REL;
1079                           rel_byte |= r->section->output_section->target_index;
1080                           *dst++ = rel_byte;
1081                         }
1082                     else 
1083 #endif
1084                         {
1085                           asymbol *p = *(r->sym_ptr_ptr);
1086
1087                           /* If this symbol has a section attached, then it
1088                              has already been resolved.  Change from a symbol
1089                              ref to a section ref */
1090                           if(p->section != (asection *)NULL) {
1091                             rel_byte |= RELOCATION_TYPE_REL;
1092                             rel_byte |=
1093                               p->section->output_section->target_index;
1094                             *dst++ = rel_byte;
1095                           }
1096                           else {
1097                             rel_byte |= RELOCATION_TYPE_UND;
1098                   
1099
1100                             *dst++ = rel_byte;
1101                             /* Next two bytes are a symbol index - we can get
1102                                this from the symbol value which has been zapped
1103                                into the symbol index in the table when the
1104                                symbol table was written
1105                                */
1106                             *dst++ = p->value >> 8;
1107                             *dst++ = p->value;
1108                           }
1109
1110                         }
1111 #define ADVANCE { if (++i >= 8) { i = 0; mod = dst++; *mod = 0; } current_byte_index++; }
1112                     /* relocations never occur from an unloadable section,
1113                        so we can assume that raw_data is not NULL
1114                      */
1115                     *dst++ = *raw_data++;
1116                     ADVANCE
1117                     *dst++ = *raw_data++;
1118                     ADVANCE
1119                     if (how->size == 2) {
1120                       *dst++ = *raw_data++;
1121                       ADVANCE
1122                       *dst++ = *raw_data++;
1123                       ADVANCE
1124                     }
1125                     continue;
1126                   }
1127                 }
1128                 /* If this is coming from an unloadable section then copy
1129                    zeros */
1130                 if (raw_data == (uint8e_type *)NULL) {
1131                   *dst++ = 0;
1132                 }
1133                 else {
1134                   *dst++ = *raw_data++;
1135                 }
1136                 ADVANCE
1137             }
1138
1139             /* Don't write a useless null modification byte */
1140             if (dst == mod+1) {
1141               --dst;
1142             }
1143
1144             oasys_write_record(abfd,
1145                                oasys_record_is_data_enum,
1146                                (oasys_record_union_type *)&processed_data,
1147                                dst - (uint8e_type*)&processed_data);
1148                          
1149           }
1150     }
1151   }
1152 }
1153 static boolean
1154 DEFUN(oasys_write_object_contents, (abfd),
1155       bfd * CONST abfd)
1156 {
1157   oasys_write_header(abfd);
1158   oasys_write_syms(abfd);
1159   oasys_write_sections(abfd);
1160   oasys_write_data(abfd);
1161   oasys_write_end(abfd);
1162   return true;
1163 }
1164
1165
1166
1167
1168 /** exec and core file sections */
1169
1170 /* set section contents is complicated with OASYS since the format is 
1171 * not a byte image, but a record stream.
1172 */
1173 static boolean
1174 DEFUN(oasys_set_section_contents,(abfd, section, location, offset, count),
1175       bfd *abfd AND
1176       sec_ptr section AND 
1177       PTR location AND
1178       file_ptr offset AND
1179       bfd_size_type count)
1180 {
1181   if (count != 0) {
1182     if (oasys_per_section(section)->data == (bfd_byte *)NULL ) 
1183         {
1184           oasys_per_section(section)->data =
1185             (bfd_byte *)(bfd_alloc(abfd,section->_cooked_size));    
1186         }
1187     (void) memcpy((PTR)(oasys_per_section(section)->data + offset),
1188                   location,
1189                   count);
1190   }
1191   return true;
1192 }
1193
1194
1195
1196 /* Native-level interface to symbols. */
1197
1198 /* We read the symbols into a buffer, which is discarded when this
1199 function exits.  We read the strings into a buffer large enough to
1200 hold them all plus all the cached symbol entries. */
1201
1202 static asymbol *
1203 DEFUN(oasys_make_empty_symbol,(abfd),
1204       bfd *abfd)
1205 {
1206
1207   oasys_symbol_type  *new =
1208     (oasys_symbol_type *)bfd_zalloc (abfd, sizeof (oasys_symbol_type));
1209   new->symbol.the_bfd = abfd;
1210   return &new->symbol;
1211
1212 }
1213
1214
1215 \f
1216
1217 /* User should have checked the file flags; perhaps we should return
1218 BFD_NO_MORE_SYMBOLS if there are none? */
1219
1220 static bfd *
1221 oasys_openr_next_archived_file(arch, prev)
1222 bfd *arch;
1223 bfd *prev;
1224 {
1225   oasys_ar_data_type *ar = OASYS_AR_DATA(arch);
1226   oasys_module_info_type *p;
1227   /* take the next one from the arch state, or reset */
1228   if (prev == (bfd *)NULL) {
1229     /* Reset the index - the first two entries are bogus*/
1230     ar->module_index = 0;
1231   }
1232
1233   p = ar->module + ar->module_index;
1234   ar->module_index++;
1235
1236   if (ar->module_index <= ar->module_count) {
1237     if (p->abfd == (bfd *)NULL) {
1238       p->abfd = _bfd_create_empty_archive_element_shell(arch);
1239       p->abfd->origin = p->pos;
1240       p->abfd->filename = p->name;
1241
1242       /* Fixup a pointer to this element for the member */
1243       p->abfd->arelt_data = (PTR)p;
1244     }
1245     return p->abfd;
1246   }
1247   else {
1248     bfd_error = no_more_archived_files;
1249     return (bfd *)NULL;
1250   }
1251 }
1252
1253 static boolean
1254 oasys_find_nearest_line(abfd,
1255                          section,
1256                          symbols,
1257                          offset,
1258                          filename_ptr,
1259                          functionname_ptr,
1260                          line_ptr)
1261 bfd *abfd;
1262 asection *section;
1263 asymbol **symbols;
1264 bfd_vma offset;
1265 char **filename_ptr;
1266 char **functionname_ptr;
1267 unsigned int *line_ptr;
1268 {
1269   return false;
1270
1271 }
1272
1273 static int
1274 DEFUN(oasys_generic_stat_arch_elt,(abfd, buf),
1275       bfd *abfd AND
1276       struct stat *buf)
1277 {
1278   oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1279   if (mod == (oasys_module_info_type *)NULL) {
1280     bfd_error = invalid_operation;
1281     return -1;
1282   }
1283   else {
1284     buf->st_size = mod->size;
1285     buf->st_mode = 0666;
1286     return 0;
1287   }
1288 }
1289
1290 static int 
1291 DEFUN(oasys_sizeof_headers,(abfd, exec),
1292       bfd *abfd AND
1293       boolean exec)
1294 {
1295 return 0;
1296 }
1297 #define FOO PROTO
1298 #define oasys_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
1299 #define oasys_core_file_failing_signal (int (*)())bfd_0
1300 #define oasys_core_file_matches_executable_p  0 
1301 #define oasys_slurp_armap bfd_true
1302 #define oasys_slurp_extended_name_table bfd_true
1303 #define oasys_truncate_arname (void (*)())bfd_nullvoidptr
1304 #define oasys_write_armap 0
1305 #define oasys_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
1306 #define oasys_close_and_cleanup         bfd_generic_close_and_cleanup
1307 #define oasys_set_arch_mach bfd_default_set_arch_mach
1308 #define oasys_bfd_debug_info_start bfd_void
1309 #define oasys_bfd_debug_info_end bfd_void
1310 #define oasys_bfd_debug_info_accumulate  (FOO(void, (*), (bfd *, asection *)))bfd_void
1311 #define oasys_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
1312 #define oasys_bfd_relax_section bfd_generic_relax_section
1313 /*SUPPRESS 460 */
1314 bfd_target oasys_vec =
1315 {
1316   "oasys",                      /* name */
1317   bfd_target_oasys_flavour,
1318   true,                         /* target byte order */
1319   true,                         /* target headers byte order */
1320   (HAS_RELOC | EXEC_P |         /* object flags */
1321    HAS_LINENO | HAS_DEBUG |
1322    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1323   (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
1324    |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1325    0,                           /* leading underscore */
1326   ' ',                          /* ar_pad_char */
1327   16,                           /* ar_max_namelen */
1328   1,                            /* minimum alignment */
1329   _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
1330   _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
1331
1332     {_bfd_dummy_target,
1333        oasys_object_p,          /* bfd_check_format */
1334        oasys_archive_p,
1335        _bfd_dummy_target,
1336      },
1337     {                           /* bfd_set_format */
1338       bfd_false,
1339       oasys_mkobject, 
1340       _bfd_generic_mkarchive,
1341       bfd_false
1342       },
1343     {                           /* bfd_write_contents */
1344       bfd_false,
1345       oasys_write_object_contents,
1346       _bfd_write_archive_contents,
1347       bfd_false,
1348     },
1349   JUMP_TABLE(oasys)
1350 };