diff options
-rw-r--r-- | bfd/README.hppaelf | 18 | ||||
-rw-r--r-- | bfd/elf32-hppa.c | 1648 |
2 files changed, 1666 insertions, 0 deletions
diff --git a/bfd/README.hppaelf b/bfd/README.hppaelf new file mode 100644 index 0000000..5d425ba --- /dev/null +++ b/bfd/README.hppaelf @@ -0,0 +1,18 @@ +HPPA/ELF README file: + + HP PA-RISC support was contributed by the Center for Software Science + at the University of Utah. + +This is the status of the hppa/elf code in bfd 2.0 as of January 29, 1993: + +1. It generates correct ELF files for all of the input I've given it +so far. I've used this version of libbfd.a to build an hppa/elf +version of gas 1.36 (emits SOM). I've run files as large as 200K +lines of assembly through it. + +2. ELF executables that are created *always* have 3 program header +table entries. This is due to the exec() support we have in the +kernel for ELF executables. It expects *exactly* 3 program header +table entries -- one for text, one for data, and one for bss. +Currently, there's no support for any other types of program header +table entries. diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c new file mode 100644 index 0000000..0b0ecbe --- /dev/null +++ b/bfd/elf32-hppa.c @@ -0,0 +1,1648 @@ +/* BFD back-end for HP PA-RISC ELF files. + Copyright (C) 1990-1991 Free Software Foundation, Inc. + + Written by + + Center for Software Science + Department of Computer Science + University of Utah + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" +#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 + in the Stratus FTX/Golf Object File Format (SED-1762) dated + November 19, 1992. +*/ + +/* + 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 + +/* 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 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) +{ + 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); + + 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); + } + } +} + +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) +{ + 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); + } + return; +} + +/* 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); +} + +/* This function provides a pretty straight-forward mapping between a */ +/* base relocation type, format and field into the relocation type */ +/* that will be emitted in an object file. The only wrinkle in the */ +/* mapping is that when the T, TR, TL, P, PR, or PL expression */ +/* prefixes are involved, the type gets promoted to a *_GOTOFF_* */ +/* relocation (in the case of T, TR, and TL) or a PLABEL relocation */ +/* (in the case of P, PR, and PL). */ + +/* NOTE: XXX the T, TR, TL, P, PR, and PL expression prefixes are not */ +/* handled yet. */ + +static void + 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); +} + +unsigned char +hppa_elf_gen_reloc_type(base_type, format, field) +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; + default: + final_type = base_type; + break; + } + + return final_type; +} + +/* 12.4.4. Derive format from instruction */ + +/* Given a machine instruction, this function determines its format. */ +/* The format can be determined solely from looking at the first six */ +/* bits (the major opcode) of the instruction. Several major opcodes */ +/* map to the same format. Opcodes which do not map to a known format */ +/* should probably be reported as an error. */ + +unsigned char +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; + } + + } + 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 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) +{ + 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; + } + + if ( symbol_in && symbol_in->section == &bfd_und_section ) + return bfd_reloc_undefined; + + sym_value = get_symbol_value(symbol_in); + + /* compute value of $global$ if it is there. */ + + if ( global_symbol == (asymbol *)NULL ) { + struct elf_backend_data * bed + = (struct elf_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_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_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); + + return (bfd_reloc_ok); + +} + +static reloc_howto_type * +elf_hppa_reloc_type_lookup (arch, code) + bfd_arch_info_type *arch; + bfd_reloc_code_real_type code; +{ + if ( code < R_HPPA_UNIMPLEMENTED ) { + return &elf_hppa_howto_table[code]; + } + + return (reloc_howto_type *)0; +} + +#include "elfcode.h" + +bfd_target elf_big_vec = +{ + /* name: identify kind of target */ + "elf-big", + + /* flavour: general indication about file */ + bfd_target_elf_flavour, + + /* byteorder_big_p: data is big endian */ + true, + + /* header_byteorder_big_p: header is also big endian */ + true, + + /* object_flags: mask of all file flags */ + (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | + DYNAMIC | WP_TEXT), + + /* section_flags: mask of all section flags */ + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY | + SEC_CODE | SEC_DATA), + + /* ar_pad_char: pad character for filenames within an archive header + FIXME: this really has nothing to do with ELF, this is a characteristic + of the archiver and/or os and should be independently tunable */ + '/', + + /* ar_max_namelen: maximum number of characters in an archive header + FIXME: this really has nothing to do with ELF, this is a characteristic + of the archiver and should be independently tunable. This value is + a WAG (wild a** guess) */ + 15, + + /* align_power_min: minimum alignment restriction for any section + FIXME: this value may be target machine dependent */ + 3, + + /* Routines to byte-swap various sized integers from the data sections */ + _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, + + /* Routines to byte-swap various sized integers from the file headers */ + _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, + + /* bfd_check_format: check the format of a file being read */ + { _bfd_dummy_target, /* unknown format */ + elf_object_p, /* assembler/linker output (object file) */ + bfd_generic_archive_p, /* an archive */ + elf_core_file_p /* a core file */ + }, + + /* bfd_set_format: set the format of a file being written */ + { bfd_false, + elf_mkobject, + _bfd_generic_mkarchive, + bfd_false + }, + + /* bfd_write_contents: write cached information into a file being written */ + { bfd_false, + elf_write_object_contents, + _bfd_write_archive_contents, + bfd_false + }, + + /* Initialize a jump table with the standard macro. All names start + with "elf" */ + JUMP_TABLE(elf), + + /* SWAP_TABLE */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + elf_hppa_reloc_type_lookup, + NULL, /* _bfd_make_debug_symbol */ + (PTR)&elf_hppa_backend_data +}; + +bfd_target elf_little_vec = +{ + /* name: identify kind of target */ + "elf-little", + + /* flavour: general indication about file */ + bfd_target_elf_flavour, + + /* byteorder_big_p: data is big endian */ + false, /* Nope -- this one's little endian */ + + /* header_byteorder_big_p: header is also big endian */ + false, /* Nope -- this one's little endian */ + + /* object_flags: mask of all file flags */ + (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | + DYNAMIC | WP_TEXT), + + /* section_flags: mask of all section flags */ + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY | + SEC_DATA), + + /* ar_pad_char: pad character for filenames within an archive header + FIXME: this really has nothing to do with ELF, this is a characteristic + of the archiver and/or os and should be independently tunable */ + '/', + + /* ar_max_namelen: maximum number of characters in an archive header + FIXME: this really has nothing to do with ELF, this is a characteristic + of the archiver and should be independently tunable. This value is + a WAG (wild a** guess) */ + 15, + + /* align_power_min: minimum alignment restriction for any section + FIXME: this value may be target machine dependent */ + 3, + + /* Routines to byte-swap various sized integers from the data sections */ + _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, + + /* Routines to byte-swap various sized integers from the file headers */ + _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, + + /* bfd_check_format: check the format of a file being read */ + { _bfd_dummy_target, /* unknown format */ + elf_object_p, /* assembler/linker output (object file) */ + bfd_generic_archive_p, /* an archive */ + elf_core_file_p /* a core file */ + }, + + /* bfd_set_format: set the format of a file being written */ + { bfd_false, + elf_mkobject, + _bfd_generic_mkarchive, + bfd_false + }, + + /* bfd_write_contents: write cached information into a file being written */ + { bfd_false, + elf_write_object_contents, + _bfd_write_archive_contents, + bfd_false + }, + + /* Initialize a jump table with the standard macro. All names start + with "elf" */ + JUMP_TABLE(elf), + + /* SWAP_TABLE */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + elf_hppa_reloc_type_lookup, + NULL, /* _bfd_make_debug_symbol */ + (PTR)&elf_hppa_backend_data +}; |