]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/gdb/bfd/coff-i386.c
This commit was generated by cvs2svn to compensate for changes in r42788,
[FreeBSD/FreeBSD.git] / contrib / gdb / bfd / coff-i386.c
1 /* BFD back-end for Intel 386 COFF files.
2    Copyright 1990, 1991, 1992, 1993, 1994, 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "obstack.h"
25
26 #include "coff/i386.h"
27
28 #include "coff/internal.h"
29
30 #ifdef COFF_WITH_PE
31 #include "coff/pe.h"
32 #endif
33
34 #include "libcoff.h"
35
36 static bfd_reloc_status_type coff_i386_reloc 
37   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38 static reloc_howto_type *coff_i386_rtype_to_howto
39   PARAMS ((bfd *, asection *, struct internal_reloc *,
40            struct coff_link_hash_entry *, struct internal_syment *,
41
42            bfd_vma *));
43
44 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
45 /* The page size is a guess based on ELF.  */
46
47 #define COFF_PAGE_SIZE 0x1000
48
49 /* For some reason when using i386 COFF the value stored in the .text
50    section for a reference to a common symbol is the value itself plus
51    any desired offset.  Ian Taylor, Cygnus Support.  */
52
53 /* If we are producing relocateable output, we need to do some
54    adjustments to the object file that are not done by the
55    bfd_perform_relocation function.  This function is called by every
56    reloc type to make any required adjustments.  */
57
58 static bfd_reloc_status_type
59 coff_i386_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
60                  error_message)
61      bfd *abfd;
62      arelent *reloc_entry;
63      asymbol *symbol;
64      PTR data;
65      asection *input_section;
66      bfd *output_bfd;
67      char **error_message;
68 {
69   symvalue diff;
70
71   if (output_bfd == (bfd *) NULL)
72     return bfd_reloc_continue;
73
74
75   if (bfd_is_com_section (symbol->section))
76     {
77       /* We are relocating a common symbol.  The current value in the
78          object file is ORIG + OFFSET, where ORIG is the value of the
79          common symbol as seen by the object file when it was compiled
80          (this may be zero if the symbol was undefined) and OFFSET is
81          the offset into the common symbol (normally zero, but may be
82          non-zero when referring to a field in a common structure).
83          ORIG is the negative of reloc_entry->addend, which is set by
84          the CALC_ADDEND macro below.  We want to replace the value in
85          the object file with NEW + OFFSET, where NEW is the value of
86          the common symbol which we are going to put in the final
87          object file.  NEW is symbol->value.  */
88       diff = symbol->value + reloc_entry->addend;
89     }
90   else
91     {
92       /* For some reason bfd_perform_relocation always effectively
93          ignores the addend for a COFF target when producing
94          relocateable output.  This seems to be always wrong for 386
95          COFF, so we handle the addend here instead.  */
96       diff = reloc_entry->addend;
97     }
98
99
100 #ifdef COFF_WITH_PE
101   if (reloc_entry->howto->type == 7)
102     {
103 /*      diff -= coff_data(output_bfd)->link_info->pe_info.image_base.value;*/
104       exit(1);
105     }
106 #endif
107
108 #define DOIT(x) \
109   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
110
111     if (diff != 0)
112       {
113         reloc_howto_type *howto = reloc_entry->howto;
114         unsigned char *addr = (unsigned char *) data + reloc_entry->address;
115
116         switch (howto->size)
117           {
118           case 0:
119             {
120               char x = bfd_get_8 (abfd, addr);
121               DOIT (x);
122               bfd_put_8 (abfd, x, addr);
123             }
124             break;
125
126           case 1:
127             {
128               short x = bfd_get_16 (abfd, addr);
129               DOIT (x);
130               bfd_put_16 (abfd, x, addr);
131             }
132             break;
133
134           case 2:
135             {
136               long x = bfd_get_32 (abfd, addr);
137               DOIT (x);
138               bfd_put_32 (abfd, x, addr);
139             }
140             break;
141
142           default:
143             abort ();
144           }
145       }
146
147   /* Now let bfd_perform_relocation finish everything up.  */
148   return bfd_reloc_continue;
149 }
150
151 #ifdef COFF_WITH_PE
152 /* Return true if this relocation should
153    appear in the output .reloc section. */
154
155 static boolean in_reloc_p(abfd, howto)
156      bfd * abfd;
157      reloc_howto_type *howto;
158 {
159   return ! howto->pc_relative && howto->type != R_IMAGEBASE;
160 }     
161 #endif
162
163 #ifndef PCRELOFFSET
164 #define PCRELOFFSET false
165 #endif
166
167 static reloc_howto_type howto_table[] = 
168 {
169   {0},
170   {1},
171   {2},
172   {3},
173   {4},
174   {5},
175   HOWTO (R_DIR32,               /* type */                                 
176          0,                     /* rightshift */                           
177          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
178          32,                    /* bitsize */                   
179          false,                 /* pc_relative */                          
180          0,                     /* bitpos */                               
181          complain_overflow_bitfield, /* complain_on_overflow */
182          coff_i386_reloc,       /* special_function */                     
183          "dir32",               /* name */                                 
184          true,                  /* partial_inplace */                      
185          0xffffffff,            /* src_mask */                             
186          0xffffffff,            /* dst_mask */                             
187          true),                /* pcrel_offset */
188   /* {7}, */
189   HOWTO (R_IMAGEBASE,            /* type */                                 
190          0,                     /* rightshift */                           
191          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
192          32,                    /* bitsize */                   
193          false,                 /* pc_relative */                          
194          0,                     /* bitpos */                               
195          complain_overflow_bitfield, /* complain_on_overflow */
196          coff_i386_reloc,       /* special_function */                     
197          "rva32",                  /* name */                                 
198          true,                  /* partial_inplace */                      
199          0xffffffff,            /* src_mask */                             
200          0xffffffff,            /* dst_mask */                             
201          false),                /* pcrel_offset */
202   {010},
203   {011},
204   {012},
205   {013},
206   {014},
207   {015},
208   {016},
209   HOWTO (R_RELBYTE,             /* type */                                 
210          0,                     /* rightshift */                           
211          0,                     /* size (0 = byte, 1 = short, 2 = long) */ 
212          8,                     /* bitsize */                   
213          false,                 /* pc_relative */                          
214          0,                     /* bitpos */                               
215          complain_overflow_bitfield, /* complain_on_overflow */
216          coff_i386_reloc,       /* special_function */                     
217          "8",                   /* name */                                 
218          true,                  /* partial_inplace */                      
219          0x000000ff,            /* src_mask */                             
220          0x000000ff,            /* dst_mask */                             
221          PCRELOFFSET),          /* pcrel_offset */
222   HOWTO (R_RELWORD,             /* type */                                 
223          0,                     /* rightshift */                           
224          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
225          16,                    /* bitsize */                   
226          false,                 /* pc_relative */                          
227          0,                     /* bitpos */                               
228          complain_overflow_bitfield, /* complain_on_overflow */
229          coff_i386_reloc,       /* special_function */                     
230          "16",                  /* name */                                 
231          true,                  /* partial_inplace */                      
232          0x0000ffff,            /* src_mask */                             
233          0x0000ffff,            /* dst_mask */                             
234          PCRELOFFSET),          /* pcrel_offset */
235   HOWTO (R_RELLONG,             /* type */                                 
236          0,                     /* rightshift */                           
237          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
238          32,                    /* bitsize */                   
239          false,                 /* pc_relative */                          
240          0,                     /* bitpos */                               
241          complain_overflow_bitfield, /* complain_on_overflow */
242          coff_i386_reloc,       /* special_function */                     
243          "32",                  /* name */                                 
244          true,                  /* partial_inplace */                      
245          0xffffffff,            /* src_mask */                             
246          0xffffffff,            /* dst_mask */                             
247          PCRELOFFSET),          /* pcrel_offset */
248   HOWTO (R_PCRBYTE,             /* type */                                 
249          0,                     /* rightshift */                           
250          0,                     /* size (0 = byte, 1 = short, 2 = long) */ 
251          8,                     /* bitsize */                   
252          true,                  /* pc_relative */                          
253          0,                     /* bitpos */                               
254          complain_overflow_signed, /* complain_on_overflow */
255          coff_i386_reloc,       /* special_function */                     
256          "DISP8",               /* name */                                 
257          true,                  /* partial_inplace */                      
258          0x000000ff,            /* src_mask */                             
259          0x000000ff,            /* dst_mask */                             
260          PCRELOFFSET),          /* pcrel_offset */
261   HOWTO (R_PCRWORD,             /* type */                                 
262          0,                     /* rightshift */                           
263          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
264          16,                    /* bitsize */                   
265          true,                  /* pc_relative */                          
266          0,                     /* bitpos */                               
267          complain_overflow_signed, /* complain_on_overflow */
268          coff_i386_reloc,       /* special_function */                     
269          "DISP16",              /* name */                                 
270          true,                  /* partial_inplace */                      
271          0x0000ffff,            /* src_mask */                             
272          0x0000ffff,            /* dst_mask */                             
273          PCRELOFFSET),          /* pcrel_offset */
274   HOWTO (R_PCRLONG,             /* type */                                 
275          0,                     /* rightshift */                           
276          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
277          32,                    /* bitsize */                   
278          true,                  /* pc_relative */                          
279          0,                     /* bitpos */                               
280          complain_overflow_signed, /* complain_on_overflow */
281          coff_i386_reloc,       /* special_function */                     
282          "DISP32",              /* name */                                 
283          true,                  /* partial_inplace */                      
284          0xffffffff,            /* src_mask */                             
285          0xffffffff,            /* dst_mask */                             
286          PCRELOFFSET)           /* pcrel_offset */
287 };
288
289 /* Turn a howto into a reloc  nunmber */
290
291 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
292 #define BADMAG(x) I386BADMAG(x)
293 #define I386 1                  /* Customize coffcode.h */
294
295 #define RTYPE2HOWTO(cache_ptr, dst) \
296             (cache_ptr)->howto = howto_table + (dst)->r_type;
297
298 /* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
299    library.  On some other COFF targets STYP_BSS is normally
300    STYP_NOLOAD.  */
301 #define BSS_NOLOAD_IS_SHARED_LIBRARY
302
303 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
304    the object file contains the value of the common symbol.  By the
305    time this is called, the linker may be using a different symbol
306    from a different object file with a different value.  Therefore, we
307    hack wildly to locate the original symbol from this file so that we
308    can make the correct adjustment.  This macro sets coffsym to the
309    symbol from the original file, and uses it to set the addend value
310    correctly.  If this is not a common symbol, the usual addend
311    calculation is done, except that an additional tweak is needed for
312    PC relative relocs.
313    FIXME: This macro refers to symbols and asect; these are from the
314    calling function, not the macro arguments.  */
315
316 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
317   {                                                             \
318     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;      \
319     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
320       coffsym = (obj_symbols (abfd)                             \
321                  + (cache_ptr->sym_ptr_ptr - symbols));         \
322     else if (ptr)                                               \
323       coffsym = coff_symbol_from (abfd, ptr);                   \
324     if (coffsym != (coff_symbol_type *) NULL                    \
325         && coffsym->native->u.syment.n_scnum == 0)              \
326       cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
327     else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
328              && ptr->section != (asection *) NULL)              \
329       cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
330     else                                                        \
331       cache_ptr->addend = 0;                                    \
332     if (ptr && howto_table[reloc.r_type].pc_relative)           \
333       cache_ptr->addend += asect->vma;                          \
334   }
335
336 /* We use the special COFF backend linker.  */
337 #define coff_relocate_section _bfd_coff_generic_relocate_section
338
339 static reloc_howto_type *
340 coff_i386_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
341      bfd *abfd;
342      asection *sec;
343      struct internal_reloc *rel;
344      struct coff_link_hash_entry *h;
345      struct internal_syment *sym;
346      bfd_vma *addendp;
347 {
348
349   reloc_howto_type *howto;
350
351   howto = howto_table + rel->r_type;
352
353 #ifdef COFF_WITH_PE
354   *addendp = 0;
355 #endif
356
357   if (howto->pc_relative)
358     *addendp += sec->vma;
359
360   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
361     {
362       /* This is a common symbol.  The section contents include the
363          size (sym->n_value) as an addend.  The relocate_section
364          function will be adding in the final value of the symbol.  We
365          need to subtract out the current size in order to get the
366          correct result.  */
367  
368       BFD_ASSERT (h != NULL);
369
370
371 #ifndef COFF_WITH_PE
372       /* I think we *do* want to bypass this.  If we don't, I have seen some data
373          parameters get the wrong relcation address.  If I link two versions
374          with and without this section bypassed and then do a binary comparison,
375          the addresses which are different can be looked up in the map.  The 
376          case in which this section has been bypassed has addresses which correspond
377          to values I can find in the map */
378       *addendp -= sym->n_value;
379 #endif
380     }
381
382   /* If the output symbol is common (in which case this must be a
383      relocateable link), we need to add in the final size of the
384      common symbol.  */
385   if (h != NULL && h->root.type == bfd_link_hash_common) 
386     *addendp += h->root.u.c.size;
387
388
389 #ifdef COFF_WITH_PE
390   if (howto->pc_relative)
391     *addendp -= 4;
392
393   if (rel->r_type == R_IMAGEBASE)
394     {
395       *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
396     }
397 #endif
398
399   return howto;
400 }
401
402
403 #define coff_bfd_reloc_type_lookup coff_i386_reloc_type_lookup
404
405
406 static reloc_howto_type *
407 coff_i386_reloc_type_lookup (abfd, code)
408      bfd *abfd;
409      bfd_reloc_code_real_type code;
410 {
411   switch (code)
412     {
413     case BFD_RELOC_RVA:
414       return howto_table +R_IMAGEBASE;
415     case BFD_RELOC_32:
416       return howto_table + R_DIR32;
417     case BFD_RELOC_32_PCREL:
418       return howto_table + R_PCRLONG;
419     default:
420       BFD_FAIL ();
421       return 0;
422     }
423 }
424
425
426
427 #define coff_rtype_to_howto coff_i386_rtype_to_howto
428
429 #include "coffcode.h"
430
431 static const bfd_target *
432 i3coff_object_p(a)
433      bfd *a;
434 {
435   return coff_object_p(a);
436 }
437
438 const bfd_target
439 #ifdef TARGET_SYM
440   TARGET_SYM =
441 #else
442   i386coff_vec =
443 #endif
444 {
445 #ifdef TARGET_NAME
446   TARGET_NAME,
447 #else
448   "coff-i386",                  /* name */
449 #endif
450   bfd_target_coff_flavour,
451   BFD_ENDIAN_LITTLE,            /* data byte order is little */
452   BFD_ENDIAN_LITTLE,            /* header byte order is little */
453
454   (HAS_RELOC | EXEC_P |         /* object flags */
455    HAS_LINENO | HAS_DEBUG |
456    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
457
458   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
459 #ifdef TARGET_UNDERSCORE
460   TARGET_UNDERSCORE,            /* leading underscore */
461 #else
462   0,                            /* leading underscore */
463 #endif
464   '/',                          /* ar_pad_char */
465   15,                           /* ar_max_namelen */
466
467   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
468      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
469      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
470   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
471      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
472      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
473
474 /* Note that we allow an object file to be treated as a core file as well. */
475     {_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
476        bfd_generic_archive_p, i3coff_object_p},
477     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
478        bfd_false},
479     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
480        _bfd_write_archive_contents, bfd_false},
481
482      BFD_JUMP_TABLE_GENERIC (coff),
483      BFD_JUMP_TABLE_COPY (coff),
484      BFD_JUMP_TABLE_CORE (_bfd_nocore),
485      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
486      BFD_JUMP_TABLE_SYMBOLS (coff),
487      BFD_JUMP_TABLE_RELOCS (coff),
488      BFD_JUMP_TABLE_WRITE (coff),
489      BFD_JUMP_TABLE_LINK (coff),
490      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
491
492   COFF_SWAP_TABLE,
493 };