diff options
-rw-r--r-- | bfd/elf32-hppa.c | 3881 |
1 files changed, 2541 insertions, 1340 deletions
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index bc347af..65940dc 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -2,7 +2,7 @@ Copyright (C) 1990-1991 Free Software Foundation, Inc. Written by - + Center for Software Science Department of Computer Science University of Utah @@ -29,11 +29,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "obstack.h" #include "libelf.h" - -static struct elf_backend_data elf_hppa_backend_data = { - NULL /* initially, $global$ is undefined */ -}; - /* ELF32/HPPA relocation support This file contains ELF32/HPPA relocation support as specified @@ -43,424 +38,432 @@ static struct elf_backend_data elf_hppa_backend_data = { /* Written by: - + Center for Software Science Department of Computer Science University of Utah */ #include "elf32-hppa.h" - -/* ELF/PA stab entries */ - -#ifdef hp800 -#undef hp800 -#include <a.out.h> /* we want the non-hp800 definition of 'struct nlist' */ -#define hp800 -#else -#include <a.out.h> -#endif +#include "libhppa.h" +#include "aout/aout64.h" /* ELF/PA relocation howto entries */ -static bfd_reloc_status_type hppa_elf_reloc(); - -reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] = { - /* 'bitpos' and 'abs' are obsolete */ - /* type rs sz bsz pcrel bpos abs ovrf sf name */ - /* 9.3.4. Address relocation types */ - { R_HPPA_NONE, 0, 3, 19, false, 0, false, true, hppa_elf_reloc, "R_HPPA_NONE"}, - { R_HPPA_32, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_32" }, - { R_HPPA_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_11" }, - { R_HPPA_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_14" }, - { R_HPPA_17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_17" }, - { R_HPPA_L21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_L21" }, - { R_HPPA_R11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_R11" }, - { R_HPPA_R14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_R14" }, - { R_HPPA_R17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_R17" }, - { R_HPPA_LS21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LS21" }, - { R_HPPA_RS11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RS11" }, - { R_HPPA_RS14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RS14" }, - { R_HPPA_RS17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RS17" }, - { R_HPPA_LD21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LD21" }, - { R_HPPA_RD11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RD11" }, - { R_HPPA_RD14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RD14" }, - { R_HPPA_RD17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RD17" }, - { R_HPPA_LR21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LR21" }, - { R_HPPA_RR14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RR14" }, - { R_HPPA_RR17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RR17" }, - /* 9.3.5. GOTOFF address relocation types */ - { R_HPPA_GOTOFF_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_11" }, - { R_HPPA_GOTOFF_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_14" }, - { R_HPPA_GOTOFF_L21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_L21" }, - { R_HPPA_GOTOFF_R11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_R11" }, - { R_HPPA_GOTOFF_R14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_R14" }, - { R_HPPA_GOTOFF_LS21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_LS21" }, - { R_HPPA_GOTOFF_RS11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RS11" }, - { R_HPPA_GOTOFF_RS14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RS14" }, - { R_HPPA_GOTOFF_LD21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_LD21" }, - { R_HPPA_GOTOFF_RD11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RD11" }, - { R_HPPA_GOTOFF_RD14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RD14" }, - { R_HPPA_GOTOFF_LR21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_LR21" }, - { R_HPPA_GOTOFF_RR14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RR14" }, - /* 9.3.6. Absolute call relocation types */ - { R_HPPA_ABS_CALL_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_11" }, - { R_HPPA_ABS_CALL_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_14" }, - { R_HPPA_ABS_CALL_17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_17" }, - { R_HPPA_ABS_CALL_L21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_L21" }, - { R_HPPA_ABS_CALL_R11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_R11" }, - { R_HPPA_ABS_CALL_R14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_R14" }, - { R_HPPA_ABS_CALL_R17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_R17" }, - { R_HPPA_ABS_CALL_LS21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_LS21" }, - { R_HPPA_ABS_CALL_RS11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS11" }, - { R_HPPA_ABS_CALL_RS14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS14" }, - { R_HPPA_ABS_CALL_RS17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS17" }, - { R_HPPA_ABS_CALL_LD21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_LD21" }, - { R_HPPA_ABS_CALL_RD11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD11" }, - { R_HPPA_ABS_CALL_RD14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD14" }, - { R_HPPA_ABS_CALL_RD17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD17" }, - { R_HPPA_ABS_CALL_LR21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_LR21" }, - { R_HPPA_ABS_CALL_RR14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RR14" }, - { R_HPPA_ABS_CALL_RR17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RR17" }, - /* 9.3.7. PC-relative call relocation types */ - { R_HPPA_PCREL_CALL_11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_11" }, - { R_HPPA_PCREL_CALL_14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_14" }, - { R_HPPA_PCREL_CALL_17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_17" }, - { R_HPPA_PCREL_CALL_L21,0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_L21" }, - { R_HPPA_PCREL_CALL_R11,0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R11" }, - { R_HPPA_PCREL_CALL_R14,0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R14" }, - { R_HPPA_PCREL_CALL_R17,0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R17" }, - { R_HPPA_PCREL_CALL_LS21,0,3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LS21" }, - { R_HPPA_PCREL_CALL_RS11,0,3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS11" }, - { R_HPPA_PCREL_CALL_RS14,0,3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS14" }, - { R_HPPA_PCREL_CALL_RS17,0,3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS17" }, - { R_HPPA_PCREL_CALL_LD21,0,3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LD21" }, - { R_HPPA_PCREL_CALL_RD11,0,3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD11" }, - { R_HPPA_PCREL_CALL_RD14,0,3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD14" }, - { R_HPPA_PCREL_CALL_RD17,0,3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD17" }, - { R_HPPA_PCREL_CALL_LR21,0,3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LR21" }, - { R_HPPA_PCREL_CALL_RR14,0,3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RR14" }, - { R_HPPA_PCREL_CALL_RR17,0,3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RR17" }, /* #69 */ - - /* 9.3.8. Plabel relocation types */ - { R_HPPA_PLABEL_32, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_32" }, - { R_HPPA_PLABEL_11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_11" }, - { R_HPPA_PLABEL_14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_14" }, - { R_HPPA_PLABEL_L21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_L21" }, - { R_HPPA_PLABEL_R11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_R11" }, - { R_HPPA_PLABEL_R14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_R14" }, /* 75 */ - - /* 9.3.9. Data linkage table (DLT) relocation types */ - { R_HPPA_DLT_32, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_32" }, - { R_HPPA_DLT_11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_11" }, - { R_HPPA_DLT_14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_14" }, - { R_HPPA_DLT_L21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_L21" }, - { R_HPPA_DLT_R11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_R11" }, - { R_HPPA_DLT_R14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_R14" }, /* 81 */ - - /* 9.3.10. Relocations for unwinder tables */ - { R_HPPA_UNWIND_ENTRY, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_UNWIND_ENTRY"}, - { R_HPPA_UNWIND_ENTRIES,0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_UNWIND_ENTRIES"}, /* 83 */ - - { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, /* 84-89 */ - { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, /* 90-99 */ - { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, /* 100-109 */ - { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, /* 110-119 */ - { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, /* 120-127 */ - - /* 9.3.11. Relocation types for complex expressions */ - { R_HPPA_PUSH_CONST, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_CONST" }, - { R_HPPA_PUSH_SYM, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_SYM" }, - { R_HPPA_PUSH_GOT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_GOT" }, - { R_HPPA_PUSH_PC, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_PC" }, - { R_HPPA_PUSH_PROC, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_PROC" }, - { R_HPPA_PUSH_PLABEL, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_PLABEL" }, - { R_HPPA_MAX, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MAX" }, - { R_HPPA_MIN, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MIN" }, - { R_HPPA_ADD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ADD" }, - { R_HPPA_SUB, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_SUB" }, - { R_HPPA_MULT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MULT" }, - { R_HPPA_DIV, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_DIV" }, - { R_HPPA_MOD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MOD" }, - { R_HPPA_AND, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_AND" }, - { R_HPPA_OR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_OR" }, - { R_HPPA_XOR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_XOR" }, - { R_HPPA_NOT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_NOT" }, - { R_HPPA_LSHIFT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LSHIFT" }, - { R_HPPA_ARITH_RSHIFT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ARITH_RSHIFT" }, - { R_HPPA_LOGIC_RSHIFT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LOGIC_RSHIFT" }, - { R_HPPA_EXPR_F, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_L" }, - { R_HPPA_EXPR_L, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_L" }, - { R_HPPA_EXPR_R, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_R" }, - { R_HPPA_EXPR_LS, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_LS" }, - { R_HPPA_EXPR_RS, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_RS" }, - { R_HPPA_EXPR_LD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_LD" }, - { R_HPPA_EXPR_RD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_RD" }, - { R_HPPA_EXPR_LR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_LR" }, - { R_HPPA_EXPR_RR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_RR" }, - - { R_HPPA_EXPR_32, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_32" }, - { R_HPPA_EXPR_21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_21" }, - { R_HPPA_EXPR_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_11" }, - { R_HPPA_EXPR_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_14" }, - { R_HPPA_EXPR_17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_17" }, - { R_HPPA_EXPR_12, 0, 3, 12, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_12" }, - { R_HPPA_UNIMPLEMENTED, 0, 0, 0, false, 0, false, false,NULL, "R_HPPA_UNIMPLEMENTED"}, /* 163 */ -}; +static bfd_reloc_status_type hppa_elf_reloc (); -static unsigned long -DEFUN(hppa_elf_rebuild_insn, (abfd,insn,value,r_type,r_field, r_format), - bfd *abfd AND - unsigned long insn AND - unsigned long value AND - unsigned short r_type AND - unsigned short r_field AND - unsigned short r_format) +reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] = { - unsigned long const_part; /* part of the instruction that does not change */ - unsigned long rebuilt_part; - - switch ( r_format ) { - case 11: { - unsigned w1, w; - - const_part = insn & 0xffffe002; - dis_assemble_12(value,&w1,&w); - rebuilt_part = (w1 << 2) | w; - return const_part | rebuilt_part; - } - - case 12: { - unsigned w1, w; - - const_part = insn & 0xffffe002; - dis_assemble_12(value,&w1,&w); - rebuilt_part = (w1 << 2) | w; - return const_part | rebuilt_part; - } - - case 14: - const_part = insn & 0xffffc000; - low_sign_unext(value,14,&rebuilt_part); - return const_part | rebuilt_part; - - case 17: { - unsigned w1, w2, w; - - const_part = insn & 0xffe0e002; - dis_assemble_17(value,&w1,&w2,&w); - rebuilt_part = (w2 << 2) | (w1 << 16) | w; - return const_part | rebuilt_part; - } +/* 'bitpos' and 'abs' are obsolete */ +/* type rs sz bsz pcrel bpos abs ovrf sf name */ +/* 9.3.4. Address relocation types */ + {R_HPPA_NONE, 0, 3, 19, false, 0, false, true, hppa_elf_reloc, "R_HPPA_NONE"}, + {R_HPPA_32, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_32"}, + {R_HPPA_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_11"}, + {R_HPPA_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_14"}, + {R_HPPA_17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_17"}, +{R_HPPA_L21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_L21"}, +{R_HPPA_R11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_R11"}, +{R_HPPA_R14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_R14"}, +{R_HPPA_R17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_R17"}, + {R_HPPA_LS21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LS21"}, + {R_HPPA_RS11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RS11"}, + {R_HPPA_RS14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RS14"}, + {R_HPPA_RS17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RS17"}, + {R_HPPA_LD21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LD21"}, + {R_HPPA_RD11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RD11"}, + {R_HPPA_RD14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RD14"}, + {R_HPPA_RD17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RD17"}, + {R_HPPA_LR21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LR21"}, + {R_HPPA_RR14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RR14"}, + {R_HPPA_RR17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_RR17"}, +/* 9.3.5. GOTOFF address relocation types */ + {R_HPPA_GOTOFF_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_11"}, + {R_HPPA_GOTOFF_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_14"}, + {R_HPPA_GOTOFF_L21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_L21"}, + {R_HPPA_GOTOFF_R11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_R11"}, + {R_HPPA_GOTOFF_R14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_R14"}, + {R_HPPA_GOTOFF_LS21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_LS21"}, + {R_HPPA_GOTOFF_RS11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RS11"}, + {R_HPPA_GOTOFF_RS14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RS14"}, + {R_HPPA_GOTOFF_LD21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_LD21"}, + {R_HPPA_GOTOFF_RD11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RD11"}, + {R_HPPA_GOTOFF_RD14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RD14"}, + {R_HPPA_GOTOFF_LR21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_LR21"}, + {R_HPPA_GOTOFF_RR14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_GOTOFF_RR14"}, +/* 9.3.6. Absolute call relocation types */ + {R_HPPA_ABS_CALL_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_11"}, + {R_HPPA_ABS_CALL_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_14"}, + {R_HPPA_ABS_CALL_17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_17"}, + {R_HPPA_ABS_CALL_L21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_L21"}, + {R_HPPA_ABS_CALL_R11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_R11"}, + {R_HPPA_ABS_CALL_R14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_R14"}, + {R_HPPA_ABS_CALL_R17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_R17"}, + {R_HPPA_ABS_CALL_LS21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_LS21"}, + {R_HPPA_ABS_CALL_RS11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS11"}, + {R_HPPA_ABS_CALL_RS14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS14"}, + {R_HPPA_ABS_CALL_RS17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS17"}, + {R_HPPA_ABS_CALL_LD21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_LD21"}, + {R_HPPA_ABS_CALL_RD11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD11"}, + {R_HPPA_ABS_CALL_RD14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD14"}, + {R_HPPA_ABS_CALL_RD17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD17"}, + {R_HPPA_ABS_CALL_LR21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_LR21"}, + {R_HPPA_ABS_CALL_RR14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RR14"}, + {R_HPPA_ABS_CALL_RR17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ABS_CALL_RR17"}, +/* 9.3.7. PC-relative call relocation types */ + {R_HPPA_PCREL_CALL_11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_11"}, + {R_HPPA_PCREL_CALL_14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_14"}, + {R_HPPA_PCREL_CALL_17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_17"}, + {R_HPPA_PCREL_CALL_12, 0, 3, 12, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_12"}, + {R_HPPA_PCREL_CALL_L21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_L21"}, + {R_HPPA_PCREL_CALL_R11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R11"}, + {R_HPPA_PCREL_CALL_R14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R14"}, + {R_HPPA_PCREL_CALL_R17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R17"}, + {R_HPPA_PCREL_CALL_LS21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LS21"}, + {R_HPPA_PCREL_CALL_RS11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS11"}, + {R_HPPA_PCREL_CALL_RS14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS14"}, + {R_HPPA_PCREL_CALL_RS17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS17"}, + {R_HPPA_PCREL_CALL_LD21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LD21"}, + {R_HPPA_PCREL_CALL_RD11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD11"}, + {R_HPPA_PCREL_CALL_RD14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD14"}, + {R_HPPA_PCREL_CALL_RD17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD17"}, + {R_HPPA_PCREL_CALL_LR21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LR21"}, + {R_HPPA_PCREL_CALL_RR14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RR14"}, + {R_HPPA_PCREL_CALL_RR17, 0, 3, 17, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RR17"}, + +/* 9.3.8. Plabel relocation types */ + {R_HPPA_PLABEL_32, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_32"}, + {R_HPPA_PLABEL_11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_11"}, + {R_HPPA_PLABEL_14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_14"}, + {R_HPPA_PLABEL_L21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_L21"}, + {R_HPPA_PLABEL_R11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_R11"}, + {R_HPPA_PLABEL_R14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_PLABEL_R14"}, + +/* 9.3.9. Data linkage table (DLT) relocation types */ + {R_HPPA_DLT_32, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_32"}, + {R_HPPA_DLT_11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_11"}, + {R_HPPA_DLT_14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_14"}, + {R_HPPA_DLT_L21, 0, 3, 21, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_L21"}, + {R_HPPA_DLT_R11, 0, 3, 11, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_R11"}, + {R_HPPA_DLT_R14, 0, 3, 14, true, 0, false, true, hppa_elf_reloc, "R_HPPA_DLT_R14"}, + +/* 9.3.10. Relocations for unwinder tables */ + {R_HPPA_UNWIND_ENTRY, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_UNWIND_ENTRY"}, + {R_HPPA_UNWIND_ENTRIES, 0, 3, 32, true, 0, false, true, hppa_elf_reloc, "R_HPPA_UNWIND_ENTRIES"}, + +/* 9.3.11. Relocation types for complex expressions */ + {R_HPPA_PUSH_CONST, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_CONST"}, + {R_HPPA_PUSH_PC, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_PC"}, + {R_HPPA_PUSH_SYM, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_SYM"}, + {R_HPPA_PUSH_GOTOFF, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_GOTOFF"}, + {R_HPPA_PUSH_ABS_CALL, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_ABS_CALL"}, + {R_HPPA_PUSH_PCREL_CALL, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_PCREL_CALL"}, + {R_HPPA_PUSH_PLABEL, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_PUSH_PLABEL"}, +{R_HPPA_MAX, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MAX"}, +{R_HPPA_MIN, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MIN"}, +{R_HPPA_ADD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ADD"}, +{R_HPPA_SUB, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_SUB"}, + {R_HPPA_MULT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MULT"}, +{R_HPPA_DIV, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_DIV"}, +{R_HPPA_MOD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_MOD"}, +{R_HPPA_AND, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_AND"}, + {R_HPPA_OR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_OR"}, +{R_HPPA_XOR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_XOR"}, +{R_HPPA_NOT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_NOT"}, + {R_HPPA_LSHIFT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LSHIFT"}, + {R_HPPA_ARITH_RSHIFT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_ARITH_RSHIFT"}, + {R_HPPA_LOGIC_RSHIFT, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_LOGIC_RSHIFT"}, +{R_HPPA_EXPR_F, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_L"}, + {R_HPPA_EXPR_L, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_L"}, + {R_HPPA_EXPR_R, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_R"}, + {R_HPPA_EXPR_LS, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_LS"}, + {R_HPPA_EXPR_RS, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_RS"}, + {R_HPPA_EXPR_LD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_LD"}, + {R_HPPA_EXPR_RD, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_RD"}, + {R_HPPA_EXPR_LR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_LR"}, + {R_HPPA_EXPR_RR, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_RR"}, + + {R_HPPA_EXPR_32, 0, 3, 32, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_32"}, + {R_HPPA_EXPR_21, 0, 3, 21, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_21"}, + {R_HPPA_EXPR_11, 0, 3, 11, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_11"}, + {R_HPPA_EXPR_14, 0, 3, 14, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_14"}, + {R_HPPA_EXPR_17, 0, 3, 17, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_17"}, + {R_HPPA_EXPR_12, 0, 3, 12, false, 0, false, true, hppa_elf_reloc, "R_HPPA_EXPR_12"}, + {R_HPPA_UNIMPLEMENTED, 0, 0, 0, false, 0, false, false, NULL, "R_HPPA_UNIMPLEMENTED"}, +}; - case 21: - const_part = insn & 0xffe00000; - dis_assemble_21(value,&rebuilt_part); - return const_part | rebuilt_part; +static symext_chainS *symext_rootP = NULL; +static symext_chainS *symext_lastP = NULL; - case 32: - const_part = 0; - return value; - - default: - fprintf(stderr,"Relocation problem : "); - fprintf(stderr,"Unrecognized reloc type %d (fmt=%d,fld=%d), in module %s\n", - r_type, r_format, r_field, abfd->filename); - } - return insn; +static unsigned long +DEFUN (hppa_elf_rebuild_insn, (abfd, insn, value, r_type, r_field, r_format), + bfd * abfd AND + unsigned long insn AND + unsigned long value AND + unsigned short r_type AND + unsigned short r_field AND + unsigned short r_format) +{ + unsigned long const_part; /* part of the instruction that does not change */ + unsigned long rebuilt_part; + + switch (r_format) + { + case 11: + { + unsigned w1, w; + + const_part = insn & 0xffffe002; + dis_assemble_12 (value, &w1, &w); + rebuilt_part = (w1 << 2) | w; + return const_part | rebuilt_part; + } + + case 12: + { + unsigned w1, w; + + const_part = insn & 0xffffe002; + dis_assemble_12 (value, &w1, &w); + rebuilt_part = (w1 << 2) | w; + return const_part | rebuilt_part; + } + + case 14: + const_part = insn & 0xffffc000; + low_sign_unext (value, 14, &rebuilt_part); + return const_part | rebuilt_part; + + case 17: + { + unsigned w1, w2, w; + + const_part = insn & 0xffe0e002; + dis_assemble_17 (value, &w1, &w2, &w); + rebuilt_part = (w2 << 2) | (w1 << 16) | w; + return const_part | rebuilt_part; + } + + case 21: + const_part = insn & 0xffe00000; + dis_assemble_21 (value, &rebuilt_part); + return const_part | rebuilt_part; + + case 32: + const_part = 0; + return value; + + default: + fprintf (stderr, "Relocation problem : "); + fprintf (stderr, + "Unrecognized reloc type %d (fmt=%d,fld=%d), in module %s\n", + r_type, r_format, r_field, abfd->filename); + } + return insn; } static unsigned long -DEFUN(hppa_elf_relocate_insn, - (abfd, input_sect, - insn, address, symp, sym_value, r_addend, - r_type, r_format, r_field, pcrel), - bfd *abfd AND - asection *input_sect AND - unsigned long insn AND - unsigned long address AND - asymbol *symp AND - long sym_value AND - long r_addend AND - unsigned short r_type AND - unsigned short r_format AND - unsigned short r_field AND - unsigned char pcrel) +DEFUN (hppa_elf_relocate_insn, + (abfd, input_sect, + insn, address, symp, sym_value, r_addend, + r_type, r_format, r_field, pcrel), + bfd * abfd AND + asection * input_sect AND + unsigned long insn AND + unsigned long address AND + asymbol * symp AND + long sym_value AND + long r_addend AND + unsigned short r_type AND + unsigned short r_format AND + unsigned short r_field AND + unsigned char pcrel) { - unsigned char opcode = get_opcode(insn); - long constant_value; - unsigned arg_reloc; - - switch ( opcode ) { - case LDO: - case LDB: - case LDH: - case LDW: - case LDWM: - case STB: - case STH: - case STW: - case STWM: - constant_value = ELF32_HPPA_R_CONSTANT(r_addend); - BFD_ASSERT(r_format == 14); - - if ( pcrel ) - sym_value -= address; - sym_value = hppa_field_adjust(sym_value,constant_value,r_field); - return hppa_elf_rebuild_insn(abfd,insn,sym_value,r_type,r_format, r_format); - - case COMICLR: - case SUBI: /* case SUBIO: */ - case ADDIT: /* case ADDITO: */ - case ADDI: /* case ADDIO: */ - BFD_ASSERT(r_format == 11); - - constant_value = ((insn & 0x1) << 10) | ((insn & 0xffe) >> 1); - sym_value = hppa_field_adjust(sym_value,constant_value,r_field); - return hppa_elf_rebuild_insn(abfd,insn,sym_value,r_type,r_field, r_format); - - case LDIL: - case ADDIL: - BFD_ASSERT(r_format == 21); - - constant_value = assemble_21(insn); - sym_value = hppa_field_adjust(sym_value,constant_value,r_field); - return hppa_elf_rebuild_insn(abfd,insn,sym_value,r_type,r_field, r_format); - - case BL: - case BE: - case BLE: - arg_reloc = ELF32_HPPA_R_ARG_RELOC(r_addend); - - BFD_ASSERT(r_format == 17); - - /* XXX computing constant_value is not needed??? */ - constant_value = assemble_17((insn & 0x001f0000) >> 16, - (insn & 0x00001ffc) >> 2, - insn & 1); - constant_value = sign_ext(constant_value,17); - if ( pcrel ) { - sym_value -= - address + input_sect->output_offset - + input_sect->output_section->vma; - sym_value = hppa_field_adjust(sym_value,-8,r_field); - } - else - sym_value = hppa_field_adjust(sym_value, constant_value, r_field); + unsigned char opcode = get_opcode (insn); + long constant_value; + unsigned arg_reloc; + + switch (opcode) + { + case LDO: + case LDB: + case LDH: + case LDW: + case LDWM: + case STB: + case STH: + case STW: + case STWM: + constant_value = ELF32_HPPA_R_CONSTANT (r_addend); + BFD_ASSERT (r_format == 14); + + if (pcrel) + sym_value -= address; + sym_value = hppa_field_adjust (sym_value, constant_value, r_field); + return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_format, r_format); + + case COMICLR: + case SUBI: /* case SUBIO: */ + case ADDIT: /* case ADDITO: */ + case ADDI: /* case ADDIO: */ + BFD_ASSERT (r_format == 11); + + constant_value = ((insn & 0x1) << 10) | ((insn & 0xffe) >> 1); + sym_value = hppa_field_adjust (sym_value, constant_value, r_field); + return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_field, r_format); + + case LDIL: + case ADDIL: + BFD_ASSERT (r_format == 21); + + constant_value = assemble_21 (insn); + constant_value += ELF32_HPPA_R_CONSTANT (r_addend); + sym_value = hppa_field_adjust (sym_value, constant_value, r_field); + return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_field, r_format); + + case BL: + case BE: + case BLE: + arg_reloc = ELF32_HPPA_R_ARG_RELOC (r_addend); + + BFD_ASSERT (r_format == 17); + + /* XXX computing constant_value is not needed??? */ + constant_value = assemble_17 ((insn & 0x001f0000) >> 16, + (insn & 0x00001ffc) >> 2, + insn & 1); + /* @@ Assumes only 32 bits. */ + constant_value = (constant_value << 15) >> 15; + if (pcrel) + { + sym_value -= + address + input_sect->output_offset + + input_sect->output_section->vma; + sym_value = hppa_field_adjust (sym_value, -8, r_field); + } + else + sym_value = hppa_field_adjust (sym_value, constant_value, r_field); - return hppa_elf_rebuild_insn(abfd,insn,sym_value >> 2,r_type,r_field, r_format); + return hppa_elf_rebuild_insn (abfd, insn, sym_value >> 2, r_type, r_field, r_format); - default: - if ( opcode == 0 && r_format == 32 ) { - constant_value = insn; - sym_value = hppa_field_adjust(sym_value,constant_value,r_field); - return sym_value; - } - else { - fprintf(stderr, - "Unrecognized opcode 0x%02x (fmt=%x,field=%x)\n", - opcode, r_format, r_field); - return (insn); - } + default: + if (opcode == 0) + { + BFD_ASSERT (r_format == 32); + constant_value = insn; + constant_value += ELF32_HPPA_R_CONSTANT (r_addend); + + return hppa_field_adjust (sym_value, constant_value, r_field); + } + else + { + fprintf (stderr, + "Unrecognized opcode 0x%02x (fmt=%x,field=%x)\n", + opcode, r_format, r_field); + return insn; } + } } static void -DEFUN(hppa_elf_relocate_unwind_table, - (abfd, input_sect, - data, address, symp, sym_value, r_addend, - r_type, r_format, r_field, pcrel), - bfd *abfd AND - asection *input_sect AND - PTR data AND - unsigned long address AND - asymbol *symp AND - long sym_value AND - long r_addend AND - unsigned short r_type AND - unsigned short r_format AND - unsigned short r_field AND - unsigned char pcrel) +DEFUN (hppa_elf_relocate_unwind_table, + (abfd, input_sect, + data, address, symp, sym_value, r_addend, + r_type, r_format, r_field, pcrel), + bfd * abfd AND + asection * input_sect AND + PTR data AND + unsigned long address AND + asymbol * symp AND + long sym_value AND + long r_addend AND + unsigned short r_type AND + unsigned short r_format AND + unsigned short r_field AND + unsigned char pcrel) { - bfd_byte *hit_data = address + (bfd_byte *)(data); - long constant_value; - long start_offset; - long end_offset; - long relocated_value; - int i; - - BFD_ASSERT( r_format == 32 ); - BFD_ASSERT( r_field == e_fsel ); - switch ( r_type ) { - case R_HPPA_UNWIND_ENTRY: - start_offset = bfd_get_32(abfd, hit_data); - relocated_value = hppa_field_adjust(sym_value,start_offset,r_field); - bfd_put_32(abfd, relocated_value ,hit_data); - - hit_data += sizeof(unsigned long); - end_offset = bfd_get_32(abfd, hit_data); - relocated_value = hppa_field_adjust(sym_value,end_offset,r_field); - bfd_put_32(abfd, relocated_value ,hit_data); - break; - - case R_HPPA_UNWIND_ENTRIES: - for ( i = 0; i < r_addend; i++,hit_data += 3*sizeof(unsigned long) ) { - unsigned int fsize; - start_offset = bfd_get_32(abfd, hit_data); - /* Stuff the symbol value into the first word */ - /* of the unwind descriptor */ - bfd_put_32(abfd, sym_value ,hit_data); - - hit_data += sizeof(unsigned long); - end_offset = bfd_get_32(abfd, hit_data); - /* We could also compute the ending offset for */ - /* the 2nd word of the unwind entry by */ - /* retrieving the st_size field of the Elf_Sym */ - /* structure stored with this symbol. We can */ - /* get it with: */ - /* e = (elf_symbol_type *)symp */ - /* fsize = e->internal_elf_sym.st_size */ - - fsize = end_offset - start_offset; - relocated_value = hppa_field_adjust(sym_value,fsize,r_field); - bfd_put_32(abfd, relocated_value ,hit_data); - - /* If this is not the last unwind entry, */ - /* adjust the symbol value. */ - if ( i+1 < r_addend ) { - start_offset = bfd_get_32(abfd, hit_data+3*sizeof(unsigned long)); - sym_value += fsize + start_offset - end_offset; - } - } - break; - - default: - fprintf(stderr, - "Unrecognized relocation type 0x%02x (fmt=%x,field=%x)\n", - r_type, r_format, r_field); + bfd_byte *hit_data = address + (bfd_byte *) (data); + long start_offset; + long end_offset; + long relocated_value; + int i; + + BFD_ASSERT (r_format == 32); + BFD_ASSERT (r_field == e_fsel); + switch (r_type) + { + case R_HPPA_UNWIND_ENTRY: + start_offset = bfd_get_32 (abfd, hit_data); + relocated_value = hppa_field_adjust (sym_value, start_offset, r_field); + bfd_put_32 (abfd, relocated_value, hit_data); + + hit_data += sizeof (unsigned long); + end_offset = bfd_get_32 (abfd, hit_data); + relocated_value = hppa_field_adjust (sym_value, end_offset, r_field); + bfd_put_32 (abfd, relocated_value, hit_data); + break; + + case R_HPPA_UNWIND_ENTRIES: + for (i = 0; i < r_addend; i++, hit_data += 3 * sizeof (unsigned long)) + { + unsigned int fsize; + start_offset = bfd_get_32 (abfd, hit_data); + /* Stuff the symbol value into the first word */ + /* of the unwind descriptor */ + bfd_put_32 (abfd, sym_value, hit_data); + + hit_data += sizeof (unsigned long); + end_offset = bfd_get_32 (abfd, hit_data); + /* We could also compute the ending offset for */ + /* the 2nd word of the unwind entry by */ + /* retrieving the st_size field of the Elf_Sym */ + /* structure stored with this symbol. We can */ + /* get it with: */ + /* e = (elf_symbol_type *)symp */ + /* fsize = e->internal_elf_sym.st_size */ + + fsize = end_offset - start_offset; + relocated_value = hppa_field_adjust (sym_value, fsize, r_field); + bfd_put_32 (abfd, relocated_value, hit_data); + + /* If this is not the last unwind entry, */ + /* adjust the symbol value. */ + if (i + 1 < r_addend) + { + start_offset = bfd_get_32 (abfd, hit_data + 3 * sizeof (unsigned long)); + sym_value += fsize + start_offset - end_offset; + } } - return; + break; + + default: + fprintf (stderr, + "Unrecognized relocation type 0x%02x (fmt=%x,field=%x)\n", + r_type, r_format, r_field); + } } /* Provided the symbol, returns the value reffed */ -static long -get_symbol_value(symbol) -asymbol *symbol; -{ - long relocation = 0; - - if ( symbol == (asymbol *)NULL ) - relocation = 0; - else if (symbol->section == &bfd_com_section) { - relocation = 0; - } - else { - relocation = symbol->value + - symbol->section->output_section->vma + - symbol->section->output_offset; - } - - return(relocation); +static long +get_symbol_value (symbol) + asymbol *symbol; +{ + long relocation = 0; + + if (symbol == (asymbol *) NULL) + relocation = 0; + else if (symbol->section == &bfd_com_section) + { + relocation = 0; + } + else + { + relocation = symbol->value + + symbol->section->output_section->vma + + symbol->section->output_offset; + } + + return (relocation); } /* This function provides a pretty straight-forward mapping between a */ @@ -475,576 +478,705 @@ asymbol *symbol; /* handled yet. */ static void - hppa_elf_gen_reloc_error(base_type,fmt,field) -elf32_hppa_reloc_type base_type; -int fmt; -int field; +hppa_elf_gen_reloc_error (base_type, fmt, field) + elf32_hppa_reloc_type base_type; + int fmt; + int field; { - fprintf(stderr, "undefined relocation: base=0x%x,fmt=0x%x,field=0x%x\n", - base_type, fmt, field); + fprintf (stderr, "undefined relocation: base=0x%x,fmt=0x%x,field=0x%x\n", + base_type, fmt, field); } -unsigned char -hppa_elf_gen_reloc_type(base_type, format, field) -elf32_hppa_reloc_type base_type; -int format; -int field; +elf32_hppa_reloc_type ** +hppa_elf_gen_reloc_type (abfd, base_type, format, field) + bfd *abfd; + elf32_hppa_reloc_type base_type; + int format; + int field; { #define UNDEFINED hppa_elf_gen_reloc_error(base_type,format,field); - elf32_hppa_reloc_type final_type = base_type; - switch ( base_type ) { - case R_HPPA: - switch (format) { - case 11: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_R11; - break; - case e_rssel: - final_type = R_HPPA_RS11; - break; - case e_rdsel: - final_type = R_HPPA_RD11; - break; - - case e_psel: - final_type = R_HPPA_PLABEL_11; - break; - case e_rpsel: - final_type = R_HPPA_PLABEL_R11; - break; - case e_lpsel: - case e_tsel: - case e_ltsel: - case e_rtsel: - - case e_fsel: - case e_lsel: - case e_lrsel: - case e_lssel: - case e_rrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 12: - UNDEFINED; - break; - case 14: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_R14; - break; - case e_rssel: - final_type = R_HPPA_RS14; - break; - case e_rdsel: - final_type = R_HPPA_RD14; - break; - case e_rrsel: - final_type = R_HPPA_RR14; - break; - - case e_psel: - final_type = R_HPPA_PLABEL_14; - break; - case e_rpsel: - final_type = R_HPPA_PLABEL_R14; - break; - case e_lpsel: - case e_tsel: - case e_ltsel: - case e_rtsel: - - case e_fsel: - case e_lsel: - case e_lssel: - case e_ldsel: - case e_lrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 17: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_R17; - break; - case e_rssel: - final_type = R_HPPA_RS17; - break; - case e_rdsel: - final_type = R_HPPA_RD17; - break; - case e_rrsel: - final_type = R_HPPA_RR17; - break; - case e_fsel: - case e_lsel: - case e_lssel: - case e_ldsel: - case e_lrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 21: - switch ( field ) { - case e_lsel: - final_type = R_HPPA_L21; - break; - case e_lssel: - final_type = R_HPPA_LS21; - break; - case e_ldsel: - final_type = R_HPPA_LD21; - break; - case e_lrsel: - final_type = R_HPPA_LR21; - break; - case e_lpsel: - final_type = R_HPPA_PLABEL_L21; - break; - case e_rsel: - case e_rssel: - case e_rdsel: - case e_rrsel: - case e_fsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 32: - switch ( field ) { - case e_fsel: - final_type = R_HPPA_32; - break; - case e_psel: - final_type = R_HPPA_PLABEL_32; - break; - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case R_HPPA_GOTOFF: - switch (format) { - case 11: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_GOTOFF_R11; - break; - case e_rssel: - final_type = R_HPPA_GOTOFF_RS11; - break; - case e_rdsel: - final_type = R_HPPA_GOTOFF_RD11; - break; - case e_fsel: - final_type = R_HPPA_GOTOFF_11; - break; - case e_lsel: - case e_lrsel: - case e_lssel: - case e_rrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 12: - UNDEFINED; - final_type = base_type; - break; - case 14: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_GOTOFF_R14; - break; - case e_rssel: - final_type = R_HPPA_GOTOFF_RS14; - break; - case e_rdsel: - final_type = R_HPPA_GOTOFF_RD14; - break; - case e_rrsel: - final_type = R_HPPA_GOTOFF_RR14; - break; - case e_fsel: - final_type = R_HPPA_GOTOFF_14; - break; - case e_lsel: - case e_lssel: - case e_ldsel: - case e_lrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 17: - UNDEFINED; - final_type = base_type; - break; - case 21: - switch ( field ) { - case e_lsel: - final_type = R_HPPA_GOTOFF_L21; - break; - case e_lssel: - final_type = R_HPPA_GOTOFF_LS21; - break; - case e_ldsel: - final_type = R_HPPA_GOTOFF_LD21; - break; - case e_lrsel: - final_type = R_HPPA_GOTOFF_LR21; - break; - case e_rsel: - case e_rssel: - case e_rdsel: - case e_rrsel: - case e_fsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 32: - UNDEFINED; - final_type = base_type; - break; - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case R_HPPA_PCREL_CALL: - switch (format) { - case 11: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_PCREL_CALL_R11; - break; - case e_rssel: - final_type = R_HPPA_PCREL_CALL_RS11; - break; - case e_rdsel: - final_type = R_HPPA_PCREL_CALL_RD11; - break; - case e_fsel: - final_type = R_HPPA_PCREL_CALL_11; - break; - case e_lsel: - case e_lrsel: - case e_lssel: - case e_rrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 12: - UNDEFINED; - final_type = base_type; - break; - case 14: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_PCREL_CALL_R14; - break; - case e_rssel: - final_type = R_HPPA_PCREL_CALL_RS14; - break; - case e_rdsel: - final_type = R_HPPA_PCREL_CALL_RD14; - break; - case e_rrsel: - final_type = R_HPPA_PCREL_CALL_RR14; - break; - case e_fsel: - final_type = R_HPPA_PCREL_CALL_14; - break; - case e_lsel: - case e_lssel: - case e_ldsel: - case e_lrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 17: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_PCREL_CALL_R17; - break; - case e_rssel: - final_type = R_HPPA_PCREL_CALL_RS17; - break; - case e_rdsel: - final_type = R_HPPA_PCREL_CALL_RD17; - break; - case e_rrsel: - final_type = R_HPPA_PCREL_CALL_RR17; - break; - case e_fsel: - final_type = R_HPPA_PCREL_CALL_17; - break; - case e_lsel: - case e_lssel: - case e_ldsel: - case e_lrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 21: - switch ( field ) { - case e_lsel: - final_type = R_HPPA_PCREL_CALL_L21; - break; - case e_lssel: - final_type = R_HPPA_PCREL_CALL_LS21; - break; - case e_ldsel: - final_type = R_HPPA_PCREL_CALL_LD21; - break; - case e_lrsel: - final_type = R_HPPA_PCREL_CALL_LR21; - break; - case e_rsel: - case e_rssel: - case e_rdsel: - case e_rrsel: - case e_fsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 32: - UNDEFINED; - final_type = base_type; - break; - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case R_HPPA_PLABEL: - switch (format) { - case 11: - switch (field) { - case e_fsel: - final_type = R_HPPA_PLABEL_11; - break; - case e_rsel: - final_type = R_HPPA_PLABEL_R11; - break; - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 14: - switch (field) { - case e_fsel: - final_type = R_HPPA_PLABEL_14; - break; - case e_rsel: - final_type = R_HPPA_PLABEL_R14; - break; - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 21: - switch (field) { - case e_lsel: - final_type = R_HPPA_PLABEL_L21; - break; - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 32: - switch (field) { - case e_fsel: - final_type = R_HPPA_PLABEL_32; - break; - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - default: - UNDEFINED; - final_type = base_type; - break; - } - case R_HPPA_ABS_CALL: - switch (format) { - case 11: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_ABS_CALL_R11; - break; - case e_rssel: - final_type = R_HPPA_ABS_CALL_RS11; - break; - case e_rdsel: - final_type = R_HPPA_ABS_CALL_RD11; - break; - case e_fsel: - final_type = R_HPPA_ABS_CALL_11; - break; - case e_lsel: - case e_lrsel: - case e_lssel: - case e_rrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 12: - UNDEFINED; - final_type = base_type; - break; - case 14: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_ABS_CALL_R14; - break; - case e_rssel: - final_type = R_HPPA_ABS_CALL_RS14; - break; - case e_rdsel: - final_type = R_HPPA_ABS_CALL_RD14; - break; - case e_rrsel: - final_type = R_HPPA_ABS_CALL_RR14; - break; - case e_fsel: - final_type = R_HPPA_ABS_CALL_14; - break; - case e_lsel: - case e_lssel: - case e_ldsel: - case e_lrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 17: - switch ( field ) { - case e_rsel: - final_type = R_HPPA_ABS_CALL_R17; - break; - case e_rssel: - final_type = R_HPPA_ABS_CALL_RS17; - break; - case e_rdsel: - final_type = R_HPPA_ABS_CALL_RD17; - break; - case e_rrsel: - final_type = R_HPPA_ABS_CALL_RR17; - break; - case e_fsel: - final_type = R_HPPA_ABS_CALL_17; - break; - case e_lsel: - case e_lssel: - case e_ldsel: - case e_lrsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 21: - switch ( field ) { - case e_lsel: - final_type = R_HPPA_ABS_CALL_L21; - break; - case e_lssel: - final_type = R_HPPA_ABS_CALL_LS21; - break; - case e_ldsel: - final_type = R_HPPA_ABS_CALL_LD21; - break; - case e_lrsel: - final_type = R_HPPA_ABS_CALL_LR21; - break; - case e_rsel: - case e_rssel: - case e_rdsel: - case e_rrsel: - case e_fsel: - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case 32: - UNDEFINED; - final_type = base_type; - break; - default: - UNDEFINED; - final_type = base_type; - break; - } - break; - case R_HPPA_UNWIND: - final_type = R_HPPA_UNWIND_ENTRY; - break; + elf32_hppa_reloc_type *finaltype; + elf32_hppa_reloc_type **final_types; + int i; + + final_types = (elf32_hppa_reloc_type **) bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type *) * 2); + BFD_ASSERT (final_types != 0); + + finaltype = (elf32_hppa_reloc_type *) bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type)); + BFD_ASSERT (finaltype != 0); + + final_types[0] = finaltype; + final_types[1] = NULL; + +#define final_type finaltype[0] + + final_type = base_type; + + switch (base_type) + { + case R_HPPA: + switch (format) + { + case 11: + switch (field) + { + case e_fsel: + final_type = R_HPPA_11; + break; + case e_rsel: + final_type = R_HPPA_R11; + break; + case e_rssel: + final_type = R_HPPA_RS11; + break; + case e_rdsel: + final_type = R_HPPA_RD11; + break; + + case e_psel: + final_type = R_HPPA_PLABEL_11; + break; + case e_rpsel: + final_type = R_HPPA_PLABEL_R11; + break; + case e_lpsel: + case e_tsel: + case e_ltsel: + case e_rtsel: + + case e_lsel: + case e_lrsel: + case e_lssel: + case e_rrsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 12: + UNDEFINED; + break; + case 14: + switch (field) + { + case e_rsel: + final_type = R_HPPA_R14; + break; + case e_rssel: + final_type = R_HPPA_RS14; + break; + case e_rdsel: + final_type = R_HPPA_RD14; + break; + case e_rrsel: + final_type = R_HPPA_RR14; + break; + + case e_psel: + final_type = R_HPPA_PLABEL_14; + break; + case e_rpsel: + final_type = R_HPPA_PLABEL_R14; + break; + case e_lpsel: + case e_tsel: + case e_ltsel: + case e_rtsel: + + case e_fsel: + case e_lsel: + case e_lssel: + case e_ldsel: + case e_lrsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 17: + switch (field) + { + case e_fsel: + final_type = R_HPPA_17; + break; + case e_rsel: + final_type = R_HPPA_R17; + break; + case e_rssel: + final_type = R_HPPA_RS17; + break; + case e_rdsel: + final_type = R_HPPA_RD17; + break; + case e_rrsel: + final_type = R_HPPA_RR17; + break; + case e_lsel: + case e_lssel: + case e_ldsel: + case e_lrsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 21: + switch (field) + { + case e_lsel: + final_type = R_HPPA_L21; + break; + case e_lssel: + final_type = R_HPPA_LS21; + break; + case e_ldsel: + final_type = R_HPPA_LD21; + break; + case e_lrsel: + final_type = R_HPPA_LR21; + break; + case e_lpsel: + final_type = R_HPPA_PLABEL_L21; + break; + case e_rsel: + case e_rssel: + case e_rdsel: + case e_rrsel: + case e_fsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 32: + switch (field) + { + case e_fsel: + final_type = R_HPPA_32; + break; + case e_psel: + final_type = R_HPPA_PLABEL_32; + break; + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case R_HPPA_GOTOFF: + switch (format) + { + case 11: + switch (field) + { + case e_rsel: + final_type = R_HPPA_GOTOFF_R11; + break; + case e_rssel: + final_type = R_HPPA_GOTOFF_RS11; + break; + case e_rdsel: + final_type = R_HPPA_GOTOFF_RD11; + break; + case e_fsel: + final_type = R_HPPA_GOTOFF_11; + break; + case e_lsel: + case e_lrsel: + case e_lssel: + case e_rrsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 12: + UNDEFINED; + final_type = base_type; + break; + case 14: + switch (field) + { + case e_rsel: + final_type = R_HPPA_GOTOFF_R14; + break; + case e_rssel: + final_type = R_HPPA_GOTOFF_RS14; + break; + case e_rdsel: + final_type = R_HPPA_GOTOFF_RD14; + break; + case e_rrsel: + final_type = R_HPPA_GOTOFF_RR14; + break; + case e_fsel: + final_type = R_HPPA_GOTOFF_14; + break; + case e_lsel: + case e_lssel: + case e_ldsel: + case e_lrsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 17: + UNDEFINED; + final_type = base_type; + break; + case 21: + switch (field) + { + case e_lsel: + final_type = R_HPPA_GOTOFF_L21; + break; + case e_lssel: + final_type = R_HPPA_GOTOFF_LS21; + break; + case e_ldsel: + final_type = R_HPPA_GOTOFF_LD21; + break; + case e_lrsel: + final_type = R_HPPA_GOTOFF_LR21; + break; + case e_rsel: + case e_rssel: + case e_rdsel: + case e_rrsel: + case e_fsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 32: + UNDEFINED; + final_type = base_type; + break; + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case R_HPPA_PCREL_CALL: + switch (format) + { + case 11: + switch (field) + { + case e_rsel: + final_type = R_HPPA_PCREL_CALL_R11; + break; + case e_rssel: + final_type = R_HPPA_PCREL_CALL_RS11; + break; + case e_rdsel: + final_type = R_HPPA_PCREL_CALL_RD11; + break; + case e_fsel: + final_type = R_HPPA_PCREL_CALL_11; + break; + case e_lsel: + case e_lrsel: + case e_lssel: + case e_rrsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 12: + UNDEFINED; + final_type = base_type; + break; + case 14: + switch (field) + { + case e_rsel: + final_type = R_HPPA_PCREL_CALL_R14; + break; + case e_rssel: + final_type = R_HPPA_PCREL_CALL_RS14; + break; + case e_rdsel: + final_type = R_HPPA_PCREL_CALL_RD14; + break; + case e_rrsel: + final_type = R_HPPA_PCREL_CALL_RR14; + break; + case e_fsel: + final_type = R_HPPA_PCREL_CALL_14; + break; + case e_lsel: + case e_lssel: + case e_ldsel: + case e_lrsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 17: + switch (field) + { + case e_rsel: + final_type = R_HPPA_PCREL_CALL_R17; + break; + case e_rssel: + final_type = R_HPPA_PCREL_CALL_RS17; + break; + case e_rdsel: + final_type = R_HPPA_PCREL_CALL_RD17; + break; + case e_rrsel: + final_type = R_HPPA_PCREL_CALL_RR17; + break; + case e_fsel: + final_type = R_HPPA_PCREL_CALL_17; + break; + case e_lsel: + case e_lssel: + case e_ldsel: + case e_lrsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 21: + switch (field) + { + case e_lsel: + final_type = R_HPPA_PCREL_CALL_L21; + break; + case e_lssel: + final_type = R_HPPA_PCREL_CALL_LS21; + break; + case e_ldsel: + final_type = R_HPPA_PCREL_CALL_LD21; + break; + case e_lrsel: + final_type = R_HPPA_PCREL_CALL_LR21; + break; + case e_rsel: + case e_rssel: + case e_rdsel: + case e_rrsel: + case e_fsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 32: + UNDEFINED; + final_type = base_type; + break; + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case R_HPPA_PLABEL: + switch (format) + { + case 11: + switch (field) + { + case e_fsel: + final_type = R_HPPA_PLABEL_11; + break; + case e_rsel: + final_type = R_HPPA_PLABEL_R11; + break; + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 14: + switch (field) + { + case e_fsel: + final_type = R_HPPA_PLABEL_14; + break; + case e_rsel: + final_type = R_HPPA_PLABEL_R14; + break; + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 21: + switch (field) + { + case e_lsel: + final_type = R_HPPA_PLABEL_L21; + break; + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 32: + switch (field) + { + case e_fsel: + final_type = R_HPPA_PLABEL_32; + break; + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + default: + UNDEFINED; + final_type = base_type; + break; + } + case R_HPPA_ABS_CALL: + switch (format) + { + case 11: + switch (field) + { + case e_rsel: + final_type = R_HPPA_ABS_CALL_R11; + break; + case e_rssel: + final_type = R_HPPA_ABS_CALL_RS11; + break; + case e_rdsel: + final_type = R_HPPA_ABS_CALL_RD11; + break; + case e_fsel: + final_type = R_HPPA_ABS_CALL_11; + break; + case e_lsel: + case e_lrsel: + case e_lssel: + case e_rrsel: default: - final_type = base_type; - break; + UNDEFINED; + final_type = base_type; + break; + } + break; + case 12: + UNDEFINED; + final_type = base_type; + break; + case 14: + switch (field) + { + case e_rsel: + final_type = R_HPPA_ABS_CALL_R14; + break; + case e_rssel: + final_type = R_HPPA_ABS_CALL_RS14; + break; + case e_rdsel: + final_type = R_HPPA_ABS_CALL_RD14; + break; + case e_rrsel: + final_type = R_HPPA_ABS_CALL_RR14; + break; + case e_fsel: + final_type = R_HPPA_ABS_CALL_14; + break; + case e_lsel: + case e_lssel: + case e_ldsel: + case e_lrsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 17: + switch (field) + { + case e_rsel: + final_type = R_HPPA_ABS_CALL_R17; + break; + case e_rssel: + final_type = R_HPPA_ABS_CALL_RS17; + break; + case e_rdsel: + final_type = R_HPPA_ABS_CALL_RD17; + break; + case e_rrsel: + final_type = R_HPPA_ABS_CALL_RR17; + break; + case e_fsel: + final_type = R_HPPA_ABS_CALL_17; + break; + case e_lsel: + case e_lssel: + case e_ldsel: + case e_lrsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 21: + switch (field) + { + case e_lsel: + final_type = R_HPPA_ABS_CALL_L21; + break; + case e_lssel: + final_type = R_HPPA_ABS_CALL_LS21; + break; + case e_ldsel: + final_type = R_HPPA_ABS_CALL_LD21; + break; + case e_lrsel: + final_type = R_HPPA_ABS_CALL_LR21; + break; + case e_rsel: + case e_rssel: + case e_rdsel: + case e_rrsel: + case e_fsel: + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case 32: + UNDEFINED; + final_type = base_type; + break; + default: + UNDEFINED; + final_type = base_type; + break; + } + break; + case R_HPPA_UNWIND: + final_type = R_HPPA_UNWIND_ENTRY; + break; + case R_HPPA_COMPLEX: + case R_HPPA_COMPLEX_PCREL_CALL: + case R_HPPA_COMPLEX_ABS_CALL: + final_types = (elf32_hppa_reloc_type **) bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type *) * 6); + BFD_ASSERT (final_types != 0); + + finaltype = (elf32_hppa_reloc_type *) bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type) * 5); + BFD_ASSERT (finaltype != 0); + + for (i = 0; i < 5; i++) + final_types[i] = &finaltype[i]; + + final_types[5] = NULL; + + finaltype[0] = R_HPPA_PUSH_SYM; + + if (base_type == R_HPPA_COMPLEX) + finaltype[1] = R_HPPA_PUSH_SYM; + else if (base_type == R_HPPA_COMPLEX_PCREL_CALL) + finaltype[1] = R_HPPA_PUSH_PCREL_CALL; + else /* base_type == R_HPPA_COMPLEX_ABS_CALL */ + finaltype[1] = R_HPPA_PUSH_ABS_CALL; + + finaltype[2] = R_HPPA_SUB; + + switch (field) + { + case e_fsel: + finaltype[3] = R_HPPA_EXPR_F; + break; + case e_lsel: + finaltype[3] = R_HPPA_EXPR_L; + break; + case e_rsel: + finaltype[3] = R_HPPA_EXPR_R; + break; + case e_lssel: + finaltype[3] = R_HPPA_EXPR_LS; + break; + case e_rssel: + finaltype[3] = R_HPPA_EXPR_RS; + break; + case e_ldsel: + finaltype[3] = R_HPPA_EXPR_LD; + break; + case e_rdsel: + finaltype[3] = R_HPPA_EXPR_RD; + break; + case e_lrsel: + finaltype[3] = R_HPPA_EXPR_LR; + break; + case e_rrsel: + finaltype[3] = R_HPPA_EXPR_RR; + break; } - return final_type; + switch (format) + { + case 11: + finaltype[4] = R_HPPA_EXPR_11; + break; + case 12: + finaltype[4] = R_HPPA_EXPR_12; + break; + case 14: + finaltype[4] = R_HPPA_EXPR_14; + break; + case 17: + finaltype[4] = R_HPPA_EXPR_17; + break; + case 21: + finaltype[4] = R_HPPA_EXPR_21; + break; + case 32: + finaltype[4] = R_HPPA_EXPR_32; + break; + } + + break; + + default: + final_type = base_type; + break; + } + + return final_types; } +#undef final_type + /* 12.4.4. Derive format from instruction */ /* Given a machine instruction, this function determines its format. */ @@ -1054,457 +1186,1526 @@ int field; /* should probably be reported as an error. */ unsigned char -hppa_elf_insn2fmt(type, insn) -elf32_hppa_reloc_type type; -unsigned long insn; +hppa_elf_insn2fmt (type, insn) + elf32_hppa_reloc_type type; + unsigned long insn; { - unsigned char fmt = 0; /* XXX: is this a proper default? */ - unsigned char op = get_opcode(insn); - - if ( type == R_HPPA_NONE ) - fmt = 0; - else { - switch ( op ) { - case ADDI: - case ADDIT: - case SUBI: - fmt = 11; - break; - case MOVB: - case MOVIB: - case COMBT: - case COMBF: - case COMIBT: - case COMIBF: - case ADDBT: - case ADDBF: - case ADDIBT: - case ADDIBF: - case BVB: - case BB: - fmt = 12; - break; - case LDO: - case LDB: - case LDH: - case LDW: - case LDWM: - case STB: - case STH: - case STW: - case STWM: - fmt = 14; - break; - case BL: - case BE: - case BLE: - fmt = 17; - break; - case LDIL: - case ADDIL: - fmt = 21; - break; - default: - fmt = 32; - break; - } - + unsigned char fmt = 0; /* XXX: is this a proper default? */ + unsigned char op = get_opcode (insn); + + if (type == R_HPPA_NONE) + fmt = 0; + else + { + switch (op) + { + case ADDI: + case ADDIT: + case SUBI: + fmt = 11; + break; + case MOVB: + case MOVIB: + case COMBT: + case COMBF: + case COMIBT: + case COMIBF: + case ADDBT: + case ADDBF: + case ADDIBT: + case ADDIBF: + case BVB: + case BB: + fmt = 12; + break; + case LDO: + case LDB: + case LDH: + case LDW: + case LDWM: + case STB: + case STH: + case STW: + case STWM: + fmt = 14; + break; + case BL: + case BE: + case BLE: + fmt = 17; + break; + case LDIL: + case ADDIL: + fmt = 21; + break; + default: + fmt = 32; + break; } - return fmt; + + } + return fmt; } /* this function is in charge of performing all the HP PA relocations */ -long global_value = 0; -long GOT_value = 0; /* XXX: need to calculate this! For HPUX, GOT == DP */ -asymbol *global_symbol = (asymbol *)NULL; +static long global_value = 0; +static long GOT_value = 0; /* XXX: need to calculate this! For HPUX, GOT == DP */ +static asymbol *global_symbol = (asymbol *) NULL; static bfd_reloc_status_type -DEFUN(hppa_elf_reloc,(abfd, reloc_entry, symbol_in, data, input_section, output_bfd), - bfd *abfd AND - arelent *reloc_entry AND - asymbol *symbol_in AND - PTR data AND - asection *input_section AND - bfd *output_bfd) +DEFUN (hppa_elf_reloc, (abfd, reloc_entry, symbol_in, data, input_section, output_bfd), + bfd * abfd AND + arelent * reloc_entry AND + asymbol * symbol_in AND + PTR data AND + asection * input_section AND + bfd * output_bfd) +{ + unsigned long insn; + long sym_value = 0; + + unsigned long addr = reloc_entry->address; /*+ input_section->vma*/ + bfd_byte *hit_data = addr + (bfd_byte *) (data); + unsigned short r_type = reloc_entry->howto->type & 0xFF; + unsigned short r_field = e_fsel; + boolean r_pcrel = reloc_entry->howto->pc_relative; + + /* howto->bitsize contains the format (11, 14, 21, etc) information */ + unsigned r_format = reloc_entry->howto->bitsize; + long r_addend = reloc_entry->addend; + + + if (output_bfd) + { + /* Partial linking - do nothing */ + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + if (symbol_in && symbol_in->section == &bfd_und_section) + return bfd_reloc_undefined; + + /* Check for stubs that might be required. */ + /* symbol_in = hppa_elf_stub_check (abfd, input_section->output_section->owner, reloc_entry); */ + + sym_value = get_symbol_value (symbol_in); + + /* compute value of $global$ if it is there. */ + + if (global_symbol == (asymbol *) NULL) + { + struct elf32_backend_data *bed + = (struct elf32_backend_data *) abfd->xvec->backend_data; + + if (bed && bed->global_sym) + { + asymbol *gsym = &bed->global_sym->symbol; + global_value + = gsym->value + + gsym->section->output_section->vma + + gsym->section->output_offset; + GOT_value = global_value; /* XXX: For HP-UX, GOT==DP */ + global_symbol = gsym; + } + } + + /* get the instruction word */ + insn = bfd_get_32 (abfd, hit_data); + + /* relocate the value based on the relocation type */ + + /* basic_type_1: relocation is relative to $global$ */ + /* basic_type_2: relocation is relative to the current GOT */ + /* basic_type_3: relocation is an absolute call */ + /* basic_type_4: relocation is an PC-relative call */ + /* basic_type_5: relocation is plabel reference */ + /* basic_type_6: relocation is an unwind table relocation */ + /* extended_type: unimplemented */ + + switch (r_type) + { + case R_HPPA_NONE: + break; + case R_HPPA_32: /* Symbol + Addend 32 */ + r_field = e_fsel; + goto do_basic_type_1; + case R_HPPA_11: /* Symbol + Addend 11 */ + r_field = e_fsel; + goto do_basic_type_1; + case R_HPPA_14: /* Symbol + Addend 14 */ + r_field = e_fsel; + goto do_basic_type_1; + case R_HPPA_17: /* Symbol + Addend 17 */ + r_field = e_fsel; + goto do_basic_type_1; + case R_HPPA_L21: /* L (Symbol, Addend) 21 */ + r_field = e_lsel; + goto do_basic_type_1; + case R_HPPA_R11: /* R (Symbol, Addend) 11 */ + r_field = e_rsel; + goto do_basic_type_1; + case R_HPPA_R14: /* R (Symbol, Addend) 14 */ + r_field = e_rsel; + goto do_basic_type_1; + case R_HPPA_R17: /* R (Symbol, Addend) 17 */ + r_field = e_rsel; + goto do_basic_type_1; + case R_HPPA_LS21: /* LS(Symbol, Addend) 21 */ + r_field = e_lssel; + goto do_basic_type_1; + case R_HPPA_RS11: /* RS(Symbol, Addend) 11 */ + r_field = e_rssel; + goto do_basic_type_1; + case R_HPPA_RS14: /* RS(Symbol, Addend) 14 */ + r_field = e_rssel; + goto do_basic_type_1; + case R_HPPA_RS17: /* RS(Symbol, Addend) 17 */ + r_field = e_ldsel; + goto do_basic_type_1; + case R_HPPA_LD21: /* LD(Symbol, Addend) 21 */ + r_field = e_ldsel; + goto do_basic_type_1; + case R_HPPA_RD11: /* RD(Symbol, Addend) 11 */ + r_field = e_rdsel; + goto do_basic_type_1; + case R_HPPA_RD14: /* RD(Symbol, Addend) 14 */ + r_field = e_rdsel; + goto do_basic_type_1; + case R_HPPA_RD17: /* RD(Symbol, Addend) 17 */ + r_field = e_rdsel; + goto do_basic_type_1; + case R_HPPA_LR21: /* LR(Symbol, Addend) 21 */ + r_field = e_lrsel; + goto do_basic_type_1; + case R_HPPA_RR14: /* RR(Symbol, Addend) 14 */ + r_field = e_rrsel; + goto do_basic_type_1; + case R_HPPA_RR17: /* RR(Symbol, Addend) 17 */ + r_field = e_rrsel; + + do_basic_type_1: + insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr, + symbol_in, sym_value, r_addend, + r_type, r_format, r_field, r_pcrel); + break; + + case R_HPPA_GOTOFF_11: /* Symbol - GOT + Addend 11 */ + r_field = e_fsel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_14: /* Symbol - GOT + Addend 14 */ + r_field = e_fsel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_L21: /* L (Sym - GOT, Addend) 21 */ + r_field = e_lsel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_R11: /* R (Sym - GOT, Addend) 11 */ + r_field = e_rsel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_R14: /* R (Sym - GOT, Addend) 14 */ + r_field = e_rsel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_LS21: /* LS(Sym - GOT, Addend) 21 */ + r_field = e_lssel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_RS11: /* RS(Sym - GOT, Addend) 11 */ + r_field = e_rssel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_RS14: /* RS(Sym - GOT, Addend) 14 */ + r_field = e_rssel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_LD21: /* LD(Sym - GOT, Addend) 21 */ + r_field = e_ldsel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_RD11: /* RD(Sym - GOT, Addend) 11 */ + r_field = e_rdsel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_RD14: /* RD(Sym - GOT, Addend) 14 */ + r_field = e_rdsel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_LR21: /* LR(Sym - GOT, Addend) 21 */ + r_field = e_lrsel; + goto do_basic_type_2; + case R_HPPA_GOTOFF_RR14: /* RR(Sym - GOT, Addend) 14 */ + r_field = e_rrsel; + do_basic_type_2: + sym_value -= GOT_value; + insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr, + symbol_in, sym_value, r_addend, + r_type, r_format, r_field, r_pcrel); + break; + + case R_HPPA_ABS_CALL_11: /* Symbol + Addend 11 */ + r_field = e_fsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_14: /* Symbol + Addend 14 */ + r_field = e_fsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_17: /* Symbol + Addend 17 */ + r_field = e_fsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_L21: /* L (Symbol, Addend) 21 */ + r_field = e_lsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_R11: /* R (Symbol, Addend) 11 */ + r_field = e_rsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_R14: /* R (Symbol, Addend) 14 */ + r_field = e_rsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_R17: /* R (Symbol, Addend) 17 */ + r_field = e_rsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_LS21: /* LS(Symbol, Addend) 21 */ + r_field = e_lssel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_RS11: /* RS(Symbol, Addend) 11 */ + r_field = e_lssel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_RS14: /* RS(Symbol, Addend) 14 */ + r_field = e_rssel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_RS17: /* RS(Symbol, Addend) 17 */ + r_field = e_rssel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_LD21: /* LD(Symbol, Addend) 21 */ + r_field = e_ldsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_RD11: /* RD(Symbol, Addend) 11 */ + r_field = e_rdsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_RD14: /* RD(Symbol, Addend) 14 */ + r_field = e_rdsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_RD17: /* RD(Symbol, Addend) 17 */ + r_field = e_rdsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_LR21: /* LR(Symbol, Addend) 21 */ + r_field = e_lrsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_RR14: /* RR(Symbol, Addend) 14 */ + r_field = e_rrsel; + goto do_basic_type_3; + case R_HPPA_ABS_CALL_RR17: /* RR(Symbol, Addend) 17 */ + r_field = e_rrsel; + do_basic_type_3: + insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr, + symbol_in, sym_value, r_addend, + r_type, r_format, r_field, r_pcrel); + break; + + case R_HPPA_PCREL_CALL_11: /* Symbol - PC + Addend 11 */ + r_field = e_fsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */ + r_field = e_fsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */ + r_field = e_fsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_L21:/* L (Symbol - PC, Addend) 21 */ + r_field = e_lsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_R11:/* R (Symbol - PC, Addend) 11 */ + r_field = e_rsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_R14:/* R (Symbol - PC, Addend) 14 */ + r_field = e_rsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_R17:/* R (Symbol - PC, Addend) 17 */ + r_field = e_rsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */ + r_field = e_lssel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */ + r_field = e_rssel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */ + r_field = e_rssel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_RS17: /* RS(Symbol - PC, Addend) 17 */ + r_field = e_rssel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_LD21: /* LD(Symbol - PC, Addend) 21 */ + r_field = e_ldsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_RD11: /* RD(Symbol - PC, Addend) 11 */ + r_field = e_rdsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_RD14: /* RD(Symbol - PC, Addend) 14 */ + r_field = e_rdsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_RD17: /* RD(Symbol - PC, Addend) 17 */ + r_field = e_rdsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */ + r_field = e_lrsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */ + r_field = e_rrsel; + goto do_basic_type_4; + case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 *//* #69 */ + r_field = e_rrsel; + do_basic_type_4: + insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr, + symbol_in, sym_value, r_addend, + r_type, r_format, r_field, r_pcrel); + break; + + case R_HPPA_PLABEL_32: + case R_HPPA_PLABEL_11: + case R_HPPA_PLABEL_14: + r_field = e_fsel; + goto do_basic_type_5; + case R_HPPA_PLABEL_L21: + r_field = e_lsel; + goto do_basic_type_5; + case R_HPPA_PLABEL_R11: + case R_HPPA_PLABEL_R14: + r_field = e_rsel; + do_basic_type_5: + insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr, + symbol_in, sym_value, r_addend, + r_type, r_format, r_field, r_pcrel); + break; + + case R_HPPA_UNWIND_ENTRY: + case R_HPPA_UNWIND_ENTRIES: + hppa_elf_relocate_unwind_table (abfd, input_section, data, addr, + symbol_in, sym_value, r_addend, + r_type, r_format, r_field, r_pcrel); + return (bfd_reloc_ok); + + case R_HPPA_PUSH_CONST: /* push Addend - - */ + case R_HPPA_PUSH_PC: /* push PC + Addend - - */ + case R_HPPA_PUSH_SYM: /* push Symbol + Addend - - */ + case R_HPPA_PUSH_GOTOFF: /* push Symbol - GOT + Addend - - */ + case R_HPPA_PUSH_ABS_CALL: /* push Symbol + Addend - - */ + case R_HPPA_PUSH_PCREL_CALL: /* push Symbol - PC + Addend - - */ + case R_HPPA_PUSH_PLABEL: /* [TBD] - - */ + case R_HPPA_MAX: /* pop A and B, push max(B,A) - - */ + case R_HPPA_MIN: /* pop A and B, push min(B,A) - - */ + case R_HPPA_ADD: /* pop A and B, push B + A - - */ + case R_HPPA_SUB: /* pop A and B, push B - A - - */ + case R_HPPA_MULT: /* pop A and B, push B * A - - */ + case R_HPPA_DIV: /* pop A and B, push B / A - - */ + case R_HPPA_MOD: /* pop A and B, push B % A - - */ + case R_HPPA_AND: /* pop A and B, push B & A - - */ + case R_HPPA_OR: /* pop A and B, push B | A - - */ + case R_HPPA_XOR: /* pop A and B, push B ^ A - - */ + case R_HPPA_NOT: /* pop A, push ~A - - */ + case R_HPPA_LSHIFT: /* pop A, push A << Addend - - */ + case R_HPPA_ARITH_RSHIFT: /* pop A, push A >> Addend - - */ + case R_HPPA_LOGIC_RSHIFT: /* pop A, push A >> Addend - - */ + case R_HPPA_EXPR_F: /* pop A, push A + Addend L - */ + case R_HPPA_EXPR_L: /* pop A, push L(A,Addend) L - */ + case R_HPPA_EXPR_R: /* pop A, push R(A,Addend) R - */ + case R_HPPA_EXPR_LS: /* pop A, push LS(A,Addend) LS - */ + case R_HPPA_EXPR_RS: /* pop A, push RS(A,Addend) RS - */ + case R_HPPA_EXPR_LD: /* pop A, push LD(A,Addend) LD - */ + case R_HPPA_EXPR_RD: /* pop A, push RD(A,Addend) RD - */ + case R_HPPA_EXPR_LR: /* pop A, push LR(A,Addend) LR - */ + case R_HPPA_EXPR_RR: /* pop A, push RR(A,Addend) RR - */ + + case R_HPPA_EXPR_32: /* pop - 32 */ + case R_HPPA_EXPR_21: /* pop - 21 */ + case R_HPPA_EXPR_11: /* pop - 11 */ + case R_HPPA_EXPR_14: /* pop - 14 */ + case R_HPPA_EXPR_17: /* pop - 17 */ + case R_HPPA_EXPR_12: /* pop - 12 */ + fprintf (stderr, "Relocation problem: "); + fprintf (stderr, "Unimplemented reloc type %d, in module %s\n", + r_type, abfd->filename); + return (bfd_reloc_notsupported); + default: + fprintf (stderr, "Relocation problem : "); + fprintf (stderr, "Unrecognized reloc type %d, in module %s\n", + r_type, abfd->filename); + return (bfd_reloc_dangerous); + } + + /* update the instruction word */ + bfd_put_32 (abfd, insn, hit_data); + + return (bfd_reloc_ok); + +} + +struct elf_reloc_map + { + unsigned char bfd_reloc_val; + unsigned char elf_reloc_val; + }; + +static CONST struct elf_reloc_map elf_hppa_reloc_map[] = { - unsigned long insn; - long sym_value = 0; - unsigned long unsigned_value; - long signed_value; - - unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/ - bfd_byte *hit_data = addr + (bfd_byte *)(data); - unsigned short r_type = reloc_entry->howto->type & 0xFF; - unsigned short r_field = e_fsel; - boolean r_pcrel = reloc_entry->howto->pc_relative; - - /* howto->bitsize contains the format (11, 14, 21, etc) information */ - unsigned r_format = reloc_entry->howto->bitsize; - long r_addend = reloc_entry->addend; - - - if (output_bfd) { - /* Partial linking - do nothing */ - reloc_entry->address += input_section->output_offset; - return bfd_reloc_ok; + {BFD_RELOC_NONE, R_HPPA_NONE,}, + {BFD_RELOC_HPPA_32, R_HPPA_32,}, + {BFD_RELOC_HPPA_11, R_HPPA_11,}, + {BFD_RELOC_HPPA_14, R_HPPA_14,}, + {BFD_RELOC_HPPA_17, R_HPPA_17,}, + {BFD_RELOC_HPPA_L21, R_HPPA_L21,}, + {BFD_RELOC_HPPA_R11, R_HPPA_R11,}, + {BFD_RELOC_HPPA_R14, R_HPPA_R14,}, + {BFD_RELOC_HPPA_R17, R_HPPA_R17,}, + {BFD_RELOC_HPPA_LS21, R_HPPA_LS21,}, + {BFD_RELOC_HPPA_RS11, R_HPPA_RS11,}, + {BFD_RELOC_HPPA_RS14, R_HPPA_RS14,}, + {BFD_RELOC_HPPA_RS17, R_HPPA_RS17,}, + {BFD_RELOC_HPPA_LD21, R_HPPA_LD21,}, + {BFD_RELOC_HPPA_RD11, R_HPPA_RD11,}, + {BFD_RELOC_HPPA_RD14, R_HPPA_RD14,}, + {BFD_RELOC_HPPA_RD17, R_HPPA_RD17,}, + {BFD_RELOC_HPPA_LR21, R_HPPA_LR21,}, + {BFD_RELOC_HPPA_RR14, R_HPPA_RR14,}, + {BFD_RELOC_HPPA_RR17, R_HPPA_RR17,}, + {BFD_RELOC_HPPA_GOTOFF_11, R_HPPA_GOTOFF_11,}, + {BFD_RELOC_HPPA_GOTOFF_14, R_HPPA_GOTOFF_14,}, + {BFD_RELOC_HPPA_GOTOFF_L21, R_HPPA_GOTOFF_L21,}, + {BFD_RELOC_HPPA_GOTOFF_R11, R_HPPA_GOTOFF_R11,}, + {BFD_RELOC_HPPA_GOTOFF_R14, R_HPPA_GOTOFF_R14,}, + {BFD_RELOC_HPPA_GOTOFF_LS21, R_HPPA_GOTOFF_LS21,}, + {BFD_RELOC_HPPA_GOTOFF_RS11, R_HPPA_GOTOFF_RS11,}, + {BFD_RELOC_HPPA_GOTOFF_RS14, R_HPPA_GOTOFF_RS14,}, + {BFD_RELOC_HPPA_GOTOFF_LD21, R_HPPA_GOTOFF_LD21,}, + {BFD_RELOC_HPPA_GOTOFF_RD11, R_HPPA_GOTOFF_RD11,}, + {BFD_RELOC_HPPA_GOTOFF_RD14, R_HPPA_GOTOFF_RD14,}, + {BFD_RELOC_HPPA_GOTOFF_LR21, R_HPPA_GOTOFF_LR21,}, + {BFD_RELOC_HPPA_GOTOFF_RR14, R_HPPA_GOTOFF_RR14,}, + {BFD_RELOC_HPPA_ABS_CALL_11, R_HPPA_ABS_CALL_11,}, + {BFD_RELOC_HPPA_ABS_CALL_14, R_HPPA_ABS_CALL_14,}, + {BFD_RELOC_HPPA_ABS_CALL_17, R_HPPA_ABS_CALL_17,}, + {BFD_RELOC_HPPA_ABS_CALL_L21, R_HPPA_ABS_CALL_L21,}, + {BFD_RELOC_HPPA_ABS_CALL_R11, R_HPPA_ABS_CALL_R11,}, + {BFD_RELOC_HPPA_ABS_CALL_R14, R_HPPA_ABS_CALL_R14,}, + {BFD_RELOC_HPPA_ABS_CALL_R17, R_HPPA_ABS_CALL_R17,}, + {BFD_RELOC_HPPA_ABS_CALL_LS21, R_HPPA_ABS_CALL_LS21,}, + {BFD_RELOC_HPPA_ABS_CALL_RS11, R_HPPA_ABS_CALL_RS11,}, + {BFD_RELOC_HPPA_ABS_CALL_RS14, R_HPPA_ABS_CALL_RS14,}, + {BFD_RELOC_HPPA_ABS_CALL_RS17, R_HPPA_ABS_CALL_RS17,}, + {BFD_RELOC_HPPA_ABS_CALL_LD21, R_HPPA_ABS_CALL_LD21,}, + {BFD_RELOC_HPPA_ABS_CALL_RD11, R_HPPA_ABS_CALL_RD11,}, + {BFD_RELOC_HPPA_ABS_CALL_RD14, R_HPPA_ABS_CALL_RD14,}, + {BFD_RELOC_HPPA_ABS_CALL_RD17, R_HPPA_ABS_CALL_RD17,}, + {BFD_RELOC_HPPA_ABS_CALL_LR21, R_HPPA_ABS_CALL_LR21,}, + {BFD_RELOC_HPPA_ABS_CALL_RR14, R_HPPA_ABS_CALL_RR14,}, + {BFD_RELOC_HPPA_ABS_CALL_RR17, R_HPPA_ABS_CALL_RR17,}, + {BFD_RELOC_HPPA_PCREL_CALL_11, R_HPPA_PCREL_CALL_11,}, + {BFD_RELOC_HPPA_PCREL_CALL_14, R_HPPA_PCREL_CALL_14,}, + {BFD_RELOC_HPPA_PCREL_CALL_17, R_HPPA_PCREL_CALL_17,}, + {BFD_RELOC_HPPA_PCREL_CALL_12, R_HPPA_PCREL_CALL_12,}, + {BFD_RELOC_HPPA_PCREL_CALL_L21, R_HPPA_PCREL_CALL_L21,}, + {BFD_RELOC_HPPA_PCREL_CALL_R11, R_HPPA_PCREL_CALL_R11,}, + {BFD_RELOC_HPPA_PCREL_CALL_R14, R_HPPA_PCREL_CALL_R14,}, + {BFD_RELOC_HPPA_PCREL_CALL_R17, R_HPPA_PCREL_CALL_R17,}, + {BFD_RELOC_HPPA_PCREL_CALL_LS21, R_HPPA_PCREL_CALL_LS21,}, + {BFD_RELOC_HPPA_PCREL_CALL_RS11, R_HPPA_PCREL_CALL_RS11,}, + {BFD_RELOC_HPPA_PCREL_CALL_RS14, R_HPPA_PCREL_CALL_RS14,}, + {BFD_RELOC_HPPA_PCREL_CALL_RS17, R_HPPA_PCREL_CALL_RS17,}, + {BFD_RELOC_HPPA_PCREL_CALL_LD21, R_HPPA_PCREL_CALL_LD21,}, + {BFD_RELOC_HPPA_PCREL_CALL_RD11, R_HPPA_PCREL_CALL_RD11,}, + {BFD_RELOC_HPPA_PCREL_CALL_RD14, R_HPPA_PCREL_CALL_RD14,}, + {BFD_RELOC_HPPA_PCREL_CALL_RD17, R_HPPA_PCREL_CALL_RD17,}, + {BFD_RELOC_HPPA_PCREL_CALL_LR21, R_HPPA_PCREL_CALL_LR21,}, + {BFD_RELOC_HPPA_PCREL_CALL_RR14, R_HPPA_PCREL_CALL_RR14,}, + {BFD_RELOC_HPPA_PCREL_CALL_RR17, R_HPPA_PCREL_CALL_RR17,}, + {BFD_RELOC_HPPA_PLABEL_32, R_HPPA_PLABEL_32,}, + {BFD_RELOC_HPPA_PLABEL_11, R_HPPA_PLABEL_11,}, + {BFD_RELOC_HPPA_PLABEL_14, R_HPPA_PLABEL_14,}, + {BFD_RELOC_HPPA_PLABEL_L21, R_HPPA_PLABEL_L21,}, + {BFD_RELOC_HPPA_PLABEL_R11, R_HPPA_PLABEL_R11,}, + {BFD_RELOC_HPPA_PLABEL_R14, R_HPPA_PLABEL_R14,}, + {BFD_RELOC_HPPA_DLT_32, R_HPPA_DLT_32,}, + {BFD_RELOC_HPPA_DLT_11, R_HPPA_DLT_11,}, + {BFD_RELOC_HPPA_DLT_14, R_HPPA_DLT_14,}, + {BFD_RELOC_HPPA_DLT_L21, R_HPPA_DLT_L21,}, + {BFD_RELOC_HPPA_DLT_R11, R_HPPA_DLT_R11,}, + {BFD_RELOC_HPPA_DLT_R14, R_HPPA_DLT_R14,}, + {BFD_RELOC_HPPA_UNWIND_ENTRY, R_HPPA_UNWIND_ENTRY,}, + {BFD_RELOC_HPPA_UNWIND_ENTRIES, R_HPPA_UNWIND_ENTRIES,}, +}; + +static reloc_howto_type * +elf_hppa_reloc_type_lookup (arch, code) + bfd_arch_info_type *arch; + bfd_reloc_code_real_type code; +{ + int i; + + if ((int) code < (int) R_HPPA_UNIMPLEMENTED) + { + BFD_ASSERT ((int) elf_hppa_howto_table[(int) code].type == (int) code); + return &elf_hppa_howto_table[(int) code]; + } + + return (reloc_howto_type *) 0; +} + +#define bfd_elf32_bfd_reloc_type_lookup elf_hppa_reloc_type_lookup + + +void +DEFUN (elf_hppa_tc_symbol, (abfd, symbolP, sym_idx), + bfd * abfd AND + elf32_symbol_type * symbolP AND + int sym_idx) +{ + symext_chainS *symextP; + unsigned int arg_reloc; + + if (!(symbolP->symbol.flags & BSF_FUNCTION)) + return; + + if (!((symbolP->symbol.flags & BSF_EXPORT) || + (symbolP->symbol.flags & BSF_GLOBAL))) + return; + + arg_reloc = symbolP->tc_data.hppa_arg_reloc; + + symextP = (symext_chainS *) bfd_alloc (abfd, sizeof (symext_chainS) * 2); + + symextP[0].entry = ELF32_HPPA_SX_WORD (HPPA_SXT_SYMNDX, sym_idx); + symextP[0].next = &symextP[1]; + + symextP[1].entry = ELF32_HPPA_SX_WORD (HPPA_SXT_ARG_RELOC, arg_reloc); + symextP[1].next = NULL; + + if (symext_rootP == NULL) + { + symext_rootP = &symextP[0]; + symext_lastP = &symextP[1]; + } + else + { + symext_lastP->next = &symextP[0]; + symext_lastP = &symextP[1]; + } +} + +static symext_entryS *symextn_contents = NULL; +static unsigned int symextn_contents_real_size = 0; + +void +DEFUN (elf_hppa_tc_make_sections, (abfd, ignored), + bfd * abfd AND + PTR ignored) +{ + symext_chainS *symextP; + symext_entryS *outbound_symexts; + int size; + int n; + int i; + extern char *stub_section_contents; /* forward declaration */ + void hppa_elf_stub_finish (); /* forward declaration */ + asection *symextn_sec; + + hppa_elf_stub_finish (abfd); + + if (symext_rootP == NULL) + return; + + for (n = 0, symextP = symext_rootP; symextP; symextP = symextP->next, ++n) + ; + + size = sizeof (symext_entryS) * n; + symextn_sec = bfd_get_section_by_name (abfd, SYMEXTN_SECTION_NAME); + if (symextn_sec == (asection *) 0) + { + symextn_sec = bfd_make_section (abfd, SYMEXTN_SECTION_NAME); + bfd_set_section_flags (abfd, + symextn_sec, + SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE | SEC_READONLY); + symextn_sec->output_section = symextn_sec; + symextn_sec->output_offset = 0; + bfd_set_section_alignment (abfd, symextn_sec, 2); + } + symextn_contents = (symext_entryS *) bfd_alloc (abfd, size); + + for (i = 0, symextP = symext_rootP; symextP; symextP = symextP->next, ++i) + symextn_contents[i] = symextP->entry; + symextn_contents_real_size = size; + bfd_set_section_size (abfd, symextn_sec, symextn_contents_real_size); + + return; +} + +/* Support for HP PA-RISC stub generation. + + Written by + + Center for Software Science + Department of Computer Science + University of Utah + + */ + +/* + HP-PA calling conventions state: + + 1. an argument relocation stub is required whenever the callee and + caller argument relocation bits do not match exactly. The exception + to this rule is if either the caller or callee argument relocation + bit are 00 (do not relocate). + + 2. The linker can optionally add a symbol record for the stub so that + the stub can be reused. The symbol record will be the same as the + original export symbol record, except that the relocation bits will + reflect the input of the stub, the type would be STUB and the symbol + value will be the location of the relocation stub. + + Other notes: + + Stubs can be inserted *before* the section of the caller. The stubs + can be treated as calls to code that manipulates the arguments. + + */ + +typedef enum + { + HPPA_STUB_ILLEGAL, + HPPA_STUB_ARG_RELOC, + HPPA_STUB_LONG_BRANCH + } hppa_stub_type; + +symext_entryS +elf32_hppa_get_sym_extn (abfd, sym, type) + bfd *abfd; + asymbol *sym; + int type; +{ + /* This function finds the symbol extension record of the */ + /* specified type for the specified symbol. It returns the */ + /* value of the symbol extension record. */ + symext_entryS retval; + + switch (type) + { + case HPPA_SXT_NULL: + retval = (symext_entryS) 0; + break; + case HPPA_SXT_SYMNDX: + retval = (symext_entryS) 0; /* XXX: need to fix this */ + break; + case HPPA_SXT_ARG_RELOC: + { + elf32_symbol_type *esymP = (elf32_symbol_type *) sym; + + retval = (symext_entryS) esymP->tc_data.hppa_arg_reloc; + break; + } + } + return retval; +} + + +typedef struct Elf32_hppa_Stub_description_struct + { + bfd *this_bfd; /* bfd to which this stub */ + /* applies */ + asection *stub_sec; /* stub section for this bfd */ + unsigned relocs_allocated_cnt; /* count of relocations for this stub section */ + unsigned real_size; + unsigned allocated_size; + int *stub_secp; /* pointer to the next available location in the buffer */ + char *stub_contents; /* contents of the stubs for this bfd */ + } + +Elf32_hppa_Stub_description; + +typedef struct Elf32_hppa_Stub_list_struct + { + Elf32_hppa_Stub_description *stub; + struct Elf32_hppa_Stub_list_struct *next; + } Elf32_hppa_Stub_list; + +static Elf32_hppa_Stub_list *elf_hppa_stub_rootP = NULL; + +/* Locate the stub section information for the given bfd. */ +static Elf32_hppa_Stub_description * +find_stubs (abfd, stub_sec) + bfd *abfd; + asection *stub_sec; +{ + Elf32_hppa_Stub_list *stubP; + + for (stubP = elf_hppa_stub_rootP; stubP; stubP = stubP->next) + { + if (stubP->stub->this_bfd == abfd + && stubP->stub->stub_sec == stub_sec) + return stubP->stub; + } + + return (Elf32_hppa_Stub_description *) NULL; +} + +static Elf32_hppa_Stub_description * +new_stub (abfd, stub_sec) + bfd *abfd; + asection *stub_sec; +{ + Elf32_hppa_Stub_description *stub = find_stubs (abfd, stub_sec); + + if (stub) + return stub; + + stub = (Elf32_hppa_Stub_description *) bfd_zalloc (abfd, sizeof (Elf32_hppa_Stub_description)); + stub->this_bfd = abfd; + stub->stub_sec = stub_sec; + stub->real_size = 0; + stub->allocated_size = 0; + stub->stub_contents = NULL; + stub->stub_secp = NULL; + + return stub; +} + +static void +add_stub (stub) + Elf32_hppa_Stub_description *stub; +{ + Elf32_hppa_Stub_list *new_entry; + + new_entry = (Elf32_hppa_Stub_list *) bfd_zalloc (stub->this_bfd, sizeof (Elf32_hppa_Stub_list)); + + if (new_entry) + { + new_entry->stub = stub; + + if (elf_hppa_stub_rootP) + { + new_entry->next = elf_hppa_stub_rootP; + elf_hppa_stub_rootP = new_entry; } + else + { + new_entry->next = (Elf32_hppa_Stub_list *) NULL; + elf_hppa_stub_rootP = new_entry; + } + } + else + { + bfd_error = no_memory; + bfd_perror ("add_stub"); + } +} + +#define ARGUMENTS 0 +#define RETURN_VALUE 1 + +#define NO_ARG_RELOC 0 +#define R_TO_FR 1 +#define FR_TO_R 2 +#define ARG_RELOC_ERR 3 - if ( symbol_in && symbol_in->section == &bfd_und_section ) - return bfd_reloc_undefined; +#define ARG0 0 +#define ARG1 1 +#define ARG2 2 +#define ARG3 3 +#define RETVAL 4 - sym_value = get_symbol_value(symbol_in); +#define AR_NO 0 +#define AR_GR 1 +#define AR_FR 2 +#define AR_FU 3 - /* compute value of $global$ if it is there. */ +static CONST char *CONST reloc_type_strings[] = +{ + "NONE", "GR->FR", "FR->GR", "ERROR" +}; - if ( global_symbol == (asymbol *)NULL ) { - struct elf_backend_data * bed - = (struct elf_backend_data *)abfd->xvec->backend_data; +static CONST char mismatches[4][4] = +{ /* CALLEE NONE CALLEE GR CALLEE FR CALLEE FU */ + /* CALLER NONE */ + {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC}, + /* CALLER GR */ + {NO_ARG_RELOC, NO_ARG_RELOC, R_TO_FR, R_TO_FR}, + /* CALLER FR */ + {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, NO_ARG_RELOC}, + /* CALLER FU */ + {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, NO_ARG_RELOC}, +}; - if ( bed && bed->global_sym ) { - asymbol *gsym = &bed->global_sym->symbol; - global_value - = gsym->value - + gsym->section->output_section->vma - + gsym->section->output_offset; - GOT_value = global_value; /* XXX: For HP-UX, GOT==DP */ - global_symbol = gsym; +static CONST char retval_mismatches[4][4] = +{ /* CALLEE NONE CALLEE GR CALLEE FR CALLEE FU */ + /* CALLER NONE */ + {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC}, + /* CALLER GR */ + {NO_ARG_RELOC, NO_ARG_RELOC, R_TO_FR, R_TO_FR}, + /* CALLER FR */ + {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, NO_ARG_RELOC}, + /* CALLER FU */ + {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, NO_ARG_RELOC}, +}; + +static int +type_of_mismatch (caller_bits, callee_bits, type) + int caller_bits; + int callee_bits; + int type; +{ + switch (type) + { + case ARGUMENTS: + return mismatches[caller_bits][callee_bits]; + case RETURN_VALUE: + return retval_mismatches[caller_bits][callee_bits]; + } + + return 0; +} + +#define EXTRACT_ARBITS(ar,which) ((ar) >> (8-(which*2))) & 3 + +#include "hppa_stubs.h" + +#define NEW_INSTRUCTION(desc,insn) \ + *((desc)->stub_secp)++ = (insn); \ + (desc)->real_size += sizeof(int); \ + bfd_set_section_size((desc)->this_bfd,(desc)->stub_sec,(desc)->real_size); + +void +hppa_elf_stub_finish (output_bfd) + bfd *output_bfd; +{ + extern bfd_error_vector_type bfd_error_vector; + Elf32_hppa_Stub_list *stub_list = elf_hppa_stub_rootP; + /* All the stubs have been built. Finish up building */ + /* stub section. Apply relocations to the section. */ + + for (; stub_list; stub_list = stub_list->next) + { + if (stub_list->stub->real_size) + { + bfd *stub_bfd = stub_list->stub->this_bfd; + asection *stub_sec = bfd_get_section_by_name (stub_bfd, ".hppa_linker_stubs"); + bfd_size_type reloc_size; + arelent **reloc_vector; + + BFD_ASSERT (stub_sec == stub_list->stub->stub_sec); + reloc_size = bfd_get_reloc_upper_bound (stub_bfd, stub_sec); + reloc_vector = (arelent **) alloca (reloc_size); + + BFD_ASSERT (stub_sec); + + /* We are not relaxing the section, so just copy the size info */ + stub_sec->_cooked_size = stub_sec->_raw_size; + stub_sec->reloc_done = true; + + + if (bfd_canonicalize_reloc (stub_bfd, + stub_sec, + reloc_vector, + output_bfd->outsymbols)) + { + arelent **parent; + for (parent = reloc_vector; *parent != (arelent *) NULL; + parent++) + { + bfd_reloc_status_type r = + bfd_perform_relocation (stub_bfd, + *parent, + stub_list->stub->stub_contents, + stub_sec, 0); + + + if (r != bfd_reloc_ok) + { + switch (r) + { + case bfd_reloc_undefined: + bfd_error_vector.undefined_symbol (*parent, NULL); + break; + case bfd_reloc_dangerous: + bfd_error_vector.reloc_dangerous (*parent, NULL); + break; + case bfd_reloc_outofrange: + case bfd_reloc_overflow: + bfd_error_vector.reloc_value_truncated (*parent, NULL); + break; + default: + abort (); + break; + } + } + } + } + + bfd_set_section_contents (output_bfd, + stub_sec, + stub_list->stub->stub_contents, + 0, + stub_list->stub->real_size); + + free (reloc_vector); + } + } +} + +void +hppa_elf_stub_branch_reloc (stub_desc, /* the bfd */ + output_bfd, /* the output bfd */ + stub_sym, /* the stub symbol */ + offset) /* the offset within the stub buffer (pre-calculated) */ + Elf32_hppa_Stub_description *stub_desc; + bfd *output_bfd; + asymbol *stub_sym; + int offset; +{ + /* Allocate a new relocation entry. */ + arelent relent; + int size; + + if (stub_desc->relocs_allocated_cnt == stub_desc->stub_sec->reloc_count) + { + if (stub_desc->stub_sec->relocation == NULL) + { + stub_desc->relocs_allocated_cnt = STUB_RELOC_INCR; + size = sizeof (arelent) * stub_desc->relocs_allocated_cnt; + stub_desc->stub_sec->relocation = (arelent *) zalloc (size); + } + else + { + stub_desc->relocs_allocated_cnt += STUB_RELOC_INCR; + size = sizeof (arelent) * stub_desc->relocs_allocated_cnt; + stub_desc->stub_sec->relocation = (arelent *) realloc (stub_desc->stub_sec->relocation, + size); + } + } + + /* Fill in the details. */ + relent.address = offset; + relent.addend = 0; + relent.sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *)); + BFD_ASSERT (relent.sym_ptr_ptr); + + relent.sym_ptr_ptr[0] = stub_sym; + relent.howto = bfd_reloc_type_lookup (stub_desc->this_bfd, R_HPPA_ABS_CALL_17); + + /* Save it in the array of relocations for the stub section. */ + + memcpy (&stub_desc->stub_sec->relocation[stub_desc->stub_sec->reloc_count++], + &relent, + sizeof (arelent)); +} + +asymbol * +hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types) + bfd *abfd; + bfd *output_bfd; + arelent *reloc_entry; + int stub_types[5]; +{ + asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs"); + Elf32_hppa_Stub_description *stub_desc = find_stubs (abfd, stub_sec); + asymbol *stub_sym = NULL; + asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text"); + int i; + char stub_sym_name[128]; + + if (!stub_sec) + { + BFD_ASSERT (stub_desc == NULL); + stub_sec = bfd_make_section (abfd, ".hppa_linker_stubs"); + bfd_set_section_flags (output_bfd, + stub_sec, + SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_READONLY); + stub_sec->output_section = output_text_section->output_section; + stub_sec->output_offset = 0; + bfd_set_section_alignment (output_bfd, stub_sec, 2); + stub_desc = new_stub (abfd, stub_sec); + add_stub (stub_desc); + } + + /* make sure we have a stub descriptor structure */ + + if (!stub_desc) + { + stub_desc = new_stub (abfd, stub_sec); + add_stub (stub_desc); + } + + /* allocate some space to write the stub */ + + if (!stub_desc->stub_contents) + { + stub_desc->allocated_size = STUB_BUFFER_INCR; + stub_desc->stub_contents = (char *) malloc (STUB_BUFFER_INCR); + } + else if ((stub_desc->allocated_size - stub_desc->real_size) < STUB_MAX_SIZE) + { + stub_desc->allocated_size = stub_desc->allocated_size + STUB_BUFFER_INCR; + stub_desc->stub_contents = (char *) realloc (stub_desc->stub_contents, + stub_desc->allocated_size); + } + + stub_desc->stub_secp = (int *) (stub_desc->stub_contents + stub_desc->real_size); + + /* create a symbol to point to this stub */ + stub_sym = bfd_make_empty_symbol (abfd); + sprintf (stub_sym_name, + "_stub_%s_%02d_%02d_%02d_%02d_%02d\000", + reloc_entry->sym_ptr_ptr[0]->name, + stub_types[0], stub_types[1], stub_types[2], stub_types[3], stub_types[4]); + stub_sym->name = bfd_zalloc (output_bfd, strlen (stub_sym_name) + 1); + strcpy ((char *) stub_sym->name, stub_sym_name); + stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents; + stub_sym->section = stub_sec; + stub_sym->flags = BSF_LOCAL | BSF_FUNCTION; + + /* redirect the original relocation from the old symbol (a function) */ + /* to the stub (the stub calls the function). */ + /* XXX do we need to change the relocation type? */ + reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *)); + reloc_entry->sym_ptr_ptr[0] = stub_sym; + + /* generate the beginning common section for all stubs */ + + NEW_INSTRUCTION (stub_desc, ADDI_8_SP); + + /* generate the code to move the arguments around */ + for (i = ARG0; i < ARG3; i++) + { + if (stub_types[i] != NO_ARG_RELOC) + { + /* A stub is needed */ + switch (stub_types[i]) + { + case R_TO_FR: + switch (i) + { + case ARG0: + NEW_INSTRUCTION (stub_desc, LDWS_M8SP_ARG0); + NEW_INSTRUCTION (stub_desc, FSTWS_FARG0_M8SP); + break; + case ARG1: + NEW_INSTRUCTION (stub_desc, LDWS_M8SP_ARG1); + NEW_INSTRUCTION (stub_desc, FSTWS_FARG1_M8SP); + break; + case ARG2: + NEW_INSTRUCTION (stub_desc, LDWS_M8SP_ARG1); + NEW_INSTRUCTION (stub_desc, FSTWS_FARG1_M8SP); + break; + case ARG3: + NEW_INSTRUCTION (stub_desc, LDWS_M8SP_ARG1); + NEW_INSTRUCTION (stub_desc, FSTWS_FARG1_M8SP); + break; + } + break; + + case FR_TO_R: + switch (i) + { + case ARG0: + NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG0); + NEW_INSTRUCTION (stub_desc, STWS_ARG0_M8SP); + break; + case ARG1: + NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG1); + NEW_INSTRUCTION (stub_desc, STWS_ARG1_M8SP); + break; + case ARG2: + NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG1); + NEW_INSTRUCTION (stub_desc, STWS_ARG1_M8SP); + break; + case ARG3: + NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG1); + NEW_INSTRUCTION (stub_desc, STWS_ARG1_M8SP); + break; + } + break; + + } + } + } + + /* generate the branch to the target routine */ + NEW_INSTRUCTION (stub_desc, STW_RP_M8SP); /* First, save the return address */ + NEW_INSTRUCTION (stub_desc, BL_XXX_RP); /* set up a branch to the function */ + + /* Fix the branch to the function. We can do this with a relocation. */ + + hppa_elf_stub_branch_reloc (stub_desc, + output_bfd, /* the output bfd */ + stub_sym, /* the stub symbol */ + (int) stub_desc->stub_secp - (int) stub_desc->stub_contents - 4); /* the offset within the stub buffer */ + + NEW_INSTRUCTION (stub_desc, NOP); + + /* generate the code to move the return value around */ + i = RETVAL; + if (stub_types[i] != NO_ARG_RELOC) + { + /* A stub is needed */ + switch (stub_types[i]) + { + case R_TO_FR: + NEW_INSTRUCTION (stub_desc, LDWS_M8SP_RET0); + NEW_INSTRUCTION (stub_desc, FSTWS_FRET0_M8SP); + break; + + case FR_TO_R: + NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FRET0); + NEW_INSTRUCTION (stub_desc, STWS_RET0_M8SP); + break; + } + } + + /* generate the ending common section for all stubs */ + + NEW_INSTRUCTION (stub_desc, LDW_M8SP_RP); /* restore return address */ + NEW_INSTRUCTION (stub_desc, SUBI_8_SP); + + /* XXX: can we assume this is a save return? */ + NEW_INSTRUCTION (stub_desc, BV_N_0RP); + + return stub_sym; +} + +int +hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types) + bfd *abfd; + arelent *reloc_entry; + int stub_types[5]; +{ + int i; + /* If the symbol is still undefined, there is */ + /* no way to know if a stub is required. */ + + if (reloc_entry->sym_ptr_ptr[0] && reloc_entry->sym_ptr_ptr[0]->section != &bfd_und_section) + { + symext_entryS caller_ar = (symext_entryS) ELF32_HPPA_R_ARG_RELOC (reloc_entry->addend); + symext_entryS callee_ar = elf32_hppa_get_sym_extn (abfd, + reloc_entry->sym_ptr_ptr[0], + HPPA_SXT_ARG_RELOC); + + /* Now, determine if a stub is */ + /* required. A stub is required if they the callee and caller */ + /* argument relocation bits are both nonzero and not equal. */ + + if (caller_ar && callee_ar) + { + /* Both are non-zero, we need to do further checking. */ + /* First, check if there is a return value relocation to be done */ + int caller_loc[5]; + int callee_loc[5]; + + callee_loc[RETVAL] = EXTRACT_ARBITS (callee_ar, RETVAL); + caller_loc[RETVAL] = EXTRACT_ARBITS (caller_ar, RETVAL); + callee_loc[ARG0] = EXTRACT_ARBITS (callee_ar, ARG0); + caller_loc[ARG0] = EXTRACT_ARBITS (caller_ar, ARG0); + callee_loc[ARG1] = EXTRACT_ARBITS (callee_ar, ARG1); + caller_loc[ARG1] = EXTRACT_ARBITS (caller_ar, ARG1); + callee_loc[ARG2] = EXTRACT_ARBITS (callee_ar, ARG2); + caller_loc[ARG2] = EXTRACT_ARBITS (caller_ar, ARG2); + callee_loc[ARG3] = EXTRACT_ARBITS (callee_ar, ARG3); + caller_loc[ARG3] = EXTRACT_ARBITS (caller_ar, ARG3); + + /* Check some special combinations. For */ + /* example, if FU appears in ARG1 or ARG3, we */ + /* can move it to ARG0 or ARG2, respectively. */ + + if (caller_loc[ARG0] == AR_FU || caller_loc[ARG1] == AR_FU) + { + caller_loc[ARG0] = AR_FU; + caller_loc[ARG1] = AR_NO; + } + if (caller_loc[ARG2] == AR_FU || caller_loc[ARG3] == AR_FU) + { + caller_loc[ARG2] = AR_FU; + caller_loc[ARG3] = AR_NO; + } + if (callee_loc[ARG0] == AR_FU || callee_loc[ARG1] == AR_FU) + { + callee_loc[ARG0] = AR_FU; + callee_loc[ARG1] = AR_NO; + } + if (callee_loc[ARG2] == AR_FU || callee_loc[ARG3] == AR_FU) + { + callee_loc[ARG2] = AR_FU; + callee_loc[ARG3] = AR_NO; + } + + stub_types[ARG0] = type_of_mismatch (caller_loc[ARG0], callee_loc[ARG0], ARGUMENTS); + stub_types[ARG1] = type_of_mismatch (caller_loc[ARG1], callee_loc[ARG1], ARGUMENTS); + stub_types[ARG2] = type_of_mismatch (caller_loc[ARG2], callee_loc[ARG2], ARGUMENTS); + stub_types[ARG3] = type_of_mismatch (caller_loc[ARG3], callee_loc[ARG3], ARGUMENTS); + stub_types[RETVAL] = type_of_mismatch (caller_loc[RETVAL], callee_loc[RETVAL], RETURN_VALUE); + + /* XXX for now, just report a */ + /* warning */ + + /* But, when we start building stubs, here are the steps involved: */ + /* 1. Determine what argument registers need to relocated. This */ + /* step is already done here. */ + /* 2. Build the appropriate stub in the .hppa_linker_stubs section. */ + /* This section should never appear in an object file. It is */ + /* only used internally. The output_section of the */ + /* .hppa_linker_stubs section is the .text section of the */ + /* executable. */ + /* 3. Build a symbol that is used (internally only) as the entry */ + /* point of the stub. */ + /* 4. Change the instruction of the original branch into a branch to */ + /* the stub routine. */ + /* 5. Build a relocation entry for the instruction of the original */ + /* branch to be R_HPPA_ABS_CALL to the stub routine. */ + + + if (stub_types[0] + || stub_types[1] + || stub_types[2] + || stub_types[3] + || stub_types[4]) + { +#ifdef DETECT_STUBS + fprintf (stderr, "Stub needed for %s @ %s+0x%x: callee/caller ar=0x%x/0x%x ", + reloc_entry->sym_ptr_ptr[0]->name, + abfd->filename, reloc_entry->address, + callee_ar, caller_ar); + for (i = ARG0; i < RETVAL; i++) + { + if (stub_types[i] != NO_ARG_RELOC) + { + fprintf (stderr, "%s%d: %s ", + i == RETVAL ? "ret" : "arg", + i == RETVAL ? 0 : i, + reloc_type_strings[stub_types[i]]); + } } + fprintf (stderr, "\n"); +#endif + return 1; + } + + } + } + return 0; +} + +asymbol * +hppa_elf_stub_check (abfd, output_bfd, reloc_entry) + bfd *abfd; + bfd *output_bfd; + arelent *reloc_entry; +{ + int stub_types[5]; + + switch (reloc_entry->howto->type) + { + case R_HPPA_ABS_CALL_11: /* Symbol + Addend 11 */ + case R_HPPA_ABS_CALL_14: /* Symbol + Addend 14 */ + case R_HPPA_ABS_CALL_17: /* Symbol + Addend 17 */ + case R_HPPA_ABS_CALL_L21: /* L (Symbol, Addend) 21 */ + case R_HPPA_ABS_CALL_R11: /* R (Symbol, Addend) 11 */ + case R_HPPA_ABS_CALL_R14: /* R (Symbol, Addend) 14 */ + case R_HPPA_ABS_CALL_R17: /* R (Symbol, Addend) 17 */ + case R_HPPA_ABS_CALL_LS21: /* LS(Symbol, Addend) 21 */ + case R_HPPA_ABS_CALL_RS11: /* RS(Symbol, Addend) 11 */ + case R_HPPA_ABS_CALL_RS14: /* RS(Symbol, Addend) 14 */ + case R_HPPA_ABS_CALL_RS17: /* RS(Symbol, Addend) 17 */ + case R_HPPA_ABS_CALL_LD21: /* LD(Symbol, Addend) 21 */ + case R_HPPA_ABS_CALL_RD11: /* RD(Symbol, Addend) 11 */ + case R_HPPA_ABS_CALL_RD14: /* RD(Symbol, Addend) 14 */ + case R_HPPA_ABS_CALL_RD17: /* RD(Symbol, Addend) 17 */ + case R_HPPA_ABS_CALL_LR21: /* LR(Symbol, Addend) 21 */ + case R_HPPA_ABS_CALL_RR14: /* RR(Symbol, Addend) 14 */ + case R_HPPA_ABS_CALL_RR17: /* RR(Symbol, Addend) 17 */ + + case R_HPPA_PCREL_CALL_11: /* Symbol - PC + Addend 11 */ + case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */ + case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */ + case R_HPPA_PCREL_CALL_12: /* Symbol - PC + Addend 12 */ + case R_HPPA_PCREL_CALL_L21:/* L (Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_R11:/* R (Symbol - PC, Addend) 11 */ + case R_HPPA_PCREL_CALL_R14:/* R (Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_R17:/* R (Symbol - PC, Addend) 17 */ + case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */ + case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_RS17: /* RS(Symbol - PC, Addend) 17 */ + case R_HPPA_PCREL_CALL_LD21: /* LD(Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_RD11: /* RD(Symbol - PC, Addend) 11 */ + case R_HPPA_PCREL_CALL_RD14: /* RD(Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_RD17: /* RD(Symbol - PC, Addend) 17 */ + case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */ + if (hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types)) + { + /* generate a stub */ + return hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types); } + break; + + default: + break; + + } + return reloc_entry->sym_ptr_ptr[0]; +} + +#define STUB_SYM_BUFFER_INC 5 + +asymbol * +hppa_look_for_stubs_in_section (abfd, output_bfd, asec, syms, new_sym_cnt) + bfd *abfd; + bfd *output_bfd; + asection *asec; + asymbol **syms; + int *new_sym_cnt; +{ + int i; + int stub_types[5]; + asymbol *new_syms = (asymbol *) NULL; + int new_cnt = 0; + int new_max = 0; + + /* Relocations are in different places depending on whether this is */ + /* an output section or an input section. Also, the relocations are */ + /* in different forms. Sigh. */ + /* Luckily, we have bfd_canonicalize_reloc() to straighten this out for us. */ + + /* if ( asec->orelocation || asec->relocation ) { */ + if (asec->reloc_count > 0) + { + arelent **reloc_vector = (arelent **) alloca (asec->reloc_count * (sizeof (arelent *) + 1)); + + bfd_canonicalize_reloc (abfd, asec, reloc_vector, syms); + for (i = 0; i < asec->reloc_count; i++) + { +#if 0 + arelent *rle; + + if ( asec->orelocation ) + rle = asec->orelocation[i]; + else + rle = asec->relocation+i; +#endif - /* get the instruction word */ - insn = bfd_get_32(abfd, hit_data); - - /* relocate the value based on the relocation type */ - - /* basic_type_1: relocation is relative to $global$ */ - /* basic_type_2: relocation is relative to the current GOT */ - /* basic_type_3: relocation is an absolute call */ - /* basic_type_4: relocation is an PC-relative call */ - /* basic_type_5: relocation is plabel reference */ - /* basic_type_6: relocation is an unwind table relocation */ - /* extended_type: unimplemented */ - - switch ( r_type ) { - case R_HPPA_NONE: - break; - case R_HPPA_32: /* Symbol + Addend 32 */ - - r_field = e_fsel; - goto do_basic_type_1; - case R_HPPA_L21: /* L (Symbol, Addend) 21 */ - r_field = e_lsel; - goto do_basic_type_1; - case R_HPPA_R11: /* R (Symbol, Addend) 11 */ - r_field = e_rsel; - goto do_basic_type_1; - case R_HPPA_R14: /* R (Symbol, Addend) 14 */ - r_field = e_rsel; - goto do_basic_type_1; - case R_HPPA_R17: /* R (Symbol, Addend) 17 */ - r_field = e_rsel; - goto do_basic_type_1; - case R_HPPA_LS21: /* LS(Symbol, Addend) 21 */ - r_field = e_lssel; - goto do_basic_type_1; - case R_HPPA_RS11: /* RS(Symbol, Addend) 11 */ - r_field = e_rssel; - goto do_basic_type_1; - case R_HPPA_RS14: /* RS(Symbol, Addend) 14 */ - r_field = e_rssel; - goto do_basic_type_1; - case R_HPPA_RS17: /* RS(Symbol, Addend) 17 */ - r_field = e_ldsel; - goto do_basic_type_1; - case R_HPPA_LD21: /* LD(Symbol, Addend) 21 */ - r_field = e_ldsel; - goto do_basic_type_1; - case R_HPPA_RD11: /* RD(Symbol, Addend) 11 */ - r_field = e_rdsel; - goto do_basic_type_1; - case R_HPPA_RD14: /* RD(Symbol, Addend) 14 */ - r_field = e_rdsel; - goto do_basic_type_1; - case R_HPPA_RD17: /* RD(Symbol, Addend) 17 */ - r_field = e_rdsel; - goto do_basic_type_1; - case R_HPPA_LR21: /* LR(Symbol, Addend) 21 */ - r_field = e_lrsel; - goto do_basic_type_1; - case R_HPPA_RR14: /* RR(Symbol, Addend) 14 */ - r_field = e_rrsel; - goto do_basic_type_1; - case R_HPPA_RR17: /* RR(Symbol, Addend) 17 */ - r_field = e_rrsel; - - do_basic_type_1: - insn = hppa_elf_relocate_insn(abfd, input_section, insn, addr, - symbol_in, sym_value, r_addend, - r_type, r_format, r_field, r_pcrel); - break; - - case R_HPPA_GOTOFF_11: /* Symbol - GOT + Addend 11 */ - r_field = e_fsel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_14: /* Symbol - GOT + Addend 14 */ - r_field = e_fsel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_L21: /* L (Sym - GOT, Addend) 21 */ - r_field = e_lsel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_R11: /* R (Sym - GOT, Addend) 11 */ - r_field = e_rsel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_R14: /* R (Sym - GOT, Addend) 14 */ - r_field = e_rsel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_LS21: /* LS(Sym - GOT, Addend) 21 */ - r_field = e_lssel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_RS11: /* RS(Sym - GOT, Addend) 11 */ - r_field = e_rssel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_RS14: /* RS(Sym - GOT, Addend) 14 */ - r_field = e_rssel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_LD21: /* LD(Sym - GOT, Addend) 21 */ - r_field = e_ldsel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_RD11: /* RD(Sym - GOT, Addend) 11 */ - r_field = e_rdsel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_RD14: /* RD(Sym - GOT, Addend) 14 */ - r_field = e_rdsel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_LR21: /* LR(Sym - GOT, Addend) 21 */ - r_field = e_lrsel; - goto do_basic_type_2; - case R_HPPA_GOTOFF_RR14: /* RR(Sym - GOT, Addend) 14 */ - r_field = e_rrsel; - do_basic_type_2: - sym_value -= GOT_value; - insn = hppa_elf_relocate_insn(abfd, input_section, insn, addr, - symbol_in, sym_value, r_addend, - r_type, r_format, r_field, r_pcrel); - break; - + arelent *rle = reloc_vector[i]; + + switch (rle->howto->type) + { case R_HPPA_ABS_CALL_11: /* Symbol + Addend 11 */ - r_field = e_fsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_14: /* Symbol + Addend 14 */ - r_field = e_fsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_17: /* Symbol + Addend 17 */ - r_field = e_fsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_L21: /* L (Symbol, Addend) 21 */ - r_field = e_lsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_R11: /* R (Symbol, Addend) 11 */ - r_field = e_rsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_R14: /* R (Symbol, Addend) 14 */ - r_field = e_rsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_R17: /* R (Symbol, Addend) 17 */ - r_field = e_rsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_LS21: /* LS(Symbol, Addend) 21 */ - r_field = e_lssel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_RS11: /* RS(Symbol, Addend) 11 */ - r_field = e_lssel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_RS14: /* RS(Symbol, Addend) 14 */ - r_field = e_rssel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_RS17: /* RS(Symbol, Addend) 17 */ - r_field = e_rssel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_LD21: /* LD(Symbol, Addend) 21 */ - r_field = e_ldsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_RD11: /* RD(Symbol, Addend) 11 */ - r_field = e_rdsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_RD14: /* RD(Symbol, Addend) 14 */ - r_field = e_rdsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_RD17: /* RD(Symbol, Addend) 17 */ - r_field = e_rdsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_LR21: /* LR(Symbol, Addend) 21 */ - r_field = e_lrsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_RR14: /* RR(Symbol, Addend) 14 */ - r_field = e_rrsel; - goto do_basic_type_3; case R_HPPA_ABS_CALL_RR17: /* RR(Symbol, Addend) 17 */ - r_field = e_rrsel; - do_basic_type_3: - insn = hppa_elf_relocate_insn(abfd, input_section, insn, addr, - symbol_in, sym_value, r_addend, - r_type, r_format, r_field, r_pcrel); - break; - + case R_HPPA_PCREL_CALL_11: /* Symbol - PC + Addend 11 */ - r_field = e_fsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */ - r_field = e_fsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */ - r_field = e_fsel; - goto do_basic_type_4; + case R_HPPA_PCREL_CALL_12: /* Symbol - PC + Addend 12 */ case R_HPPA_PCREL_CALL_L21: /* L (Symbol - PC, Addend) 21 */ - r_field = e_lsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_R11: /* R (Symbol - PC, Addend) 11 */ - r_field = e_rsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_R14: /* R (Symbol - PC, Addend) 14 */ - r_field = e_rsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_R17: /* R (Symbol - PC, Addend) 17 */ - r_field = e_rsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */ - r_field = e_lssel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */ - r_field = e_rssel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */ - r_field = e_rssel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_RS17: /* RS(Symbol - PC, Addend) 17 */ - r_field = e_rssel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_LD21: /* LD(Symbol - PC, Addend) 21 */ - r_field = e_ldsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_RD11: /* RD(Symbol - PC, Addend) 11 */ - r_field = e_rdsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_RD14: /* RD(Symbol - PC, Addend) 14 */ - r_field = e_rdsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_RD17: /* RD(Symbol - PC, Addend) 17 */ - r_field = e_rdsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */ - r_field = e_lrsel; - goto do_basic_type_4; case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */ - r_field = e_rrsel; - goto do_basic_type_4; - case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */ /* #69 */ - r_field = e_rrsel; - do_basic_type_4: - insn = hppa_elf_relocate_insn(abfd, input_section, insn, addr, - symbol_in, sym_value, r_addend, - r_type, r_format, r_field, r_pcrel); - break; - - case R_HPPA_PLABEL_32: - case R_HPPA_PLABEL_11: - case R_HPPA_PLABEL_14: - r_field = e_fsel; - goto do_basic_type_5; - case R_HPPA_PLABEL_L21: - r_field = e_lsel; - goto do_basic_type_5; - case R_HPPA_PLABEL_R11: - case R_HPPA_PLABEL_R14: - r_field = e_rsel; - do_basic_type_5: - insn = hppa_elf_relocate_insn(abfd, input_section, insn, addr, - symbol_in, sym_value, r_addend, - r_type, r_format, r_field, r_pcrel); - break; - - case R_HPPA_UNWIND_ENTRY: - case R_HPPA_UNWIND_ENTRIES: - hppa_elf_relocate_unwind_table(abfd, input_section, data, addr, - symbol_in, sym_value, r_addend, - r_type, r_format, r_field, r_pcrel); - return (bfd_reloc_ok); - - case R_HPPA_PUSH_CONST: /* push Addend - - */ - case R_HPPA_PUSH_SYM: /* push Symbol - - */ - case R_HPPA_PUSH_GOT: /* push GOT - - */ - case R_HPPA_PUSH_PC: /* push PC - - */ - case R_HPPA_PUSH_PROC: /* push Symbol - - */ - case R_HPPA_PUSH_PLABEL: /* [TBD] - - */ - case R_HPPA_MAX: /* pop A and B, push max(B,A) - - */ - case R_HPPA_MIN: /* pop A and B, push min(B,A) - - */ - case R_HPPA_ADD: /* pop A and B, push B + A - - */ - case R_HPPA_SUB: /* pop A and B, push B - A - - */ - case R_HPPA_MULT: /* pop A and B, push B * A - - */ - case R_HPPA_DIV: /* pop A and B, push B / A - - */ - case R_HPPA_MOD: /* pop A and B, push B % A - - */ - case R_HPPA_AND: /* pop A and B, push B & A - - */ - case R_HPPA_OR: /* pop A and B, push B | A - - */ - case R_HPPA_XOR: /* pop A and B, push B ^ A - - */ - case R_HPPA_NOT: /* pop A, push ~A - - */ - case R_HPPA_LSHIFT: /* pop A, push A << Addend - - */ - case R_HPPA_ARITH_RSHIFT: /* pop A, push A >> Addend - - */ - case R_HPPA_LOGIC_RSHIFT: /* pop A, push A >> Addend - - */ - case R_HPPA_EXPR_F: /* pop A, push A + Addend L - */ - case R_HPPA_EXPR_L: /* pop A, push L(A,Addend) L - */ - case R_HPPA_EXPR_R: /* pop A, push R(A,Addend) R - */ - case R_HPPA_EXPR_LS: /* pop A, push LS(A,Addend) LS - */ - case R_HPPA_EXPR_RS: /* pop A, push RS(A,Addend) RS - */ - case R_HPPA_EXPR_LD: /* pop A, push LD(A,Addend) LD - */ - case R_HPPA_EXPR_RD: /* pop A, push RD(A,Addend) RD - */ - case R_HPPA_EXPR_LR: /* pop A, push LR(A,Addend) LR - */ - case R_HPPA_EXPR_RR: /* pop A, push RR(A,Addend) RR - */ - - case R_HPPA_EXPR_32: /* pop - 32 */ - case R_HPPA_EXPR_21: /* pop - 21 */ - case R_HPPA_EXPR_11: /* pop - 11 */ - case R_HPPA_EXPR_14: /* pop - 14 */ - case R_HPPA_EXPR_17: /* pop - 17 */ - case R_HPPA_EXPR_12: /* pop - 12 */ - fprintf(stderr, "Relocation problem: "); - fprintf(stderr,"Unimplemented reloc type %d, in module %s\n", - r_type,abfd->filename); - return(bfd_reloc_notsupported); - default: - fprintf(stderr,"Relocation problem : "); - fprintf(stderr,"Unrecognized reloc type %d, in module %s\n", - r_type,abfd->filename); - return (bfd_reloc_dangerous); - } - - /* update the instruction word */ - bfd_put_32(abfd, insn ,hit_data); + case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */ + if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types)) + { + /* generate a stub */ + /* keep track of the new symbol */ + if (new_cnt == new_max) + { + new_max += STUB_SYM_BUFFER_INC; + new_syms = (asymbol *) realloc (new_syms, new_max * sizeof (asymbol)); + } + new_syms[new_cnt++] = *(hppa_elf_build_arg_reloc_stub (abfd, output_bfd, rle, stub_types)); + } + break; - return (bfd_reloc_ok); + default: + break; + } + } + } + *new_sym_cnt = new_cnt; + return new_syms; } -static reloc_howto_type * -elf_hppa_reloc_type_lookup (arch, code) - bfd_arch_info_type *arch; - bfd_reloc_code_real_type code; +int +hppa_look_for_stubs (abfd, output_bfd) + bfd *abfd; + bfd *output_bfd; { - if (code < R_HPPA_UNIMPLEMENTED) - return &elf_hppa_howto_table[code]; + /* bfd_map_over_sections(abfd,hppa_look_for_stubs_in_section,(PTR)output_bfd,NULL); */ +} - return (reloc_howto_type *)0; +boolean +DEFUN (hppa_elf_get_section_contents, (abfd, section, location, offset, count), + bfd * abfd AND + sec_ptr section AND + PTR location AND + file_ptr offset AND + bfd_size_type count) +{ + /* if this is the linker stub section, then we have the */ + /* section contents in memory rather than on disk. */ + if (strcmp (section->name, ".hppa_linker_stubs") == 0) + { + Elf32_hppa_Stub_description *stub_desc = find_stubs (abfd, section); + + if (count == 0) + return true; + if ((bfd_size_type) (offset + count) > section->_raw_size) + return (false); /* on error */ + if ((bfd_size_type) (offset + count) > stub_desc->real_size) + return (false); /* on error */ + + memcpy (location, stub_desc->stub_contents + offset, count); + return (true); + } + /* if this is the symbol extension section, then we have the */ + /* section contents in memory rather than on disk. */ + else if (strcmp (section->name, ".hppa_symextn") == 0) + { + if (count == 0) + return true; + if ((bfd_size_type) (offset + count) > section->_raw_size) + return (false); /* on error */ + if ((bfd_size_type) (offset + count) > symextn_contents_real_size) + return (false); /* on error */ + + memcpy (location, symextn_contents + offset, count); + return (true); + } + else + return bfd_generic_get_section_contents (abfd, section, location, offset, count); } -#define elf_bfd_reloc_type_lookup elf_hppa_reloc_type_lookup static void DEFUN (elf_info_to_howto, (abfd, cache_ptr, dst), - bfd *abfd AND - arelent *cache_ptr AND - Elf_Internal_Rela *dst) + bfd * abfd AND + arelent * cache_ptr AND + Elf32_Internal_Rela * dst) { abort (); } -#define TARGET_BIG_SYM elf32_hppa_vec +#define TARGET_BIG_SYM bfd_elf32_hppa_vec #define TARGET_BIG_NAME "elf32-hppa" #define ELF_ARCH bfd_arch_hppa |