Applied Michael's Sokolov's patch to implement --embedded-relocs for m68k coff.
[platform/upstream/binutils.git] / bfd / coff-m68k.c
1 /* BFD back-end for Motorola 68000 COFF binaries.
2    Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 99, 2000
3    Free Software Foundation, Inc.
4    Written by Cygnus Support.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "coff/m68k.h"
26 #include "coff/internal.h"
27 #include "libcoff.h"
28
29 /* This source file is compiled multiple times for various m68k COFF
30    variants.  The following macros control its behaviour:
31
32    TARGET_SYM
33      The C name of the BFD target vector.  The default is m68kcoff_vec.
34    TARGET_NAME
35      The user visible target name.  The default is "coff-m68k".
36    NAMES_HAVE_UNDERSCORE
37      Whether symbol names have an underscore.
38    ONLY_DECLARE_RELOCS
39      Only declare the relocation howto array.  Don't actually compile
40      it.  The actual array will be picked up in another version of the
41      file.
42    STATIC_RELOCS
43      Make the relocation howto array, and associated functions, static.
44    COFF_COMMON_ADDEND
45      If this is defined, then, for a relocation against a common
46      symbol, the object file holds the value (the size) of the common
47      symbol.  If this is not defined, then, for a relocation against a
48      common symbol, the object file holds zero.  */
49
50 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
51
52 #ifndef COFF_PAGE_SIZE
53 /* The page size is a guess based on ELF.  */
54 #define COFF_PAGE_SIZE 0x2000
55 #endif
56
57 #ifndef COFF_COMMON_ADDEND
58 #define RELOC_SPECIAL_FN 0
59 #else
60 static bfd_reloc_status_type m68kcoff_common_addend_special_fn
61   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
62 static reloc_howto_type *m68kcoff_common_addend_rtype_to_howto
63   PARAMS ((bfd *, asection *, struct internal_reloc *,
64            struct coff_link_hash_entry *, struct internal_syment *,
65            bfd_vma *));
66 #define RELOC_SPECIAL_FN m68kcoff_common_addend_special_fn
67 #endif
68
69 static boolean m68k_coff_is_local_label_name PARAMS ((bfd *, const char *));
70
71 /* On the delta, a symbol starting with L% is local.  We won't see
72    such a symbol on other platforms, so it should be safe to always
73    consider it local here.  */
74
75 static boolean
76 m68k_coff_is_local_label_name (abfd, name)
77      bfd *abfd;
78      const char *name;
79 {
80   if (name[0] == 'L' && name[1] == '%')
81     return true;
82
83   return _bfd_coff_is_local_label_name (abfd, name);
84 }
85
86 #ifndef STATIC_RELOCS
87 /* Clean up namespace.  */
88 #define m68kcoff_howto_table    _bfd_m68kcoff_howto_table
89 #define m68k_rtype2howto        _bfd_m68kcoff_rtype2howto
90 #define m68k_howto2rtype        _bfd_m68kcoff_howto2rtype
91 #define m68k_reloc_type_lookup  _bfd_m68kcoff_reloc_type_lookup
92 #endif
93
94 #ifdef ONLY_DECLARE_RELOCS
95 extern reloc_howto_type m68kcoff_howto_table[];
96 #else
97 #ifdef STATIC_RELOCS
98 static
99 #endif
100 reloc_howto_type m68kcoff_howto_table[] = 
101 {
102   HOWTO(R_RELBYTE,             0,  0,   8,  false, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "8",        true, 0x000000ff,0x000000ff, false),
103   HOWTO(R_RELWORD,             0,  1,   16, false, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "16",       true, 0x0000ffff,0x0000ffff, false),
104   HOWTO(R_RELLONG,             0,  2,   32, false, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "32",       true, 0xffffffff,0xffffffff, false),
105   HOWTO(R_PCRBYTE,             0,  0,   8,  true,  0, complain_overflow_signed, RELOC_SPECIAL_FN, "DISP8",    true, 0x000000ff,0x000000ff, false),
106   HOWTO(R_PCRWORD,             0,  1,   16, true,  0, complain_overflow_signed, RELOC_SPECIAL_FN, "DISP16",   true, 0x0000ffff,0x0000ffff, false),
107   HOWTO(R_PCRLONG,             0,  2,   32, true,  0, complain_overflow_signed, RELOC_SPECIAL_FN, "DISP32",   true, 0xffffffff,0xffffffff, false),
108   HOWTO(R_RELLONG_NEG,         0,  -2,  32, false, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "-32",      true, 0xffffffff,0xffffffff, false),
109 };
110 #endif /* not ONLY_DECLARE_RELOCS */
111
112 #ifndef BADMAG
113 #define BADMAG(x) M68KBADMAG(x)
114 #endif
115 #define M68 1           /* Customize coffcode.h */
116
117 /* Turn a howto into a reloc number */
118
119 #ifdef ONLY_DECLARE_RELOCS
120 extern void m68k_rtype2howto PARAMS ((arelent *internal, int relocentry));
121 extern int m68k_howto2rtype PARAMS ((reloc_howto_type *));
122 extern reloc_howto_type *m68k_reloc_type_lookup
123   PARAMS ((bfd *, bfd_reloc_code_real_type));
124 #else
125 #ifdef STATIC_RELOCS
126 static
127 #endif
128 void
129 m68k_rtype2howto(internal, relocentry)
130      arelent *internal;
131      int relocentry;
132 {
133   switch (relocentry) 
134   {
135    case R_RELBYTE:      internal->howto = m68kcoff_howto_table + 0; break;
136    case R_RELWORD:      internal->howto = m68kcoff_howto_table + 1; break;
137    case R_RELLONG:      internal->howto = m68kcoff_howto_table + 2; break;
138    case R_PCRBYTE:      internal->howto = m68kcoff_howto_table + 3; break;
139    case R_PCRWORD:      internal->howto = m68kcoff_howto_table + 4; break;
140    case R_PCRLONG:      internal->howto = m68kcoff_howto_table + 5; break;
141    case R_RELLONG_NEG:  internal->howto = m68kcoff_howto_table + 6; break;
142   }
143 }
144
145 #ifdef STATIC_RELOCS
146 static
147 #endif
148 int 
149 m68k_howto2rtype (internal)
150      reloc_howto_type *internal;
151 {
152   if (internal->pc_relative) 
153   {
154     switch (internal->bitsize) 
155     {
156      case 32: return R_PCRLONG;
157      case 16: return R_PCRWORD;
158      case 8: return R_PCRBYTE;
159     }
160   }
161   else 
162   {
163     switch (internal->bitsize) 
164      {
165       case 32: return R_RELLONG;
166       case 16: return R_RELWORD;
167       case 8: return R_RELBYTE;
168      }
169   }
170   return R_RELLONG;    
171 }
172
173 #ifdef STATIC_RELOCS
174 static
175 #endif
176 reloc_howto_type *
177 m68k_reloc_type_lookup (abfd, code)
178      bfd *abfd ATTRIBUTE_UNUSED;
179      bfd_reloc_code_real_type code;
180 {
181   switch (code)
182     {
183     default:                    return NULL;
184     case BFD_RELOC_8:           return m68kcoff_howto_table + 0;
185     case BFD_RELOC_16:          return m68kcoff_howto_table + 1;
186     case BFD_RELOC_CTOR:
187     case BFD_RELOC_32:          return m68kcoff_howto_table + 2;
188     case BFD_RELOC_8_PCREL:     return m68kcoff_howto_table + 3;
189     case BFD_RELOC_16_PCREL:    return m68kcoff_howto_table + 4;
190     case BFD_RELOC_32_PCREL:    return m68kcoff_howto_table + 5;
191       /* FIXME: There doesn't seem to be a code for R_RELLONG_NEG.  */
192     }
193   /*NOTREACHED*/
194 }
195
196 #endif /* not ONLY_DECLARE_RELOCS */
197
198 #define RTYPE2HOWTO(internal, relocentry) \
199   m68k_rtype2howto(internal, (relocentry)->r_type)
200
201 #define SELECT_RELOC(external, internal) \
202   external.r_type = m68k_howto2rtype (internal)
203
204 #define coff_bfd_reloc_type_lookup m68k_reloc_type_lookup
205
206 #ifndef COFF_COMMON_ADDEND
207 #ifndef coff_rtype_to_howto
208
209 #define coff_rtype_to_howto m68kcoff_rtype_to_howto
210
211 static reloc_howto_type *m68kcoff_rtype_to_howto
212   PARAMS ((bfd *, asection *, struct internal_reloc *,
213            struct coff_link_hash_entry *, struct internal_syment *,
214            bfd_vma *));
215
216 /*ARGSUSED*/
217 static reloc_howto_type *
218 m68kcoff_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
219      bfd *abfd ATTRIBUTE_UNUSED;
220      asection *sec;
221      struct internal_reloc *rel;
222      struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
223      struct internal_syment *sym ATTRIBUTE_UNUSED;
224      bfd_vma *addendp;
225 {
226   arelent relent;
227   reloc_howto_type *howto;
228
229   RTYPE2HOWTO (&relent, rel);
230
231   howto = relent.howto;
232
233   if (howto->pc_relative)
234     *addendp += sec->vma;
235
236   return howto;
237 }
238
239 #endif /* ! defined (coff_rtype_to_howto) */
240 #endif /* ! defined (COFF_COMMON_ADDEND) */
241 \f
242 #ifdef COFF_COMMON_ADDEND
243
244 /* If COFF_COMMON_ADDEND is defined, then when using m68k COFF the
245    value stored in the .text section for a reference to a common
246    symbol is the value itself plus any desired offset.  (taken from
247    work done by Ian Taylor, Cygnus Support, for I386 COFF).  */
248
249 /* If we are producing relocateable output, we need to do some
250    adjustments to the object file that are not done by the
251    bfd_perform_relocation function.  This function is called by every
252    reloc type to make any required adjustments.  */
253
254 static bfd_reloc_status_type
255 m68kcoff_common_addend_special_fn (abfd, reloc_entry, symbol, data,
256                                    input_section, output_bfd, error_message)
257      bfd *abfd;
258      arelent *reloc_entry;
259      asymbol *symbol;
260      PTR data;
261      asection *input_section ATTRIBUTE_UNUSED;
262      bfd *output_bfd;
263      char **error_message ATTRIBUTE_UNUSED;
264 {
265   symvalue diff;
266
267   if (output_bfd == (bfd *) NULL)
268     return bfd_reloc_continue;
269
270   if (bfd_is_com_section (symbol->section))
271     {
272       /* We are relocating a common symbol.  The current value in the
273          object file is ORIG + OFFSET, where ORIG is the value of the
274          common symbol as seen by the object file when it was compiled
275          (this may be zero if the symbol was undefined) and OFFSET is
276          the offset into the common symbol (normally zero, but may be
277          non-zero when referring to a field in a common structure).
278          ORIG is the negative of reloc_entry->addend, which is set by
279          the CALC_ADDEND macro below.  We want to replace the value in
280          the object file with NEW + OFFSET, where NEW is the value of
281          the common symbol which we are going to put in the final
282          object file.  NEW is symbol->value.  */
283       diff = symbol->value + reloc_entry->addend;
284     }
285   else
286     {
287       /* For some reason bfd_perform_relocation always effectively
288          ignores the addend for a COFF target when producing
289          relocateable output.  This seems to be always wrong for 386
290          COFF, so we handle the addend here instead.  */
291       diff = reloc_entry->addend;
292     }
293
294 #define DOIT(x) \
295   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
296
297   if (diff != 0)
298     {
299       reloc_howto_type *howto = reloc_entry->howto;
300       unsigned char *addr = (unsigned char *) data + reloc_entry->address;
301
302       switch (howto->size)
303         {
304         case 0:
305           {
306             char x = bfd_get_8 (abfd, addr);
307             DOIT (x);
308             bfd_put_8 (abfd, x, addr);
309           }
310           break;
311
312         case 1:
313           {
314             short x = bfd_get_16 (abfd, addr);
315             DOIT (x);
316             bfd_put_16 (abfd, x, addr);
317           }
318           break;
319
320         case 2:
321           {
322             long x = bfd_get_32 (abfd, addr);
323             DOIT (x);
324             bfd_put_32 (abfd, x, addr);
325           }
326           break;
327
328         default:
329           abort ();
330         }
331     }
332
333   /* Now let bfd_perform_relocation finish everything up.  */
334   return bfd_reloc_continue;
335 }
336
337 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
338    the object file contains the value of the common symbol.  By the
339    time this is called, the linker may be using a different symbol
340    from a different object file with a different value.  Therefore, we
341    hack wildly to locate the original symbol from this file so that we
342    can make the correct adjustment.  This macro sets coffsym to the
343    symbol from the original file, and uses it to set the addend value
344    correctly.  If this is not a common symbol, the usual addend
345    calculation is done, except that an additional tweak is needed for
346    PC relative relocs.
347    FIXME: This macro refers to symbols and asect; these are from the
348    calling function, not the macro arguments.  */
349
350 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
351   {                                                             \
352     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
353     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
354       coffsym = (obj_symbols (abfd)                             \
355                  + (cache_ptr->sym_ptr_ptr - symbols));         \
356     else if (ptr)                                               \
357       coffsym = coff_symbol_from (abfd, ptr);                   \
358     if (coffsym != (coff_symbol_type *) NULL                    \
359         && coffsym->native->u.syment.n_scnum == 0)              \
360       cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
361     else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
362              && ptr->section != (asection *) NULL)              \
363       cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
364     else                                                        \
365       cache_ptr->addend = 0;                                    \
366     if (ptr && (reloc.r_type == R_PCRBYTE                       \
367                 || reloc.r_type == R_PCRWORD                    \
368                 || reloc.r_type == R_PCRLONG))                  \
369       cache_ptr->addend += asect->vma;                          \
370   }
371
372 #ifndef coff_rtype_to_howto
373
374 /* coff-m68k.c uses the special COFF backend linker.  We need to
375    adjust common symbols.  */
376
377 /*ARGSUSED*/
378 static reloc_howto_type *
379 m68kcoff_common_addend_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
380      bfd *abfd ATTRIBUTE_UNUSED;
381      asection *sec;
382      struct internal_reloc *rel;
383      struct coff_link_hash_entry *h;
384      struct internal_syment *sym;
385      bfd_vma *addendp;
386 {
387   arelent relent;
388   reloc_howto_type *howto;
389
390   RTYPE2HOWTO (&relent, rel);
391
392   howto = relent.howto;
393
394   if (howto->pc_relative)
395     *addendp += sec->vma;
396
397   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
398     {
399       /* This is a common symbol.  The section contents include the
400          size (sym->n_value) as an addend.  The relocate_section
401          function will be adding in the final value of the symbol.  We
402          need to subtract out the current size in order to get the
403          correct result.  */
404       BFD_ASSERT (h != NULL);
405       *addendp -= sym->n_value;
406     }
407
408   /* If the output symbol is common (in which case this must be a
409      relocateable link), we need to add in the final size of the
410      common symbol.  */
411   if (h != NULL && h->root.type == bfd_link_hash_common)
412     *addendp += h->root.u.c.size;
413
414   return howto;
415 }
416
417 #define coff_rtype_to_howto m68kcoff_common_addend_rtype_to_howto
418
419 #endif /* ! defined (coff_rtype_to_howto) */
420
421 #endif /* COFF_COMMON_ADDEND */
422
423 #if !defined ONLY_DECLARE_RELOCS && ! defined STATIC_RELOCS
424 /* Given a .data section and a .emreloc in-memory section, store
425    relocation information into the .emreloc section which can be
426    used at runtime to relocate the section.  This is called by the
427    linker when the --embedded-relocs switch is used.  This is called
428    after the add_symbols entry point has been called for all the
429    objects, and before the final_link entry point is called.  */
430
431 boolean
432 bfd_m68k_coff_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
433      bfd *abfd;
434      struct bfd_link_info *info;
435      asection *datasec;
436      asection *relsec;
437      char **errmsg;
438 {
439   char *extsyms;
440   bfd_size_type symesz;
441   struct internal_reloc *irel, *irelend;
442   bfd_byte *p;
443
444   BFD_ASSERT (! info->relocateable);
445
446   *errmsg = NULL;
447
448   if (datasec->reloc_count == 0)
449     return true;
450
451   extsyms = obj_coff_external_syms (abfd);
452   symesz = bfd_coff_symesz (abfd);
453
454   irel = _bfd_coff_read_internal_relocs (abfd, datasec, true, NULL, false,
455                                          NULL);
456   irelend = irel + datasec->reloc_count;
457
458   relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12);
459   if (relsec->contents == NULL)
460     return false;
461
462   p = relsec->contents;
463
464   for (; irel < irelend; irel++, p += 12)
465     {
466       asection *targetsec;
467
468       /* We are going to write a four byte longword into the runtime
469        reloc section.  The longword will be the address in the data
470        section which must be relocated.  It is followed by the name
471        of the target section NUL-padded or truncated to 8
472        characters.  */
473
474       /* We can only relocate absolute longword relocs at run time.  */
475       if (irel->r_type != R_RELLONG)
476         {
477           *errmsg = _("unsupported reloc type");
478           bfd_set_error (bfd_error_bad_value);
479           return false;
480         }
481
482       if (irel->r_symndx == -1)
483         targetsec = bfd_abs_section_ptr;
484       else
485         {
486           struct coff_link_hash_entry *h;
487           
488           h = obj_coff_sym_hashes (abfd)[irel->r_symndx];
489           if (h == NULL)
490             {
491               struct internal_syment isym;
492               
493               bfd_coff_swap_sym_in (abfd, extsyms + symesz * irel->r_symndx,
494                                     &isym);
495               targetsec = coff_section_from_bfd_index (abfd, isym.n_scnum);
496             }
497           else if (h->root.type == bfd_link_hash_defined
498                    || h->root.type == bfd_link_hash_defweak)
499             targetsec = h->root.u.def.section;
500           else
501             targetsec = NULL;
502         }
503       
504       bfd_put_32 (abfd,
505                   (irel->r_vaddr - datasec->vma + datasec->output_offset), p);
506       memset (p + 4, 0, 8);
507       strncpy (p + 4, targetsec->output_section->name, 8);
508     }
509   
510   return true;
511 }
512 #endif /* neither ONLY_DECLARE_RELOCS not STATIC_RELOCS  */
513 \f
514 #define coff_bfd_is_local_label_name m68k_coff_is_local_label_name
515
516 #define coff_relocate_section _bfd_coff_generic_relocate_section
517
518 #include "coffcode.h"
519
520 #ifndef TARGET_SYM
521 #define TARGET_SYM m68kcoff_vec
522 #endif
523
524 #ifndef TARGET_NAME
525 #define TARGET_NAME "coff-m68k"
526 #endif
527
528 #ifdef NAMES_HAVE_UNDERSCORE
529 CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, '_', NULL)
530 #else
531 CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, 0, NULL)
532 #endif