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