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