OSDN Git Service

Convert to ISO C90 formatting
[pf3gnuchains/pf3gnuchains4x.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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                 per->data = bfd_zalloc (abfd, section->size);
388                 if (!per->data)
389                   return FALSE;
390                 per->reloc_tail_ptr
391                   = (oasys_reloc_type **) &section->relocation;
392                 per->had_vma = FALSE;
393                 per->initialized = TRUE;
394                 section->reloc_count = 0;
395                 section->flags = SEC_ALLOC;
396               }
397
398             dst_offset = H_GET_32 (abfd, record.data.addr);
399             if (! per->had_vma)
400               {
401                 /* Take the first vma we see as the base.  */
402                 section->vma = dst_offset;
403                 per->had_vma = TRUE;
404               }
405
406             dst_offset -= section->vma;
407
408             dst_base_ptr = oasys_per_section (section)->data;
409             dst_ptr = oasys_per_section (section)->data +
410               dst_offset;
411
412             if (src < end_src)
413               section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
414
415             while (src < end_src)
416               {
417                 unsigned char mod_byte = *src++;
418                 size_t gap = end_src - src;
419
420                 count = 8;
421                 if (mod_byte == 0 && gap >= 8)
422                   {
423                     dst_ptr[0] = src[0];
424                     dst_ptr[1] = src[1];
425                     dst_ptr[2] = src[2];
426                     dst_ptr[3] = src[3];
427                     dst_ptr[4] = src[4];
428                     dst_ptr[5] = src[5];
429                     dst_ptr[6] = src[6];
430                     dst_ptr[7] = src[7];
431                     dst_ptr += 8;
432                     src += 8;
433                   }
434                 else
435                   {
436                     for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
437                       {
438                         if (relbit & mod_byte)
439                           {
440                             unsigned char reloc = *src;
441                             /* This item needs to be relocated.  */
442                             switch (reloc & RELOCATION_TYPE_BITS)
443                               {
444                               case RELOCATION_TYPE_ABS:
445                                 break;
446
447                               case RELOCATION_TYPE_REL:
448                                 {
449                                   /* Relocate the item relative to the section.  */
450                                   oasys_reloc_type *r;
451
452                                   amt = sizeof (oasys_reloc_type);
453                                   r = bfd_alloc (abfd, amt);
454                                   if (!r)
455                                     return FALSE;
456                                   *(per->reloc_tail_ptr) = r;
457                                   per->reloc_tail_ptr = &r->next;
458                                   r->next = NULL;
459                                   /* Reference to undefined symbol.  */
460                                   src++;
461                                   /* There is no symbol.  */
462                                   r->symbol = 0;
463                                   /* Work out the howto.  */
464                                   abort ();
465                                   r->relent.address = dst_ptr - dst_base_ptr;
466                                   r->relent.howto = &howto_table[reloc >> 6];
467                                   r->relent.sym_ptr_ptr = NULL;
468                                   section->reloc_count++;
469
470                                   /* Fake up the data to look like
471                                      it's got the -ve pc in it, this
472                                      makes it much easier to convert
473                                      into other formats.  This is done
474                                      by hitting the addend.  */
475                                   if (r->relent.howto->pc_relative)
476                                     r->relent.addend -= dst_ptr - dst_base_ptr;
477                                 }
478                                 break;
479
480                               case RELOCATION_TYPE_UND:
481                                 {
482                                   oasys_reloc_type *r;
483
484                                   amt = sizeof (oasys_reloc_type);
485                                   r = bfd_alloc (abfd, amt);
486                                   if (!r)
487                                     return FALSE;
488                                   *(per->reloc_tail_ptr) = r;
489                                   per->reloc_tail_ptr = &r->next;
490                                   r->next = NULL;
491                                   /* Reference to undefined symbol.  */
492                                   src++;
493                                   /* Get symbol number.  */
494                                   r->symbol = (src[0] << 8) | src[1];
495                                   /* Work out the howto.  */
496                                   abort ();
497
498                                   r->relent.addend = 0;
499                                   r->relent.address = dst_ptr - dst_base_ptr;
500                                   r->relent.howto = &howto_table[reloc >> 6];
501                                   r->relent.sym_ptr_ptr = NULL;
502                                   section->reloc_count++;
503
504                                   src += 2;
505                                   /* Fake up the data to look like
506                                      it's got the -ve pc in it, this
507                                      makes it much easier to convert
508                                      into other formats.  This is done
509                                      by hitting the addend.  */
510                                   if (r->relent.howto->pc_relative)
511                                     r->relent.addend -= dst_ptr - dst_base_ptr;
512                                 }
513                                 break;
514                               case RELOCATION_TYPE_COM:
515                                 BFD_FAIL ();
516                               }
517                           }
518                         *dst_ptr++ = *src++;
519                       }
520                   }
521               }
522           }
523           break;
524         case oasys_record_is_local_enum:
525         case oasys_record_is_symbol_enum:
526         case oasys_record_is_section_enum:
527           break;
528         default:
529           loop = FALSE;
530         }
531     }
532
533   return TRUE;
534
535 }
536
537 #define MAX_SECS 16
538
539 static const bfd_target *
540 oasys_object_p (bfd *abfd)
541 {
542   oasys_data_type *oasys;
543   oasys_data_type *save = OASYS_DATA (abfd);
544   bfd_boolean loop = TRUE;
545   bfd_boolean had_usefull = FALSE;
546
547   abfd->tdata.oasys_obj_data = 0;
548   oasys_mkobject (abfd);
549   oasys = OASYS_DATA (abfd);
550   memset ((void *) oasys->sections, 0xff, sizeof (oasys->sections));
551
552   /* Point to the start of the file.  */
553   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
554     goto fail;
555   oasys->symbol_string_length = 0;
556
557   /* Inspect the records, but only keep the section info -
558      remember the size of the symbols.  */
559   oasys->first_data_record = 0;
560   while (loop)
561     {
562       oasys_record_union_type record;
563       if (! oasys_read_record (abfd, &record))
564         goto fail;
565       if ((size_t) record.header.length < (size_t) sizeof (record.header))
566         goto fail;
567
568       switch ((oasys_record_enum_type) (record.header.type))
569         {
570         case oasys_record_is_header_enum:
571           had_usefull = TRUE;
572           break;
573         case oasys_record_is_symbol_enum:
574         case oasys_record_is_local_enum:
575           /* Count symbols and remember their size for a future malloc.  */
576           abfd->symcount++;
577           oasys->symbol_string_length += 1 + oasys_string_length (&record);
578           had_usefull = TRUE;
579           break;
580         case oasys_record_is_section_enum:
581           {
582             asection *s;
583             char *buffer;
584             unsigned int section_number;
585
586             if (record.section.header.length != sizeof (record.section))
587               goto fail;
588
589             buffer = bfd_alloc (abfd, (bfd_size_type) 3);
590             if (!buffer)
591               goto fail;
592             section_number = record.section.relb & RELOCATION_SECT_BITS;
593             sprintf (buffer, "%u", section_number);
594             s = bfd_make_section (abfd, buffer);
595             oasys->sections[section_number] = s;
596             switch (record.section.relb & RELOCATION_TYPE_BITS)
597               {
598               case RELOCATION_TYPE_ABS:
599               case RELOCATION_TYPE_REL:
600                 break;
601               case RELOCATION_TYPE_UND:
602               case RELOCATION_TYPE_COM:
603                 BFD_FAIL ();
604               }
605
606             s->size = H_GET_32 (abfd, record.section.value);
607             s->vma = H_GET_32 (abfd, record.section.vma);
608             s->flags = 0;
609             had_usefull = TRUE;
610           }
611           break;
612         case oasys_record_is_data_enum:
613           oasys->first_data_record = bfd_tell (abfd) - record.header.length;
614         case oasys_record_is_debug_enum:
615         case oasys_record_is_module_enum:
616         case oasys_record_is_named_section_enum:
617         case oasys_record_is_end_enum:
618           if (! had_usefull)
619             goto fail;
620           loop = FALSE;
621           break;
622         default:
623           goto fail;
624         }
625     }
626   oasys->symbols = NULL;
627
628   /* Oasys support several architectures, but I can't see a simple way
629      to discover which one is in a particular file - we'll guess.  */
630   bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
631   if (abfd->symcount != 0)
632     abfd->flags |= HAS_SYMS;
633
634   /* We don't know if a section has data until we've read it.  */
635   oasys_slurp_section_data (abfd);
636
637   return abfd->xvec;
638
639 fail:
640   (void) bfd_release (abfd, oasys);
641   abfd->tdata.oasys_obj_data = save;
642   return NULL;
643 }
644
645
646 static void
647 oasys_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
648                        asymbol *symbol,
649                        symbol_info *ret)
650 {
651   bfd_symbol_info (symbol, ret);
652
653   if (!symbol->section)
654     ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
655 }
656
657 static void
658 oasys_print_symbol (bfd *abfd, void * afile, asymbol *symbol, bfd_print_symbol_type how)
659 {
660   FILE *file = (FILE *) afile;
661
662   switch (how)
663     {
664     case bfd_print_symbol_name:
665     case bfd_print_symbol_more:
666       fprintf (file, "%s", symbol->name);
667       break;
668     case bfd_print_symbol_all:
669       {
670         const char *section_name = symbol->section == NULL ?
671         (const char *) "*abs" : symbol->section->name;
672
673         bfd_print_symbol_vandf (abfd, (void *) file, symbol);
674
675         fprintf (file, " %-5s %s",
676                  section_name,
677                  symbol->name);
678       }
679       break;
680     }
681 }
682
683 static bfd_boolean
684 oasys_new_section_hook (bfd *abfd, asection *newsect)
685 {
686   newsect->used_by_bfd = bfd_alloc (abfd, (bfd_size_type) sizeof (oasys_per_section_type));
687   if (!newsect->used_by_bfd)
688     return FALSE;
689   oasys_per_section (newsect)->data = NULL;
690   oasys_per_section (newsect)->section = newsect;
691   oasys_per_section (newsect)->offset = 0;
692   oasys_per_section (newsect)->initialized = FALSE;
693   newsect->alignment_power = 1;
694
695   /* Turn the section string into an index.  */
696   sscanf (newsect->name, "%u", &newsect->target_index);
697
698   return TRUE;
699 }
700
701
702 static long
703 oasys_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
704 {
705   if (! oasys_slurp_section_data (abfd))
706     return -1;
707   return (asect->reloc_count + 1) * sizeof (arelent *);
708 }
709
710 static bfd_boolean
711 oasys_get_section_contents (bfd *abfd,
712                             sec_ptr section,
713                             void * location,
714                             file_ptr offset,
715                             bfd_size_type count)
716 {
717   oasys_per_section_type *p = oasys_per_section (section);
718
719   oasys_slurp_section_data (abfd);
720
721   if (! p->initialized)
722     (void) memset (location, 0, (size_t) count);
723   else
724     (void) memcpy (location, (void *) (p->data + offset), (size_t) count);
725
726   return TRUE;
727 }
728
729 static long
730 oasys_canonicalize_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
731                           sec_ptr section,
732                           arelent **relptr,
733                           asymbol **symbols ATTRIBUTE_UNUSED)
734 {
735   unsigned int reloc_count = 0;
736   oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
737
738   if (src != NULL)
739     abort ();
740
741   *relptr = NULL;
742   return section->reloc_count = reloc_count;
743 }
744
745
746 /* Writing.  */
747
748 /* Calculate the checksum and write one record.  */
749
750 static bfd_boolean
751 oasys_write_record (bfd *abfd,
752                     oasys_record_enum_type type,
753                     oasys_record_union_type *record,
754                     size_t size)
755 {
756   int checksum;
757   size_t i;
758   unsigned char *ptr;
759
760   record->header.length = size;
761   record->header.type = (int) type;
762   record->header.check_sum = 0;
763   record->header.fill = 0;
764   ptr = (unsigned char *) &record->pad[0];
765   checksum = 0;
766   for (i = 0; i < size; i++)
767     checksum += *ptr++;
768   record->header.check_sum = 0xff & (-checksum);
769   if (bfd_bwrite ((void *) record, (bfd_size_type) size, abfd) != size)
770     return FALSE;
771   return TRUE;
772 }
773
774
775 /* Write out all the symbols.  */
776
777 static bfd_boolean
778 oasys_write_syms (bfd *abfd)
779 {
780   unsigned int count;
781   asymbol **generic = bfd_get_outsymbols (abfd);
782   unsigned int index = 0;
783
784   for (count = 0; count < bfd_get_symcount (abfd); count++)
785     {
786       oasys_symbol_record_type symbol;
787       asymbol *const g = generic[count];
788       const char *src = g->name;
789       char *dst = symbol.name;
790       unsigned int l = 0;
791
792       if (bfd_is_com_section (g->section))
793         {
794           symbol.relb = RELOCATION_TYPE_COM;
795           H_PUT_16 (abfd, index, symbol.refno);
796           index++;
797         }
798       else if (bfd_is_abs_section (g->section))
799         {
800           symbol.relb = RELOCATION_TYPE_ABS;
801           H_PUT_16 (abfd, 0, symbol.refno);
802         }
803       else if (bfd_is_und_section (g->section))
804         {
805           symbol.relb = RELOCATION_TYPE_UND;
806           H_PUT_16 (abfd, index, symbol.refno);
807           /* Overload the value field with the output index number */
808           index++;
809         }
810       else if (g->flags & BSF_DEBUGGING)
811         /* Throw it away.  */
812         continue;
813       else
814         {
815           if (g->section == NULL)
816             /* Sometime, the oasys tools give out a symbol with illegal
817                bits in it, we'll output it in the same broken way.  */
818             symbol.relb = RELOCATION_TYPE_REL | 0;
819           else
820             symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
821
822           H_PUT_16 (abfd, 0, symbol.refno);
823         }
824
825 #ifdef UNDERSCORE_HACK
826       if (src[l] == '_')
827         dst[l++] = '.';
828 #endif
829       while (src[l])
830         {
831           dst[l] = src[l];
832           l++;
833         }
834
835       H_PUT_32 (abfd, g->value, symbol.value);
836
837       if (g->flags & BSF_LOCAL)
838         {
839           if (! oasys_write_record (abfd,
840                                     oasys_record_is_local_enum,
841                                     (oasys_record_union_type *) & symbol,
842                                     offsetof (oasys_symbol_record_type,
843                                               name[0]) + l))
844             return FALSE;
845         }
846       else
847         {
848           if (! oasys_write_record (abfd,
849                                     oasys_record_is_symbol_enum,
850                                     (oasys_record_union_type *) & symbol,
851                                     offsetof (oasys_symbol_record_type,
852                                               name[0]) + l))
853             return FALSE;
854         }
855       g->value = index - 1;
856     }
857
858   return TRUE;
859 }
860
861 /* Write a section header for each section.  */
862
863 static bfd_boolean
864 oasys_write_sections (bfd *abfd)
865 {
866   asection *s;
867   static oasys_section_record_type out;
868
869   for (s = abfd->sections; s != NULL; s = s->next)
870     {
871       if (!ISDIGIT (s->name[0]))
872         {
873           (*_bfd_error_handler)
874             (_("%s: can not represent section `%s' in oasys"),
875              bfd_get_filename (abfd), s->name);
876           bfd_set_error (bfd_error_nonrepresentable_section);
877           return FALSE;
878         }
879       out.relb = RELOCATION_TYPE_REL | s->target_index;
880       H_PUT_32 (abfd, s->size, out.value);
881       H_PUT_32 (abfd, s->vma, out.vma);
882
883       if (! oasys_write_record (abfd,
884                                 oasys_record_is_section_enum,
885                                 (oasys_record_union_type *) & out,
886                                 sizeof (out)))
887         return FALSE;
888     }
889   return TRUE;
890 }
891
892 static bfd_boolean
893 oasys_write_header (bfd *abfd)
894 {
895   /* Create and write the header.  */
896   oasys_header_record_type r;
897   size_t length = strlen (abfd->filename);
898
899   if (length > (size_t) sizeof (r.module_name))
900     length = sizeof (r.module_name);
901
902   (void) memcpy (r.module_name, abfd->filename, length);
903   (void) memset (r.module_name + length, ' ', sizeof (r.module_name) - length);
904
905   r.version_number = OASYS_VERSION_NUMBER;
906   r.rev_number = OASYS_REV_NUMBER;
907
908   return oasys_write_record (abfd, oasys_record_is_header_enum,
909                              (oasys_record_union_type *) & r,
910                              offsetof (oasys_header_record_type,
911                                        description[0]));
912 }
913
914 static bfd_boolean
915 oasys_write_end (bfd *abfd)
916 {
917   oasys_end_record_type end;
918   unsigned char null = 0;
919
920   end.relb = RELOCATION_TYPE_ABS;
921   H_PUT_32 (abfd, abfd->start_address, end.entry);
922   H_PUT_16 (abfd, 0, end.fill);
923   end.zero = 0;
924   if (! oasys_write_record (abfd,
925                             oasys_record_is_end_enum,
926                             (oasys_record_union_type *) & end,
927                             sizeof (end)))
928     return FALSE;
929
930   return bfd_bwrite ((void *) &null, (bfd_size_type) 1, abfd) == 1;
931 }
932
933 static int
934 comp (const void * ap, const void * bp)
935 {
936   arelent *a = *((arelent **) ap);
937   arelent *b = *((arelent **) bp);
938
939   return a->address - b->address;
940 }
941
942 static bfd_boolean
943 oasys_write_data (bfd *abfd)
944 {
945   asection *s;
946
947   for (s = abfd->sections; s != NULL; s = s->next)
948     {
949       if (s->flags & SEC_LOAD)
950         {
951           bfd_byte *raw_data = oasys_per_section (s)->data;
952           oasys_data_record_type processed_data;
953           bfd_size_type current_byte_index = 0;
954           unsigned int relocs_to_go = s->reloc_count;
955           arelent **p = s->orelocation;
956
957           if (s->reloc_count != 0)
958             /* Sort the reloc records so it's easy to insert the relocs into the
959                data.  */
960             qsort (s->orelocation, s->reloc_count, sizeof (arelent **), comp);
961
962           current_byte_index = 0;
963           processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
964
965           while (current_byte_index < s->size)
966             {
967               /* Scan forwards by eight bytes or however much is left and see if
968                there are any relocations going on.  */
969               bfd_byte *mod = &processed_data.data[0];
970               bfd_byte *dst = &processed_data.data[1];
971
972               unsigned int i = 0;
973               *mod = 0;
974
975               H_PUT_32 (abfd, s->vma + current_byte_index,
976                         processed_data.addr);
977
978               /* Don't start a relocation unless you're sure you can finish it
979                  within the same data record.  The worst case relocation is a
980                  4-byte relocatable value which is split across two modification
981                  bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
982                  1 modification byte + 2 data = 8 bytes total).  That's where
983                  the magic number 8 comes from.  */
984               while (current_byte_index < s->size && dst <=
985                      & processed_data.data[sizeof (processed_data.data) - 8])
986                 {
987                   if (relocs_to_go != 0)
988                     {
989                       arelent *r = *p;
990
991                       /* There is a relocation, is it for this byte ?  */
992                       if (r->address == current_byte_index)
993                         abort ();
994                     }
995
996                   /* If this is coming from an unloadable section then copy
997                      zeros.  */
998                   if (raw_data == NULL)
999                     *dst++ = 0;
1000                   else
1001                     *dst++ = *raw_data++;
1002
1003                   if (++i >= 8)
1004                     {
1005                       i = 0;
1006                       mod = dst++;
1007                       *mod = 0;
1008                     }
1009                   current_byte_index++;
1010                 }
1011
1012               /* Don't write a useless null modification byte.  */
1013               if (dst == mod + 1)
1014                 --dst;
1015
1016               if (! (oasys_write_record
1017                      (abfd, oasys_record_is_data_enum,
1018                       ((oasys_record_union_type *) &processed_data),
1019                       (size_t) (dst - (bfd_byte *) &processed_data))))
1020                 return FALSE;
1021             }
1022         }
1023     }
1024
1025   return TRUE;
1026 }
1027
1028 static bfd_boolean
1029 oasys_write_object_contents (bfd *abfd)
1030 {
1031   if (! oasys_write_header (abfd))
1032     return FALSE;
1033   if (! oasys_write_syms (abfd))
1034     return FALSE;
1035   if (! oasys_write_sections (abfd))
1036     return FALSE;
1037   if (! oasys_write_data (abfd))
1038     return FALSE;
1039   if (! oasys_write_end (abfd))
1040     return FALSE;
1041   return TRUE;
1042 }
1043
1044 /* Set section contents is complicated with OASYS since the format is
1045    not a byte image, but a record stream.  */
1046
1047 static bfd_boolean
1048 oasys_set_section_contents (bfd *abfd,
1049                             sec_ptr section,
1050                             const void * location,
1051                             file_ptr offset,
1052                             bfd_size_type count)
1053 {
1054   if (count != 0)
1055     {
1056       if (oasys_per_section (section)->data == NULL)
1057         {
1058           oasys_per_section (section)->data = bfd_alloc (abfd, section->size);
1059           if (!oasys_per_section (section)->data)
1060             return FALSE;
1061         }
1062       (void) memcpy ((void *) (oasys_per_section (section)->data + offset),
1063                      location, (size_t) count);
1064     }
1065   return TRUE;
1066 }
1067
1068
1069
1070 /* Native-level interface to symbols.  */
1071
1072 /* We read the symbols into a buffer, which is discarded when this
1073    function exits.  We read the strings into a buffer large enough to
1074    hold them all plus all the cached symbol entries.  */
1075
1076 static asymbol *
1077 oasys_make_empty_symbol (bfd *abfd)
1078 {
1079   bfd_size_type amt = sizeof (oasys_symbol_type);
1080   oasys_symbol_type *new = bfd_zalloc (abfd, amt);
1081
1082   if (!new)
1083     return NULL;
1084   new->symbol.the_bfd = abfd;
1085   return &new->symbol;
1086 }
1087
1088 /* User should have checked the file flags; perhaps we should return
1089    BFD_NO_MORE_SYMBOLS if there are none?  */
1090
1091 static bfd *
1092 oasys_openr_next_archived_file (bfd *arch, bfd *prev)
1093 {
1094   oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
1095   oasys_module_info_type *p;
1096
1097   /* Take the next one from the arch state, or reset.  */
1098   if (prev == NULL)
1099     /* Reset the index - the first two entries are bogus.  */
1100     ar->module_index = 0;
1101
1102   p = ar->module + ar->module_index;
1103   ar->module_index++;
1104
1105   if (ar->module_index <= ar->module_count)
1106     {
1107       if (p->abfd == NULL)
1108         {
1109           p->abfd = _bfd_create_empty_archive_element_shell (arch);
1110           p->abfd->origin = p->pos;
1111           p->abfd->filename = p->name;
1112
1113           /* Fixup a pointer to this element for the member.  */
1114           p->abfd->arelt_data = (void *) p;
1115         }
1116       return p->abfd;
1117     }
1118
1119   bfd_set_error (bfd_error_no_more_archived_files);
1120   return NULL;
1121 }
1122
1123 static bfd_boolean
1124 oasys_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED,
1125                          asection *section ATTRIBUTE_UNUSED,
1126                          asymbol **symbols ATTRIBUTE_UNUSED,
1127                          bfd_vma offset ATTRIBUTE_UNUSED,
1128                          const char **filename_ptr ATTRIBUTE_UNUSED,
1129                          const char **functionname_ptr ATTRIBUTE_UNUSED,
1130                          unsigned int *line_ptr ATTRIBUTE_UNUSED)
1131 {
1132   return FALSE;
1133 }
1134
1135 static int
1136 oasys_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
1137 {
1138   oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1139
1140   if (mod == NULL)
1141     {
1142       bfd_set_error (bfd_error_invalid_operation);
1143       return -1;
1144     }
1145
1146   buf->st_size = mod->size;
1147   buf->st_mode = 0666;
1148   return 0;
1149 }
1150
1151 static int
1152 oasys_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean exec ATTRIBUTE_UNUSED)
1153 {
1154   return 0;
1155 }
1156
1157 #define oasys_close_and_cleanup                    _bfd_generic_close_and_cleanup
1158 #define oasys_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
1159 #define oasys_slurp_armap                          bfd_true
1160 #define oasys_slurp_extended_name_table            bfd_true
1161 #define oasys_construct_extended_name_table        ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_true)
1162 #define oasys_truncate_arname                      bfd_dont_truncate_arname
1163 #define oasys_write_armap                          ((bfd_boolean (*) (bfd *, unsigned int, struct orl *, unsigned int, int)) bfd_true)
1164 #define oasys_read_ar_hdr                          bfd_nullvoidptr
1165 #define oasys_get_elt_at_index                     _bfd_generic_get_elt_at_index
1166 #define oasys_update_armap_timestamp               bfd_true
1167 #define oasys_bfd_is_local_label_name              bfd_generic_is_local_label_name
1168 #define oasys_bfd_is_target_special_symbol         ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
1169 #define oasys_get_lineno                           _bfd_nosymbols_get_lineno
1170 #define oasys_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
1171 #define oasys_read_minisymbols                     _bfd_generic_read_minisymbols
1172 #define oasys_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
1173 #define oasys_bfd_reloc_type_lookup                _bfd_norelocs_bfd_reloc_type_lookup
1174 #define oasys_set_arch_mach                        bfd_default_set_arch_mach
1175 #define oasys_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
1176 #define oasys_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
1177 #define oasys_bfd_relax_section                    bfd_generic_relax_section
1178 #define oasys_bfd_gc_sections                      bfd_generic_gc_sections
1179 #define oasys_bfd_merge_sections                   bfd_generic_merge_sections
1180 #define oasys_bfd_is_group_section                 bfd_generic_is_group_section
1181 #define oasys_bfd_discard_group                    bfd_generic_discard_group
1182 #define oasys_section_already_linked               _bfd_generic_section_already_linked
1183 #define oasys_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
1184 #define oasys_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
1185 #define oasys_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
1186 #define oasys_bfd_link_just_syms                   _bfd_generic_link_just_syms
1187 #define oasys_bfd_final_link                       _bfd_generic_final_link
1188 #define oasys_bfd_link_split_section               _bfd_generic_link_split_section
1189
1190 const bfd_target oasys_vec =
1191 {
1192   "oasys",                      /* Name.  */
1193   bfd_target_oasys_flavour,
1194   BFD_ENDIAN_BIG,               /* Target byte order.  */
1195   BFD_ENDIAN_BIG,               /* Target headers byte order.  */
1196   (HAS_RELOC | EXEC_P |         /* Object flags.  */
1197    HAS_LINENO | HAS_DEBUG |
1198    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1199   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1200    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
1201   0,                            /* Leading underscore.  */
1202   ' ',                          /* AR_pad_char.  */
1203   16,                           /* AR_max_namelen.  */
1204   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1205   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1206   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Data.  */
1207   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1208   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1209   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Headers.  */
1210
1211   {_bfd_dummy_target,
1212    oasys_object_p,              /* bfd_check_format.  */
1213    oasys_archive_p,
1214    _bfd_dummy_target,
1215   },
1216   {                             /* bfd_set_format.  */
1217     bfd_false,
1218     oasys_mkobject,
1219     _bfd_generic_mkarchive,
1220     bfd_false
1221   },
1222   {                             /* bfd_write_contents.  */
1223     bfd_false,
1224     oasys_write_object_contents,
1225     _bfd_write_archive_contents,
1226     bfd_false,
1227   },
1228
1229   BFD_JUMP_TABLE_GENERIC (oasys),
1230   BFD_JUMP_TABLE_COPY (_bfd_generic),
1231   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1232   BFD_JUMP_TABLE_ARCHIVE (oasys),
1233   BFD_JUMP_TABLE_SYMBOLS (oasys),
1234   BFD_JUMP_TABLE_RELOCS (oasys),
1235   BFD_JUMP_TABLE_WRITE (oasys),
1236   BFD_JUMP_TABLE_LINK (oasys),
1237   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1238
1239   NULL,
1240
1241   NULL
1242 };