bfd/
[external/binutils.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, 2006 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   if (!newsect->used_by_bfd)
689     {
690       newsect->used_by_bfd
691         = bfd_alloc (abfd, (bfd_size_type) sizeof (oasys_per_section_type));
692       if (!newsect->used_by_bfd)
693         return FALSE;
694     }
695   oasys_per_section (newsect)->data = NULL;
696   oasys_per_section (newsect)->section = newsect;
697   oasys_per_section (newsect)->offset = 0;
698   oasys_per_section (newsect)->initialized = FALSE;
699   newsect->alignment_power = 1;
700
701   /* Turn the section string into an index.  */
702   sscanf (newsect->name, "%u", &newsect->target_index);
703
704   return _bfd_generic_new_section_hook (abfd, newsect);
705 }
706
707
708 static long
709 oasys_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
710 {
711   if (! oasys_slurp_section_data (abfd))
712     return -1;
713   return (asect->reloc_count + 1) * sizeof (arelent *);
714 }
715
716 static bfd_boolean
717 oasys_get_section_contents (bfd *abfd,
718                             sec_ptr section,
719                             void * location,
720                             file_ptr offset,
721                             bfd_size_type count)
722 {
723   oasys_per_section_type *p = oasys_per_section (section);
724
725   oasys_slurp_section_data (abfd);
726
727   if (! p->initialized)
728     (void) memset (location, 0, (size_t) count);
729   else
730     (void) memcpy (location, (void *) (p->data + offset), (size_t) count);
731
732   return TRUE;
733 }
734
735 static long
736 oasys_canonicalize_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
737                           sec_ptr section,
738                           arelent **relptr,
739                           asymbol **symbols ATTRIBUTE_UNUSED)
740 {
741   unsigned int reloc_count = 0;
742   oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
743
744   if (src != NULL)
745     abort ();
746
747   *relptr = NULL;
748   return section->reloc_count = reloc_count;
749 }
750
751
752 /* Writing.  */
753
754 /* Calculate the checksum and write one record.  */
755
756 static bfd_boolean
757 oasys_write_record (bfd *abfd,
758                     oasys_record_enum_type type,
759                     oasys_record_union_type *record,
760                     size_t size)
761 {
762   int checksum;
763   size_t i;
764   unsigned char *ptr;
765
766   record->header.length = size;
767   record->header.type = (int) type;
768   record->header.check_sum = 0;
769   record->header.fill = 0;
770   ptr = (unsigned char *) &record->pad[0];
771   checksum = 0;
772   for (i = 0; i < size; i++)
773     checksum += *ptr++;
774   record->header.check_sum = 0xff & (-checksum);
775   if (bfd_bwrite ((void *) record, (bfd_size_type) size, abfd) != size)
776     return FALSE;
777   return TRUE;
778 }
779
780
781 /* Write out all the symbols.  */
782
783 static bfd_boolean
784 oasys_write_syms (bfd *abfd)
785 {
786   unsigned int count;
787   asymbol **generic = bfd_get_outsymbols (abfd);
788   unsigned int index = 0;
789
790   for (count = 0; count < bfd_get_symcount (abfd); count++)
791     {
792       oasys_symbol_record_type symbol;
793       asymbol *const g = generic[count];
794       const char *src = g->name;
795       char *dst = symbol.name;
796       unsigned int l = 0;
797
798       if (bfd_is_com_section (g->section))
799         {
800           symbol.relb = RELOCATION_TYPE_COM;
801           H_PUT_16 (abfd, index, symbol.refno);
802           index++;
803         }
804       else if (bfd_is_abs_section (g->section))
805         {
806           symbol.relb = RELOCATION_TYPE_ABS;
807           H_PUT_16 (abfd, 0, symbol.refno);
808         }
809       else if (bfd_is_und_section (g->section))
810         {
811           symbol.relb = RELOCATION_TYPE_UND;
812           H_PUT_16 (abfd, index, symbol.refno);
813           /* Overload the value field with the output index number */
814           index++;
815         }
816       else if (g->flags & BSF_DEBUGGING)
817         /* Throw it away.  */
818         continue;
819       else
820         {
821           if (g->section == NULL)
822             /* Sometime, the oasys tools give out a symbol with illegal
823                bits in it, we'll output it in the same broken way.  */
824             symbol.relb = RELOCATION_TYPE_REL | 0;
825           else
826             symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
827
828           H_PUT_16 (abfd, 0, symbol.refno);
829         }
830
831 #ifdef UNDERSCORE_HACK
832       if (src[l] == '_')
833         dst[l++] = '.';
834 #endif
835       while (src[l])
836         {
837           dst[l] = src[l];
838           l++;
839         }
840
841       H_PUT_32 (abfd, g->value, symbol.value);
842
843       if (g->flags & BSF_LOCAL)
844         {
845           if (! oasys_write_record (abfd,
846                                     oasys_record_is_local_enum,
847                                     (oasys_record_union_type *) & symbol,
848                                     offsetof (oasys_symbol_record_type,
849                                               name[0]) + l))
850             return FALSE;
851         }
852       else
853         {
854           if (! oasys_write_record (abfd,
855                                     oasys_record_is_symbol_enum,
856                                     (oasys_record_union_type *) & symbol,
857                                     offsetof (oasys_symbol_record_type,
858                                               name[0]) + l))
859             return FALSE;
860         }
861       g->value = index - 1;
862     }
863
864   return TRUE;
865 }
866
867 /* Write a section header for each section.  */
868
869 static bfd_boolean
870 oasys_write_sections (bfd *abfd)
871 {
872   asection *s;
873   static oasys_section_record_type out;
874
875   for (s = abfd->sections; s != NULL; s = s->next)
876     {
877       if (!ISDIGIT (s->name[0]))
878         {
879           (*_bfd_error_handler)
880             (_("%s: can not represent section `%s' in oasys"),
881              bfd_get_filename (abfd), s->name);
882           bfd_set_error (bfd_error_nonrepresentable_section);
883           return FALSE;
884         }
885       out.relb = RELOCATION_TYPE_REL | s->target_index;
886       H_PUT_32 (abfd, s->size, out.value);
887       H_PUT_32 (abfd, s->vma, out.vma);
888
889       if (! oasys_write_record (abfd,
890                                 oasys_record_is_section_enum,
891                                 (oasys_record_union_type *) & out,
892                                 sizeof (out)))
893         return FALSE;
894     }
895   return TRUE;
896 }
897
898 static bfd_boolean
899 oasys_write_header (bfd *abfd)
900 {
901   /* Create and write the header.  */
902   oasys_header_record_type r;
903   size_t length = strlen (abfd->filename);
904
905   if (length > (size_t) sizeof (r.module_name))
906     length = sizeof (r.module_name);
907
908   (void) memcpy (r.module_name, abfd->filename, length);
909   (void) memset (r.module_name + length, ' ', sizeof (r.module_name) - length);
910
911   r.version_number = OASYS_VERSION_NUMBER;
912   r.rev_number = OASYS_REV_NUMBER;
913
914   return oasys_write_record (abfd, oasys_record_is_header_enum,
915                              (oasys_record_union_type *) & r,
916                              offsetof (oasys_header_record_type,
917                                        description[0]));
918 }
919
920 static bfd_boolean
921 oasys_write_end (bfd *abfd)
922 {
923   oasys_end_record_type end;
924   unsigned char null = 0;
925
926   end.relb = RELOCATION_TYPE_ABS;
927   H_PUT_32 (abfd, abfd->start_address, end.entry);
928   H_PUT_16 (abfd, 0, end.fill);
929   end.zero = 0;
930   if (! oasys_write_record (abfd,
931                             oasys_record_is_end_enum,
932                             (oasys_record_union_type *) & end,
933                             sizeof (end)))
934     return FALSE;
935
936   return bfd_bwrite ((void *) &null, (bfd_size_type) 1, abfd) == 1;
937 }
938
939 static int
940 comp (const void * ap, const void * bp)
941 {
942   arelent *a = *((arelent **) ap);
943   arelent *b = *((arelent **) bp);
944
945   return a->address - b->address;
946 }
947
948 static bfd_boolean
949 oasys_write_data (bfd *abfd)
950 {
951   asection *s;
952
953   for (s = abfd->sections; s != NULL; s = s->next)
954     {
955       if (s->flags & SEC_LOAD)
956         {
957           bfd_byte *raw_data = oasys_per_section (s)->data;
958           oasys_data_record_type processed_data;
959           bfd_size_type current_byte_index = 0;
960           unsigned int relocs_to_go = s->reloc_count;
961           arelent **p = s->orelocation;
962
963           if (s->reloc_count != 0)
964             /* Sort the reloc records so it's easy to insert the relocs into the
965                data.  */
966             qsort (s->orelocation, s->reloc_count, sizeof (arelent **), comp);
967
968           current_byte_index = 0;
969           processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
970
971           while (current_byte_index < s->size)
972             {
973               /* Scan forwards by eight bytes or however much is left and see if
974                there are any relocations going on.  */
975               bfd_byte *mod = &processed_data.data[0];
976               bfd_byte *dst = &processed_data.data[1];
977
978               unsigned int i = 0;
979               *mod = 0;
980
981               H_PUT_32 (abfd, s->vma + current_byte_index,
982                         processed_data.addr);
983
984               /* Don't start a relocation unless you're sure you can finish it
985                  within the same data record.  The worst case relocation is a
986                  4-byte relocatable value which is split across two modification
987                  bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
988                  1 modification byte + 2 data = 8 bytes total).  That's where
989                  the magic number 8 comes from.  */
990               while (current_byte_index < s->size && dst <=
991                      & processed_data.data[sizeof (processed_data.data) - 8])
992                 {
993                   if (relocs_to_go != 0)
994                     {
995                       arelent *r = *p;
996
997                       /* There is a relocation, is it for this byte ?  */
998                       if (r->address == current_byte_index)
999                         abort ();
1000                     }
1001
1002                   /* If this is coming from an unloadable section then copy
1003                      zeros.  */
1004                   if (raw_data == NULL)
1005                     *dst++ = 0;
1006                   else
1007                     *dst++ = *raw_data++;
1008
1009                   if (++i >= 8)
1010                     {
1011                       i = 0;
1012                       mod = dst++;
1013                       *mod = 0;
1014                     }
1015                   current_byte_index++;
1016                 }
1017
1018               /* Don't write a useless null modification byte.  */
1019               if (dst == mod + 1)
1020                 --dst;
1021
1022               if (! (oasys_write_record
1023                      (abfd, oasys_record_is_data_enum,
1024                       ((oasys_record_union_type *) &processed_data),
1025                       (size_t) (dst - (bfd_byte *) &processed_data))))
1026                 return FALSE;
1027             }
1028         }
1029     }
1030
1031   return TRUE;
1032 }
1033
1034 static bfd_boolean
1035 oasys_write_object_contents (bfd *abfd)
1036 {
1037   if (! oasys_write_header (abfd))
1038     return FALSE;
1039   if (! oasys_write_syms (abfd))
1040     return FALSE;
1041   if (! oasys_write_sections (abfd))
1042     return FALSE;
1043   if (! oasys_write_data (abfd))
1044     return FALSE;
1045   if (! oasys_write_end (abfd))
1046     return FALSE;
1047   return TRUE;
1048 }
1049
1050 /* Set section contents is complicated with OASYS since the format is
1051    not a byte image, but a record stream.  */
1052
1053 static bfd_boolean
1054 oasys_set_section_contents (bfd *abfd,
1055                             sec_ptr section,
1056                             const void * location,
1057                             file_ptr offset,
1058                             bfd_size_type count)
1059 {
1060   if (count != 0)
1061     {
1062       if (oasys_per_section (section)->data == NULL)
1063         {
1064           oasys_per_section (section)->data = bfd_alloc (abfd, section->size);
1065           if (!oasys_per_section (section)->data)
1066             return FALSE;
1067         }
1068       (void) memcpy ((void *) (oasys_per_section (section)->data + offset),
1069                      location, (size_t) count);
1070     }
1071   return TRUE;
1072 }
1073
1074
1075
1076 /* Native-level interface to symbols.  */
1077
1078 /* We read the symbols into a buffer, which is discarded when this
1079    function exits.  We read the strings into a buffer large enough to
1080    hold them all plus all the cached symbol entries.  */
1081
1082 static asymbol *
1083 oasys_make_empty_symbol (bfd *abfd)
1084 {
1085   bfd_size_type amt = sizeof (oasys_symbol_type);
1086   oasys_symbol_type *new = bfd_zalloc (abfd, amt);
1087
1088   if (!new)
1089     return NULL;
1090   new->symbol.the_bfd = abfd;
1091   return &new->symbol;
1092 }
1093
1094 /* User should have checked the file flags; perhaps we should return
1095    BFD_NO_MORE_SYMBOLS if there are none?  */
1096
1097 static bfd *
1098 oasys_openr_next_archived_file (bfd *arch, bfd *prev)
1099 {
1100   oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
1101   oasys_module_info_type *p;
1102
1103   /* Take the next one from the arch state, or reset.  */
1104   if (prev == NULL)
1105     /* Reset the index - the first two entries are bogus.  */
1106     ar->module_index = 0;
1107
1108   p = ar->module + ar->module_index;
1109   ar->module_index++;
1110
1111   if (ar->module_index <= ar->module_count)
1112     {
1113       if (p->abfd == NULL)
1114         {
1115           p->abfd = _bfd_create_empty_archive_element_shell (arch);
1116           p->abfd->origin = p->pos;
1117           p->abfd->filename = p->name;
1118
1119           /* Fixup a pointer to this element for the member.  */
1120           p->abfd->arelt_data = (void *) p;
1121         }
1122       return p->abfd;
1123     }
1124
1125   bfd_set_error (bfd_error_no_more_archived_files);
1126   return NULL;
1127 }
1128
1129 static bfd_boolean
1130 oasys_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED,
1131                          asection *section ATTRIBUTE_UNUSED,
1132                          asymbol **symbols ATTRIBUTE_UNUSED,
1133                          bfd_vma offset ATTRIBUTE_UNUSED,
1134                          const char **filename_ptr ATTRIBUTE_UNUSED,
1135                          const char **functionname_ptr ATTRIBUTE_UNUSED,
1136                          unsigned int *line_ptr ATTRIBUTE_UNUSED)
1137 {
1138   return FALSE;
1139 }
1140
1141 static bfd_boolean
1142 oasys_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED,
1143                          const char **filename_ptr ATTRIBUTE_UNUSED,
1144                          const char **functionname_ptr ATTRIBUTE_UNUSED,
1145                          unsigned int *line_ptr ATTRIBUTE_UNUSED)
1146 {
1147   return FALSE;
1148 }
1149
1150 static int
1151 oasys_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
1152 {
1153   oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
1154
1155   if (mod == NULL)
1156     {
1157       bfd_set_error (bfd_error_invalid_operation);
1158       return -1;
1159     }
1160
1161   buf->st_size = mod->size;
1162   buf->st_mode = 0666;
1163   return 0;
1164 }
1165
1166 static int
1167 oasys_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean exec ATTRIBUTE_UNUSED)
1168 {
1169   return 0;
1170 }
1171
1172 #define oasys_close_and_cleanup                    _bfd_generic_close_and_cleanup
1173 #define oasys_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
1174 #define oasys_slurp_armap                          bfd_true
1175 #define oasys_slurp_extended_name_table            bfd_true
1176 #define oasys_construct_extended_name_table        ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_true)
1177 #define oasys_truncate_arname                      bfd_dont_truncate_arname
1178 #define oasys_write_armap                          ((bfd_boolean (*) (bfd *, unsigned int, struct orl *, unsigned int, int)) bfd_true)
1179 #define oasys_read_ar_hdr                          bfd_nullvoidptr
1180 #define oasys_get_elt_at_index                     _bfd_generic_get_elt_at_index
1181 #define oasys_update_armap_timestamp               bfd_true
1182 #define oasys_bfd_is_local_label_name              bfd_generic_is_local_label_name
1183 #define oasys_bfd_is_target_special_symbol         ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
1184 #define oasys_get_lineno                           _bfd_nosymbols_get_lineno
1185 #define oasys_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
1186 #define oasys_read_minisymbols                     _bfd_generic_read_minisymbols
1187 #define oasys_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
1188 #define oasys_bfd_reloc_type_lookup                _bfd_norelocs_bfd_reloc_type_lookup
1189 #define oasys_set_arch_mach                        bfd_default_set_arch_mach
1190 #define oasys_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
1191 #define oasys_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
1192 #define oasys_bfd_relax_section                    bfd_generic_relax_section
1193 #define oasys_bfd_gc_sections                      bfd_generic_gc_sections
1194 #define oasys_bfd_merge_sections                   bfd_generic_merge_sections
1195 #define oasys_bfd_is_group_section                 bfd_generic_is_group_section
1196 #define oasys_bfd_discard_group                    bfd_generic_discard_group
1197 #define oasys_section_already_linked               _bfd_generic_section_already_linked
1198 #define oasys_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
1199 #define oasys_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
1200 #define oasys_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
1201 #define oasys_bfd_link_just_syms                   _bfd_generic_link_just_syms
1202 #define oasys_bfd_final_link                       _bfd_generic_final_link
1203 #define oasys_bfd_link_split_section               _bfd_generic_link_split_section
1204
1205 const bfd_target oasys_vec =
1206 {
1207   "oasys",                      /* Name.  */
1208   bfd_target_oasys_flavour,
1209   BFD_ENDIAN_BIG,               /* Target byte order.  */
1210   BFD_ENDIAN_BIG,               /* Target headers byte order.  */
1211   (HAS_RELOC | EXEC_P |         /* Object flags.  */
1212    HAS_LINENO | HAS_DEBUG |
1213    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1214   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1215    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
1216   0,                            /* Leading underscore.  */
1217   ' ',                          /* AR_pad_char.  */
1218   16,                           /* AR_max_namelen.  */
1219   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1220   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1221   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Data.  */
1222   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1223   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1224   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Headers.  */
1225
1226   {_bfd_dummy_target,
1227    oasys_object_p,              /* bfd_check_format.  */
1228    oasys_archive_p,
1229    _bfd_dummy_target,
1230   },
1231   {                             /* bfd_set_format.  */
1232     bfd_false,
1233     oasys_mkobject,
1234     _bfd_generic_mkarchive,
1235     bfd_false
1236   },
1237   {                             /* bfd_write_contents.  */
1238     bfd_false,
1239     oasys_write_object_contents,
1240     _bfd_write_archive_contents,
1241     bfd_false,
1242   },
1243
1244   BFD_JUMP_TABLE_GENERIC (oasys),
1245   BFD_JUMP_TABLE_COPY (_bfd_generic),
1246   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1247   BFD_JUMP_TABLE_ARCHIVE (oasys),
1248   BFD_JUMP_TABLE_SYMBOLS (oasys),
1249   BFD_JUMP_TABLE_RELOCS (oasys),
1250   BFD_JUMP_TABLE_WRITE (oasys),
1251   BFD_JUMP_TABLE_LINK (oasys),
1252   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1253
1254   NULL,
1255
1256   NULL
1257 };