- {0},
- {1},
- {2},
- {3},
- {4},
- {5},
- HOWTO(R_DIR32, 0, 2, 32, false, 0, true,true,0,"dir32", true, 0xffffffff,0xffffffff, false),
- {7},
- {010},
- {011},
- {012},
- {013},
- {014},
- {015},
- {016},
- HOWTO(R_RELBYTE, 0, 0, 8, false, 0, true, true,0,"8", true, 0x000000ff,0x000000ff, false),
- HOWTO(R_RELWORD, 0, 1, 16, false, 0, true, true,0,"16", true, 0x0000ffff,0x0000ffff, false),
- HOWTO(R_RELLONG, 0, 2, 32, false, 0, true, true,0,"32", true, 0xffffffff,0xffffffff, false),
- HOWTO(R_PCRBYTE, 0, 0, 8, true, 0, false, true,0,"DISP8", true, 0x000000ff,0x000000ff, false),
- HOWTO(R_PCRWORD, 0, 1, 16, true, 0, false, true,0,"DISP16", true, 0x0000ffff,0x0000ffff, false),
- HOWTO(R_PCRLONG, 0, 2, 32, true, 0, false, true,0,"DISP32", true, 0xffffffff,0xffffffff, false),
+ symvalue diff;
+
+#ifndef COFF_WITH_PE
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+#endif
+
+ if (bfd_is_com_section (symbol->section))
+ {
+#ifndef COFF_WITH_PE
+ /* We are relocating a common symbol. The current value in the
+ object file is ORIG + OFFSET, where ORIG is the value of the
+ common symbol as seen by the object file when it was compiled
+ (this may be zero if the symbol was undefined) and OFFSET is
+ the offset into the common symbol (normally zero, but may be
+ non-zero when referring to a field in a common structure).
+ ORIG is the negative of reloc_entry->addend, which is set by
+ the CALC_ADDEND macro below. We want to replace the value in
+ the object file with NEW + OFFSET, where NEW is the value of
+ the common symbol which we are going to put in the final
+ object file. NEW is symbol->value. */
+ diff = symbol->value + reloc_entry->addend;
+#else
+ /* In PE mode, we do not offset the common symbol. */
+ diff = reloc_entry->addend;
+#endif
+ }
+ else
+ {
+ /* For some reason bfd_perform_relocation always effectively
+ ignores the addend for a COFF target when producing
+ relocatable output. This seems to be always wrong for 386
+ COFF, so we handle the addend here instead. */
+#ifdef COFF_WITH_PE
+ if (output_bfd == (bfd *) NULL)
+ {
+ reloc_howto_type *howto = reloc_entry->howto;
+
+ /* Although PC relative relocations are very similar between
+ PE and non-PE formats, but they are off by 1 << howto->size
+ bytes. For the external relocation, PE is very different
+ from others. See md_apply_fix3 () in gas/config/tc-i386.c.
+ When we link PE and non-PE object files together to
+ generate a non-PE executable, we have to compensate it
+ here. */
+ if (howto->pc_relative && howto->pcrel_offset)
+ diff = -(1 << howto->size);
+ else if (symbol->flags & BSF_WEAK)
+ diff = reloc_entry->addend - symbol->value;
+ else
+ diff = -reloc_entry->addend;
+ }
+ else
+#endif
+ diff = reloc_entry->addend;
+ }
+
+#ifdef COFF_WITH_PE
+ /* FIXME: How should this case be handled? */
+ if (reloc_entry->howto->type == R_IMAGEBASE
+ && output_bfd != NULL
+ && bfd_get_flavour(output_bfd) == bfd_target_coff_flavour)
+ diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
+#endif
+
+#define DOIT(x) \
+ x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
+
+ if (diff != 0)
+ {
+ reloc_howto_type *howto = reloc_entry->howto;
+ unsigned char *addr = (unsigned char *) data + reloc_entry->address;
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = bfd_get_8 (abfd, addr);
+ DOIT (x);
+ bfd_put_8 (abfd, x, addr);
+ }
+ break;
+
+ case 1:
+ {
+ short x = bfd_get_16 (abfd, addr);
+ DOIT (x);
+ bfd_put_16 (abfd, (bfd_vma) x, addr);
+ }
+ break;
+
+ case 2:
+ {
+ long x = bfd_get_32 (abfd, addr);
+ DOIT (x);
+ bfd_put_32 (abfd, (bfd_vma) x, addr);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ /* Now let bfd_perform_relocation finish everything up. */
+ return bfd_reloc_continue;
+}
+
+#ifdef COFF_WITH_PE
+/* Return TRUE if this relocation should appear in the output .reloc
+ section. */
+
+static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
+
+static bfd_boolean in_reloc_p (abfd, howto)
+ bfd * abfd ATTRIBUTE_UNUSED;
+ reloc_howto_type *howto;
+{
+ return ! howto->pc_relative && howto->type != R_IMAGEBASE;
+}
+#endif /* COFF_WITH_PE */
+
+#ifndef PCRELOFFSET
+#define PCRELOFFSET FALSE
+#endif
+
+static reloc_howto_type howto_table[] =
+{
+ EMPTY_HOWTO (0),
+ EMPTY_HOWTO (1),
+ EMPTY_HOWTO (2),
+ EMPTY_HOWTO (3),
+ EMPTY_HOWTO (4),
+ EMPTY_HOWTO (5),
+ HOWTO (R_DIR32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "dir32", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+ /* PE IMAGE_REL_I386_DIR32NB relocation (7). */
+ HOWTO (R_IMAGEBASE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "rva32", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+ EMPTY_HOWTO (010),
+ EMPTY_HOWTO (011),
+ EMPTY_HOWTO (012),
+#ifdef COFF_WITH_PE
+ /* 32-bit longword section relative relocation (013). */
+ HOWTO (R_SECREL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "secrel32", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+#else
+ EMPTY_HOWTO (013),
+#endif
+ EMPTY_HOWTO (014),
+ EMPTY_HOWTO (015),
+ EMPTY_HOWTO (016),
+ /* Byte relocation (017). */
+ HOWTO (R_RELBYTE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "8", /* name */
+ TRUE, /* partial_inplace */
+ 0x000000ff, /* src_mask */
+ 0x000000ff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ /* 16-bit word relocation (020). */
+ HOWTO (R_RELWORD, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ /* 32-bit longword relocation (021). */
+ HOWTO (R_RELLONG, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "32", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ /* Byte PC relative relocation (022). */
+ HOWTO (R_PCRBYTE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "DISP8", /* name */
+ TRUE, /* partial_inplace */
+ 0x000000ff, /* src_mask */
+ 0x000000ff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ /* 16-bit word PC relative relocation (023). */
+ HOWTO (R_PCRWORD, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "DISP16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ /* 32-bit longword PC relative relocation (024). */
+ HOWTO (R_PCRLONG, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "DISP32", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ PCRELOFFSET) /* pcrel_offset */