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