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