Sun Feb 27 15:22:36 1994 Stan Shebs (shebs@andros.cygnus.com)
[deliverable/binutils-gdb.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 };
This page took 0.03627 seconds and 4 git commands to generate.