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