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