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