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