* Minimal support for reading SOM fixup streams. Allows
[binutils-gdb.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 /* Size (in chars) of the temporary buffers used during fixup and string
71 table writes. */
72
73 #define SOM_TMP_BUFSIZE 8192
74
75
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. */
83 struct 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). */
92 typedef 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
105 /* Forward declarations */
106
107 static boolean som_mkobject PARAMS ((bfd *));
108 static bfd_target * som_object_setup PARAMS ((bfd *,
109 struct header *,
110 struct som_exec_auxhdr *));
111 static asection * make_unique_section PARAMS ((bfd *, CONST char *, int));
112 static boolean setup_sections PARAMS ((bfd *, struct header *));
113 static bfd_target * som_object_p PARAMS ((bfd *));
114 static boolean som_write_object_contents PARAMS ((bfd *));
115 static boolean som_slurp_string_table PARAMS ((bfd *));
116 static unsigned int som_slurp_symbol_table PARAMS ((bfd *));
117 static unsigned int som_get_symtab_upper_bound PARAMS ((bfd *));
118 static unsigned int som_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
119 arelent **, asymbol **));
120 static unsigned int som_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
121 static unsigned int som_set_reloc_info PARAMS ((unsigned char *, unsigned int,
122 arelent *, asection *,
123 asymbol **, boolean));
124 static boolean som_slurp_reloc_table PARAMS ((bfd *, asection *,
125 asymbol **, boolean));
126 static unsigned int som_get_symtab PARAMS ((bfd *, asymbol **));
127 static asymbol * som_make_empty_symbol PARAMS ((bfd *));
128 static void som_print_symbol PARAMS ((bfd *, PTR,
129 asymbol *, bfd_print_symbol_type));
130 static boolean som_new_section_hook PARAMS ((bfd *, asection *));
131 static boolean som_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
132 file_ptr, bfd_size_type));
133 static boolean som_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
134 unsigned long));
135 static boolean som_find_nearest_line PARAMS ((bfd *, asection *,
136 asymbol **, bfd_vma,
137 CONST char **,
138 CONST char **,
139 unsigned int *));
140 static void som_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
141 static asection * som_section_from_subspace_index PARAMS ((bfd *,
142 unsigned int));
143 static int log2 PARAMS ((unsigned int));
144 static bfd_reloc_status_type hppa_som_reloc PARAMS ((bfd *, arelent *,
145 asymbol *, PTR,
146 asection *, bfd *));
147 static void som_initialize_reloc_queue PARAMS ((struct reloc_queue *));
148 static void som_reloc_queue_insert PARAMS ((unsigned char *, unsigned int,
149 struct reloc_queue *));
150 static void som_reloc_queue_fix PARAMS ((struct reloc_queue *, unsigned int));
151 static int som_reloc_queue_find PARAMS ((unsigned char *, unsigned int,
152 struct reloc_queue *));
153 static unsigned char * try_prev_fixup PARAMS ((bfd *, int *, unsigned char *,
154 unsigned int,
155 struct reloc_queue *));
156
157 static unsigned char * som_reloc_skip PARAMS ((bfd *, unsigned int,
158 unsigned char *, unsigned int *,
159 struct reloc_queue *));
160 static unsigned char * som_reloc_addend PARAMS ((bfd *, int, unsigned char *,
161 unsigned int *,
162 struct reloc_queue *));
163 static unsigned char * som_reloc_call PARAMS ((bfd *, unsigned char *,
164 unsigned int *,
165 arelent *, int,
166 struct reloc_queue *));
167 static unsigned long som_count_spaces PARAMS ((bfd *));
168 static unsigned long som_count_subspaces PARAMS ((bfd *));
169 static int compare_syms PARAMS ((asymbol **, asymbol **));
170 static unsigned long som_compute_checksum PARAMS ((bfd *));
171 static boolean som_prep_headers PARAMS ((bfd *));
172 static int som_sizeof_headers PARAMS ((bfd *, boolean));
173 static boolean som_write_headers PARAMS ((bfd *));
174 static boolean som_build_and_write_symbol_table PARAMS ((bfd *));
175 static void som_prep_for_fixups PARAMS ((bfd *, asymbol **, unsigned long));
176 static boolean som_write_fixups PARAMS ((bfd *, unsigned long, unsigned int *));
177 static boolean som_write_space_strings PARAMS ((bfd *, unsigned long,
178 unsigned int *));
179 static boolean som_write_symbol_strings PARAMS ((bfd *, unsigned long,
180 asymbol **, unsigned int,
181 unsigned *));
182 static boolean som_begin_writing PARAMS ((bfd *));
183 static const reloc_howto_type * som_bfd_reloc_type_lookup
184 PARAMS ((bfd_arch_info_type *, bfd_reloc_code_real_type));
185
186 /* About the relocation formatting table...
187
188 There are 256 entries in the table, one for each possible
189 relocation opcode available in SOM. We index the table by
190 the relocation opcode. The names and operations are those
191 defined by a.out_800 (4).
192
193 Right now this table is only used to count and perform minimal
194 processing on relocation streams so that they can be internalized
195 into BFD and symbolically printed by utilities. To make actual use
196 of them would be much more difficult, BFD's concept of relocations
197 is far too simple to handle SOM relocations. The basic assumption
198 that a relocation can be completely processed independent of other
199 relocations before an object file is written is invalid for SOM.
200
201 The SOM relocations are meant to be processed as a stream, they
202 specify copying of data from the input section to the output section
203 while possibly modifying the data in some manner. They also can
204 specify that a variable number of zeros or uninitialized data be
205 inserted on in the output segment at the current offset. Some
206 relocations specify that some previous relocation be re-applied at
207 the current location in the input/output sections. And finally a number
208 of relocations have effects on other sections (R_ENTRY, R_EXIT,
209 R_UNWIND_AUX and a variety of others). There isn't even enough room
210 in the BFD relocation data structure to store enough information to
211 perform all the relocations.
212
213 Each entry in the table has three fields.
214
215 The first entry is an index into this "class" of relocations. This
216 index can then be used as a variable within the relocation itself.
217
218 The second field is a format string which actually controls processing
219 of the relocation. It uses a simple postfix machine to do calculations
220 based on variables/constants found in the string and the relocation
221 stream.
222
223 The third field specifys whether or not this relocation may use
224 a constant (V) from the previous R_DATA_OVERRIDE rather than a constant
225 stored in the instruction.
226
227 Variables:
228
229 L = input space byte count
230 D = index into class of relocations
231 M = output space byte count
232 N = statement number (unused?)
233 O = stack operation
234 R = parameter relocation bits
235 S = symbol index
236 U = 64 bits of stack unwind and frame size info (we only keep 32 bits)
237 V = a literal constant (usually used in the next relocation)
238 P = a previous relocation
239
240 Lower case letters (starting with 'b') refer to following
241 bytes in the relocation stream. 'b' is the next 1 byte,
242 c is the next 2 bytes, d is the next 3 bytes, etc...
243 This is the variable part of the relocation entries that
244 makes our life a living hell.
245
246 numerical constants are also used in the format string. Note
247 the constants are represented in decimal.
248
249 '+', "*" and "=" represents the obvious postfix operators.
250 '<' represents a left shift.
251
252 Stack Operations:
253
254 Parameter Relocation Bits:
255
256 Unwind Entries:
257
258 Previous Relocations: The index field represents which in the queue
259 of 4 previous fixups should be re-applied.
260
261 Literal Constants: These are generally used to represent addend
262 parts of relocations when these constants are not stored in the
263 fields of the instructions themselves. For example the instruction
264 addil foo-$global$-0x1234 would use an override for "0x1234" rather
265 than storing it into the addil itself. */
266
267 struct fixup_format
268 {
269 int D;
270 char *format;
271 };
272
273 static const struct fixup_format som_fixup_formats[256] =
274 {
275 /* R_NO_RELOCATION */
276 0, "LD1+4*=", /* 0x00 */
277 1, "LD1+4*=", /* 0x01 */
278 2, "LD1+4*=", /* 0x02 */
279 3, "LD1+4*=", /* 0x03 */
280 4, "LD1+4*=", /* 0x04 */
281 5, "LD1+4*=", /* 0x05 */
282 6, "LD1+4*=", /* 0x06 */
283 7, "LD1+4*=", /* 0x07 */
284 8, "LD1+4*=", /* 0x08 */
285 9, "LD1+4*=", /* 0x09 */
286 10, "LD1+4*=", /* 0x0a */
287 11, "LD1+4*=", /* 0x0b */
288 12, "LD1+4*=", /* 0x0c */
289 13, "LD1+4*=", /* 0x0d */
290 14, "LD1+4*=", /* 0x0e */
291 15, "LD1+4*=", /* 0x0f */
292 16, "LD1+4*=", /* 0x10 */
293 17, "LD1+4*=", /* 0x11 */
294 18, "LD1+4*=", /* 0x12 */
295 19, "LD1+4*=", /* 0x13 */
296 20, "LD1+4*=", /* 0x14 */
297 21, "LD1+4*=", /* 0x15 */
298 22, "LD1+4*=", /* 0x16 */
299 23, "LD1+4*=", /* 0x17 */
300 0, "LD8<b+1+4*=", /* 0x18 */
301 1, "LD8<b+1+4*=", /* 0x19 */
302 2, "LD8<b+1+4*=", /* 0x1a */
303 3, "LD8<b+1+4*=", /* 0x1b */
304 0, "LD16<c+1+4*=", /* 0x1c */
305 1, "LD16<c+1+4*=", /* 0x1d */
306 2, "LD16<c+1+4*=", /* 0x1e */
307 0, "Ld1+=", /* 0x1f */
308 /* R_ZEROES */
309 0, "Lb1+4*=", /* 0x20 */
310 1, "Ld1+=", /* 0x21 */
311 /* R_UNINIT */
312 0, "Lb1+4*=", /* 0x22 */
313 1, "Ld1+=", /* 0x23 */
314 /* R_RELOCATION */
315 0, "L4=", /* 0x24 */
316 /* R_DATA_ONE_SYMBOL */
317 0, "L4=Sb=", /* 0x25 */
318 1, "L4=Sd=", /* 0x26 */
319 /* R_DATA_PLEBEL */
320 0, "L4=Sb=", /* 0x27 */
321 1, "L4=Sd=", /* 0x28 */
322 /* R_SPACE_REF */
323 0, "L4=", /* 0x29 */
324 /* R_REPEATED_INIT */
325 0, "L4=Mb1+4*=", /* 0x2a */
326 1, "Lb4*=Mb1+L*=", /* 0x2b */
327 2, "Lb4*=Md1+4*=", /* 0x2c */
328 3, "Ld1+=Me1+=", /* 0x2d */
329 /* R_RESERVED */
330 0, "", /* 0x2e */
331 0, "", /* 0x2f */
332 /* R_PCREL_CALL */
333 0, "L4=RD=Sb=", /* 0x30 */
334 1, "L4=RD=Sb=", /* 0x31 */
335 2, "L4=RD=Sb=", /* 0x32 */
336 3, "L4=RD=Sb=", /* 0x33 */
337 4, "L4=RD=Sb=", /* 0x34 */
338 5, "L4=RD=Sb=", /* 0x35 */
339 6, "L4=RD=Sb=", /* 0x36 */
340 7, "L4=RD=Sb=", /* 0x37 */
341 8, "L4=RD=Sb=", /* 0x38 */
342 9, "L4=RD=Sb=", /* 0x39 */
343 0, "L4=RD8<b+=Sb=",/* 0x3a */
344 1, "L4=RD8<b+=Sb=",/* 0x3b */
345 0, "L4=RD8<b+=Sd=",/* 0x3c */
346 1, "L4=RD8<b+=Sd=",/* 0x3d */
347 /* R_RESERVED */
348 0, "", /* 0x3e */
349 0, "", /* 0x3f */
350 /* R_ABS_CALL */
351 0, "L4=RD=Sb=", /* 0x40 */
352 1, "L4=RD=Sb=", /* 0x41 */
353 2, "L4=RD=Sb=", /* 0x42 */
354 3, "L4=RD=Sb=", /* 0x43 */
355 4, "L4=RD=Sb=", /* 0x44 */
356 5, "L4=RD=Sb=", /* 0x45 */
357 6, "L4=RD=Sb=", /* 0x46 */
358 7, "L4=RD=Sb=", /* 0x47 */
359 8, "L4=RD=Sb=", /* 0x48 */
360 9, "L4=RD=Sb=", /* 0x49 */
361 0, "L4=RD8<b+=Sb=",/* 0x4a */
362 1, "L4=RD8<b+=Sb=",/* 0x4b */
363 0, "L4=RD8<b+=Sd=",/* 0x4c */
364 1, "L4=RD8<b+=Sd=",/* 0x4d */
365 /* R_RESERVED */
366 0, "", /* 0x4e */
367 0, "", /* 0x4f */
368 /* R_DP_RELATIVE */
369 0, "L4=SD=", /* 0x50 */
370 1, "L4=SD=", /* 0x51 */
371 2, "L4=SD=", /* 0x52 */
372 3, "L4=SD=", /* 0x53 */
373 4, "L4=SD=", /* 0x54 */
374 5, "L4=SD=", /* 0x55 */
375 6, "L4=SD=", /* 0x56 */
376 7, "L4=SD=", /* 0x57 */
377 8, "L4=SD=", /* 0x58 */
378 9, "L4=SD=", /* 0x59 */
379 10, "L4=SD=", /* 0x5a */
380 11, "L4=SD=", /* 0x5b */
381 12, "L4=SD=", /* 0x5c */
382 13, "L4=SD=", /* 0x5d */
383 14, "L4=SD=", /* 0x5e */
384 15, "L4=SD=", /* 0x5f */
385 16, "L4=SD=", /* 0x60 */
386 17, "L4=SD=", /* 0x61 */
387 18, "L4=SD=", /* 0x62 */
388 19, "L4=SD=", /* 0x63 */
389 20, "L4=SD=", /* 0x64 */
390 21, "L4=SD=", /* 0x65 */
391 22, "L4=SD=", /* 0x66 */
392 23, "L4=SD=", /* 0x67 */
393 24, "L4=SD=", /* 0x68 */
394 25, "L4=SD=", /* 0x69 */
395 26, "L4=SD=", /* 0x6a */
396 27, "L4=SD=", /* 0x6b */
397 28, "L4=SD=", /* 0x6c */
398 29, "L4=SD=", /* 0x6d */
399 30, "L4=SD=", /* 0x6e */
400 31, "L4=SD=", /* 0x6f */
401 32, "L4=Sb=", /* 0x70 */
402 33, "L4=Sd=", /* 0x71 */
403 /* R_RESERVED */
404 0, "", /* 0x72 */
405 0, "", /* 0x73 */
406 0, "", /* 0x74 */
407 0, "", /* 0x75 */
408 0, "", /* 0x76 */
409 0, "", /* 0x77 */
410 /* R_DLT_REL */
411 0, "L4=Sb=", /* 0x78 */
412 1, "L4=Sd=", /* 0x79 */
413 /* R_RESERVED */
414 0, "", /* 0x7a */
415 0, "", /* 0x7b */
416 0, "", /* 0x7c */
417 0, "", /* 0x7d */
418 0, "", /* 0x7e */
419 0, "", /* 0x7f */
420 /* R_CODE_ONE_SYMBOL */
421 0, "L4=SD=", /* 0x80 */
422 1, "L4=SD=", /* 0x81 */
423 2, "L4=SD=", /* 0x82 */
424 3, "L4=SD=", /* 0x83 */
425 4, "L4=SD=", /* 0x84 */
426 5, "L4=SD=", /* 0x85 */
427 6, "L4=SD=", /* 0x86 */
428 7, "L4=SD=", /* 0x87 */
429 8, "L4=SD=", /* 0x88 */
430 9, "L4=SD=", /* 0x89 */
431 10, "L4=SD=", /* 0x8q */
432 11, "L4=SD=", /* 0x8b */
433 12, "L4=SD=", /* 0x8c */
434 13, "L4=SD=", /* 0x8d */
435 14, "L4=SD=", /* 0x8e */
436 15, "L4=SD=", /* 0x8f */
437 16, "L4=SD=", /* 0x90 */
438 17, "L4=SD=", /* 0x91 */
439 18, "L4=SD=", /* 0x92 */
440 19, "L4=SD=", /* 0x93 */
441 20, "L4=SD=", /* 0x94 */
442 21, "L4=SD=", /* 0x95 */
443 22, "L4=SD=", /* 0x96 */
444 23, "L4=SD=", /* 0x97 */
445 24, "L4=SD=", /* 0x98 */
446 25, "L4=SD=", /* 0x99 */
447 26, "L4=SD=", /* 0x9a */
448 27, "L4=SD=", /* 0x9b */
449 28, "L4=SD=", /* 0x9c */
450 29, "L4=SD=", /* 0x9d */
451 30, "L4=SD=", /* 0x9e */
452 31, "L4=SD=", /* 0x9f */
453 32, "L4=Sb=", /* 0xa0 */
454 33, "L4=Sd=", /* 0xa1 */
455 /* R_RESERVED */
456 0, "", /* 0xa2 */
457 0, "", /* 0xa3 */
458 0, "", /* 0xa4 */
459 0, "", /* 0xa5 */
460 0, "", /* 0xa6 */
461 0, "", /* 0xa7 */
462 0, "", /* 0xa8 */
463 0, "", /* 0xa9 */
464 0, "", /* 0xaa */
465 0, "", /* 0xab */
466 0, "", /* 0xac */
467 0, "", /* 0xad */
468 /* R_MILLI_REL */
469 0, "L4=Sb=", /* 0xae */
470 1, "L4=Sd=", /* 0xaf */
471 /* R_CODE_PLABEL */
472 0, "L4=Sb=", /* 0xb0 */
473 1, "L4=Sd=", /* 0xb1 */
474 /* R_BREAKPOINT */
475 0, "L4=", /* 0xb2 */
476 /* R_ENTRY */
477 0, "Ui=", /* 0xb3 */
478 1, "Uf=", /* 0xb4 */
479 /* R_ALT_ENTRY */
480 0, "", /* 0xb5 */
481 /* R_EXIT */
482 0, "", /* 0xb6 */
483 /* R_BEGIN_TRY */
484 0, "", /* 0xb7 */
485 /* R_END_TRY */
486 0, "R0=", /* 0xb8 */
487 1, "Rb4*=", /* 0xb9 */
488 2, "Rd4*=", /* 0xba */
489 /* R_BEGIN_BRTAB */
490 0, "", /* 0xbb */
491 /* R_END_BRTAB */
492 0, "", /* 0xbc */
493 /* R_STATEMENT */
494 0, "Nb=", /* 0xbd */
495 1, "Nc=", /* 0xbe */
496 2, "Nd=", /* 0xbf */
497 /* R_DATA_EXPR */
498 0, "L4=", /* 0xc0 */
499 /* R_CODE_EXPR */
500 0, "L4=", /* 0xc1 */
501 /* R_FSEL */
502 0, "", /* 0xc2 */
503 /* R_LSEL */
504 0, "", /* 0xc3 */
505 /* R_RSEL */
506 0, "", /* 0xc4 */
507 /* R_N_MODE */
508 0, "", /* 0xc5 */
509 /* R_S_MODE */
510 0, "", /* 0xc6 */
511 /* R_D_MODE */
512 0, "", /* 0xc7 */
513 /* R_R_MODE */
514 0, "", /* 0xc8 */
515 /* R_DATA_OVERRIDE */
516 0, "V0=", /* 0xc9 */
517 1, "Vb=", /* 0xca */
518 2, "Vc=", /* 0xcb */
519 3, "Vd=", /* 0xcc */
520 4, "Ve=", /* 0xcd */
521 /* R_TRANSLATED */
522 0, "", /* 0xce */
523 /* R_RESERVED */
524 0, "", /* 0xcf */
525 /* R_COMP1 */
526 0, "Ob=", /* 0xd0 */
527 /* R_COMP2 */
528 0, "Ob=Sd=", /* 0xd1 */
529 /* R_COMP3 */
530 0, "Ob=Ve=", /* 0xd2 */
531 /* R_PREV_FIXUP */
532 0, "P", /* 0xd3 */
533 1, "P", /* 0xd4 */
534 2, "P", /* 0xd5 */
535 3, "P", /* 0xd6 */
536 /* R_RESERVED */
537 0, "", /* 0xd7 */
538 0, "", /* 0xd8 */
539 0, "", /* 0xd9 */
540 0, "", /* 0xda */
541 0, "", /* 0xdb */
542 0, "", /* 0xdc */
543 0, "", /* 0xdd */
544 0, "", /* 0xde */
545 0, "", /* 0xdf */
546 0, "", /* 0xe0 */
547 0, "", /* 0xe1 */
548 0, "", /* 0xe2 */
549 0, "", /* 0xe3 */
550 0, "", /* 0xe4 */
551 0, "", /* 0xe5 */
552 0, "", /* 0xe6 */
553 0, "", /* 0xe7 */
554 0, "", /* 0xe8 */
555 0, "", /* 0xe9 */
556 0, "", /* 0xea */
557 0, "", /* 0xeb */
558 0, "", /* 0xec */
559 0, "", /* 0xed */
560 0, "", /* 0xee */
561 0, "", /* 0xef */
562 0, "", /* 0xf0 */
563 0, "", /* 0xf1 */
564 0, "", /* 0xf2 */
565 0, "", /* 0xf3 */
566 0, "", /* 0xf4 */
567 0, "", /* 0xf5 */
568 0, "", /* 0xf6 */
569 0, "", /* 0xf7 */
570 0, "", /* 0xf8 */
571 0, "", /* 0xf9 */
572 0, "", /* 0xfa */
573 0, "", /* 0xfb */
574 0, "", /* 0xfc */
575 0, "", /* 0xfd */
576 0, "", /* 0xfe */
577 0, "", /* 0xff */
578 };
579
580 static const int comp1_opcodes[] =
581 {
582 0x00,
583 0x40,
584 0x41,
585 0x42,
586 0x43,
587 0x44,
588 0x45,
589 0x46,
590 0x47,
591 0x48,
592 0x49,
593 0x4a,
594 0x4b,
595 0x60,
596 0x80,
597 0xa0,
598 0xc0,
599 -1
600 };
601
602 static const int comp2_opcodes[] =
603 {
604 0x00,
605 0x80,
606 0x82,
607 0xc0,
608 -1
609 };
610
611 static const int comp3_opcodes[] =
612 {
613 0x00,
614 0x02,
615 -1
616 };
617
618 static reloc_howto_type som_hppa_howto_table[] =
619 {
620 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
621 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
622 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
623 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
624 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
625 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
626 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
627 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
628 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
629 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
630 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
631 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
632 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
633 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
634 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
635 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
636 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
637 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
638 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
639 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
640 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
641 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
642 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
643 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
644 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
645 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
646 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
647 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
648 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
649 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
650 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
651 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
652 {R_ZEROES, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ZEROES"},
653 {R_ZEROES, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ZEROES"},
654 {R_UNINIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_UNINIT"},
655 {R_UNINIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_UNINIT"},
656 {R_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RELOCATION"},
657 {R_DATA_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_ONE_SYMBOL"},
658 {R_DATA_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_ONE_SYMBOL"},
659 {R_DATA_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_PLABEL"},
660 {R_DATA_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_PLABEL"},
661 {R_SPACE_REF, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SPACE_REF"},
662 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
663 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
664 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
665 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
666 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
667 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
668 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
669 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
670 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
671 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
672 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
673 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
674 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
675 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
676 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
677 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
678 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
679 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
680 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
681 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
682 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
683 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
684 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
685 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
686 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
687 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
688 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
689 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
690 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
691 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
692 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
693 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
694 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
695 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
696 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
697 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
698 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
699 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
700 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
701 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
702 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
703 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
704 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
705 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
706 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
707 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
708 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
709 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
710 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
711 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
712 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
713 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
714 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
715 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
716 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
717 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
718 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
719 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
720 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
721 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
722 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
723 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
724 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
725 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
726 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
727 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
728 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
729 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
730 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
731 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
732 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
733 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
734 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
735 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
736 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
737 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
738 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
739 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
740 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
741 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
742 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
743 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
744 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
745 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
746 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
747 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
748 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
749 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
750 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
751 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
752 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
753 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
754 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
755 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
756 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
757 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
758 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
759 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
760 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
761 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
762 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
763 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
764 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
765 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
766 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
767 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
768 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
769 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
770 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
771 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
772 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
773 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
774 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
775 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
776 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
777 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
778 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
779 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
780 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
781 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
782 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
783 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
784 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
785 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
786 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
787 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
788 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
789 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
790 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
791 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
792 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
793 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
794 {R_MILLI_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_MILLI_REL"},
795 {R_MILLI_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_MILLI_REL"},
796 {R_CODE_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_PLABEL"},
797 {R_CODE_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_PLABEL"},
798 {R_BREAKPOINT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BREAKPOINT"},
799 {R_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ENTRY"},
800 {R_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ENTRY"},
801 {R_ALT_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ALT_ENTRY"},
802 {R_EXIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_EXIT"},
803 {R_BEGIN_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BEGIN_TRY"},
804 {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
805 {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
806 {R_BEGIN_BRTAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BEGIN_BRTAB"},
807 {R_END_BRTAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_BRTAB"},
808 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
809 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
810 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
811 {R_DATA_EXPR, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_EXPR"},
812 {R_CODE_EXPR, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_EXPR"},
813 {R_FSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_FSEL"},
814 {R_LSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LSEL"},
815 {R_RSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RSEL"},
816 {R_N_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N_MODE"},
817 {R_S_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_S_MODE"},
818 {R_D_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_D_MODE"},
819 {R_R_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_R_MODE"},
820 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
821 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
822 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
823 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
824 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
825 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
826 {R_TRANSLATED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_TRANSLATED"},
827 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
828 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
829 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
830 {R_COMP1, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP1"},
831 {R_COMP2, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP2"},
832 {R_COMP3, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP3"},
833 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
834 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
835 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
836 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
837 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
838 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
839 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
840 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
841 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
842 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
843 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
844 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
845 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
846 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
847 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
848 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
849 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
850 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
851 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
852 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
853 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
854 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
855 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
856 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
857 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
858 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
859 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
860 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
861 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
862 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
863 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
864 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
865 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
866 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
867 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
868 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
869 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
870 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
871 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
872 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
873 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
874 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
875 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
876 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
877 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"}};
878
879
880 /* Initialize the SOM relocation queue. By definition the queue holds
881 the last four multibyte fixups. */
882
883 static void
884 som_initialize_reloc_queue (queue)
885 struct reloc_queue *queue;
886 {
887 queue[0].reloc = NULL;
888 queue[0].size = 0;
889 queue[1].reloc = NULL;
890 queue[1].size = 0;
891 queue[2].reloc = NULL;
892 queue[2].size = 0;
893 queue[3].reloc = NULL;
894 queue[3].size = 0;
895 }
896
897 /* Insert a new relocation into the relocation queue. */
898
899 static void
900 som_reloc_queue_insert (p, size, queue)
901 unsigned char *p;
902 unsigned int size;
903 struct reloc_queue *queue;
904 {
905 queue[3].reloc = queue[2].reloc;
906 queue[3].size = queue[2].size;
907 queue[2].reloc = queue[1].reloc;
908 queue[2].size = queue[1].size;
909 queue[1].reloc = queue[0].reloc;
910 queue[1].size = queue[0].size;
911 queue[0].reloc = p;
912 queue[0].size = size;
913 }
914
915 /* When an entry in the relocation queue is reused, the entry moves
916 to the front of the queue. */
917
918 static void
919 som_reloc_queue_fix (queue, index)
920 struct reloc_queue *queue;
921 unsigned int index;
922 {
923 if (index == 0)
924 return;
925
926 if (index == 1)
927 {
928 unsigned char *tmp1 = queue[0].reloc;
929 unsigned int tmp2 = queue[0].size;
930 queue[0].reloc = queue[1].reloc;
931 queue[0].size = queue[1].size;
932 queue[1].reloc = tmp1;
933 queue[1].size = tmp2;
934 return;
935 }
936
937 if (index == 2)
938 {
939 unsigned char *tmp1 = queue[0].reloc;
940 unsigned int tmp2 = queue[0].size;
941 queue[0].reloc = queue[2].reloc;
942 queue[0].size = queue[2].size;
943 queue[2].reloc = queue[1].reloc;
944 queue[2].size = queue[1].size;
945 queue[1].reloc = tmp1;
946 queue[1].size = tmp2;
947 return;
948 }
949
950 if (index == 3)
951 {
952 unsigned char *tmp1 = queue[0].reloc;
953 unsigned int tmp2 = queue[0].size;
954 queue[0].reloc = queue[3].reloc;
955 queue[0].size = queue[3].size;
956 queue[3].reloc = queue[2].reloc;
957 queue[3].size = queue[2].size;
958 queue[2].reloc = queue[1].reloc;
959 queue[2].size = queue[1].size;
960 queue[1].reloc = tmp1;
961 queue[1].size = tmp2;
962 return;
963 }
964 abort();
965 }
966
967 /* Search for a particular relocation in the relocation queue. */
968
969 static int
970 som_reloc_queue_find (p, size, queue)
971 unsigned char *p;
972 unsigned int size;
973 struct reloc_queue *queue;
974 {
975 if (!bcmp (p, queue[0].reloc, size)
976 && size == queue[0].size)
977 return 0;
978 if (!bcmp (p, queue[1].reloc, size)
979 && size == queue[1].size)
980 return 1;
981 if (!bcmp (p, queue[2].reloc, size)
982 && size == queue[2].size)
983 return 2;
984 if (!bcmp (p, queue[3].reloc, size)
985 && size == queue[3].size)
986 return 3;
987 return -1;
988 }
989
990 static unsigned char *
991 try_prev_fixup (abfd, subspace_reloc_sizep, p, size, queue)
992 bfd *abfd;
993 int *subspace_reloc_sizep;
994 unsigned char *p;
995 unsigned int size;
996 struct reloc_queue *queue;
997 {
998 int queue_index = som_reloc_queue_find (p, size, queue);
999
1000 if (queue_index != -1)
1001 {
1002 /* Found this in a previous fixup. Undo the fixup we
1003 just built and use R_PREV_FIXUP instead. We saved
1004 a total of size - 1 bytes in the fixup stream. */
1005 bfd_put_8 (abfd, R_PREV_FIXUP + queue_index, p);
1006 p += 1;
1007 *subspace_reloc_sizep += 1;
1008 som_reloc_queue_fix (queue, queue_index);
1009 }
1010 else
1011 {
1012 som_reloc_queue_insert (p, size, queue);
1013 *subspace_reloc_sizep += size;
1014 p += size;
1015 }
1016 return p;
1017 }
1018
1019 /* Emit the proper R_NO_RELOCATION fixups to map the next SKIP
1020 bytes without any relocation. Update the size of the subspace
1021 relocation stream via SUBSPACE_RELOC_SIZE_P; also return the
1022 current pointer into the relocation stream. */
1023
1024 static unsigned char *
1025 som_reloc_skip (abfd, skip, p, subspace_reloc_sizep, queue)
1026 bfd *abfd;
1027 unsigned int skip;
1028 unsigned char *p;
1029 unsigned int *subspace_reloc_sizep;
1030 struct reloc_queue *queue;
1031 {
1032 /* Use a 4 byte R_NO_RELOCATION entry with a maximal value
1033 then R_PREV_FIXUPs to get the difference down to a
1034 reasonable size. */
1035 if (skip >= 0x1000000)
1036 {
1037 skip -= 0x1000000;
1038 bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
1039 bfd_put_8 (abfd, 0xff, p + 1);
1040 bfd_put_16 (abfd, 0xffff, p + 2);
1041 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
1042 while (skip >= 0x1000000)
1043 {
1044 skip -= 0x1000000;
1045 bfd_put_8 (abfd, R_PREV_FIXUP, p);
1046 p++;
1047 *subspace_reloc_sizep += 1;
1048 /* No need to adjust queue here since we are repeating the
1049 most recent fixup. */
1050 }
1051 }
1052
1053 /* The difference must be less than 0x1000000. Use one
1054 more R_NO_RELOCATION entry to get to the right difference. */
1055 if ((skip & 3) == 0 && skip <= 0xc0000 && skip > 0)
1056 {
1057 /* Difference can be handled in a simple single-byte
1058 R_NO_RELOCATION entry. */
1059 if (skip <= 0x60)
1060 {
1061 bfd_put_8 (abfd, R_NO_RELOCATION + (skip >> 2) - 1, p);
1062 *subspace_reloc_sizep += 1;
1063 p++;
1064 }
1065 /* Handle it with a two byte R_NO_RELOCATION entry. */
1066 else if (skip <= 0x1000)
1067 {
1068 bfd_put_8 (abfd, R_NO_RELOCATION + 24 + (((skip >> 2) - 1) >> 8), p);
1069 bfd_put_8 (abfd, (skip >> 2) - 1, p + 1);
1070 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1071 }
1072 /* Handle it with a three byte R_NO_RELOCATION entry. */
1073 else
1074 {
1075 bfd_put_8 (abfd, R_NO_RELOCATION + 28 + (((skip >> 2) - 1) >> 16), p);
1076 bfd_put_16 (abfd, (skip >> 2) - 1, p + 1);
1077 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1078 }
1079 }
1080 /* Ugh. Punt and use a 4 byte entry. */
1081 else if (skip > 0)
1082 {
1083 bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
1084 bfd_put_8 (abfd, skip >> 16, p + 1);
1085 bfd_put_16 (abfd, skip, p + 2);
1086 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
1087 }
1088 return p;
1089 }
1090
1091 /* Emit the proper R_DATA_OVERRIDE fixups to handle a nonzero addend
1092 from a BFD relocation. Update the size of the subspace relocation
1093 stream via SUBSPACE_RELOC_SIZE_P; also return the current pointer
1094 into the relocation stream. */
1095
1096 static unsigned char *
1097 som_reloc_addend (abfd, addend, p, subspace_reloc_sizep, queue)
1098 bfd *abfd;
1099 int addend;
1100 unsigned char *p;
1101 unsigned int *subspace_reloc_sizep;
1102 struct reloc_queue *queue;
1103 {
1104 if ((unsigned)(addend) + 0x80 < 0x100)
1105 {
1106 bfd_put_8 (abfd, R_DATA_OVERRIDE + 1, p);
1107 bfd_put_8 (abfd, addend, p + 1);
1108 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1109 }
1110 else if ((unsigned) (addend) + 0x8000 < 0x10000)
1111 {
1112 bfd_put_8 (abfd, R_DATA_OVERRIDE + 2, p);
1113 bfd_put_16 (abfd, addend, p + 1);
1114 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1115 }
1116 else if ((unsigned) (addend) + 0x800000 < 0x1000000)
1117 {
1118 bfd_put_8 (abfd, R_DATA_OVERRIDE + 3, p);
1119 bfd_put_8 (abfd, addend >> 16, p + 1);
1120 bfd_put_16 (abfd, addend, p + 2);
1121 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
1122 }
1123 else
1124 {
1125 bfd_put_8 (abfd, R_DATA_OVERRIDE + 4, p);
1126 bfd_put_32 (abfd, addend, p + 1);
1127 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
1128 }
1129 return p;
1130 }
1131
1132 /* Handle a single function call relocation. */
1133
1134 static unsigned char *
1135 som_reloc_call (abfd, p, subspace_reloc_sizep, bfd_reloc, sym_num, queue)
1136 bfd *abfd;
1137 unsigned char *p;
1138 unsigned int *subspace_reloc_sizep;
1139 arelent *bfd_reloc;
1140 int sym_num;
1141 struct reloc_queue *queue;
1142 {
1143 int arg_bits = HPPA_R_ARG_RELOC (bfd_reloc->addend);
1144 int rtn_bits = arg_bits & 0x3;
1145 int type, done = 0;
1146
1147 /* You'll never believe all this is necessary to handle relocations
1148 for function calls. Having to compute and pack the argument
1149 relocation bits is the real nightmare.
1150
1151 If you're interested in how this works, just forget it. You really
1152 do not want to know about this braindamage. */
1153
1154 /* First see if this can be done with a "simple" relocation. Simple
1155 relocations have a symbol number < 0x100 and have simple encodings
1156 of argument relocations. */
1157
1158 if (sym_num < 0x100)
1159 {
1160 switch (arg_bits)
1161 {
1162 case 0:
1163 case 1:
1164 type = 0;
1165 break;
1166 case 1 << 8:
1167 case 1 << 8 | 1:
1168 type = 1;
1169 break;
1170 case 1 << 8 | 1 << 6:
1171 case 1 << 8 | 1 << 6 | 1:
1172 type = 2;
1173 break;
1174 case 1 << 8 | 1 << 6 | 1 << 4:
1175 case 1 << 8 | 1 << 6 | 1 << 4 | 1:
1176 type = 3;
1177 break;
1178 case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2:
1179 case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1:
1180 type = 4;
1181 break;
1182 default:
1183 /* Not one of the easy encodings. This will have to be
1184 handled by the more complex code below. */
1185 type = -1;
1186 break;
1187 }
1188 if (type != -1)
1189 {
1190 /* Account for the return value too. */
1191 if (rtn_bits)
1192 type += 5;
1193
1194 /* Emit a 2 byte relocation. Then see if it can be handled
1195 with a relocation which is already in the relocation queue. */
1196 bfd_put_8 (abfd, bfd_reloc->howto->type + type, p);
1197 bfd_put_8 (abfd, sym_num, p + 1);
1198 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1199 done = 1;
1200 }
1201 }
1202
1203 /* If this could not be handled with a simple relocation, then do a hard
1204 one. Hard relocations occur if the symbol number was too high or if
1205 the encoding of argument relocation bits is too complex. */
1206 if (! done)
1207 {
1208 /* Don't ask about these magic sequences. I took them straight
1209 from gas-1.36 which took them from the a.out man page. */
1210 type = rtn_bits;
1211 if ((arg_bits >> 6 & 0xf) == 0xe)
1212 type += 9 * 40;
1213 else
1214 type += (3 * (arg_bits >> 8 & 3) + (arg_bits >> 6 & 3)) * 40;
1215 if ((arg_bits >> 2 & 0xf) == 0xe)
1216 type += 9 * 4;
1217 else
1218 type += (3 * (arg_bits >> 4 & 3) + (arg_bits >> 2 & 3)) * 4;
1219
1220 /* Output the first two bytes of the relocation. These describe
1221 the length of the relocation and encoding style. */
1222 bfd_put_8 (abfd, bfd_reloc->howto->type + 10
1223 + 2 * (sym_num >= 0x100) + (type >= 0x100),
1224 p);
1225 bfd_put_8 (abfd, type, p + 1);
1226
1227 /* Now output the symbol index and see if this bizarre relocation
1228 just happened to be in the relocation queue. */
1229 if (sym_num < 0x100)
1230 {
1231 bfd_put_8 (abfd, sym_num, p + 2);
1232 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1233 }
1234 else
1235 {
1236 bfd_put_8 (abfd, sym_num >> 16, p + 2);
1237 bfd_put_16 (abfd, sym_num, p + 3);
1238 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
1239 }
1240 }
1241 return p;
1242 }
1243
1244
1245 /* Return the logarithm of X, base 2, considering X unsigned.
1246 Abort if X is not a power of two -- this should never happen (FIXME:
1247 It will happen on corrupt executables. GDB should give an error, not
1248 a coredump, in that case). */
1249
1250 static int
1251 log2 (x)
1252 unsigned int x;
1253 {
1254 int log = 0;
1255
1256 /* Test for 0 or a power of 2. */
1257 if (x == 0 || x != (x & -x))
1258 abort();
1259
1260 while ((x >>= 1) != 0)
1261 log++;
1262 return log;
1263 }
1264
1265 static bfd_reloc_status_type
1266 hppa_som_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd)
1267 bfd *abfd;
1268 arelent *reloc_entry;
1269 asymbol *symbol_in;
1270 PTR data;
1271 asection *input_section;
1272 bfd *output_bfd;
1273 {
1274 if (output_bfd)
1275 {
1276 reloc_entry->address += input_section->output_offset;
1277 return bfd_reloc_ok;
1278 }
1279 return bfd_reloc_ok;
1280 }
1281
1282 /* Given a generic HPPA relocation type, the instruction format,
1283 and a field selector, return an appropriate SOM reloation.
1284
1285 FIXME. Need to handle %RR, %LR and the like as field selectors.
1286 These will need to generate multiple SOM relocations. */
1287
1288 int **
1289 hppa_som_gen_reloc_type (abfd, base_type, format, field)
1290 bfd *abfd;
1291 int base_type;
1292 int format;
1293 int field;
1294 {
1295 int *final_type, **final_types;
1296
1297 final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 2);
1298 final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1299
1300
1301 final_types[0] = final_type;
1302 final_types[1] = NULL;
1303
1304 /* Default to the basic relocation passed in. */
1305 *final_type = base_type;
1306
1307 switch (base_type)
1308 {
1309 case R_HPPA:
1310 /* PLABELs get their own relocation type. */
1311 if (field == e_psel
1312 || field == e_lpsel
1313 || field == e_rpsel)
1314 {
1315 /* A PLABEL relocation that has a size of 32 bits must
1316 be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */
1317 if (format == 32)
1318 *final_type = R_DATA_PLABEL;
1319 else
1320 *final_type = R_CODE_PLABEL;
1321 }
1322 /* A relocatoin in the data space is always a full 32bits. */
1323 else if (format == 32)
1324 *final_type = R_DATA_ONE_SYMBOL;
1325
1326 break;
1327
1328 case R_HPPA_GOTOFF:
1329 /* More PLABEL special cases. */
1330 if (field == e_psel
1331 || field == e_lpsel
1332 || field == e_rpsel)
1333 *final_type = R_DATA_PLABEL;
1334 break;
1335
1336 case R_HPPA_NONE:
1337 case R_HPPA_ABS_CALL:
1338 case R_HPPA_PCREL_CALL:
1339 case R_HPPA_COMPLEX:
1340 case R_HPPA_COMPLEX_PCREL_CALL:
1341 case R_HPPA_COMPLEX_ABS_CALL:
1342 /* Right now we can default all these. */
1343 break;
1344 }
1345 return final_types;
1346 }
1347
1348 /* Return the address of the correct entry in the PA SOM relocation
1349 howto table. */
1350
1351 static const reloc_howto_type *
1352 som_bfd_reloc_type_lookup (arch, code)
1353 bfd_arch_info_type *arch;
1354 bfd_reloc_code_real_type code;
1355 {
1356 if ((int) code < (int) R_NO_RELOCATION + 255)
1357 {
1358 BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code);
1359 return &som_hppa_howto_table[(int) code];
1360 }
1361
1362 return (reloc_howto_type *) 0;
1363 }
1364
1365 /* Perform some initialization for an object. Save results of this
1366 initialization in the BFD. */
1367
1368 static bfd_target *
1369 som_object_setup (abfd, file_hdrp, aux_hdrp)
1370 bfd *abfd;
1371 struct header *file_hdrp;
1372 struct som_exec_auxhdr *aux_hdrp;
1373 {
1374 /* som_mkobject will set bfd_error if som_mkobject fails. */
1375 if (som_mkobject (abfd) != true)
1376 return 0;
1377
1378 /* Set BFD flags based on what information is available in the SOM. */
1379 abfd->flags = NO_FLAGS;
1380 if (! file_hdrp->entry_offset)
1381 abfd->flags |= HAS_RELOC;
1382 else
1383 abfd->flags |= EXEC_P;
1384 if (file_hdrp->symbol_total)
1385 abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
1386
1387 bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
1388 bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
1389 bfd_get_symcount (abfd) = file_hdrp->symbol_total;
1390
1391 /* Initialize the saved symbol table and string table to NULL.
1392 Save important offsets and sizes from the SOM header into
1393 the BFD. */
1394 obj_som_stringtab (abfd) = (char *) NULL;
1395 obj_som_symtab (abfd) = (som_symbol_type *) NULL;
1396 obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
1397 obj_som_sym_filepos (abfd) = file_hdrp->symbol_location;
1398 obj_som_str_filepos (abfd) = file_hdrp->symbol_strings_location;
1399 obj_som_reloc_filepos (abfd) = file_hdrp->fixup_request_location;
1400
1401 return abfd->xvec;
1402 }
1403
1404 /* Create a new BFD section for NAME. If NAME already exists, then create a
1405 new unique name, with NAME as the prefix. This exists because SOM .o files
1406 may have more than one $CODE$ subspace. */
1407
1408 static asection *
1409 make_unique_section (abfd, name, num)
1410 bfd *abfd;
1411 CONST char *name;
1412 int num;
1413 {
1414 asection *sect;
1415 char *newname;
1416 char altname[100];
1417
1418 sect = bfd_make_section (abfd, name);
1419 while (!sect)
1420 {
1421 sprintf (altname, "%s-%d", name, num++);
1422 sect = bfd_make_section (abfd, altname);
1423 }
1424
1425 newname = bfd_alloc (abfd, strlen (sect->name) + 1);
1426 strcpy (newname, sect->name);
1427
1428 sect->name = newname;
1429 return sect;
1430 }
1431
1432 /* Convert all of the space and subspace info into BFD sections. Each space
1433 contains a number of subspaces, which in turn describe the mapping between
1434 regions of the exec file, and the address space that the program runs in.
1435 BFD sections which correspond to spaces will overlap the sections for the
1436 associated subspaces. */
1437
1438 static boolean
1439 setup_sections (abfd, file_hdr)
1440 bfd *abfd;
1441 struct header *file_hdr;
1442 {
1443 char *space_strings;
1444 int space_index;
1445 unsigned int total_subspaces = 0;
1446
1447 /* First, read in space names */
1448
1449 space_strings = alloca (file_hdr->space_strings_size);
1450 if (!space_strings)
1451 return false;
1452
1453 if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
1454 return false;
1455 if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd)
1456 != file_hdr->space_strings_size)
1457 return false;
1458
1459 /* Loop over all of the space dictionaries, building up sections */
1460 for (space_index = 0; space_index < file_hdr->space_total; space_index++)
1461 {
1462 struct space_dictionary_record space;
1463 struct subspace_dictionary_record subspace, save_subspace;
1464 int subspace_index;
1465 asection *space_asect;
1466
1467 /* Read the space dictionary element */
1468 if (bfd_seek (abfd, file_hdr->space_location
1469 + space_index * sizeof space, SEEK_SET) < 0)
1470 return false;
1471 if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space)
1472 return false;
1473
1474 /* Setup the space name string */
1475 space.name.n_name = space.name.n_strx + space_strings;
1476
1477 /* Make a section out of it */
1478 space_asect = make_unique_section (abfd, space.name.n_name, space_index);
1479 if (!space_asect)
1480 return false;
1481
1482 /* Now, read in the first subspace for this space */
1483 if (bfd_seek (abfd, file_hdr->subspace_location
1484 + space.subspace_index * sizeof subspace,
1485 SEEK_SET) < 0)
1486 return false;
1487 if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace)
1488 return false;
1489 /* Seek back to the start of the subspaces for loop below */
1490 if (bfd_seek (abfd, file_hdr->subspace_location
1491 + space.subspace_index * sizeof subspace,
1492 SEEK_SET) < 0)
1493 return false;
1494
1495 /* Setup the start address and file loc from the first subspace record */
1496 space_asect->vma = subspace.subspace_start;
1497 space_asect->filepos = subspace.file_loc_init_value;
1498 space_asect->alignment_power = log2 (subspace.alignment);
1499
1500 /* Initialize save_subspace so we can reliably determine if this
1501 loop placed any useful values into it. */
1502 bzero (&save_subspace, sizeof (struct subspace_dictionary_record));
1503
1504 /* Loop over the rest of the subspaces, building up more sections */
1505 for (subspace_index = 0; subspace_index < space.subspace_quantity;
1506 subspace_index++)
1507 {
1508 asection *subspace_asect;
1509
1510 /* Read in the next subspace */
1511 if (bfd_read (&subspace, 1, sizeof subspace, abfd)
1512 != sizeof subspace)
1513 return false;
1514
1515 /* Setup the subspace name string */
1516 subspace.name.n_name = subspace.name.n_strx + space_strings;
1517
1518 /* Make a section out of this subspace */
1519 subspace_asect = make_unique_section (abfd, subspace.name.n_name,
1520 space.subspace_index + subspace_index);
1521
1522 if (!subspace_asect)
1523 return false;
1524
1525 /* Keep an easy mapping between subspaces and sections. */
1526 som_section_data (subspace_asect)->subspace_index
1527 = total_subspaces++;
1528
1529 /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
1530 by the access_control_bits in the subspace header. */
1531 switch (subspace.access_control_bits >> 4)
1532 {
1533 /* Readonly data. */
1534 case 0x0:
1535 subspace_asect->flags |= SEC_DATA | SEC_READONLY;
1536 break;
1537
1538 /* Normal data. */
1539 case 0x1:
1540 subspace_asect->flags |= SEC_DATA;
1541 break;
1542
1543 /* Readonly code and the gateways.
1544 Gateways have other attributes which do not map
1545 into anything BFD knows about. */
1546 case 0x2:
1547 case 0x4:
1548 case 0x5:
1549 case 0x6:
1550 case 0x7:
1551 subspace_asect->flags |= SEC_CODE | SEC_READONLY;
1552 break;
1553
1554 /* dynamic (writable) code. */
1555 case 0x3:
1556 subspace_asect->flags |= SEC_CODE;
1557 break;
1558 }
1559
1560 if (subspace.dup_common || subspace.is_common)
1561 subspace_asect->flags |= SEC_IS_COMMON;
1562 else if (subspace.subspace_length > 0)
1563 subspace_asect->flags |= SEC_HAS_CONTENTS;
1564 if (subspace.is_loadable)
1565 subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
1566 if (subspace.code_only)
1567 subspace_asect->flags |= SEC_CODE;
1568
1569 /* Both file_loc_init_value and initialization_length will
1570 be zero for a BSS like subspace. */
1571 if (subspace.file_loc_init_value == 0
1572 && subspace.initialization_length == 0)
1573 subspace_asect->flags &= ~(SEC_DATA | SEC_LOAD);
1574
1575 /* This subspace has relocations.
1576 The fixup_request_quantity is a byte count for the number of
1577 entries in the relocation stream; it is not the actual number
1578 of relocations in the subspace. */
1579 if (subspace.fixup_request_quantity != 0)
1580 {
1581 subspace_asect->flags |= SEC_RELOC;
1582 subspace_asect->rel_filepos = subspace.fixup_request_index;
1583 som_section_data (subspace_asect)->reloc_size
1584 = subspace.fixup_request_quantity;
1585 /* We can not determine this yet. When we read in the
1586 relocation table the correct value will be filled in. */
1587 subspace_asect->reloc_count = -1;
1588 }
1589
1590 /* Update save_subspace if appropriate. */
1591 if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
1592 save_subspace = subspace;
1593
1594 subspace_asect->vma = subspace.subspace_start;
1595 subspace_asect->_cooked_size = subspace.subspace_length;
1596 subspace_asect->_raw_size = subspace.subspace_length;
1597 subspace_asect->alignment_power = log2 (subspace.alignment);
1598 subspace_asect->filepos = subspace.file_loc_init_value;
1599 }
1600
1601 /* Yow! there is no subspace within the space which actually
1602 has initialized information in it; this should never happen
1603 as far as I know. */
1604 if (!save_subspace.file_loc_init_value)
1605 abort ();
1606
1607 /* Setup the sizes for the space section based upon the info in the
1608 last subspace of the space. */
1609 space_asect->_cooked_size = save_subspace.subspace_start
1610 - space_asect->vma + save_subspace.subspace_length;
1611 space_asect->_raw_size = save_subspace.file_loc_init_value
1612 - space_asect->filepos + save_subspace.initialization_length;
1613 }
1614 return true;
1615 }
1616
1617 /* Read in a SOM object and make it into a BFD. */
1618
1619 static bfd_target *
1620 som_object_p (abfd)
1621 bfd *abfd;
1622 {
1623 struct header file_hdr;
1624 struct som_exec_auxhdr aux_hdr;
1625
1626 if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
1627 {
1628 bfd_error = system_call_error;
1629 return 0;
1630 }
1631
1632 if (!_PA_RISC_ID (file_hdr.system_id))
1633 {
1634 bfd_error = wrong_format;
1635 return 0;
1636 }
1637
1638 switch (file_hdr.a_magic)
1639 {
1640 case RELOC_MAGIC:
1641 case EXEC_MAGIC:
1642 case SHARE_MAGIC:
1643 case DEMAND_MAGIC:
1644 #ifdef DL_MAGIC
1645 case DL_MAGIC:
1646 #endif
1647 #ifdef SHL_MAGIC
1648 case SHL_MAGIC:
1649 #endif
1650 #ifdef EXECLIBMAGIC
1651 case EXECLIBMAGIC:
1652 #endif
1653 break;
1654 default:
1655 bfd_error = wrong_format;
1656 return 0;
1657 }
1658
1659 if (file_hdr.version_id != VERSION_ID
1660 && file_hdr.version_id != NEW_VERSION_ID)
1661 {
1662 bfd_error = wrong_format;
1663 return 0;
1664 }
1665
1666 /* If the aux_header_size field in the file header is zero, then this
1667 object is an incomplete executable (a .o file). Do not try to read
1668 a non-existant auxiliary header. */
1669 bzero (&aux_hdr, sizeof (struct som_exec_auxhdr));
1670 if (file_hdr.aux_header_size != 0)
1671 {
1672 if (bfd_read ((PTR) & aux_hdr, 1, AUX_HDR_SIZE, abfd) != AUX_HDR_SIZE)
1673 {
1674 bfd_error = wrong_format;
1675 return 0;
1676 }
1677 }
1678
1679 if (!setup_sections (abfd, &file_hdr))
1680 {
1681 /* setup_sections does not bubble up a bfd error code. */
1682 bfd_error = bad_value;
1683 return 0;
1684 }
1685
1686 /* This appears to be a valid SOM object. Do some initialization. */
1687 return som_object_setup (abfd, &file_hdr, &aux_hdr);
1688 }
1689
1690 /* Create a SOM object. */
1691
1692 static boolean
1693 som_mkobject (abfd)
1694 bfd *abfd;
1695 {
1696 /* Allocate memory to hold backend information. */
1697 abfd->tdata.som_data = (struct som_data_struct *)
1698 bfd_zalloc (abfd, sizeof (struct som_data_struct));
1699 if (abfd->tdata.som_data == NULL)
1700 {
1701 bfd_error = no_memory;
1702 return false;
1703 }
1704 obj_som_file_hdr (abfd) = bfd_zalloc (abfd, sizeof (struct header));
1705 if (obj_som_file_hdr (abfd) == NULL)
1706
1707 {
1708 bfd_error = no_memory;
1709 return false;
1710 }
1711 return true;
1712 }
1713
1714 /* Initialize some information in the file header. This routine makes
1715 not attempt at doing the right thing for a full executable; it
1716 is only meant to handle relocatable objects. */
1717
1718 static boolean
1719 som_prep_headers (abfd)
1720 bfd *abfd;
1721 {
1722 struct header *file_hdr = obj_som_file_hdr (abfd);
1723 asection *section;
1724
1725 /* FIXME. This should really be conditional based on whether or not
1726 PA1.1 instructions/registers have been used. */
1727 file_hdr->system_id = HP9000S800_ID;
1728
1729 /* FIXME. Only correct for building relocatable objects. */
1730 if (abfd->flags & EXEC_P)
1731 abort ();
1732 else
1733 file_hdr->a_magic = RELOC_MAGIC;
1734
1735 /* Only new format SOM is supported. */
1736 file_hdr->version_id = NEW_VERSION_ID;
1737
1738 /* These fields are optional, and embedding timestamps is not always
1739 a wise thing to do, it makes comparing objects during a multi-stage
1740 bootstrap difficult. */
1741 file_hdr->file_time.secs = 0;
1742 file_hdr->file_time.nanosecs = 0;
1743
1744 if (abfd->flags & EXEC_P)
1745 abort ();
1746 else
1747 {
1748 file_hdr->entry_space = 0;
1749 file_hdr->entry_subspace = 0;
1750 file_hdr->entry_offset = 0;
1751 }
1752
1753 /* FIXME. I do not know if we ever need to put anything other
1754 than zero in this field. */
1755 file_hdr->presumed_dp = 0;
1756
1757 /* Now iterate over the sections translating information from
1758 BFD sections to SOM spaces/subspaces. */
1759
1760 for (section = abfd->sections; section != NULL; section = section->next)
1761 {
1762 /* Ignore anything which has not been marked as a space or
1763 subspace. */
1764 if (som_section_data (section)->is_space == 0
1765
1766 && som_section_data (section)->is_subspace == 0)
1767 continue;
1768
1769 if (som_section_data (section)->is_space)
1770 {
1771 /* Set space attributes. Note most attributes of SOM spaces
1772 are set based on the subspaces it contains. */
1773 som_section_data (section)->space_dict.loader_fix_index = -1;
1774 som_section_data (section)->space_dict.init_pointer_index = -1;
1775 }
1776 else
1777 {
1778 /* Set subspace attributes. Basic stuff is done here, additional
1779 attributes are filled in later as more information becomes
1780 available. */
1781 if (section->flags & SEC_IS_COMMON)
1782 {
1783 som_section_data (section)->subspace_dict.dup_common = 1;
1784 som_section_data (section)->subspace_dict.is_common = 1;
1785 }
1786
1787 if (section->flags & SEC_ALLOC)
1788 som_section_data (section)->subspace_dict.is_loadable = 1;
1789
1790 if (section->flags & SEC_CODE)
1791 som_section_data (section)->subspace_dict.code_only = 1;
1792
1793 som_section_data (section)->subspace_dict.subspace_start =
1794 section->vma;
1795 som_section_data (section)->subspace_dict.subspace_length =
1796 bfd_section_size (abfd, section);
1797 som_section_data (section)->subspace_dict.initialization_length =
1798 bfd_section_size (abfd, section);
1799 som_section_data (section)->subspace_dict.alignment =
1800 1 << section->alignment_power;
1801 }
1802 }
1803 return true;
1804 }
1805
1806 /* Count and return the number of spaces attached to the given BFD. */
1807
1808 static unsigned long
1809 som_count_spaces (abfd)
1810 bfd *abfd;
1811 {
1812 int count = 0;
1813 asection *section;
1814
1815 for (section = abfd->sections; section != NULL; section = section->next)
1816 count += som_section_data (section)->is_space;
1817
1818 return count;
1819 }
1820
1821 /* Count the number of subspaces attached to the given BFD. */
1822
1823 static unsigned long
1824 som_count_subspaces (abfd)
1825 bfd *abfd;
1826 {
1827 int count = 0;
1828 asection *section;
1829
1830 for (section = abfd->sections; section != NULL; section = section->next)
1831 count += som_section_data (section)->is_subspace;
1832
1833 return count;
1834 }
1835
1836 /* Return -1, 0, 1 indicating the relative ordering of sym1 and sym2.
1837
1838 We desire symbols to be ordered starting with the symbol with the
1839 highest relocation count down to the symbol with the lowest relocation
1840 count. Doing so compacts the relocation stream. */
1841
1842 static int
1843 compare_syms (sym1, sym2)
1844 asymbol **sym1;
1845 asymbol **sym2;
1846
1847 {
1848 unsigned int count1, count2;
1849
1850 /* Get relocation count for each symbol. Note that the count
1851 is stored in the udata pointer for section symbols! */
1852 if ((*sym1)->flags & BSF_SECTION_SYM)
1853 count1 = (int)(*sym1)->udata;
1854 else
1855 count1 = (*som_symbol_data ((*sym1)))->reloc_count;
1856
1857 if ((*sym2)->flags & BSF_SECTION_SYM)
1858 count2 = (int)(*sym2)->udata;
1859 else
1860 count2 = (*som_symbol_data ((*sym2)))->reloc_count;
1861
1862 /* Return the appropriate value. */
1863 if (count1 < count2)
1864 return 1;
1865 else if (count1 > count2)
1866 return -1;
1867 return 0;
1868 }
1869
1870 /* Perform various work in preparation for emitting the fixup stream. */
1871
1872 static void
1873 som_prep_for_fixups (abfd, syms, num_syms)
1874 bfd *abfd;
1875 asymbol **syms;
1876 unsigned long num_syms;
1877 {
1878 int i;
1879 asection *section;
1880
1881 /* Most SOM relocations involving a symbol have a length which is
1882 dependent on the index of the symbol. So symbols which are
1883 used often in relocations should have a small index. */
1884
1885 /* First initialize the counters for each symbol. */
1886 for (i = 0; i < num_syms; i++)
1887 {
1888 /* Handle a section symbol; these have no pointers back to the
1889 SOM symbol info. So we just use the pointer field (udata)
1890 to hold the relocation count.
1891
1892 FIXME. While we're here set the name of any section symbol
1893 to something which will not screw GDB. How do other formats
1894 deal with this?!? */
1895 if (som_symbol_data (syms[i]) == NULL)
1896 {
1897 syms[i]->flags |= BSF_SECTION_SYM;
1898 syms[i]->name = "L$0\002";
1899 syms[i]->udata = (PTR) 0;
1900 }
1901 else
1902 (*som_symbol_data (syms[i]))->reloc_count = 0;
1903 }
1904
1905 /* Now that the counters are initialized, make a weighted count
1906 of how often a given symbol is used in a relocation. */
1907 for (section = abfd->sections; section != NULL; section = section->next)
1908 {
1909 int i;
1910
1911 /* Does this section have any relocations? */
1912 if (section->reloc_count <= 0)
1913 continue;
1914
1915 /* Walk through each relocation for this section. */
1916 for (i = 1; i < section->reloc_count; i++)
1917 {
1918 arelent *reloc = section->orelocation[i];
1919 int scale;
1920
1921 /* If no symbol, then there is no counter to increase. */
1922 if (reloc->sym_ptr_ptr == NULL)
1923 continue;
1924
1925 /* Scaling to encourage symbols involved in R_DP_RELATIVE
1926 and R_CODE_ONE_SYMBOL relocations to come first. These
1927 two relocations have single byte versions if the symbol
1928 index is very small. */
1929 if (reloc->howto->type == R_DP_RELATIVE
1930 || reloc->howto->type == R_CODE_ONE_SYMBOL)
1931 scale = 2;
1932 else
1933 scale = 1;
1934
1935 /* Handle section symbols by ramming the count in the udata
1936 field. It will not be used and the count is very important
1937 for these symbols. */
1938 if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
1939 {
1940 (*reloc->sym_ptr_ptr)->udata =
1941 (PTR) ((int) (*reloc->sym_ptr_ptr)->udata + scale);
1942 continue;
1943 }
1944
1945 /* A normal symbol. Increment the count. */
1946 (*som_symbol_data ((*reloc->sym_ptr_ptr)))->reloc_count += scale;
1947 }
1948 }
1949
1950 /* Now sort the symbols. */
1951 qsort (syms, num_syms, sizeof (asymbol *), compare_syms);
1952
1953 /* Compute the symbol indexes, they will be needed by the relocation
1954 code. */
1955 for (i = 0; i < num_syms; i++)
1956 {
1957 /* A section symbol. Again, there is no pointer to backend symbol
1958 information, so we reuse (abuse) the udata field again. */
1959 if (syms[i]->flags & BSF_SECTION_SYM)
1960 syms[i]->udata = (PTR) i;
1961 else
1962 (*som_symbol_data (syms[i]))->index = i;
1963 }
1964 }
1965
1966 static boolean
1967 som_write_fixups (abfd, current_offset, total_reloc_sizep)
1968 bfd *abfd;
1969 unsigned long current_offset;
1970 unsigned int *total_reloc_sizep;
1971 {
1972 unsigned int i, j;
1973 unsigned char *tmp_space, *p;
1974 unsigned int total_reloc_size = 0;
1975 unsigned int subspace_reloc_size = 0;
1976 unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
1977 asection *section = abfd->sections;
1978
1979 /* Get a chunk of memory that we can use as buffer space, then throw
1980 away. */
1981 tmp_space = alloca (SOM_TMP_BUFSIZE);
1982 bzero (tmp_space, SOM_TMP_BUFSIZE);
1983 p = tmp_space;
1984
1985 /* All the fixups for a particular subspace are emitted in a single
1986 stream. All the subspaces for a particular space are emitted
1987 as a single stream.
1988
1989 So, to get all the locations correct one must iterate through all the
1990 spaces, for each space iterate through its subspaces and output a
1991 fixups stream. */
1992 for (i = 0; i < num_spaces; i++)
1993 {
1994 asection *subsection;
1995
1996 /* Find a space. */
1997 while (som_section_data (section)->is_space == 0)
1998 section = section->next;
1999
2000 /* Now iterate through each of its subspaces. */
2001 for (subsection = abfd->sections;
2002 subsection != NULL;
2003 subsection = subsection->next)
2004 {
2005 int reloc_offset;
2006
2007 /* Find a subspace of this space. */
2008 if (som_section_data (subsection)->is_subspace == 0
2009 || som_section_data (subsection)->containing_space != section)
2010 continue;
2011
2012 /* If this subspace had no relocations, then we're finished
2013 with it. */
2014 if (subsection->reloc_count <= 0)
2015 {
2016 som_section_data (subsection)->subspace_dict.fixup_request_index
2017 = -1;
2018 continue;
2019 }
2020
2021 /* This subspace has some relocations. Put the relocation stream
2022 index into the subspace record. */
2023 som_section_data (subsection)->subspace_dict.fixup_request_index
2024 = total_reloc_size;
2025
2026 /* To make life easier start over with a clean slate for
2027 each subspace. Seek to the start of the relocation stream
2028 for this subspace in preparation for writing out its fixup
2029 stream. */
2030 if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) != 0)
2031 {
2032 bfd_error = system_call_error;
2033 return false;
2034 }
2035
2036 /* Buffer space has already been allocated. Just perform some
2037 initialization here. */
2038 p = tmp_space;
2039 subspace_reloc_size = 0;
2040 reloc_offset = 0;
2041 som_initialize_reloc_queue (reloc_queue);
2042
2043 /* Translate each BFD relocation into one or more SOM
2044 relocations. */
2045 for (j = 0; j < subsection->reloc_count; j++)
2046 {
2047 arelent *bfd_reloc = subsection->orelocation[j];
2048 unsigned int skip;
2049 int sym_num;
2050
2051 /* Get the symbol number. Remember it's stored in a
2052 special place for section symbols. */
2053 if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2054 sym_num = (int) (*bfd_reloc->sym_ptr_ptr)->udata;
2055 else
2056 sym_num = (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->index;
2057
2058 /* If there is not enough room for the next couple relocations,
2059 then dump the current buffer contents now. Also reinitialize
2060 the relocation queue.
2061
2062 FIXME. We assume here that no BFD relocation will expand
2063 to more than 100 bytes of SOM relocations. This should (?!?)
2064 be quite safe. */
2065 if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
2066 {
2067 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2068 != p - tmp_space)
2069 {
2070 bfd_error = system_call_error;
2071 return false;
2072 }
2073 p = tmp_space;
2074 som_initialize_reloc_queue (reloc_queue);
2075 }
2076
2077 /* Emit R_NO_RELOCATION fixups to map any bytes which were
2078 skipped. */
2079 skip = bfd_reloc->address - reloc_offset;
2080 p = som_reloc_skip (abfd, skip, p,
2081 &subspace_reloc_size, reloc_queue);
2082
2083 /* Update reloc_offset for the next iteration.
2084
2085 Note R_ENTRY and R_EXIT relocations are just markers,
2086 they do not consume input bytes. */
2087 if (bfd_reloc->howto->type != R_ENTRY
2088 && bfd_reloc->howto->type != R_EXIT)
2089 reloc_offset = bfd_reloc->address + 4;
2090 else
2091 reloc_offset = bfd_reloc->address;
2092
2093
2094 /* Now the actual relocation we care about. */
2095 switch (bfd_reloc->howto->type)
2096 {
2097 case R_PCREL_CALL:
2098 case R_ABS_CALL:
2099 p = som_reloc_call (abfd, p, &subspace_reloc_size,
2100 bfd_reloc, sym_num, reloc_queue);
2101 break;
2102
2103 case R_CODE_ONE_SYMBOL:
2104 case R_DP_RELATIVE:
2105 /* Account for any addend. */
2106 if (bfd_reloc->addend)
2107 p = som_reloc_addend (abfd, bfd_reloc->addend, p,
2108 &subspace_reloc_size, reloc_queue);
2109
2110 if (sym_num < 0x20)
2111 {
2112 bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
2113 subspace_reloc_size += 1;
2114 p += 1;
2115 }
2116 else if (sym_num < 0x100)
2117 {
2118 bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
2119 bfd_put_8 (abfd, sym_num, p + 1);
2120 p = try_prev_fixup (abfd, &subspace_reloc_size, p,
2121 2, reloc_queue);
2122 }
2123 else if (sym_num < 0x10000000)
2124 {
2125 bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
2126 bfd_put_8 (abfd, sym_num >> 16, p + 1);
2127 bfd_put_16 (abfd, sym_num, p + 2);
2128 p = try_prev_fixup (abfd, &subspace_reloc_size,
2129 p, 4, reloc_queue);
2130 }
2131 else
2132 abort ();
2133 break;
2134
2135 case R_DATA_ONE_SYMBOL:
2136 case R_DATA_PLABEL:
2137 case R_CODE_PLABEL:
2138 /* Account for any addend. */
2139 if (bfd_reloc->addend)
2140 p = som_reloc_addend (abfd, bfd_reloc->addend, p,
2141 &subspace_reloc_size, reloc_queue);
2142
2143 if (sym_num < 0x100)
2144 {
2145 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2146 bfd_put_8 (abfd, sym_num, p + 1);
2147 p = try_prev_fixup (abfd, &subspace_reloc_size, p,
2148 2, reloc_queue);
2149 }
2150 else if (sym_num < 0x10000000)
2151 {
2152 bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
2153 bfd_put_8 (abfd, sym_num >> 16, p + 1);
2154 bfd_put_16 (abfd, sym_num, p + 2);
2155 p = try_prev_fixup (abfd, &subspace_reloc_size,
2156 p, 4, reloc_queue);
2157 }
2158 else
2159 abort ();
2160 break;
2161
2162 case R_ENTRY:
2163 {
2164 int *descp
2165 = (int *) (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->unwind;
2166 bfd_put_8 (abfd, R_ENTRY, p);
2167 bfd_put_32 (abfd, descp[0], p + 1);
2168 bfd_put_32 (abfd, descp[1], p + 5);
2169 p = try_prev_fixup (abfd, &subspace_reloc_size,
2170 p, 9, reloc_queue);
2171 break;
2172 }
2173
2174 case R_EXIT:
2175 bfd_put_8 (abfd, R_EXIT, p);
2176 subspace_reloc_size += 1;
2177 p += 1;
2178 break;
2179
2180 /* Put a "R_RESERVED" relocation in the stream if
2181 we hit something we do not understand. The linker
2182 will complain loudly if this ever happens. */
2183 default:
2184 bfd_put_8 (abfd, 0xff, p);
2185 subspace_reloc_size += 1;
2186 p += 1;
2187 }
2188 }
2189
2190 /* Last BFD relocation for a subspace has been processed.
2191 Map the rest of the subspace with R_NO_RELOCATION fixups. */
2192 p = som_reloc_skip (abfd, bfd_section_size (abfd, subsection)
2193 - reloc_offset,
2194 p, &subspace_reloc_size, reloc_queue);
2195
2196 /* Scribble out the relocations. */
2197 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2198 != p - tmp_space)
2199 {
2200 bfd_error = system_call_error;
2201 return false;
2202 }
2203 p = tmp_space;
2204
2205 total_reloc_size += subspace_reloc_size;
2206 som_section_data (subsection)->subspace_dict.fixup_request_quantity
2207 = subspace_reloc_size;
2208 }
2209 section = section->next;
2210 }
2211 *total_reloc_sizep = total_reloc_size;
2212 return true;
2213 }
2214
2215 /* Write out the space/subspace string table. */
2216
2217 static boolean
2218 som_write_space_strings (abfd, current_offset, string_sizep)
2219 bfd *abfd;
2220 unsigned long current_offset;
2221 unsigned int *string_sizep;
2222 {
2223 unsigned char *tmp_space, *p;
2224 unsigned int strings_size = 0;
2225 asection *section;
2226
2227 /* Get a chunk of memory that we can use as buffer space, then throw
2228 away. */
2229 tmp_space = alloca (SOM_TMP_BUFSIZE);
2230 bzero (tmp_space, SOM_TMP_BUFSIZE);
2231 p = tmp_space;
2232
2233 /* Seek to the start of the space strings in preparation for writing
2234 them out. */
2235 if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
2236 {
2237 bfd_error = system_call_error;
2238 return false;
2239 }
2240
2241 /* Walk through all the spaces and subspaces (order is not important)
2242 building up and writing string table entries for their names. */
2243 for (section = abfd->sections; section != NULL; section = section->next)
2244 {
2245 int length;
2246
2247 /* Only work with space/subspaces; avoid any other sections
2248 which might have been made (.text for example). */
2249 if (som_section_data (section)->is_space == 0
2250 && som_section_data (section)->is_subspace == 0)
2251 continue;
2252
2253 /* Get the length of the space/subspace name. */
2254 length = strlen (section->name);
2255
2256 /* If there is not enough room for the next entry, then dump the
2257 current buffer contents now. Each entry will take 4 bytes to
2258 hold the string length + the string itself + null terminator. */
2259 if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
2260 {
2261 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2262 != p - tmp_space)
2263 {
2264 bfd_error = system_call_error;
2265 return false;
2266 }
2267 /* Reset to beginning of the buffer space. */
2268 p = tmp_space;
2269 }
2270
2271 /* First element in a string table entry is the length of the
2272 string. Alignment issues are already handled. */
2273 bfd_put_32 (abfd, length, p);
2274 p += 4;
2275 strings_size += 4;
2276
2277 /* Record the index in the space/subspace records. */
2278 if (som_section_data (section)->is_space)
2279 som_section_data (section)->space_dict.name.n_strx = strings_size;
2280 else
2281 som_section_data (section)->subspace_dict.name.n_strx = strings_size;
2282
2283 /* Next comes the string itself + a null terminator. */
2284 strcpy (p, section->name);
2285 p += length + 1;
2286 strings_size += length + 1;
2287
2288 /* Always align up to the next word boundary. */
2289 while (strings_size % 4)
2290 {
2291 bfd_put_8 (abfd, 0, p);
2292 p++;
2293 strings_size++;
2294 }
2295 }
2296
2297 /* Done with the space/subspace strings. Write out any information
2298 contained in a partial block. */
2299 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd) != p - tmp_space)
2300 {
2301 bfd_error = system_call_error;
2302 return false;
2303 }
2304 *string_sizep = strings_size;
2305 return true;
2306 }
2307
2308 /* Write out the symbol string table. */
2309
2310 static boolean
2311 som_write_symbol_strings (abfd, current_offset, syms, num_syms, string_sizep)
2312 bfd *abfd;
2313 unsigned long current_offset;
2314 asymbol **syms;
2315 unsigned int num_syms;
2316 unsigned int *string_sizep;
2317 {
2318 unsigned int i;
2319 unsigned char *tmp_space, *p;
2320 unsigned int strings_size = 0;
2321
2322 /* Get a chunk of memory that we can use as buffer space, then throw
2323 away. */
2324 tmp_space = alloca (SOM_TMP_BUFSIZE);
2325 bzero (tmp_space, SOM_TMP_BUFSIZE);
2326 p = tmp_space;
2327
2328 /* Seek to the start of the space strings in preparation for writing
2329 them out. */
2330 if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
2331 {
2332 bfd_error = system_call_error;
2333 return false;
2334 }
2335
2336 for (i = 0; i < num_syms; i++)
2337 {
2338 int length = strlen (syms[i]->name);
2339
2340 /* If there is not enough room for the next entry, then dump the
2341 current buffer contents now. */
2342 if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
2343 {
2344 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2345 != p - tmp_space)
2346 {
2347 bfd_error = system_call_error;
2348 return false;
2349 }
2350 /* Reset to beginning of the buffer space. */
2351 p = tmp_space;
2352 }
2353
2354 /* First element in a string table entry is the length of the
2355 string. This must always be 4 byte aligned. This is also
2356 an appropriate time to fill in the string index field in the
2357 symbol table entry. */
2358 bfd_put_32 (abfd, length, p);
2359 strings_size += 4;
2360 p += 4;
2361
2362 /* Next comes the string itself + a null terminator. */
2363 strcpy (p, syms[i]->name);
2364
2365 /* ACK. FIXME. */
2366 syms[i]->name = (char *)strings_size;
2367 p += length + 1;
2368 strings_size += length + 1;
2369
2370 /* Always align up to the next word boundary. */
2371 while (strings_size % 4)
2372 {
2373 bfd_put_8 (abfd, 0, p);
2374 strings_size++;
2375 p++;
2376 }
2377 }
2378
2379 /* Scribble out any partial block. */
2380 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd) != p - tmp_space)
2381 {
2382 bfd_error = system_call_error;
2383 return false;
2384 }
2385
2386 *string_sizep = strings_size;
2387 return true;
2388 }
2389
2390 /* Compute variable information to be placed in the SOM headers,
2391 space/subspace dictionaries, relocation streams, etc. Begin
2392 writing parts of the object file. */
2393
2394 static boolean
2395 som_begin_writing (abfd)
2396 bfd *abfd;
2397 {
2398 unsigned long current_offset = 0;
2399 int strings_size = 0;
2400 unsigned int total_reloc_size = 0;
2401 unsigned long num_spaces, num_subspaces, num_syms, i;
2402 asection *section;
2403 asymbol **syms = bfd_get_outsymbols (abfd);
2404 unsigned int total_subspaces = 0;
2405
2406 /* The file header will always be first in an object file,
2407 everything else can be in random locations. To keep things
2408 "simple" BFD will lay out the object file in the manner suggested
2409 by the PRO ABI for PA-RISC Systems. */
2410
2411 /* Before any output can really begin offsets for all the major
2412 portions of the object file must be computed. So, starting
2413 with the initial file header compute (and sometimes write)
2414 each portion of the object file. */
2415
2416 /* Make room for the file header, it's contents are not complete
2417 yet, so it can not be written at this time. */
2418 current_offset += sizeof (struct header);
2419
2420 /* Any auxiliary headers will follow the file header. Right now
2421 we have no auxiliary headers, so current_offset does not change. */
2422 obj_som_file_hdr (abfd)->aux_header_location = current_offset;
2423 obj_som_file_hdr (abfd)->aux_header_size = 0;
2424
2425 /* Next comes the initialization pointers; again we have no
2426 initialization pointers, so current offset does not change. */
2427 obj_som_file_hdr (abfd)->init_array_location = current_offset;
2428 obj_som_file_hdr (abfd)->init_array_total = 0;
2429
2430 /* Next are the space records. These are fixed length records.
2431
2432 Count the number of spaces to determine how much room is needed
2433 in the object file for the space records.
2434
2435 The names of the spaces are stored in a separate string table,
2436 and the index for each space into the string table is computed
2437 below. Therefore, it is not possible to write the space headers
2438 at this time. */
2439 num_spaces = som_count_spaces (abfd);
2440 obj_som_file_hdr (abfd)->space_location = current_offset;
2441 obj_som_file_hdr (abfd)->space_total = num_spaces;
2442 current_offset += num_spaces * sizeof (struct space_dictionary_record);
2443
2444 /* Next are the subspace records. These are fixed length records.
2445
2446 Count the number of subspaes to determine how much room is needed
2447 in the object file for the subspace records.
2448
2449 A variety if fields in the subspace record are still unknown at
2450 this time (index into string table, fixup stream location/size, etc). */
2451 num_subspaces = som_count_subspaces (abfd);
2452 obj_som_file_hdr (abfd)->subspace_location = current_offset;
2453 obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
2454 current_offset += num_subspaces * sizeof (struct subspace_dictionary_record);
2455
2456 /* Next is the string table for the space/subspace names. We will
2457 build and write the string table on the fly. At the same time
2458 we will fill in the space/subspace name index fields. */
2459
2460 /* The string table needs to be aligned on a word boundary. */
2461 if (current_offset % 4)
2462 current_offset += (4 - (current_offset % 4));
2463
2464 /* Mark the offset of the space/subspace string table in the
2465 file header. */
2466 obj_som_file_hdr (abfd)->space_strings_location = current_offset;
2467
2468 /* Scribble out the space strings. */
2469 if (som_write_space_strings (abfd, current_offset, &strings_size) == false)
2470 return false;
2471
2472 /* Record total string table size in the header and update the
2473 current offset. */
2474 obj_som_file_hdr (abfd)->space_strings_size = strings_size;
2475 current_offset += strings_size;
2476
2477 /* Next is the symbol table. These are fixed length records.
2478
2479 Count the number of symbols to determine how much room is needed
2480 in the object file for the symbol table.
2481
2482 The names of the symbols are stored in a separate string table,
2483 and the index for each symbol name into the string table is computed
2484 below. Therefore, it is not possible to write the symobl table
2485 at this time. */
2486 num_syms = bfd_get_symcount (abfd);
2487 obj_som_file_hdr (abfd)->symbol_location = current_offset;
2488 obj_som_file_hdr (abfd)->symbol_total = num_syms;
2489 current_offset += num_syms * sizeof (struct symbol_dictionary_record);
2490
2491 /* Do prep work before handling fixups. */
2492 som_prep_for_fixups (abfd, syms, num_syms);
2493
2494 /* Next comes the fixup stream which starts on a word boundary. */
2495 if (current_offset % 4)
2496 current_offset += (4 - (current_offset % 4));
2497 obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
2498
2499 /* Write the fixups and update fields in subspace headers which
2500 relate to the fixup stream. */
2501 if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
2502 return false;
2503
2504 /* Record the total size of the fixup stream in the file header. */
2505 obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
2506 current_offset += total_reloc_size;
2507
2508 /* Next are the symbol strings.
2509 Align them to a word boundary. */
2510 if (current_offset % 4)
2511 current_offset += (4 - (current_offset % 4));
2512 obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
2513
2514 /* Scribble out the symbol strings. */
2515 if (som_write_symbol_strings (abfd, current_offset, syms,
2516 num_syms, &strings_size)
2517 == false)
2518 return false;
2519
2520 /* Record total string table size in header and update the
2521 current offset. */
2522 obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
2523 current_offset += strings_size;
2524
2525 /* Next is the compiler records. We do not use these. */
2526 obj_som_file_hdr (abfd)->compiler_location = current_offset;
2527 obj_som_file_hdr (abfd)->compiler_total = 0;
2528
2529 /* Now compute the file positions for the loadable subspaces. */
2530
2531 section = abfd->sections;
2532 for (i = 0; i < num_spaces; i++)
2533 {
2534 asection *subsection;
2535
2536 /* Find a space. */
2537 while (som_section_data (section)->is_space == 0)
2538 section = section->next;
2539
2540 /* Now look for all its subspaces. */
2541 for (subsection = abfd->sections;
2542 subsection != NULL;
2543 subsection = subsection->next)
2544 {
2545
2546 if (som_section_data (subsection)->is_subspace == 0
2547 || som_section_data (subsection)->containing_space != section
2548 || (subsection->flags & SEC_ALLOC) == 0)
2549 continue;
2550
2551 som_section_data (subsection)->subspace_index = total_subspaces++;
2552 /* This is real data to be loaded from the file. */
2553 if (subsection->flags & SEC_LOAD)
2554 {
2555 som_section_data (subsection)->subspace_dict.file_loc_init_value
2556 = current_offset;
2557 section->filepos = current_offset;
2558 current_offset += bfd_section_size (abfd, subsection);
2559 }
2560 /* Looks like uninitialized data. */
2561 else
2562 {
2563 som_section_data (subsection)->subspace_dict.file_loc_init_value
2564 = 0;
2565 som_section_data (subsection)->subspace_dict.
2566 initialization_length = 0;
2567 }
2568 }
2569 /* Goto the next section. */
2570 section = section->next;
2571 }
2572
2573 /* Finally compute the file positions for unloadable subspaces. */
2574
2575 obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
2576 section = abfd->sections;
2577 for (i = 0; i < num_spaces; i++)
2578 {
2579 asection *subsection;
2580
2581 /* Find a space. */
2582 while (som_section_data (section)->is_space == 0)
2583 section = section->next;
2584
2585 /* Now look for all its subspaces. */
2586 for (subsection = abfd->sections;
2587 subsection != NULL;
2588 subsection = subsection->next)
2589 {
2590
2591 if (som_section_data (subsection)->is_subspace == 0
2592 || som_section_data (subsection)->containing_space != section
2593 || (subsection->flags & SEC_ALLOC) != 0)
2594 continue;
2595
2596 som_section_data (subsection)->subspace_index = total_subspaces++;
2597 /* This is real data to be loaded from the file. */
2598 if ((subsection->flags & SEC_LOAD) == 0)
2599 {
2600 som_section_data (subsection)->subspace_dict.file_loc_init_value
2601 = current_offset;
2602 section->filepos = current_offset;
2603 current_offset += bfd_section_size (abfd, subsection);
2604 }
2605 /* Looks like uninitialized data. */
2606 else
2607 {
2608 som_section_data (subsection)->subspace_dict.file_loc_init_value
2609 = 0;
2610 som_section_data (subsection)->subspace_dict.
2611 initialization_length = bfd_section_size (abfd, subsection);
2612 }
2613 }
2614 /* Goto the next section. */
2615 section = section->next;
2616 }
2617
2618 obj_som_file_hdr (abfd)->unloadable_sp_size
2619 = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
2620
2621 /* Loader fixups are not supported in any way shape or form. */
2622 obj_som_file_hdr (abfd)->loader_fixup_location = 0;
2623 obj_som_file_hdr (abfd)->loader_fixup_total = 0;
2624
2625 /* Done. Store the total size of the SOM. */
2626 obj_som_file_hdr (abfd)->som_length = current_offset;
2627 return true;
2628 }
2629
2630 /* Finally, scribble out the various headers to the disk. */
2631
2632 static boolean
2633 som_write_headers (abfd)
2634 bfd *abfd;
2635 {
2636 int num_spaces = som_count_spaces (abfd);
2637 int i;
2638 int subspace_index = 0;
2639 file_ptr location;
2640 asection *section;
2641
2642 /* Subspaces are written first so that we can set up information
2643 about them in their containing spaces as the subspace is written. */
2644
2645 /* Seek to the start of the subspace dictionary records. */
2646 location = obj_som_file_hdr (abfd)->subspace_location;
2647 bfd_seek (abfd, location, SEEK_SET);
2648 section = abfd->sections;
2649 /* Now for each loadable space write out records for its subspaces. */
2650 for (i = 0; i < num_spaces; i++)
2651 {
2652 asection *subsection;
2653
2654 /* Find a space. */
2655 while (som_section_data (section)->is_space == 0)
2656 section = section->next;
2657
2658 /* Now look for all its subspaces. */
2659 for (subsection = abfd->sections;
2660 subsection != NULL;
2661 subsection = subsection->next)
2662 {
2663
2664 /* Skip any section which does not correspond to a space
2665 or subspace. Or does not have SEC_ALLOC set (and therefore
2666 has no real bits on the disk). */
2667 if (som_section_data (subsection)->is_subspace == 0
2668 || som_section_data (subsection)->containing_space != section
2669 || (subsection->flags & SEC_ALLOC) == 0)
2670 continue;
2671
2672 /* If this is the first subspace for this space, then save
2673 the index of the subspace in its containing space. Also
2674 set "is_loadable" in the containing space. */
2675
2676 if (som_section_data (section)->space_dict.subspace_quantity == 0)
2677 {
2678 som_section_data (section)->space_dict.is_loadable = 1;
2679 som_section_data (section)->space_dict.subspace_index
2680 = subspace_index;
2681 }
2682
2683 /* Increment the number of subspaces seen and the number of
2684 subspaces contained within the current space. */
2685 subspace_index++;
2686 som_section_data (section)->space_dict.subspace_quantity++;
2687
2688 /* Mark the index of the current space within the subspace's
2689 dictionary record. */
2690 som_section_data (subsection)->subspace_dict.space_index = i;
2691
2692 /* Dump the current subspace header. */
2693 if (bfd_write ((PTR) &som_section_data (subsection)->subspace_dict,
2694 sizeof (struct subspace_dictionary_record), 1, abfd)
2695 != sizeof (struct subspace_dictionary_record))
2696 {
2697 bfd_error = system_call_error;
2698 return false;
2699 }
2700 }
2701 /* Goto the next section. */
2702 section = section->next;
2703 }
2704
2705 /* Now repeat the process for unloadable subspaces. */
2706 section = abfd->sections;
2707 /* Now for each space write out records for its subspaces. */
2708 for (i = 0; i < num_spaces; i++)
2709 {
2710 asection *subsection;
2711
2712 /* Find a space. */
2713 while (som_section_data (section)->is_space == 0)
2714 section = section->next;
2715
2716 /* Now look for all its subspaces. */
2717 for (subsection = abfd->sections;
2718 subsection != NULL;
2719 subsection = subsection->next)
2720 {
2721
2722 /* Skip any section which does not correspond to a space or
2723 subspace, or which SEC_ALLOC set (and therefore handled
2724 in the loadable spaces/subspaces code above. */
2725
2726 if (som_section_data (subsection)->is_subspace == 0
2727 || som_section_data (subsection)->containing_space != section
2728 || (subsection->flags & SEC_ALLOC) != 0)
2729 continue;
2730
2731 /* If this is the first subspace for this space, then save
2732 the index of the subspace in its containing space. Clear
2733 "is_loadable". */
2734
2735 if (som_section_data (section)->space_dict.subspace_quantity == 0)
2736 {
2737 som_section_data (section)->space_dict.is_loadable = 0;
2738 som_section_data (section)->space_dict.subspace_index
2739 = subspace_index;
2740 }
2741
2742 /* Increment the number of subspaces seen and the number of
2743 subspaces contained within the current space. */
2744 som_section_data (section)->space_dict.subspace_quantity++;
2745 subspace_index++;
2746
2747 /* Mark the index of the current space within the subspace's
2748 dictionary record. */
2749 som_section_data (subsection)->subspace_dict.space_index = i;
2750
2751 /* Dump this subspace header. */
2752 if (bfd_write ((PTR) &som_section_data (subsection)->subspace_dict,
2753 sizeof (struct subspace_dictionary_record), 1, abfd)
2754 != sizeof (struct subspace_dictionary_record))
2755 {
2756 bfd_error = system_call_error;
2757 return false;
2758 }
2759 }
2760 /* Goto the next section. */
2761 section = section->next;
2762 }
2763
2764 /* All the subspace dictiondary records are written, and all the
2765 fields are set up in the space dictionary records.
2766
2767 Seek to the right location and start writing the space
2768 dictionary records. */
2769 location = obj_som_file_hdr (abfd)->space_location;
2770 bfd_seek (abfd, location, SEEK_SET);
2771
2772 section = abfd->sections;
2773 for (i = 0; i < num_spaces; i++)
2774 {
2775
2776 /* Find a space. */
2777 while (som_section_data (section)->is_space == 0)
2778 section = section->next;
2779
2780 /* Dump its header */
2781 if (bfd_write ((PTR) &som_section_data (section)->space_dict,
2782 sizeof (struct space_dictionary_record), 1, abfd)
2783 != sizeof (struct space_dictionary_record))
2784 {
2785 bfd_error = system_call_error;
2786 return false;
2787 }
2788
2789 /* Goto the next section. */
2790 section = section->next;
2791 }
2792
2793 /* Only thing left to do is write out the file header. It is always
2794 at location zero. Seek there and write it. */
2795 bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
2796 if (bfd_write ((PTR) obj_som_file_hdr (abfd),
2797 sizeof (struct header), 1, abfd)
2798 != sizeof (struct header))
2799 {
2800 bfd_error = system_call_error;
2801 return false;
2802 }
2803 return true;
2804 }
2805
2806 /* Compute and return the checksum for a SOM file header. */
2807
2808 static unsigned long
2809 som_compute_checksum (abfd)
2810 bfd *abfd;
2811 {
2812 unsigned long checksum, count, i;
2813 unsigned long *buffer = (unsigned long *) obj_som_file_hdr (abfd);
2814
2815 checksum = 0;
2816 count = sizeof (struct header) / sizeof (unsigned long);
2817 for (i = 0; i < count; i++)
2818 checksum ^= *(buffer + i);
2819
2820 return checksum;
2821 }
2822
2823 /* Build and write, in one big chunk, the entire symbol table for
2824 this BFD. */
2825
2826 static boolean
2827 som_build_and_write_symbol_table (abfd)
2828 bfd *abfd;
2829 {
2830 unsigned int num_syms = bfd_get_symcount (abfd);
2831 file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
2832 asymbol **bfd_syms = bfd_get_outsymbols (abfd);
2833 struct symbol_dictionary_record *som_symtab;
2834 int i, symtab_size;
2835
2836 /* Compute total symbol table size and allocate a chunk of memory
2837 to hold the symbol table as we build it. */
2838 symtab_size = num_syms * sizeof (struct symbol_dictionary_record);
2839 som_symtab = (struct symbol_dictionary_record *) alloca (symtab_size);
2840 bzero (som_symtab, symtab_size);
2841
2842 /* Walk over each symbol. */
2843 for (i = 0; i < num_syms; i++)
2844 {
2845 /* This is really an index into the symbol strings table.
2846 By the time we get here, the index has already been
2847 computed and stored into the name field in the BFD symbol. */
2848 som_symtab[i].name.n_strx = (int) bfd_syms[i]->name;
2849
2850 /* The HP SOM linker requires detailed type information about
2851 all symbols (including undefined symbols!). Unfortunately,
2852 the type specified in an import/export statement does not
2853 always match what the linker wants. Severe braindamage. */
2854
2855 /* Section symbols will not have a SOM symbol type assigned to
2856 them yet. Assign all section symbols type ST_DATA. */
2857 if (bfd_syms[i]->flags & BSF_SECTION_SYM)
2858 som_symtab[i].symbol_type = ST_DATA;
2859 else
2860 {
2861 /* Common symbols must have scope SS_UNSAT and type
2862 ST_STORAGE or the linker will choke. */
2863 if (bfd_syms[i]->section == &bfd_com_section)
2864 {
2865 som_symtab[i].symbol_scope = SS_UNSAT;
2866 som_symtab[i].symbol_type = ST_STORAGE;
2867 }
2868
2869 /* It is possible to have a symbol without an associated
2870 type. This happens if the user imported the symbol
2871 without a type and the symbol was never defined
2872 locally. If BSF_FUNCTION is set for this symbol, then
2873 assign it type ST_CODE (the HP linker requires undefined
2874 external functions to have type ST_CODE rather than ST_ENTRY. */
2875 else if (((*som_symbol_data (bfd_syms[i]))->som_type
2876 == SYMBOL_TYPE_UNKNOWN)
2877 && (bfd_syms[i]->section == &bfd_und_section)
2878 && (bfd_syms[i]->flags & BSF_FUNCTION))
2879 som_symtab[i].symbol_type = ST_CODE;
2880
2881 /* Handle function symbols which were defined in this file.
2882 They should have type ST_ENTRY. Also retrieve the argument
2883 relocation bits from the SOM backend information. */
2884 else if (((*som_symbol_data (bfd_syms[i]))->som_type
2885 == SYMBOL_TYPE_ENTRY)
2886 || (((*som_symbol_data (bfd_syms[i]))->som_type
2887 == SYMBOL_TYPE_CODE)
2888 && (bfd_syms[i]->flags & BSF_FUNCTION))
2889 || (((*som_symbol_data (bfd_syms[i]))->som_type
2890 == SYMBOL_TYPE_UNKNOWN)
2891 && (bfd_syms[i]->flags & BSF_FUNCTION)))
2892 {
2893 som_symtab[i].symbol_type = ST_ENTRY;
2894 som_symtab[i].arg_reloc
2895 = (*som_symbol_data (bfd_syms[i]))->tc_data.hppa_arg_reloc;
2896 }
2897
2898 /* If the type is unknown at this point, it should be
2899 ST_DATA (functions were handled as special cases above). */
2900 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2901 == SYMBOL_TYPE_UNKNOWN)
2902 som_symtab[i].symbol_type = ST_DATA;
2903
2904 /* From now on it's a very simple mapping. */
2905 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2906 == SYMBOL_TYPE_ABSOLUTE)
2907 som_symtab[i].symbol_type = ST_ABSOLUTE;
2908 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2909 == SYMBOL_TYPE_CODE)
2910 som_symtab[i].symbol_type = ST_CODE;
2911 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2912 == SYMBOL_TYPE_DATA)
2913 som_symtab[i].symbol_type = ST_DATA;
2914 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2915 == SYMBOL_TYPE_MILLICODE)
2916 som_symtab[i].symbol_type = ST_MILLICODE;
2917 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2918 == SYMBOL_TYPE_PLABEL)
2919 som_symtab[i].symbol_type = ST_PLABEL;
2920 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2921 == SYMBOL_TYPE_PRI_PROG)
2922 som_symtab[i].symbol_type = ST_PRI_PROG;
2923 else if ((*som_symbol_data (bfd_syms[i]))->som_type
2924 == SYMBOL_TYPE_SEC_PROG)
2925 som_symtab[i].symbol_type = ST_SEC_PROG;
2926 }
2927
2928 /* Now handle the symbol's scope. Exported data which is not
2929 in the common section has scope SS_UNIVERSAL. Note scope
2930 of common symbols was handled earlier! */
2931 if (bfd_syms[i]->flags & BSF_EXPORT
2932 && bfd_syms[i]->section != &bfd_com_section)
2933 som_symtab[i].symbol_scope = SS_UNIVERSAL;
2934 /* Any undefined symbol at this point has a scope SS_UNSAT. */
2935 else if (bfd_syms[i]->section == &bfd_und_section)
2936 som_symtab[i].symbol_scope = SS_UNSAT;
2937 /* Anything else which is not in the common section has scope
2938 SS_LOCAL. */
2939 else if (bfd_syms[i]->section != &bfd_com_section)
2940 som_symtab[i].symbol_scope = SS_LOCAL;
2941
2942 /* Now set the symbol_info field. It has no real meaning
2943 for undefined or common symbols, but the HP linker will
2944 choke if it's not set to some "reasonable" value. We
2945 use zero as a reasonable value. */
2946 if (bfd_syms[i]->section == &bfd_com_section
2947 || bfd_syms[i]->section == &bfd_und_section)
2948 som_symtab[i].symbol_info = 0;
2949 /* For all other symbols, the symbol_info field contains the
2950 subspace index of the space this symbol is contained in. */
2951 else
2952 som_symtab[i].symbol_info
2953 = som_section_data (bfd_syms[i]->section)->subspace_index;
2954
2955 /* Set the symbol's value. */
2956 som_symtab[i].symbol_value
2957 = bfd_syms[i]->value + bfd_syms[i]->section->vma;
2958 }
2959
2960 /* Egad. Everything is ready, seek to the right location and
2961 scribble out the symbol table. */
2962 if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
2963 {
2964 bfd_error = system_call_error;
2965 return false;
2966 }
2967
2968 if (bfd_write ((PTR) som_symtab, symtab_size, 1, abfd) != symtab_size)
2969 {
2970 bfd_error = system_call_error;
2971 return false;
2972 }
2973 return true;
2974 }
2975
2976 /* Write an object in SOM format. */
2977
2978 static boolean
2979 som_write_object_contents (abfd)
2980 bfd *abfd;
2981 {
2982 if (abfd->output_has_begun == false)
2983 {
2984 /* Set up fixed parts of the file, space, and subspace headers.
2985 Notify the world that output has begun. */
2986 som_prep_headers (abfd);
2987 abfd->output_has_begun = true;
2988 /* Start writing the object file. This include all the string
2989 tables, fixup streams, and other portions of the object file. */
2990 som_begin_writing (abfd);
2991 }
2992
2993 /* Now that the symbol table information is complete, build and
2994 write the symbol table. */
2995 if (som_build_and_write_symbol_table (abfd) == false)
2996 return false;
2997
2998 /* Compute the checksum for the file header just before writing
2999 the header to disk. */
3000 obj_som_file_hdr (abfd)->checksum = som_compute_checksum (abfd);
3001 return (som_write_headers (abfd));
3002 }
3003
3004 \f
3005 /* Read and save the string table associated with the given BFD. */
3006
3007 static boolean
3008 som_slurp_string_table (abfd)
3009 bfd *abfd;
3010 {
3011 char *stringtab;
3012
3013 /* Use the saved version if its available. */
3014 if (obj_som_stringtab (abfd) != NULL)
3015 return true;
3016
3017 /* Allocate and read in the string table. */
3018 stringtab = bfd_zalloc (abfd, obj_som_stringtab_size (abfd));
3019 if (stringtab == NULL)
3020 {
3021 bfd_error = no_memory;
3022 return false;
3023 }
3024
3025 if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
3026 {
3027 bfd_error = system_call_error;
3028 return false;
3029 }
3030
3031 if (bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd)
3032 != obj_som_stringtab_size (abfd))
3033 {
3034 bfd_error = system_call_error;
3035 return false;
3036 }
3037
3038 /* Save our results and return success. */
3039 obj_som_stringtab (abfd) = stringtab;
3040 return true;
3041 }
3042
3043 /* Return the amount of data (in bytes) required to hold the symbol
3044 table for this object. */
3045
3046 static unsigned int
3047 som_get_symtab_upper_bound (abfd)
3048 bfd *abfd;
3049 {
3050 if (!som_slurp_symbol_table (abfd))
3051 return 0;
3052
3053 return (bfd_get_symcount (abfd) + 1) * (sizeof (som_symbol_type *));
3054 }
3055
3056 /* Convert from a SOM subspace index to a BFD section. */
3057
3058 static asection *
3059 som_section_from_subspace_index (abfd, index)
3060 bfd *abfd;
3061 unsigned int index;
3062 {
3063 asection *section;
3064
3065 for (section = abfd->sections; section != NULL; section = section->next)
3066 if (som_section_data (section)->subspace_index == index)
3067 return section;
3068
3069 /* Should never happen. */
3070 abort();
3071 }
3072
3073 /* Read and save the symbol table associated with the given BFD. */
3074
3075 static unsigned int
3076 som_slurp_symbol_table (abfd)
3077 bfd *abfd;
3078 {
3079 int symbol_count = bfd_get_symcount (abfd);
3080 int symsize = sizeof (struct symbol_dictionary_record);
3081 char *stringtab;
3082 struct symbol_dictionary_record *buf, *bufp, *endbufp;
3083 som_symbol_type *sym, *symbase;
3084
3085 /* Return saved value if it exists. */
3086 if (obj_som_symtab (abfd) != NULL)
3087 return true;
3088
3089 /* Sanity checking. Make sure there are some symbols and that
3090 we can read the string table too. */
3091 if (symbol_count == 0)
3092 {
3093 bfd_error = no_symbols;
3094 return false;
3095 }
3096
3097 if (!som_slurp_string_table (abfd))
3098 return false;
3099
3100 stringtab = obj_som_stringtab (abfd);
3101
3102 symbase = (som_symbol_type *)
3103 bfd_zalloc (abfd, symbol_count * sizeof (som_symbol_type));
3104 if (symbase == NULL)
3105 {
3106 bfd_error = no_memory;
3107 return false;
3108 }
3109
3110 /* Read in the external SOM representation. */
3111 buf = alloca (symbol_count * symsize);
3112 if (buf == NULL)
3113 {
3114 bfd_error = no_memory;
3115 return false;
3116 }
3117 if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
3118 {
3119 bfd_error = system_call_error;
3120 return false;
3121 }
3122 if (bfd_read (buf, symbol_count * symsize, 1, abfd)
3123 != symbol_count * symsize)
3124 {
3125 bfd_error = no_symbols;
3126 return (false);
3127 }
3128
3129 /* Iterate over all the symbols and internalize them. */
3130 endbufp = buf + symbol_count;
3131 for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
3132 {
3133
3134 /* I don't think we care about these. */
3135 if (bufp->symbol_type == ST_SYM_EXT
3136 || bufp->symbol_type == ST_ARG_EXT)
3137 continue;
3138
3139 /* Some reasonable defaults. */
3140 sym->symbol.the_bfd = abfd;
3141 sym->symbol.name = bufp->name.n_strx + stringtab;
3142 sym->symbol.value = bufp->symbol_value;
3143 sym->symbol.section = 0;
3144 sym->symbol.flags = 0;
3145
3146 switch (bufp->symbol_type)
3147 {
3148 case ST_ENTRY:
3149 case ST_PRI_PROG:
3150 case ST_SEC_PROG:
3151 case ST_MILLICODE:
3152 sym->symbol.flags |= BSF_FUNCTION;
3153 sym->symbol.value &= ~0x3;
3154 break;
3155
3156 case ST_STUB:
3157 case ST_CODE:
3158 sym->symbol.value &= ~0x3;
3159
3160 default:
3161 break;
3162 }
3163
3164 /* Handle scoping and section information. */
3165 switch (bufp->symbol_scope)
3166 {
3167 /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
3168 so the section associated with this symbol can't be known. */
3169 case SS_EXTERNAL:
3170 case SS_UNSAT:
3171 sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3172 break;
3173
3174 case SS_UNIVERSAL:
3175 sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3176 sym->symbol.section
3177 = som_section_from_subspace_index (abfd, bufp->symbol_info);
3178 sym->symbol.value -= sym->symbol.section->vma;
3179 break;
3180
3181 #if 0
3182 /* SS_GLOBAL and SS_LOCAL are two names for the same thing.
3183 Sound dumb? It is. */
3184 case SS_GLOBAL:
3185 #endif
3186 case SS_LOCAL:
3187 sym->symbol.flags |= BSF_LOCAL;
3188 sym->symbol.section
3189 = som_section_from_subspace_index (abfd, bufp->symbol_info);
3190 sym->symbol.value -= sym->symbol.section->vma;
3191 break;
3192 }
3193
3194 /* Mark symbols left around by the debugger. */
3195 if (strlen (sym->symbol.name) >= 2
3196 && sym->symbol.name[0] == 'L'
3197 && (sym->symbol.name[1] == '$' || sym->symbol.name[2] == '$'
3198 || sym->symbol.name[3] == '$'))
3199 sym->symbol.flags |= BSF_DEBUGGING;
3200
3201 /* Note increment at bottom of loop, since we skip some symbols
3202 we can not include it as part of the for statement. */
3203 sym++;
3204 }
3205
3206 /* Save our results and return success. */
3207 obj_som_symtab (abfd) = symbase;
3208 return (true);
3209 }
3210
3211 /* Canonicalize a SOM symbol table. Return the number of entries
3212 in the symbol table. */
3213
3214 static unsigned int
3215 som_get_symtab (abfd, location)
3216 bfd *abfd;
3217 asymbol **location;
3218 {
3219 int i;
3220 som_symbol_type *symbase;
3221
3222 if (!som_slurp_symbol_table (abfd))
3223 return 0;
3224
3225 i = bfd_get_symcount (abfd);
3226 symbase = obj_som_symtab (abfd);
3227
3228 for (; i > 0; i--, location++, symbase++)
3229 *location = &symbase->symbol;
3230
3231 /* Final null pointer. */
3232 *location = 0;
3233 return (bfd_get_symcount (abfd));
3234 }
3235
3236 /* Make a SOM symbol. There is nothing special to do here. */
3237
3238 static asymbol *
3239 som_make_empty_symbol (abfd)
3240 bfd *abfd;
3241 {
3242 som_symbol_type *new =
3243 (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
3244 if (new == NULL)
3245 {
3246 bfd_error = no_memory;
3247 return 0;
3248 }
3249 new->symbol.the_bfd = abfd;
3250
3251 return &new->symbol;
3252 }
3253
3254 /* Print symbol information. */
3255
3256 static void
3257 som_print_symbol (ignore_abfd, afile, symbol, how)
3258 bfd *ignore_abfd;
3259 PTR afile;
3260 asymbol *symbol;
3261 bfd_print_symbol_type how;
3262 {
3263 FILE *file = (FILE *) afile;
3264 switch (how)
3265 {
3266 case bfd_print_symbol_name:
3267 fprintf (file, "%s", symbol->name);
3268 break;
3269 case bfd_print_symbol_more:
3270 fprintf (file, "som ");
3271 fprintf_vma (file, symbol->value);
3272 fprintf (file, " %lx", (long) symbol->flags);
3273 break;
3274 case bfd_print_symbol_all:
3275 {
3276 CONST char *section_name;
3277 section_name = symbol->section ? symbol->section->name : "(*none*)";
3278 bfd_print_symbol_vandf ((PTR) file, symbol);
3279 fprintf (file, " %s\t%s", section_name, symbol->name);
3280 break;
3281 }
3282 }
3283 }
3284
3285 /* Count or process variable-length SOM fixup records.
3286
3287 To avoid code duplication we use this code both to compute the number
3288 of relocations requested by a stream, and to internalize the stream.
3289
3290 When computing the number of relocations requested by a stream the
3291 variables rptr, section, and symbols have no meaning.
3292
3293 Return the number of relocations requested by the fixup stream. When
3294 not just counting
3295
3296 This needs at least two or three more passes to get it cleaned up. */
3297
3298 static unsigned int
3299 som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
3300 unsigned char *fixup;
3301 unsigned int end;
3302 arelent *internal_relocs;
3303 asection *section;
3304 asymbol **symbols;
3305 boolean just_count;
3306 {
3307 unsigned int op, varname;
3308 unsigned char *end_fixups = &fixup[end];
3309 const struct fixup_format *fp;
3310 char *cp;
3311 unsigned char *save_fixup;
3312 int variables[26], stack[20], c, v, count, prev_fixup, *sp;
3313 const int *subop;
3314 arelent *rptr= internal_relocs;
3315 unsigned int offset = just_count ? 0 : section->vma;
3316
3317 #define var(c) variables[(c) - 'A']
3318 #define push(v) (*sp++ = (v))
3319 #define pop() (*--sp)
3320 #define emptystack() (sp == stack)
3321
3322 som_initialize_reloc_queue (reloc_queue);
3323 bzero (variables, sizeof (variables));
3324 bzero (stack, sizeof (stack));
3325 count = 0;
3326 prev_fixup = 0;
3327 sp = stack;
3328
3329 while (fixup < end_fixups)
3330 {
3331
3332 /* Save pointer to the start of this fixup. We'll use
3333 it later to determine if it is necessary to put this fixup
3334 on the queue. */
3335 save_fixup = fixup;
3336
3337 /* Get the fixup code and its associated format. */
3338 op = *fixup++;
3339 fp = &som_fixup_formats[op];
3340
3341 /* Handle a request for a previous fixup. */
3342 if (*fp->format == 'P')
3343 {
3344 /* Get pointer to the beginning of the prev fixup, move
3345 the repeated fixup to the head of the queue. */
3346 fixup = reloc_queue[fp->D].reloc;
3347 som_reloc_queue_fix (reloc_queue, fp->D);
3348 prev_fixup = 1;
3349
3350 /* Get the fixup code and its associated format. */
3351 op = *fixup++;
3352 fp = &som_fixup_formats[op];
3353 }
3354
3355 /* If we are not just counting, set some reasonable defaults. */
3356 if (! just_count)
3357 {
3358 rptr->address = offset;
3359 rptr->howto = &som_hppa_howto_table[op];
3360 rptr->addend = 0;
3361 }
3362
3363 /* Set default input length to 0. Get the opcode class index
3364 into D. */
3365 var ('L') = 0;
3366 var ('D') = fp->D;
3367
3368 /* Get the opcode format. */
3369 cp = fp->format;
3370
3371 /* Process the format string. Parsing happens in two phases,
3372 parse RHS, then assign to LHS. Repeat until no more
3373 characters in the format string. */
3374 while (*cp)
3375 {
3376 /* The variable this pass is going to compute a value for. */
3377 varname = *cp++;
3378
3379 /* Start processing RHS. Continue until a NULL or '=' is found. */
3380 do
3381 {
3382 c = *cp++;
3383
3384 /* If this is a variable, push it on the stack. */
3385 if (isupper (c))
3386 push (var (c));
3387
3388 /* If this is a lower case letter, then it represents
3389 additional data from the fixup stream to be pushed onto
3390 the stack. */
3391 else if (islower (c))
3392 {
3393 for (v = 0; c > 'a'; --c)
3394 v = (v << 8) | *fixup++;
3395 push (v);
3396 }
3397
3398 /* A decimal constant. Push it on the stack. */
3399 else if (isdigit (c))
3400 {
3401 v = c - '0';
3402 while (isdigit (*cp))
3403 v = (v * 10) + (*cp++ - '0');
3404 push (v);
3405 }
3406 else
3407
3408 /* An operator. Pop two two values from the stack and
3409 use them as operands to the given operation. Push
3410 the result of the operation back on the stack. */
3411 switch (c)
3412 {
3413 case '+':
3414 v = pop ();
3415 v += pop ();
3416 push (v);
3417 break;
3418 case '*':
3419 v = pop ();
3420 v *= pop ();
3421 push (v);
3422 break;
3423 case '<':
3424 v = pop ();
3425 v = pop () << v;
3426 push (v);
3427 break;
3428 default:
3429 abort ();
3430 }
3431 }
3432 while (*cp && *cp != '=');
3433
3434 /* Move over the equal operator. */
3435 cp++;
3436
3437 /* Pop the RHS off the stack. */
3438 c = pop ();
3439
3440 /* Perform the assignment. */
3441 var (varname) = c;
3442
3443 /* Handle side effects. and special 'O' stack cases. */
3444 switch (varname)
3445 {
3446 /* Consume some bytes from the input space. */
3447 case 'L':
3448 offset += c;
3449 break;
3450 /* A symbol to use in the relocation. Make a note
3451 of this if we are not just counting. */
3452 case 'S':
3453 if (! just_count)
3454 rptr->sym_ptr_ptr = &symbols[c];
3455 break;
3456 /* Handle the linker expression stack. */
3457 case 'O':
3458 switch (op)
3459 {
3460 case R_COMP1:
3461 subop = comp1_opcodes;
3462 break;
3463 case R_COMP2:
3464 subop = comp2_opcodes;
3465 break;
3466 case R_COMP3:
3467 subop = comp3_opcodes;
3468 break;
3469 default:
3470 abort ();
3471 }
3472 while (*subop <= (unsigned char) c)
3473 ++subop;
3474 --subop;
3475 break;
3476 default:
3477 break;
3478 }
3479 }
3480
3481 /* If we used a previous fixup, clean up after it. */
3482 if (prev_fixup)
3483 {
3484 fixup = save_fixup + 1;
3485 prev_fixup = 0;
3486 }
3487 /* Queue it. */
3488 else if (fixup > save_fixup + 1)
3489 som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
3490
3491 /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION
3492 fixups to BFD. */
3493 if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
3494 && som_hppa_howto_table[op].type != R_NO_RELOCATION)
3495 {
3496 /* Done with a single reloction. Loop back to the top. */
3497 if (! just_count)
3498 {
3499 rptr->addend = var ('V');
3500 rptr++;
3501 }
3502 count++;
3503 /* Now that we've handled a "full" relocation, reset
3504 some state. */
3505 bzero (variables, sizeof (variables));
3506 bzero (stack, sizeof (stack));
3507 }
3508 }
3509 return count;
3510
3511 #undef var
3512 #undef push
3513 #undef pop
3514 #undef emptystack
3515 }
3516
3517 /* Read in the relocs (aka fixups in SOM terms) for a section.
3518
3519 som_get_reloc_upper_bound calls this routine with JUST_COUNT
3520 set to true to indicate it only needs a count of the number
3521 of actual relocations. */
3522
3523 static boolean
3524 som_slurp_reloc_table (abfd, section, symbols, just_count)
3525 bfd *abfd;
3526 asection *section;
3527 asymbol **symbols;
3528 boolean just_count;
3529 {
3530 char *external_relocs;
3531 unsigned int fixup_stream_size;
3532 arelent *internal_relocs;
3533 unsigned int num_relocs;
3534
3535 fixup_stream_size = som_section_data (section)->reloc_size;
3536 /* If there were no relocations, then there is nothing to do. */
3537 if (section->reloc_count == 0)
3538 return true;
3539
3540 /* If reloc_count is -1, then the relocation stream has not been
3541 parsed. We must do so now to know how many relocations exist. */
3542 if (section->reloc_count == -1)
3543 {
3544 external_relocs = (char *) bfd_zalloc (abfd, fixup_stream_size);
3545 if (external_relocs == (char *) NULL)
3546 {
3547 bfd_error = no_memory;
3548 return false;
3549 }
3550 /* Read in the external forms. */
3551 if (bfd_seek (abfd,
3552 obj_som_reloc_filepos (abfd) + section->rel_filepos,
3553 SEEK_SET)
3554 != 0)
3555 {
3556 bfd_error = system_call_error;
3557 return false;
3558 }
3559 if (bfd_read (external_relocs, 1, fixup_stream_size, abfd)
3560 != fixup_stream_size)
3561 {
3562 bfd_error = system_call_error;
3563 return false;
3564 }
3565 /* Let callers know how many relocations found.
3566 also save the relocation stream as we will
3567 need it again. */
3568 section->reloc_count = som_set_reloc_info (external_relocs,
3569 fixup_stream_size,
3570 NULL, NULL, NULL, true);
3571
3572 som_section_data (section)->reloc_stream = external_relocs;
3573 }
3574
3575 /* If the caller only wanted a count, then return now. */
3576 if (just_count)
3577 return true;
3578
3579 num_relocs = section->reloc_count;
3580 external_relocs = som_section_data (section)->reloc_stream;
3581 /* Return saved information about the relocations if it is available. */
3582 if (section->relocation != (arelent *) NULL)
3583 return true;
3584
3585 internal_relocs = (arelent *) bfd_zalloc (abfd,
3586 num_relocs * sizeof (arelent));
3587 if (internal_relocs == (arelent *) NULL)
3588 {
3589 bfd_error = no_memory;
3590 return false;
3591 }
3592
3593 /* Process and internalize the relocations. */
3594 som_set_reloc_info (external_relocs, fixup_stream_size,
3595 internal_relocs, section, symbols, false);
3596
3597 /* Save our results and return success. */
3598 section->relocation = internal_relocs;
3599 return (true);
3600 }
3601
3602 /* Return the number of bytes required to store the relocation
3603 information associated with the given section. */
3604
3605 static unsigned int
3606 som_get_reloc_upper_bound (abfd, asect)
3607 bfd *abfd;
3608 sec_ptr asect;
3609 {
3610 /* If section has relocations, then read in the relocation stream
3611 and parse it to determine how many relocations exist. */
3612 if (asect->flags & SEC_RELOC)
3613 {
3614 if (som_slurp_reloc_table (abfd, asect, NULL, true))
3615 return (asect->reloc_count + 1) * sizeof (arelent);
3616 }
3617 /* Either there are no relocations or an error occurred while
3618 reading and parsing the relocation stream. */
3619 return 0;
3620 }
3621
3622 /* Convert relocations from SOM (external) form into BFD internal
3623 form. Return the number of relocations. */
3624
3625 static unsigned int
3626 som_canonicalize_reloc (abfd, section, relptr, symbols)
3627 bfd *abfd;
3628 sec_ptr section;
3629 arelent **relptr;
3630 asymbol **symbols;
3631 {
3632 arelent *tblptr;
3633 int count;
3634
3635 if (som_slurp_reloc_table (abfd, section, symbols, false) == false)
3636 return 0;
3637
3638 count = section->reloc_count;
3639 tblptr = section->relocation;
3640 if (tblptr == (arelent *) NULL)
3641 return 0;
3642
3643 while (count--)
3644 *relptr++ = tblptr++;
3645
3646 *relptr = (arelent *) NULL;
3647 return section->reloc_count;
3648 }
3649
3650 extern bfd_target som_vec;
3651
3652 /* A hook to set up object file dependent section information. */
3653
3654 static boolean
3655 som_new_section_hook (abfd, newsect)
3656 bfd *abfd;
3657 asection *newsect;
3658 {
3659 newsect->used_by_bfd = (struct som_section_data_struct *)
3660 bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
3661 newsect->alignment_power = 3;
3662
3663 /* Initialize the subspace_index field to -1 so that it does
3664 not match a subspace with an index of 0. */
3665 som_section_data (newsect)->subspace_index = -1;
3666
3667 /* We allow more than three sections internally */
3668 return true;
3669 }
3670
3671 /* Set backend info for sections which can not be described
3672 in the BFD data structures. */
3673
3674 void
3675 bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
3676 asection *section;
3677 char defined;
3678 char private;
3679 unsigned char sort_key;
3680 int spnum;
3681 {
3682 struct space_dictionary_record *space_dict;
3683
3684 som_section_data (section)->is_space = 1;
3685 space_dict = &som_section_data (section)->space_dict;
3686 space_dict->is_defined = defined;
3687 space_dict->is_private = private;
3688 space_dict->sort_key = sort_key;
3689 space_dict->space_number = spnum;
3690 }
3691
3692 /* Set backend info for subsections which can not be described
3693 in the BFD data structures. */
3694
3695 void
3696 bfd_som_set_subsection_attributes (section, container, access,
3697 sort_key, quadrant)
3698 asection *section;
3699 asection *container;
3700 int access;
3701 unsigned char sort_key;
3702 int quadrant;
3703 {
3704 struct subspace_dictionary_record *subspace_dict;
3705 som_section_data (section)->is_subspace = 1;
3706 subspace_dict = &som_section_data (section)->subspace_dict;
3707 subspace_dict->access_control_bits = access;
3708 subspace_dict->sort_key = sort_key;
3709 subspace_dict->quadrant = quadrant;
3710 som_section_data (section)->containing_space = container;
3711 }
3712
3713 /* Set the full SOM symbol type. SOM needs far more symbol information
3714 than any other object file format I'm aware of. It is mandatory
3715 to be able to know if a symbol is an entry point, millicode, data,
3716 code, absolute, storage request, or procedure label. If you get
3717 the symbol type wrong your program will not link. */
3718
3719 void
3720 bfd_som_set_symbol_type (symbol, type)
3721 asymbol *symbol;
3722 unsigned int type;
3723 {
3724 (*som_symbol_data (symbol))->som_type = type;
3725 }
3726
3727 /* Attach 64bits of unwind information to a symbol (which hopefully
3728 is a function of some kind!). It would be better to keep this
3729 in the R_ENTRY relocation, but there is not enough space. */
3730
3731 void
3732 bfd_som_attach_unwind_info (symbol, unwind_desc)
3733 asymbol *symbol;
3734 char *unwind_desc;
3735 {
3736 (*som_symbol_data (symbol))->unwind = unwind_desc;
3737 }
3738
3739 static boolean
3740 som_set_section_contents (abfd, section, location, offset, count)
3741 bfd *abfd;
3742 sec_ptr section;
3743 PTR location;
3744 file_ptr offset;
3745 bfd_size_type count;
3746 {
3747 if (abfd->output_has_begun == false)
3748 {
3749 /* Set up fixed parts of the file, space, and subspace headers.
3750 Notify the world that output has begun. */
3751 som_prep_headers (abfd);
3752 abfd->output_has_begun = true;
3753 /* Start writing the object file. This include all the string
3754 tables, fixup streams, and other portions of the object file. */
3755 som_begin_writing (abfd);
3756 }
3757
3758 /* Only write subspaces which have "real" contents (eg. the contents
3759 are not generated at run time by the OS). */
3760 if (som_section_data (section)->is_subspace != 1
3761 || ((section->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0))
3762 return true;
3763
3764 /* Seek to the proper offset within the object file and write the
3765 data. */
3766 offset += som_section_data (section)->subspace_dict.file_loc_init_value;
3767 if (bfd_seek (abfd, offset, SEEK_SET) == -1)
3768 {
3769 bfd_error = system_call_error;
3770 return false;
3771 }
3772
3773 if (bfd_write ((PTR) location, 1, count, abfd) != count)
3774 {
3775 bfd_error = system_call_error;
3776 return false;
3777 }
3778 return true;
3779 }
3780
3781 static boolean
3782 som_set_arch_mach (abfd, arch, machine)
3783 bfd *abfd;
3784 enum bfd_architecture arch;
3785 unsigned long machine;
3786 {
3787 /* Allow any architecture to be supported by the SOM backend */
3788 return bfd_default_set_arch_mach (abfd, arch, machine);
3789 }
3790
3791 static boolean
3792 som_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
3793 functionname_ptr, line_ptr)
3794 bfd *abfd;
3795 asection *section;
3796 asymbol **symbols;
3797 bfd_vma offset;
3798 CONST char **filename_ptr;
3799 CONST char **functionname_ptr;
3800 unsigned int *line_ptr;
3801 {
3802 fprintf (stderr, "som_find_nearest_line unimplemented\n");
3803 fflush (stderr);
3804 abort ();
3805 return (false);
3806 }
3807
3808 static int
3809 som_sizeof_headers (abfd, reloc)
3810 bfd *abfd;
3811 boolean reloc;
3812 {
3813 fprintf (stderr, "som_sizeof_headers unimplemented\n");
3814 fflush (stderr);
3815 abort ();
3816 return (0);
3817 }
3818
3819 /* Return information about SOM symbol SYMBOL in RET. */
3820
3821 static void
3822 som_get_symbol_info (ignore_abfd, symbol, ret)
3823 bfd *ignore_abfd; /* Ignored. */
3824 asymbol *symbol;
3825 symbol_info *ret;
3826 {
3827 bfd_symbol_info (symbol, ret);
3828 }
3829
3830 /* End of miscellaneous support functions. */
3831
3832 #define som_bfd_debug_info_start bfd_void
3833 #define som_bfd_debug_info_end bfd_void
3834 #define som_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
3835
3836 #define som_openr_next_archived_file bfd_generic_openr_next_archived_file
3837 #define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
3838 #define som_slurp_armap bfd_false
3839 #define som_slurp_extended_name_table _bfd_slurp_extended_name_table
3840 #define som_truncate_arname (void (*)())bfd_nullvoidptr
3841 #define som_write_armap 0
3842
3843 #define som_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
3844 #define som_close_and_cleanup bfd_generic_close_and_cleanup
3845 #define som_get_section_contents bfd_generic_get_section_contents
3846
3847 #define som_bfd_get_relocated_section_contents \
3848 bfd_generic_get_relocated_section_contents
3849 #define som_bfd_relax_section bfd_generic_relax_section
3850 #define som_bfd_seclet_link bfd_generic_seclet_link
3851 #define som_bfd_make_debug_symbol \
3852 ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
3853
3854 /* Core file support is in the hpux-core backend. */
3855 #define som_core_file_failing_command _bfd_dummy_core_file_failing_command
3856 #define som_core_file_failing_signal _bfd_dummy_core_file_failing_signal
3857 #define som_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
3858
3859 bfd_target som_vec =
3860 {
3861 "som", /* name */
3862 bfd_target_som_flavour,
3863 true, /* target byte order */
3864 true, /* target headers byte order */
3865 (HAS_RELOC | EXEC_P | /* object flags */
3866 HAS_LINENO | HAS_DEBUG |
3867 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
3868 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
3869 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
3870
3871 /* leading_symbol_char: is the first char of a user symbol
3872 predictable, and if so what is it */
3873 0,
3874 ' ', /* ar_pad_char */
3875 16, /* ar_max_namelen */
3876 3, /* minimum alignment */
3877 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
3878 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
3879 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
3880 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
3881 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
3882 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
3883 {_bfd_dummy_target,
3884 som_object_p, /* bfd_check_format */
3885 bfd_generic_archive_p,
3886 _bfd_dummy_target
3887 },
3888 {
3889 bfd_false,
3890 som_mkobject,
3891 _bfd_generic_mkarchive,
3892 bfd_false
3893 },
3894 {
3895 bfd_false,
3896 som_write_object_contents,
3897 _bfd_write_archive_contents,
3898 bfd_false,
3899 },
3900 #undef som
3901 JUMP_TABLE (som),
3902 (PTR) 0
3903 };
3904
3905 #endif /* HOST_HPPAHPUX || HOST_HPPABSD */