* gas/hppa/reloc/reloc.exp: Minor fixes so that SOM & ELF can
[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
9d0dea6f
JL
70/* Size (in chars) of the temporary buffers used during fixup and string
71 table writes. */
72
73#define SOM_TMP_BUFSIZE 8192
74
75
4fdb66cd
JL
76/* SOM allows any one of the four previous relocations to be reused
77 with a "R_PREV_FIXUP" relocation entry. Since R_PREV_FIXUP
78 relocations are always a single byte, using a R_PREV_FIXUP instead
79 of some multi-byte relocation makes object files smaller.
80
81 Note one side effect of using a R_PREV_FIXUP is the relocation that
82 is being repeated moves to the front of the queue. */
83struct reloc_queue
84 {
85 unsigned char *reloc;
86 unsigned int size;
87 } reloc_queue[4];
88
89/* This fully describes the symbol types which may be attached to
90 an EXPORT or IMPORT directive. Only SOM uses this formation
91 (ELF has no need for it). */
92typedef enum
93{
94 SYMBOL_TYPE_UNKNOWN,
95 SYMBOL_TYPE_ABSOLUTE,
96 SYMBOL_TYPE_CODE,
97 SYMBOL_TYPE_DATA,
98 SYMBOL_TYPE_ENTRY,
99 SYMBOL_TYPE_MILLICODE,
100 SYMBOL_TYPE_PLABEL,
101 SYMBOL_TYPE_PRI_PROG,
102 SYMBOL_TYPE_SEC_PROG,
103} pa_symbol_type;
104
9e16fcf1
SG
105/* Forward declarations */
106
107static boolean som_mkobject PARAMS ((bfd *));
108static bfd_target * som_object_setup PARAMS ((bfd *,
109 struct header *,
110 struct som_exec_auxhdr *));
111static asection * make_unique_section PARAMS ((bfd *, CONST char *, int));
112static boolean setup_sections PARAMS ((bfd *, struct header *));
113static bfd_target * som_object_p PARAMS ((bfd *));
114static boolean som_write_object_contents PARAMS ((bfd *));
115static boolean som_slurp_string_table PARAMS ((bfd *));
116static unsigned int som_slurp_symbol_table PARAMS ((bfd *));
117static unsigned int som_get_symtab_upper_bound PARAMS ((bfd *));
118static unsigned int som_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
119 arelent **, asymbol **));
120static unsigned int som_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
121static unsigned int som_get_symtab PARAMS ((bfd *, asymbol **));
122static asymbol * som_make_empty_symbol PARAMS ((bfd *));
123static void som_print_symbol PARAMS ((bfd *, PTR,
124 asymbol *, bfd_print_symbol_type));
125static boolean som_new_section_hook PARAMS ((bfd *, asection *));
126static boolean som_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
127 file_ptr, bfd_size_type));
128static boolean som_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
129 unsigned long));
130static boolean som_find_nearest_line PARAMS ((bfd *, asection *,
131 asymbol **, bfd_vma,
132 CONST char **,
133 CONST char **,
134 unsigned int *));
135static void som_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
136static asection * som_section_from_subspace_index PARAMS ((bfd *,
137 unsigned int));
138static int log2 PARAMS ((unsigned int));
fcb0c846
JL
139static bfd_reloc_status_type hppa_som_reloc PARAMS ((bfd *, arelent *,
140 asymbol *, PTR,
141 asection *, bfd *));
d125665c
JL
142static void som_initialize_reloc_queue PARAMS ((struct reloc_queue *));
143static void som_reloc_queue_insert PARAMS ((unsigned char *, unsigned int,
144 struct reloc_queue *));
145static void som_reloc_queue_fix PARAMS ((struct reloc_queue *, unsigned int));
146static int som_reloc_queue_find PARAMS ((unsigned char *, unsigned int,
147 struct reloc_queue *));
54bbfd37
JL
148static unsigned char * try_prev_fixup PARAMS ((bfd *, int *, unsigned char *,
149 unsigned int,
150 struct reloc_queue *));
151
152static unsigned char * som_reloc_skip PARAMS ((bfd *, unsigned int,
153 unsigned char *, unsigned int *,
154 struct reloc_queue *));
155static unsigned char * som_reloc_addend PARAMS ((bfd *, int, unsigned char *,
156 unsigned int *,
157 struct reloc_queue *));
7057b78f
JL
158static unsigned char * som_reloc_call PARAMS ((bfd *, unsigned char *,
159 unsigned int *,
160 arelent *, int,
161 struct reloc_queue *));
5532fc5a
JL
162static unsigned long som_count_spaces PARAMS ((bfd *));
163static unsigned long som_count_subspaces PARAMS ((bfd *));
164static int compare_syms PARAMS ((asymbol **, asymbol **));
165static unsigned long som_compute_checksum PARAMS ((bfd *));
0ffa24b9 166static boolean som_prep_headers PARAMS ((bfd *));
2212ff92 167static int som_sizeof_headers PARAMS ((bfd *, boolean));
efc0df7c 168static boolean som_write_headers PARAMS ((bfd *));
713de7ec 169static boolean som_build_and_write_symbol_table PARAMS ((bfd *));
aff97790 170static void som_prep_for_fixups PARAMS ((bfd *, asymbol **, unsigned long));
9d0dea6f 171static boolean som_write_fixups PARAMS ((bfd *, unsigned long, unsigned int *));
0b35f7ec
JL
172static boolean som_write_space_strings PARAMS ((bfd *, unsigned long,
173 unsigned int *));
174static boolean som_write_symbol_strings PARAMS ((bfd *, unsigned long,
175 asymbol **, unsigned int,
176 unsigned *));
6eb64408 177static boolean som_begin_writing PARAMS ((bfd *));
91c0bcbb
JL
178static const reloc_howto_type * som_bfd_reloc_type_lookup
179 PARAMS ((bfd_arch_info_type *, bfd_reloc_code_real_type));
2212ff92 180
fcb0c846
JL
181static reloc_howto_type som_hppa_howto_table[] =
182{
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_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
188 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
189 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
190 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
191 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
192 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
193 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
194 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
195 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
196 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
197 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
198 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
199 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
200 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
201 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
202 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
203 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
204 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
205 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
206 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
207 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
208 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
209 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
210 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
211 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
212 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
213 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
214 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
215 {R_ZEROES, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ZEROES"},
216 {R_ZEROES, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ZEROES"},
217 {R_UNINIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_UNINIT"},
218 {R_UNINIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_UNINIT"},
219 {R_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RELOCATION"},
220 {R_DATA_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_ONE_SYMBOL"},
221 {R_DATA_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_ONE_SYMBOL"},
222 {R_DATA_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_PLABEL"},
223 {R_DATA_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_PLABEL"},
224 {R_SPACE_REF, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SPACE_REF"},
225 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
226 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
227 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
228 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
229 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
230 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
231 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
232 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
233 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
234 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
235 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
236 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
237 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
238 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
239 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
240 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
241 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
242 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
243 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
244 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
245 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
246 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
247 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
248 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
249 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
250 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
251 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
252 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
253 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
254 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
255 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
256 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
257 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
258 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
259 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
260 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
261 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
262 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
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_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
271 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
272 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
273 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
274 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
275 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
276 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
277 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
278 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
279 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
280 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
281 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
282 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
283 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
284 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
285 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
286 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
287 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
288 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
289 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
290 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
291 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
292 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
293 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
294 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
295 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
296 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
297 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
298 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
299 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
300 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
301 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
302 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
303 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
304 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
305 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
306 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
307 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
308 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
309 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
310 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
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_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
319 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
320 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
321 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
322 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
323 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
324 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
325 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
326 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
327 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
328 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
329 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
330 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
331 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
332 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
333 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
334 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
335 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
336 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
337 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
338 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
339 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
340 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
341 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
342 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
343 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
344 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
345 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
346 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
347 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
348 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
349 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
350 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
351 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
352 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
353 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
354 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
355 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
356 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
357 {R_MILLI_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_MILLI_REL"},
358 {R_MILLI_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_MILLI_REL"},
359 {R_CODE_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_PLABEL"},
360 {R_CODE_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_PLABEL"},
361 {R_BREAKPOINT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BREAKPOINT"},
362 {R_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ENTRY"},
363 {R_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ENTRY"},
364 {R_ALT_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ALT_ENTRY"},
365 {R_EXIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_EXIT"},
366 {R_BEGIN_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BEGIN_TRY"},
367 {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
368 {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
369 {R_BEGIN_BRTAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BEGIN_BRTAB"},
370 {R_END_BRTAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_BRTAB"},
371 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
372 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
373 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
374 {R_DATA_EXPR, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_EXPR"},
375 {R_CODE_EXPR, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_EXPR"},
376 {R_FSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_FSEL"},
377 {R_LSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LSEL"},
378 {R_RSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RSEL"},
379 {R_N_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N_MODE"},
380 {R_S_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_S_MODE"},
381 {R_D_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_D_MODE"},
382 {R_R_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_R_MODE"},
383 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
384 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
385 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
386 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
387 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
388 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
389 {R_TRANSLATED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_TRANSLATED"},
390 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
391 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
392 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
393 {R_COMP1, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP1"},
394 {R_COMP2, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP2"},
395 {R_COMP3, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP3"},
396 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
397 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
398 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
399 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
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 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
414 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
415 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
416 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
417 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
418 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
419 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
420 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
421 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
422 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
423 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
424 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
425 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
426 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
427 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
428 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
429 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
430 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
431 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
432 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
433 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
434 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
435 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
436 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
437 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
438 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
439 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
440 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"}};
441
d125665c
JL
442
443/* Initialize the SOM relocation queue. By definition the queue holds
444 the last four multibyte fixups. */
445
446static void
447som_initialize_reloc_queue (queue)
448 struct reloc_queue *queue;
449{
450 queue[0].reloc = NULL;
451 queue[0].size = 0;
452 queue[1].reloc = NULL;
453 queue[1].size = 0;
454 queue[2].reloc = NULL;
455 queue[2].size = 0;
456 queue[3].reloc = NULL;
457 queue[3].size = 0;
458}
459
460/* Insert a new relocation into the relocation queue. */
461
462static void
463som_reloc_queue_insert (p, size, queue)
464 unsigned char *p;
465 unsigned int size;
466 struct reloc_queue *queue;
467{
468 queue[3].reloc = queue[2].reloc;
469 queue[3].size = queue[2].size;
470 queue[2].reloc = queue[1].reloc;
471 queue[2].size = queue[1].size;
472 queue[1].reloc = queue[0].reloc;
473 queue[1].size = queue[0].size;
474 queue[0].reloc = p;
475 queue[0].size = size;
476}
477
478/* When an entry in the relocation queue is reused, the entry moves
479 to the front of the queue. */
480
481static void
482som_reloc_queue_fix (queue, index)
483 struct reloc_queue *queue;
484 unsigned int index;
485{
486 if (index == 0)
487 return;
488
489 if (index == 1)
490 {
491 unsigned char *tmp1 = queue[0].reloc;
492 unsigned int tmp2 = queue[0].size;
493 queue[0].reloc = queue[1].reloc;
494 queue[0].size = queue[1].size;
495 queue[1].reloc = tmp1;
496 queue[1].size = tmp2;
497 return;
498 }
499
500 if (index == 2)
501 {
502 unsigned char *tmp1 = queue[0].reloc;
503 unsigned int tmp2 = queue[0].size;
504 queue[0].reloc = queue[2].reloc;
505 queue[0].size = queue[2].size;
506 queue[2].reloc = queue[1].reloc;
507 queue[2].size = queue[1].size;
508 queue[1].reloc = tmp1;
509 queue[1].size = tmp2;
510 return;
511 }
512
513 if (index == 3)
514 {
515 unsigned char *tmp1 = queue[0].reloc;
516 unsigned int tmp2 = queue[0].size;
517 queue[0].reloc = queue[3].reloc;
518 queue[0].size = queue[3].size;
519 queue[3].reloc = queue[2].reloc;
520 queue[3].size = queue[2].size;
521 queue[2].reloc = queue[1].reloc;
522 queue[2].size = queue[1].size;
523 queue[1].reloc = tmp1;
524 queue[1].size = tmp2;
525 return;
526 }
527 abort();
528}
529
530/* Search for a particular relocation in the relocation queue. */
531
532static int
533som_reloc_queue_find (p, size, queue)
534 unsigned char *p;
535 unsigned int size;
536 struct reloc_queue *queue;
537{
538 if (!bcmp (p, queue[0].reloc, size)
539 && size == queue[0].size)
540 return 0;
541 if (!bcmp (p, queue[1].reloc, size)
542 && size == queue[1].size)
543 return 1;
544 if (!bcmp (p, queue[2].reloc, size)
545 && size == queue[2].size)
546 return 2;
547 if (!bcmp (p, queue[3].reloc, size)
548 && size == queue[3].size)
549 return 3;
550 return -1;
551}
54bbfd37
JL
552
553static unsigned char *
554try_prev_fixup (abfd, subspace_reloc_sizep, p, size, queue)
555 bfd *abfd;
556 int *subspace_reloc_sizep;
557 unsigned char *p;
558 unsigned int size;
559 struct reloc_queue *queue;
560{
561 int queue_index = som_reloc_queue_find (p, size, queue);
562
563 if (queue_index != -1)
564 {
565 /* Found this in a previous fixup. Undo the fixup we
566 just built and use R_PREV_FIXUP instead. We saved
567 a total of size - 1 bytes in the fixup stream. */
568 bfd_put_8 (abfd, R_PREV_FIXUP + queue_index, p);
569 p += 1;
570 *subspace_reloc_sizep += 1;
571 som_reloc_queue_fix (queue, queue_index);
572 }
573 else
574 {
575 som_reloc_queue_insert (p, size, queue);
576 *subspace_reloc_sizep += size;
577 p += size;
578 }
579 return p;
580}
581
582/* Emit the proper R_NO_RELOCATION fixups to map the next SKIP
583 bytes without any relocation. Update the size of the subspace
584 relocation stream via SUBSPACE_RELOC_SIZE_P; also return the
585 current pointer into the relocation stream. */
586
587static unsigned char *
588som_reloc_skip (abfd, skip, p, subspace_reloc_sizep, queue)
589 bfd *abfd;
590 unsigned int skip;
591 unsigned char *p;
592 unsigned int *subspace_reloc_sizep;
593 struct reloc_queue *queue;
594{
595 /* Use a 4 byte R_NO_RELOCATION entry with a maximal value
596 then R_PREV_FIXUPs to get the difference down to a
597 reasonable size. */
598 if (skip >= 0x1000000)
599 {
600 skip -= 0x1000000;
601 bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
602 bfd_put_8 (abfd, 0xff, p + 1);
603 bfd_put_16 (abfd, 0xffff, p + 2);
604 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
605 while (skip >= 0x1000000)
606 {
607 skip -= 0x1000000;
608 bfd_put_8 (abfd, R_PREV_FIXUP, p);
609 p++;
610 *subspace_reloc_sizep += 1;
611 /* No need to adjust queue here since we are repeating the
612 most recent fixup. */
613 }
614 }
615
616 /* The difference must be less than 0x1000000. Use one
617 more R_NO_RELOCATION entry to get to the right difference. */
618 if ((skip & 3) == 0 && skip <= 0xc0000 && skip > 0)
619 {
620 /* Difference can be handled in a simple single-byte
621 R_NO_RELOCATION entry. */
622 if (skip <= 0x60)
623 {
624 bfd_put_8 (abfd, R_NO_RELOCATION + (skip >> 2) - 1, p);
625 *subspace_reloc_sizep += 1;
626 p++;
627 }
628 /* Handle it with a two byte R_NO_RELOCATION entry. */
629 else if (skip <= 0x1000)
630 {
631 bfd_put_8 (abfd, R_NO_RELOCATION + 24 + (((skip >> 2) - 1) >> 8), p);
632 bfd_put_8 (abfd, (skip >> 2) - 1, p + 1);
633 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
634 }
635 /* Handle it with a three byte R_NO_RELOCATION entry. */
636 else
637 {
638 bfd_put_8 (abfd, R_NO_RELOCATION + 28 + (((skip >> 2) - 1) >> 16), p);
639 bfd_put_16 (abfd, (skip >> 2) - 1, p + 1);
640 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
641 }
642 }
643 /* Ugh. Punt and use a 4 byte entry. */
644 else if (skip > 0)
645 {
646 bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
647 bfd_put_8 (abfd, skip >> 16, p + 1);
648 bfd_put_16 (abfd, skip, p + 2);
649 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
650 }
651 return p;
652}
653
654/* Emit the proper R_DATA_OVERRIDE fixups to handle a nonzero addend
655 from a BFD relocation. Update the size of the subspace relocation
656 stream via SUBSPACE_RELOC_SIZE_P; also return the current pointer
657 into the relocation stream. */
658
659static unsigned char *
660som_reloc_addend (abfd, addend, p, subspace_reloc_sizep, queue)
661 bfd *abfd;
662 int addend;
663 unsigned char *p;
664 unsigned int *subspace_reloc_sizep;
665 struct reloc_queue *queue;
666{
667 if ((unsigned)(addend) + 0x80 < 0x100)
668 {
669 bfd_put_8 (abfd, R_DATA_OVERRIDE + 1, p);
670 bfd_put_8 (abfd, addend, p + 1);
671 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
672 }
673 else if ((unsigned) (addend) + 0x8000 < 0x10000)
674 {
675 bfd_put_8 (abfd, R_DATA_OVERRIDE + 2, p);
676 bfd_put_16 (abfd, addend, p + 1);
677 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
678 }
679 else if ((unsigned) (addend) + 0x800000 < 0x1000000)
680 {
681 bfd_put_8 (abfd, R_DATA_OVERRIDE + 3, p);
682 bfd_put_8 (abfd, addend >> 16, p + 1);
683 bfd_put_16 (abfd, addend, p + 2);
684 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
685 }
686 else
687 {
688 bfd_put_8 (abfd, R_DATA_OVERRIDE + 4, p);
689 bfd_put_32 (abfd, addend, p + 1);
690 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
691 }
692 return p;
693}
694
7057b78f
JL
695/* Handle a single function call relocation. */
696
697static unsigned char *
698som_reloc_call (abfd, p, subspace_reloc_sizep, bfd_reloc, sym_num, queue)
699 bfd *abfd;
700 unsigned char *p;
701 unsigned int *subspace_reloc_sizep;
702 arelent *bfd_reloc;
703 int sym_num;
704 struct reloc_queue *queue;
705{
706 int arg_bits = HPPA_R_ARG_RELOC (bfd_reloc->addend);
707 int rtn_bits = arg_bits & 0x3;
708 int type, done = 0;
709
710 /* You'll never believe all this is necessary to handle relocations
711 for function calls. Having to compute and pack the argument
712 relocation bits is the real nightmare.
713
714 If you're interested in how this works, just forget it. You really
715 do not want to know about this braindamage. */
716
717 /* First see if this can be done with a "simple" relocation. Simple
718 relocations have a symbol number < 0x100 and have simple encodings
719 of argument relocations. */
720
721 if (sym_num < 0x100)
722 {
723 switch (arg_bits)
724 {
725 case 0:
726 case 1:
727 type = 0;
728 break;
729 case 1 << 8:
730 case 1 << 8 | 1:
731 type = 1;
732 break;
733 case 1 << 8 | 1 << 6:
734 case 1 << 8 | 1 << 6 | 1:
735 type = 2;
736 break;
737 case 1 << 8 | 1 << 6 | 1 << 4:
738 case 1 << 8 | 1 << 6 | 1 << 4 | 1:
739 type = 3;
740 break;
741 case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2:
742 case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1:
743 type = 4;
744 break;
745 default:
746 /* Not one of the easy encodings. This will have to be
747 handled by the more complex code below. */
748 type = -1;
749 break;
750 }
751 if (type != -1)
752 {
753 /* Account for the return value too. */
754 if (rtn_bits)
755 type += 5;
756
757 /* Emit a 2 byte relocation. Then see if it can be handled
758 with a relocation which is already in the relocation queue. */
759 bfd_put_8 (abfd, bfd_reloc->howto->type + type, p);
760 bfd_put_8 (abfd, sym_num, p + 1);
761 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
762 done = 1;
763 }
764 }
765
766 /* If this could not be handled with a simple relocation, then do a hard
767 one. Hard relocations occur if the symbol number was too high or if
768 the encoding of argument relocation bits is too complex. */
769 if (! done)
770 {
771 /* Don't ask about these magic sequences. I took them straight
772 from gas-1.36 which took them from the a.out man page. */
773 type = rtn_bits;
774 if ((arg_bits >> 6 & 0xf) == 0xe)
775 type += 9 * 40;
776 else
777 type += (3 * (arg_bits >> 8 & 3) + (arg_bits >> 6 & 3)) * 40;
778 if ((arg_bits >> 2 & 0xf) == 0xe)
779 type += 9 * 4;
780 else
781 type += (3 * (arg_bits >> 4 & 3) + (arg_bits >> 2 & 3)) * 4;
782
783 /* Output the first two bytes of the relocation. These describe
784 the length of the relocation and encoding style. */
785 bfd_put_8 (abfd, bfd_reloc->howto->type + 10
786 + 2 * (sym_num >= 0x100) + (type >= 0x100),
787 p);
788 bfd_put_8 (abfd, type, p + 1);
789
790 /* Now output the symbol index and see if this bizarre relocation
791 just happened to be in the relocation queue. */
792 if (sym_num < 0x100)
793 {
794 bfd_put_8 (abfd, sym_num, p + 2);
795 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
796 }
797 else
798 {
799 bfd_put_8 (abfd, sym_num >> 16, p + 2);
800 bfd_put_16 (abfd, sym_num, p + 3);
801 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
802 }
803 }
804 return p;
805}
806
807
9e16fcf1 808/* Return the logarithm of X, base 2, considering X unsigned.
40249bfb
JL
809 Abort if X is not a power of two -- this should never happen (FIXME:
810 It will happen on corrupt executables. GDB should give an error, not
811 a coredump, in that case). */
9e16fcf1
SG
812
813static int
814log2 (x)
815 unsigned int x;
816{
817 int log = 0;
818
819 /* Test for 0 or a power of 2. */
820 if (x == 0 || x != (x & -x))
821 abort();
822
823 while ((x >>= 1) != 0)
824 log++;
825 return log;
826}
827
fcb0c846
JL
828static bfd_reloc_status_type
829hppa_som_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd)
830 bfd *abfd;
831 arelent *reloc_entry;
832 asymbol *symbol_in;
833 PTR data;
834 asection *input_section;
835 bfd *output_bfd;
836{
837 if (output_bfd)
838 {
839 reloc_entry->address += input_section->output_offset;
840 return bfd_reloc_ok;
841 }
842 return bfd_reloc_ok;
843}
32619c58
JL
844
845/* Given a generic HPPA relocation type, the instruction format,
846 and a field selector, return an appropriate SOM reloation.
847
848 FIXME. Need to handle %RR, %LR and the like as field selectors.
849 These will need to generate multiple SOM relocations. */
850
851int **
852hppa_som_gen_reloc_type (abfd, base_type, format, field)
853 bfd *abfd;
854 int base_type;
855 int format;
856 int field;
857{
858 int *final_type, **final_types;
859
860 final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 2);
861 final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
862
863
864 final_types[0] = final_type;
865 final_types[1] = NULL;
866
867 /* Default to the basic relocation passed in. */
868 *final_type = base_type;
869
870 switch (base_type)
871 {
872 case R_HPPA:
873 /* PLABELs get their own relocation type. */
874 if (field == e_psel
875 || field == e_lpsel
876 || field == e_rpsel)
877 {
878 /* A PLABEL relocation that has a size of 32 bits must
879 be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */
880 if (format == 32)
881 *final_type = R_DATA_PLABEL;
882 else
883 *final_type = R_CODE_PLABEL;
884 }
885 /* A relocatoin in the data space is always a full 32bits. */
886 else if (format == 32)
887 *final_type = R_DATA_ONE_SYMBOL;
888
889 break;
890
891 case R_HPPA_GOTOFF:
892 /* More PLABEL special cases. */
893 if (field == e_psel
894 || field == e_lpsel
895 || field == e_rpsel)
896 *final_type = R_DATA_PLABEL;
897 break;
898
899 case R_HPPA_NONE:
900 case R_HPPA_ABS_CALL:
901 case R_HPPA_PCREL_CALL:
902 case R_HPPA_COMPLEX:
903 case R_HPPA_COMPLEX_PCREL_CALL:
904 case R_HPPA_COMPLEX_ABS_CALL:
905 /* Right now we can default all these. */
906 break;
907 }
908 return final_types;
909}
910
911/* Return the address of the correct entry in the PA SOM relocation
912 howto table. */
913
91c0bcbb 914static const reloc_howto_type *
32619c58
JL
915som_bfd_reloc_type_lookup (arch, code)
916 bfd_arch_info_type *arch;
917 bfd_reloc_code_real_type code;
918{
919 if ((int) code < (int) R_NO_RELOCATION + 255)
920 {
921 BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code);
922 return &som_hppa_howto_table[(int) code];
923 }
924
925 return (reloc_howto_type *) 0;
926}
927
9e16fcf1
SG
928/* Perform some initialization for an object. Save results of this
929 initialization in the BFD. */
d9ad93bc
KR
930
931static bfd_target *
9e16fcf1 932som_object_setup (abfd, file_hdrp, aux_hdrp)
d9ad93bc
KR
933 bfd *abfd;
934 struct header *file_hdrp;
935 struct som_exec_auxhdr *aux_hdrp;
936{
d9ad93bc
KR
937 asection *text, *data, *bss;
938
9e16fcf1
SG
939 /* som_mkobject will set bfd_error if som_mkobject fails. */
940 if (som_mkobject (abfd) != true)
941 return 0;
d9ad93bc 942
9e16fcf1
SG
943 /* Make the standard .text, .data, and .bss sections so that tools
944 which assume those names work (size for example). They will have
945 no contents, but the sizes and such will reflect those of the
946 $CODE$, $DATA$, and $BSS$ subspaces respectively.
d9ad93bc 947
9e16fcf1 948 FIXME: Should check return status from bfd_make_section calls below. */
d9ad93bc
KR
949
950 text = bfd_make_section (abfd, ".text");
951 data = bfd_make_section (abfd, ".data");
952 bss = bfd_make_section (abfd, ".bss");
953
954 text->_raw_size = aux_hdrp->exec_tsize;
955 data->_raw_size = aux_hdrp->exec_dsize;
956 bss->_raw_size = aux_hdrp->exec_bsize;
957
9e16fcf1 958 text->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_CODE);
d9ad93bc
KR
959 data->flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS);
960 bss->flags = (SEC_ALLOC | SEC_IS_COMMON);
961
962 /* The virtual memory addresses of the sections */
963 text->vma = aux_hdrp->exec_tmem;
964 data->vma = aux_hdrp->exec_dmem;
965 bss->vma = aux_hdrp->exec_bfill;
966
967 /* The file offsets of the sections */
968 text->filepos = aux_hdrp->exec_tfile;
969 data->filepos = aux_hdrp->exec_dfile;
970
971 /* The file offsets of the relocation info */
972 text->rel_filepos = 0;
973 data->rel_filepos = 0;
974
9e16fcf1
SG
975 /* Set BFD flags based on what information is available in the SOM. */
976 abfd->flags = NO_FLAGS;
977 if (! file_hdrp->entry_offset)
978 abfd->flags |= HAS_RELOC;
979 else
980 abfd->flags |= EXEC_P;
981 if (file_hdrp->symbol_total)
982 abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
983
984 bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
985 bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
d9ad93bc 986 bfd_get_symcount (abfd) = file_hdrp->symbol_total;
9e16fcf1
SG
987
988 /* Initialize the saved symbol table and string table to NULL.
989 Save important offsets and sizes from the SOM header into
990 the BFD. */
991 obj_som_stringtab (abfd) = (char *) NULL;
992 obj_som_symtab (abfd) = (som_symbol_type *) NULL;
993 obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
994 obj_som_sym_filepos (abfd) = file_hdrp->symbol_location;
995 obj_som_str_filepos (abfd) = file_hdrp->symbol_strings_location;
996 obj_som_reloc_filepos (abfd) = file_hdrp->fixup_request_location;
d9ad93bc
KR
997
998 return abfd->xvec;
999}
1000
1001/* Create a new BFD section for NAME. If NAME already exists, then create a
1002 new unique name, with NAME as the prefix. This exists because SOM .o files
9e16fcf1 1003 may have more than one $CODE$ subspace. */
d9ad93bc
KR
1004
1005static asection *
1006make_unique_section (abfd, name, num)
1007 bfd *abfd;
1008 CONST char *name;
1009 int num;
1010{
1011 asection *sect;
1012 char *newname;
1013 char altname[100];
1014
1015 sect = bfd_make_section (abfd, name);
1016 while (!sect)
1017 {
1018 sprintf (altname, "%s-%d", name, num++);
1019 sect = bfd_make_section (abfd, altname);
1020 }
1021
1022 newname = bfd_alloc (abfd, strlen (sect->name) + 1);
1023 strcpy (newname, sect->name);
1024
1025 sect->name = newname;
1026 return sect;
1027}
1028
1029/* Convert all of the space and subspace info into BFD sections. Each space
1030 contains a number of subspaces, which in turn describe the mapping between
1031 regions of the exec file, and the address space that the program runs in.
1032 BFD sections which correspond to spaces will overlap the sections for the
1033 associated subspaces. */
1034
9e16fcf1 1035static boolean
d9ad93bc
KR
1036setup_sections (abfd, file_hdr)
1037 bfd *abfd;
1038 struct header *file_hdr;
1039{
1040 char *space_strings;
1041 int space_index;
9e16fcf1 1042 unsigned int total_subspaces = 0;
d9ad93bc
KR
1043
1044 /* First, read in space names */
1045
1046 space_strings = alloca (file_hdr->space_strings_size);
1047 if (!space_strings)
9e16fcf1 1048 return false;
d9ad93bc
KR
1049
1050 if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
9e16fcf1 1051 return false;
d9ad93bc
KR
1052 if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd)
1053 != file_hdr->space_strings_size)
9e16fcf1 1054 return false;
d9ad93bc
KR
1055
1056 /* Loop over all of the space dictionaries, building up sections */
d9ad93bc
KR
1057 for (space_index = 0; space_index < file_hdr->space_total; space_index++)
1058 {
1059 struct space_dictionary_record space;
9e16fcf1
SG
1060 struct subspace_dictionary_record subspace, save_subspace;
1061 int subspace_index;
d9ad93bc
KR
1062 asection *space_asect;
1063
1064 /* Read the space dictionary element */
1065 if (bfd_seek (abfd, file_hdr->space_location
1066 + space_index * sizeof space, SEEK_SET) < 0)
9e16fcf1 1067 return false;
d9ad93bc 1068 if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space)
9e16fcf1 1069 return false;
d9ad93bc
KR
1070
1071 /* Setup the space name string */
1072 space.name.n_name = space.name.n_strx + space_strings;
1073
1074 /* Make a section out of it */
1075 space_asect = make_unique_section (abfd, space.name.n_name, space_index);
1076 if (!space_asect)
9e16fcf1 1077 return false;
d9ad93bc
KR
1078
1079 /* Now, read in the first subspace for this space */
1080 if (bfd_seek (abfd, file_hdr->subspace_location
1081 + space.subspace_index * sizeof subspace,
1082 SEEK_SET) < 0)
9e16fcf1 1083 return false;
d9ad93bc 1084 if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace)
9e16fcf1 1085 return false;
d9ad93bc
KR
1086 /* Seek back to the start of the subspaces for loop below */
1087 if (bfd_seek (abfd, file_hdr->subspace_location
1088 + space.subspace_index * sizeof subspace,
1089 SEEK_SET) < 0)
9e16fcf1 1090 return false;
d9ad93bc
KR
1091
1092 /* Setup the start address and file loc from the first subspace record */
1093 space_asect->vma = subspace.subspace_start;
1094 space_asect->filepos = subspace.file_loc_init_value;
9e16fcf1
SG
1095 space_asect->alignment_power = log2 (subspace.alignment);
1096
1097 /* Initialize save_subspace so we can reliably determine if this
1098 loop placed any useful values into it. */
1099 bzero (&save_subspace, sizeof (struct subspace_dictionary_record));
d9ad93bc
KR
1100
1101 /* Loop over the rest of the subspaces, building up more sections */
1102 for (subspace_index = 0; subspace_index < space.subspace_quantity;
1103 subspace_index++)
1104 {
1105 asection *subspace_asect;
1106
1107 /* Read in the next subspace */
1108 if (bfd_read (&subspace, 1, sizeof subspace, abfd)
1109 != sizeof subspace)
9e16fcf1 1110 return false;
d9ad93bc
KR
1111
1112 /* Setup the subspace name string */
1113 subspace.name.n_name = subspace.name.n_strx + space_strings;
1114
1115 /* Make a section out of this subspace */
1116 subspace_asect = make_unique_section (abfd, subspace.name.n_name,
1117 space.subspace_index + subspace_index);
1118
1119 if (!subspace_asect)
9e16fcf1
SG
1120 return false;
1121
1122 /* Keep an easy mapping between subspaces and sections. */
1123 som_section_data (subspace_asect)->subspace_index
1124 = total_subspaces++;
1125
1126 /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
1127 by the access_control_bits in the subspace header. */
1128 switch (subspace.access_control_bits >> 4)
1129 {
1130 /* Readonly data. */
1131 case 0x0:
1132 subspace_asect->flags |= SEC_DATA | SEC_READONLY;
1133 break;
1134
1135 /* Normal data. */
1136 case 0x1:
1137 subspace_asect->flags |= SEC_DATA;
1138 break;
1139
1140 /* Readonly code and the gateways.
1141 Gateways have other attributes which do not map
1142 into anything BFD knows about. */
1143 case 0x2:
1144 case 0x4:
1145 case 0x5:
1146 case 0x6:
1147 case 0x7:
1148 subspace_asect->flags |= SEC_CODE | SEC_READONLY;
1149 break;
1150
1151 /* dynamic (writable) code. */
1152 case 0x3:
1153 subspace_asect->flags |= SEC_CODE;
1154 break;
1155 }
1156
1157 if (subspace.dup_common || subspace.is_common)
1158 subspace_asect->flags |= SEC_IS_COMMON;
1159 else
1160 subspace_asect->flags |= SEC_HAS_CONTENTS;
d9ad93bc
KR
1161 if (subspace.is_loadable)
1162 subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
1163 if (subspace.code_only)
1164 subspace_asect->flags |= SEC_CODE;
1165
9e16fcf1
SG
1166 /* This subspace has relocations.
1167 The fixup_request_quantity is a byte count for the number of
1168 entries in the relocation stream; it is not the actual number
1169 of relocations in the subspace. */
1170 if (subspace.fixup_request_quantity != 0)
1171 {
1172 subspace_asect->flags |= SEC_RELOC;
1173 subspace_asect->rel_filepos = subspace.fixup_request_index;
1174 som_section_data (subspace_asect)->reloc_size
1175 = subspace.fixup_request_quantity;
1176 /* We can not determine this yet. When we read in the
1177 relocation table the correct value will be filled in. */
1178 subspace_asect->reloc_count = -1;
1179 }
1180
1181 /* Update save_subspace if appropriate. */
1182 if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
1183 save_subspace = subspace;
1184
d9ad93bc
KR
1185 subspace_asect->vma = subspace.subspace_start;
1186 subspace_asect->_cooked_size = subspace.subspace_length;
1187 subspace_asect->_raw_size = subspace.initialization_length;
9e16fcf1 1188 subspace_asect->alignment_power = log2 (subspace.alignment);
d9ad93bc 1189 subspace_asect->filepos = subspace.file_loc_init_value;
d9ad93bc 1190 }
9e16fcf1
SG
1191
1192 /* Yow! there is no subspace within the space which actually
1193 has initialized information in it; this should never happen
1194 as far as I know. */
1195 if (!save_subspace.file_loc_init_value)
1196 abort ();
1197
d9ad93bc 1198 /* Setup the sizes for the space section based upon the info in the
9e16fcf1
SG
1199 last subspace of the space. */
1200 space_asect->_cooked_size = save_subspace.subspace_start
1201 - space_asect->vma + save_subspace.subspace_length;
1202 space_asect->_raw_size = save_subspace.file_loc_init_value
1203 - space_asect->filepos + save_subspace.initialization_length;
d9ad93bc 1204 }
9e16fcf1 1205 return true;
d9ad93bc
KR
1206}
1207
9e16fcf1
SG
1208/* Read in a SOM object and make it into a BFD. */
1209
d9ad93bc 1210static bfd_target *
9e16fcf1 1211som_object_p (abfd)
d9ad93bc
KR
1212 bfd *abfd;
1213{
1214 struct header file_hdr;
1215 struct som_exec_auxhdr aux_hdr;
1216
1217 if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
9e16fcf1
SG
1218 {
1219 bfd_error = system_call_error;
1220 return 0;
1221 }
d9ad93bc
KR
1222
1223 if (!_PA_RISC_ID (file_hdr.system_id))
1224 {
1225 bfd_error = wrong_format;
1226 return 0;
1227 }
1228
1229 switch (file_hdr.a_magic)
1230 {
9e16fcf1 1231 case RELOC_MAGIC:
d9ad93bc
KR
1232 case EXEC_MAGIC:
1233 case SHARE_MAGIC:
1234 case DEMAND_MAGIC:
1235#ifdef DL_MAGIC
1236 case DL_MAGIC:
1237#endif
1238#ifdef SHL_MAGIC
1239 case SHL_MAGIC:
9e16fcf1
SG
1240#endif
1241#ifdef EXECLIBMAGIC
1242 case EXECLIBMAGIC:
d9ad93bc
KR
1243#endif
1244 break;
1245 default:
1246 bfd_error = wrong_format;
1247 return 0;
1248 }
1249
1250 if (file_hdr.version_id != VERSION_ID
1251 && file_hdr.version_id != NEW_VERSION_ID)
1252 {
1253 bfd_error = wrong_format;
1254 return 0;
1255 }
1256
9e16fcf1
SG
1257 /* If the aux_header_size field in the file header is zero, then this
1258 object is an incomplete executable (a .o file). Do not try to read
1259 a non-existant auxiliary header. */
1260 bzero (&aux_hdr, sizeof (struct som_exec_auxhdr));
1261 if (file_hdr.aux_header_size != 0)
1262 {
1263 if (bfd_read ((PTR) & aux_hdr, 1, AUX_HDR_SIZE, abfd) != AUX_HDR_SIZE)
1264 {
1265 bfd_error = wrong_format;
1266 return 0;
1267 }
1268 }
d9ad93bc
KR
1269
1270 if (!setup_sections (abfd, &file_hdr))
9e16fcf1
SG
1271 {
1272 /* setup_sections does not bubble up a bfd error code. */
1273 bfd_error = bad_value;
1274 return 0;
1275 }
d9ad93bc 1276
9e16fcf1
SG
1277 /* This appears to be a valid SOM object. Do some initialization. */
1278 return som_object_setup (abfd, &file_hdr, &aux_hdr);
d9ad93bc
KR
1279}
1280
9e16fcf1
SG
1281/* Create a SOM object. */
1282
d9ad93bc 1283static boolean
9e16fcf1 1284som_mkobject (abfd)
d9ad93bc
KR
1285 bfd *abfd;
1286{
9e16fcf1
SG
1287 /* Allocate memory to hold backend information. */
1288 abfd->tdata.som_data = (struct som_data_struct *)
1289 bfd_zalloc (abfd, sizeof (struct som_data_struct));
1290 if (abfd->tdata.som_data == NULL)
1291 {
1292 bfd_error = no_memory;
1293 return false;
1294 }
1295 obj_som_file_hdr (abfd) = bfd_zalloc (abfd, sizeof (struct header));
1296 if (obj_som_file_hdr (abfd) == NULL)
1297
1298 {
1299 bfd_error = no_memory;
1300 return false;
1301 }
1302 return true;
d9ad93bc
KR
1303}
1304
0ffa24b9
JL
1305/* Initialize some information in the file header. This routine makes
1306 not attempt at doing the right thing for a full executable; it
1307 is only meant to handle relocatable objects. */
1308
1309static boolean
1310som_prep_headers (abfd)
1311 bfd *abfd;
1312{
1313 struct header *file_hdr = obj_som_file_hdr (abfd);
1314 asection *section;
1315
1316 /* FIXME. This should really be conditional based on whether or not
1317 PA1.1 instructions/registers have been used. */
1318 file_hdr->system_id = HP9000S800_ID;
1319
1320 /* FIXME. Only correct for building relocatable objects. */
1321 if (abfd->flags & EXEC_P)
1322 abort ();
1323 else
1324 file_hdr->a_magic = RELOC_MAGIC;
1325
1326 /* Only new format SOM is supported. */
1327 file_hdr->version_id = NEW_VERSION_ID;
1328
1329 /* These fields are optional, and embedding timestamps is not always
1330 a wise thing to do, it makes comparing objects during a multi-stage
1331 bootstrap difficult. */
1332 file_hdr->file_time.secs = 0;
1333 file_hdr->file_time.nanosecs = 0;
1334
1335 if (abfd->flags & EXEC_P)
1336 abort ();
1337 else
1338 {
1339 file_hdr->entry_space = 0;
1340 file_hdr->entry_subspace = 0;
1341 file_hdr->entry_offset = 0;
1342 }
1343
1344 /* FIXME. I do not know if we ever need to put anything other
1345 than zero in this field. */
1346 file_hdr->presumed_dp = 0;
1347
1348 /* Now iterate over the sections translating information from
1349 BFD sections to SOM spaces/subspaces. */
1350
1351 for (section = abfd->sections; section != NULL; section = section->next)
1352 {
1353 /* Ignore anything which has not been marked as a space or
1354 subspace. */
1355 if (som_section_data (section)->is_space == 0
1356
1357 && som_section_data (section)->is_subspace == 0)
1358 continue;
1359
1360 if (som_section_data (section)->is_space)
1361 {
1362 /* Set space attributes. Note most attributes of SOM spaces
1363 are set based on the subspaces it contains. */
1364 som_section_data (section)->space_dict.loader_fix_index = -1;
1365 som_section_data (section)->space_dict.init_pointer_index = -1;
1366 }
1367 else
1368 {
1369 /* Set subspace attributes. Basic stuff is done here, additional
1370 attributes are filled in later as more information becomes
1371 available. */
1372 if (section->flags & SEC_IS_COMMON)
1373 {
1374 som_section_data (section)->subspace_dict.dup_common = 1;
1375 som_section_data (section)->subspace_dict.is_common = 1;
1376 }
1377
1378 if (section->flags & SEC_ALLOC)
1379 som_section_data (section)->subspace_dict.is_loadable = 1;
1380
1381 if (section->flags & SEC_CODE)
1382 som_section_data (section)->subspace_dict.code_only = 1;
1383
1384 som_section_data (section)->subspace_dict.subspace_start =
1385 section->vma;
1386 som_section_data (section)->subspace_dict.subspace_length =
1387 bfd_section_size (abfd, section);
1388 som_section_data (section)->subspace_dict.initialization_length =
1389 bfd_section_size (abfd, section);
1390 som_section_data (section)->subspace_dict.alignment =
1391 1 << section->alignment_power;
1392 }
1393 }
1394 return true;
1395}
1396
5532fc5a
JL
1397/* Count and return the number of spaces attached to the given BFD. */
1398
1399static unsigned long
1400som_count_spaces (abfd)
1401 bfd *abfd;
1402{
1403 int count = 0;
1404 asection *section;
1405
1406 for (section = abfd->sections; section != NULL; section = section->next)
1407 count += som_section_data (section)->is_space;
1408
1409 return count;
1410}
1411
1412/* Count the number of subspaces attached to the given BFD. */
1413
1414static unsigned long
1415som_count_subspaces (abfd)
1416 bfd *abfd;
1417{
1418 int count = 0;
1419 asection *section;
1420
1421 for (section = abfd->sections; section != NULL; section = section->next)
1422 count += som_section_data (section)->is_subspace;
1423
1424 return count;
1425}
1426
1427/* Return -1, 0, 1 indicating the relative ordering of sym1 and sym2.
1428
1429 We desire symbols to be ordered starting with the symbol with the
1430 highest relocation count down to the symbol with the lowest relocation
1431 count. Doing so compacts the relocation stream. */
1432
1433static int
1434compare_syms (sym1, sym2)
1435 asymbol **sym1;
1436 asymbol **sym2;
1437
1438{
1439 unsigned int count1, count2;
1440
1441 /* Get relocation count for each symbol. Note that the count
1442 is stored in the udata pointer for section symbols! */
1443 if ((*sym1)->flags & BSF_SECTION_SYM)
1444 count1 = (int)(*sym1)->udata;
1445 else
1446 count1 = (*som_symbol_data ((*sym1)))->reloc_count;
1447
1448 if ((*sym2)->flags & BSF_SECTION_SYM)
1449 count2 = (int)(*sym2)->udata;
1450 else
1451 count2 = (*som_symbol_data ((*sym2)))->reloc_count;
1452
1453 /* Return the appropriate value. */
1454 if (count1 < count2)
1455 return 1;
1456 else if (count1 > count2)
1457 return -1;
1458 return 0;
1459}
1460
aff97790
JL
1461/* Perform various work in preparation for emitting the fixup stream. */
1462
1463static void
1464som_prep_for_fixups (abfd, syms, num_syms)
1465 bfd *abfd;
1466 asymbol **syms;
1467 unsigned long num_syms;
1468{
1469 int i;
1470 asection *section;
1471
1472 /* Most SOM relocations involving a symbol have a length which is
1473 dependent on the index of the symbol. So symbols which are
1474 used often in relocations should have a small index. */
1475
1476 /* First initialize the counters for each symbol. */
1477 for (i = 0; i < num_syms; i++)
1478 {
1479 /* Handle a section symbol; these have no pointers back to the
1480 SOM symbol info. So we just use the pointer field (udata)
1481 to hold the relocation count.
1482
1483 FIXME. While we're here set the name of any section symbol
1484 to something which will not screw GDB. How do other formats
1485 deal with this?!? */
1486 if (som_symbol_data (syms[i]) == NULL)
1487 {
1488 syms[i]->flags |= BSF_SECTION_SYM;
1489 syms[i]->name = "L$0\002";
1490 syms[i]->udata = (PTR) 0;
1491 }
1492 else
1493 (*som_symbol_data (syms[i]))->reloc_count = 0;
1494 }
1495
1496 /* Now that the counters are initialized, make a weighted count
1497 of how often a given symbol is used in a relocation. */
1498 for (section = abfd->sections; section != NULL; section = section->next)
1499 {
1500 int i;
1501
1502 /* Does this section have any relocations? */
1503 if (section->reloc_count <= 0)
1504 continue;
1505
1506 /* Walk through each relocation for this section. */
1507 for (i = 1; i < section->reloc_count; i++)
1508 {
1509 arelent *reloc = section->orelocation[i];
1510 int scale;
1511
1512 /* If no symbol, then there is no counter to increase. */
1513 if (reloc->sym_ptr_ptr == NULL)
1514 continue;
1515
1516 /* Scaling to encourage symbols involved in R_DP_RELATIVE
1517 and R_CODE_ONE_SYMBOL relocations to come first. These
1518 two relocations have single byte versions if the symbol
1519 index is very small. */
1520 if (reloc->howto->type == R_DP_RELATIVE
1521 || reloc->howto->type == R_CODE_ONE_SYMBOL)
1522 scale = 2;
1523 else
1524 scale = 1;
1525
1526 /* Handle section symbols by ramming the count in the udata
1527 field. It will not be used and the count is very important
1528 for these symbols. */
1529 if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
1530 {
1531 (*reloc->sym_ptr_ptr)->udata =
1532 (PTR) ((int) (*reloc->sym_ptr_ptr)->udata + scale);
1533 continue;
1534 }
1535
1536 /* A normal symbol. Increment the count. */
1537 (*som_symbol_data ((*reloc->sym_ptr_ptr)))->reloc_count += scale;
1538 }
1539 }
1540
1541 /* Now sort the symbols. */
1542 qsort (syms, num_syms, sizeof (asymbol *), compare_syms);
1543
1544 /* Compute the symbol indexes, they will be needed by the relocation
1545 code. */
1546 for (i = 0; i < num_syms; i++)
1547 {
1548 /* A section symbol. Again, there is no pointer to backend symbol
1549 information, so we reuse (abuse) the udata field again. */
1550 if (syms[i]->flags & BSF_SECTION_SYM)
1551 syms[i]->udata = (PTR) i;
1552 else
1553 (*som_symbol_data (syms[i]))->index = i;
1554 }
1555}
1556
9d0dea6f
JL
1557static boolean
1558som_write_fixups (abfd, current_offset, total_reloc_sizep)
1559 bfd *abfd;
1560 unsigned long current_offset;
1561 unsigned int *total_reloc_sizep;
1562{
1563 unsigned int i, j;
1564 unsigned char *tmp_space, *p;
1565 unsigned int total_reloc_size = 0;
1566 unsigned int subspace_reloc_size = 0;
1567 unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
1568 asection *section = abfd->sections;
1569
1570 /* Get a chunk of memory that we can use as buffer space, then throw
1571 away. */
1572 tmp_space = alloca (SOM_TMP_BUFSIZE);
1573 bzero (tmp_space, SOM_TMP_BUFSIZE);
1574 p = tmp_space;
1575
1576 /* All the fixups for a particular subspace are emitted in a single
1577 stream. All the subspaces for a particular space are emitted
1578 as a single stream.
1579
1580 So, to get all the locations correct one must iterate through all the
1581 spaces, for each space iterate through its subspaces and output a
1582 fixups stream. */
1583 for (i = 0; i < num_spaces; i++)
1584 {
1585 asection *subsection;
1586
1587 /* Find a space. */
1588 while (som_section_data (section)->is_space == 0)
1589 section = section->next;
1590
1591 /* Now iterate through each of its subspaces. */
1592 for (subsection = abfd->sections;
1593 subsection != NULL;
1594 subsection = subsection->next)
1595 {
1596 int reloc_offset;
1597
1598 /* Find a subspace of this space. */
1599 if (som_section_data (subsection)->is_subspace == 0
1600 || som_section_data (subsection)->containing_space != section)
1601 continue;
1602
1603 /* If this subspace had no relocations, then we're finished
1604 with it. */
1605 if (subsection->reloc_count <= 0)
1606 {
1607 som_section_data (subsection)->subspace_dict.fixup_request_index
1608 = -1;
1609 continue;
1610 }
1611
1612 /* This subspace has some relocations. Put the relocation stream
1613 index into the subspace record. */
1614 som_section_data (subsection)->subspace_dict.fixup_request_index
1615 = total_reloc_size;
1616
1617 /* To make life easier start over with a clean slate for
1618 each subspace. Seek to the start of the relocation stream
1619 for this subspace in preparation for writing out its fixup
1620 stream. */
1621 if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) != 0)
1622 {
1623 bfd_error = system_call_error;
1624 return false;
1625 }
1626
1627 /* Buffer space has already been allocated. Just perform some
1628 initialization here. */
1629 p = tmp_space;
1630 subspace_reloc_size = 0;
1631 reloc_offset = 0;
1632 som_initialize_reloc_queue (reloc_queue);
1633
1634 /* Translate each BFD relocation into one or more SOM
1635 relocations. */
1636 for (j = 0; j < subsection->reloc_count; j++)
1637 {
1638 arelent *bfd_reloc = subsection->orelocation[j];
1639 unsigned int skip;
1640 int sym_num;
1641
1642 /* Get the symbol number. Remember it's stored in a
1643 special place for section symbols. */
1644 if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
1645 sym_num = (int) (*bfd_reloc->sym_ptr_ptr)->udata;
1646 else
91c0bcbb 1647 sym_num = (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->index;
9d0dea6f
JL
1648
1649 /* If there is not enough room for the next couple relocations,
1650 then dump the current buffer contents now. Also reinitialize
1651 the relocation queue.
1652
1653 FIXME. We assume here that no BFD relocation will expand
1654 to more than 100 bytes of SOM relocations. This should (?!?)
1655 be quite safe. */
1656 if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
1657 {
1658 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
1659 != p - tmp_space)
1660 {
1661 bfd_error = system_call_error;
1662 return false;
1663 }
1664 p = tmp_space;
1665 som_initialize_reloc_queue (reloc_queue);
1666 }
1667
1668 /* Emit R_NO_RELOCATION fixups to map any bytes which were
1669 skipped. */
1670 skip = bfd_reloc->address - reloc_offset;
1671 p = som_reloc_skip (abfd, skip, p,
1672 &subspace_reloc_size, reloc_queue);
1673
1674 /* Update reloc_offset for the next iteration.
1675
1676 Note R_ENTRY and R_EXIT relocations are just markers,
1677 they do not consume input bytes. */
1678 if (bfd_reloc->howto->type != R_ENTRY
1679 && bfd_reloc->howto->type != R_EXIT)
1680 reloc_offset = bfd_reloc->address + 4;
1681 else
1682 reloc_offset = bfd_reloc->address;
1683
1684
1685 /* Now the actual relocation we care about. */
1686 switch (bfd_reloc->howto->type)
1687 {
1688 case R_PCREL_CALL:
1689 case R_ABS_CALL:
1690 p = som_reloc_call (abfd, p, &subspace_reloc_size,
1691 bfd_reloc, sym_num, reloc_queue);
1692 break;
1693
1694 case R_CODE_ONE_SYMBOL:
1695 case R_DP_RELATIVE:
1696 /* Account for any addend. */
1697 if (bfd_reloc->addend)
1698 p = som_reloc_addend (abfd, bfd_reloc->addend, p,
1699 &subspace_reloc_size, reloc_queue);
1700
1701 if (sym_num < 0x20)
1702 {
1703 bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
1704 subspace_reloc_size += 1;
1705 p += 1;
1706 }
1707 else if (sym_num < 0x100)
1708 {
1709 bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
1710 bfd_put_8 (abfd, sym_num, p + 1);
1711 p = try_prev_fixup (abfd, &subspace_reloc_size, p,
1712 2, reloc_queue);
1713 }
1714 else if (sym_num < 0x10000000)
1715 {
1716 bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
1717 bfd_put_8 (abfd, sym_num >> 16, p + 1);
1718 bfd_put_16 (abfd, sym_num, p + 2);
1719 p = try_prev_fixup (abfd, &subspace_reloc_size,
1720 p, 4, reloc_queue);
1721 }
1722 else
1723 abort ();
1724 break;
1725
1726 case R_DATA_ONE_SYMBOL:
1727 case R_DATA_PLABEL:
1728 case R_CODE_PLABEL:
1729 /* Account for any addend. */
1730 if (bfd_reloc->addend)
1731 p = som_reloc_addend (abfd, bfd_reloc->addend, p,
1732 &subspace_reloc_size, reloc_queue);
1733
1734 if (sym_num < 0x100)
1735 {
1736 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
1737 bfd_put_8 (abfd, sym_num, p + 1);
1738 p = try_prev_fixup (abfd, &subspace_reloc_size, p,
1739 2, reloc_queue);
1740 }
1741 else if (sym_num < 0x10000000)
1742 {
1743 bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
1744 bfd_put_8 (abfd, sym_num >> 16, p + 1);
1745 bfd_put_16 (abfd, sym_num, p + 2);
1746 p = try_prev_fixup (abfd, &subspace_reloc_size,
1747 p, 4, reloc_queue);
1748 }
1749 else
1750 abort ();
1751 break;
1752
1753 case R_ENTRY:
1754 {
1755 int *descp
1756 = (int *) (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->unwind;
1757 bfd_put_8 (abfd, R_ENTRY, p);
1758 bfd_put_32 (abfd, descp[0], p + 1);
1759 bfd_put_32 (abfd, descp[1], p + 5);
1760 p = try_prev_fixup (abfd, &subspace_reloc_size,
1761 p, 9, reloc_queue);
1762 break;
1763 }
1764
1765 case R_EXIT:
1766 bfd_put_8 (abfd, R_EXIT, p);
1767 subspace_reloc_size += 1;
1768 p += 1;
1769 break;
1770
1771 /* Put a "R_RESERVED" relocation in the stream if
1772 we hit something we do not understand. The linker
1773 will complain loudly if this ever happens. */
1774 default:
1775 bfd_put_8 (abfd, 0xff, p);
1776 subspace_reloc_size += 1;
1777 p += 1;
1778 }
1779 }
1780
1781 /* Last BFD relocation for a subspace has been processed.
1782 Map the rest of the subspace with R_NO_RELOCATION fixups. */
1783 p = som_reloc_skip (abfd, bfd_section_size (abfd, subsection)
1784 - reloc_offset,
1785 p, &subspace_reloc_size, reloc_queue);
1786
1787 /* Scribble out the relocations. */
1788 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
1789 != p - tmp_space)
1790 {
1791 bfd_error = system_call_error;
1792 return false;
1793 }
1794 p = tmp_space;
1795
1796 total_reloc_size += subspace_reloc_size;
1797 som_section_data (subsection)->subspace_dict.fixup_request_quantity
1798 = subspace_reloc_size;
1799 }
1800 section = section->next;
1801 }
1802 *total_reloc_sizep = total_reloc_size;
1803 return true;
1804}
1805
0b35f7ec
JL
1806/* Write out the space/subspace string table. */
1807
1808static boolean
1809som_write_space_strings (abfd, current_offset, string_sizep)
1810 bfd *abfd;
1811 unsigned long current_offset;
1812 unsigned int *string_sizep;
1813{
1814 unsigned char *tmp_space, *p;
1815 unsigned int strings_size = 0;
1816 asection *section;
1817
1818 /* Get a chunk of memory that we can use as buffer space, then throw
1819 away. */
1820 tmp_space = alloca (SOM_TMP_BUFSIZE);
1821 bzero (tmp_space, SOM_TMP_BUFSIZE);
1822 p = tmp_space;
1823
1824 /* Seek to the start of the space strings in preparation for writing
1825 them out. */
1826 if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
1827 {
1828 bfd_error = system_call_error;
1829 return false;
1830 }
1831
1832 /* Walk through all the spaces and subspaces (order is not important)
1833 building up and writing string table entries for their names. */
1834 for (section = abfd->sections; section != NULL; section = section->next)
1835 {
1836 int length;
1837
1838 /* Only work with space/subspaces; avoid any other sections
1839 which might have been made (.text for example). */
1840 if (som_section_data (section)->is_space == 0
1841 && som_section_data (section)->is_subspace == 0)
1842 continue;
1843
1844 /* Get the length of the space/subspace name. */
1845 length = strlen (section->name);
1846
1847 /* If there is not enough room for the next entry, then dump the
1848 current buffer contents now. Each entry will take 4 bytes to
1849 hold the string length + the string itself + null terminator. */
1850 if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
1851 {
1852 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
1853 != p - tmp_space)
1854 {
1855 bfd_error = system_call_error;
1856 return false;
1857 }
1858 /* Reset to beginning of the buffer space. */
1859 p = tmp_space;
1860 }
1861
1862 /* First element in a string table entry is the length of the
1863 string. Alignment issues are already handled. */
1864 bfd_put_32 (abfd, length, p);
1865 p += 4;
1866 strings_size += 4;
1867
1868 /* Record the index in the space/subspace records. */
1869 if (som_section_data (section)->is_space)
1870 som_section_data (section)->space_dict.name.n_strx = strings_size;
1871 else
1872 som_section_data (section)->subspace_dict.name.n_strx = strings_size;
1873
1874 /* Next comes the string itself + a null terminator. */
1875 strcpy (p, section->name);
1876 p += length + 1;
1877 strings_size += length + 1;
1878
1879 /* Always align up to the next word boundary. */
1880 while (strings_size % 4)
1881 {
1882 bfd_put_8 (abfd, 0, p);
1883 p++;
1884 strings_size++;
1885 }
1886 }
1887
1888 /* Done with the space/subspace strings. Write out any information
1889 contained in a partial block. */
1890 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd) != p - tmp_space)
1891 {
1892 bfd_error = system_call_error;
1893 return false;
1894 }
1895 *string_sizep = strings_size;
1896 return true;
1897}
1898
1899/* Write out the symbol string table. */
1900
1901static boolean
1902som_write_symbol_strings (abfd, current_offset, syms, num_syms, string_sizep)
1903 bfd *abfd;
1904 unsigned long current_offset;
1905 asymbol **syms;
1906 unsigned int num_syms;
1907 unsigned int *string_sizep;
1908{
1909 unsigned int i;
1910 unsigned char *tmp_space, *p;
1911 unsigned int strings_size = 0;
1912
1913 /* Get a chunk of memory that we can use as buffer space, then throw
1914 away. */
1915 tmp_space = alloca (SOM_TMP_BUFSIZE);
1916 bzero (tmp_space, SOM_TMP_BUFSIZE);
1917 p = tmp_space;
1918
1919 /* Seek to the start of the space strings in preparation for writing
1920 them out. */
1921 if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
1922 {
1923 bfd_error = system_call_error;
1924 return false;
1925 }
1926
1927 for (i = 0; i < num_syms; i++)
1928 {
1929 int length = strlen (syms[i]->name);
1930
1931 /* If there is not enough room for the next entry, then dump the
1932 current buffer contents now. */
1933 if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
1934 {
1935 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
1936 != p - tmp_space)
1937 {
1938 bfd_error = system_call_error;
1939 return false;
1940 }
1941 /* Reset to beginning of the buffer space. */
1942 p = tmp_space;
1943 }
1944
1945 /* First element in a string table entry is the length of the
1946 string. This must always be 4 byte aligned. This is also
1947 an appropriate time to fill in the string index field in the
1948 symbol table entry. */
1949 bfd_put_32 (abfd, length, p);
1950 strings_size += 4;
1951 p += 4;
1952
1953 /* Next comes the string itself + a null terminator. */
1954 strcpy (p, syms[i]->name);
1955
1956 /* ACK. FIXME. */
1957 syms[i]->name = (char *)strings_size;
1958 p += length + 1;
1959 strings_size += length + 1;
1960
1961 /* Always align up to the next word boundary. */
1962 while (strings_size % 4)
1963 {
1964 bfd_put_8 (abfd, 0, p);
1965 strings_size++;
1966 p++;
1967 }
1968 }
1969
1970 /* Scribble out any partial block. */
1971 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd) != p - tmp_space)
1972 {
1973 bfd_error = system_call_error;
1974 return false;
1975 }
1976
1977 *string_sizep = strings_size;
1978 return true;
1979}
1980
6eb64408
JL
1981/* Compute variable information to be placed in the SOM headers,
1982 space/subspace dictionaries, relocation streams, etc. Begin
1983 writing parts of the object file. */
1984
1985static boolean
1986som_begin_writing (abfd)
1987 bfd *abfd;
1988{
1989 unsigned long current_offset = 0;
1990 int strings_size = 0;
1991 unsigned int total_reloc_size = 0;
1992 unsigned long num_spaces, num_subspaces, num_syms, i;
1993 asection *section;
1994 asymbol **syms = bfd_get_outsymbols (abfd);
1995 unsigned int total_subspaces = 0;
1996
1997 /* The file header will always be first in an object file,
1998 everything else can be in random locations. To keep things
1999 "simple" BFD will lay out the object file in the manner suggested
2000 by the PRO ABI for PA-RISC Systems. */
2001
2002 /* Before any output can really begin offsets for all the major
2003 portions of the object file must be computed. So, starting
2004 with the initial file header compute (and sometimes write)
2005 each portion of the object file. */
2006
2007 /* Make room for the file header, it's contents are not complete
2008 yet, so it can not be written at this time. */
2009 current_offset += sizeof (struct header);
2010
2011 /* Any auxiliary headers will follow the file header. Right now
2012 we have no auxiliary headers, so current_offset does not change. */
2013 obj_som_file_hdr (abfd)->aux_header_location = current_offset;
2014 obj_som_file_hdr (abfd)->aux_header_size = 0;
2015
2016 /* Next comes the initialization pointers; again we have no
2017 initialization pointers, so current offset does not change. */
2018 obj_som_file_hdr (abfd)->init_array_location = current_offset;
2019 obj_som_file_hdr (abfd)->init_array_total = 0;
2020
2021 /* Next are the space records. These are fixed length records.
2022
2023 Count the number of spaces to determine how much room is needed
2024 in the object file for the space records.
2025
2026 The names of the spaces are stored in a separate string table,
2027 and the index for each space into the string table is computed
2028 below. Therefore, it is not possible to write the space headers
2029 at this time. */
2030 num_spaces = som_count_spaces (abfd);
2031 obj_som_file_hdr (abfd)->space_location = current_offset;
2032 obj_som_file_hdr (abfd)->space_total = num_spaces;
2033 current_offset += num_spaces * sizeof (struct space_dictionary_record);
2034
2035 /* Next are the subspace records. These are fixed length records.
2036
2037 Count the number of subspaes to determine how much room is needed
2038 in the object file for the subspace records.
2039
2040 A variety if fields in the subspace record are still unknown at
2041 this time (index into string table, fixup stream location/size, etc). */
2042 num_subspaces = som_count_subspaces (abfd);
2043 obj_som_file_hdr (abfd)->subspace_location = current_offset;
2044 obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
2045 current_offset += num_subspaces * sizeof (struct subspace_dictionary_record);
2046
2047 /* Next is the string table for the space/subspace names. We will
2048 build and write the string table on the fly. At the same time
2049 we will fill in the space/subspace name index fields. */
2050
2051 /* The string table needs to be aligned on a word boundary. */
2052 if (current_offset % 4)
2053 current_offset += (4 - (current_offset % 4));
2054
2055 /* Mark the offset of the space/subspace string table in the
2056 file header. */
2057 obj_som_file_hdr (abfd)->space_strings_location = current_offset;
2058
2059 /* Scribble out the space strings. */
2060 if (som_write_space_strings (abfd, current_offset, &strings_size) == false)
2061 return false;
2062
2063 /* Record total string table size in the header and update the
2064 current offset. */
2065 obj_som_file_hdr (abfd)->space_strings_size = strings_size;
2066 current_offset += strings_size;
2067
2068 /* Next is the symbol table. These are fixed length records.
2069
2070 Count the number of symbols to determine how much room is needed
2071 in the object file for the symbol table.
2072
2073 The names of the symbols are stored in a separate string table,
2074 and the index for each symbol name into the string table is computed
2075 below. Therefore, it is not possible to write the symobl table
2076 at this time. */
2077 num_syms = bfd_get_symcount (abfd);
2078 obj_som_file_hdr (abfd)->symbol_location = current_offset;
2079 obj_som_file_hdr (abfd)->symbol_total = num_syms;
2080 current_offset += num_syms * sizeof (struct symbol_dictionary_record);
2081
2082 /* Do prep work before handling fixups. */
2083 som_prep_for_fixups (abfd, syms, num_syms);
2084
2085 /* Next comes the fixup stream which starts on a word boundary. */
2086 if (current_offset % 4)
2087 current_offset += (4 - (current_offset % 4));
2088 obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
2089
2090 /* Write the fixups and update fields in subspace headers which
2091 relate to the fixup stream. */
2092 if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
2093 return false;
2094
2095 /* Record the total size of the fixup stream in the file header. */
2096 obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
2097 current_offset += total_reloc_size;
2098
2099 /* Next are the symbol strings.
2100 Align them to a word boundary. */
2101 if (current_offset % 4)
2102 current_offset += (4 - (current_offset % 4));
2103 obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
2104
2105 /* Scribble out the symbol strings. */
2106 if (som_write_symbol_strings (abfd, current_offset, syms,
2107 num_syms, &strings_size)
2108 == false)
2109 return false;
2110
2111 /* Record total string table size in header and update the
2112 current offset. */
2113 obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
2114 current_offset += strings_size;
2115
2116 /* Next is the compiler records. We do not use these. */
2117 obj_som_file_hdr (abfd)->compiler_location = current_offset;
2118 obj_som_file_hdr (abfd)->compiler_total = 0;
2119
2120 /* Now compute the file positions for the loadable subspaces. */
2121
2122 section = abfd->sections;
2123 for (i = 0; i < num_spaces; i++)
2124 {
2125 asection *subsection;
2126
2127 /* Find a space. */
2128 while (som_section_data (section)->is_space == 0)
2129 section = section->next;
2130
2131 /* Now look for all its subspaces. */
2132 for (subsection = abfd->sections;
2133 subsection != NULL;
2134 subsection = subsection->next)
2135 {
2136
2137 if (som_section_data (subsection)->is_subspace == 0
2138 || som_section_data (subsection)->containing_space != section
2139 || (subsection->flags & SEC_ALLOC) == 0)
2140 continue;
2141
2142 som_section_data (subsection)->subspace_index = total_subspaces++;
2143 /* This is real data to be loaded from the file. */
2144 if (subsection->flags & SEC_LOAD)
2145 {
2146 som_section_data (subsection)->subspace_dict.file_loc_init_value
2147 = current_offset;
2148 section->filepos = current_offset;
2149 current_offset += bfd_section_size (abfd, subsection);
2150 }
2151 /* Looks like uninitialized data. */
2152 else
2153 {
2154 som_section_data (subsection)->subspace_dict.file_loc_init_value
2155 = 0;
2156 som_section_data (subsection)->subspace_dict.
2157 initialization_length = 0;
2158 }
2159 }
2160 /* Goto the next section. */
2161 section = section->next;
2162 }
2163
2164 /* Finally compute the file positions for unloadable subspaces. */
2165
2166 obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
2167 section = abfd->sections;
2168 for (i = 0; i < num_spaces; i++)
2169 {
2170 asection *subsection;
2171
2172 /* Find a space. */
2173 while (som_section_data (section)->is_space == 0)
2174 section = section->next;
2175
2176 /* Now look for all its subspaces. */
2177 for (subsection = abfd->sections;
2178 subsection != NULL;
2179 subsection = subsection->next)
2180 {
2181
2182 if (som_section_data (subsection)->is_subspace == 0
2183 || som_section_data (subsection)->containing_space != section
2184 || (subsection->flags & SEC_ALLOC) != 0)
2185 continue;
2186
2187 som_section_data (subsection)->subspace_index = total_subspaces++;
2188 /* This is real data to be loaded from the file. */
2189 if ((subsection->flags & SEC_LOAD) == 0)
2190 {
2191 som_section_data (subsection)->subspace_dict.file_loc_init_value
2192 = current_offset;
2193 section->filepos = current_offset;
2194 current_offset += bfd_section_size (abfd, subsection);
2195 }
2196 /* Looks like uninitialized data. */
2197 else
2198 {
2199 som_section_data (subsection)->subspace_dict.file_loc_init_value
2200 = 0;
2201 som_section_data (subsection)->subspace_dict.
2202 initialization_length = bfd_section_size (abfd, subsection);
2203 }
2204 }
2205 /* Goto the next section. */
2206 section = section->next;
2207 }
2208
2209 obj_som_file_hdr (abfd)->unloadable_sp_size
2210 = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
2211
2212 /* Loader fixups are not supported in any way shape or form. */
2213 obj_som_file_hdr (abfd)->loader_fixup_location = 0;
2214 obj_som_file_hdr (abfd)->loader_fixup_total = 0;
2215
2216 /* Done. Store the total size of the SOM. */
2217 obj_som_file_hdr (abfd)->som_length = current_offset;
2218 return true;
2219}
2220
efc0df7c
JL
2221/* Finally, scribble out the various headers to the disk. */
2222
2223static boolean
2224som_write_headers (abfd)
2225 bfd *abfd;
2226{
2227 int num_spaces = som_count_spaces (abfd);
2228 int i;
2229 int subspace_index = 0;
2230 file_ptr location;
2231 asection *section;
2232
2233 /* Subspaces are written first so that we can set up information
2234 about them in their containing spaces as the subspace is written. */
2235
2236 /* Seek to the start of the subspace dictionary records. */
2237 location = obj_som_file_hdr (abfd)->subspace_location;
2238 bfd_seek (abfd, location, SEEK_SET);
2239 section = abfd->sections;
2240 /* Now for each loadable space write out records for its subspaces. */
2241 for (i = 0; i < num_spaces; i++)
2242 {
2243 asection *subsection;
2244
2245 /* Find a space. */
2246 while (som_section_data (section)->is_space == 0)
2247 section = section->next;
2248
2249 /* Now look for all its subspaces. */
2250 for (subsection = abfd->sections;
2251 subsection != NULL;
2252 subsection = subsection->next)
2253 {
2254
2255 /* Skip any section which does not correspond to a space
2256 or subspace. Or does not have SEC_ALLOC set (and therefore
2257 has no real bits on the disk). */
2258 if (som_section_data (subsection)->is_subspace == 0
2259 || som_section_data (subsection)->containing_space != section
2260 || (subsection->flags & SEC_ALLOC) == 0)
2261 continue;
2262
2263 /* If this is the first subspace for this space, then save
2264 the index of the subspace in its containing space. Also
2265 set "is_loadable" in the containing space. */
2266
2267 if (som_section_data (section)->space_dict.subspace_quantity == 0)
2268 {
2269 som_section_data (section)->space_dict.is_loadable = 1;
2270 som_section_data (section)->space_dict.subspace_index
2271 = subspace_index;
2272 }
2273
2274 /* Increment the number of subspaces seen and the number of
2275 subspaces contained within the current space. */
2276 subspace_index++;
2277 som_section_data (section)->space_dict.subspace_quantity++;
2278
2279 /* Mark the index of the current space within the subspace's
2280 dictionary record. */
2281 som_section_data (subsection)->subspace_dict.space_index = i;
2282
2283 /* Dump the current subspace header. */
2284 if (bfd_write ((PTR) &som_section_data (subsection)->subspace_dict,
2285 sizeof (struct subspace_dictionary_record), 1, abfd)
2286 != sizeof (struct subspace_dictionary_record))
2287 {
2288 bfd_error = system_call_error;
2289 return false;
2290 }
2291 }
2292 /* Goto the next section. */
2293 section = section->next;
2294 }
2295
2296 /* Now repeat the process for unloadable subspaces. */
2297 section = abfd->sections;
2298 /* Now for each space write out records for its subspaces. */
2299 for (i = 0; i < num_spaces; i++)
2300 {
2301 asection *subsection;
2302
2303 /* Find a space. */
2304 while (som_section_data (section)->is_space == 0)
2305 section = section->next;
2306
2307 /* Now look for all its subspaces. */
2308 for (subsection = abfd->sections;
2309 subsection != NULL;
2310 subsection = subsection->next)
2311 {
2312
2313 /* Skip any section which does not correspond to a space or
2314 subspace, or which SEC_ALLOC set (and therefore handled
2315 in the loadable spaces/subspaces code above. */
2316
2317 if (som_section_data (subsection)->is_subspace == 0
2318 || som_section_data (subsection)->containing_space != section
2319 || (subsection->flags & SEC_ALLOC) != 0)
2320 continue;
2321
2322 /* If this is the first subspace for this space, then save
2323 the index of the subspace in its containing space. Clear
2324 "is_loadable". */
2325
2326 if (som_section_data (section)->space_dict.subspace_quantity == 0)
2327 {
2328 som_section_data (section)->space_dict.is_loadable = 0;
2329 som_section_data (section)->space_dict.subspace_index
2330 = subspace_index;
2331 }
2332
2333 /* Increment the number of subspaces seen and the number of
2334 subspaces contained within the current space. */
2335 som_section_data (section)->space_dict.subspace_quantity++;
2336 subspace_index++;
2337
2338 /* Mark the index of the current space within the subspace's
2339 dictionary record. */
2340 som_section_data (subsection)->subspace_dict.space_index = i;
2341
2342 /* Dump this subspace header. */
2343 if (bfd_write ((PTR) &som_section_data (subsection)->subspace_dict,
2344 sizeof (struct subspace_dictionary_record), 1, abfd)
2345 != sizeof (struct subspace_dictionary_record))
2346 {
2347 bfd_error = system_call_error;
2348 return false;
2349 }
2350 }
2351 /* Goto the next section. */
2352 section = section->next;
2353 }
2354
2355 /* All the subspace dictiondary records are written, and all the
2356 fields are set up in the space dictionary records.
2357
2358 Seek to the right location and start writing the space
2359 dictionary records. */
2360 location = obj_som_file_hdr (abfd)->space_location;
2361 bfd_seek (abfd, location, SEEK_SET);
2362
2363 section = abfd->sections;
2364 for (i = 0; i < num_spaces; i++)
2365 {
2366
2367 /* Find a space. */
2368 while (som_section_data (section)->is_space == 0)
2369 section = section->next;
2370
2371 /* Dump its header */
2372 if (bfd_write ((PTR) &som_section_data (section)->space_dict,
2373 sizeof (struct space_dictionary_record), 1, abfd)
2374 != sizeof (struct space_dictionary_record))
2375 {
2376 bfd_error = system_call_error;
2377 return false;
2378 }
2379
2380 /* Goto the next section. */
2381 section = section->next;
2382 }
2383
2384 /* Only thing left to do is write out the file header. It is always
2385 at location zero. Seek there and write it. */
2386 bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
2387 if (bfd_write ((PTR) obj_som_file_hdr (abfd),
2388 sizeof (struct header), 1, abfd)
2389 != sizeof (struct header))
2390 {
2391 bfd_error = system_call_error;
2392 return false;
2393 }
2394 return true;
2395}
2396
980bac64
JL
2397/* Compute and return the checksum for a SOM file header. */
2398
5532fc5a
JL
2399static unsigned long
2400som_compute_checksum (abfd)
2401 bfd *abfd;
2402{
2403 unsigned long checksum, count, i;
2404 unsigned long *buffer = (unsigned long *) obj_som_file_hdr (abfd);
2405
2406 checksum = 0;
2407 count = sizeof (struct header) / sizeof (unsigned long);
2408 for (i = 0; i < count; i++)
2409 checksum ^= *(buffer + i);
2410
2411 return checksum;
2412}
2413
713de7ec
JL
2414/* Build and write, in one big chunk, the entire symbol table for
2415 this BFD. */
2416
2417static boolean
2418som_build_and_write_symbol_table (abfd)
2419 bfd *abfd;
2420{
2421 unsigned int num_syms = bfd_get_symcount (abfd);
2422 file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
2423 asymbol **bfd_syms = bfd_get_outsymbols (abfd);
2424 struct symbol_dictionary_record *som_symtab;
2425 int i, symtab_size;
2426
2427 /* Compute total symbol table size and allocate a chunk of memory
2428 to hold the symbol table as we build it. */
2429 symtab_size = num_syms * sizeof (struct symbol_dictionary_record);
2430 som_symtab = (struct symbol_dictionary_record *) alloca (symtab_size);
2431 bzero (som_symtab, symtab_size);
2432
2433 /* Walk over each symbol. */
2434 for (i = 0; i < num_syms; i++)
2435 {
2436 /* This is really an index into the symbol strings table.
2437 By the time we get here, the index has already been
2438 computed and stored into the name field in the BFD symbol. */
2439 som_symtab[i].name.n_strx = (int) bfd_syms[i]->name;
2440
2441 /* The HP SOM linker requires detailed type information about
2442 all symbols (including undefined symbols!). Unfortunately,
2443 the type specified in an import/export statement does not
2444 always match what the linker wants. Severe braindamage. */
2445
2446 /* Section symbols will not have a SOM symbol type assigned to
2447 them yet. Assign all section symbols type ST_DATA. */
2448 if (bfd_syms[i]->flags & BSF_SECTION_SYM)
2449 som_symtab[i].symbol_type = ST_DATA;
2450 else
2451 {
2452 /* Common symbols must have scope SS_UNSAT and type
2453 ST_STORAGE or the linker will choke. */
2454 if (bfd_syms[i]->section == &bfd_com_section)
2455 {
2456 som_symtab[i].symbol_scope = SS_UNSAT;
2457 som_symtab[i].symbol_type = ST_STORAGE;
2458 }
2459
2460 /* It is possible to have a symbol without an associated
2461 type. This happens if the user imported the symbol
2462 without a type and the symbol was never defined
2463 locally. If BSF_FUNCTION is set for this symbol, then
2464 assign it type ST_CODE (the HP linker requires undefined
2465 external functions to have type ST_CODE rather than ST_ENTRY. */
2466 else if (((*som_symbol_data (bfd_syms[i]))->som_type
2467 == SYMBOL_TYPE_UNKNOWN)
2468 && (bfd_syms[i]->section == &bfd_und_section)
2469 && (bfd_syms[i]->flags & BSF_FUNCTION))
2470 som_symtab[i].symbol_type = ST_CODE;
2471
2472 /* Handle function symbols which were defined in this file.
2473 They should have type ST_ENTRY. Also retrieve the argument
2474 relocation bits from the SOM backend information. */
2475 else if (((*som_symbol_data (bfd_syms[i]))->som_type
2476 == SYMBOL_TYPE_ENTRY)
2477 || (((*som_symbol_data (bfd_syms[i]))->som_type
2478 == SYMBOL_TYPE_CODE)
2479 && (bfd_syms[i]->flags & BSF_FUNCTION))
2480 || (((*som_symbol_data (bfd_syms[i]))->som_type
2481 == SYMBOL_TYPE_UNKNOWN)
2482 && (bfd_syms[i]->flags & BSF_FUNCTION)))
2483 {
2484 som_symtab[i].symbol_type = ST_ENTRY;
2485 som_symtab[i].arg_reloc
2486 = (*som_symbol_data (bfd_syms[i]))->tc_data.hppa_arg_reloc;
2487 }
2488
2489 /* If the type is unknown at this point, it should be
2490 ST_DATA (functions were handled as special cases above). */
2491 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2492 == SYMBOL_TYPE_UNKNOWN)
2493 som_symtab[i].symbol_type = ST_DATA;
2494
2495 /* From now on it's a very simple mapping. */
2496 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2497 == SYMBOL_TYPE_ABSOLUTE)
2498 som_symtab[i].symbol_type = ST_ABSOLUTE;
2499 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2500 == SYMBOL_TYPE_CODE)
2501 som_symtab[i].symbol_type = ST_CODE;
2502 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2503 == SYMBOL_TYPE_DATA)
2504 som_symtab[i].symbol_type = ST_DATA;
2505 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2506 == SYMBOL_TYPE_MILLICODE)
2507 som_symtab[i].symbol_type = ST_MILLICODE;
2508 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2509 == SYMBOL_TYPE_PLABEL)
2510 som_symtab[i].symbol_type = ST_PLABEL;
2511 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2512 == SYMBOL_TYPE_PRI_PROG)
2513 som_symtab[i].symbol_type = ST_PRI_PROG;
2514 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2515 == SYMBOL_TYPE_SEC_PROG)
2516 som_symtab[i].symbol_type = ST_SEC_PROG;
2517 }
2518
2519 /* Now handle the symbol's scope. Exported data which is not
2520 in the common section has scope SS_UNIVERSAL. Note scope
980bac64 2521 of common symbols was handled earlier! */
713de7ec
JL
2522 if (bfd_syms[i]->flags & BSF_EXPORT
2523 && bfd_syms[i]->section != &bfd_com_section)
2524 som_symtab[i].symbol_scope = SS_UNIVERSAL;
2525 /* Any undefined symbol at this point has a scope SS_UNSAT. */
2526 else if (bfd_syms[i]->section == &bfd_und_section)
2527 som_symtab[i].symbol_scope = SS_UNSAT;
2528 /* Anything else which is not in the common section has scope
2529 SS_LOCAL. */
2530 else if (bfd_syms[i]->section != &bfd_com_section)
2531 som_symtab[i].symbol_scope = SS_LOCAL;
2532
2533 /* Now set the symbol_info field. It has no real meaning
2534 for undefined or common symbols, but the HP linker will
2535 choke if it's not set to some "reasonable" value. We
2536 use zero as a reasonable value. */
2537 if (bfd_syms[i]->section == &bfd_com_section
2538 || bfd_syms[i]->section == &bfd_und_section)
2539 som_symtab[i].symbol_info = 0;
2540 /* For all other symbols, the symbol_info field contains the
2541 subspace index of the space this symbol is contained in. */
2542 else
2543 som_symtab[i].symbol_info
2544 = som_section_data (bfd_syms[i]->section)->subspace_index;
2545
2546 /* Set the symbol's value. */
2547 som_symtab[i].symbol_value
2548 = bfd_syms[i]->value + bfd_syms[i]->section->vma;
2549 }
2550
2551 /* Egad. Everything is ready, seek to the right location and
2552 scribble out the symbol table. */
2553 if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
2554 {
2555 bfd_error = system_call_error;
2556 return false;
2557 }
2558
2559 if (bfd_write ((PTR) som_symtab, symtab_size, 1, abfd) != symtab_size)
2560 {
2561 bfd_error = system_call_error;
2562 return false;
2563 }
2564 return true;
2565}
2566
980bac64
JL
2567/* Write an object in SOM format. */
2568
2569static boolean
9e16fcf1 2570som_write_object_contents (abfd)
d9ad93bc
KR
2571 bfd *abfd;
2572{
980bac64
JL
2573 if (abfd->output_has_begun == false)
2574 {
2575 /* Set up fixed parts of the file, space, and subspace headers.
2576 Notify the world that output has begun. */
2577 som_prep_headers (abfd);
2578 abfd->output_has_begun = true;
980bac64
JL
2579 /* Start writing the object file. This include all the string
2580 tables, fixup streams, and other portions of the object file. */
2581 som_begin_writing (abfd);
980bac64
JL
2582 }
2583
2584 /* Now that the symbol table information is complete, build and
2585 write the symbol table. */
2586 if (som_build_and_write_symbol_table (abfd) == false)
2587 return false;
2588
2589 /* Compute the checksum for the file header just before writing
2590 the header to disk. */
2591 obj_som_file_hdr (abfd)->checksum = som_compute_checksum (abfd);
2592 return (som_write_headers (abfd));
d9ad93bc 2593}
980bac64
JL
2594
2595\f
9e16fcf1 2596/* Read and save the string table associated with the given BFD. */
d9ad93bc 2597
9e16fcf1
SG
2598static boolean
2599som_slurp_string_table (abfd)
d9ad93bc
KR
2600 bfd *abfd;
2601{
9e16fcf1
SG
2602 char *stringtab;
2603
2604 /* Use the saved version if its available. */
2605 if (obj_som_stringtab (abfd) != NULL)
2606 return true;
2607
2608 /* Allocate and read in the string table. */
2609 stringtab = bfd_zalloc (abfd, obj_som_stringtab_size (abfd));
2610 if (stringtab == NULL)
2611 {
2612 bfd_error = no_memory;
2613 return false;
2614 }
2615
2616 if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
2617 {
2618 bfd_error = system_call_error;
2619 return false;
2620 }
2621
2622 if (bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd)
2623 != obj_som_stringtab_size (abfd))
2624 {
2625 bfd_error = system_call_error;
2626 return false;
2627 }
2628
2629 /* Save our results and return success. */
2630 obj_som_stringtab (abfd) = stringtab;
2631 return true;
d9ad93bc
KR
2632}
2633
9e16fcf1
SG
2634/* Return the amount of data (in bytes) required to hold the symbol
2635 table for this object. */
2636
d9ad93bc 2637static unsigned int
9e16fcf1 2638som_get_symtab_upper_bound (abfd)
d9ad93bc 2639 bfd *abfd;
d9ad93bc 2640{
9e16fcf1
SG
2641 if (!som_slurp_symbol_table (abfd))
2642 return 0;
2643
2644 return (bfd_get_symcount (abfd) + 1) * (sizeof (som_symbol_type *));
d9ad93bc
KR
2645}
2646
9e16fcf1
SG
2647/* Convert from a SOM subspace index to a BFD section. */
2648
2649static asection *
2650som_section_from_subspace_index (abfd, index)
2651 bfd *abfd;
2652 unsigned int index;
2653{
2654 asection *section;
2655
2656 for (section = abfd->sections; section != NULL; section = section->next)
2657 if (som_section_data (section)->subspace_index == index)
2658 return section;
2659
2660 /* Should never happen. */
2661 abort();
2662}
2663
2664/* Read and save the symbol table associated with the given BFD. */
2665
d9ad93bc 2666static unsigned int
9e16fcf1 2667som_slurp_symbol_table (abfd)
d9ad93bc 2668 bfd *abfd;
d9ad93bc 2669{
9e16fcf1
SG
2670 int symbol_count = bfd_get_symcount (abfd);
2671 int symsize = sizeof (struct symbol_dictionary_record);
2672 char *stringtab;
2673 struct symbol_dictionary_record *buf, *bufp, *endbufp;
2674 som_symbol_type *sym, *symbase;
2675
2676 /* Return saved value if it exists. */
2677 if (obj_som_symtab (abfd) != NULL)
2678 return true;
2679
2680 /* Sanity checking. Make sure there are some symbols and that
2681 we can read the string table too. */
2682 if (symbol_count == 0)
2683 {
2684 bfd_error = no_symbols;
2685 return false;
2686 }
2687
2688 if (!som_slurp_string_table (abfd))
2689 return false;
2690
2691 stringtab = obj_som_stringtab (abfd);
2692
2693 symbase = (som_symbol_type *)
2694 bfd_zalloc (abfd, symbol_count * sizeof (som_symbol_type));
2695 if (symbase == NULL)
2696 {
2697 bfd_error = no_memory;
2698 return false;
2699 }
2700
2701 /* Read in the external SOM representation. */
2702 buf = alloca (symbol_count * symsize);
2703 if (buf == NULL)
2704 {
2705 bfd_error = no_memory;
2706 return false;
2707 }
2708 if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
2709 {
2710 bfd_error = system_call_error;
2711 return false;
2712 }
2713 if (bfd_read (buf, symbol_count * symsize, 1, abfd)
2714 != symbol_count * symsize)
2715 {
2716 bfd_error = no_symbols;
2717 return (false);
2718 }
2719
2720 /* Iterate over all the symbols and internalize them. */
2721 endbufp = buf + symbol_count;
2722 for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
2723 {
2724
2725 /* I don't think we care about these. */
2726 if (bufp->symbol_type == ST_SYM_EXT
2727 || bufp->symbol_type == ST_ARG_EXT)
2728 continue;
2729
2730 /* Some reasonable defaults. */
2731 sym->symbol.the_bfd = abfd;
2732 sym->symbol.name = bufp->name.n_strx + stringtab;
2733 sym->symbol.value = bufp->symbol_value;
2734 sym->symbol.section = 0;
2735 sym->symbol.flags = 0;
2736
2737 switch (bufp->symbol_type)
2738 {
2739 case ST_ENTRY:
2740 sym->symbol.flags |= BSF_FUNCTION;
2741 sym->symbol.value &= ~0x3;
2742 break;
2743
2744 case ST_PRI_PROG:
2745 case ST_SEC_PROG:
2746 case ST_STUB:
2747 case ST_MILLICODE:
2748 case ST_CODE:
2749 sym->symbol.value &= ~0x3;
2750
2751 default:
2752 break;
2753 }
2754
2755 /* Handle scoping and section information. */
2756 switch (bufp->symbol_scope)
2757 {
2758 /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
2759 so the section associated with this symbol can't be known. */
2760 case SS_EXTERNAL:
2761 case SS_UNSAT:
2762 sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
2763 break;
2764
2765 case SS_UNIVERSAL:
2766 sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
2767 sym->symbol.section
2768 = som_section_from_subspace_index (abfd, bufp->symbol_info);
2769 sym->symbol.value -= sym->symbol.section->vma;
2770 break;
2771
2772#if 0
2773 /* SS_GLOBAL and SS_LOCAL are two names for the same thing.
2774 Sound dumb? It is. */
2775 case SS_GLOBAL:
2776#endif
2777 case SS_LOCAL:
2778 sym->symbol.flags |= BSF_LOCAL;
2779 sym->symbol.section
2780 = som_section_from_subspace_index (abfd, bufp->symbol_info);
2781 sym->symbol.value -= sym->symbol.section->vma;
2782 break;
2783 }
2784
2785 /* Mark symbols left around by the debugger. */
2786 if (strlen (sym->symbol.name) >= 3
2787 && sym->symbol.name[0] == 'L'
2788 && (sym->symbol.name[2] == '$' || sym->symbol.name[3] == '$'))
2789 sym->symbol.flags |= BSF_DEBUGGING;
2790
2791 /* Note increment at bottom of loop, since we skip some symbols
2792 we can not include it as part of the for statement. */
2793 sym++;
2794 }
2795
2796 /* Save our results and return success. */
2797 obj_som_symtab (abfd) = symbase;
2798 return (true);
d9ad93bc
KR
2799}
2800
9e16fcf1
SG
2801/* Canonicalize a SOM symbol table. Return the number of entries
2802 in the symbol table. */
d9ad93bc
KR
2803
2804static unsigned int
9e16fcf1 2805som_get_symtab (abfd, location)
d9ad93bc
KR
2806 bfd *abfd;
2807 asymbol **location;
2808{
9e16fcf1
SG
2809 int i;
2810 som_symbol_type *symbase;
2811
2812 if (!som_slurp_symbol_table (abfd))
2813 return 0;
2814
2815 i = bfd_get_symcount (abfd);
2816 symbase = obj_som_symtab (abfd);
2817
2818 for (; i > 0; i--, location++, symbase++)
2819 *location = &symbase->symbol;
2820
2821 /* Final null pointer. */
2822 *location = 0;
2823 return (bfd_get_symcount (abfd));
d9ad93bc
KR
2824}
2825
9e16fcf1
SG
2826/* Make a SOM symbol. There is nothing special to do here. */
2827
d9ad93bc 2828static asymbol *
9e16fcf1 2829som_make_empty_symbol (abfd)
d9ad93bc
KR
2830 bfd *abfd;
2831{
9e16fcf1
SG
2832 som_symbol_type *new =
2833 (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
2834 if (new == NULL)
2835 {
2836 bfd_error = no_memory;
2837 return 0;
2838 }
d9ad93bc
KR
2839 new->symbol.the_bfd = abfd;
2840
2841 return &new->symbol;
2842}
2843
9e16fcf1
SG
2844/* Print symbol information. */
2845
d9ad93bc 2846static void
9e16fcf1 2847som_print_symbol (ignore_abfd, afile, symbol, how)
d9ad93bc
KR
2848 bfd *ignore_abfd;
2849 PTR afile;
2850 asymbol *symbol;
2851 bfd_print_symbol_type how;
2852{
9e16fcf1
SG
2853 FILE *file = (FILE *) afile;
2854 switch (how)
2855 {
2856 case bfd_print_symbol_name:
2857 fprintf (file, "%s", symbol->name);
2858 break;
2859 case bfd_print_symbol_more:
2860 fprintf (file, "som ");
2861 fprintf_vma (file, symbol->value);
2862 fprintf (file, " %lx", (long) symbol->flags);
2863 break;
2864 case bfd_print_symbol_all:
2865 {
2866 CONST char *section_name;
2867 section_name = symbol->section ? symbol->section->name : "(*none*)";
2868 bfd_print_symbol_vandf ((PTR) file, symbol);
2869 fprintf (file, " %s\t%s", section_name, symbol->name);
2870 break;
2871 }
2872 }
2873}
2874
2875static unsigned int
2876som_get_reloc_upper_bound (abfd, asect)
2877 bfd *abfd;
2878 sec_ptr asect;
2879{
2880 fprintf (stderr, "som_get_reloc_upper_bound unimplemented\n");
d9ad93bc
KR
2881 fflush (stderr);
2882 abort ();
9e16fcf1 2883 return (0);
d9ad93bc
KR
2884}
2885
9e16fcf1
SG
2886static unsigned int
2887som_canonicalize_reloc (abfd, section, relptr, symbols)
2888 bfd *abfd;
2889 sec_ptr section;
2890 arelent **relptr;
2891 asymbol **symbols;
2892{
2893 fprintf (stderr, "som_canonicalize_reloc unimplemented\n");
2894 fflush (stderr);
2895 abort ();
2896}
2897
2898extern bfd_target som_vec;
2899
2900/* A hook to set up object file dependent section information. */
2901
d9ad93bc 2902static boolean
9e16fcf1 2903som_new_section_hook (abfd, newsect)
d9ad93bc
KR
2904 bfd *abfd;
2905 asection *newsect;
2906{
9e16fcf1
SG
2907 newsect->used_by_bfd = (struct som_section_data_struct *)
2908 bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
d9ad93bc
KR
2909 newsect->alignment_power = 3;
2910
9e16fcf1
SG
2911 /* Initialize the subspace_index field to -1 so that it does
2912 not match a subspace with an index of 0. */
2913 som_section_data (newsect)->subspace_index = -1;
2914
d9ad93bc
KR
2915 /* We allow more than three sections internally */
2916 return true;
2917}
2918
40249bfb
JL
2919/* Set backend info for sections which can not be described
2920 in the BFD data structures. */
2921
2922void
2923bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
2924 asection *section;
2925 char defined;
2926 char private;
2927 unsigned char sort_key;
2928 int spnum;
2929{
2930 struct space_dictionary_record *space_dict;
2931
2932 som_section_data (section)->is_space = 1;
2933 space_dict = &som_section_data (section)->space_dict;
2934 space_dict->is_defined = defined;
2935 space_dict->is_private = private;
2936 space_dict->sort_key = sort_key;
2937 space_dict->space_number = spnum;
2938}
2939
2940/* Set backend info for subsections which can not be described
2941 in the BFD data structures. */
2942
2943void
2944bfd_som_set_subsection_attributes (section, container, access,
2945 sort_key, quadrant)
2946 asection *section;
2947 asection *container;
2948 int access;
2949 unsigned char sort_key;
2950 int quadrant;
2951{
2952 struct subspace_dictionary_record *subspace_dict;
2953 som_section_data (section)->is_subspace = 1;
2954 subspace_dict = &som_section_data (section)->subspace_dict;
2955 subspace_dict->access_control_bits = access;
2956 subspace_dict->sort_key = sort_key;
2957 subspace_dict->quadrant = quadrant;
2958 som_section_data (section)->containing_space = container;
2959}
2960
2961/* Set the full SOM symbol type. SOM needs far more symbol information
2962 than any other object file format I'm aware of. It is mandatory
2963 to be able to know if a symbol is an entry point, millicode, data,
2964 code, absolute, storage request, or procedure label. If you get
2965 the symbol type wrong your program will not link. */
2966
2967void
2968bfd_som_set_symbol_type (symbol, type)
2969 asymbol *symbol;
2970 unsigned int type;
2971{
2972 (*som_symbol_data (symbol))->som_type = type;
2973}
2974
2975/* Attach 64bits of unwind information to a symbol (which hopefully
2976 is a function of some kind!). It would be better to keep this
2977 in the R_ENTRY relocation, but there is not enough space. */
2978
2979void
2980bfd_som_attach_unwind_info (symbol, unwind_desc)
2981 asymbol *symbol;
2982 char *unwind_desc;
2983{
2984 (*som_symbol_data (symbol))->unwind = unwind_desc;
2985}
2986
d9ad93bc 2987static boolean
9e16fcf1 2988som_set_section_contents (abfd, section, location, offset, count)
d9ad93bc
KR
2989 bfd *abfd;
2990 sec_ptr section;
2991 PTR location;
2992 file_ptr offset;
2993 bfd_size_type count;
2994{
980bac64
JL
2995 if (abfd->output_has_begun == false)
2996 {
2997 /* Set up fixed parts of the file, space, and subspace headers.
2998 Notify the world that output has begun. */
2999 som_prep_headers (abfd);
3000 abfd->output_has_begun = true;
980bac64
JL
3001 /* Start writing the object file. This include all the string
3002 tables, fixup streams, and other portions of the object file. */
3003 som_begin_writing (abfd);
980bac64
JL
3004 }
3005
3006 /* Only write subspaces which have "real" contents (eg. the contents
3007 are not generated at run time by the OS). */
3008 if (som_section_data (section)->is_subspace != 1
3009 || ((section->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0))
3010 return true;
3011
3012 /* Seek to the proper offset within the object file and write the
3013 data. */
3014 offset += som_section_data (section)->subspace_dict.file_loc_init_value;
3015 if (bfd_seek (abfd, offset, SEEK_SET) == -1)
3016 {
3017 bfd_error = system_call_error;
3018 return false;
3019 }
3020
3021 if (bfd_write ((PTR) location, 1, count, abfd) != count)
3022 {
3023 bfd_error = system_call_error;
3024 return false;
3025 }
3026 return true;
d9ad93bc
KR
3027}
3028
3029static boolean
9e16fcf1 3030som_set_arch_mach (abfd, arch, machine)
d9ad93bc
KR
3031 bfd *abfd;
3032 enum bfd_architecture arch;
3033 unsigned long machine;
3034{
2212ff92 3035 /* Allow any architecture to be supported by the SOM backend */
d9ad93bc
KR
3036 return bfd_default_set_arch_mach (abfd, arch, machine);
3037}
3038
3039static boolean
9e16fcf1 3040som_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
d9ad93bc
KR
3041 functionname_ptr, line_ptr)
3042 bfd *abfd;
3043 asection *section;
3044 asymbol **symbols;
3045 bfd_vma offset;
3046 CONST char **filename_ptr;
3047 CONST char **functionname_ptr;
3048 unsigned int *line_ptr;
3049{
9e16fcf1 3050 fprintf (stderr, "som_find_nearest_line unimplemented\n");
d9ad93bc
KR
3051 fflush (stderr);
3052 abort ();
3053 return (false);
3054}
3055
3056static int
9e16fcf1 3057som_sizeof_headers (abfd, reloc)
d9ad93bc
KR
3058 bfd *abfd;
3059 boolean reloc;
3060{
9e16fcf1 3061 fprintf (stderr, "som_sizeof_headers unimplemented\n");
d9ad93bc
KR
3062 fflush (stderr);
3063 abort ();
3064 return (0);
3065}
3066
3067/* Return information about SOM symbol SYMBOL in RET. */
3068
3069static void
9e16fcf1 3070som_get_symbol_info (ignore_abfd, symbol, ret)
d9ad93bc
KR
3071 bfd *ignore_abfd; /* Ignored. */
3072 asymbol *symbol;
3073 symbol_info *ret;
3074{
3075 bfd_symbol_info (symbol, ret);
3076}
3077
3078/* End of miscellaneous support functions. */
3079
9e16fcf1
SG
3080#define som_bfd_debug_info_start bfd_void
3081#define som_bfd_debug_info_end bfd_void
3082#define som_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
d9ad93bc 3083
9e16fcf1
SG
3084#define som_openr_next_archived_file bfd_generic_openr_next_archived_file
3085#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
3086#define som_slurp_armap bfd_false
3087#define som_slurp_extended_name_table _bfd_slurp_extended_name_table
3088#define som_truncate_arname (void (*)())bfd_nullvoidptr
3089#define som_write_armap 0
d9ad93bc 3090
9e16fcf1
SG
3091#define som_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
3092#define som_close_and_cleanup bfd_generic_close_and_cleanup
3093#define som_get_section_contents bfd_generic_get_section_contents
d9ad93bc 3094
9e16fcf1 3095#define som_bfd_get_relocated_section_contents \
d9ad93bc 3096 bfd_generic_get_relocated_section_contents
9e16fcf1
SG
3097#define som_bfd_relax_section bfd_generic_relax_section
3098#define som_bfd_seclet_link bfd_generic_seclet_link
9e16fcf1 3099#define som_bfd_make_debug_symbol \
d9ad93bc
KR
3100 ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
3101
3102/* Core file support is in the hpux-core backend. */
9e16fcf1
SG
3103#define som_core_file_failing_command _bfd_dummy_core_file_failing_command
3104#define som_core_file_failing_signal _bfd_dummy_core_file_failing_signal
3105#define som_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
d9ad93bc 3106
9e16fcf1 3107bfd_target som_vec =
d9ad93bc 3108{
9e16fcf1
SG
3109 "som", /* name */
3110 bfd_target_som_flavour,
d9ad93bc
KR
3111 true, /* target byte order */
3112 true, /* target headers byte order */
3113 (HAS_RELOC | EXEC_P | /* object flags */
3114 HAS_LINENO | HAS_DEBUG |
40249bfb 3115 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
d9ad93bc 3116 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
9e16fcf1 3117 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
d9ad93bc
KR
3118
3119/* leading_symbol_char: is the first char of a user symbol
9e16fcf1 3120 predictable, and if so what is it */
d9ad93bc
KR
3121 0,
3122 ' ', /* ar_pad_char */
3123 16, /* ar_max_namelen */
3124 3, /* minimum alignment */
9e16fcf1
SG
3125 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
3126 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
3127 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
3128 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
3129 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
3130 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
d9ad93bc 3131 {_bfd_dummy_target,
9e16fcf1 3132 som_object_p, /* bfd_check_format */
d9ad93bc
KR
3133 bfd_generic_archive_p,
3134 _bfd_dummy_target
3135 },
3136 {
3137 bfd_false,
9e16fcf1 3138 som_mkobject,
d9ad93bc
KR
3139 _bfd_generic_mkarchive,
3140 bfd_false
3141 },
3142 {
3143 bfd_false,
9e16fcf1 3144 som_write_object_contents,
d9ad93bc
KR
3145 _bfd_write_archive_contents,
3146 bfd_false,
3147 },
9e16fcf1
SG
3148#undef som
3149 JUMP_TABLE (som),
d9ad93bc
KR
3150 (PTR) 0
3151};
3152
3153#endif /* HOST_HPPAHPUX || HOST_HPPABSD */
This page took 0.286144 seconds and 4 git commands to generate.