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