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