* som.c (hppa_som_gen_reloc_type): New function.
[deliverable/binutils-gdb.git] / bfd / som.c
CommitLineData
d9ad93bc
KR
1/* bfd back-end for HP PA-RISC SOM objects.
2 Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3
4 Contributed by the Center for Software Science at the
5 University of Utah (pa-gdb-bugs@cs.utah.edu).
6
9e16fcf1 7 This file is part of BFD, the Binary File Descriptor library.
d9ad93bc 8
9e16fcf1
SG
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
d9ad93bc 13
9e16fcf1
SG
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
d9ad93bc 18
9e16fcf1
SG
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
d9ad93bc
KR
22
23#include "bfd.h"
24#include "sysdep.h"
25
d9ad93bc
KR
26#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD)
27
28#include "libbfd.h"
29#include "som.h"
70f1d738 30#include "libhppa.h"
d9ad93bc
KR
31
32#include <stdio.h>
33#include <sys/types.h>
34#include <sys/param.h>
35#include <sys/dir.h>
36#include <signal.h>
37#include <machine/reg.h>
38#include <sys/user.h> /* After a.out.h */
39#include <sys/file.h>
40#include <errno.h>
41
42/* Magic not defined in standard HP-UX header files until 8.0 */
43
44#ifndef CPU_PA_RISC1_0
45#define CPU_PA_RISC1_0 0x20B
46#endif /* CPU_PA_RISC1_0 */
47
48#ifndef CPU_PA_RISC1_1
49#define CPU_PA_RISC1_1 0x210
50#endif /* CPU_PA_RISC1_1 */
51
52#ifndef _PA_RISC1_0_ID
53#define _PA_RISC1_0_ID CPU_PA_RISC1_0
54#endif /* _PA_RISC1_0_ID */
55
56#ifndef _PA_RISC1_1_ID
57#define _PA_RISC1_1_ID CPU_PA_RISC1_1
58#endif /* _PA_RISC1_1_ID */
59
60#ifndef _PA_RISC_MAXID
61#define _PA_RISC_MAXID 0x2FF
62#endif /* _PA_RISC_MAXID */
63
64#ifndef _PA_RISC_ID
65#define _PA_RISC_ID(__m_num) \
66 (((__m_num) == _PA_RISC1_0_ID) || \
67 ((__m_num) >= _PA_RISC1_1_ID && (__m_num) <= _PA_RISC_MAXID))
68#endif /* _PA_RISC_ID */
69
4fdb66cd
JL
70/* SOM allows any one of the four previous relocations to be reused
71 with a "R_PREV_FIXUP" relocation entry. Since R_PREV_FIXUP
72 relocations are always a single byte, using a R_PREV_FIXUP instead
73 of some multi-byte relocation makes object files smaller.
74
75 Note one side effect of using a R_PREV_FIXUP is the relocation that
76 is being repeated moves to the front of the queue. */
77struct reloc_queue
78 {
79 unsigned char *reloc;
80 unsigned int size;
81 } reloc_queue[4];
82
83/* This fully describes the symbol types which may be attached to
84 an EXPORT or IMPORT directive. Only SOM uses this formation
85 (ELF has no need for it). */
86typedef enum
87{
88 SYMBOL_TYPE_UNKNOWN,
89 SYMBOL_TYPE_ABSOLUTE,
90 SYMBOL_TYPE_CODE,
91 SYMBOL_TYPE_DATA,
92 SYMBOL_TYPE_ENTRY,
93 SYMBOL_TYPE_MILLICODE,
94 SYMBOL_TYPE_PLABEL,
95 SYMBOL_TYPE_PRI_PROG,
96 SYMBOL_TYPE_SEC_PROG,
97} pa_symbol_type;
98
9e16fcf1
SG
99/* Forward declarations */
100
101static boolean som_mkobject PARAMS ((bfd *));
102static bfd_target * som_object_setup PARAMS ((bfd *,
103 struct header *,
104 struct som_exec_auxhdr *));
105static asection * make_unique_section PARAMS ((bfd *, CONST char *, int));
106static boolean setup_sections PARAMS ((bfd *, struct header *));
107static bfd_target * som_object_p PARAMS ((bfd *));
108static boolean som_write_object_contents PARAMS ((bfd *));
109static boolean som_slurp_string_table PARAMS ((bfd *));
110static unsigned int som_slurp_symbol_table PARAMS ((bfd *));
111static unsigned int som_get_symtab_upper_bound PARAMS ((bfd *));
112static unsigned int som_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
113 arelent **, asymbol **));
114static unsigned int som_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
115static unsigned int som_get_symtab PARAMS ((bfd *, asymbol **));
116static asymbol * som_make_empty_symbol PARAMS ((bfd *));
117static void som_print_symbol PARAMS ((bfd *, PTR,
118 asymbol *, bfd_print_symbol_type));
119static boolean som_new_section_hook PARAMS ((bfd *, asection *));
120static boolean som_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
121 file_ptr, bfd_size_type));
122static boolean som_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
123 unsigned long));
124static boolean som_find_nearest_line PARAMS ((bfd *, asection *,
125 asymbol **, bfd_vma,
126 CONST char **,
127 CONST char **,
128 unsigned int *));
129static void som_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
130static asection * som_section_from_subspace_index PARAMS ((bfd *,
131 unsigned int));
132static int log2 PARAMS ((unsigned int));
fcb0c846
JL
133static bfd_reloc_status_type hppa_som_reloc PARAMS ((bfd *, arelent *,
134 asymbol *, PTR,
135 asection *, bfd *));
d125665c
JL
136static void som_initialize_reloc_queue PARAMS ((struct reloc_queue *));
137static void som_reloc_queue_insert PARAMS ((unsigned char *, unsigned int,
138 struct reloc_queue *));
139static void som_reloc_queue_fix PARAMS ((struct reloc_queue *, unsigned int));
140static int som_reloc_queue_find PARAMS ((unsigned char *, unsigned int,
141 struct reloc_queue *));
54bbfd37
JL
142static unsigned char * try_prev_fixup PARAMS ((bfd *, int *, unsigned char *,
143 unsigned int,
144 struct reloc_queue *));
145
146static unsigned char * som_reloc_skip PARAMS ((bfd *, unsigned int,
147 unsigned char *, unsigned int *,
148 struct reloc_queue *));
149static unsigned char * som_reloc_addend PARAMS ((bfd *, int, unsigned char *,
150 unsigned int *,
151 struct reloc_queue *));
9e16fcf1 152
fcb0c846
JL
153static reloc_howto_type som_hppa_howto_table[] =
154{
155 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
156 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
157 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
158 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
159 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
160 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
161 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
162 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
163 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
164 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
165 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
166 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
167 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
168 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
169 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
170 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
171 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
172 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
173 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
174 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
175 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
176 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
177 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
178 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
179 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
180 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
181 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
182 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
183 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
184 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
185 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
186 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
187 {R_ZEROES, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ZEROES"},
188 {R_ZEROES, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ZEROES"},
189 {R_UNINIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_UNINIT"},
190 {R_UNINIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_UNINIT"},
191 {R_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RELOCATION"},
192 {R_DATA_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_ONE_SYMBOL"},
193 {R_DATA_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_ONE_SYMBOL"},
194 {R_DATA_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_PLABEL"},
195 {R_DATA_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_PLABEL"},
196 {R_SPACE_REF, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SPACE_REF"},
197 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
198 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
199 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
200 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
201 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
202 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
203 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
204 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
205 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
206 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
207 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
208 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
209 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
210 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
211 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
212 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
213 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
214 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
215 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
216 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
217 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
218 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
219 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
220 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
221 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
222 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
223 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
224 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
225 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
226 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
227 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
228 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
229 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
230 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
231 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
232 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
233 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
234 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
235 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
236 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
237 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
238 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
239 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
240 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
241 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
242 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
243 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
244 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
245 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
246 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
247 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
248 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
249 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
250 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
251 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
252 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
253 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
254 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
255 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
256 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
257 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
258 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
259 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
260 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
261 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
262 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
263 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
264 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
265 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
266 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
267 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
268 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
269 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
270 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
271 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
272 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
273 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
274 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
275 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
276 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
277 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
278 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
279 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
280 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
281 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
282 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
283 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
284 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
285 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
286 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
287 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
288 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
289 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
290 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
291 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
292 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
293 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
294 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
295 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
296 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
297 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
298 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
299 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
300 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
301 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
302 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
303 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
304 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
305 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
306 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
307 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
308 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
309 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
310 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
311 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
312 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
313 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
314 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
315 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
316 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
317 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
318 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
319 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
320 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
321 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
322 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
323 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
324 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
325 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
326 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
327 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
328 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
329 {R_MILLI_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_MILLI_REL"},
330 {R_MILLI_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_MILLI_REL"},
331 {R_CODE_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_PLABEL"},
332 {R_CODE_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_PLABEL"},
333 {R_BREAKPOINT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BREAKPOINT"},
334 {R_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ENTRY"},
335 {R_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ENTRY"},
336 {R_ALT_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ALT_ENTRY"},
337 {R_EXIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_EXIT"},
338 {R_BEGIN_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BEGIN_TRY"},
339 {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
340 {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
341 {R_BEGIN_BRTAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BEGIN_BRTAB"},
342 {R_END_BRTAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_BRTAB"},
343 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
344 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
345 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
346 {R_DATA_EXPR, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_EXPR"},
347 {R_CODE_EXPR, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_EXPR"},
348 {R_FSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_FSEL"},
349 {R_LSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LSEL"},
350 {R_RSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RSEL"},
351 {R_N_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N_MODE"},
352 {R_S_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_S_MODE"},
353 {R_D_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_D_MODE"},
354 {R_R_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_R_MODE"},
355 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
356 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
357 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
358 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
359 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
360 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
361 {R_TRANSLATED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_TRANSLATED"},
362 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
363 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
364 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
365 {R_COMP1, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP1"},
366 {R_COMP2, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP2"},
367 {R_COMP3, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP3"},
368 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
369 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
370 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
371 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
372 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
373 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
374 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
375 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
376 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
377 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
378 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
379 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
380 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
381 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
382 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
383 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
384 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
385 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
386 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
387 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
388 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
389 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
390 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
391 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
392 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
393 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
394 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
395 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
396 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
397 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
398 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
399 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
400 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
401 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
402 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
403 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
404 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
405 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
406 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
407 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
408 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
409 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
410 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
411 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
412 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"}};
413
d125665c
JL
414
415/* Initialize the SOM relocation queue. By definition the queue holds
416 the last four multibyte fixups. */
417
418static void
419som_initialize_reloc_queue (queue)
420 struct reloc_queue *queue;
421{
422 queue[0].reloc = NULL;
423 queue[0].size = 0;
424 queue[1].reloc = NULL;
425 queue[1].size = 0;
426 queue[2].reloc = NULL;
427 queue[2].size = 0;
428 queue[3].reloc = NULL;
429 queue[3].size = 0;
430}
431
432/* Insert a new relocation into the relocation queue. */
433
434static void
435som_reloc_queue_insert (p, size, queue)
436 unsigned char *p;
437 unsigned int size;
438 struct reloc_queue *queue;
439{
440 queue[3].reloc = queue[2].reloc;
441 queue[3].size = queue[2].size;
442 queue[2].reloc = queue[1].reloc;
443 queue[2].size = queue[1].size;
444 queue[1].reloc = queue[0].reloc;
445 queue[1].size = queue[0].size;
446 queue[0].reloc = p;
447 queue[0].size = size;
448}
449
450/* When an entry in the relocation queue is reused, the entry moves
451 to the front of the queue. */
452
453static void
454som_reloc_queue_fix (queue, index)
455 struct reloc_queue *queue;
456 unsigned int index;
457{
458 if (index == 0)
459 return;
460
461 if (index == 1)
462 {
463 unsigned char *tmp1 = queue[0].reloc;
464 unsigned int tmp2 = queue[0].size;
465 queue[0].reloc = queue[1].reloc;
466 queue[0].size = queue[1].size;
467 queue[1].reloc = tmp1;
468 queue[1].size = tmp2;
469 return;
470 }
471
472 if (index == 2)
473 {
474 unsigned char *tmp1 = queue[0].reloc;
475 unsigned int tmp2 = queue[0].size;
476 queue[0].reloc = queue[2].reloc;
477 queue[0].size = queue[2].size;
478 queue[2].reloc = queue[1].reloc;
479 queue[2].size = queue[1].size;
480 queue[1].reloc = tmp1;
481 queue[1].size = tmp2;
482 return;
483 }
484
485 if (index == 3)
486 {
487 unsigned char *tmp1 = queue[0].reloc;
488 unsigned int tmp2 = queue[0].size;
489 queue[0].reloc = queue[3].reloc;
490 queue[0].size = queue[3].size;
491 queue[3].reloc = queue[2].reloc;
492 queue[3].size = queue[2].size;
493 queue[2].reloc = queue[1].reloc;
494 queue[2].size = queue[1].size;
495 queue[1].reloc = tmp1;
496 queue[1].size = tmp2;
497 return;
498 }
499 abort();
500}
501
502/* Search for a particular relocation in the relocation queue. */
503
504static int
505som_reloc_queue_find (p, size, queue)
506 unsigned char *p;
507 unsigned int size;
508 struct reloc_queue *queue;
509{
510 if (!bcmp (p, queue[0].reloc, size)
511 && size == queue[0].size)
512 return 0;
513 if (!bcmp (p, queue[1].reloc, size)
514 && size == queue[1].size)
515 return 1;
516 if (!bcmp (p, queue[2].reloc, size)
517 && size == queue[2].size)
518 return 2;
519 if (!bcmp (p, queue[3].reloc, size)
520 && size == queue[3].size)
521 return 3;
522 return -1;
523}
54bbfd37
JL
524
525static unsigned char *
526try_prev_fixup (abfd, subspace_reloc_sizep, p, size, queue)
527 bfd *abfd;
528 int *subspace_reloc_sizep;
529 unsigned char *p;
530 unsigned int size;
531 struct reloc_queue *queue;
532{
533 int queue_index = som_reloc_queue_find (p, size, queue);
534
535 if (queue_index != -1)
536 {
537 /* Found this in a previous fixup. Undo the fixup we
538 just built and use R_PREV_FIXUP instead. We saved
539 a total of size - 1 bytes in the fixup stream. */
540 bfd_put_8 (abfd, R_PREV_FIXUP + queue_index, p);
541 p += 1;
542 *subspace_reloc_sizep += 1;
543 som_reloc_queue_fix (queue, queue_index);
544 }
545 else
546 {
547 som_reloc_queue_insert (p, size, queue);
548 *subspace_reloc_sizep += size;
549 p += size;
550 }
551 return p;
552}
553
554/* Emit the proper R_NO_RELOCATION fixups to map the next SKIP
555 bytes without any relocation. Update the size of the subspace
556 relocation stream via SUBSPACE_RELOC_SIZE_P; also return the
557 current pointer into the relocation stream. */
558
559static unsigned char *
560som_reloc_skip (abfd, skip, p, subspace_reloc_sizep, queue)
561 bfd *abfd;
562 unsigned int skip;
563 unsigned char *p;
564 unsigned int *subspace_reloc_sizep;
565 struct reloc_queue *queue;
566{
567 /* Use a 4 byte R_NO_RELOCATION entry with a maximal value
568 then R_PREV_FIXUPs to get the difference down to a
569 reasonable size. */
570 if (skip >= 0x1000000)
571 {
572 skip -= 0x1000000;
573 bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
574 bfd_put_8 (abfd, 0xff, p + 1);
575 bfd_put_16 (abfd, 0xffff, p + 2);
576 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
577 while (skip >= 0x1000000)
578 {
579 skip -= 0x1000000;
580 bfd_put_8 (abfd, R_PREV_FIXUP, p);
581 p++;
582 *subspace_reloc_sizep += 1;
583 /* No need to adjust queue here since we are repeating the
584 most recent fixup. */
585 }
586 }
587
588 /* The difference must be less than 0x1000000. Use one
589 more R_NO_RELOCATION entry to get to the right difference. */
590 if ((skip & 3) == 0 && skip <= 0xc0000 && skip > 0)
591 {
592 /* Difference can be handled in a simple single-byte
593 R_NO_RELOCATION entry. */
594 if (skip <= 0x60)
595 {
596 bfd_put_8 (abfd, R_NO_RELOCATION + (skip >> 2) - 1, p);
597 *subspace_reloc_sizep += 1;
598 p++;
599 }
600 /* Handle it with a two byte R_NO_RELOCATION entry. */
601 else if (skip <= 0x1000)
602 {
603 bfd_put_8 (abfd, R_NO_RELOCATION + 24 + (((skip >> 2) - 1) >> 8), p);
604 bfd_put_8 (abfd, (skip >> 2) - 1, p + 1);
605 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
606 }
607 /* Handle it with a three byte R_NO_RELOCATION entry. */
608 else
609 {
610 bfd_put_8 (abfd, R_NO_RELOCATION + 28 + (((skip >> 2) - 1) >> 16), p);
611 bfd_put_16 (abfd, (skip >> 2) - 1, p + 1);
612 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
613 }
614 }
615 /* Ugh. Punt and use a 4 byte entry. */
616 else if (skip > 0)
617 {
618 bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
619 bfd_put_8 (abfd, skip >> 16, p + 1);
620 bfd_put_16 (abfd, skip, p + 2);
621 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
622 }
623 return p;
624}
625
626/* Emit the proper R_DATA_OVERRIDE fixups to handle a nonzero addend
627 from a BFD relocation. Update the size of the subspace relocation
628 stream via SUBSPACE_RELOC_SIZE_P; also return the current pointer
629 into the relocation stream. */
630
631static unsigned char *
632som_reloc_addend (abfd, addend, p, subspace_reloc_sizep, queue)
633 bfd *abfd;
634 int addend;
635 unsigned char *p;
636 unsigned int *subspace_reloc_sizep;
637 struct reloc_queue *queue;
638{
639 if ((unsigned)(addend) + 0x80 < 0x100)
640 {
641 bfd_put_8 (abfd, R_DATA_OVERRIDE + 1, p);
642 bfd_put_8 (abfd, addend, p + 1);
643 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
644 }
645 else if ((unsigned) (addend) + 0x8000 < 0x10000)
646 {
647 bfd_put_8 (abfd, R_DATA_OVERRIDE + 2, p);
648 bfd_put_16 (abfd, addend, p + 1);
649 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
650 }
651 else if ((unsigned) (addend) + 0x800000 < 0x1000000)
652 {
653 bfd_put_8 (abfd, R_DATA_OVERRIDE + 3, p);
654 bfd_put_8 (abfd, addend >> 16, p + 1);
655 bfd_put_16 (abfd, addend, p + 2);
656 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
657 }
658 else
659 {
660 bfd_put_8 (abfd, R_DATA_OVERRIDE + 4, p);
661 bfd_put_32 (abfd, addend, p + 1);
662 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
663 }
664 return p;
665}
666
9e16fcf1 667/* Return the logarithm of X, base 2, considering X unsigned.
40249bfb
JL
668 Abort if X is not a power of two -- this should never happen (FIXME:
669 It will happen on corrupt executables. GDB should give an error, not
670 a coredump, in that case). */
9e16fcf1
SG
671
672static int
673log2 (x)
674 unsigned int x;
675{
676 int log = 0;
677
678 /* Test for 0 or a power of 2. */
679 if (x == 0 || x != (x & -x))
680 abort();
681
682 while ((x >>= 1) != 0)
683 log++;
684 return log;
685}
686
fcb0c846
JL
687static bfd_reloc_status_type
688hppa_som_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd)
689 bfd *abfd;
690 arelent *reloc_entry;
691 asymbol *symbol_in;
692 PTR data;
693 asection *input_section;
694 bfd *output_bfd;
695{
696 if (output_bfd)
697 {
698 reloc_entry->address += input_section->output_offset;
699 return bfd_reloc_ok;
700 }
701 return bfd_reloc_ok;
702}
32619c58
JL
703
704/* Given a generic HPPA relocation type, the instruction format,
705 and a field selector, return an appropriate SOM reloation.
706
707 FIXME. Need to handle %RR, %LR and the like as field selectors.
708 These will need to generate multiple SOM relocations. */
709
710int **
711hppa_som_gen_reloc_type (abfd, base_type, format, field)
712 bfd *abfd;
713 int base_type;
714 int format;
715 int field;
716{
717 int *final_type, **final_types;
718
719 final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 2);
720 final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
721
722
723 final_types[0] = final_type;
724 final_types[1] = NULL;
725
726 /* Default to the basic relocation passed in. */
727 *final_type = base_type;
728
729 switch (base_type)
730 {
731 case R_HPPA:
732 /* PLABELs get their own relocation type. */
733 if (field == e_psel
734 || field == e_lpsel
735 || field == e_rpsel)
736 {
737 /* A PLABEL relocation that has a size of 32 bits must
738 be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */
739 if (format == 32)
740 *final_type = R_DATA_PLABEL;
741 else
742 *final_type = R_CODE_PLABEL;
743 }
744 /* A relocatoin in the data space is always a full 32bits. */
745 else if (format == 32)
746 *final_type = R_DATA_ONE_SYMBOL;
747
748 break;
749
750 case R_HPPA_GOTOFF:
751 /* More PLABEL special cases. */
752 if (field == e_psel
753 || field == e_lpsel
754 || field == e_rpsel)
755 *final_type = R_DATA_PLABEL;
756 break;
757
758 case R_HPPA_NONE:
759 case R_HPPA_ABS_CALL:
760 case R_HPPA_PCREL_CALL:
761 case R_HPPA_COMPLEX:
762 case R_HPPA_COMPLEX_PCREL_CALL:
763 case R_HPPA_COMPLEX_ABS_CALL:
764 /* Right now we can default all these. */
765 break;
766 }
767 return final_types;
768}
769
770/* Return the address of the correct entry in the PA SOM relocation
771 howto table. */
772
773static reloc_howto_type *
774som_bfd_reloc_type_lookup (arch, code)
775 bfd_arch_info_type *arch;
776 bfd_reloc_code_real_type code;
777{
778 if ((int) code < (int) R_NO_RELOCATION + 255)
779 {
780 BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code);
781 return &som_hppa_howto_table[(int) code];
782 }
783
784 return (reloc_howto_type *) 0;
785}
786
9e16fcf1
SG
787/* Perform some initialization for an object. Save results of this
788 initialization in the BFD. */
d9ad93bc
KR
789
790static bfd_target *
9e16fcf1 791som_object_setup (abfd, file_hdrp, aux_hdrp)
d9ad93bc
KR
792 bfd *abfd;
793 struct header *file_hdrp;
794 struct som_exec_auxhdr *aux_hdrp;
795{
d9ad93bc
KR
796 asection *text, *data, *bss;
797
9e16fcf1
SG
798 /* som_mkobject will set bfd_error if som_mkobject fails. */
799 if (som_mkobject (abfd) != true)
800 return 0;
d9ad93bc 801
9e16fcf1
SG
802 /* Make the standard .text, .data, and .bss sections so that tools
803 which assume those names work (size for example). They will have
804 no contents, but the sizes and such will reflect those of the
805 $CODE$, $DATA$, and $BSS$ subspaces respectively.
d9ad93bc 806
9e16fcf1 807 FIXME: Should check return status from bfd_make_section calls below. */
d9ad93bc
KR
808
809 text = bfd_make_section (abfd, ".text");
810 data = bfd_make_section (abfd, ".data");
811 bss = bfd_make_section (abfd, ".bss");
812
813 text->_raw_size = aux_hdrp->exec_tsize;
814 data->_raw_size = aux_hdrp->exec_dsize;
815 bss->_raw_size = aux_hdrp->exec_bsize;
816
9e16fcf1 817 text->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_CODE);
d9ad93bc
KR
818 data->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS);
819 bss->flags = (SEC_ALLOC | SEC_IS_COMMON);
820
821 /* The virtual memory addresses of the sections */
822 text->vma = aux_hdrp->exec_tmem;
823 data->vma = aux_hdrp->exec_dmem;
824 bss->vma = aux_hdrp->exec_bfill;
825
826 /* The file offsets of the sections */
827 text->filepos = aux_hdrp->exec_tfile;
828 data->filepos = aux_hdrp->exec_dfile;
829
830 /* The file offsets of the relocation info */
831 text->rel_filepos = 0;
832 data->rel_filepos = 0;
833
9e16fcf1
SG
834 /* Set BFD flags based on what information is available in the SOM. */
835 abfd->flags = NO_FLAGS;
836 if (! file_hdrp->entry_offset)
837 abfd->flags |= HAS_RELOC;
838 else
839 abfd->flags |= EXEC_P;
840 if (file_hdrp->symbol_total)
841 abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
842
843 bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
844 bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
d9ad93bc 845 bfd_get_symcount (abfd) = file_hdrp->symbol_total;
9e16fcf1
SG
846
847 /* Initialize the saved symbol table and string table to NULL.
848 Save important offsets and sizes from the SOM header into
849 the BFD. */
850 obj_som_stringtab (abfd) = (char *) NULL;
851 obj_som_symtab (abfd) = (som_symbol_type *) NULL;
852 obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
853 obj_som_sym_filepos (abfd) = file_hdrp->symbol_location;
854 obj_som_str_filepos (abfd) = file_hdrp->symbol_strings_location;
855 obj_som_reloc_filepos (abfd) = file_hdrp->fixup_request_location;
d9ad93bc
KR
856
857 return abfd->xvec;
858}
859
860/* Create a new BFD section for NAME. If NAME already exists, then create a
861 new unique name, with NAME as the prefix. This exists because SOM .o files
9e16fcf1 862 may have more than one $CODE$ subspace. */
d9ad93bc
KR
863
864static asection *
865make_unique_section (abfd, name, num)
866 bfd *abfd;
867 CONST char *name;
868 int num;
869{
870 asection *sect;
871 char *newname;
872 char altname[100];
873
874 sect = bfd_make_section (abfd, name);
875 while (!sect)
876 {
877 sprintf (altname, "%s-%d", name, num++);
878 sect = bfd_make_section (abfd, altname);
879 }
880
881 newname = bfd_alloc (abfd, strlen (sect->name) + 1);
882 strcpy (newname, sect->name);
883
884 sect->name = newname;
885 return sect;
886}
887
888/* Convert all of the space and subspace info into BFD sections. Each space
889 contains a number of subspaces, which in turn describe the mapping between
890 regions of the exec file, and the address space that the program runs in.
891 BFD sections which correspond to spaces will overlap the sections for the
892 associated subspaces. */
893
9e16fcf1 894static boolean
d9ad93bc
KR
895setup_sections (abfd, file_hdr)
896 bfd *abfd;
897 struct header *file_hdr;
898{
899 char *space_strings;
900 int space_index;
9e16fcf1 901 unsigned int total_subspaces = 0;
d9ad93bc
KR
902
903 /* First, read in space names */
904
905 space_strings = alloca (file_hdr->space_strings_size);
906 if (!space_strings)
9e16fcf1 907 return false;
d9ad93bc
KR
908
909 if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
9e16fcf1 910 return false;
d9ad93bc
KR
911 if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd)
912 != file_hdr->space_strings_size)
9e16fcf1 913 return false;
d9ad93bc
KR
914
915 /* Loop over all of the space dictionaries, building up sections */
d9ad93bc
KR
916 for (space_index = 0; space_index < file_hdr->space_total; space_index++)
917 {
918 struct space_dictionary_record space;
9e16fcf1
SG
919 struct subspace_dictionary_record subspace, save_subspace;
920 int subspace_index;
d9ad93bc
KR
921 asection *space_asect;
922
923 /* Read the space dictionary element */
924 if (bfd_seek (abfd, file_hdr->space_location
925 + space_index * sizeof space, SEEK_SET) < 0)
9e16fcf1 926 return false;
d9ad93bc 927 if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space)
9e16fcf1 928 return false;
d9ad93bc
KR
929
930 /* Setup the space name string */
931 space.name.n_name = space.name.n_strx + space_strings;
932
933 /* Make a section out of it */
934 space_asect = make_unique_section (abfd, space.name.n_name, space_index);
935 if (!space_asect)
9e16fcf1 936 return false;
d9ad93bc
KR
937
938 /* Now, read in the first subspace for this space */
939 if (bfd_seek (abfd, file_hdr->subspace_location
940 + space.subspace_index * sizeof subspace,
941 SEEK_SET) < 0)
9e16fcf1 942 return false;
d9ad93bc 943 if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace)
9e16fcf1 944 return false;
d9ad93bc
KR
945 /* Seek back to the start of the subspaces for loop below */
946 if (bfd_seek (abfd, file_hdr->subspace_location
947 + space.subspace_index * sizeof subspace,
948 SEEK_SET) < 0)
9e16fcf1 949 return false;
d9ad93bc
KR
950
951 /* Setup the start address and file loc from the first subspace record */
952 space_asect->vma = subspace.subspace_start;
953 space_asect->filepos = subspace.file_loc_init_value;
9e16fcf1
SG
954 space_asect->alignment_power = log2 (subspace.alignment);
955
956 /* Initialize save_subspace so we can reliably determine if this
957 loop placed any useful values into it. */
958 bzero (&save_subspace, sizeof (struct subspace_dictionary_record));
d9ad93bc
KR
959
960 /* Loop over the rest of the subspaces, building up more sections */
961 for (subspace_index = 0; subspace_index < space.subspace_quantity;
962 subspace_index++)
963 {
964 asection *subspace_asect;
965
966 /* Read in the next subspace */
967 if (bfd_read (&subspace, 1, sizeof subspace, abfd)
968 != sizeof subspace)
9e16fcf1 969 return false;
d9ad93bc
KR
970
971 /* Setup the subspace name string */
972 subspace.name.n_name = subspace.name.n_strx + space_strings;
973
974 /* Make a section out of this subspace */
975 subspace_asect = make_unique_section (abfd, subspace.name.n_name,
976 space.subspace_index + subspace_index);
977
978 if (!subspace_asect)
9e16fcf1
SG
979 return false;
980
981 /* Keep an easy mapping between subspaces and sections. */
982 som_section_data (subspace_asect)->subspace_index
983 = total_subspaces++;
984
985 /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
986 by the access_control_bits in the subspace header. */
987 switch (subspace.access_control_bits >> 4)
988 {
989 /* Readonly data. */
990 case 0x0:
991 subspace_asect->flags |= SEC_DATA | SEC_READONLY;
992 break;
993
994 /* Normal data. */
995 case 0x1:
996 subspace_asect->flags |= SEC_DATA;
997 break;
998
999 /* Readonly code and the gateways.
1000 Gateways have other attributes which do not map
1001 into anything BFD knows about. */
1002 case 0x2:
1003 case 0x4:
1004 case 0x5:
1005 case 0x6:
1006 case 0x7:
1007 subspace_asect->flags |= SEC_CODE | SEC_READONLY;
1008 break;
1009
1010 /* dynamic (writable) code. */
1011 case 0x3:
1012 subspace_asect->flags |= SEC_CODE;
1013 break;
1014 }
1015
1016 if (subspace.dup_common || subspace.is_common)
1017 subspace_asect->flags |= SEC_IS_COMMON;
1018 else
1019 subspace_asect->flags |= SEC_HAS_CONTENTS;
d9ad93bc
KR
1020 if (subspace.is_loadable)
1021 subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
1022 if (subspace.code_only)
1023 subspace_asect->flags |= SEC_CODE;
1024
9e16fcf1
SG
1025 /* This subspace has relocations.
1026 The fixup_request_quantity is a byte count for the number of
1027 entries in the relocation stream; it is not the actual number
1028 of relocations in the subspace. */
1029 if (subspace.fixup_request_quantity != 0)
1030 {
1031 subspace_asect->flags |= SEC_RELOC;
1032 subspace_asect->rel_filepos = subspace.fixup_request_index;
1033 som_section_data (subspace_asect)->reloc_size
1034 = subspace.fixup_request_quantity;
1035 /* We can not determine this yet. When we read in the
1036 relocation table the correct value will be filled in. */
1037 subspace_asect->reloc_count = -1;
1038 }
1039
1040 /* Update save_subspace if appropriate. */
1041 if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
1042 save_subspace = subspace;
1043
d9ad93bc
KR
1044 subspace_asect->vma = subspace.subspace_start;
1045 subspace_asect->_cooked_size = subspace.subspace_length;
1046 subspace_asect->_raw_size = subspace.initialization_length;
9e16fcf1 1047 subspace_asect->alignment_power = log2 (subspace.alignment);
d9ad93bc 1048 subspace_asect->filepos = subspace.file_loc_init_value;
d9ad93bc 1049 }
9e16fcf1
SG
1050
1051 /* Yow! there is no subspace within the space which actually
1052 has initialized information in it; this should never happen
1053 as far as I know. */
1054 if (!save_subspace.file_loc_init_value)
1055 abort ();
1056
d9ad93bc 1057 /* Setup the sizes for the space section based upon the info in the
9e16fcf1
SG
1058 last subspace of the space. */
1059 space_asect->_cooked_size = save_subspace.subspace_start
1060 - space_asect->vma + save_subspace.subspace_length;
1061 space_asect->_raw_size = save_subspace.file_loc_init_value
1062 - space_asect->filepos + save_subspace.initialization_length;
d9ad93bc 1063 }
9e16fcf1 1064 return true;
d9ad93bc
KR
1065}
1066
9e16fcf1
SG
1067/* Read in a SOM object and make it into a BFD. */
1068
d9ad93bc 1069static bfd_target *
9e16fcf1 1070som_object_p (abfd)
d9ad93bc
KR
1071 bfd *abfd;
1072{
1073 struct header file_hdr;
1074 struct som_exec_auxhdr aux_hdr;
1075
1076 if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
9e16fcf1
SG
1077 {
1078 bfd_error = system_call_error;
1079 return 0;
1080 }
d9ad93bc
KR
1081
1082 if (!_PA_RISC_ID (file_hdr.system_id))
1083 {
1084 bfd_error = wrong_format;
1085 return 0;
1086 }
1087
1088 switch (file_hdr.a_magic)
1089 {
9e16fcf1 1090 case RELOC_MAGIC:
d9ad93bc
KR
1091 case EXEC_MAGIC:
1092 case SHARE_MAGIC:
1093 case DEMAND_MAGIC:
1094#ifdef DL_MAGIC
1095 case DL_MAGIC:
1096#endif
1097#ifdef SHL_MAGIC
1098 case SHL_MAGIC:
9e16fcf1
SG
1099#endif
1100#ifdef EXECLIBMAGIC
1101 case EXECLIBMAGIC:
d9ad93bc
KR
1102#endif
1103 break;
1104 default:
1105 bfd_error = wrong_format;
1106 return 0;
1107 }
1108
1109 if (file_hdr.version_id != VERSION_ID
1110 && file_hdr.version_id != NEW_VERSION_ID)
1111 {
1112 bfd_error = wrong_format;
1113 return 0;
1114 }
1115
9e16fcf1
SG
1116 /* If the aux_header_size field in the file header is zero, then this
1117 object is an incomplete executable (a .o file). Do not try to read
1118 a non-existant auxiliary header. */
1119 bzero (&aux_hdr, sizeof (struct som_exec_auxhdr));
1120 if (file_hdr.aux_header_size != 0)
1121 {
1122 if (bfd_read ((PTR) & aux_hdr, 1, AUX_HDR_SIZE, abfd) != AUX_HDR_SIZE)
1123 {
1124 bfd_error = wrong_format;
1125 return 0;
1126 }
1127 }
d9ad93bc
KR
1128
1129 if (!setup_sections (abfd, &file_hdr))
9e16fcf1
SG
1130 {
1131 /* setup_sections does not bubble up a bfd error code. */
1132 bfd_error = bad_value;
1133 return 0;
1134 }
d9ad93bc 1135
9e16fcf1
SG
1136 /* This appears to be a valid SOM object. Do some initialization. */
1137 return som_object_setup (abfd, &file_hdr, &aux_hdr);
d9ad93bc
KR
1138}
1139
9e16fcf1
SG
1140/* Create a SOM object. */
1141
d9ad93bc 1142static boolean
9e16fcf1 1143som_mkobject (abfd)
d9ad93bc
KR
1144 bfd *abfd;
1145{
9e16fcf1
SG
1146 /* Allocate memory to hold backend information. */
1147 abfd->tdata.som_data = (struct som_data_struct *)
1148 bfd_zalloc (abfd, sizeof (struct som_data_struct));
1149 if (abfd->tdata.som_data == NULL)
1150 {
1151 bfd_error = no_memory;
1152 return false;
1153 }
1154 obj_som_file_hdr (abfd) = bfd_zalloc (abfd, sizeof (struct header));
1155 if (obj_som_file_hdr (abfd) == NULL)
1156
1157 {
1158 bfd_error = no_memory;
1159 return false;
1160 }
1161 return true;
d9ad93bc
KR
1162}
1163
1164boolean
9e16fcf1 1165som_write_object_contents (abfd)
d9ad93bc
KR
1166 bfd *abfd;
1167{
9e16fcf1 1168 fprintf (stderr, "som_write_object_contents unimplemented\n");
d9ad93bc
KR
1169 fflush (stderr);
1170 abort ();
1171 return (false);
1172}
9e16fcf1 1173/* Read and save the string table associated with the given BFD. */
d9ad93bc 1174
9e16fcf1
SG
1175static boolean
1176som_slurp_string_table (abfd)
d9ad93bc
KR
1177 bfd *abfd;
1178{
9e16fcf1
SG
1179 char *stringtab;
1180
1181 /* Use the saved version if its available. */
1182 if (obj_som_stringtab (abfd) != NULL)
1183 return true;
1184
1185 /* Allocate and read in the string table. */
1186 stringtab = bfd_zalloc (abfd, obj_som_stringtab_size (abfd));
1187 if (stringtab == NULL)
1188 {
1189 bfd_error = no_memory;
1190 return false;
1191 }
1192
1193 if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
1194 {
1195 bfd_error = system_call_error;
1196 return false;
1197 }
1198
1199 if (bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd)
1200 != obj_som_stringtab_size (abfd))
1201 {
1202 bfd_error = system_call_error;
1203 return false;
1204 }
1205
1206 /* Save our results and return success. */
1207 obj_som_stringtab (abfd) = stringtab;
1208 return true;
d9ad93bc
KR
1209}
1210
9e16fcf1
SG
1211/* Return the amount of data (in bytes) required to hold the symbol
1212 table for this object. */
1213
d9ad93bc 1214static unsigned int
9e16fcf1 1215som_get_symtab_upper_bound (abfd)
d9ad93bc 1216 bfd *abfd;
d9ad93bc 1217{
9e16fcf1
SG
1218 if (!som_slurp_symbol_table (abfd))
1219 return 0;
1220
1221 return (bfd_get_symcount (abfd) + 1) * (sizeof (som_symbol_type *));
d9ad93bc
KR
1222}
1223
9e16fcf1
SG
1224/* Convert from a SOM subspace index to a BFD section. */
1225
1226static asection *
1227som_section_from_subspace_index (abfd, index)
1228 bfd *abfd;
1229 unsigned int index;
1230{
1231 asection *section;
1232
1233 for (section = abfd->sections; section != NULL; section = section->next)
1234 if (som_section_data (section)->subspace_index == index)
1235 return section;
1236
1237 /* Should never happen. */
1238 abort();
1239}
1240
1241/* Read and save the symbol table associated with the given BFD. */
1242
d9ad93bc 1243static unsigned int
9e16fcf1 1244som_slurp_symbol_table (abfd)
d9ad93bc 1245 bfd *abfd;
d9ad93bc 1246{
9e16fcf1
SG
1247 int symbol_count = bfd_get_symcount (abfd);
1248 int symsize = sizeof (struct symbol_dictionary_record);
1249 char *stringtab;
1250 struct symbol_dictionary_record *buf, *bufp, *endbufp;
1251 som_symbol_type *sym, *symbase;
1252
1253 /* Return saved value if it exists. */
1254 if (obj_som_symtab (abfd) != NULL)
1255 return true;
1256
1257 /* Sanity checking. Make sure there are some symbols and that
1258 we can read the string table too. */
1259 if (symbol_count == 0)
1260 {
1261 bfd_error = no_symbols;
1262 return false;
1263 }
1264
1265 if (!som_slurp_string_table (abfd))
1266 return false;
1267
1268 stringtab = obj_som_stringtab (abfd);
1269
1270 symbase = (som_symbol_type *)
1271 bfd_zalloc (abfd, symbol_count * sizeof (som_symbol_type));
1272 if (symbase == NULL)
1273 {
1274 bfd_error = no_memory;
1275 return false;
1276 }
1277
1278 /* Read in the external SOM representation. */
1279 buf = alloca (symbol_count * symsize);
1280 if (buf == NULL)
1281 {
1282 bfd_error = no_memory;
1283 return false;
1284 }
1285 if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
1286 {
1287 bfd_error = system_call_error;
1288 return false;
1289 }
1290 if (bfd_read (buf, symbol_count * symsize, 1, abfd)
1291 != symbol_count * symsize)
1292 {
1293 bfd_error = no_symbols;
1294 return (false);
1295 }
1296
1297 /* Iterate over all the symbols and internalize them. */
1298 endbufp = buf + symbol_count;
1299 for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
1300 {
1301
1302 /* I don't think we care about these. */
1303 if (bufp->symbol_type == ST_SYM_EXT
1304 || bufp->symbol_type == ST_ARG_EXT)
1305 continue;
1306
1307 /* Some reasonable defaults. */
1308 sym->symbol.the_bfd = abfd;
1309 sym->symbol.name = bufp->name.n_strx + stringtab;
1310 sym->symbol.value = bufp->symbol_value;
1311 sym->symbol.section = 0;
1312 sym->symbol.flags = 0;
1313
1314 switch (bufp->symbol_type)
1315 {
1316 case ST_ENTRY:
1317 sym->symbol.flags |= BSF_FUNCTION;
1318 sym->symbol.value &= ~0x3;
1319 break;
1320
1321 case ST_PRI_PROG:
1322 case ST_SEC_PROG:
1323 case ST_STUB:
1324 case ST_MILLICODE:
1325 case ST_CODE:
1326 sym->symbol.value &= ~0x3;
1327
1328 default:
1329 break;
1330 }
1331
1332 /* Handle scoping and section information. */
1333 switch (bufp->symbol_scope)
1334 {
1335 /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
1336 so the section associated with this symbol can't be known. */
1337 case SS_EXTERNAL:
1338 case SS_UNSAT:
1339 sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
1340 break;
1341
1342 case SS_UNIVERSAL:
1343 sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
1344 sym->symbol.section
1345 = som_section_from_subspace_index (abfd, bufp->symbol_info);
1346 sym->symbol.value -= sym->symbol.section->vma;
1347 break;
1348
1349#if 0
1350 /* SS_GLOBAL and SS_LOCAL are two names for the same thing.
1351 Sound dumb? It is. */
1352 case SS_GLOBAL:
1353#endif
1354 case SS_LOCAL:
1355 sym->symbol.flags |= BSF_LOCAL;
1356 sym->symbol.section
1357 = som_section_from_subspace_index (abfd, bufp->symbol_info);
1358 sym->symbol.value -= sym->symbol.section->vma;
1359 break;
1360 }
1361
1362 /* Mark symbols left around by the debugger. */
1363 if (strlen (sym->symbol.name) >= 3
1364 && sym->symbol.name[0] == 'L'
1365 && (sym->symbol.name[2] == '$' || sym->symbol.name[3] == '$'))
1366 sym->symbol.flags |= BSF_DEBUGGING;
1367
1368 /* Note increment at bottom of loop, since we skip some symbols
1369 we can not include it as part of the for statement. */
1370 sym++;
1371 }
1372
1373 /* Save our results and return success. */
1374 obj_som_symtab (abfd) = symbase;
1375 return (true);
d9ad93bc
KR
1376}
1377
9e16fcf1
SG
1378/* Canonicalize a SOM symbol table. Return the number of entries
1379 in the symbol table. */
d9ad93bc
KR
1380
1381static unsigned int
9e16fcf1 1382som_get_symtab (abfd, location)
d9ad93bc
KR
1383 bfd *abfd;
1384 asymbol **location;
1385{
9e16fcf1
SG
1386 int i;
1387 som_symbol_type *symbase;
1388
1389 if (!som_slurp_symbol_table (abfd))
1390 return 0;
1391
1392 i = bfd_get_symcount (abfd);
1393 symbase = obj_som_symtab (abfd);
1394
1395 for (; i > 0; i--, location++, symbase++)
1396 *location = &symbase->symbol;
1397
1398 /* Final null pointer. */
1399 *location = 0;
1400 return (bfd_get_symcount (abfd));
d9ad93bc
KR
1401}
1402
9e16fcf1
SG
1403/* Make a SOM symbol. There is nothing special to do here. */
1404
d9ad93bc 1405static asymbol *
9e16fcf1 1406som_make_empty_symbol (abfd)
d9ad93bc
KR
1407 bfd *abfd;
1408{
9e16fcf1
SG
1409 som_symbol_type *new =
1410 (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
1411 if (new == NULL)
1412 {
1413 bfd_error = no_memory;
1414 return 0;
1415 }
d9ad93bc
KR
1416 new->symbol.the_bfd = abfd;
1417
1418 return &new->symbol;
1419}
1420
9e16fcf1
SG
1421/* Print symbol information. */
1422
d9ad93bc 1423static void
9e16fcf1 1424som_print_symbol (ignore_abfd, afile, symbol, how)
d9ad93bc
KR
1425 bfd *ignore_abfd;
1426 PTR afile;
1427 asymbol *symbol;
1428 bfd_print_symbol_type how;
1429{
9e16fcf1
SG
1430 FILE *file = (FILE *) afile;
1431 switch (how)
1432 {
1433 case bfd_print_symbol_name:
1434 fprintf (file, "%s", symbol->name);
1435 break;
1436 case bfd_print_symbol_more:
1437 fprintf (file, "som ");
1438 fprintf_vma (file, symbol->value);
1439 fprintf (file, " %lx", (long) symbol->flags);
1440 break;
1441 case bfd_print_symbol_all:
1442 {
1443 CONST char *section_name;
1444 section_name = symbol->section ? symbol->section->name : "(*none*)";
1445 bfd_print_symbol_vandf ((PTR) file, symbol);
1446 fprintf (file, " %s\t%s", section_name, symbol->name);
1447 break;
1448 }
1449 }
1450}
1451
1452static unsigned int
1453som_get_reloc_upper_bound (abfd, asect)
1454 bfd *abfd;
1455 sec_ptr asect;
1456{
1457 fprintf (stderr, "som_get_reloc_upper_bound unimplemented\n");
d9ad93bc
KR
1458 fflush (stderr);
1459 abort ();
9e16fcf1 1460 return (0);
d9ad93bc
KR
1461}
1462
9e16fcf1
SG
1463static unsigned int
1464som_canonicalize_reloc (abfd, section, relptr, symbols)
1465 bfd *abfd;
1466 sec_ptr section;
1467 arelent **relptr;
1468 asymbol **symbols;
1469{
1470 fprintf (stderr, "som_canonicalize_reloc unimplemented\n");
1471 fflush (stderr);
1472 abort ();
1473}
1474
1475extern bfd_target som_vec;
1476
1477/* A hook to set up object file dependent section information. */
1478
d9ad93bc 1479static boolean
9e16fcf1 1480som_new_section_hook (abfd, newsect)
d9ad93bc
KR
1481 bfd *abfd;
1482 asection *newsect;
1483{
9e16fcf1
SG
1484 newsect->used_by_bfd = (struct som_section_data_struct *)
1485 bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
d9ad93bc
KR
1486 newsect->alignment_power = 3;
1487
9e16fcf1
SG
1488 /* Initialize the subspace_index field to -1 so that it does
1489 not match a subspace with an index of 0. */
1490 som_section_data (newsect)->subspace_index = -1;
1491
d9ad93bc
KR
1492 /* We allow more than three sections internally */
1493 return true;
1494}
1495
40249bfb
JL
1496/* Set backend info for sections which can not be described
1497 in the BFD data structures. */
1498
1499void
1500bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
1501 asection *section;
1502 char defined;
1503 char private;
1504 unsigned char sort_key;
1505 int spnum;
1506{
1507 struct space_dictionary_record *space_dict;
1508
1509 som_section_data (section)->is_space = 1;
1510 space_dict = &som_section_data (section)->space_dict;
1511 space_dict->is_defined = defined;
1512 space_dict->is_private = private;
1513 space_dict->sort_key = sort_key;
1514 space_dict->space_number = spnum;
1515}
1516
1517/* Set backend info for subsections which can not be described
1518 in the BFD data structures. */
1519
1520void
1521bfd_som_set_subsection_attributes (section, container, access,
1522 sort_key, quadrant)
1523 asection *section;
1524 asection *container;
1525 int access;
1526 unsigned char sort_key;
1527 int quadrant;
1528{
1529 struct subspace_dictionary_record *subspace_dict;
1530 som_section_data (section)->is_subspace = 1;
1531 subspace_dict = &som_section_data (section)->subspace_dict;
1532 subspace_dict->access_control_bits = access;
1533 subspace_dict->sort_key = sort_key;
1534 subspace_dict->quadrant = quadrant;
1535 som_section_data (section)->containing_space = container;
1536}
1537
1538/* Set the full SOM symbol type. SOM needs far more symbol information
1539 than any other object file format I'm aware of. It is mandatory
1540 to be able to know if a symbol is an entry point, millicode, data,
1541 code, absolute, storage request, or procedure label. If you get
1542 the symbol type wrong your program will not link. */
1543
1544void
1545bfd_som_set_symbol_type (symbol, type)
1546 asymbol *symbol;
1547 unsigned int type;
1548{
1549 (*som_symbol_data (symbol))->som_type = type;
1550}
1551
1552/* Attach 64bits of unwind information to a symbol (which hopefully
1553 is a function of some kind!). It would be better to keep this
1554 in the R_ENTRY relocation, but there is not enough space. */
1555
1556void
1557bfd_som_attach_unwind_info (symbol, unwind_desc)
1558 asymbol *symbol;
1559 char *unwind_desc;
1560{
1561 (*som_symbol_data (symbol))->unwind = unwind_desc;
1562}
1563
d9ad93bc 1564static boolean
9e16fcf1 1565som_set_section_contents (abfd, section, location, offset, count)
d9ad93bc
KR
1566 bfd *abfd;
1567 sec_ptr section;
1568 PTR location;
1569 file_ptr offset;
1570 bfd_size_type count;
1571{
9e16fcf1 1572 fprintf (stderr, "som_set_section_contents unimplimented\n");
d9ad93bc
KR
1573 fflush (stderr);
1574 abort ();
1575 return false;
1576}
1577
1578static boolean
9e16fcf1 1579som_set_arch_mach (abfd, arch, machine)
d9ad93bc
KR
1580 bfd *abfd;
1581 enum bfd_architecture arch;
1582 unsigned long machine;
1583{
9e16fcf1 1584 fprintf (stderr, "som_set_arch_mach unimplemented\n");
d9ad93bc 1585 fflush (stderr);
9e16fcf1 1586 /* Allow any architecture to be supported by the som backend */
d9ad93bc
KR
1587 return bfd_default_set_arch_mach (abfd, arch, machine);
1588}
1589
1590static boolean
9e16fcf1 1591som_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
d9ad93bc
KR
1592 functionname_ptr, line_ptr)
1593 bfd *abfd;
1594 asection *section;
1595 asymbol **symbols;
1596 bfd_vma offset;
1597 CONST char **filename_ptr;
1598 CONST char **functionname_ptr;
1599 unsigned int *line_ptr;
1600{
9e16fcf1 1601 fprintf (stderr, "som_find_nearest_line unimplemented\n");
d9ad93bc
KR
1602 fflush (stderr);
1603 abort ();
1604 return (false);
1605}
1606
1607static int
9e16fcf1 1608som_sizeof_headers (abfd, reloc)
d9ad93bc
KR
1609 bfd *abfd;
1610 boolean reloc;
1611{
9e16fcf1 1612 fprintf (stderr, "som_sizeof_headers unimplemented\n");
d9ad93bc
KR
1613 fflush (stderr);
1614 abort ();
1615 return (0);
1616}
1617
1618/* Return information about SOM symbol SYMBOL in RET. */
1619
1620static void
9e16fcf1 1621som_get_symbol_info (ignore_abfd, symbol, ret)
d9ad93bc
KR
1622 bfd *ignore_abfd; /* Ignored. */
1623 asymbol *symbol;
1624 symbol_info *ret;
1625{
1626 bfd_symbol_info (symbol, ret);
1627}
1628
1629/* End of miscellaneous support functions. */
1630
9e16fcf1
SG
1631#define som_bfd_debug_info_start bfd_void
1632#define som_bfd_debug_info_end bfd_void
1633#define som_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
d9ad93bc 1634
9e16fcf1
SG
1635#define som_openr_next_archived_file bfd_generic_openr_next_archived_file
1636#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
1637#define som_slurp_armap bfd_false
1638#define som_slurp_extended_name_table _bfd_slurp_extended_name_table
1639#define som_truncate_arname (void (*)())bfd_nullvoidptr
1640#define som_write_armap 0
d9ad93bc 1641
9e16fcf1
SG
1642#define som_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
1643#define som_close_and_cleanup bfd_generic_close_and_cleanup
1644#define som_get_section_contents bfd_generic_get_section_contents
d9ad93bc 1645
9e16fcf1 1646#define som_bfd_get_relocated_section_contents \
d9ad93bc 1647 bfd_generic_get_relocated_section_contents
9e16fcf1
SG
1648#define som_bfd_relax_section bfd_generic_relax_section
1649#define som_bfd_seclet_link bfd_generic_seclet_link
1650#define som_bfd_reloc_type_lookup \
d9ad93bc 1651 ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
9e16fcf1 1652#define som_bfd_make_debug_symbol \
d9ad93bc
KR
1653 ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
1654
1655/* Core file support is in the hpux-core backend. */
9e16fcf1
SG
1656#define som_core_file_failing_command _bfd_dummy_core_file_failing_command
1657#define som_core_file_failing_signal _bfd_dummy_core_file_failing_signal
1658#define som_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
d9ad93bc 1659
9e16fcf1 1660bfd_target som_vec =
d9ad93bc 1661{
9e16fcf1
SG
1662 "som", /* name */
1663 bfd_target_som_flavour,
d9ad93bc
KR
1664 true, /* target byte order */
1665 true, /* target headers byte order */
1666 (HAS_RELOC | EXEC_P | /* object flags */
1667 HAS_LINENO | HAS_DEBUG |
40249bfb 1668 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
d9ad93bc 1669 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
9e16fcf1 1670 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
d9ad93bc
KR
1671
1672/* leading_symbol_char: is the first char of a user symbol
9e16fcf1 1673 predictable, and if so what is it */
d9ad93bc
KR
1674 0,
1675 ' ', /* ar_pad_char */
1676 16, /* ar_max_namelen */
1677 3, /* minimum alignment */
9e16fcf1
SG
1678 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1679 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1680 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
1681 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1682 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1683 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
d9ad93bc 1684 {_bfd_dummy_target,
9e16fcf1 1685 som_object_p, /* bfd_check_format */
d9ad93bc
KR
1686 bfd_generic_archive_p,
1687 _bfd_dummy_target
1688 },
1689 {
1690 bfd_false,
9e16fcf1 1691 som_mkobject,
d9ad93bc
KR
1692 _bfd_generic_mkarchive,
1693 bfd_false
1694 },
1695 {
1696 bfd_false,
9e16fcf1 1697 som_write_object_contents,
d9ad93bc
KR
1698 _bfd_write_archive_contents,
1699 bfd_false,
1700 },
9e16fcf1
SG
1701#undef som
1702 JUMP_TABLE (som),
d9ad93bc
KR
1703 (PTR) 0
1704};
1705
1706#endif /* HOST_HPPAHPUX || HOST_HPPABSD */
This page took 0.098402 seconds and 4 git commands to generate.