]> Git Repo - binutils.git/blob - bfd/elf32-hppa.c
* som.c (som_hppa_howto_table): SOM howto relocation table.
[binutils.git] / bfd / elf32-hppa.c
1 /* BFD back-end for HP PA-RISC ELF files.
2    Copyright (C) 1990-1991 Free Software Foundation, Inc.
3
4    Written by
5
6         Center for Software Science
7         Department of Computer Science
8         University of Utah
9
10 This file is part of BFD, the Binary File Descriptor library.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 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
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:
41
42         Center for Software Science
43         Department of Computer Science
44         University of Utah
45 */
46
47 #include "elf32-hppa.h"
48 #include "libhppa.h"
49 #include "aout/aout64.h"
50 #include "hppa_stubs.h"
51
52 /* ELF/PA relocation howto entries */
53
54 static bfd_reloc_status_type hppa_elf_reloc ();
55
56 static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
57 {
58 /*  'bitpos' and 'abs' are obsolete */
59 /* type                 rs sz bsz pcrel  bpos abs    ovrf  sf              name */
60 /* 9.3.4. Address relocation types */
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"},
81 /* 9.3.5. GOTOFF address relocation types               */
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"},
95 /* 9.3.6. Absolute call relocation types        */
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"},
114 /* 9.3.7. PC-relative call relocation types     */
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"},
134
135 /* 9.3.8. Plabel relocation types */
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"},
142
143 /* 9.3.9. Data linkage table (DLT) relocation types     */
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"},
150
151 /* 9.3.10. Relocations for unwinder tables      */
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"},
154
155 /*  9.3.11. Relocation types for complex expressions    */
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"},
195 };
196
197 static symext_chainS *symext_rootP;
198 static symext_chainS *symext_lastP;
199 static boolean symext_chain_built;
200
201 static unsigned long
202 DEFUN (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;
266 }
267
268 static unsigned long
269 DEFUN (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)
284 {
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:
300       constant_value = HPPA_R_CONSTANT (r_addend);
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);
306       return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_field, r_format);
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
314       constant_value = HPPA_R_CONSTANT(r_addend);
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
322       constant_value = HPPA_R_CONSTANT (r_addend);
323       sym_value = hppa_field_adjust (sym_value, constant_value, r_field);
324       return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_field, r_format);
325
326     case BL:
327     case BE:
328     case BLE:
329       arg_reloc = HPPA_R_ARG_RELOC (r_addend);
330
331       BFD_ASSERT (r_format == 17);
332
333       /* XXX computing constant_value is not needed??? */
334       constant_value = assemble_17 ((insn & 0x001f0000) >> 16,
335                                     (insn & 0x00001ffc) >> 2,
336                                     insn & 1);
337       /* @@ Assumes only 32 bits.  */
338       constant_value = (constant_value << 15) >> 15;
339       if (pcrel)
340         {
341           sym_value -=
342             address + input_sect->output_offset
343             + input_sect->output_section->vma;
344           sym_value = hppa_field_adjust (sym_value, -8, r_field);
345         }
346       else
347         sym_value = hppa_field_adjust (sym_value, constant_value, r_field);
348
349       return hppa_elf_rebuild_insn (abfd, insn, sym_value >> 2, r_type, r_field, r_format);
350
351     default:
352       if (opcode == 0)
353         {
354           BFD_ASSERT (r_format == 32);
355           constant_value = HPPA_R_CONSTANT (r_addend);
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;
365         }
366     }
367 }
368
369 static void
370 DEFUN (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)
385 {
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         {
410           unsigned int adjustment;
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);
415           adjustment = sym_value - start_offset;
416
417           hit_data += sizeof (unsigned long);
418           end_offset = adjustment + bfd_get_32 (abfd, hit_data);
419           bfd_put_32 (abfd, end_offset, hit_data);
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));
426               sym_value = start_offset + adjustment;
427             }
428         }
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     }
436 }
437
438 /* Provided the symbol, returns the value reffed */
439 static long
440 get_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);
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
472 static void
473 hppa_elf_gen_reloc_error (base_type, fmt, field)
474      elf32_hppa_reloc_type base_type;
475      int fmt;
476      int field;
477 {
478   fprintf (stderr, "undefined relocation: base=0x%x,fmt=0x%x,field=0x%x\n",
479            base_type, fmt, field);
480 }
481
482 elf32_hppa_reloc_type **
483 hppa_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;
488 {
489 #define UNDEFINED       hppa_elf_gen_reloc_error(base_type,format,field)
490
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:
977             default:
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;
1136         }
1137
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;
1168 }
1169
1170 #undef final_type
1171
1172
1173 /* this function is in charge of performing all the HP PA relocations */
1174 static long global_value;
1175 static long GOT_value;  /* XXX:  need to calculate this! For HPUX, GOT == DP */
1176 static asymbol *global_symbol;
1177 static int global_sym_defined;
1178
1179 static bfd_reloc_status_type
1180 DEFUN (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
1219   if (!global_sym_defined)
1220     {
1221       if (global_symbol)
1222         {
1223           global_value = (global_symbol->value
1224                           + global_symbol->section->output_section->vma
1225                           + global_symbol->section->output_offset);
1226           GOT_value = global_value;     /* XXX: For HP-UX, GOT==DP */
1227           global_sym_defined++;
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);
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 */
1542       if ( insn & 2 )
1543         insn = BLE_N_XXX_0_0;
1544       else
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         }
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       
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
1588 static const reloc_howto_type *
1589 elf_hppa_reloc_type_lookup (arch, code)
1590      bfd_arch_info_type *arch;
1591      bfd_reloc_code_real_type code;
1592 {
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
1605 void
1606 DEFUN (elf_hppa_tc_symbol, (abfd, symbolP, sym_idx),
1607        bfd * abfd AND
1608        elf_symbol_type * symbolP AND
1609        int sym_idx)
1610 {
1611   symext_chainS *symextP;
1612   unsigned int arg_reloc;
1613
1614   /* Only functions can have argument relocations.  */
1615   if (!(symbolP->symbol.flags & BSF_FUNCTION))
1616     return;
1617
1618   arg_reloc = symbolP->tc_data.hppa_arg_reloc;
1619
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
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
1645 /* Accessor function for the list of symbol extension records. */
1646 symext_chainS *elf32_hppa_get_symextn_chain()
1647 {
1648   return symext_rootP;
1649 }
1650
1651 static symext_entryS *symextn_contents;
1652 static unsigned int symextn_contents_real_size;
1653
1654 void
1655 DEFUN (elf_hppa_tc_make_sections, (abfd, ignored),
1656        bfd * abfd AND
1657        PTR ignored)
1658 {
1659   symext_chainS *symextP;
1660   int size;
1661   int n;
1662   int i;
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
1727 typedef enum
1728   {
1729     HPPA_STUB_ILLEGAL,
1730     HPPA_STUB_ARG_RELOC,
1731     HPPA_STUB_LONG_BRANCH
1732   } hppa_stub_type;
1733
1734 symext_entryS
1735 elf32_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       {
1755         elf_symbol_type *esymP = (elf_symbol_type *) sym;
1756
1757         retval = (symext_entryS) esymP->tc_data.hppa_arg_reloc;
1758         break;
1759       }
1760     /* This should never happen.  */
1761     default:
1762       abort();
1763     }
1764   return retval;
1765 }
1766
1767 typedef 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
1781 typedef struct elf32_hppa_stub_description_struct
1782   {
1783     struct elf32_hppa_stub_description_struct *next;
1784     bfd *this_bfd;              /* bfd to which this stub applies */
1785     asection *stub_sec;         /* stub section for this bfd */
1786     unsigned relocs_allocated_cnt; /* count of relocations for this stub section */
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 */
1791     elf32_hppa_stub_name_list *stub_listP;
1792   }
1793 elf32_hppa_stub_description;
1794
1795 static elf32_hppa_stub_description *elf_hppa_stub_rootP;
1796
1797 /* Locate the stub section information for the given bfd. */
1798 static elf32_hppa_stub_description *
1799 find_stubs (abfd, stub_sec)
1800      bfd *abfd;
1801      asection *stub_sec;
1802 {
1803   elf32_hppa_stub_description *stubP;
1804
1805   for (stubP = elf_hppa_stub_rootP; stubP; stubP = stubP->next)
1806     {
1807       if (stubP->this_bfd == abfd
1808           && stubP->stub_sec == stub_sec)
1809         return stubP;
1810     }
1811
1812   return (elf32_hppa_stub_description *) NULL;
1813 }
1814
1815 static elf32_hppa_stub_description *
1816 new_stub (abfd, stub_sec)
1817      bfd *abfd;
1818      asection *stub_sec;
1819 {
1820   elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec);
1821
1822   if (stub)
1823     return stub;
1824
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     }
1843
1844   return stub;
1845 }
1846
1847 /* Locate the stub by the given name.  */
1848 static elf32_hppa_stub_name_list *
1849 find_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.  */
1871 static elf32_hppa_stub_name_list *
1872 add_stub_by_name(abfd, stub_sec, sym)
1873      bfd *abfd;
1874      asection *stub_sec;
1875      asymbol *sym;
1876 {
1877   elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec);
1878   elf32_hppa_stub_name_list *stub_entry;
1879
1880   if (!stub)
1881     stub = new_stub(abfd, stub_sec);
1882
1883   if (stub)
1884     {
1885       stub_entry = (elf32_hppa_stub_name_list *)
1886         bfd_zalloc (abfd, sizeof (elf32_hppa_stub_name_list));
1887
1888       if (stub_entry)
1889         {
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;
1902         }
1903       else
1904         {
1905           bfd_error = no_memory;
1906           bfd_perror("add_stub_by_name");
1907         }
1908     }
1909
1910   return (elf32_hppa_stub_name_list *)NULL;
1911 }
1912
1913 #define ARGUMENTS       0
1914 #define RETURN_VALUE    1
1915
1916 #define NO_ARG_RELOC    0
1917 #define R_TO_FR         1
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
1924
1925 #define ARG0    0
1926 #define ARG1    1
1927 #define ARG2    2
1928 #define ARG3    3
1929 #define RETVAL  4
1930
1931 #define AR_NO   0
1932 #define AR_GR   1
1933 #define AR_FR   2
1934 #define AR_FU   3
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])
1943
1944 static CONST char *CONST reloc_type_strings[] =
1945 {
1946   "NONE", "GR->FR", "GR0,GR1->FR1", "GR2,GR3->FR3", "FR->GR", "FR->GR0,GR1", "FR->GR2,GR3", "ERROR"
1947 };
1948
1949 static CONST char *CONST reloc_loc_strings[] =
1950 {
1951   "ARG0", "ARG1", "ARG2", "ARG3", "RETVAL"
1952 };
1953
1954 static CONST char mismatches[6][6] =
1955 {                               /*      CALLEE NONE     CALLEE GR       CALLEE FR       CALLEE FU       CALLEE DBL01    CALLEE DBL23    */
1956   /* CALLER NONE        */
1957  {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, NO_ARG_RELOC},
1958  /* CALLER GR   */
1959  {NO_ARG_RELOC, NO_ARG_RELOC, R_TO_FR, ARG_RELOC_ERR, R01_TO_FR, ARG_RELOC_ERR},
1960  /* CALLER FR   */
1961  {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR},
1962  /* CALLER FU   */
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},
1968 };
1969
1970 static CONST char retval_mismatches[6][6] =
1971 {       /*      CALLEE NONE     CALLEE GR       CALLEE FR       CALLEE FU       CALLEE DBL01    CALLEE DBL23    */
1972   /* CALLER NONE        */
1973  {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, NO_ARG_RELOC},
1974  /* CALLER GR   */
1975  {NO_ARG_RELOC, NO_ARG_RELOC, FR_TO_R, ARG_RELOC_ERR, FR_TO_R01, ARG_RELOC_ERR},
1976  /* CALLER FR   */
1977  {NO_ARG_RELOC, R_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
1978  /* CALLER FU   */
1979  {ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
1980  /* CALLER DBL01        */
1981  {NO_ARG_RELOC, R01_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, ARG_RELOC_ERR},
1982  /* CALLER DBL23        */
1983  {NO_ARG_RELOC, R23_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, NO_ARG_RELOC},
1984 };
1985
1986 static int
1987 type_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
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);
2012
2013 #define CURRENT_STUB_OFFSET(entry)      \
2014   ((int)(entry)->stub_desc->stub_secp - (int)(entry)->stub_desc->stub_contents - 4)
2015
2016 static boolean stubs_finished = false;
2017
2018 void
2019 hppa_elf_stub_finish (output_bfd)
2020      bfd *output_bfd;
2021 {
2022   extern bfd_error_vector_type bfd_error_vector;
2023   elf32_hppa_stub_description *stub_list = elf_hppa_stub_rootP;
2024   /* All the stubs have been built.  Finish up building */
2025   /* stub section.  Apply relocations to the section.   */
2026
2027   if ( stubs_finished )
2028     return;
2029
2030   for (; stub_list; stub_list = stub_list->next)
2031     {
2032       if (stub_list->real_size)
2033         {
2034           bfd *stub_bfd = stub_list->this_bfd;
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
2039           BFD_ASSERT (stub_sec == stub_list->stub_sec);
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,
2062                                           stub_list->stub_contents,
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,
2090                                     stub_list->stub_contents,
2091                                     0,
2092                                     stub_list->real_size);
2093
2094           free (reloc_vector);
2095         }
2096     }
2097   stubs_finished = true;
2098 }
2099
2100 void
2101 hppa_elf_stub_branch_reloc (stub_desc,  /* the bfd */
2102                             output_bfd, /* the output bfd */
2103                             target_sym, /* the target symbol */
2104                             offset)     /* the offset within the stub buffer (pre-calculated) */
2105      elf32_hppa_stub_description *stub_desc;
2106      bfd *output_bfd;
2107      asymbol *target_sym;
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
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
2147 void
2148 hppa_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)
2153 elf32_hppa_stub_description *stub_desc;
2154 bfd *output_bfd;
2155 asymbol *target_sym;
2156 int offset;
2157 elf32_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);
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
2200 asymbol *
2201 hppa_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");
2208   elf32_hppa_stub_description *stub_desc = find_stubs (abfd, stub_sec);
2209   asymbol *stub_sym = NULL;
2210   asymbol *target_sym = reloc_entry->sym_ptr_ptr[0];
2211   asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text");
2212   int i;
2213   char stub_sym_name[128];
2214   elf32_hppa_stub_name_list *stub_entry;
2215
2216   if (!stub_sec)
2217     {
2218       BFD_ASSERT (stub_desc == NULL);
2219       stub_sec = bfd_make_section (abfd, ".hppa_linker_stubs");
2220       bfd_set_section_flags (abfd,
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;
2225       bfd_set_section_alignment (abfd, stub_sec, 2);
2226       stub_desc = new_stub (abfd, stub_sec);
2227     }
2228
2229   /* make sure we have a stub descriptor structure */
2230
2231   if (!stub_desc)
2232     stub_desc = new_stub (abfd, stub_sec);
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;
2239       stub_desc->stub_contents = (char *) bfd_xmalloc (STUB_BUFFER_INCR);
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;
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 ();
2248     }
2249
2250   stub_desc->stub_secp = (int *) (stub_desc->stub_contents + stub_desc->real_size);
2251
2252   sprintf (stub_sym_name,
2253            "_stub_%s_%02d_%02d_%02d_%02d_%02d",
2254            reloc_entry->sym_ptr_ptr[0]->name,
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);
2257
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         }
2400
2401       NEW_INSTRUCTION (stub_entry, ADDI_M8_SP);
2402
2403       /* generate the branch to the target routine */
2404       NEW_INSTRUCTION (stub_entry, STW_RP_M8SP);        /* First, save the return address */
2405
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;
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:
2435               NEW_INSTRUCTION (stub_entry, STWS_RET0_M8SP);
2436               NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FRET0);
2437               break;
2438               
2439             case FR_TO_R:
2440               NEW_INSTRUCTION (stub_entry, FSTWS_FRET0_M8SP);
2441               NEW_INSTRUCTION (stub_entry, LDWS_M4SP_RET0);
2442               break;
2443             }
2444         }
2445       
2446       /* generate the ending common section for all stubs */
2447       
2448       /* XXX: can we assume this is a save return? */
2449       NEW_INSTRUCTION (stub_entry, BV_N_0_RP);
2450     }
2451
2452   return stub_sym;
2453 }
2454
2455 int
2456 hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types, caller_ar)
2457      bfd *abfd;
2458      arelent *reloc_entry;
2459      int stub_types[5];
2460      symext_entryS caller_ar;
2461 {
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     {
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             {
2499               caller_loc[ARG0] = AR_DBL01;
2500               caller_loc[ARG1] = AR_NO;
2501             }
2502           if (caller_loc[ARG2] == AR_FU || caller_loc[ARG3] == AR_FU)
2503             {
2504               caller_loc[ARG2] = AR_DBL23;
2505               caller_loc[ARG3] = AR_NO;
2506             }
2507           if (callee_loc[ARG0] == AR_FU || callee_loc[ARG1] == AR_FU)
2508             {
2509               callee_loc[ARG0] = AR_DBL01;
2510               callee_loc[ARG1] = AR_NO;
2511             }
2512           if (callee_loc[ARG2] == AR_FU || callee_loc[ARG3] == AR_FU)
2513             {
2514               callee_loc[ARG2] = AR_DBL23;
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
2524           /* Steps involved in building stubs: */
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 */
2537           /*    branch to be R_HPPA_PCREL_CALL to the stub routine. */
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
2547               int i;
2548
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                     }
2562                 }
2563               fprintf (stderr, "\n");
2564 #endif
2565               return 1;
2566             }
2567
2568         }
2569     }
2570   return 0;
2571 }
2572
2573 asymbol *
2574 hppa_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");
2582   elf32_hppa_stub_description *stub_desc = find_stubs (abfd, stub_sec);
2583   asymbol *stub_sym = NULL;
2584   asymbol *target_sym = reloc_entry->sym_ptr_ptr[0];
2585   asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text");
2586   char stub_sym_name[128];
2587   int milli = false;
2588   int dyncall = false;
2589   elf32_hppa_stub_name_list *stub_entry;
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);
2656     }
2657
2658   if (!stub_desc)
2659     stub_desc = new_stub (abfd, stub_sec);
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
2677   sprintf (stub_sym_name,
2678            "_lb_stub_%s", reloc_entry->sym_ptr_ptr[0]->name);
2679   stub_entry = find_stub_by_name(abfd, stub_sec, stub_sym_name);
2680
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);
2690     }
2691   else
2692     {
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
2718       if ( strcmp(symbol->name,"$$dyncall") == 0 )
2719         dyncall = true;
2720
2721       /* 1. initialization for the call. */
2722
2723       NEW_INSTRUCTION(stub_entry, LDSID_31_1);
2724       NEW_INSTRUCTION(stub_entry, MTSP_1_SR0);
2725
2726       if ( !dyncall )
2727         {
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
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. */
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             }
2765           /* 3. Branch back to the original location.           */
2766           /*    (for non-millicode calls, accomplished with the COPY_31_2 instruction)  */
2767           /*    (for millicode calls, return location is already in r2) */
2768         }
2769       else
2770         {
2771           NEW_INSTRUCTION(stub_entry, LDIL_XXX_31);
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);
2777
2778           NEW_INSTRUCTION(stub_entry,BE_N_XXX_0_31);
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);
2784         }
2785     }
2786
2787   return stub_sym;
2788 }
2789
2790 int
2791 hppa_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
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
2822 asymbol *
2823 hppa_elf_stub_check (abfd, output_bfd, input_section, reloc_entry, symbol, hit_data)
2824      bfd *abfd;
2825      bfd *output_bfd;
2826      asection *input_section;
2827      arelent *reloc_entry;
2828      asymbol *symbol;
2829      bfd_byte *hit_data;
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      */
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       {
2874         symext_entryS caller_ar = (symext_entryS) HPPA_R_ARG_RELOC (reloc_entry->addend);
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       }
2890       break;
2891
2892     default:
2893       break;
2894     }
2895   return reloc_entry->sym_ptr_ptr[0];
2896 }
2897
2898 #define STUB_SYM_BUFFER_INC     5
2899
2900 asymbol *
2901 hppa_look_for_stubs_in_section (stub_bfd, abfd, output_bfd, asec, syms, new_sym_cnt)
2902      bfd *stub_bfd;
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
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. */
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
2936
2937           arelent *rle = reloc_vector[i];
2938
2939           switch (rle->howto->type)
2940             {
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               {
2980                 symext_entryS caller_ar = (symext_entryS) HPPA_R_ARG_RELOC (rle->addend);
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;
2987
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;
3001
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))
3007                     {
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;
3023                     }
3024                 }
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.  */
3040               {
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;
3045
3046                 if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types,
3047                                                  caller_ar))
3048                   {
3049                     /* generate a plabel stub */
3050                     /* keep track of the new symbol */
3051                     asymbol *r;
3052
3053                     if (new_cnt == new_max)
3054                       {
3055                         new_max += STUB_SYM_BUFFER_INC;
3056                         new_syms = (asymbol *) realloc (new_syms,
3057                                                         (new_max
3058                                                          * sizeof (asymbol)));
3059                       }
3060                     r = hppa_elf_build_arg_reloc_stub (stub_bfd,
3061                                                        output_bfd,
3062                                                        rle,
3063                                                        stub_types);
3064                     new_syms[new_cnt++] = *r;
3065                   }
3066               }
3067               break;
3068
3069             default:
3070               break;
3071
3072             }
3073         }
3074     }
3075   *new_sym_cnt = new_cnt;
3076   return new_syms;
3077 }
3078
3079
3080 char *linker_stubs = NULL;
3081 int linker_stubs_size = 0;
3082 int linker_stubs_max_size = 0;
3083 #define STUB_ALLOC_INCR 100
3084
3085 boolean
3086 DEFUN (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)
3092 {
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);
3110 }
3111
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
3119 boolean
3120 hppa_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;
3126 {
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.  */
3132   if (strcmp (section->name, ".hppa_linker_stubs") == 0)
3133     {
3134       elf32_hppa_stub_description *stub_desc = find_stubs (abfd, section);
3135       
3136       if (count == 0)
3137         return true;
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       
3144       memcpy (location, stub_desc->stub_contents + offset, count);
3145       return (true);
3146     }
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. */
3151   else if (strcmp (section->name, ".hppa_symextn") == 0)
3152     {
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)
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;
3168           int *symtab_map =
3169             (int *) elf_sym_extra(section->output_section->owner);
3170           
3171           for (i = 0; i < section->output_section->owner->symcount; i++ )
3172             {
3173               elf_hppa_tc_symbol(section->output_section->owner,
3174                                  ((elf_symbol_type *)
3175                                   section->output_section->owner->outsymbols[i]),
3176                                  symtab_map[i]);
3177             }
3178           symext_chain_built++;
3179           elf_hppa_tc_make_sections (section->output_section->owner, NULL);
3180         }
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.  */
3184       if (count == 0)
3185         return true;
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);
3195       return (true);
3196     }
3197   else
3198     return bfd_generic_get_section_contents (abfd, section, location,
3199                                              offset, count);
3200 }
3201
3202 static void
3203 DEFUN (elf_info_to_howto, (abfd, cache_ptr, dst),
3204        bfd * abfd AND
3205        arelent * cache_ptr AND
3206        Elf32_Internal_Rela * dst)
3207 {
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
3212 static void
3213 DEFUN (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
3229 struct elf32_hppa_symextn_map_struct
3230 {
3231   int old_index;
3232   bfd *bfd;
3233   asymbol *sym;
3234   int new_index;
3235 };
3236
3237 static struct elf32_hppa_symextn_map_struct *elf32_hppa_symextn_map;
3238 static int elf32_hppa_symextn_map_size;
3239
3240 static boolean
3241 DEFUN (elf32_hppa_backend_symbol_table_processing, (abfd, esyms,symcnt),
3242        bfd              * abfd AND
3243        elf_symbol_type  *esyms AND
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
3320 static boolean
3321 DEFUN (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
3376 static boolean
3377 DEFUN (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
3424 static boolean
3425 DEFUN (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
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
3462   return false;
3463 }
3464
3465 #define elf_backend_fake_sections       elf32_hppa_backend_fake_sections
3466
3467 static boolean
3468 DEFUN (elf32_hppa_backend_section_from_bfd_section, (abfd, hdr, asect, retval),
3469        bfd                      *abfd AND
3470        Elf32_Internal_Shdr      *hdr AND
3471        asection                 *asect AND
3472        int                      *retval)
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     }
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     }
3497
3498   return false;
3499 }
3500
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
3506 #define TARGET_BIG_SYM          bfd_elf32_hppa_vec
3507 #define TARGET_BIG_NAME         "elf32-hppa"
3508 #define ELF_ARCH                bfd_arch_hppa
3509 #define ELF_MACHINE_CODE        EM_HPPA
3510 #define ELF_MAXPAGESIZE         0x1000
3511
3512 #include "elf32-target.h"
This page took 0.226453 seconds and 4 git commands to generate.