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