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