* breakpoint.c, breakpoint.h (breakpoint_init_inferior): New function
[deliverable/binutils-gdb.git] / bfd / elf32-hppa.c
CommitLineData
4c85cbfa
KR
1/* BFD back-end for HP PA-RISC ELF files.
2 Copyright (C) 1990-1991 Free Software Foundation, Inc.
3
4 Written by
e8f2240a 5
4c85cbfa
KR
6 Center for Software Science
7 Department of Computer Science
8 University of Utah
9
10This file is part of BFD, the Binary File Descriptor library.
11
12This program is free software; you can redistribute it and/or modify
13it under the terms of the GNU General Public License as published by
14the Free Software Foundation; either version 2 of the License, or
15(at your option) any later version.
16
17This program is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20GNU General Public License for more details.
21
22You should have received a copy of the GNU General Public License
23along with this program; if not, write to the Free Software
24Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
25
26#include "bfd.h"
27#include "sysdep.h"
28#include "libbfd.h"
29#include "obstack.h"
30#include "libelf.h"
31
4c85cbfa
KR
32/* ELF32/HPPA relocation support
33
34 This file contains ELF32/HPPA relocation support as specified
35 in the Stratus FTX/Golf Object File Format (SED-1762) dated
36 November 19, 1992.
37*/
38
39/*
40 Written by:
e8f2240a 41
4c85cbfa
KR
42 Center for Software Science
43 Department of Computer Science
44 University of Utah
45*/
46
47#include "elf32-hppa.h"
d9ad93bc 48#include "libhppa.h"
e8f2240a 49#include "aout/aout64.h"
d9ad93bc 50#include "hppa_stubs.h"
4c85cbfa
KR
51
52/* ELF/PA relocation howto entries */
53
e8f2240a 54static bfd_reloc_status_type hppa_elf_reloc ();
4c85cbfa 55
d9ad93bc 56static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
4c85cbfa 57{
e8f2240a
KR
58/* 'bitpos' and 'abs' are obsolete */
59/* type rs sz bsz pcrel bpos abs ovrf sf name */
60/* 9.3.4. Address relocation types */
d9ad93bc
KR
61 {R_HPPA_NONE, 0, 3, 19, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_NONE"},
62 {R_HPPA_32, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_32"},
63 {R_HPPA_11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_11"},
64 {R_HPPA_14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_14"},
65 {R_HPPA_17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_17"},
66{R_HPPA_L21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_L21"},
67{R_HPPA_R11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_R11"},
68{R_HPPA_R14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_R14"},
69{R_HPPA_R17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_R17"},
70 {R_HPPA_LS21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_LS21"},
71 {R_HPPA_RS11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RS11"},
72 {R_HPPA_RS14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RS14"},
73 {R_HPPA_RS17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RS17"},
74 {R_HPPA_LD21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_LD21"},
75 {R_HPPA_RD11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RD11"},
76 {R_HPPA_RD14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RD14"},
77 {R_HPPA_RD17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RD17"},
78 {R_HPPA_LR21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_LR21"},
79 {R_HPPA_RR14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RR14"},
80 {R_HPPA_RR17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_RR17"},
e8f2240a 81/* 9.3.5. GOTOFF address relocation types */
d9ad93bc
KR
82 {R_HPPA_GOTOFF_11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_11"},
83 {R_HPPA_GOTOFF_14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_14"},
84 {R_HPPA_GOTOFF_L21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_L21"},
85 {R_HPPA_GOTOFF_R11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_R11"},
86 {R_HPPA_GOTOFF_R14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_R14"},
87 {R_HPPA_GOTOFF_LS21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_LS21"},
88 {R_HPPA_GOTOFF_RS11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_RS11"},
89 {R_HPPA_GOTOFF_RS14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_RS14"},
90 {R_HPPA_GOTOFF_LD21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_LD21"},
91 {R_HPPA_GOTOFF_RD11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_RD11"},
92 {R_HPPA_GOTOFF_RD14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_RD14"},
93 {R_HPPA_GOTOFF_LR21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_LR21"},
94 {R_HPPA_GOTOFF_RR14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_GOTOFF_RR14"},
e8f2240a 95/* 9.3.6. Absolute call relocation types */
d9ad93bc
KR
96 {R_HPPA_ABS_CALL_11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_11"},
97 {R_HPPA_ABS_CALL_14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_14"},
98 {R_HPPA_ABS_CALL_17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_17"},
99 {R_HPPA_ABS_CALL_L21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_L21"},
100 {R_HPPA_ABS_CALL_R11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_R11"},
101 {R_HPPA_ABS_CALL_R14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_R14"},
102 {R_HPPA_ABS_CALL_R17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_R17"},
103 {R_HPPA_ABS_CALL_LS21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_LS21"},
104 {R_HPPA_ABS_CALL_RS11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS11"},
105 {R_HPPA_ABS_CALL_RS14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS14"},
106 {R_HPPA_ABS_CALL_RS17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RS17"},
107 {R_HPPA_ABS_CALL_LD21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_LD21"},
108 {R_HPPA_ABS_CALL_RD11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD11"},
109 {R_HPPA_ABS_CALL_RD14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD14"},
110 {R_HPPA_ABS_CALL_RD17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RD17"},
111 {R_HPPA_ABS_CALL_LR21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_LR21"},
112 {R_HPPA_ABS_CALL_RR14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RR14"},
113 {R_HPPA_ABS_CALL_RR17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ABS_CALL_RR17"},
e8f2240a 114/* 9.3.7. PC-relative call relocation types */
d9ad93bc
KR
115 {R_HPPA_PCREL_CALL_11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_11"},
116 {R_HPPA_PCREL_CALL_14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_14"},
117 {R_HPPA_PCREL_CALL_17, 0, 3, 17, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_17"},
118 {R_HPPA_PCREL_CALL_12, 0, 3, 12, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_12"},
119 {R_HPPA_PCREL_CALL_L21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_L21"},
120 {R_HPPA_PCREL_CALL_R11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R11"},
121 {R_HPPA_PCREL_CALL_R14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R14"},
122 {R_HPPA_PCREL_CALL_R17, 0, 3, 17, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_R17"},
123 {R_HPPA_PCREL_CALL_LS21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LS21"},
124 {R_HPPA_PCREL_CALL_RS11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS11"},
125 {R_HPPA_PCREL_CALL_RS14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS14"},
126 {R_HPPA_PCREL_CALL_RS17, 0, 3, 17, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RS17"},
127 {R_HPPA_PCREL_CALL_LD21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LD21"},
128 {R_HPPA_PCREL_CALL_RD11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD11"},
129 {R_HPPA_PCREL_CALL_RD14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD14"},
130 {R_HPPA_PCREL_CALL_RD17, 0, 3, 17, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RD17"},
131 {R_HPPA_PCREL_CALL_LR21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_LR21"},
132 {R_HPPA_PCREL_CALL_RR14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RR14"},
133 {R_HPPA_PCREL_CALL_RR17, 0, 3, 17, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PCREL_CALL_RR17"},
e8f2240a
KR
134
135/* 9.3.8. Plabel relocation types */
d9ad93bc
KR
136 {R_HPPA_PLABEL_32, 0, 3, 32, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_32"},
137 {R_HPPA_PLABEL_11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_11"},
138 {R_HPPA_PLABEL_14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_14"},
139 {R_HPPA_PLABEL_L21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_L21"},
140 {R_HPPA_PLABEL_R11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_R11"},
141 {R_HPPA_PLABEL_R14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_PLABEL_R14"},
e8f2240a
KR
142
143/* 9.3.9. Data linkage table (DLT) relocation types */
d9ad93bc
KR
144 {R_HPPA_DLT_32, 0, 3, 32, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_32"},
145 {R_HPPA_DLT_11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_11"},
146 {R_HPPA_DLT_14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_14"},
147 {R_HPPA_DLT_L21, 0, 3, 21, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_L21"},
148 {R_HPPA_DLT_R11, 0, 3, 11, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_R11"},
149 {R_HPPA_DLT_R14, 0, 3, 14, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_DLT_R14"},
e8f2240a
KR
150
151/* 9.3.10. Relocations for unwinder tables */
d9ad93bc
KR
152 {R_HPPA_UNWIND_ENTRY, 0, 3, 32, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_UNWIND_ENTRY"},
153 {R_HPPA_UNWIND_ENTRIES, 0, 3, 32, true, 0, complain_overflow_signed, hppa_elf_reloc, "R_HPPA_UNWIND_ENTRIES"},
e8f2240a
KR
154
155/* 9.3.11. Relocation types for complex expressions */
d9ad93bc
KR
156 {R_HPPA_PUSH_CONST, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_CONST"},
157 {R_HPPA_PUSH_PC, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_PC"},
158 {R_HPPA_PUSH_SYM, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_SYM"},
159 {R_HPPA_PUSH_GOTOFF, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_GOTOFF"},
160 {R_HPPA_PUSH_ABS_CALL, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_ABS_CALL"},
161 {R_HPPA_PUSH_PCREL_CALL, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_PCREL_CALL"},
162 {R_HPPA_PUSH_PLABEL, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_PUSH_PLABEL"},
163{R_HPPA_MAX, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_MAX"},
164{R_HPPA_MIN, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_MIN"},
165{R_HPPA_ADD, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ADD"},
166{R_HPPA_SUB, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_SUB"},
167 {R_HPPA_MULT, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_MULT"},
168{R_HPPA_DIV, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_DIV"},
169{R_HPPA_MOD, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_MOD"},
170{R_HPPA_AND, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_AND"},
171 {R_HPPA_OR, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_OR"},
172{R_HPPA_XOR, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_XOR"},
173{R_HPPA_NOT, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_NOT"},
174 {R_HPPA_LSHIFT, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_LSHIFT"},
175 {R_HPPA_ARITH_RSHIFT, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_ARITH_RSHIFT"},
176 {R_HPPA_LOGIC_RSHIFT, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_LOGIC_RSHIFT"},
177{R_HPPA_EXPR_F, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_L"},
178 {R_HPPA_EXPR_L, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_L"},
179 {R_HPPA_EXPR_R, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_R"},
180 {R_HPPA_EXPR_LS, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_LS"},
181 {R_HPPA_EXPR_RS, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_RS"},
182 {R_HPPA_EXPR_LD, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_LD"},
183 {R_HPPA_EXPR_RD, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_RD"},
184 {R_HPPA_EXPR_LR, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_LR"},
185 {R_HPPA_EXPR_RR, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_RR"},
186
187 {R_HPPA_EXPR_32, 0, 3, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_32"},
188 {R_HPPA_EXPR_21, 0, 3, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_21"},
189 {R_HPPA_EXPR_11, 0, 3, 11, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_11"},
190 {R_HPPA_EXPR_14, 0, 3, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_14"},
191 {R_HPPA_EXPR_17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_17"},
192 {R_HPPA_EXPR_12, 0, 3, 12, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_EXPR_12"},
193 {R_HPPA_STUB_CALL_17, 0, 3, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_HPPA_STUB_CALL_17"},
194 {R_HPPA_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_dont, NULL, "R_HPPA_UNIMPLEMENTED"},
e8f2240a 195};
4c85cbfa 196
d9ad93bc
KR
197static symext_chainS *symext_rootP;
198static symext_chainS *symext_lastP;
4c85cbfa 199
e8f2240a
KR
200static unsigned long
201DEFUN (hppa_elf_rebuild_insn, (abfd, insn, value, r_type, r_field, r_format),
202 bfd * abfd AND
203 unsigned long insn AND
204 unsigned long value AND
205 unsigned short r_type AND
206 unsigned short r_field AND
207 unsigned short r_format)
208{
209 unsigned long const_part; /* part of the instruction that does not change */
210 unsigned long rebuilt_part;
211
212 switch (r_format)
213 {
214 case 11:
215 {
216 unsigned w1, w;
217
218 const_part = insn & 0xffffe002;
219 dis_assemble_12 (value, &w1, &w);
220 rebuilt_part = (w1 << 2) | w;
221 return const_part | rebuilt_part;
222 }
223
224 case 12:
225 {
226 unsigned w1, w;
227
228 const_part = insn & 0xffffe002;
229 dis_assemble_12 (value, &w1, &w);
230 rebuilt_part = (w1 << 2) | w;
231 return const_part | rebuilt_part;
232 }
233
234 case 14:
235 const_part = insn & 0xffffc000;
236 low_sign_unext (value, 14, &rebuilt_part);
237 return const_part | rebuilt_part;
238
239 case 17:
240 {
241 unsigned w1, w2, w;
242
243 const_part = insn & 0xffe0e002;
244 dis_assemble_17 (value, &w1, &w2, &w);
245 rebuilt_part = (w2 << 2) | (w1 << 16) | w;
246 return const_part | rebuilt_part;
247 }
248
249 case 21:
250 const_part = insn & 0xffe00000;
251 dis_assemble_21 (value, &rebuilt_part);
252 return const_part | rebuilt_part;
253
254 case 32:
255 const_part = 0;
256 return value;
257
258 default:
259 fprintf (stderr, "Relocation problem : ");
260 fprintf (stderr,
261 "Unrecognized reloc type %d (fmt=%d,fld=%d), in module %s\n",
262 r_type, r_format, r_field, abfd->filename);
263 }
264 return insn;
4c85cbfa
KR
265}
266
267static unsigned long
e8f2240a
KR
268DEFUN (hppa_elf_relocate_insn,
269 (abfd, input_sect,
270 insn, address, symp, sym_value, r_addend,
271 r_type, r_format, r_field, pcrel),
272 bfd * abfd AND
273 asection * input_sect AND
274 unsigned long insn AND
275 unsigned long address AND
276 asymbol * symp AND
277 long sym_value AND
278 long r_addend AND
279 unsigned short r_type AND
280 unsigned short r_format AND
281 unsigned short r_field AND
282 unsigned char pcrel)
4c85cbfa 283{
e8f2240a
KR
284 unsigned char opcode = get_opcode (insn);
285 long constant_value;
286 unsigned arg_reloc;
287
288 switch (opcode)
289 {
290 case LDO:
291 case LDB:
292 case LDH:
293 case LDW:
294 case LDWM:
295 case STB:
296 case STH:
297 case STW:
298 case STWM:
299 constant_value = ELF32_HPPA_R_CONSTANT (r_addend);
300 BFD_ASSERT (r_format == 14);
301
302 if (pcrel)
303 sym_value -= address;
304 sym_value = hppa_field_adjust (sym_value, constant_value, r_field);
d9ad93bc 305 return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_field, r_format);
e8f2240a
KR
306
307 case COMICLR:
308 case SUBI: /* case SUBIO: */
309 case ADDIT: /* case ADDITO: */
310 case ADDI: /* case ADDIO: */
311 BFD_ASSERT (r_format == 11);
312
313 constant_value = ((insn & 0x1) << 10) | ((insn & 0xffe) >> 1);
314 sym_value = hppa_field_adjust (sym_value, constant_value, r_field);
315 return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_field, r_format);
316
317 case LDIL:
318 case ADDIL:
319 BFD_ASSERT (r_format == 21);
320
321 constant_value = assemble_21 (insn);
322 constant_value += ELF32_HPPA_R_CONSTANT (r_addend);
323 sym_value = hppa_field_adjust (sym_value, constant_value, r_field);
324 return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_field, r_format);
325
326 case BL:
327 case BE:
328 case BLE:
329 arg_reloc = ELF32_HPPA_R_ARG_RELOC (r_addend);
330
331 BFD_ASSERT (r_format == 17);
332
333 /* XXX computing constant_value is not needed??? */
334 constant_value = assemble_17 ((insn & 0x001f0000) >> 16,
335 (insn & 0x00001ffc) >> 2,
336 insn & 1);
337 /* @@ Assumes only 32 bits. */
338 constant_value = (constant_value << 15) >> 15;
339 if (pcrel)
340 {
341 sym_value -=
342 address + input_sect->output_offset
343 + input_sect->output_section->vma;
344 sym_value = hppa_field_adjust (sym_value, -8, r_field);
345 }
346 else
347 sym_value = hppa_field_adjust (sym_value, constant_value, r_field);
4c85cbfa 348
e8f2240a 349 return hppa_elf_rebuild_insn (abfd, insn, sym_value >> 2, r_type, r_field, r_format);
4c85cbfa 350
e8f2240a
KR
351 default:
352 if (opcode == 0)
353 {
354 BFD_ASSERT (r_format == 32);
355 constant_value = insn;
356 constant_value += ELF32_HPPA_R_CONSTANT (r_addend);
357
358 return hppa_field_adjust (sym_value, constant_value, r_field);
359 }
360 else
361 {
362 fprintf (stderr,
363 "Unrecognized opcode 0x%02x (fmt=%x,field=%x)\n",
364 opcode, r_format, r_field);
365 return insn;
4c85cbfa 366 }
e8f2240a 367 }
4c85cbfa
KR
368}
369
370static void
e8f2240a
KR
371DEFUN (hppa_elf_relocate_unwind_table,
372 (abfd, input_sect,
373 data, address, symp, sym_value, r_addend,
374 r_type, r_format, r_field, pcrel),
375 bfd * abfd AND
376 asection * input_sect AND
377 PTR data AND
378 unsigned long address AND
379 asymbol * symp AND
380 long sym_value AND
381 long r_addend AND
382 unsigned short r_type AND
383 unsigned short r_format AND
384 unsigned short r_field AND
385 unsigned char pcrel)
4c85cbfa 386{
e8f2240a
KR
387 bfd_byte *hit_data = address + (bfd_byte *) (data);
388 long start_offset;
389 long end_offset;
390 long relocated_value;
391 int i;
392
393 BFD_ASSERT (r_format == 32);
394 BFD_ASSERT (r_field == e_fsel);
395 switch (r_type)
396 {
397 case R_HPPA_UNWIND_ENTRY:
398 start_offset = bfd_get_32 (abfd, hit_data);
399 relocated_value = hppa_field_adjust (sym_value, start_offset, r_field);
400 bfd_put_32 (abfd, relocated_value, hit_data);
401
402 hit_data += sizeof (unsigned long);
403 end_offset = bfd_get_32 (abfd, hit_data);
404 relocated_value = hppa_field_adjust (sym_value, end_offset, r_field);
405 bfd_put_32 (abfd, relocated_value, hit_data);
406 break;
407
408 case R_HPPA_UNWIND_ENTRIES:
409 for (i = 0; i < r_addend; i++, hit_data += 3 * sizeof (unsigned long))
410 {
d9ad93bc 411 unsigned int adjustment;
e8f2240a
KR
412 start_offset = bfd_get_32 (abfd, hit_data);
413 /* Stuff the symbol value into the first word */
414 /* of the unwind descriptor */
415 bfd_put_32 (abfd, sym_value, hit_data);
d9ad93bc 416 adjustment = sym_value - start_offset;
e8f2240a
KR
417
418 hit_data += sizeof (unsigned long);
d9ad93bc
KR
419 end_offset = adjustment + bfd_get_32 (abfd, hit_data);
420 bfd_put_32 (abfd, end_offset, hit_data);
e8f2240a
KR
421
422 /* If this is not the last unwind entry, */
423 /* adjust the symbol value. */
424 if (i + 1 < r_addend)
425 {
426 start_offset = bfd_get_32 (abfd, hit_data + 3 * sizeof (unsigned long));
d9ad93bc 427 sym_value = start_offset + adjustment;
e8f2240a 428 }
4c85cbfa 429 }
e8f2240a
KR
430 break;
431
432 default:
433 fprintf (stderr,
434 "Unrecognized relocation type 0x%02x (fmt=%x,field=%x)\n",
435 r_type, r_format, r_field);
436 }
4c85cbfa
KR
437}
438
439/* Provided the symbol, returns the value reffed */
e8f2240a
KR
440static long
441get_symbol_value (symbol)
442 asymbol *symbol;
443{
444 long relocation = 0;
445
446 if (symbol == (asymbol *) NULL)
447 relocation = 0;
448 else if (symbol->section == &bfd_com_section)
449 {
450 relocation = 0;
451 }
452 else
453 {
454 relocation = symbol->value +
455 symbol->section->output_section->vma +
456 symbol->section->output_offset;
457 }
458
459 return (relocation);
4c85cbfa
KR
460}
461
462/* This function provides a pretty straight-forward mapping between a */
463/* base relocation type, format and field into the relocation type */
464/* that will be emitted in an object file. The only wrinkle in the */
465/* mapping is that when the T, TR, TL, P, PR, or PL expression */
466/* prefixes are involved, the type gets promoted to a *_GOTOFF_* */
467/* relocation (in the case of T, TR, and TL) or a PLABEL relocation */
468/* (in the case of P, PR, and PL). */
469
470/* NOTE: XXX the T, TR, TL, P, PR, and PL expression prefixes are not */
471/* handled yet. */
472
473static void
e8f2240a
KR
474hppa_elf_gen_reloc_error (base_type, fmt, field)
475 elf32_hppa_reloc_type base_type;
476 int fmt;
477 int field;
4c85cbfa 478{
e8f2240a
KR
479 fprintf (stderr, "undefined relocation: base=0x%x,fmt=0x%x,field=0x%x\n",
480 base_type, fmt, field);
4c85cbfa
KR
481}
482
e8f2240a
KR
483elf32_hppa_reloc_type **
484hppa_elf_gen_reloc_type (abfd, base_type, format, field)
485 bfd *abfd;
486 elf32_hppa_reloc_type base_type;
487 int format;
488 int field;
4c85cbfa 489{
d9ad93bc 490#define UNDEFINED hppa_elf_gen_reloc_error(base_type,format,field)
4c85cbfa 491
e8f2240a
KR
492 elf32_hppa_reloc_type *finaltype;
493 elf32_hppa_reloc_type **final_types;
494 int i;
495
496 final_types = (elf32_hppa_reloc_type **) bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type *) * 2);
497 BFD_ASSERT (final_types != 0);
498
499 finaltype = (elf32_hppa_reloc_type *) bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type));
500 BFD_ASSERT (finaltype != 0);
501
502 final_types[0] = finaltype;
503 final_types[1] = NULL;
504
505#define final_type finaltype[0]
506
507 final_type = base_type;
508
509 switch (base_type)
510 {
511 case R_HPPA:
512 switch (format)
513 {
514 case 11:
515 switch (field)
516 {
517 case e_fsel:
518 final_type = R_HPPA_11;
519 break;
520 case e_rsel:
521 final_type = R_HPPA_R11;
522 break;
523 case e_rssel:
524 final_type = R_HPPA_RS11;
525 break;
526 case e_rdsel:
527 final_type = R_HPPA_RD11;
528 break;
529
530 case e_psel:
531 final_type = R_HPPA_PLABEL_11;
532 break;
533 case e_rpsel:
534 final_type = R_HPPA_PLABEL_R11;
535 break;
536 case e_lpsel:
537 case e_tsel:
538 case e_ltsel:
539 case e_rtsel:
540
541 case e_lsel:
542 case e_lrsel:
543 case e_lssel:
544 case e_rrsel:
545 default:
546 UNDEFINED;
547 final_type = base_type;
548 break;
549 }
550 break;
551 case 12:
552 UNDEFINED;
553 break;
554 case 14:
555 switch (field)
556 {
557 case e_rsel:
558 final_type = R_HPPA_R14;
559 break;
560 case e_rssel:
561 final_type = R_HPPA_RS14;
562 break;
563 case e_rdsel:
564 final_type = R_HPPA_RD14;
565 break;
566 case e_rrsel:
567 final_type = R_HPPA_RR14;
568 break;
569
570 case e_psel:
571 final_type = R_HPPA_PLABEL_14;
572 break;
573 case e_rpsel:
574 final_type = R_HPPA_PLABEL_R14;
575 break;
576 case e_lpsel:
577 case e_tsel:
578 case e_ltsel:
579 case e_rtsel:
580
581 case e_fsel:
582 case e_lsel:
583 case e_lssel:
584 case e_ldsel:
585 case e_lrsel:
586 default:
587 UNDEFINED;
588 final_type = base_type;
589 break;
590 }
591 break;
592 case 17:
593 switch (field)
594 {
595 case e_fsel:
596 final_type = R_HPPA_17;
597 break;
598 case e_rsel:
599 final_type = R_HPPA_R17;
600 break;
601 case e_rssel:
602 final_type = R_HPPA_RS17;
603 break;
604 case e_rdsel:
605 final_type = R_HPPA_RD17;
606 break;
607 case e_rrsel:
608 final_type = R_HPPA_RR17;
609 break;
610 case e_lsel:
611 case e_lssel:
612 case e_ldsel:
613 case e_lrsel:
614 default:
615 UNDEFINED;
616 final_type = base_type;
617 break;
618 }
619 break;
620 case 21:
621 switch (field)
622 {
623 case e_lsel:
624 final_type = R_HPPA_L21;
625 break;
626 case e_lssel:
627 final_type = R_HPPA_LS21;
628 break;
629 case e_ldsel:
630 final_type = R_HPPA_LD21;
631 break;
632 case e_lrsel:
633 final_type = R_HPPA_LR21;
634 break;
635 case e_lpsel:
636 final_type = R_HPPA_PLABEL_L21;
637 break;
638 case e_rsel:
639 case e_rssel:
640 case e_rdsel:
641 case e_rrsel:
642 case e_fsel:
643 default:
644 UNDEFINED;
645 final_type = base_type;
646 break;
647 }
648 break;
649 case 32:
650 switch (field)
651 {
652 case e_fsel:
653 final_type = R_HPPA_32;
654 break;
655 case e_psel:
656 final_type = R_HPPA_PLABEL_32;
657 break;
658 default:
659 UNDEFINED;
660 final_type = base_type;
661 break;
662 }
663 break;
664 default:
665 UNDEFINED;
666 final_type = base_type;
667 break;
668 }
669 break;
670 case R_HPPA_GOTOFF:
671 switch (format)
672 {
673 case 11:
674 switch (field)
675 {
676 case e_rsel:
677 final_type = R_HPPA_GOTOFF_R11;
678 break;
679 case e_rssel:
680 final_type = R_HPPA_GOTOFF_RS11;
681 break;
682 case e_rdsel:
683 final_type = R_HPPA_GOTOFF_RD11;
684 break;
685 case e_fsel:
686 final_type = R_HPPA_GOTOFF_11;
687 break;
688 case e_lsel:
689 case e_lrsel:
690 case e_lssel:
691 case e_rrsel:
692 default:
693 UNDEFINED;
694 final_type = base_type;
695 break;
696 }
697 break;
698 case 12:
699 UNDEFINED;
700 final_type = base_type;
701 break;
702 case 14:
703 switch (field)
704 {
705 case e_rsel:
706 final_type = R_HPPA_GOTOFF_R14;
707 break;
708 case e_rssel:
709 final_type = R_HPPA_GOTOFF_RS14;
710 break;
711 case e_rdsel:
712 final_type = R_HPPA_GOTOFF_RD14;
713 break;
714 case e_rrsel:
715 final_type = R_HPPA_GOTOFF_RR14;
716 break;
717 case e_fsel:
718 final_type = R_HPPA_GOTOFF_14;
719 break;
720 case e_lsel:
721 case e_lssel:
722 case e_ldsel:
723 case e_lrsel:
724 default:
725 UNDEFINED;
726 final_type = base_type;
727 break;
728 }
729 break;
730 case 17:
731 UNDEFINED;
732 final_type = base_type;
733 break;
734 case 21:
735 switch (field)
736 {
737 case e_lsel:
738 final_type = R_HPPA_GOTOFF_L21;
739 break;
740 case e_lssel:
741 final_type = R_HPPA_GOTOFF_LS21;
742 break;
743 case e_ldsel:
744 final_type = R_HPPA_GOTOFF_LD21;
745 break;
746 case e_lrsel:
747 final_type = R_HPPA_GOTOFF_LR21;
748 break;
749 case e_rsel:
750 case e_rssel:
751 case e_rdsel:
752 case e_rrsel:
753 case e_fsel:
754 default:
755 UNDEFINED;
756 final_type = base_type;
757 break;
758 }
759 break;
760 case 32:
761 UNDEFINED;
762 final_type = base_type;
763 break;
764 default:
765 UNDEFINED;
766 final_type = base_type;
767 break;
768 }
769 break;
770 case R_HPPA_PCREL_CALL:
771 switch (format)
772 {
773 case 11:
774 switch (field)
775 {
776 case e_rsel:
777 final_type = R_HPPA_PCREL_CALL_R11;
778 break;
779 case e_rssel:
780 final_type = R_HPPA_PCREL_CALL_RS11;
781 break;
782 case e_rdsel:
783 final_type = R_HPPA_PCREL_CALL_RD11;
784 break;
785 case e_fsel:
786 final_type = R_HPPA_PCREL_CALL_11;
787 break;
788 case e_lsel:
789 case e_lrsel:
790 case e_lssel:
791 case e_rrsel:
792 default:
793 UNDEFINED;
794 final_type = base_type;
795 break;
796 }
797 break;
798 case 12:
799 UNDEFINED;
800 final_type = base_type;
801 break;
802 case 14:
803 switch (field)
804 {
805 case e_rsel:
806 final_type = R_HPPA_PCREL_CALL_R14;
807 break;
808 case e_rssel:
809 final_type = R_HPPA_PCREL_CALL_RS14;
810 break;
811 case e_rdsel:
812 final_type = R_HPPA_PCREL_CALL_RD14;
813 break;
814 case e_rrsel:
815 final_type = R_HPPA_PCREL_CALL_RR14;
816 break;
817 case e_fsel:
818 final_type = R_HPPA_PCREL_CALL_14;
819 break;
820 case e_lsel:
821 case e_lssel:
822 case e_ldsel:
823 case e_lrsel:
824 default:
825 UNDEFINED;
826 final_type = base_type;
827 break;
828 }
829 break;
830 case 17:
831 switch (field)
832 {
833 case e_rsel:
834 final_type = R_HPPA_PCREL_CALL_R17;
835 break;
836 case e_rssel:
837 final_type = R_HPPA_PCREL_CALL_RS17;
838 break;
839 case e_rdsel:
840 final_type = R_HPPA_PCREL_CALL_RD17;
841 break;
842 case e_rrsel:
843 final_type = R_HPPA_PCREL_CALL_RR17;
844 break;
845 case e_fsel:
846 final_type = R_HPPA_PCREL_CALL_17;
847 break;
848 case e_lsel:
849 case e_lssel:
850 case e_ldsel:
851 case e_lrsel:
852 default:
853 UNDEFINED;
854 final_type = base_type;
855 break;
856 }
857 break;
858 case 21:
859 switch (field)
860 {
861 case e_lsel:
862 final_type = R_HPPA_PCREL_CALL_L21;
863 break;
864 case e_lssel:
865 final_type = R_HPPA_PCREL_CALL_LS21;
866 break;
867 case e_ldsel:
868 final_type = R_HPPA_PCREL_CALL_LD21;
869 break;
870 case e_lrsel:
871 final_type = R_HPPA_PCREL_CALL_LR21;
872 break;
873 case e_rsel:
874 case e_rssel:
875 case e_rdsel:
876 case e_rrsel:
877 case e_fsel:
878 default:
879 UNDEFINED;
880 final_type = base_type;
881 break;
882 }
883 break;
884 case 32:
885 UNDEFINED;
886 final_type = base_type;
887 break;
888 default:
889 UNDEFINED;
890 final_type = base_type;
891 break;
892 }
893 break;
894 case R_HPPA_PLABEL:
895 switch (format)
896 {
897 case 11:
898 switch (field)
899 {
900 case e_fsel:
901 final_type = R_HPPA_PLABEL_11;
902 break;
903 case e_rsel:
904 final_type = R_HPPA_PLABEL_R11;
905 break;
906 default:
907 UNDEFINED;
908 final_type = base_type;
909 break;
910 }
911 break;
912 case 14:
913 switch (field)
914 {
915 case e_fsel:
916 final_type = R_HPPA_PLABEL_14;
917 break;
918 case e_rsel:
919 final_type = R_HPPA_PLABEL_R14;
920 break;
921 default:
922 UNDEFINED;
923 final_type = base_type;
924 break;
925 }
926 break;
927 case 21:
928 switch (field)
929 {
930 case e_lsel:
931 final_type = R_HPPA_PLABEL_L21;
932 break;
933 default:
934 UNDEFINED;
935 final_type = base_type;
936 break;
937 }
938 break;
939 case 32:
940 switch (field)
941 {
942 case e_fsel:
943 final_type = R_HPPA_PLABEL_32;
944 break;
945 default:
946 UNDEFINED;
947 final_type = base_type;
948 break;
949 }
950 break;
951 default:
952 UNDEFINED;
953 final_type = base_type;
954 break;
955 }
956 case R_HPPA_ABS_CALL:
957 switch (format)
958 {
959 case 11:
960 switch (field)
961 {
962 case e_rsel:
963 final_type = R_HPPA_ABS_CALL_R11;
964 break;
965 case e_rssel:
966 final_type = R_HPPA_ABS_CALL_RS11;
967 break;
968 case e_rdsel:
969 final_type = R_HPPA_ABS_CALL_RD11;
970 break;
971 case e_fsel:
972 final_type = R_HPPA_ABS_CALL_11;
973 break;
974 case e_lsel:
975 case e_lrsel:
976 case e_lssel:
977 case e_rrsel:
4c85cbfa 978 default:
e8f2240a
KR
979 UNDEFINED;
980 final_type = base_type;
981 break;
982 }
983 break;
984 case 12:
985 UNDEFINED;
986 final_type = base_type;
987 break;
988 case 14:
989 switch (field)
990 {
991 case e_rsel:
992 final_type = R_HPPA_ABS_CALL_R14;
993 break;
994 case e_rssel:
995 final_type = R_HPPA_ABS_CALL_RS14;
996 break;
997 case e_rdsel:
998 final_type = R_HPPA_ABS_CALL_RD14;
999 break;
1000 case e_rrsel:
1001 final_type = R_HPPA_ABS_CALL_RR14;
1002 break;
1003 case e_fsel:
1004 final_type = R_HPPA_ABS_CALL_14;
1005 break;
1006 case e_lsel:
1007 case e_lssel:
1008 case e_ldsel:
1009 case e_lrsel:
1010 default:
1011 UNDEFINED;
1012 final_type = base_type;
1013 break;
1014 }
1015 break;
1016 case 17:
1017 switch (field)
1018 {
1019 case e_rsel:
1020 final_type = R_HPPA_ABS_CALL_R17;
1021 break;
1022 case e_rssel:
1023 final_type = R_HPPA_ABS_CALL_RS17;
1024 break;
1025 case e_rdsel:
1026 final_type = R_HPPA_ABS_CALL_RD17;
1027 break;
1028 case e_rrsel:
1029 final_type = R_HPPA_ABS_CALL_RR17;
1030 break;
1031 case e_fsel:
1032 final_type = R_HPPA_ABS_CALL_17;
1033 break;
1034 case e_lsel:
1035 case e_lssel:
1036 case e_ldsel:
1037 case e_lrsel:
1038 default:
1039 UNDEFINED;
1040 final_type = base_type;
1041 break;
1042 }
1043 break;
1044 case 21:
1045 switch (field)
1046 {
1047 case e_lsel:
1048 final_type = R_HPPA_ABS_CALL_L21;
1049 break;
1050 case e_lssel:
1051 final_type = R_HPPA_ABS_CALL_LS21;
1052 break;
1053 case e_ldsel:
1054 final_type = R_HPPA_ABS_CALL_LD21;
1055 break;
1056 case e_lrsel:
1057 final_type = R_HPPA_ABS_CALL_LR21;
1058 break;
1059 case e_rsel:
1060 case e_rssel:
1061 case e_rdsel:
1062 case e_rrsel:
1063 case e_fsel:
1064 default:
1065 UNDEFINED;
1066 final_type = base_type;
1067 break;
1068 }
1069 break;
1070 case 32:
1071 UNDEFINED;
1072 final_type = base_type;
1073 break;
1074 default:
1075 UNDEFINED;
1076 final_type = base_type;
1077 break;
1078 }
1079 break;
1080 case R_HPPA_UNWIND:
1081 final_type = R_HPPA_UNWIND_ENTRY;
1082 break;
1083 case R_HPPA_COMPLEX:
1084 case R_HPPA_COMPLEX_PCREL_CALL:
1085 case R_HPPA_COMPLEX_ABS_CALL:
1086 final_types = (elf32_hppa_reloc_type **) bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type *) * 6);
1087 BFD_ASSERT (final_types != 0);
1088
1089 finaltype = (elf32_hppa_reloc_type *) bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type) * 5);
1090 BFD_ASSERT (finaltype != 0);
1091
1092 for (i = 0; i < 5; i++)
1093 final_types[i] = &finaltype[i];
1094
1095 final_types[5] = NULL;
1096
1097 finaltype[0] = R_HPPA_PUSH_SYM;
1098
1099 if (base_type == R_HPPA_COMPLEX)
1100 finaltype[1] = R_HPPA_PUSH_SYM;
1101 else if (base_type == R_HPPA_COMPLEX_PCREL_CALL)
1102 finaltype[1] = R_HPPA_PUSH_PCREL_CALL;
1103 else /* base_type == R_HPPA_COMPLEX_ABS_CALL */
1104 finaltype[1] = R_HPPA_PUSH_ABS_CALL;
1105
1106 finaltype[2] = R_HPPA_SUB;
1107
1108 switch (field)
1109 {
1110 case e_fsel:
1111 finaltype[3] = R_HPPA_EXPR_F;
1112 break;
1113 case e_lsel:
1114 finaltype[3] = R_HPPA_EXPR_L;
1115 break;
1116 case e_rsel:
1117 finaltype[3] = R_HPPA_EXPR_R;
1118 break;
1119 case e_lssel:
1120 finaltype[3] = R_HPPA_EXPR_LS;
1121 break;
1122 case e_rssel:
1123 finaltype[3] = R_HPPA_EXPR_RS;
1124 break;
1125 case e_ldsel:
1126 finaltype[3] = R_HPPA_EXPR_LD;
1127 break;
1128 case e_rdsel:
1129 finaltype[3] = R_HPPA_EXPR_RD;
1130 break;
1131 case e_lrsel:
1132 finaltype[3] = R_HPPA_EXPR_LR;
1133 break;
1134 case e_rrsel:
1135 finaltype[3] = R_HPPA_EXPR_RR;
1136 break;
4c85cbfa
KR
1137 }
1138
e8f2240a
KR
1139 switch (format)
1140 {
1141 case 11:
1142 finaltype[4] = R_HPPA_EXPR_11;
1143 break;
1144 case 12:
1145 finaltype[4] = R_HPPA_EXPR_12;
1146 break;
1147 case 14:
1148 finaltype[4] = R_HPPA_EXPR_14;
1149 break;
1150 case 17:
1151 finaltype[4] = R_HPPA_EXPR_17;
1152 break;
1153 case 21:
1154 finaltype[4] = R_HPPA_EXPR_21;
1155 break;
1156 case 32:
1157 finaltype[4] = R_HPPA_EXPR_32;
1158 break;
1159 }
1160
1161 break;
1162
1163 default:
1164 final_type = base_type;
1165 break;
1166 }
1167
1168 return final_types;
4c85cbfa
KR
1169}
1170
e8f2240a
KR
1171#undef final_type
1172
d9ad93bc 1173/* 12.4.4. Derive format from instruction
4c85cbfa 1174
d9ad93bc
KR
1175 Given a machine instruction, this function determines its format.
1176 The format can be determined solely from looking at the first six
1177 bits (the major opcode) of the instruction. Several major opcodes
1178 map to the same format. Opcodes which do not map to a known format
1179 should probably be reported as an error. */
4c85cbfa
KR
1180
1181unsigned char
e8f2240a
KR
1182hppa_elf_insn2fmt (type, insn)
1183 elf32_hppa_reloc_type type;
1184 unsigned long insn;
4c85cbfa 1185{
e8f2240a
KR
1186 unsigned char fmt = 0; /* XXX: is this a proper default? */
1187 unsigned char op = get_opcode (insn);
1188
1189 if (type == R_HPPA_NONE)
1190 fmt = 0;
1191 else
1192 {
1193 switch (op)
1194 {
1195 case ADDI:
1196 case ADDIT:
1197 case SUBI:
1198 fmt = 11;
1199 break;
1200 case MOVB:
1201 case MOVIB:
1202 case COMBT:
1203 case COMBF:
1204 case COMIBT:
1205 case COMIBF:
1206 case ADDBT:
1207 case ADDBF:
1208 case ADDIBT:
1209 case ADDIBF:
1210 case BVB:
1211 case BB:
1212 fmt = 12;
1213 break;
1214 case LDO:
1215 case LDB:
1216 case LDH:
1217 case LDW:
1218 case LDWM:
1219 case STB:
1220 case STH:
1221 case STW:
1222 case STWM:
1223 fmt = 14;
1224 break;
1225 case BL:
1226 case BE:
1227 case BLE:
1228 fmt = 17;
1229 break;
1230 case LDIL:
1231 case ADDIL:
1232 fmt = 21;
1233 break;
1234 default:
1235 fmt = 32;
1236 break;
4c85cbfa 1237 }
e8f2240a
KR
1238
1239 }
1240 return fmt;
4c85cbfa
KR
1241}
1242
1243/* this function is in charge of performing all the HP PA relocations */
d9ad93bc
KR
1244static long global_value;
1245static long GOT_value; /* XXX: need to calculate this! For HPUX, GOT == DP */
1246static asymbol *global_symbol;
1247static int global_sym_defined;
4c85cbfa
KR
1248
1249static bfd_reloc_status_type
e8f2240a
KR
1250DEFUN (hppa_elf_reloc, (abfd, reloc_entry, symbol_in, data, input_section, output_bfd),
1251 bfd * abfd AND
1252 arelent * reloc_entry AND
1253 asymbol * symbol_in AND
1254 PTR data AND
1255 asection * input_section AND
1256 bfd * output_bfd)
1257{
1258 unsigned long insn;
1259 long sym_value = 0;
1260
1261 unsigned long addr = reloc_entry->address; /*+ input_section->vma*/
1262 bfd_byte *hit_data = addr + (bfd_byte *) (data);
1263 unsigned short r_type = reloc_entry->howto->type & 0xFF;
1264 unsigned short r_field = e_fsel;
1265 boolean r_pcrel = reloc_entry->howto->pc_relative;
1266
1267 /* howto->bitsize contains the format (11, 14, 21, etc) information */
1268 unsigned r_format = reloc_entry->howto->bitsize;
1269 long r_addend = reloc_entry->addend;
1270
1271
1272 if (output_bfd)
1273 {
1274 /* Partial linking - do nothing */
1275 reloc_entry->address += input_section->output_offset;
1276 return bfd_reloc_ok;
1277 }
1278
1279 if (symbol_in && symbol_in->section == &bfd_und_section)
1280 return bfd_reloc_undefined;
1281
1282 /* Check for stubs that might be required. */
1283 /* symbol_in = hppa_elf_stub_check (abfd, input_section->output_section->owner, reloc_entry); */
1284
1285 sym_value = get_symbol_value (symbol_in);
1286
1287 /* compute value of $global$ if it is there. */
1288
d9ad93bc 1289 if (!global_sym_defined)
e8f2240a 1290 {
d9ad93bc 1291 if (global_symbol)
e8f2240a 1292 {
d9ad93bc
KR
1293 global_value = (global_symbol->value
1294 + global_symbol->section->output_section->vma
1295 + global_symbol->section->output_offset);
e8f2240a 1296 GOT_value = global_value; /* XXX: For HP-UX, GOT==DP */
d9ad93bc 1297 global_sym_defined++;
e8f2240a
KR
1298 }
1299 }
1300
1301 /* get the instruction word */
1302 insn = bfd_get_32 (abfd, hit_data);
1303
1304 /* relocate the value based on the relocation type */
1305
1306 /* basic_type_1: relocation is relative to $global$ */
1307 /* basic_type_2: relocation is relative to the current GOT */
1308 /* basic_type_3: relocation is an absolute call */
1309 /* basic_type_4: relocation is an PC-relative call */
1310 /* basic_type_5: relocation is plabel reference */
1311 /* basic_type_6: relocation is an unwind table relocation */
1312 /* extended_type: unimplemented */
1313
1314 switch (r_type)
1315 {
1316 case R_HPPA_NONE:
1317 break;
1318 case R_HPPA_32: /* Symbol + Addend 32 */
1319 r_field = e_fsel;
1320 goto do_basic_type_1;
1321 case R_HPPA_11: /* Symbol + Addend 11 */
1322 r_field = e_fsel;
1323 goto do_basic_type_1;
1324 case R_HPPA_14: /* Symbol + Addend 14 */
1325 r_field = e_fsel;
1326 goto do_basic_type_1;
1327 case R_HPPA_17: /* Symbol + Addend 17 */
1328 r_field = e_fsel;
1329 goto do_basic_type_1;
1330 case R_HPPA_L21: /* L (Symbol, Addend) 21 */
1331 r_field = e_lsel;
1332 goto do_basic_type_1;
1333 case R_HPPA_R11: /* R (Symbol, Addend) 11 */
1334 r_field = e_rsel;
1335 goto do_basic_type_1;
1336 case R_HPPA_R14: /* R (Symbol, Addend) 14 */
1337 r_field = e_rsel;
1338 goto do_basic_type_1;
1339 case R_HPPA_R17: /* R (Symbol, Addend) 17 */
1340 r_field = e_rsel;
1341 goto do_basic_type_1;
1342 case R_HPPA_LS21: /* LS(Symbol, Addend) 21 */
1343 r_field = e_lssel;
1344 goto do_basic_type_1;
1345 case R_HPPA_RS11: /* RS(Symbol, Addend) 11 */
1346 r_field = e_rssel;
1347 goto do_basic_type_1;
1348 case R_HPPA_RS14: /* RS(Symbol, Addend) 14 */
1349 r_field = e_rssel;
1350 goto do_basic_type_1;
1351 case R_HPPA_RS17: /* RS(Symbol, Addend) 17 */
1352 r_field = e_ldsel;
1353 goto do_basic_type_1;
1354 case R_HPPA_LD21: /* LD(Symbol, Addend) 21 */
1355 r_field = e_ldsel;
1356 goto do_basic_type_1;
1357 case R_HPPA_RD11: /* RD(Symbol, Addend) 11 */
1358 r_field = e_rdsel;
1359 goto do_basic_type_1;
1360 case R_HPPA_RD14: /* RD(Symbol, Addend) 14 */
1361 r_field = e_rdsel;
1362 goto do_basic_type_1;
1363 case R_HPPA_RD17: /* RD(Symbol, Addend) 17 */
1364 r_field = e_rdsel;
1365 goto do_basic_type_1;
1366 case R_HPPA_LR21: /* LR(Symbol, Addend) 21 */
1367 r_field = e_lrsel;
1368 goto do_basic_type_1;
1369 case R_HPPA_RR14: /* RR(Symbol, Addend) 14 */
1370 r_field = e_rrsel;
1371 goto do_basic_type_1;
1372 case R_HPPA_RR17: /* RR(Symbol, Addend) 17 */
1373 r_field = e_rrsel;
1374
1375 do_basic_type_1:
1376 insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr,
1377 symbol_in, sym_value, r_addend,
1378 r_type, r_format, r_field, r_pcrel);
1379 break;
1380
1381 case R_HPPA_GOTOFF_11: /* Symbol - GOT + Addend 11 */
1382 r_field = e_fsel;
1383 goto do_basic_type_2;
1384 case R_HPPA_GOTOFF_14: /* Symbol - GOT + Addend 14 */
1385 r_field = e_fsel;
1386 goto do_basic_type_2;
1387 case R_HPPA_GOTOFF_L21: /* L (Sym - GOT, Addend) 21 */
1388 r_field = e_lsel;
1389 goto do_basic_type_2;
1390 case R_HPPA_GOTOFF_R11: /* R (Sym - GOT, Addend) 11 */
1391 r_field = e_rsel;
1392 goto do_basic_type_2;
1393 case R_HPPA_GOTOFF_R14: /* R (Sym - GOT, Addend) 14 */
1394 r_field = e_rsel;
1395 goto do_basic_type_2;
1396 case R_HPPA_GOTOFF_LS21: /* LS(Sym - GOT, Addend) 21 */
1397 r_field = e_lssel;
1398 goto do_basic_type_2;
1399 case R_HPPA_GOTOFF_RS11: /* RS(Sym - GOT, Addend) 11 */
1400 r_field = e_rssel;
1401 goto do_basic_type_2;
1402 case R_HPPA_GOTOFF_RS14: /* RS(Sym - GOT, Addend) 14 */
1403 r_field = e_rssel;
1404 goto do_basic_type_2;
1405 case R_HPPA_GOTOFF_LD21: /* LD(Sym - GOT, Addend) 21 */
1406 r_field = e_ldsel;
1407 goto do_basic_type_2;
1408 case R_HPPA_GOTOFF_RD11: /* RD(Sym - GOT, Addend) 11 */
1409 r_field = e_rdsel;
1410 goto do_basic_type_2;
1411 case R_HPPA_GOTOFF_RD14: /* RD(Sym - GOT, Addend) 14 */
1412 r_field = e_rdsel;
1413 goto do_basic_type_2;
1414 case R_HPPA_GOTOFF_LR21: /* LR(Sym - GOT, Addend) 21 */
1415 r_field = e_lrsel;
1416 goto do_basic_type_2;
1417 case R_HPPA_GOTOFF_RR14: /* RR(Sym - GOT, Addend) 14 */
1418 r_field = e_rrsel;
1419 do_basic_type_2:
1420 sym_value -= GOT_value;
1421 insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr,
1422 symbol_in, sym_value, r_addend,
1423 r_type, r_format, r_field, r_pcrel);
1424 break;
1425
1426 case R_HPPA_ABS_CALL_11: /* Symbol + Addend 11 */
1427 r_field = e_fsel;
1428 goto do_basic_type_3;
1429 case R_HPPA_ABS_CALL_14: /* Symbol + Addend 14 */
1430 r_field = e_fsel;
1431 goto do_basic_type_3;
1432 case R_HPPA_ABS_CALL_17: /* Symbol + Addend 17 */
1433 r_field = e_fsel;
1434 goto do_basic_type_3;
1435 case R_HPPA_ABS_CALL_L21: /* L (Symbol, Addend) 21 */
1436 r_field = e_lsel;
1437 goto do_basic_type_3;
1438 case R_HPPA_ABS_CALL_R11: /* R (Symbol, Addend) 11 */
1439 r_field = e_rsel;
1440 goto do_basic_type_3;
1441 case R_HPPA_ABS_CALL_R14: /* R (Symbol, Addend) 14 */
1442 r_field = e_rsel;
1443 goto do_basic_type_3;
1444 case R_HPPA_ABS_CALL_R17: /* R (Symbol, Addend) 17 */
1445 r_field = e_rsel;
1446 goto do_basic_type_3;
1447 case R_HPPA_ABS_CALL_LS21: /* LS(Symbol, Addend) 21 */
1448 r_field = e_lssel;
1449 goto do_basic_type_3;
1450 case R_HPPA_ABS_CALL_RS11: /* RS(Symbol, Addend) 11 */
1451 r_field = e_lssel;
1452 goto do_basic_type_3;
1453 case R_HPPA_ABS_CALL_RS14: /* RS(Symbol, Addend) 14 */
1454 r_field = e_rssel;
1455 goto do_basic_type_3;
1456 case R_HPPA_ABS_CALL_RS17: /* RS(Symbol, Addend) 17 */
1457 r_field = e_rssel;
1458 goto do_basic_type_3;
1459 case R_HPPA_ABS_CALL_LD21: /* LD(Symbol, Addend) 21 */
1460 r_field = e_ldsel;
1461 goto do_basic_type_3;
1462 case R_HPPA_ABS_CALL_RD11: /* RD(Symbol, Addend) 11 */
1463 r_field = e_rdsel;
1464 goto do_basic_type_3;
1465 case R_HPPA_ABS_CALL_RD14: /* RD(Symbol, Addend) 14 */
1466 r_field = e_rdsel;
1467 goto do_basic_type_3;
1468 case R_HPPA_ABS_CALL_RD17: /* RD(Symbol, Addend) 17 */
1469 r_field = e_rdsel;
1470 goto do_basic_type_3;
1471 case R_HPPA_ABS_CALL_LR21: /* LR(Symbol, Addend) 21 */
1472 r_field = e_lrsel;
1473 goto do_basic_type_3;
1474 case R_HPPA_ABS_CALL_RR14: /* RR(Symbol, Addend) 14 */
1475 r_field = e_rrsel;
1476 goto do_basic_type_3;
1477 case R_HPPA_ABS_CALL_RR17: /* RR(Symbol, Addend) 17 */
1478 r_field = e_rrsel;
1479 do_basic_type_3:
1480 insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr,
1481 symbol_in, sym_value, r_addend,
1482 r_type, r_format, r_field, r_pcrel);
1483 break;
1484
1485 case R_HPPA_PCREL_CALL_11: /* Symbol - PC + Addend 11 */
1486 r_field = e_fsel;
1487 goto do_basic_type_4;
1488 case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */
1489 r_field = e_fsel;
1490 goto do_basic_type_4;
1491 case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */
1492 r_field = e_fsel;
1493 goto do_basic_type_4;
1494 case R_HPPA_PCREL_CALL_L21:/* L (Symbol - PC, Addend) 21 */
1495 r_field = e_lsel;
1496 goto do_basic_type_4;
1497 case R_HPPA_PCREL_CALL_R11:/* R (Symbol - PC, Addend) 11 */
1498 r_field = e_rsel;
1499 goto do_basic_type_4;
1500 case R_HPPA_PCREL_CALL_R14:/* R (Symbol - PC, Addend) 14 */
1501 r_field = e_rsel;
1502 goto do_basic_type_4;
1503 case R_HPPA_PCREL_CALL_R17:/* R (Symbol - PC, Addend) 17 */
1504 r_field = e_rsel;
1505 goto do_basic_type_4;
1506 case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */
1507 r_field = e_lssel;
1508 goto do_basic_type_4;
1509 case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */
1510 r_field = e_rssel;
1511 goto do_basic_type_4;
1512 case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */
1513 r_field = e_rssel;
1514 goto do_basic_type_4;
1515 case R_HPPA_PCREL_CALL_RS17: /* RS(Symbol - PC, Addend) 17 */
1516 r_field = e_rssel;
1517 goto do_basic_type_4;
1518 case R_HPPA_PCREL_CALL_LD21: /* LD(Symbol - PC, Addend) 21 */
1519 r_field = e_ldsel;
1520 goto do_basic_type_4;
1521 case R_HPPA_PCREL_CALL_RD11: /* RD(Symbol - PC, Addend) 11 */
1522 r_field = e_rdsel;
1523 goto do_basic_type_4;
1524 case R_HPPA_PCREL_CALL_RD14: /* RD(Symbol - PC, Addend) 14 */
1525 r_field = e_rdsel;
1526 goto do_basic_type_4;
1527 case R_HPPA_PCREL_CALL_RD17: /* RD(Symbol - PC, Addend) 17 */
1528 r_field = e_rdsel;
1529 goto do_basic_type_4;
1530 case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */
1531 r_field = e_lrsel;
1532 goto do_basic_type_4;
1533 case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */
1534 r_field = e_rrsel;
1535 goto do_basic_type_4;
1536 case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 *//* #69 */
1537 r_field = e_rrsel;
1538 do_basic_type_4:
1539 insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr,
1540 symbol_in, sym_value, r_addend,
1541 r_type, r_format, r_field, r_pcrel);
1542 break;
1543
1544 case R_HPPA_PLABEL_32:
1545 case R_HPPA_PLABEL_11:
1546 case R_HPPA_PLABEL_14:
1547 r_field = e_fsel;
1548 goto do_basic_type_5;
1549 case R_HPPA_PLABEL_L21:
1550 r_field = e_lsel;
1551 goto do_basic_type_5;
1552 case R_HPPA_PLABEL_R11:
1553 case R_HPPA_PLABEL_R14:
1554 r_field = e_rsel;
1555 do_basic_type_5:
1556 insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr,
1557 symbol_in, sym_value, r_addend,
1558 r_type, r_format, r_field, r_pcrel);
1559 break;
1560
1561 case R_HPPA_UNWIND_ENTRY:
1562 case R_HPPA_UNWIND_ENTRIES:
1563 hppa_elf_relocate_unwind_table (abfd, input_section, data, addr,
1564 symbol_in, sym_value, r_addend,
1565 r_type, r_format, r_field, r_pcrel);
1566 return (bfd_reloc_ok);
1567
1568 case R_HPPA_PUSH_CONST: /* push Addend - - */
1569 case R_HPPA_PUSH_PC: /* push PC + Addend - - */
1570 case R_HPPA_PUSH_SYM: /* push Symbol + Addend - - */
1571 case R_HPPA_PUSH_GOTOFF: /* push Symbol - GOT + Addend - - */
1572 case R_HPPA_PUSH_ABS_CALL: /* push Symbol + Addend - - */
1573 case R_HPPA_PUSH_PCREL_CALL: /* push Symbol - PC + Addend - - */
1574 case R_HPPA_PUSH_PLABEL: /* [TBD] - - */
1575 case R_HPPA_MAX: /* pop A and B, push max(B,A) - - */
1576 case R_HPPA_MIN: /* pop A and B, push min(B,A) - - */
1577 case R_HPPA_ADD: /* pop A and B, push B + A - - */
1578 case R_HPPA_SUB: /* pop A and B, push B - A - - */
1579 case R_HPPA_MULT: /* pop A and B, push B * A - - */
1580 case R_HPPA_DIV: /* pop A and B, push B / A - - */
1581 case R_HPPA_MOD: /* pop A and B, push B % A - - */
1582 case R_HPPA_AND: /* pop A and B, push B & A - - */
1583 case R_HPPA_OR: /* pop A and B, push B | A - - */
1584 case R_HPPA_XOR: /* pop A and B, push B ^ A - - */
1585 case R_HPPA_NOT: /* pop A, push ~A - - */
1586 case R_HPPA_LSHIFT: /* pop A, push A << Addend - - */
1587 case R_HPPA_ARITH_RSHIFT: /* pop A, push A >> Addend - - */
1588 case R_HPPA_LOGIC_RSHIFT: /* pop A, push A >> Addend - - */
1589 case R_HPPA_EXPR_F: /* pop A, push A + Addend L - */
1590 case R_HPPA_EXPR_L: /* pop A, push L(A,Addend) L - */
1591 case R_HPPA_EXPR_R: /* pop A, push R(A,Addend) R - */
1592 case R_HPPA_EXPR_LS: /* pop A, push LS(A,Addend) LS - */
1593 case R_HPPA_EXPR_RS: /* pop A, push RS(A,Addend) RS - */
1594 case R_HPPA_EXPR_LD: /* pop A, push LD(A,Addend) LD - */
1595 case R_HPPA_EXPR_RD: /* pop A, push RD(A,Addend) RD - */
1596 case R_HPPA_EXPR_LR: /* pop A, push LR(A,Addend) LR - */
1597 case R_HPPA_EXPR_RR: /* pop A, push RR(A,Addend) RR - */
1598
1599 case R_HPPA_EXPR_32: /* pop - 32 */
1600 case R_HPPA_EXPR_21: /* pop - 21 */
1601 case R_HPPA_EXPR_11: /* pop - 11 */
1602 case R_HPPA_EXPR_14: /* pop - 14 */
1603 case R_HPPA_EXPR_17: /* pop - 17 */
1604 case R_HPPA_EXPR_12: /* pop - 12 */
1605 fprintf (stderr, "Relocation problem: ");
1606 fprintf (stderr, "Unimplemented reloc type %d, in module %s\n",
1607 r_type, abfd->filename);
1608 return (bfd_reloc_notsupported);
d9ad93bc
KR
1609 case R_HPPA_STUB_CALL_17:
1610 /* yes, a branch to a long branch stub. Change instruction to a BLE */
1611 /* or BLE,N */
1612 if ( *(unsigned *)hit_data & 2 )
1613 insn = BLE_N_XXX_0_0;
1614 else
1615 insn = BLE_XXX_0_0;
1616 bfd_put_32 (abfd, insn, hit_data);
1617 r_type = R_HPPA_ABS_CALL_17;
1618 r_pcrel = 0;
1619 insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr,
1620 symbol_in, sym_value, r_addend,
1621 r_type, r_format, r_field, r_pcrel);
1622 break;
1623
e8f2240a
KR
1624 default:
1625 fprintf (stderr, "Relocation problem : ");
1626 fprintf (stderr, "Unrecognized reloc type %d, in module %s\n",
1627 r_type, abfd->filename);
1628 return (bfd_reloc_dangerous);
1629 }
1630
1631 /* update the instruction word */
1632 bfd_put_32 (abfd, insn, hit_data);
1633
1634 return (bfd_reloc_ok);
1635
1636}
1637
e8f2240a
KR
1638static reloc_howto_type *
1639elf_hppa_reloc_type_lookup (arch, code)
1640 bfd_arch_info_type *arch;
1641 bfd_reloc_code_real_type code;
1642{
e8f2240a
KR
1643 if ((int) code < (int) R_HPPA_UNIMPLEMENTED)
1644 {
1645 BFD_ASSERT ((int) elf_hppa_howto_table[(int) code].type == (int) code);
1646 return &elf_hppa_howto_table[(int) code];
1647 }
1648
1649 return (reloc_howto_type *) 0;
1650}
1651
1652#define bfd_elf32_bfd_reloc_type_lookup elf_hppa_reloc_type_lookup
1653
1654
1655void
1656DEFUN (elf_hppa_tc_symbol, (abfd, symbolP, sym_idx),
1657 bfd * abfd AND
3a70b01d 1658 elf_symbol_type * symbolP AND
e8f2240a
KR
1659 int sym_idx)
1660{
1661 symext_chainS *symextP;
1662 unsigned int arg_reloc;
1663
3a70b01d 1664 /* Only functions can have argument relocations. */
e8f2240a
KR
1665 if (!(symbolP->symbol.flags & BSF_FUNCTION))
1666 return;
1667
e8f2240a
KR
1668 arg_reloc = symbolP->tc_data.hppa_arg_reloc;
1669
3a70b01d
KR
1670 /* If there are no argument relocation bits, then no relocation is
1671 necessary. Do not add this to the symextn section. */
1672 if (arg_reloc == 0)
1673 return;
1674
e8f2240a
KR
1675 symextP = (symext_chainS *) bfd_alloc (abfd, sizeof (symext_chainS) * 2);
1676
1677 symextP[0].entry = ELF32_HPPA_SX_WORD (HPPA_SXT_SYMNDX, sym_idx);
1678 symextP[0].next = &symextP[1];
1679
1680 symextP[1].entry = ELF32_HPPA_SX_WORD (HPPA_SXT_ARG_RELOC, arg_reloc);
1681 symextP[1].next = NULL;
1682
1683 if (symext_rootP == NULL)
1684 {
1685 symext_rootP = &symextP[0];
1686 symext_lastP = &symextP[1];
1687 }
1688 else
1689 {
1690 symext_lastP->next = &symextP[0];
1691 symext_lastP = &symextP[1];
1692 }
1693}
1694
d9ad93bc
KR
1695/* Accessor function for the list of symbol extension records. */
1696symext_chainS *elf32_hppa_get_symextn_chain()
1697{
1698 return symext_rootP;
1699}
1700
1701static symext_entryS *symextn_contents;
1702static unsigned int symextn_contents_real_size;
e8f2240a
KR
1703
1704void
1705DEFUN (elf_hppa_tc_make_sections, (abfd, ignored),
1706 bfd * abfd AND
1707 PTR ignored)
1708{
1709 symext_chainS *symextP;
e8f2240a
KR
1710 int size;
1711 int n;
1712 int i;
e8f2240a
KR
1713 void hppa_elf_stub_finish (); /* forward declaration */
1714 asection *symextn_sec;
1715
1716 hppa_elf_stub_finish (abfd);
1717
1718 if (symext_rootP == NULL)
1719 return;
1720
1721 for (n = 0, symextP = symext_rootP; symextP; symextP = symextP->next, ++n)
1722 ;
1723
1724 size = sizeof (symext_entryS) * n;
1725 symextn_sec = bfd_get_section_by_name (abfd, SYMEXTN_SECTION_NAME);
1726 if (symextn_sec == (asection *) 0)
1727 {
1728 symextn_sec = bfd_make_section (abfd, SYMEXTN_SECTION_NAME);
1729 bfd_set_section_flags (abfd,
1730 symextn_sec,
1731 SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE | SEC_READONLY);
1732 symextn_sec->output_section = symextn_sec;
1733 symextn_sec->output_offset = 0;
1734 bfd_set_section_alignment (abfd, symextn_sec, 2);
1735 }
1736 symextn_contents = (symext_entryS *) bfd_alloc (abfd, size);
1737
1738 for (i = 0, symextP = symext_rootP; symextP; symextP = symextP->next, ++i)
1739 symextn_contents[i] = symextP->entry;
1740 symextn_contents_real_size = size;
1741 bfd_set_section_size (abfd, symextn_sec, symextn_contents_real_size);
1742
1743 return;
1744}
1745
1746/* Support for HP PA-RISC stub generation.
1747
1748 Written by
1749
1750 Center for Software Science
1751 Department of Computer Science
1752 University of Utah
1753
1754 */
1755
1756/*
1757 HP-PA calling conventions state:
1758
1759 1. an argument relocation stub is required whenever the callee and
1760 caller argument relocation bits do not match exactly. The exception
1761 to this rule is if either the caller or callee argument relocation
1762 bit are 00 (do not relocate).
1763
1764 2. The linker can optionally add a symbol record for the stub so that
1765 the stub can be reused. The symbol record will be the same as the
1766 original export symbol record, except that the relocation bits will
1767 reflect the input of the stub, the type would be STUB and the symbol
1768 value will be the location of the relocation stub.
1769
1770 Other notes:
1771
1772 Stubs can be inserted *before* the section of the caller. The stubs
1773 can be treated as calls to code that manipulates the arguments.
1774
1775 */
1776
1777typedef enum
1778 {
1779 HPPA_STUB_ILLEGAL,
1780 HPPA_STUB_ARG_RELOC,
1781 HPPA_STUB_LONG_BRANCH
1782 } hppa_stub_type;
1783
1784symext_entryS
1785elf32_hppa_get_sym_extn (abfd, sym, type)
1786 bfd *abfd;
1787 asymbol *sym;
1788 int type;
1789{
1790 /* This function finds the symbol extension record of the */
1791 /* specified type for the specified symbol. It returns the */
1792 /* value of the symbol extension record. */
1793 symext_entryS retval;
1794
1795 switch (type)
1796 {
1797 case HPPA_SXT_NULL:
1798 retval = (symext_entryS) 0;
1799 break;
1800 case HPPA_SXT_SYMNDX:
1801 retval = (symext_entryS) 0; /* XXX: need to fix this */
1802 break;
1803 case HPPA_SXT_ARG_RELOC:
1804 {
3a70b01d 1805 elf_symbol_type *esymP = (elf_symbol_type *) sym;
e8f2240a
KR
1806
1807 retval = (symext_entryS) esymP->tc_data.hppa_arg_reloc;
1808 break;
1809 }
d9ad93bc
KR
1810 /* This should never happen. */
1811 default:
1812 abort();
e8f2240a
KR
1813 }
1814 return retval;
1815}
1816
3a70b01d
KR
1817typedef struct elf32_hppa_stub_name_list_struct
1818{
1819 /* name of this stub */
1820 asymbol *sym;
1821 /* stub description for this stub */
1822 struct elf32_hppa_stub_description_struct *stub_desc;
1823 /* pointer into stub contents */
1824 int *stub_secp;
1825 /* size of this stub */
1826 unsigned size;
1827 /* next stub name entry */
1828 struct elf32_hppa_stub_name_list_struct *next;
1829} elf32_hppa_stub_name_list;
1830
1831typedef struct elf32_hppa_stub_description_struct
e8f2240a 1832 {
3a70b01d
KR
1833 struct elf32_hppa_stub_description_struct *next;
1834 bfd *this_bfd; /* bfd to which this stub applies */
e8f2240a 1835 asection *stub_sec; /* stub section for this bfd */
3a70b01d 1836 unsigned relocs_allocated_cnt; /* count of relocations for this stub section */
e8f2240a
KR
1837 unsigned real_size;
1838 unsigned allocated_size;
1839 int *stub_secp; /* pointer to the next available location in the buffer */
1840 char *stub_contents; /* contents of the stubs for this bfd */
3a70b01d 1841 elf32_hppa_stub_name_list *stub_listP;
e8f2240a 1842 }
3a70b01d 1843elf32_hppa_stub_description;
e8f2240a 1844
3a70b01d 1845static elf32_hppa_stub_description *elf_hppa_stub_rootP;
e8f2240a
KR
1846
1847/* Locate the stub section information for the given bfd. */
3a70b01d 1848static elf32_hppa_stub_description *
e8f2240a
KR
1849find_stubs (abfd, stub_sec)
1850 bfd *abfd;
1851 asection *stub_sec;
1852{
3a70b01d 1853 elf32_hppa_stub_description *stubP;
e8f2240a
KR
1854
1855 for (stubP = elf_hppa_stub_rootP; stubP; stubP = stubP->next)
1856 {
3a70b01d
KR
1857 if (stubP->this_bfd == abfd
1858 && stubP->stub_sec == stub_sec)
1859 return stubP;
e8f2240a
KR
1860 }
1861
3a70b01d 1862 return (elf32_hppa_stub_description *) NULL;
e8f2240a
KR
1863}
1864
3a70b01d 1865static elf32_hppa_stub_description *
e8f2240a
KR
1866new_stub (abfd, stub_sec)
1867 bfd *abfd;
1868 asection *stub_sec;
1869{
3a70b01d 1870 elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec);
e8f2240a
KR
1871
1872 if (stub)
1873 return stub;
1874
3a70b01d
KR
1875 stub = (elf32_hppa_stub_description *) bfd_zalloc (abfd, sizeof (elf32_hppa_stub_description));
1876 if (stub)
1877 {
1878 stub->this_bfd = abfd;
1879 stub->stub_sec = stub_sec;
1880 stub->real_size = 0;
1881 stub->allocated_size = 0;
1882 stub->stub_contents = NULL;
1883 stub->stub_secp = NULL;
1884
1885 stub->next = elf_hppa_stub_rootP;
1886 elf_hppa_stub_rootP = stub;
1887 }
1888 else
1889 {
1890 bfd_error = no_memory;
1891 bfd_perror ("new_stub");
1892 }
e8f2240a
KR
1893
1894 return stub;
1895}
1896
3a70b01d
KR
1897/* Locate the stub by the given name. */
1898static elf32_hppa_stub_name_list *
1899find_stub_by_name (abfd, stub_sec, name)
1900 bfd *abfd;
1901 asection *stub_sec;
1902 char *name;
1903{
1904 elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec);
1905
1906 if (stub)
1907 {
1908 elf32_hppa_stub_name_list *name_listP;
1909
1910 for (name_listP = stub->stub_listP; name_listP; name_listP = name_listP->next)
1911 {
1912 if (!strcmp (name_listP->sym->name, name))
1913 return name_listP;
1914 }
1915 }
1916
1917 return 0;
1918}
1919
1920/* Locate the stub by the given name. */
1921static elf32_hppa_stub_name_list *
1922add_stub_by_name(abfd, stub_sec, sym)
1923 bfd *abfd;
1924 asection *stub_sec;
1925 asymbol *sym;
e8f2240a 1926{
3a70b01d
KR
1927 elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec);
1928 elf32_hppa_stub_name_list *stub_entry;
e8f2240a 1929
3a70b01d
KR
1930 if (!stub)
1931 stub = new_stub(abfd, stub_sec);
e8f2240a 1932
3a70b01d 1933 if (stub)
e8f2240a 1934 {
3a70b01d
KR
1935 stub_entry = (elf32_hppa_stub_name_list *)
1936 bfd_zalloc (abfd, sizeof (elf32_hppa_stub_name_list));
e8f2240a 1937
3a70b01d 1938 if (stub_entry)
e8f2240a 1939 {
3a70b01d
KR
1940 stub_entry->size = 0;
1941 stub_entry->sym = sym;
1942 stub_entry->stub_desc = stub;
1943 /* First byte of this stub is the pointer to
1944 the next available location in the stub buffer. */
1945 stub_entry->stub_secp = stub->stub_secp;
1946 if (stub->stub_listP)
1947 stub_entry->next = stub->stub_listP;
1948 else
1949 stub_entry->next = NULL;
1950 stub->stub_listP = stub_entry;
1951 return stub_entry;
4c85cbfa 1952 }
e8f2240a
KR
1953 else
1954 {
3a70b01d
KR
1955 bfd_error = no_memory;
1956 bfd_perror("add_stub_by_name");
e8f2240a
KR
1957 }
1958 }
3a70b01d
KR
1959
1960 return (elf32_hppa_stub_name_list *)NULL;
e8f2240a
KR
1961}
1962
1963#define ARGUMENTS 0
1964#define RETURN_VALUE 1
1965
1966#define NO_ARG_RELOC 0
1967#define R_TO_FR 1
d9ad93bc
KR
1968#define R01_TO_FR 2
1969#define R23_TO_FR 3
1970#define FR_TO_R 4
1971#define FR_TO_R01 5
1972#define FR_TO_R23 6
1973#define ARG_RELOC_ERR 7
4c85cbfa 1974
e8f2240a
KR
1975#define ARG0 0
1976#define ARG1 1
1977#define ARG2 2
1978#define ARG3 3
1979#define RETVAL 4
4c85cbfa 1980
e8f2240a
KR
1981#define AR_NO 0
1982#define AR_GR 1
1983#define AR_FR 2
1984#define AR_FU 3
d9ad93bc
KR
1985/* FP register in arg0/arg1. This value can only appear in the arg0 location. */
1986#define AR_DBL01 4
1987/* FP register in arg2/arg3. This value can only appear in the arg2 location. */
1988#define AR_DBL23 5
1989
1990#define AR_WARN(type,loc) \
1991 fprintf(stderr,"WARNING: Illegal argument relocation: %s for %s\n", \
1992 reloc_type_strings[type],reloc_loc_strings[loc])
4c85cbfa 1993
e8f2240a
KR
1994static CONST char *CONST reloc_type_strings[] =
1995{
d9ad93bc
KR
1996 "NONE", "GR->FR", "GR0,GR1->FR1", "GR2,GR3->FR3", "FR->GR", "FR->GR0,GR1", "FR->GR2,GR3", "ERROR"
1997};
1998
1999static CONST char *CONST reloc_loc_strings[] =
2000{
2001 "ARG0", "ARG1", "ARG2", "ARG3", "RETVAL"
e8f2240a 2002};
4c85cbfa 2003
d9ad93bc
KR
2004static CONST char mismatches[6][6] =
2005{ /* CALLEE NONE CALLEE GR CALLEE FR CALLEE FU CALLEE DBL01 CALLEE DBL23 */
e8f2240a 2006 /* CALLER NONE */
d9ad93bc 2007 {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, NO_ARG_RELOC},
e8f2240a 2008 /* CALLER GR */
d9ad93bc 2009 {NO_ARG_RELOC, NO_ARG_RELOC, R_TO_FR, ARG_RELOC_ERR, R01_TO_FR, ARG_RELOC_ERR},
e8f2240a 2010 /* CALLER FR */
d9ad93bc 2011 {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR},
e8f2240a 2012 /* CALLER FU */
d9ad93bc
KR
2013 {ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
2014 /* CALLER DBL01 */
2015 {NO_ARG_RELOC, FR_TO_R01, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, ARG_RELOC_ERR},
2016 /* CALLER DBL23 */
2017 {NO_ARG_RELOC, FR_TO_R23, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, NO_ARG_RELOC},
e8f2240a 2018};
4c85cbfa 2019
d9ad93bc 2020static CONST char retval_mismatches[6][6] =
3a70b01d 2021{ /* CALLEE NONE CALLEE GR CALLEE FR CALLEE FU CALLEE DBL01 CALLEE DBL23 */
e8f2240a 2022 /* CALLER NONE */
d9ad93bc 2023 {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, NO_ARG_RELOC},
e8f2240a 2024 /* CALLER GR */
3a70b01d 2025 {NO_ARG_RELOC, NO_ARG_RELOC, FR_TO_R, ARG_RELOC_ERR, FR_TO_R01, ARG_RELOC_ERR},
e8f2240a 2026 /* CALLER FR */
3a70b01d 2027 {NO_ARG_RELOC, R_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
e8f2240a 2028 /* CALLER FU */
d9ad93bc
KR
2029 {ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
2030 /* CALLER DBL01 */
3a70b01d 2031 {NO_ARG_RELOC, R01_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, ARG_RELOC_ERR},
d9ad93bc 2032 /* CALLER DBL23 */
3a70b01d 2033 {NO_ARG_RELOC, R23_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, NO_ARG_RELOC},
e8f2240a
KR
2034};
2035
2036static int
2037type_of_mismatch (caller_bits, callee_bits, type)
2038 int caller_bits;
2039 int callee_bits;
2040 int type;
2041{
2042 switch (type)
2043 {
2044 case ARGUMENTS:
2045 return mismatches[caller_bits][callee_bits];
2046 case RETURN_VALUE:
2047 return retval_mismatches[caller_bits][callee_bits];
2048 }
2049
2050 return 0;
2051}
2052
2053#define EXTRACT_ARBITS(ar,which) ((ar) >> (8-(which*2))) & 3
2054
3a70b01d
KR
2055#define NEW_INSTRUCTION(entry,insn) \
2056 *((entry)->stub_desc->stub_secp)++ = (insn); \
2057 (entry)->stub_desc->real_size += sizeof(int); \
2058 (entry)->size += sizeof(int); \
2059 bfd_set_section_size((entry)->stub_desc->this_bfd, \
2060 (entry)->stub_desc->stub_sec, \
2061 (entry)->stub_desc->real_size);
e8f2240a 2062
3a70b01d
KR
2063#define CURRENT_STUB_OFFSET(entry) \
2064 ((int)(entry)->stub_desc->stub_secp - (int)(entry)->stub_desc->stub_contents - 4)
d9ad93bc
KR
2065
2066static boolean stubs_finished = false;
2067
e8f2240a
KR
2068void
2069hppa_elf_stub_finish (output_bfd)
2070 bfd *output_bfd;
2071{
2072 extern bfd_error_vector_type bfd_error_vector;
3a70b01d 2073 elf32_hppa_stub_description *stub_list = elf_hppa_stub_rootP;
e8f2240a
KR
2074 /* All the stubs have been built. Finish up building */
2075 /* stub section. Apply relocations to the section. */
2076
d9ad93bc
KR
2077 if ( stubs_finished )
2078 return;
2079
e8f2240a
KR
2080 for (; stub_list; stub_list = stub_list->next)
2081 {
3a70b01d 2082 if (stub_list->real_size)
e8f2240a 2083 {
3a70b01d 2084 bfd *stub_bfd = stub_list->this_bfd;
e8f2240a
KR
2085 asection *stub_sec = bfd_get_section_by_name (stub_bfd, ".hppa_linker_stubs");
2086 bfd_size_type reloc_size;
2087 arelent **reloc_vector;
2088
3a70b01d 2089 BFD_ASSERT (stub_sec == stub_list->stub_sec);
e8f2240a
KR
2090 reloc_size = bfd_get_reloc_upper_bound (stub_bfd, stub_sec);
2091 reloc_vector = (arelent **) alloca (reloc_size);
2092
2093 BFD_ASSERT (stub_sec);
2094
2095 /* We are not relaxing the section, so just copy the size info */
2096 stub_sec->_cooked_size = stub_sec->_raw_size;
2097 stub_sec->reloc_done = true;
2098
2099
2100 if (bfd_canonicalize_reloc (stub_bfd,
2101 stub_sec,
2102 reloc_vector,
2103 output_bfd->outsymbols))
2104 {
2105 arelent **parent;
2106 for (parent = reloc_vector; *parent != (arelent *) NULL;
2107 parent++)
2108 {
2109 bfd_reloc_status_type r =
2110 bfd_perform_relocation (stub_bfd,
2111 *parent,
3a70b01d 2112 stub_list->stub_contents,
e8f2240a
KR
2113 stub_sec, 0);
2114
2115
2116 if (r != bfd_reloc_ok)
2117 {
2118 switch (r)
2119 {
2120 case bfd_reloc_undefined:
2121 bfd_error_vector.undefined_symbol (*parent, NULL);
2122 break;
2123 case bfd_reloc_dangerous:
2124 bfd_error_vector.reloc_dangerous (*parent, NULL);
2125 break;
2126 case bfd_reloc_outofrange:
2127 case bfd_reloc_overflow:
2128 bfd_error_vector.reloc_value_truncated (*parent, NULL);
2129 break;
2130 default:
2131 abort ();
2132 break;
2133 }
2134 }
2135 }
2136 }
2137
2138 bfd_set_section_contents (output_bfd,
2139 stub_sec,
3a70b01d 2140 stub_list->stub_contents,
e8f2240a 2141 0,
3a70b01d 2142 stub_list->real_size);
e8f2240a
KR
2143
2144 free (reloc_vector);
2145 }
2146 }
d9ad93bc 2147 stubs_finished = true;
e8f2240a
KR
2148}
2149
2150void
2151hppa_elf_stub_branch_reloc (stub_desc, /* the bfd */
2152 output_bfd, /* the output bfd */
d9ad93bc 2153 target_sym, /* the target symbol */
e8f2240a 2154 offset) /* the offset within the stub buffer (pre-calculated) */
3a70b01d 2155 elf32_hppa_stub_description *stub_desc;
e8f2240a 2156 bfd *output_bfd;
d9ad93bc 2157 asymbol *target_sym;
e8f2240a
KR
2158 int offset;
2159{
2160 /* Allocate a new relocation entry. */
2161 arelent relent;
2162 int size;
2163
2164 if (stub_desc->relocs_allocated_cnt == stub_desc->stub_sec->reloc_count)
2165 {
2166 if (stub_desc->stub_sec->relocation == NULL)
2167 {
2168 stub_desc->relocs_allocated_cnt = STUB_RELOC_INCR;
2169 size = sizeof (arelent) * stub_desc->relocs_allocated_cnt;
2170 stub_desc->stub_sec->relocation = (arelent *) zalloc (size);
2171 }
2172 else
2173 {
2174 stub_desc->relocs_allocated_cnt += STUB_RELOC_INCR;
2175 size = sizeof (arelent) * stub_desc->relocs_allocated_cnt;
2176 stub_desc->stub_sec->relocation = (arelent *) realloc (stub_desc->stub_sec->relocation,
2177 size);
2178 }
2179 }
2180
2181 /* Fill in the details. */
2182 relent.address = offset;
2183 relent.addend = 0;
2184 relent.sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
2185 BFD_ASSERT (relent.sym_ptr_ptr);
2186
d9ad93bc
KR
2187 relent.sym_ptr_ptr[0] = target_sym;
2188 relent.howto = bfd_reloc_type_lookup (stub_desc->this_bfd, R_HPPA_PCREL_CALL_17);
2189
2190 /* Save it in the array of relocations for the stub section. */
2191
2192 memcpy (&stub_desc->stub_sec->relocation[stub_desc->stub_sec->reloc_count++],
2193 &relent,
2194 sizeof (arelent));
2195}
2196
2197void
2198hppa_elf_stub_reloc (stub_desc, /* the bfd */
2199 output_bfd, /* the output bfd */
2200 target_sym, /* the target symbol */
2201 offset, /* the offset within the stub buffer (pre-calculated) */
2202 type)
3a70b01d 2203elf32_hppa_stub_description *stub_desc;
d9ad93bc
KR
2204bfd *output_bfd;
2205asymbol *target_sym;
2206int offset;
2207elf32_hppa_reloc_type type;
2208{
2209 /* Allocate a new relocation entry. */
2210 arelent relent;
2211 int size;
2212 Elf_Internal_Shdr *rela_hdr;
2213
2214 if (stub_desc->relocs_allocated_cnt == stub_desc->stub_sec->reloc_count)
2215 {
2216 if (stub_desc->stub_sec->relocation == NULL)
2217 {
2218 stub_desc->relocs_allocated_cnt = STUB_RELOC_INCR;
2219 size = sizeof (arelent) * stub_desc->relocs_allocated_cnt;
2220 stub_desc->stub_sec->relocation = (arelent *) zalloc (size);
2221 }
2222 else
2223 {
2224 stub_desc->relocs_allocated_cnt += STUB_RELOC_INCR;
2225 size = sizeof (arelent) * stub_desc->relocs_allocated_cnt;
2226 stub_desc->stub_sec->relocation = (arelent *) realloc (stub_desc->stub_sec->relocation,
2227 size);
2228 }
2229 }
2230
2231 rela_hdr = &elf_section_data(stub_desc->stub_sec)->rel_hdr;
2232 rela_hdr->sh_size += sizeof(Elf32_External_Rela);
2233
2234 /* Fill in the details. */
2235 relent.address = offset;
2236 relent.addend = 0;
2237 relent.sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
2238 BFD_ASSERT (relent.sym_ptr_ptr);
2239
2240 relent.sym_ptr_ptr[0] = target_sym;
2241 relent.howto = bfd_reloc_type_lookup (stub_desc->this_bfd, type);
e8f2240a
KR
2242
2243 /* Save it in the array of relocations for the stub section. */
2244
2245 memcpy (&stub_desc->stub_sec->relocation[stub_desc->stub_sec->reloc_count++],
2246 &relent,
2247 sizeof (arelent));
2248}
2249
2250asymbol *
2251hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
2252 bfd *abfd;
2253 bfd *output_bfd;
2254 arelent *reloc_entry;
2255 int stub_types[5];
2256{
2257 asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs");
3a70b01d 2258 elf32_hppa_stub_description *stub_desc = find_stubs (abfd, stub_sec);
e8f2240a 2259 asymbol *stub_sym = NULL;
d9ad93bc 2260 asymbol *target_sym = reloc_entry->sym_ptr_ptr[0];
e8f2240a
KR
2261 asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text");
2262 int i;
2263 char stub_sym_name[128];
3a70b01d 2264 elf32_hppa_stub_name_list *stub_entry;
e8f2240a
KR
2265
2266 if (!stub_sec)
2267 {
2268 BFD_ASSERT (stub_desc == NULL);
2269 stub_sec = bfd_make_section (abfd, ".hppa_linker_stubs");
d9ad93bc 2270 bfd_set_section_flags (abfd,
e8f2240a
KR
2271 stub_sec,
2272 SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_READONLY);
2273 stub_sec->output_section = output_text_section->output_section;
2274 stub_sec->output_offset = 0;
d9ad93bc 2275 bfd_set_section_alignment (abfd, stub_sec, 2);
e8f2240a 2276 stub_desc = new_stub (abfd, stub_sec);
e8f2240a
KR
2277 }
2278
2279 /* make sure we have a stub descriptor structure */
2280
2281 if (!stub_desc)
3a70b01d 2282 stub_desc = new_stub (abfd, stub_sec);
e8f2240a
KR
2283
2284 /* allocate some space to write the stub */
2285
2286 if (!stub_desc->stub_contents)
2287 {
2288 stub_desc->allocated_size = STUB_BUFFER_INCR;
ab00002f 2289 stub_desc->stub_contents = (char *) xmalloc (STUB_BUFFER_INCR);
e8f2240a
KR
2290 }
2291 else if ((stub_desc->allocated_size - stub_desc->real_size) < STUB_MAX_SIZE)
2292 {
2293 stub_desc->allocated_size = stub_desc->allocated_size + STUB_BUFFER_INCR;
ab00002f
KR
2294 stub_desc->stub_contents = (char *) xrealloc (stub_desc->stub_contents,
2295 stub_desc->allocated_size);
e8f2240a
KR
2296 }
2297
2298 stub_desc->stub_secp = (int *) (stub_desc->stub_contents + stub_desc->real_size);
2299
e8f2240a 2300 sprintf (stub_sym_name,
3a70b01d 2301 "_stub_%s_%02d_%02d_%02d_%02d_%02d",
e8f2240a 2302 reloc_entry->sym_ptr_ptr[0]->name,
3a70b01d
KR
2303 stub_types[0], stub_types[1], stub_types[2], stub_types[3], stub_types[4]);
2304 stub_entry = find_stub_by_name(abfd, stub_sec, stub_sym_name);
e8f2240a 2305
3a70b01d
KR
2306 if (stub_entry)
2307 {
2308 stub_sym = stub_entry->sym;
2309 /* redirect the original relocation from the old symbol (a function) */
2310 /* to the stub (the stub calls the function). */
2311 /* XXX do we need to change the relocation type? */
2312 reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
2313 reloc_entry->sym_ptr_ptr[0] = stub_sym;
2314 }
2315 else
2316 {
2317 /* Stub does not already exist. Create a new stub. */
2318 /* Create a new symbol to point to this stub */
2319 stub_sym = bfd_make_empty_symbol (abfd);
2320 stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1);
2321 strcpy ((char *) stub_sym->name, stub_sym_name);
2322 stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents;
2323 stub_sym->section = stub_sec;
2324 stub_sym->flags = BSF_LOCAL | BSF_FUNCTION;
2325 stub_entry = add_stub_by_name(abfd, stub_sec, stub_sym);
2326
2327 /* redirect the original relocation from the old symbol (a function) */
2328 /* to the stub (the stub calls the function). */
2329 /* XXX do we need to change the relocation type? */
2330 reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
2331 reloc_entry->sym_ptr_ptr[0] = stub_sym;
2332
2333 /* generate the beginning common section for all stubs */
2334
2335 NEW_INSTRUCTION (stub_entry, ADDI_8_SP);
2336
2337 /* generate the code to move the arguments around */
2338 for (i = ARG0; i < ARG3; i++)
2339 {
2340 if (stub_types[i] != NO_ARG_RELOC)
2341 {
2342 /* A stub is needed */
2343 switch (stub_types[i])
2344 {
2345 case R_TO_FR:
2346 switch (i)
2347 {
2348 case ARG0:
2349 NEW_INSTRUCTION (stub_entry, STWS_ARG0_M8SP);
2350 NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG0);
2351 break;
2352 case ARG1:
2353 NEW_INSTRUCTION (stub_entry, STWS_ARG1_M8SP);
2354 NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG1);
2355 break;
2356 case ARG2:
2357 NEW_INSTRUCTION (stub_entry, STWS_ARG2_M8SP);
2358 NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG2);
2359 break;
2360 case ARG3:
2361 NEW_INSTRUCTION (stub_entry, STWS_ARG3_M8SP);
2362 NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG3);
2363 break;
2364 }
2365 continue;
2366
2367 case R01_TO_FR:
2368 switch (i)
2369 {
2370 case ARG0:
2371 NEW_INSTRUCTION(stub_entry, STWS_ARG0_M4SP);
2372 NEW_INSTRUCTION(stub_entry, STWS_ARG1_M8SP);
2373 NEW_INSTRUCTION(stub_entry, FLDDS_M8SP_FARG1);
2374 break;
2375 default:
2376 AR_WARN(stub_types[i],i);
2377 break;
2378 }
2379 continue;
2380
2381 case R23_TO_FR:
2382 switch (i)
2383 {
2384 case ARG2:
2385 NEW_INSTRUCTION(stub_entry, STWS_ARG2_M4SP);
2386 NEW_INSTRUCTION(stub_entry, STWS_ARG3_M8SP);
2387 NEW_INSTRUCTION(stub_entry, FLDDS_M8SP_FARG3);
2388 break;
2389 default:
2390 AR_WARN(stub_types[i],i);
2391 break;
2392 }
2393 continue;
2394
2395 case FR_TO_R:
2396 switch (i)
2397 {
2398 case ARG0:
2399 NEW_INSTRUCTION (stub_entry, FSTWS_FARG0_M8SP);
2400 NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG0);
2401 break;
2402 case ARG1:
2403 NEW_INSTRUCTION (stub_entry, FSTWS_FARG1_M8SP);
2404 NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG1);
2405 break;
2406 case ARG2:
2407 NEW_INSTRUCTION (stub_entry, FSTWS_FARG2_M8SP);
2408 NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG2);
2409 break;
2410 case ARG3:
2411 NEW_INSTRUCTION (stub_entry, FSTWS_FARG3_M8SP);
2412 NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG3);
2413 break;
2414 }
2415 continue;
2416
2417 case FR_TO_R01:
2418 switch (i)
2419 {
2420 case ARG0:
2421 NEW_INSTRUCTION(stub_entry, FSTDS_FARG1_M8SP);
2422 NEW_INSTRUCTION(stub_entry, LDWS_M4SP_ARG0);
2423 NEW_INSTRUCTION(stub_entry, LDWS_M8SP_ARG1);
2424 break;
2425 default:
2426 AR_WARN(stub_types[i],i);
2427 break;
2428 }
2429 continue;
2430
2431 case FR_TO_R23:
2432 switch (i)
2433 {
2434 case ARG2:
2435 NEW_INSTRUCTION(stub_entry, FSTDS_FARG3_M8SP);
2436 NEW_INSTRUCTION(stub_entry, LDWS_M4SP_ARG2);
2437 NEW_INSTRUCTION(stub_entry, LDWS_M8SP_ARG3);
2438 break;
2439 default:
2440 AR_WARN(stub_types[i],i);
2441 break;
2442 }
2443 continue;
2444
2445 }
2446 }
2447 }
e8f2240a 2448
3a70b01d 2449 NEW_INSTRUCTION (stub_entry, ADDI_M8_SP);
e8f2240a 2450
3a70b01d
KR
2451 /* generate the branch to the target routine */
2452 NEW_INSTRUCTION (stub_entry, STW_RP_M8SP); /* First, save the return address */
e8f2240a 2453
3a70b01d
KR
2454 /* Branch to the target function. */
2455 /* (Make it a long call, so we do not */
2456 /* have to worry about generating a */
2457 /* long call stub.) */
2458 NEW_INSTRUCTION(stub_entry, LDIL_XXX_31);
2459 hppa_elf_stub_reloc (stub_entry->stub_desc,
2460 abfd, /* the output bfd */
2461 target_sym, /* the target symbol */
2462 CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
2463 R_HPPA_L21);
2464 NEW_INSTRUCTION(stub_entry,BLE_XXX_0_31);
2465 hppa_elf_stub_reloc (stub_entry->stub_desc,
2466 abfd, /* the output bfd */
2467 target_sym, /* the target symbol */
2468 CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
2469 R_HPPA_ABS_CALL_R17);
2470 NEW_INSTRUCTION(stub_entry,COPY_31_2);
2471
2472 /* generate the code to move the return value around */
2473
2474 NEW_INSTRUCTION (stub_entry, LDW_M8SP_RP); /* restore return address */
2475
2476 i = RETVAL;
e8f2240a
KR
2477 if (stub_types[i] != NO_ARG_RELOC)
2478 {
2479 /* A stub is needed */
2480 switch (stub_types[i])
2481 {
2482 case R_TO_FR:
3a70b01d
KR
2483 NEW_INSTRUCTION (stub_entry, STWS_RET0_M8SP);
2484 NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FRET0);
2485 break;
2486
e8f2240a 2487 case FR_TO_R:
3a70b01d
KR
2488 NEW_INSTRUCTION (stub_entry, FSTWS_FRET0_M8SP);
2489 NEW_INSTRUCTION (stub_entry, LDWS_M4SP_RET0);
2490 break;
e8f2240a 2491 }
e8f2240a 2492 }
3a70b01d
KR
2493
2494 /* generate the ending common section for all stubs */
2495
2496 /* XXX: can we assume this is a save return? */
2497 NEW_INSTRUCTION (stub_entry, BV_N_0RP);
e8f2240a
KR
2498 }
2499
e8f2240a
KR
2500 return stub_sym;
2501}
2502
2503int
3a70b01d 2504hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types, caller_ar)
e8f2240a
KR
2505 bfd *abfd;
2506 arelent *reloc_entry;
2507 int stub_types[5];
3a70b01d 2508 symext_entryS caller_ar;
e8f2240a 2509{
e8f2240a
KR
2510 /* If the symbol is still undefined, there is */
2511 /* no way to know if a stub is required. */
2512
2513 if (reloc_entry->sym_ptr_ptr[0] && reloc_entry->sym_ptr_ptr[0]->section != &bfd_und_section)
2514 {
e8f2240a
KR
2515 symext_entryS callee_ar = elf32_hppa_get_sym_extn (abfd,
2516 reloc_entry->sym_ptr_ptr[0],
2517 HPPA_SXT_ARG_RELOC);
2518
2519 /* Now, determine if a stub is */
2520 /* required. A stub is required if they the callee and caller */
2521 /* argument relocation bits are both nonzero and not equal. */
2522
2523 if (caller_ar && callee_ar)
2524 {
2525 /* Both are non-zero, we need to do further checking. */
2526 /* First, check if there is a return value relocation to be done */
2527 int caller_loc[5];
2528 int callee_loc[5];
2529
2530 callee_loc[RETVAL] = EXTRACT_ARBITS (callee_ar, RETVAL);
2531 caller_loc[RETVAL] = EXTRACT_ARBITS (caller_ar, RETVAL);
2532 callee_loc[ARG0] = EXTRACT_ARBITS (callee_ar, ARG0);
2533 caller_loc[ARG0] = EXTRACT_ARBITS (caller_ar, ARG0);
2534 callee_loc[ARG1] = EXTRACT_ARBITS (callee_ar, ARG1);
2535 caller_loc[ARG1] = EXTRACT_ARBITS (caller_ar, ARG1);
2536 callee_loc[ARG2] = EXTRACT_ARBITS (callee_ar, ARG2);
2537 caller_loc[ARG2] = EXTRACT_ARBITS (caller_ar, ARG2);
2538 callee_loc[ARG3] = EXTRACT_ARBITS (callee_ar, ARG3);
2539 caller_loc[ARG3] = EXTRACT_ARBITS (caller_ar, ARG3);
2540
2541 /* Check some special combinations. For */
2542 /* example, if FU appears in ARG1 or ARG3, we */
2543 /* can move it to ARG0 or ARG2, respectively. */
2544
2545 if (caller_loc[ARG0] == AR_FU || caller_loc[ARG1] == AR_FU)
2546 {
d9ad93bc 2547 caller_loc[ARG0] = AR_DBL01;
e8f2240a
KR
2548 caller_loc[ARG1] = AR_NO;
2549 }
2550 if (caller_loc[ARG2] == AR_FU || caller_loc[ARG3] == AR_FU)
2551 {
d9ad93bc 2552 caller_loc[ARG2] = AR_DBL23;
e8f2240a
KR
2553 caller_loc[ARG3] = AR_NO;
2554 }
2555 if (callee_loc[ARG0] == AR_FU || callee_loc[ARG1] == AR_FU)
2556 {
d9ad93bc 2557 callee_loc[ARG0] = AR_DBL01;
e8f2240a
KR
2558 callee_loc[ARG1] = AR_NO;
2559 }
2560 if (callee_loc[ARG2] == AR_FU || callee_loc[ARG3] == AR_FU)
2561 {
d9ad93bc 2562 callee_loc[ARG2] = AR_DBL23;
e8f2240a
KR
2563 callee_loc[ARG3] = AR_NO;
2564 }
2565
2566 stub_types[ARG0] = type_of_mismatch (caller_loc[ARG0], callee_loc[ARG0], ARGUMENTS);
2567 stub_types[ARG1] = type_of_mismatch (caller_loc[ARG1], callee_loc[ARG1], ARGUMENTS);
2568 stub_types[ARG2] = type_of_mismatch (caller_loc[ARG2], callee_loc[ARG2], ARGUMENTS);
2569 stub_types[ARG3] = type_of_mismatch (caller_loc[ARG3], callee_loc[ARG3], ARGUMENTS);
2570 stub_types[RETVAL] = type_of_mismatch (caller_loc[RETVAL], callee_loc[RETVAL], RETURN_VALUE);
2571
d9ad93bc 2572 /* Steps involved in building stubs: */
e8f2240a
KR
2573 /* 1. Determine what argument registers need to relocated. This */
2574 /* step is already done here. */
2575 /* 2. Build the appropriate stub in the .hppa_linker_stubs section. */
2576 /* This section should never appear in an object file. It is */
2577 /* only used internally. The output_section of the */
2578 /* .hppa_linker_stubs section is the .text section of the */
2579 /* executable. */
2580 /* 3. Build a symbol that is used (internally only) as the entry */
2581 /* point of the stub. */
2582 /* 4. Change the instruction of the original branch into a branch to */
2583 /* the stub routine. */
2584 /* 5. Build a relocation entry for the instruction of the original */
d9ad93bc 2585 /* branch to be R_HPPA_PCREL_CALL to the stub routine. */
e8f2240a
KR
2586
2587
2588 if (stub_types[0]
2589 || stub_types[1]
2590 || stub_types[2]
2591 || stub_types[3]
2592 || stub_types[4])
2593 {
2594#ifdef DETECT_STUBS
3a70b01d
KR
2595 int i;
2596
e8f2240a
KR
2597 fprintf (stderr, "Stub needed for %s @ %s+0x%x: callee/caller ar=0x%x/0x%x ",
2598 reloc_entry->sym_ptr_ptr[0]->name,
2599 abfd->filename, reloc_entry->address,
2600 callee_ar, caller_ar);
2601 for (i = ARG0; i < RETVAL; i++)
2602 {
2603 if (stub_types[i] != NO_ARG_RELOC)
2604 {
2605 fprintf (stderr, "%s%d: %s ",
2606 i == RETVAL ? "ret" : "arg",
2607 i == RETVAL ? 0 : i,
2608 reloc_type_strings[stub_types[i]]);
2609 }
4c85cbfa 2610 }
e8f2240a
KR
2611 fprintf (stderr, "\n");
2612#endif
2613 return 1;
2614 }
2615
2616 }
2617 }
2618 return 0;
2619}
2620
2621asymbol *
d9ad93bc
KR
2622hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
2623 bfd *abfd;
2624 bfd *output_bfd;
2625 arelent *reloc_entry;
2626 asymbol *symbol;
2627 unsigned *data;
2628{
2629 asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs");
3a70b01d 2630 elf32_hppa_stub_description *stub_desc = find_stubs (abfd, stub_sec);
d9ad93bc
KR
2631 asymbol *stub_sym = NULL;
2632 asymbol *target_sym = reloc_entry->sym_ptr_ptr[0];
d9ad93bc
KR
2633 asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text");
2634 char stub_sym_name[128];
2635 int milli = false;
3a70b01d 2636 elf32_hppa_stub_name_list *stub_entry;
d9ad93bc
KR
2637
2638 if (!stub_sec)
2639 {
2640 BFD_ASSERT (stub_desc == NULL);
2641 stub_sec = bfd_make_section (abfd, ".hppa_linker_stubs");
2642 bfd_set_section_flags (abfd,
2643 stub_sec,
2644 SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_READONLY);
2645 stub_sec->output_section = output_text_section->output_section;
2646 stub_sec->output_offset = 0;
2647 /* set up the ELF section header for this new section. */
2648 /* This is basically the same processing as elf_make_sections() */
2649 /* (elf_make_sections() is static so it is not accessible from */
2650 /* here.) */
2651
2652 {
2653 Elf_Internal_Shdr *this_hdr;
2654 this_hdr = &elf_section_data (stub_sec)->this_hdr;
2655
2656 this_hdr->sh_addr = stub_sec->vma;
2657 this_hdr->sh_size = stub_sec->_raw_size;
2658 /* contents already set by elf_set_section_contents */
2659
2660 if (stub_sec->flags & SEC_RELOC)
2661 {
2662 /* emit a reloc section, and thus strtab and symtab... */
2663 Elf_Internal_Shdr *rela_hdr;
2664 int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
2665
2666 rela_hdr = &elf_section_data (stub_sec)->rel_hdr;
2667
2668 /* orelocation has the data, reloc_count has the count... */
2669 if (use_rela_p)
2670 {
2671 rela_hdr->sh_type = SHT_RELA;
2672 rela_hdr->sh_entsize = sizeof (Elf32_External_Rela);
2673 }
2674 else
2675 /* REL relocations */
2676 {
2677 rela_hdr->sh_type = SHT_REL;
2678 rela_hdr->sh_entsize = sizeof (Elf32_External_Rel);
2679 }
2680 rela_hdr->sh_flags = 0;
2681 rela_hdr->sh_addr = 0;
2682 rela_hdr->sh_offset = 0;
2683 rela_hdr->sh_addralign = 0;
2684 rela_hdr->size = 0;
2685 }
2686 if (stub_sec->flags & SEC_ALLOC)
2687 {
2688 this_hdr->sh_flags |= SHF_ALLOC;
2689 if (stub_sec->flags & SEC_LOAD)
2690 {
2691 /* @@ Do something with sh_type? */
2692 }
2693 }
2694 if (!(stub_sec->flags & SEC_READONLY))
2695 this_hdr->sh_flags |= SHF_WRITE;
2696
2697 if (stub_sec->flags & SEC_CODE)
2698 this_hdr->sh_flags |= SHF_EXECINSTR;
2699 }
2700
2701 bfd_set_section_alignment (abfd, stub_sec, 2);
2702 stub_desc = new_stub (abfd, stub_sec);
d9ad93bc
KR
2703 }
2704
2705 if (!stub_desc)
3a70b01d 2706 stub_desc = new_stub (abfd, stub_sec);
d9ad93bc
KR
2707
2708 /* allocate some space to write the stub */
2709
2710 if (!stub_desc->stub_contents)
2711 {
2712 stub_desc->allocated_size = STUB_BUFFER_INCR;
2713 stub_desc->stub_contents = (char *) malloc (STUB_BUFFER_INCR);
2714 }
2715 else if ((stub_desc->allocated_size - stub_desc->real_size) < STUB_MAX_SIZE)
2716 {
2717 stub_desc->allocated_size = stub_desc->allocated_size + STUB_BUFFER_INCR;
2718 stub_desc->stub_contents = (char *) realloc (stub_desc->stub_contents,
2719 stub_desc->allocated_size);
2720 }
2721
2722 stub_desc->stub_secp = (int *) (stub_desc->stub_contents + stub_desc->real_size);
2723
d9ad93bc 2724 sprintf (stub_sym_name,
3a70b01d
KR
2725 "_lb_stub_%s", reloc_entry->sym_ptr_ptr[0]->name);
2726 stub_entry = find_stub_by_name(abfd, stub_sec, stub_sym_name);
d9ad93bc 2727
3a70b01d
KR
2728 if (stub_entry)
2729 {
2730 stub_sym = stub_entry->sym;
2731 /* redirect the original relocation from the old symbol (a function) */
2732 /* to the stub (the stub calls the function). */
2733 /* XXX do we need to change the relocation type? */
2734 reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
2735 reloc_entry->sym_ptr_ptr[0] = stub_sym;
2736 reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17);
d9ad93bc
KR
2737 }
2738 else
2739 {
3a70b01d
KR
2740 /* Stub does not already exist. Create a new stub. */
2741 /* create a symbol to point to this stub */
2742 stub_sym = bfd_make_empty_symbol (abfd);
2743 stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1);
2744 strcpy ((char *) stub_sym->name, stub_sym_name);
2745 stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents;
2746 stub_sym->section = stub_sec;
2747 stub_sym->flags = BSF_LOCAL | BSF_FUNCTION;
2748 stub_entry = add_stub_by_name(abfd, stub_sec, stub_sym);
2749
2750 /* redirect the original relocation from the old symbol (a function) */
2751 /* to the stub (the stub calls the function). */
2752 /* XXX do we need to change the relocation type? */
2753 reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
2754 reloc_entry->sym_ptr_ptr[0] = stub_sym;
2755 reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17);
2756
2757 /* Build the stub */
2758
2759 /* A millicode call? */
2760 /* If so, the return address comes in on r31 rather than r2 (rp) so a */
2761 /* slightly different code sequence is needed. */
2762 if ( ((*data & 0x03e00000) >> 21) == 31 )
2763 milli = true;
2764
2765 /* 1. initialization for the call. */
2766
2767 NEW_INSTRUCTION(stub_entry, LDSID_31_RP);
2768 NEW_INSTRUCTION(stub_entry, MTSP_RP_SR0);
2769 if ( !milli )
2770 {
2771 NEW_INSTRUCTION(stub_entry, COPY_31_2);
2772
2773 NEW_INSTRUCTION(stub_entry, LDIL_XXX_31);
2774 hppa_elf_stub_reloc (stub_desc,
2775 abfd, /* the output bfd */
2776 target_sym, /* the target symbol */
2777 CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
2778 R_HPPA_L21);
2779
2780 /* 2. Make the call. */
2781
2782 NEW_INSTRUCTION(stub_entry,BE_N_XXX_0_31);
2783 hppa_elf_stub_reloc (stub_desc,
2784 abfd, /* the output bfd */
2785 target_sym, /* the target symbol */
2786 CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
2787 R_HPPA_ABS_CALL_R17);
2788 /* 3. Branch back to the original location. */
2789 /* (accomplished with the COPY_31_2 instruction) */
2790 }
2791 else
2792 {
2793 NEW_INSTRUCTION(stub_entry, STW_31_M24SP);
2794 NEW_INSTRUCTION(stub_entry, LDIL_XXX_RP);
2795 hppa_elf_stub_reloc (stub_desc,
2796 abfd, /* the output bfd */
2797 target_sym, /* the target symbol */
2798 CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
2799 R_HPPA_L21);
2800
2801 /* 2. Make the call. */
2802
2803 NEW_INSTRUCTION(stub_entry,BLE_XXX_0_RP);
2804 hppa_elf_stub_reloc (stub_desc,
2805 abfd, /* the output bfd */
2806 target_sym, /* the target symbol */
2807 CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
2808 R_HPPA_ABS_CALL_R17);
2809 NEW_INSTRUCTION(stub_entry,COPY_31_2);
2810
2811 /* 3. Branch back to the original location. */
2812 NEW_INSTRUCTION(stub_entry, LDW_M24SP_RP);
2813 NEW_INSTRUCTION(stub_entry, BV_N_0RP);
2814 }
d9ad93bc
KR
2815 }
2816
2817 return stub_sym;
2818}
2819
2820int
2821hppa_elf_long_branch_needed_p (abfd, asec, reloc_entry, symbol, insn)
2822 bfd *abfd;
2823 asection *asec;
2824 arelent *reloc_entry;
2825 asymbol *symbol;
2826 unsigned insn;
2827{
2828 long sym_value = get_symbol_value(symbol);
2829 int fmt = reloc_entry->howto->bitsize;
2830 unsigned char op = get_opcode(insn);
2831 unsigned raddr;
2832
2833#define too_far(val,num_bits) ((int)(val) > (1<<(num_bits))-1) || ((int)(val) < (-1<<(num_bits)))
2834
2835 BFD_ASSERT(fmt == hppa_elf_insn2fmt(reloc_entry->howto->type,insn));
2836
2837 switch (op)
2838 {
2839 case BL:
2840 raddr =
2841 reloc_entry->address + asec->output_offset + asec->output_section->vma;
2842 if ( too_far(sym_value - raddr,fmt+1) )
2843 {
2844#ifdef DETECT_STUBS
2845 fprintf(stderr,"long_branch needed on BL insn: abfd=%s,sym=%s,distance=0x%x\n",abfd->filename,symbol->name,sym_value - reloc_entry->address);
2846#endif
2847 return 1;
2848 }
2849 break;
2850 }
2851 return 0;
2852}
2853
2854asymbol *
2855hppa_elf_stub_check (abfd, output_bfd, input_section, reloc_entry, symbol, hit_data)
e8f2240a
KR
2856 bfd *abfd;
2857 bfd *output_bfd;
d9ad93bc 2858 asection *input_section;
e8f2240a 2859 arelent *reloc_entry;
d9ad93bc
KR
2860 asymbol *symbol;
2861 bfd_byte *hit_data;
e8f2240a
KR
2862{
2863 int stub_types[5];
2864
2865 switch (reloc_entry->howto->type)
2866 {
2867 case R_HPPA_ABS_CALL_11: /* Symbol + Addend 11 */
2868 case R_HPPA_ABS_CALL_14: /* Symbol + Addend 14 */
2869 case R_HPPA_ABS_CALL_17: /* Symbol + Addend 17 */
2870 case R_HPPA_ABS_CALL_L21: /* L (Symbol, Addend) 21 */
2871 case R_HPPA_ABS_CALL_R11: /* R (Symbol, Addend) 11 */
2872 case R_HPPA_ABS_CALL_R14: /* R (Symbol, Addend) 14 */
2873 case R_HPPA_ABS_CALL_R17: /* R (Symbol, Addend) 17 */
2874 case R_HPPA_ABS_CALL_LS21: /* LS(Symbol, Addend) 21 */
2875 case R_HPPA_ABS_CALL_RS11: /* RS(Symbol, Addend) 11 */
2876 case R_HPPA_ABS_CALL_RS14: /* RS(Symbol, Addend) 14 */
2877 case R_HPPA_ABS_CALL_RS17: /* RS(Symbol, Addend) 17 */
2878 case R_HPPA_ABS_CALL_LD21: /* LD(Symbol, Addend) 21 */
2879 case R_HPPA_ABS_CALL_RD11: /* RD(Symbol, Addend) 11 */
2880 case R_HPPA_ABS_CALL_RD14: /* RD(Symbol, Addend) 14 */
2881 case R_HPPA_ABS_CALL_RD17: /* RD(Symbol, Addend) 17 */
2882 case R_HPPA_ABS_CALL_LR21: /* LR(Symbol, Addend) 21 */
2883 case R_HPPA_ABS_CALL_RR14: /* RR(Symbol, Addend) 14 */
2884 case R_HPPA_ABS_CALL_RR17: /* RR(Symbol, Addend) 17 */
2885
2886 case R_HPPA_PCREL_CALL_11: /* Symbol - PC + Addend 11 */
2887 case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */
2888 case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */
2889 case R_HPPA_PCREL_CALL_12: /* Symbol - PC + Addend 12 */
3a70b01d
KR
2890 case R_HPPA_PCREL_CALL_L21: /* L (Symbol - PC, Addend) 21 */
2891 case R_HPPA_PCREL_CALL_R11: /* R (Symbol - PC, Addend) 11 */
2892 case R_HPPA_PCREL_CALL_R14: /* R (Symbol - PC, Addend) 14 */
2893 case R_HPPA_PCREL_CALL_R17: /* R (Symbol - PC, Addend) 17 */
2894 case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */
2895 case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */
2896 case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */
2897 case R_HPPA_PCREL_CALL_RS17: /* RS(Symbol - PC, Addend) 17 */
2898 case R_HPPA_PCREL_CALL_LD21: /* LD(Symbol - PC, Addend) 21 */
2899 case R_HPPA_PCREL_CALL_RD11: /* RD(Symbol - PC, Addend) 11 */
2900 case R_HPPA_PCREL_CALL_RD14: /* RD(Symbol - PC, Addend) 14 */
2901 case R_HPPA_PCREL_CALL_RD17: /* RD(Symbol - PC, Addend) 17 */
2902 case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */
2903 case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */
2904 case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */
2905 {
2906 symext_entryS caller_ar = (symext_entryS) ELF32_HGPPA_R_ARG_RELOC (reloc_entry->addend);
2907 if (hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types, caller_ar))
2908 {
2909 /* generate a stub */
2910 return hppa_elf_build_arg_reloc_stub (abfd, output_bfd,
2911 reloc_entry, stub_types);
2912 }
2913 if (hppa_elf_long_branch_needed_p (abfd, input_section, reloc_entry,
2914 symbol, *(unsigned *)hit_data))
2915 {
2916 /* generate a stub */
2917 return hppa_elf_build_long_branch_stub (abfd, output_bfd,
2918 reloc_entry, symbol,
2919 (unsigned *)hit_data);
2920 }
2921 }
e8f2240a
KR
2922 break;
2923
2924 default:
2925 break;
e8f2240a
KR
2926 }
2927 return reloc_entry->sym_ptr_ptr[0];
2928}
2929
2930#define STUB_SYM_BUFFER_INC 5
2931
2932asymbol *
d9ad93bc
KR
2933hppa_look_for_stubs_in_section (stub_bfd, abfd, output_bfd, asec, syms, new_sym_cnt)
2934 bfd *stub_bfd;
e8f2240a
KR
2935 bfd *abfd;
2936 bfd *output_bfd;
2937 asection *asec;
2938 asymbol **syms;
2939 int *new_sym_cnt;
2940{
2941 int i;
2942 int stub_types[5];
2943 asymbol *new_syms = (asymbol *) NULL;
2944 int new_cnt = 0;
2945 int new_max = 0;
2946
3a70b01d
KR
2947 /* Relocations are in different places depending on whether this is
2948 an output section or an input section. Also, the relocations are
2949 in different forms. Sigh. Luckily, we have
2950 bfd_canonicalize_reloc() to straighten this out for us. */
e8f2240a
KR
2951
2952 /* if ( asec->orelocation || asec->relocation ) { */
2953 if (asec->reloc_count > 0)
2954 {
2955 arelent **reloc_vector = (arelent **) alloca (asec->reloc_count * (sizeof (arelent *) + 1));
2956
2957 bfd_canonicalize_reloc (abfd, asec, reloc_vector, syms);
2958 for (i = 0; i < asec->reloc_count; i++)
2959 {
2960#if 0
2961 arelent *rle;
2962
2963 if ( asec->orelocation )
2964 rle = asec->orelocation[i];
2965 else
2966 rle = asec->relocation+i;
2967#endif
4c85cbfa 2968
e8f2240a
KR
2969 arelent *rle = reloc_vector[i];
2970
2971 switch (rle->howto->type)
2972 {
3a70b01d
KR
2973 case R_HPPA_ABS_CALL_11: /* Symbol + Addend 11 */
2974 case R_HPPA_ABS_CALL_14: /* Symbol + Addend 14 */
2975 case R_HPPA_ABS_CALL_17: /* Symbol + Addend 17 */
2976 case R_HPPA_ABS_CALL_L21: /* L (Symbol, Addend) 21 */
2977 case R_HPPA_ABS_CALL_R11: /* R (Symbol, Addend) 11 */
2978 case R_HPPA_ABS_CALL_R14: /* R (Symbol, Addend) 14 */
2979 case R_HPPA_ABS_CALL_R17: /* R (Symbol, Addend) 17 */
2980 case R_HPPA_ABS_CALL_LS21: /* LS(Symbol, Addend) 21 */
2981 case R_HPPA_ABS_CALL_RS11: /* RS(Symbol, Addend) 11 */
2982 case R_HPPA_ABS_CALL_RS14: /* RS(Symbol, Addend) 14 */
2983 case R_HPPA_ABS_CALL_RS17: /* RS(Symbol, Addend) 17 */
2984 case R_HPPA_ABS_CALL_LD21: /* LD(Symbol, Addend) 21 */
2985 case R_HPPA_ABS_CALL_RD11: /* RD(Symbol, Addend) 11 */
2986 case R_HPPA_ABS_CALL_RD14: /* RD(Symbol, Addend) 14 */
2987 case R_HPPA_ABS_CALL_RD17: /* RD(Symbol, Addend) 17 */
2988 case R_HPPA_ABS_CALL_LR21: /* LR(Symbol, Addend) 21 */
2989 case R_HPPA_ABS_CALL_RR14: /* RR(Symbol, Addend) 14 */
2990 case R_HPPA_ABS_CALL_RR17: /* RR(Symbol, Addend) 17 */
2991
2992 case R_HPPA_PCREL_CALL_11: /* Symbol - PC + Addend 11 */
2993 case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */
2994 case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */
2995 case R_HPPA_PCREL_CALL_12: /* Symbol - PC + Addend 12 */
2996 case R_HPPA_PCREL_CALL_L21: /* L (Symbol - PC, Addend) 21 */
2997 case R_HPPA_PCREL_CALL_R11: /* R (Symbol - PC, Addend) 11 */
2998 case R_HPPA_PCREL_CALL_R14: /* R (Symbol - PC, Addend) 14 */
2999 case R_HPPA_PCREL_CALL_R17: /* R (Symbol - PC, Addend) 17 */
3000 case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */
3001 case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */
3002 case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */
3003 case R_HPPA_PCREL_CALL_RS17: /* RS(Symbol - PC, Addend) 17 */
3004 case R_HPPA_PCREL_CALL_LD21: /* LD(Symbol - PC, Addend) 21 */
3005 case R_HPPA_PCREL_CALL_RD11: /* RD(Symbol - PC, Addend) 11 */
3006 case R_HPPA_PCREL_CALL_RD14: /* RD(Symbol - PC, Addend) 14 */
3007 case R_HPPA_PCREL_CALL_RD17: /* RD(Symbol - PC, Addend) 17 */
3008 case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */
3009 case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */
3010 case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */
3011 {
3012 symext_entryS caller_ar = (symext_entryS) ELF32_HPPA_R_ARG_RELOC (rle->addend);
3013 if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types,
3014 caller_ar))
3015 {
3016 /* generate a stub */
3017 /* keep track of the new symbol */
3018 asymbol *r;
d9ad93bc 3019
3a70b01d
KR
3020 if (new_cnt == new_max)
3021 {
3022 new_max += STUB_SYM_BUFFER_INC;
3023 new_syms = (asymbol *) realloc (new_syms, new_max * sizeof (asymbol));
3024 }
3025 r = hppa_elf_build_arg_reloc_stub (stub_bfd, output_bfd,
3026 rle, stub_types);
3027 new_syms[new_cnt++] = *r;
3028 }
3029 /* We need to retrieve the section contents to check for
3030 plabel stubs. */
3031 {
3032 unsigned insn;
d9ad93bc 3033
3a70b01d
KR
3034 bfd_get_section_contents (abfd, asec, &insn, rle->address,
3035 sizeof(insn));
3036 if (hppa_elf_long_branch_needed_p (abfd, asec, rle,
3037 rle->sym_ptr_ptr[0],
3038 insn))
e8f2240a 3039 {
3a70b01d
KR
3040 /* generate a stub */
3041 /* keep track of the new symbol */
3042 asymbol *r;
3043
3044 if (new_cnt == new_max)
3045 {
3046 new_max += STUB_SYM_BUFFER_INC;
3047 new_syms = (asymbol *) realloc (new_syms, (new_max * sizeof (asymbol)));
3048 }
3049 r = hppa_elf_build_long_branch_stub (stub_bfd,
3050 output_bfd,
3051 rle,
3052 rle->sym_ptr_ptr[0],
3053 &insn);
3054 new_syms[new_cnt++] = *r;
e8f2240a 3055 }
e8f2240a 3056 }
3a70b01d
KR
3057 }
3058 break;
3059
3060 /* Plabels are designed to allow code pointers to be
3061 passed between spaces. These relocations correspond
3062 to the P%, LP%, and RP% field selectors. */
3063
3064 case R_HPPA_PLABEL_32: /* F(Plabel(Symbol,Addend),0) 32 */
3065 case R_HPPA_PLABEL_11: /* F(Plabel(Symbol,Addend),0) 11 */
3066 case R_HPPA_PLABEL_14: /* F(Plabel(Symbol,Addend),0) 14 */
3067 case R_HPPA_PLABEL_L21: /* L(Plabel(Symbol,Addend),0) 21 */
3068 case R_HPPA_PLABEL_R11: /* R(Plabel(Symbol,Addend),0) 11 */
3069 case R_HPPA_PLABEL_R14: /* R(Plabel(Symbol,Addend),0) 14 */
3070 /* We need to retrieve the section contents to check for
3071 long branch stubs. */
d9ad93bc 3072 {
3a70b01d
KR
3073 /* On a plabel relocation, assume the arguments of the
3074 caller are set up in general registers. */
3075 /* 0x155 = ARGW0=CR,ARGW1=GR,ARGW2=GR,RETVAL=GR */
3076 symext_entryS caller_ar = (symext_entryS) 0x155;
d9ad93bc 3077
3a70b01d
KR
3078 if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types,
3079 caller_ar))
d9ad93bc 3080 {
3a70b01d 3081 /* generate a plabel stub */
d9ad93bc 3082 /* keep track of the new symbol */
d9ad93bc
KR
3083 asymbol *r;
3084
3085 if (new_cnt == new_max)
3086 {
3087 new_max += STUB_SYM_BUFFER_INC;
3a70b01d
KR
3088 new_syms = (asymbol *) realloc (new_syms,
3089 (new_max
3090 * sizeof (asymbol)));
d9ad93bc 3091 }
3a70b01d
KR
3092 r = hppa_elf_build_arg_reloc_stub (stub_bfd,
3093 output_bfd,
3094 rle,
3095 stub_types);
d9ad93bc
KR
3096 new_syms[new_cnt++] = *r;
3097 }
3098 }
e8f2240a 3099 break;
4c85cbfa 3100
e8f2240a
KR
3101 default:
3102 break;
4c85cbfa 3103
e8f2240a
KR
3104 }
3105 }
3106 }
3107 *new_sym_cnt = new_cnt;
3108 return new_syms;
4c85cbfa
KR
3109}
3110
d9ad93bc
KR
3111
3112char *linker_stubs = NULL;
3113int linker_stubs_size = 0;
3114int linker_stubs_max_size = 0;
3115#define STUB_ALLOC_INCR 100
3116
3117boolean
3118DEFUN (hppa_elf_set_section_contents, (abfd, section, location, offset, count),
3119 bfd * abfd AND
3120 sec_ptr section AND
3121 PTR location AND
3122 file_ptr offset AND
3123 bfd_size_type count)
4c85cbfa 3124{
d9ad93bc
KR
3125 if ( strcmp(section->name, ".hppa_linker_stubs") == 0 )
3126 {
3127 if ( linker_stubs_max_size < offset + count )
3128 {
3129 linker_stubs_max_size = offset + count + STUB_ALLOC_INCR;
3130 linker_stubs = (char *)realloc(linker_stubs, linker_stubs_max_size);
3131 }
3132
3133 if ( offset + count > linker_stubs_size )
3134 linker_stubs_size = offset + count;
3135
3136 memcpy(linker_stubs + offset,location,count);
3137 return (true);
3138 }
3139 else
3140 return bfd_elf32_set_section_contents (abfd, section, location,
3141 offset, count);
e8f2240a 3142}
4c85cbfa 3143
e8f2240a
KR
3144boolean
3145DEFUN (hppa_elf_get_section_contents, (abfd, section, location, offset, count),
3146 bfd * abfd AND
3147 sec_ptr section AND
3148 PTR location AND
3149 file_ptr offset AND
3150 bfd_size_type count)
3151{
3152 /* if this is the linker stub section, then we have the */
3153 /* section contents in memory rather than on disk. */
3154 if (strcmp (section->name, ".hppa_linker_stubs") == 0)
3155 {
3a70b01d 3156 elf32_hppa_stub_description *stub_desc = find_stubs (abfd, section);
e8f2240a
KR
3157
3158 if (count == 0)
3159 return true;
3160 if ((bfd_size_type) (offset + count) > section->_raw_size)
3161 return (false); /* on error */
3162 if ((bfd_size_type) (offset + count) > stub_desc->real_size)
3163 return (false); /* on error */
3164
3165 memcpy (location, stub_desc->stub_contents + offset, count);
3166 return (true);
3167 }
3168 /* if this is the symbol extension section, then we have the */
3169 /* section contents in memory rather than on disk. */
3170 else if (strcmp (section->name, ".hppa_symextn") == 0)
3171 {
3172 if (count == 0)
3173 return true;
3174 if ((bfd_size_type) (offset + count) > section->_raw_size)
3175 return (false); /* on error */
3176 if ((bfd_size_type) (offset + count) > symextn_contents_real_size)
3177 return (false); /* on error */
3178
3179 memcpy (location, symextn_contents + offset, count);
3180 return (true);
3181 }
3182 else
3a70b01d
KR
3183 return bfd_generic_get_section_contents (abfd, section, location, offset,
3184 count);
4c85cbfa
KR
3185}
3186
8ddd7ab3
KR
3187static void
3188DEFUN (elf_info_to_howto, (abfd, cache_ptr, dst),
e8f2240a
KR
3189 bfd * abfd AND
3190 arelent * cache_ptr AND
3191 Elf32_Internal_Rela * dst)
4c85cbfa 3192{
d9ad93bc
KR
3193 BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_HPPA_UNIMPLEMENTED);
3194 cache_ptr->howto = &elf_hppa_howto_table[ELF32_R_TYPE(dst->r_info)];
3195}
3196
3197static void
3198DEFUN (elf32_hppa_backend_symbol_processing, (abfd, sym),
3199 bfd * abfd AND
3200 asymbol * sym)
3201{
3202 /* Is this a definition of $global$? If so, keep it because it will be
3203 needed if any relocations are performed. */
3204
3205 if (!strcmp (sym->name, "$global$")
3206 && sym->section != &bfd_und_section)
3207 {
3208 global_symbol = sym;
3209 }
3210}
3211
3212#define elf_backend_symbol_processing elf32_hppa_backend_symbol_processing
3213
3214struct elf32_hppa_symextn_map_struct
3215{
3216 int old_index;
3217 bfd *bfd;
3218 asymbol *sym;
3219 int new_index;
3220};
3221
3222static struct elf32_hppa_symextn_map_struct *elf32_hppa_symextn_map;
3223static int elf32_hppa_symextn_map_size;
3224
3225static boolean
3226DEFUN (elf32_hppa_backend_symbol_table_processing, (abfd, esyms,symcnt),
3227 bfd * abfd AND
3a70b01d 3228 elf_symbol_type *esyms AND
d9ad93bc
KR
3229 int symcnt)
3230{
3231 Elf32_Internal_Shdr *symextn_hdr = bfd_elf_find_section (abfd, SYMEXTN_SECTION_NAME);
3232 int i;
3233 int current_sym_idx = 0;
3234
3235 /* If the symbol extension section does not exist, all the symbol */
3236 /* all the symbol extension information is assumed to be zero. */
3237
3238 if ( symextn_hdr == NULL )
3239 {
3240 for ( i = 0; i < symcnt; i++ )
3241 {
3242 esyms[i].tc_data.hppa_arg_reloc = 0;
3243 }
3244 return (true);
3245 }
3246
3247 /* allocate a buffer of the appropriate size for the symextn section */
3248
3249 symextn_hdr->contents = bfd_zalloc(abfd,symextn_hdr->sh_size);
3250 symextn_hdr->size = symextn_hdr->sh_size;
3251
3252 /* read in the symextn section */
3253
3254 if (bfd_seek (abfd, symextn_hdr->sh_offset, SEEK_SET) == -1)
3255 {
3256 bfd_error = system_call_error;
3257 return (false);
3258 }
3259 if (bfd_read ((PTR) symextn_hdr->contents, 1, symextn_hdr->size, abfd)
3260 != symextn_hdr->size)
3261 {
3262 free ((PTR)symextn_hdr->contents);
3263 bfd_error = system_call_error;
3264 return (false);
3265 }
3266
3267 /* parse the entries, updating the symtab entries as we go */
3268
3269 for ( i = 0; i < symextn_hdr->size / sizeof(symext_entryS); i++ )
3270 {
3271 symext_entryS *seP = ((symext_entryS *)symextn_hdr->contents) + i;
3272 int se_value = ELF32_HPPA_SX_VAL(*seP);
3273 int se_type = ELF32_HPPA_SX_TYPE(*seP);
3274
3275 switch ( se_type )
3276 {
3277 case HPPA_SXT_NULL:
3278 break;
3279
3280 case HPPA_SXT_SYMNDX:
3281 if ( se_value >= symcnt )
3282 {
3283 bfd_error = bad_value;
3284 bfd_perror("elf32_hppa_backend_symbol_table_processing -- symbol index");
3285 return (false);
3286 }
3287 current_sym_idx = se_value - 1;
3288 break;
3289
3290 case HPPA_SXT_ARG_RELOC:
3291 esyms[current_sym_idx].tc_data.hppa_arg_reloc = se_value;
3292 break;
3293
3294 default:
3295 bfd_error = bad_value;
3296 bfd_perror("elf32_hppa_backend_symbol_table_processing");
3297 return (false);
3298 }
3299 }
3300 return (true);
3301}
3302
3303#define elf_backend_symbol_table_processing elf32_hppa_backend_symbol_table_processing
3304
3305static boolean
3306DEFUN (elf32_hppa_backend_section_processing, (abfd, secthdr),
3307 bfd * abfd AND
3308 Elf32_Internal_Shdr *secthdr)
3309{
3310 int i,j,k;
3311
3312 if ( secthdr->sh_type == SHT_HPPA_SYMEXTN )
3313 {
3314 for ( i = 0; i < secthdr->size / sizeof(symext_entryS); i++ )
3315 {
3316 symext_entryS *seP = ((symext_entryS *)secthdr->contents) + i;
3317 int se_value = ELF32_HPPA_SX_VAL(*seP);
3318 int se_type = ELF32_HPPA_SX_TYPE(*seP);
3319
3320 switch ( se_type )
3321 {
3322 case HPPA_SXT_NULL:
3323 break;
3324
3325 case HPPA_SXT_SYMNDX:
3326 for ( j = 0; j < abfd->symcount; j++ )
3327 {
3328 /* locate the map entry for this symbol, if there is one. */
3329 /* modify the symbol extension section symbol index entry */
3330 /* to reflect the new symbol table index */
3331
3332 for ( k = 0; k < elf32_hppa_symextn_map_size; k++ )
3333 {
3334 if ( elf32_hppa_symextn_map[k].old_index == se_value
3335 && elf32_hppa_symextn_map[k].bfd == abfd->outsymbols[j]->the_bfd
3336 && elf32_hppa_symextn_map[k].sym == abfd->outsymbols[j] )
3337 {
3338 bfd_put_32(abfd,
3339 ELF32_HPPA_SX_WORD (HPPA_SXT_SYMNDX, j),
3340 (char *)seP);
3341 }
3342 }
3343 }
3344 break;
3345
3346 case HPPA_SXT_ARG_RELOC:
3347 break;
3348
3349 default:
3350 bfd_error = bad_value;
3351 bfd_perror("elf32_hppa_backend_section_processing");
3352 return (false);
3353 }
3354 }
3355 }
3356 return true;
3357}
3358
3359#define elf_backend_section_processing elf32_hppa_backend_section_processing
3360
3361static boolean
3362DEFUN (elf32_hppa_backend_section_from_shdr, (abfd, hdr, name),
3363 bfd * abfd AND
3364 Elf32_Internal_Shdr *hdr AND
3365 char * name)
3366{
3367 asection *newsect;
3368
3369 if ( hdr->sh_type == SHT_HPPA_SYMEXTN )
3370 {
3371 BFD_ASSERT ( strcmp(name,".hppa_symextn") == 0 );
3372
3373 /* Bits that get saved. This one is real. */
3374 if (!hdr->rawdata)
3375 {
3376 newsect = bfd_make_section (abfd, name);
3377 if (newsect != NULL)
3378 {
3379 newsect->vma = hdr->sh_addr;
3380 newsect->_raw_size = hdr->sh_size;
3381 newsect->filepos = hdr->sh_offset; /* so we can read back the bits */
3382 newsect->flags |= SEC_HAS_CONTENTS;
3383 newsect->alignment_power = hdr->sh_addralign;
3384
3385 if (hdr->sh_flags & SHF_ALLOC)
3386 {
3387 newsect->flags |= SEC_ALLOC;
3388 newsect->flags |= SEC_LOAD;
3389 }
3390
3391 if (!(hdr->sh_flags & SHF_WRITE))
3392 newsect->flags |= SEC_READONLY;
3393
3394 if (hdr->sh_flags & SHF_EXECINSTR)
3395 newsect->flags |= SEC_CODE; /* FIXME: may only contain SOME code */
3396 else
3397 newsect->flags |= SEC_DATA;
3398
3399 hdr->rawdata = (void *) newsect;
3400 }
3401 }
3402 return true;
3403 }
3404 return false;
3405}
3406
3407#define elf_backend_section_from_shdr elf32_hppa_backend_section_from_shdr
3408
3409static boolean
3410DEFUN (elf32_hppa_backend_fake_sections, (abfd, secthdr, asect),
3411 bfd * abfd AND
3412 Elf_Internal_Shdr *secthdr AND
3413 asection *asect)
3414{
3415
3416 if ( strcmp(asect->name, ".hppa_symextn") == 0 )
3417 {
3418 secthdr->sh_type = SHT_HPPA_SYMEXTN;
3419 secthdr->sh_flags = 0;
3420 secthdr->sh_info = elf_section_data(asect)->rel_hdr.sh_link;
3421 secthdr->sh_link = elf_onesymtab(abfd);
3422 return true;
3423 }
3424
3425 if (!strcmp (asect->name, ".hppa_unwind"))
3426 {
3427 secthdr->sh_type = SHT_PROGBITS;
3428 /* Unwind descriptors are not part of the program memory image. */
3429 secthdr->sh_flags = 0;
3430 secthdr->sh_info = 0;
3431 secthdr->sh_link = 0;
3432 secthdr->sh_entsize = 16;
3433 return true;
3434 }
3435
3436 return false;
3437}
3438
3439#define elf_backend_fake_sections elf32_hppa_backend_fake_sections
3440
3441static boolean
3442DEFUN (elf32_hppa_backend_section_from_bfd_section, (abfd, hdr, asect),
3443 bfd *abfd AND
3444 Elf32_Internal_Shdr *hdr AND
3445 asection *asect)
3446{
3447
3448 if ( hdr->sh_type == SHT_HPPA_SYMEXTN )
3449 {
3450 if (hdr->rawdata)
3451 {
3452 if (((struct sec *) (hdr->rawdata)) == asect)
3453 {
3454 BFD_ASSERT( strcmp(asect->name, ".hppa_symextn") == 0 );
3455 return true;
3456 }
3457 }
3458 }
3459
3460 return false;
8ddd7ab3 3461}
4c85cbfa 3462
d9ad93bc
KR
3463#define elf_backend_section_from_bfd_section elf32_hppa_backend_section_from_bfd_section
3464
3465#define bfd_generic_get_section_contents hppa_elf_get_section_contents
3466#define bfd_elf32_set_section_contents hppa_elf_set_section_contents
3467
e8f2240a 3468#define TARGET_BIG_SYM bfd_elf32_hppa_vec
8ddd7ab3
KR
3469#define TARGET_BIG_NAME "elf32-hppa"
3470#define ELF_ARCH bfd_arch_hppa
3a70b01d 3471#define ELF_MAXPAGESIZE 0x1000
8ddd7ab3
KR
3472
3473#include "elf32-target.h"
This page took 0.180248 seconds and 4 git commands to generate.