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