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