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