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