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