This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / bfd / coff-go32.c
1 /* BFD back-end for Intel 386 COFF files (go32 variant).
2    Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3    Written by DJ Delorie.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "obstack.h"
25 #include "coff/i386.h"
26 #include "coff/internal.h"
27 #include "libcoff.h"
28
29 static bfd_reloc_status_type coff_go32_reloc PARAMS ((bfd *abfd,
30                                                       arelent *reloc_entry,
31                                                       asymbol *symbol,
32                                                       PTR data,
33                                                       asection *input_section,
34                                                       bfd *output_bfd,
35                                                       char **error_message));
36
37 /* For some reason when using i386 COFF the value stored in the .text
38    section for a reference to a common symbol is the value itself plus
39    any desired offset.  Ian Taylor, Cygnus Support.  */
40
41 /* If we are producing relocateable output, we need to do some
42    adjustments to the object file that are not done by the
43    bfd_perform_relocation function.  This function is called by every
44    reloc type to make any required adjustments.  */
45
46 static bfd_reloc_status_type
47 coff_go32_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
48                  error_message)
49      bfd *abfd;
50      arelent *reloc_entry;
51      asymbol *symbol;
52      PTR data;
53      asection *input_section;
54      bfd *output_bfd;
55      char **error_message;
56 {
57   symvalue diff;
58
59   if (output_bfd == (bfd *) NULL)
60     return bfd_reloc_continue;
61
62   if (bfd_is_com_section (symbol->section))
63     {
64       /* We are relocating a common symbol.  The current value in the
65          object file is ORIG + OFFSET, where ORIG is the value of the
66          common symbol as seen by the object file when it was compiled
67          (this may be zero if the symbol was undefined) and OFFSET is
68          the offset into the common symbol (normally zero, but may be
69          non-zero when referring to a field in a common structure).
70          ORIG is the negative of reloc_entry->addend, which is set by
71          the CALC_ADDEND macro below.  We want to replace the value in
72          the object file with NEW + OFFSET, where NEW is the value of
73          the common symbol which we are going to put in the final
74          object file.  NEW is symbol->value.  */
75       diff = symbol->value + reloc_entry->addend;
76     }
77   else
78     {
79       /* For some reason bfd_perform_relocation always effectively
80          ignores the addend for a COFF target when producing
81          relocateable output.  This seems to be always wrong for 386
82          COFF, so we handle the addend here instead.  */
83       diff = reloc_entry->addend;
84     }
85
86 #define DOIT(x) \
87   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
88
89   if (diff != 0)
90     {
91       const reloc_howto_type *howto = reloc_entry->howto;
92       unsigned char *addr = (unsigned char *) data + reloc_entry->address;
93
94       switch (howto->size)
95         {
96         case 0:
97           {
98             char x = bfd_get_8 (abfd, addr);
99             DOIT (x);
100             bfd_put_8 (abfd, x, addr);
101           }
102           break;
103
104         case 1:
105           {
106             short x = bfd_get_16 (abfd, addr);
107             DOIT (x);
108             bfd_put_16 (abfd, x, addr);
109           }
110           break;
111
112         case 2:
113           {
114             long x = bfd_get_32 (abfd, addr);
115             DOIT (x);
116             bfd_put_32 (abfd, x, addr);
117           }
118           break;
119
120         default:
121           abort ();
122         }
123     }
124
125   /* Now let bfd_perform_relocation finish everything up.  */
126   return bfd_reloc_continue;
127 }
128
129 static reloc_howto_type howto_table[] = 
130 {
131   {0},
132   {1},
133   {2},
134   {3},
135   {4},
136   {5},
137   HOWTO (R_DIR32,               /* type */                                 
138          0,                     /* rightshift */                           
139          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
140          32,                    /* bitsize */                   
141          false,                 /* pc_relative */                          
142          0,                     /* bitpos */                               
143          complain_overflow_bitfield, /* complain_on_overflow */
144          coff_go32_reloc,       /* special_function */                     
145          "dir32",               /* name */                                 
146          true,                  /* partial_inplace */                      
147          0xffffffff,            /* src_mask */                             
148          0xffffffff,            /* dst_mask */                             
149          false),                /* pcrel_offset */
150   {7},
151   {010},
152   {011},
153   {012},
154   {013},
155   {014},
156   {015},
157   {016},
158   HOWTO (R_RELBYTE,             /* type */                                 
159          0,                     /* rightshift */                           
160          0,                     /* size (0 = byte, 1 = short, 2 = long) */ 
161          8,                     /* bitsize */                   
162          false,                 /* pc_relative */                          
163          0,                     /* bitpos */                               
164          complain_overflow_bitfield, /* complain_on_overflow */
165          coff_go32_reloc,       /* special_function */                     
166          "8",                   /* name */                                 
167          true,                  /* partial_inplace */                      
168          0x000000ff,            /* src_mask */                             
169          0x000000ff,            /* dst_mask */                             
170          false),                /* pcrel_offset */
171   HOWTO (R_RELWORD,             /* type */                                 
172          0,                     /* rightshift */                           
173          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
174          16,                    /* bitsize */                   
175          false,                 /* pc_relative */                          
176          0,                     /* bitpos */                               
177          complain_overflow_bitfield, /* complain_on_overflow */
178          coff_go32_reloc,       /* special_function */                     
179          "16",                  /* name */                                 
180          true,                  /* partial_inplace */                      
181          0x0000ffff,            /* src_mask */                             
182          0x0000ffff,            /* dst_mask */                             
183          false),                /* pcrel_offset */
184   HOWTO (R_RELLONG,             /* type */                                 
185          0,                     /* rightshift */                           
186          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
187          32,                    /* bitsize */                   
188          false,                 /* pc_relative */                          
189          0,                     /* bitpos */                               
190          complain_overflow_bitfield, /* complain_on_overflow */
191          coff_go32_reloc,       /* special_function */                     
192          "32",                  /* name */                                 
193          true,                  /* partial_inplace */                      
194          0xffffffff,            /* src_mask */                             
195          0xffffffff,            /* dst_mask */                             
196          false),                /* pcrel_offset */
197   HOWTO (R_PCRBYTE,             /* type */                                 
198          0,                     /* rightshift */                           
199          0,                     /* size (0 = byte, 1 = short, 2 = long) */ 
200          8,                     /* bitsize */                   
201          true,                  /* pc_relative */                          
202          0,                     /* bitpos */                               
203          complain_overflow_signed, /* complain_on_overflow */
204          coff_go32_reloc,       /* special_function */                     
205          "DISP8",               /* name */                                 
206          true,                  /* partial_inplace */                      
207          0x000000ff,            /* src_mask */                             
208          0x000000ff,            /* dst_mask */                             
209          false),                /* pcrel_offset */
210   HOWTO (R_PCRWORD,             /* type */                                 
211          0,                     /* rightshift */                           
212          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
213          16,                    /* bitsize */                   
214          true,                  /* pc_relative */                          
215          0,                     /* bitpos */                               
216          complain_overflow_signed, /* complain_on_overflow */
217          coff_go32_reloc,       /* special_function */                     
218          "DISP16",              /* name */                                 
219          true,                  /* partial_inplace */                      
220          0x0000ffff,            /* src_mask */                             
221          0x0000ffff,            /* dst_mask */                             
222          false),                /* pcrel_offset */
223   HOWTO (R_PCRLONG,             /* type */                                 
224          0,                     /* rightshift */                           
225          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
226          32,                    /* bitsize */                   
227          true,                  /* pc_relative */                          
228          0,                     /* bitpos */                               
229          complain_overflow_signed, /* complain_on_overflow */
230          coff_go32_reloc,       /* special_function */                     
231          "DISP32",              /* name */                                 
232          true,                  /* partial_inplace */                      
233          0xffffffff,            /* src_mask */                             
234          0xffffffff,            /* dst_mask */                             
235          false)                 /* pcrel_offset */
236 };
237
238 /* Turn a howto into a reloc  nunmber */
239
240 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
241 #define BADMAG(x) I386BADMAG(x)
242 #define I386 1                  /* Customize coffcode.h */
243
244 #define RTYPE2HOWTO(cache_ptr, dst) \
245             cache_ptr->howto = howto_table + (dst)->r_type;
246
247 /* On SCO Unix 3.2.2 the native assembler generates two .data
248    sections.  We handle that by renaming the second one to .data2.  It
249    does no harm to do this for any 386 COFF target.  */
250 #define TWO_DATA_SECS
251
252 /* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
253    library.  On some other COFF targets STYP_BSS is normally
254    STYP_NOLOAD.  */
255 #define BSS_NOLOAD_IS_SHARED_LIBRARY
256
257 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
258    the object file contains the value of the common symbol.  By the
259    time this is called, the linker may be using a different symbol
260    from a different object file with a different value.  Therefore, we
261    hack wildly to locate the original symbol from this file so that we
262    can make the correct adjustment.  This macro sets coffsym to the
263    symbol from the original file, and uses it to set the addend value
264    correctly.  If this is not a common symbol, the usual addend
265    calculation is done, except that an additional tweak is needed for
266    PC relative relocs.
267    FIXME: This macro refers to symbols and asect; these are from the
268    calling function, not the macro arguments.  */
269
270 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
271   {                                                             \
272     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
273     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
274       coffsym = (obj_symbols (abfd)                             \
275                  + (cache_ptr->sym_ptr_ptr - symbols));         \
276     else if (ptr)                                               \
277       coffsym = coff_symbol_from (abfd, ptr);                   \
278     if (coffsym != (coff_symbol_type *) NULL                    \
279         && coffsym->native->u.syment.n_scnum == 0)              \
280       cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
281     else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
282              && ptr->section != (asection *) NULL)              \
283       cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
284     else                                                        \
285       cache_ptr->addend = 0;                                    \
286     if (ptr && howto_table[reloc.r_type].pc_relative)           \
287       cache_ptr->addend += asect->vma;                          \
288   }
289
290 #include "coffcode.h"
291
292 static const bfd_target *
293 go32coff_object_p(a)
294      bfd *a;
295 {
296   return coff_object_p(a);
297 }
298
299 static const bfd_target *
300 go32coff_archive_p(a)
301      bfd *a;
302 {
303   return 0;
304 }
305
306 const bfd_target
307 #ifdef TARGET_SYM
308   TARGET_SYM =
309 #else
310   go32coff_vec =
311 #endif
312 {
313 #ifdef TARGET_NAME
314   TARGET_NAME,
315 #else
316   "coff-go32",                  /* name */
317 #endif
318   bfd_target_coff_flavour,
319   false,                        /* data byte order is little */
320   false,                        /* header byte order is little */
321
322   (HAS_RELOC | EXEC_P |         /* object flags */
323    HAS_LINENO | HAS_DEBUG |
324    HAS_SYMS | HAS_LOCALS | WP_TEXT),
325
326   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
327   '_',                          /* leading underscore */
328   '/',                          /* ar_pad_char */
329   15,                           /* ar_max_namelen */
330
331   2,                            /* minimum alignment power */
332   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
333      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
334      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
335   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
336      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
337      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
338
339 /* Note that we allow an object file to be treated as a core file as well. */
340     {_bfd_dummy_target, go32coff_object_p, /* bfd_check_format */
341        bfd_generic_archive_p, go32coff_object_p},
342     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
343        bfd_false},
344     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
345        _bfd_write_archive_contents, bfd_false},
346
347      BFD_JUMP_TABLE_GENERIC (coff),
348      BFD_JUMP_TABLE_COPY (coff),
349      BFD_JUMP_TABLE_CORE (_bfd_nocore),
350      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
351      BFD_JUMP_TABLE_SYMBOLS (coff),
352      BFD_JUMP_TABLE_RELOCS (coff),
353      BFD_JUMP_TABLE_WRITE (coff),
354      BFD_JUMP_TABLE_LINK (coff),
355      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
356
357   COFF_SWAP_TABLE,
358 };