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