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