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