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