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