update copyright dates
[platform/upstream/binutils.git] / bfd / coff-sh.c
1 /* BFD back-end for Hitachi Super-H COFF binaries.
2    Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
3    Contributed by Cygnus Support.
4    Written by Steve Chamberlain, <sac@cygnus.com>.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "obstack.h"
25 #include "libbfd.h"
26 #include "bfdlink.h"
27 #include "coff/sh.h"
28 #include "coff/internal.h"
29 #include "libcoff.h"
30
31 static bfd_reloc_status_type sh_reloc();
32
33 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
34
35 /*#define COFF_LONG_FILENAMES*/
36
37 static reloc_howto_type r_imm32 =
38   {R_SH_IMM32,  0, 2, 32, false, 0, 
39      complain_overflow_bitfield, sh_reloc,"r_imm32",    true, 0xffffffff,0xffffffff, false};
40
41
42 #define BADMAG(x) SHBADMAG(x)
43 #define SH 1                    /* Customize coffcode.h */
44
45 #define __A_MAGIC_SET__
46
47 /* Code to swap in the reloc */
48 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
49   dst->r_stuff[0] = 'S'; \
50   dst->r_stuff[1] = 'C';
51
52 /* Code to turn a r_type into a howto ptr, uses the above howto table.  */
53 static long
54 get_symbol_value (symbol)       
55      asymbol *symbol;
56 {                                             
57   long relocation = 0;
58
59   if (bfd_is_com_section (symbol->section))
60   {
61     relocation = 0;                           
62   }
63   else 
64   {                                      
65     relocation = symbol->value +
66      symbol->section->output_section->vma +
67       symbol->section->output_offset;
68   }                                           
69
70   return(relocation);
71 }
72
73 #define RTYPE2HOWTO(x,y) ((x)->howto = &r_imm32)
74
75
76 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
77    the object file contains the value of the common symbol.  By the
78    time this is called, the linker may be using a different symbol
79    from a different object file with a different value.  Therefore, we
80    hack wildly to locate the original symbol from this file so that we
81    can make the correct adjustment.  This macro sets coffsym to the
82    symbol from the original file, and uses it to set the addend value
83    correctly.  If this is not a common symbol, the usual addend
84    calculation is done, except that an additional tweak is needed for
85    PC relative relocs.
86    FIXME: This macro refers to symbols and asect; these are from the
87    calling function, not the macro arguments.  */
88
89 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
90   {                                                             \
91     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
92     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
93       coffsym = (obj_symbols (abfd)                             \
94                  + (cache_ptr->sym_ptr_ptr - symbols));         \
95     else if (ptr)                                               \
96       coffsym = coff_symbol_from (abfd, ptr);                   \
97     if (coffsym != (coff_symbol_type *) NULL                    \
98         && coffsym->native->u.syment.n_scnum == 0)              \
99       cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
100     else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
101              && ptr->section != (asection *) NULL)              \
102       cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
103     else                                                        \
104       cache_ptr->addend = 0;                                    \
105   }
106
107 /* this function is in charge of performing all the 29k relocations */
108
109 static bfd_reloc_status_type
110 sh_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
111             error_message)
112      bfd *abfd;
113      arelent *reloc_entry;
114      asymbol *symbol_in;
115      PTR data;
116      asection *input_section;
117      bfd *output_bfd;
118      char **error_message;
119 {
120   /* the consth relocation comes in two parts, we have to remember
121      the state between calls, in these variables */
122   unsigned long insn;
123   unsigned long sym_value;
124   unsigned short r_type;
125
126   unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/
127   bfd_byte  *hit_data =addr + (bfd_byte *)(data);
128         
129   r_type = reloc_entry->howto->type;
130
131   if (output_bfd) {
132     /* Partial linking - do nothing */
133     reloc_entry->address += input_section->output_offset;
134     return bfd_reloc_ok;
135   }
136
137   if (symbol_in != NULL
138       && bfd_is_und_section (symbol_in->section))
139     {
140       /* Keep the state machine happy in case we're called again */
141       return (bfd_reloc_undefined);
142     }
143
144
145   sym_value = get_symbol_value(symbol_in);
146
147   switch (r_type) 
148     {
149     case R_SH_IMM32:
150       insn = sym_value + reloc_entry->addend;  
151       insn += bfd_get_32 (abfd, hit_data);
152       bfd_put_32(abfd, insn, hit_data);
153       break;
154     default:
155       *error_message = "Unrecognized reloc";
156       return (bfd_reloc_dangerous);
157     }
158
159
160   return(bfd_reloc_ok); 
161 }
162
163 /* The reloc processing routine for the optimized COFF linker.  */
164
165 static boolean
166 coff_sh_relocate_section (output_bfd, info, input_bfd, input_section,
167                             contents, relocs, syms, sections)
168      bfd *output_bfd;
169      struct bfd_link_info *info;
170      bfd *input_bfd;
171      asection *input_section;
172      bfd_byte *contents;
173      struct internal_reloc *relocs;
174      struct internal_syment *syms;
175      asection **sections;
176 {
177   struct internal_reloc *rel;
178   struct internal_reloc *relend;
179
180   /* If we are performing a relocateable link, we don't need to do a
181      thing.  The caller will take care of adjusting the reloc
182      addresses and symbol indices.  */
183   if (info->relocateable)
184     return true;
185
186
187   rel = relocs;
188   relend = rel + input_section->reloc_count;
189   for (; rel < relend; rel++)
190     {
191       long symndx;
192       bfd_byte *loc;
193       struct coff_link_hash_entry *h;
194       struct internal_syment *sym;
195       asection *sec;
196       bfd_vma val;
197
198       symndx = rel->r_symndx;
199       loc = contents + rel->r_vaddr - input_section->vma;
200
201       if (symndx == -1)
202         h = NULL;
203       else
204         h = obj_coff_sym_hashes (input_bfd)[symndx];
205
206       sym = NULL;
207       sec = NULL;
208       val = 0;
209
210
211       if (h == NULL)
212         {
213           if (symndx == -1)
214             sec = bfd_abs_section_ptr;
215           else
216             {
217               sym = syms + symndx;
218               sec = sections[symndx];
219               val = (sec->output_section->vma
220                      + sec->output_offset
221                      + sym->n_value
222                      - sec->vma);
223             }
224         }
225       else
226         {
227           if (h->root.type == bfd_link_hash_defined)
228             {
229               sec = h->root.u.def.section;
230               val = (h->root.u.def.value
231                      + sec->output_section->vma
232                      + sec->output_offset);
233             }
234           else
235             {
236               if (! ((*info->callbacks->undefined_symbol)
237                      (info, h->root.root.string, input_bfd, input_section,
238                       rel->r_vaddr - input_section->vma)))
239                 return false;
240             }
241         }
242
243       switch (rel->r_type)
244         {
245         default:
246           bfd_set_error (bfd_error_bad_value);
247           return false;
248
249         case R_SH_IMM32:
250           {
251             long x = bfd_get_32 (input_bfd, loc);
252             x += val;
253             bfd_put_32 (input_bfd, x, loc);
254
255           }
256
257           break;
258         }
259     }     
260
261   return true;
262 }
263
264 #define coff_relocate_section coff_sh_relocate_section
265 #include "coffcode.h"
266
267 const bfd_target shcoff_vec =
268 {
269   "coff-sh",                    /* name */
270   bfd_target_coff_flavour,
271   true,                         /* data byte order is big */
272   true,                         /* header byte order is big */
273
274   (HAS_RELOC | EXEC_P |         /* object flags */
275    HAS_LINENO | HAS_DEBUG |
276    HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
277
278   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),        /* section flags */
279   '_',                          /* leading symbol underscore */
280   '/',                          /* ar_pad_char */
281   15,                           /* ar_max_namelen */
282   2,                            /* minimum section alignment */
283      bfd_getb64, bfd_getb_signed_64, bfd_putb64,
284      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
285      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
286      bfd_getb64, bfd_getb_signed_64, bfd_putb64,
287      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
288      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
289
290   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
291      bfd_generic_archive_p, _bfd_dummy_target},
292   {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
293      bfd_false},
294   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
295      _bfd_write_archive_contents, bfd_false},
296
297      BFD_JUMP_TABLE_GENERIC (coff),
298      BFD_JUMP_TABLE_COPY (coff),
299      BFD_JUMP_TABLE_CORE (_bfd_nocore),
300      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
301      BFD_JUMP_TABLE_SYMBOLS (coff),
302      BFD_JUMP_TABLE_RELOCS (coff),
303      BFD_JUMP_TABLE_WRITE (coff),
304      BFD_JUMP_TABLE_LINK (coff),
305      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
306
307     COFF_SWAP_TABLE,
308 };
309
310 const bfd_target shlcoff_vec =
311 {
312   "coff-shl",                   /* name */
313   bfd_target_coff_flavour,
314   false,                        /* data byte order is little */
315   false,                        /* header byte order is little endian too*/
316
317   (HAS_RELOC | EXEC_P |         /* object flags */
318    HAS_LINENO | HAS_DEBUG |
319    HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
320
321   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),        /* section flags */
322   '_',                          /* leading symbol underscore */
323   '/',                          /* ar_pad_char */
324   15,                           /* ar_max_namelen */
325   2,                            /* minimum section alignment */
326      bfd_getl64, bfd_getl_signed_64, bfd_putl64,
327      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
328      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
329      bfd_getl64, bfd_getl_signed_64, bfd_putl64,
330      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
331      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
332
333 /* Note that we use a special archive recognizer.
334    This is so that we only use one archive format for both
335    object file types */
336   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
337      _bfd_dummy_target, _bfd_dummy_target},   
338   {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
339      bfd_false},
340   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
341      _bfd_write_archive_contents, bfd_false},
342
343      BFD_JUMP_TABLE_GENERIC (coff),
344      BFD_JUMP_TABLE_COPY (coff),
345      BFD_JUMP_TABLE_CORE (_bfd_nocore),
346      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
347      BFD_JUMP_TABLE_SYMBOLS (coff),
348      BFD_JUMP_TABLE_RELOCS (coff),
349      BFD_JUMP_TABLE_WRITE (coff),
350      BFD_JUMP_TABLE_LINK (coff),
351      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
352
353     COFF_SWAP_TABLE,
354 };
355