-static bfd_reloc_status_type pj_elf_reloc
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-static reloc_howto_type *pj_elf_reloc_type_lookup
- PARAMS ((bfd *, bfd_reloc_code_real_type));
-static void pj_elf_info_to_howto
- PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
-static void pj_elf_final_write_processing
- PARAMS ((bfd *, boolean));
+/* This function is used for normal relocs. This is like the COFF
+ function, and is almost certainly incorrect for other ELF targets. */
+
+static bfd_reloc_status_type
+pj_elf_reloc (bfd *abfd,
+ arelent *reloc_entry,
+ asymbol *symbol_in,
+ void * data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ unsigned long insn;
+ bfd_vma sym_value;
+ enum elf_pj_reloc_type r_type;
+ bfd_vma addr = reloc_entry->address;
+ bfd_byte *hit_data = addr + (bfd_byte *) data;
+
+ r_type = (enum elf_pj_reloc_type) reloc_entry->howto->type;
+
+ if (output_bfd != NULL)
+ {
+ /* Partial linking--do nothing. */
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ if (symbol_in != NULL
+ && (symbol_in->flags & BSF_WEAK) == 0
+ && bfd_is_und_section (symbol_in->section))
+ return bfd_reloc_undefined;
+
+ if (bfd_is_com_section (symbol_in->section))
+ sym_value = 0;
+ else
+ sym_value = (symbol_in->value +
+ symbol_in->section->output_section->vma +
+ symbol_in->section->output_offset);
+
+ switch (r_type)
+ {
+ case R_PJ_DATA_DIR32:
+ insn = bfd_get_32 (abfd, hit_data);
+ insn += sym_value + reloc_entry->addend;
+ bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
+ break;
+
+ /* Relocations in code are always bigendian, no matter what the
+ data endianness is. */
+
+ case R_PJ_CODE_DIR32:
+ insn = bfd_getb32 (hit_data);
+ insn += sym_value + reloc_entry->addend;
+ bfd_putb32 ((bfd_vma) insn, hit_data);
+ break;
+
+ case R_PJ_CODE_REL16:
+ insn = bfd_getb16 (hit_data);
+ insn += sym_value + reloc_entry->addend
+ - (input_section->output_section->vma
+ + input_section->output_offset);
+ bfd_putb16 ((bfd_vma) insn, hit_data);
+ break;
+ case R_PJ_CODE_LO16:
+ insn = bfd_getb16 (hit_data);
+ insn += sym_value + reloc_entry->addend;
+ bfd_putb16 ((bfd_vma) insn, hit_data);
+ break;
+
+ case R_PJ_CODE_HI16:
+ insn = bfd_getb16 (hit_data);
+ insn += (sym_value + reloc_entry->addend) >> 16;
+ bfd_putb16 ((bfd_vma) insn, hit_data);
+ break;
+
+ default:
+ abort ();
+ break;
+ }
+
+ return bfd_reloc_ok;
+}