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