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