+ reloc_howto_type *howto;
+
+ if (rel->r_type > sizeof (howto_table) / sizeof (howto_table[0]))
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return NULL;
+ }
+
+ howto = howto_table + rel->r_type;
+
+#ifdef COFF_WITH_PE
+ /* Cancel out code in _bfd_coff_generic_relocate_section. */
+ *addendp = 0;
+#endif
+
+ if (howto->pc_relative)
+ *addendp += sec->vma;
+
+ if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
+ {
+ /* This is a common symbol. The section contents include the
+ size (sym->n_value) as an addend. The relocate_section
+ function will be adding in the final value of the symbol. We
+ need to subtract out the current size in order to get the
+ correct result. */
+
+ BFD_ASSERT (h != NULL);
+
+#ifndef COFF_WITH_PE
+ /* I think we *do* want to bypass this. If we don't, I have
+ seen some data parameters get the wrong relocation address.
+ If I link two versions with and without this section bypassed
+ and then do a binary comparison, the addresses which are
+ different can be looked up in the map. The case in which
+ this section has been bypassed has addresses which correspond
+ to values I can find in the map. */
+ *addendp -= sym->n_value;
+#endif
+ }
+
+#ifndef COFF_WITH_PE
+ /* If the output symbol is common (in which case this must be a
+ relocateable link), we need to add in the final size of the
+ common symbol. */
+ if (h != NULL && h->root.type == bfd_link_hash_common)
+ *addendp += h->root.u.c.size;
+#endif
+
+#ifdef COFF_WITH_PE
+ if (howto->pc_relative)
+ {
+ *addendp -= 4;
+
+ /* If the symbol is defined, then the generic code is going to
+ add back the symbol value in order to cancel out an
+ adjustment it made to the addend. However, we set the addend
+ to 0 at the start of this function. We need to adjust here,
+ to avoid the adjustment the generic code will make. FIXME:
+ This is getting a bit hackish. */
+ if (sym != NULL && sym->n_scnum != 0)
+ *addendp -= sym->n_value;
+ }
+
+ if (rel->r_type == R_IMAGEBASE
+ && (bfd_get_flavour(sec->output_section->owner)
+ == bfd_target_coff_flavour))
+ {
+ *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
+ }
+#endif
+
+ return howto;
+}
+
+#define coff_bfd_reloc_type_lookup coff_i386_reloc_type_lookup
+
+static reloc_howto_type *
+coff_i386_reloc_type_lookup (abfd, code)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ bfd_reloc_code_real_type code;
+{
+ switch (code)
+ {
+ case BFD_RELOC_RVA:
+ return howto_table + R_IMAGEBASE;
+ case BFD_RELOC_32:
+ return howto_table + R_DIR32;
+ case BFD_RELOC_32_PCREL:
+ return howto_table + R_PCRLONG;
+ case BFD_RELOC_16:
+ return howto_table + R_RELWORD;
+ case BFD_RELOC_16_PCREL:
+ return howto_table + R_PCRWORD;
+ case BFD_RELOC_8:
+ return howto_table + R_RELBYTE;
+ case BFD_RELOC_8_PCREL:
+ return howto_table + R_PCRBYTE;
+ default:
+ BFD_FAIL ();
+ return 0;
+ }