*** empty log message ***
[binutils-gdb.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 #include <sysdep.h>
28
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_get_16(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_get_32(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
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 file_ptr filepos;
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_32(abfd, header_ext.version);
227 header.mod_count = bfd_h_get_32(abfd, header_ext.mod_count);
228 header.mod_tbl_offset = bfd_h_get_32(abfd, header_ext.mod_tbl_offset);
229 header.sym_tbl_size = bfd_h_get_32(abfd, header_ext.sym_tbl_size);
230 header.sym_count = bfd_h_get_32(abfd, header_ext.sym_count);
231 header.sym_tbl_offset = bfd_h_get_32(abfd, header_ext.sym_tbl_offset);
232 header.xref_count = bfd_h_get_32(abfd, header_ext.xref_count);
233 header.xref_lst_offset = bfd_h_get_32(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
260 oasys_module_table_type record;
261 oasys_external_module_table_type record_ext;
262
263 set_tdata(abfd, ar);
264 ar->module = module;
265 ar->module_count = header.mod_count;
266
267
268 filepos = header.mod_tbl_offset;
269 for (i = 0; i < header.mod_count; i++) {
270 bfd_seek(abfd , filepos, SEEK_SET);
271 bfd_read((PTR)&record_ext, 1, sizeof(record_ext), abfd);
272
273 record.mod_size = bfd_h_get_32(abfd, record_ext.mod_size);
274 record.file_offset = bfd_h_get_32(abfd,
275 record_ext.file_offset);
276
277 record.dep_count = bfd_h_get_32(abfd, record_ext.dep_count);
278 record.depee_count = bfd_h_get_32(abfd, record_ext.depee_count);
279 record.sect_count = bfd_h_get_32(abfd, record_ext.sect_count);
280
281
282 module[i].name = bfd_alloc(abfd,33);
283
284 memcpy(module[i].name, record_ext.mod_name, 33);
285 filepos +=
286 sizeof(record_ext) +
287 record.dep_count * 4 +
288 record.depee_count * 4 +
289 record.sect_count * 8 + 187,
290
291
292 module[i].size = record.mod_size;
293 module[i].pos = record.file_offset;
294 module[i].abfd = 0;
295 }
296
297 }
298 return abfd->xvec;
299 }
300
301 static boolean
302 DEFUN(oasys_mkobject,(abfd),
303 bfd *abfd)
304 {
305 oasys_data_type *oasys;
306
307 set_tdata (abfd,
308 (oasys_data_type*)bfd_alloc(abfd, sizeof(oasys_data_type)));
309 oasys = oasys_data(abfd);
310 return true;
311 }
312
313 #define MAX_SECS 16
314 static bfd_target *
315 DEFUN(oasys_object_p,(abfd),
316 bfd *abfd)
317 {
318 oasys_data_type *oasys;
319 oasys_data_type *save = oasys_data(abfd);
320 boolean loop = true;
321 boolean had_usefull = false;
322
323 set_tdata (abfd, 0);
324 oasys_mkobject(abfd);
325 oasys = oasys_data(abfd);
326 memset((PTR)oasys->sections, 0xff, sizeof(oasys->sections));
327
328 /* Point to the start of the file */
329 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
330 oasys->symbol_string_length = 0;
331 /* Inspect the records, but only keep the section info -
332 remember the size of the symbols
333 */
334 oasys->first_data_record = 0;
335 while (loop) {
336 oasys_record_union_type record;
337 oasys_read_record(abfd, &record);
338 if ((size_t)record.header.length < (size_t)sizeof(record.header))
339 goto fail;
340
341
342 switch ((oasys_record_enum_type)(record.header.type)) {
343 case oasys_record_is_header_enum:
344 had_usefull = true;
345 break;
346 case oasys_record_is_symbol_enum:
347 case oasys_record_is_local_enum:
348 /* Count symbols and remember their size for a future malloc */
349 abfd->symcount++;
350 oasys->symbol_string_length += 1 + oasys_string_length(&record);
351 had_usefull = true;
352 break;
353 case oasys_record_is_section_enum:
354 {
355 asection *s;
356 char *buffer;
357 unsigned int section_number;
358 if (record.section.header.length != sizeof(record.section))
359 {
360 goto fail;
361 }
362 buffer = bfd_alloc(abfd, 3);
363 section_number= record.section.relb & RELOCATION_SECT_BITS;
364 sprintf(buffer,"%u", section_number);
365 s = bfd_make_section(abfd,buffer);
366 oasys->sections[section_number] = s;
367 switch (record.section.relb & RELOCATION_TYPE_BITS) {
368 case RELOCATION_TYPE_ABS:
369 case RELOCATION_TYPE_REL:
370 break;
371 case RELOCATION_TYPE_UND:
372 case RELOCATION_TYPE_COM:
373 BFD_FAIL();
374 }
375
376 s->size = bfd_h_get_32(abfd, & record.section.value[0]) ;
377 s->vma = bfd_h_get_32(abfd, &record.section.vma[0]);
378 s->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
379 had_usefull = true;
380 }
381 break;
382 case oasys_record_is_data_enum:
383 oasys->first_data_record = bfd_tell(abfd) - record.header.length;
384 case oasys_record_is_debug_enum:
385 case oasys_record_is_module_enum:
386 case oasys_record_is_named_section_enum:
387 case oasys_record_is_end_enum:
388 if (had_usefull == false) goto fail;
389 loop = false;
390 break;
391 default:
392 goto fail;
393 }
394 }
395 oasys->symbols = (asymbol *)NULL;
396 /*
397 Oasys support several architectures, but I can't see a simple way
398 to discover which one is in a particular file - we'll guess
399 */
400 abfd->obj_arch = bfd_arch_m68k;
401 abfd->obj_machine =0;
402 if (abfd->symcount != 0) {
403 abfd->flags |= HAS_SYMS;
404 }
405 return abfd->xvec;
406
407 fail:
408 (void) bfd_release(abfd, oasys);
409 set_tdata (abfd, save);
410 return (bfd_target *)NULL;
411 }
412
413
414 static void
415 DEFUN(oasys_print_symbol,(ignore_abfd, afile, symbol, how),
416 bfd *ignore_abfd AND
417 PTR afile AND
418 asymbol *symbol AND
419 bfd_print_symbol_enum_type how)
420 {
421 FILE *file = (FILE *)afile;
422
423 switch (how) {
424 case bfd_print_symbol_name_enum:
425 case bfd_print_symbol_type_enum:
426 fprintf(file,"%s", symbol->name);
427 break;
428 case bfd_print_symbol_all_enum:
429 {
430 CONST char *section_name = symbol->section == (asection *)NULL ?
431 "*abs" : symbol->section->name;
432
433 bfd_print_symbol_vandf((PTR)file,symbol);
434
435 fprintf(file," %-5s %s",
436 section_name,
437 symbol->name);
438 }
439 break;
440 }
441 }
442 /*
443 The howto table is build using the top two bits of a reloc byte to
444 index into it. The bits are PCREL,WORD/LONG
445 */
446 static reloc_howto_type howto_table[]=
447 {
448
449 HOWTO( 0, 0, 1, 16, false,0, true,true,0,"abs16",true,0x0000ffff, 0x0000ffff,false),
450 HOWTO( 0, 0, 2, 32, false,0, true,true,0,"abs32",true,0xffffffff, 0xffffffff,false),
451 HOWTO( 0, 0, 1, 16, true,0, true,true,0,"pcrel16",true,0x0000ffff, 0x0000ffff,false),
452 HOWTO( 0, 0, 2, 32, true,0, true,true,0,"pcrel32",true,0xffffffff, 0xffffffff,false)
453 };
454
455 /* Read in all the section data and relocation stuff too */
456 static boolean
457 DEFUN(oasys_slurp_section_data,(abfd),
458 bfd *CONST abfd)
459 {
460 oasys_record_union_type record;
461 oasys_data_type *data = oasys_data(abfd);
462 boolean loop = true;
463
464 oasys_per_section_type *per ;
465
466 asection *s;
467
468 /* Buy enough memory for all the section data and relocations */
469 for (s = abfd->sections; s != (asection *)NULL; s= s->next) {
470 per = oasys_per_section(s);
471 if (per->data != (bfd_byte*)NULL) return true;
472 per->data = (bfd_byte *) bfd_alloc(abfd, s->size);
473 per->reloc_tail_ptr = (oasys_reloc_type **)&(s->relocation);
474 per->had_vma = false;
475 s->reloc_count = 0;
476 }
477
478 if (data->first_data_record == 0) return true;
479 bfd_seek(abfd, data->first_data_record, SEEK_SET);
480 while (loop) {
481 oasys_read_record(abfd, &record);
482 switch (record.header.type) {
483 case oasys_record_is_header_enum:
484 break;
485 case oasys_record_is_data_enum:
486 {
487
488 uint8e_type *src = record.data.data;
489 uint8e_type *end_src = ((uint8e_type *)&record) +
490 record.header.length;
491 unsigned int relbit;
492 bfd_byte *dst_ptr ;
493 bfd_byte *dst_base_ptr ;
494 unsigned int count;
495 asection * section =
496 data->sections[record.data.relb & RELOCATION_SECT_BITS];
497 bfd_vma dst_offset ;
498 per = oasys_per_section(section);
499 dst_offset = bfd_h_get_32(abfd, record.data.addr) ;
500 if (per->had_vma == false) {
501 /* Take the first vma we see as the base */
502
503 section->vma = dst_offset;
504 per->had_vma = true;
505 }
506
507
508 dst_offset -= section->vma;
509
510
511 dst_base_ptr = oasys_per_section(section)->data;
512 dst_ptr = oasys_per_section(section)->data +
513 dst_offset;
514
515 while (src < end_src) {
516 uint32_type gap = end_src - src -1;
517 uint8e_type mod_byte = *src++;
518 count = 8;
519 if (mod_byte == 0 && gap >= 8) {
520 dst_ptr[0] = src[0];
521 dst_ptr[1] = src[1];
522 dst_ptr[2] = src[2];
523 dst_ptr[3] = src[3];
524 dst_ptr[4] = src[4];
525 dst_ptr[5] = src[5];
526 dst_ptr[6] = src[6];
527 dst_ptr[7] = src[7];
528 dst_ptr+= 8;
529 src += 8;
530 }
531 else {
532 for (relbit = 1; count-- != 0 && gap != 0; gap --, relbit <<=1)
533 {
534 if (relbit & mod_byte)
535 {
536 uint8e_type reloc = *src;
537 /* This item needs to be relocated */
538 switch (reloc & RELOCATION_TYPE_BITS) {
539 case RELOCATION_TYPE_ABS:
540
541 break;
542
543 case RELOCATION_TYPE_REL:
544 {
545 /* Relocate the item relative to the section */
546 oasys_reloc_type *r =
547 (oasys_reloc_type *)
548 bfd_alloc(abfd,
549 sizeof(oasys_reloc_type));
550 *(per->reloc_tail_ptr) = r;
551 per->reloc_tail_ptr = &r->next;
552 r->next= (oasys_reloc_type *)NULL;
553 /* Reference to undefined symbol */
554 src++;
555 /* There is no symbol */
556 r->symbol = 0;
557 /* Work out the howto */
558 r->relent.section =
559 data->sections[reloc & RELOCATION_SECT_BITS];
560 r->relent.addend = - r->relent.section->vma;
561 r->relent.address = dst_ptr - dst_base_ptr;
562 r->relent.howto = &howto_table[reloc>>6];
563 r->relent.sym_ptr_ptr = (asymbol **)NULL;
564 section->reloc_count++;
565
566 /* Fake up the data to look like it's got the -ve pc in it, this makes
567 it much easier to convert into other formats. This is done by
568 hitting the addend.
569 */
570 if (r->relent.howto->pc_relative == true) {
571 r->relent.addend -= dst_ptr - dst_base_ptr;
572 }
573
574
575 }
576 break;
577
578
579 case RELOCATION_TYPE_UND:
580 {
581 oasys_reloc_type *r =
582 (oasys_reloc_type *)
583 bfd_alloc(abfd,
584 sizeof(oasys_reloc_type));
585 *(per->reloc_tail_ptr) = r;
586 per->reloc_tail_ptr = &r->next;
587 r->next= (oasys_reloc_type *)NULL;
588 /* Reference to undefined symbol */
589 src++;
590 /* Get symbol number */
591 r->symbol = (src[0]<<8) | src[1];
592 /* Work out the howto */
593 r->relent.section = (asection *)NULL;
594 r->relent.addend = 0;
595 r->relent.address = dst_ptr - dst_base_ptr;
596 r->relent.howto = &howto_table[reloc>>6];
597 r->relent.sym_ptr_ptr = (asymbol **)NULL;
598 section->reloc_count++;
599
600 src+=2;
601 /* Fake up the data to look like it's got the -ve pc in it, this makes
602 it much easier to convert into other formats. This is done by
603 hitting the addend.
604 */
605 if (r->relent.howto->pc_relative == true) {
606 r->relent.addend -= dst_ptr - dst_base_ptr;
607 }
608
609
610
611 }
612 break;
613 case RELOCATION_TYPE_COM:
614 BFD_FAIL();
615 }
616 }
617 *dst_ptr++ = *src++;
618 }
619 }
620 }
621 }
622 break;
623 case oasys_record_is_local_enum:
624 case oasys_record_is_symbol_enum:
625 case oasys_record_is_section_enum:
626 break;
627 default:
628 loop = false;
629 }
630 }
631 return true;
632
633 }
634
635
636
637 bfd_error_vector_type bfd_error_vector;
638
639 static boolean
640 DEFUN(oasys_new_section_hook,(abfd, newsect),
641 bfd *abfd AND
642 asection *newsect)
643 {
644 newsect->used_by_bfd = (PTR)
645 bfd_alloc(abfd, sizeof(oasys_per_section_type));
646 oasys_per_section( newsect)->data = (bfd_byte *)NULL;
647 oasys_per_section(newsect)->section = newsect;
648 oasys_per_section(newsect)->offset = 0;
649 newsect->alignment_power = 3;
650 /* Turn the section string into an index */
651
652 sscanf(newsect->name,"%u", &newsect->target_index);
653
654 return true;
655 }
656
657
658 static unsigned int
659 DEFUN(oasys_get_reloc_upper_bound, (abfd, asect),
660 bfd *abfd AND
661 sec_ptr asect)
662 {
663 oasys_slurp_section_data(abfd);
664 return (asect->reloc_count+1) * sizeof(arelent *);
665 }
666
667 static boolean
668 DEFUN(oasys_get_section_contents,(abfd, section, location, offset, count),
669 bfd *abfd AND
670 sec_ptr section AND
671 PTR location AND
672 file_ptr offset AND
673 bfd_size_type count)
674 {
675 oasys_per_section_type *p = (oasys_per_section_type *) section->used_by_bfd;
676 oasys_slurp_section_data(abfd);
677 (void) memcpy(location, p->data + offset, (int)count);
678 return true;
679 }
680
681
682 unsigned int
683 DEFUN(oasys_canonicalize_reloc,(abfd, section, relptr, symbols),
684 bfd *abfd AND
685 sec_ptr section AND
686 arelent **relptr AND
687 asymbol **symbols)
688 {
689 unsigned int reloc_count = 0;
690 oasys_reloc_type *src = (oasys_reloc_type *)(section->relocation);
691 while (src != (oasys_reloc_type *)NULL) {
692 if (src->relent.section == (asection *)NULL)
693 {
694 src->relent.sym_ptr_ptr = symbols + src->symbol;
695 }
696 *relptr ++ = &src->relent;
697 src = src->next;
698 reloc_count++;
699 }
700 *relptr = (arelent *)NULL;
701 return section->reloc_count = reloc_count;
702 }
703
704
705 boolean
706 DEFUN(oasys_set_arch_mach, (abfd, arch, machine),
707 bfd *abfd AND
708 enum bfd_architecture arch AND
709 unsigned long machine)
710 {
711 abfd->obj_arch = arch;
712 abfd->obj_machine = machine;
713 return true;
714 }
715
716
717
718 /* Writing */
719
720
721 /* Calculate the checksum and write one record */
722 static void
723 DEFUN(oasys_write_record,(abfd, type, record, size),
724 bfd *CONST abfd AND
725 CONST oasys_record_enum_type type AND
726 oasys_record_union_type *record AND
727 CONST size_t size)
728 {
729 int checksum;
730 size_t i;
731 uint8e_type *ptr;
732 record->header.length = size;
733 record->header.type = type;
734 record->header.check_sum = 0;
735 record->header.fill = 0;
736 ptr = &record->pad[0];
737 checksum = 0;
738 for (i = 0; i < size; i++) {
739 checksum += *ptr++;
740 }
741 record->header.check_sum = 0xff & (- checksum);
742 bfd_write((PTR)record, 1, size, abfd);
743 }
744
745
746 /* Write out all the symbols */
747 static void
748 DEFUN(oasys_write_syms, (abfd),
749 bfd * CONST abfd)
750 {
751 unsigned int count;
752 asymbol **generic = bfd_get_outsymbols(abfd);
753 unsigned int index = 0;
754 for (count = 0; count < bfd_get_symcount(abfd); count++) {
755
756 oasys_symbol_record_type symbol;
757 asymbol * CONST g = generic[count];
758
759 CONST char *src = g->name;
760 char *dst = symbol.name;
761 unsigned int l = 0;
762
763 if (g->flags & BSF_FORT_COMM) {
764 symbol.relb = RELOCATION_TYPE_COM;
765 bfd_h_put_16(abfd, index, (uint8e_type *)(&symbol.refno[0]));
766 index++;
767 }
768 else if (g->flags & BSF_ABSOLUTE) {
769 symbol.relb = RELOCATION_TYPE_ABS;
770 bfd_h_put_16(abfd, 0, (uint8e_type *)(&symbol.refno[0]));
771
772 }
773 else if (g->flags & BSF_UNDEFINED) {
774 symbol.relb = RELOCATION_TYPE_UND ;
775 bfd_h_put_16(abfd, index, (uint8e_type *)(&symbol.refno[0]));
776 /* Overload the value field with the output index number */
777 index++;
778 }
779 else if (g->flags & BSF_DEBUGGING) {
780 /* throw it away */
781 continue;
782 }
783 else {
784 symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
785 bfd_h_put_16(abfd, 0, (uint8e_type *)(&symbol.refno[0]));
786 }
787 while (src[l]) {
788 dst[l] = src[l];
789 l++;
790 }
791
792 bfd_h_put_32(abfd, g->value, symbol.value);
793
794
795 if (g->flags & BSF_LOCAL) {
796 oasys_write_record(abfd,
797 oasys_record_is_local_enum,
798 (oasys_record_union_type *) &symbol,
799 offsetof(oasys_symbol_record_type, name[0]) + l);
800 }
801 else {
802 oasys_write_record(abfd,
803 oasys_record_is_symbol_enum,
804 (oasys_record_union_type *) &symbol,
805 offsetof(oasys_symbol_record_type, name[0]) + l);
806 }
807 g->value = index-1;
808 }
809 }
810
811
812 /* Write a section header for each section */
813 static void
814 DEFUN(oasys_write_sections, (abfd),
815 bfd *CONST abfd)
816 {
817 asection *s;
818 static oasys_section_record_type out = {0};
819
820 for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
821 if (!isdigit(s->name[0]))
822 {
823 bfd_error_vector.nonrepresentable_section(abfd,
824 s->name);
825 }
826 out.relb = RELOCATION_TYPE_REL | s->target_index;
827 bfd_h_put_32(abfd, s->size, out.value);
828 bfd_h_put_32(abfd, s->vma, out.vma);
829
830 oasys_write_record(abfd,
831 oasys_record_is_section_enum,
832 (oasys_record_union_type *) &out,
833 sizeof(out));
834 }
835 }
836
837 static void
838 DEFUN(oasys_write_header, (abfd),
839 bfd *CONST abfd)
840 {
841 /* Create and write the header */
842 oasys_header_record_type r;
843 size_t length = strlen(abfd->filename);
844 if (length > (size_t)sizeof(r.module_name)) {
845 length = sizeof(r.module_name);
846 }
847
848 (void)memcpy(r.module_name,
849 abfd->filename,
850 length);
851 (void)memset(r.module_name + length,
852 ' ',
853 sizeof(r.module_name) - length);
854
855 r.version_number = OASYS_VERSION_NUMBER;
856 r.rev_number = OASYS_REV_NUMBER;
857 oasys_write_record(abfd,
858 oasys_record_is_header_enum,
859 (oasys_record_union_type *)&r,
860 offsetof(oasys_header_record_type, description[0]));
861
862
863
864 }
865
866 static void
867 DEFUN(oasys_write_end,(abfd),
868 bfd *CONST abfd)
869 {
870 oasys_end_record_type end;
871 uint8e_type null = 0;
872 end.relb = RELOCATION_TYPE_ABS;
873 bfd_h_put_32(abfd, abfd->start_address, end.entry);
874 bfd_h_put_16(abfd, 0, end.fill);
875 end.zero =0;
876 oasys_write_record(abfd,
877 oasys_record_is_end_enum,
878 (oasys_record_union_type *)&end,
879 sizeof(end));
880 bfd_write((PTR)&null, 1, 1, abfd);
881 }
882
883 static int
884 DEFUN(comp,(ap, bp),
885 CONST PTR ap AND
886 CONST PTR bp)
887 {
888 arelent *a = *((arelent **)ap);
889 arelent *b = *((arelent **)bp);
890 return a->address - b->address;
891 }
892
893 /*
894 Writing data..
895
896 */
897 static void
898 DEFUN(oasys_write_data, (abfd),
899 bfd *CONST abfd)
900 {
901 asection *s;
902 for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
903 uint8e_type *raw_data = oasys_per_section(s)->data;
904 oasys_data_record_type processed_data;
905 bfd_size_type current_byte_index = 0;
906 unsigned int relocs_to_go = s->reloc_count;
907 arelent **p = s->orelocation;
908 if (s->reloc_count != 0) {
909 /* Sort the reloc records so it's easy to insert the relocs into the
910 data */
911
912 qsort(s->orelocation,
913 s->reloc_count,
914 sizeof(arelent **),
915 comp);
916 }
917 current_byte_index = 0;
918 processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
919
920 while (current_byte_index < s->size)
921 {
922 /* Scan forwards by eight bytes or however much is left and see if
923 there are any relocations going on */
924 uint8e_type *mod = &processed_data.data[0];
925 uint8e_type *dst = &processed_data.data[1];
926
927 unsigned int i;
928 unsigned int long_length = 128;
929
930
931 bfd_h_put_32(abfd, s->vma + current_byte_index, processed_data.addr);
932 if ((size_t)(long_length + current_byte_index) > (size_t)(s->size)) {
933 long_length = s->size - current_byte_index;
934 }
935 while (long_length > 0 && (dst - (uint8e_type*)&processed_data < 128)) {
936
937 unsigned int length = long_length;
938 *mod =0;
939 if (length > 8)
940 length = 8;
941
942 for (i = 0; i < length; i++) {
943 if (relocs_to_go != 0) {
944 arelent *r = *p;
945 reloc_howto_type *CONST how=r->howto;
946 /* There is a relocation, is it for this byte ? */
947 if (r->address == current_byte_index) {
948 uint8e_type rel_byte;
949 p++;
950 relocs_to_go--;
951
952 *mod |= (1<<i);
953 if(how->pc_relative) {
954 rel_byte = 0x80;
955
956 /* Also patch the raw data so that it doesn't have
957 the -ve stuff any more */
958 if (how->size != 2) {
959 bfd_put_16(abfd,
960 bfd_get_16(abfd,raw_data) +
961 current_byte_index, raw_data);
962 }
963
964 else {
965 bfd_put_32(abfd,
966 bfd_get_32(abfd,raw_data) +
967 current_byte_index, raw_data);
968 }
969 }
970 else {
971 rel_byte = 0;
972 }
973 if (how->size ==2) {
974 rel_byte |= 0x40;
975 }
976
977 /* Is this a section relative relocation, or a symbol
978 relative relocation ? */
979 if (r->section != (asection*)NULL)
980 {
981 /* The relent has a section attatched, so it must be section
982 relative */
983 rel_byte |= RELOCATION_TYPE_REL;
984 rel_byte |= r->section->output_section->target_index;
985 *dst++ = rel_byte;
986 }
987 else
988 {
989 asymbol *p = *(r->sym_ptr_ptr);
990
991 /* If this symbol has a section attatched, then it
992 has already been resolved. Change from a symbol
993 ref to a section ref */
994 if(p->section != (asection *)NULL) {
995 rel_byte |= RELOCATION_TYPE_REL;
996 rel_byte |=
997 p->section->output_section->target_index;
998 *dst++ = rel_byte;
999 }
1000 else {
1001 rel_byte |= RELOCATION_TYPE_UND;
1002
1003
1004 *dst++ = rel_byte;
1005 /* Next two bytes are a symbol index - we can get
1006 this from the symbol value which has been zapped
1007 into the symbol index in the table when the
1008 symbol table was written
1009 */
1010 *dst++ = p->value >> 8;
1011 *dst++ = p->value;
1012 }
1013
1014 }
1015 }
1016 }
1017 /* If this is coming from an unloadable section then copy
1018 zeros */
1019 if (raw_data == (uint8e_type *)NULL) {
1020 *dst++ = 0;
1021 }
1022 else {
1023 *dst++ = *raw_data++;
1024 }
1025 current_byte_index++;
1026 }
1027 mod = dst++;
1028 long_length -= length;
1029 }
1030
1031 oasys_write_record(abfd,
1032 oasys_record_is_data_enum,
1033 (oasys_record_union_type *)&processed_data,
1034 dst - (uint8e_type*)&processed_data);
1035
1036 }
1037 }
1038 }
1039 static boolean
1040 DEFUN(oasys_write_object_contents, (abfd),
1041 bfd * CONST abfd)
1042 {
1043 oasys_write_header(abfd);
1044 oasys_write_syms(abfd);
1045 oasys_write_sections(abfd);
1046 oasys_write_data(abfd);
1047 oasys_write_end(abfd);
1048 return true;
1049 }
1050
1051
1052
1053
1054 /** exec and core file sections */
1055
1056 /* set section contents is complicated with OASYS since the format is
1057 * not a byte image, but a record stream.
1058 */
1059 static boolean
1060 DEFUN(oasys_set_section_contents,(abfd, section, location, offset, count),
1061 bfd *abfd AND
1062 sec_ptr section AND
1063 PTR location AND
1064 file_ptr offset AND
1065 bfd_size_type count)
1066 {
1067 if (count != 0) {
1068 if (oasys_per_section(section)->data == (bfd_byte *)NULL )
1069 {
1070 oasys_per_section(section)->data =
1071 (bfd_byte *)(bfd_alloc(abfd,section->size));
1072 }
1073 (void) memcpy(oasys_per_section(section)->data + offset,
1074 location,
1075 count);
1076 }
1077 return true;
1078 }
1079
1080
1081
1082 /* Native-level interface to symbols. */
1083
1084 /* We read the symbols into a buffer, which is discarded when this
1085 function exits. We read the strings into a buffer large enough to
1086 hold them all plus all the cached symbol entries. */
1087
1088 static asymbol *
1089 DEFUN(oasys_make_empty_symbol,(abfd),
1090 bfd *abfd)
1091 {
1092
1093 oasys_symbol_type *new =
1094 (oasys_symbol_type *)bfd_zalloc (abfd, sizeof (oasys_symbol_type));
1095 new->symbol.the_bfd = abfd;
1096 return &new->symbol;
1097
1098 }
1099
1100
1101 \f
1102
1103 /* User should have checked the file flags; perhaps we should return
1104 BFD_NO_MORE_SYMBOLS if there are none? */
1105
1106 static bfd *
1107 oasys_openr_next_archived_file(arch, prev)
1108 bfd *arch;
1109 bfd *prev;
1110 {
1111 oasys_ar_data_type *ar = oasys_ar_data(arch);
1112 oasys_module_info_type *p;
1113 /* take the next one from the arch state, or reset */
1114 if (prev == (bfd *)NULL) {
1115 /* Reset the index - the first two entries are bogus*/
1116 ar->module_index = 0;
1117 }
1118
1119 p = ar->module + ar->module_index;
1120 ar->module_index++;
1121
1122 if (ar->module_index <= ar->module_count) {
1123 if (p->abfd == (bfd *)NULL) {
1124 p->abfd = _bfd_create_empty_archive_element_shell(arch);
1125 p->abfd->origin = p->pos;
1126 p->abfd->filename = p->name;
1127
1128 /* Fixup a pointer to this element for the member */
1129 p->abfd->arelt_data = (PTR)p;
1130 }
1131 return p->abfd;
1132 }
1133 else {
1134 bfd_error = no_more_archived_files;
1135 return (bfd *)NULL;
1136 }
1137 }
1138
1139 static boolean
1140 oasys_find_nearest_line(abfd,
1141 section,
1142 symbols,
1143 offset,
1144 filename_ptr,
1145 functionname_ptr,
1146 line_ptr)
1147 bfd *abfd;
1148 asection *section;
1149 asymbol **symbols;
1150 bfd_vma offset;
1151 char **filename_ptr;
1152 char **functionname_ptr;
1153 unsigned int *line_ptr;
1154 {
1155 return false;
1156
1157 }
1158
1159 static int
1160 DEFUN(oasys_generic_stat_arch_elt,(abfd, buf),
1161 bfd *abfd AND
1162 struct stat *buf)
1163 {
1164 oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1165 if (mod == (oasys_module_info_type *)NULL) {
1166 bfd_error = invalid_operation;
1167 return -1;
1168 }
1169 else {
1170 buf->st_size = mod->size;
1171 buf->st_mode = 0666;
1172 return 0;
1173 }
1174 }
1175
1176 static int
1177 DEFUN(oasys_sizeof_headers,(abfd, exec),
1178 bfd *abfd AND
1179 boolean exec)
1180 {
1181 return 0;
1182 }
1183
1184 #define oasys_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
1185 #define oasys_core_file_failing_signal (int (*)())bfd_0
1186 #define oasys_core_file_matches_executable_p 0 /*(PROTO(boolean, (*),(bfd*, bfd*)))bfd_false*/
1187 #define oasys_slurp_armap bfd_true
1188 #define oasys_slurp_extended_name_table bfd_true
1189 #define oasys_truncate_arname (void (*)())bfd_nullvoidptr
1190 #define oasys_write_armap 0 /* (PROTO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr*/
1191 #define oasys_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
1192 #define oasys_close_and_cleanup bfd_generic_close_and_cleanup
1193
1194
1195
1196 /*SUPPRESS 460 */
1197 bfd_target oasys_vec =
1198 {
1199 "oasys", /* name */
1200 bfd_target_oasys_flavour_enum,
1201 true, /* target byte order */
1202 true, /* target headers byte order */
1203 (HAS_RELOC | EXEC_P | /* object flags */
1204 HAS_LINENO | HAS_DEBUG |
1205 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1206 (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
1207 |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1208 ' ', /* ar_pad_char */
1209 16, /* ar_max_namelen */
1210
1211 _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
1212 _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
1213
1214 {_bfd_dummy_target,
1215 oasys_object_p, /* bfd_check_format */
1216 oasys_archive_p,
1217 _bfd_dummy_target,
1218 },
1219 { /* bfd_set_format */
1220 bfd_false,
1221 oasys_mkobject,
1222 _bfd_generic_mkarchive,
1223 bfd_false
1224 },
1225 { /* bfd_write_contents */
1226 bfd_false,
1227 oasys_write_object_contents,
1228 _bfd_write_archive_contents,
1229 bfd_false,
1230 },
1231 JUMP_TABLE(oasys)
1232 };