]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/som.c
* elf32-hppa.h (R_HPPA_ABS_CALL): Define.
[thirdparty/binutils-gdb.git] / bfd / som.c
1 /* bfd back-end for HP PA-RISC SOM objects.
2 Copyright (C) 1990, 1991, 1992, 1993, 1994 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) || defined (HOST_HPPAOSF)
27
28 #include "libbfd.h"
29 #include "som.h"
30
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/dir.h>
35 #include <signal.h>
36 #include <machine/reg.h>
37 #include <sys/user.h> /* After a.out.h */
38 #include <sys/file.h>
39 #include <errno.h>
40
41 /* Magic not defined in standard HP-UX header files until 8.0 */
42
43 #ifndef CPU_PA_RISC1_0
44 #define CPU_PA_RISC1_0 0x20B
45 #endif /* CPU_PA_RISC1_0 */
46
47 #ifndef CPU_PA_RISC1_1
48 #define CPU_PA_RISC1_1 0x210
49 #endif /* CPU_PA_RISC1_1 */
50
51 #ifndef _PA_RISC1_0_ID
52 #define _PA_RISC1_0_ID CPU_PA_RISC1_0
53 #endif /* _PA_RISC1_0_ID */
54
55 #ifndef _PA_RISC1_1_ID
56 #define _PA_RISC1_1_ID CPU_PA_RISC1_1
57 #endif /* _PA_RISC1_1_ID */
58
59 #ifndef _PA_RISC_MAXID
60 #define _PA_RISC_MAXID 0x2FF
61 #endif /* _PA_RISC_MAXID */
62
63 #ifndef _PA_RISC_ID
64 #define _PA_RISC_ID(__m_num) \
65 (((__m_num) == _PA_RISC1_0_ID) || \
66 ((__m_num) >= _PA_RISC1_1_ID && (__m_num) <= _PA_RISC_MAXID))
67 #endif /* _PA_RISC_ID */
68
69 /* Size (in chars) of the temporary buffers used during fixup and string
70 table writes. */
71
72 #define SOM_TMP_BUFSIZE 8192
73
74 /* Size of the hash table in archives. */
75 #define SOM_LST_HASH_SIZE 31
76
77 /* Max number of SOMs to be found in an archive. */
78 #define SOM_LST_MODULE_LIMIT 1024
79
80 /* Generic alignment macro. */
81 #define SOM_ALIGN(val, alignment) \
82 (((val) + (alignment) - 1) & ~((alignment) - 1))
83
84 /* SOM allows any one of the four previous relocations to be reused
85 with a "R_PREV_FIXUP" relocation entry. Since R_PREV_FIXUP
86 relocations are always a single byte, using a R_PREV_FIXUP instead
87 of some multi-byte relocation makes object files smaller.
88
89 Note one side effect of using a R_PREV_FIXUP is the relocation that
90 is being repeated moves to the front of the queue. */
91 struct reloc_queue
92 {
93 unsigned char *reloc;
94 unsigned int size;
95 } reloc_queue[4];
96
97 /* This fully describes the symbol types which may be attached to
98 an EXPORT or IMPORT directive. Only SOM uses this formation
99 (ELF has no need for it). */
100 typedef enum
101 {
102 SYMBOL_TYPE_UNKNOWN,
103 SYMBOL_TYPE_ABSOLUTE,
104 SYMBOL_TYPE_CODE,
105 SYMBOL_TYPE_DATA,
106 SYMBOL_TYPE_ENTRY,
107 SYMBOL_TYPE_MILLICODE,
108 SYMBOL_TYPE_PLABEL,
109 SYMBOL_TYPE_PRI_PROG,
110 SYMBOL_TYPE_SEC_PROG,
111 } pa_symbol_type;
112
113 struct section_to_type
114 {
115 char *section;
116 char type;
117 };
118
119 /* Assorted symbol information that needs to be derived from the BFD symbol
120 and/or the BFD backend private symbol data. */
121 struct som_misc_symbol_info
122 {
123 unsigned int symbol_type;
124 unsigned int symbol_scope;
125 unsigned int arg_reloc;
126 unsigned int symbol_info;
127 unsigned int symbol_value;
128 };
129
130 /* Forward declarations */
131
132 static boolean som_mkobject PARAMS ((bfd *));
133 static bfd_target * som_object_setup PARAMS ((bfd *,
134 struct header *,
135 struct som_exec_auxhdr *));
136 static boolean setup_sections PARAMS ((bfd *, struct header *));
137 static bfd_target * som_object_p PARAMS ((bfd *));
138 static boolean som_write_object_contents PARAMS ((bfd *));
139 static boolean som_slurp_string_table PARAMS ((bfd *));
140 static unsigned int som_slurp_symbol_table PARAMS ((bfd *));
141 static long som_get_symtab_upper_bound PARAMS ((bfd *));
142 static long som_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
143 arelent **, asymbol **));
144 static long som_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
145 static unsigned int som_set_reloc_info PARAMS ((unsigned char *, unsigned int,
146 arelent *, asection *,
147 asymbol **, boolean));
148 static boolean som_slurp_reloc_table PARAMS ((bfd *, asection *,
149 asymbol **, boolean));
150 static long som_get_symtab PARAMS ((bfd *, asymbol **));
151 static asymbol * som_make_empty_symbol PARAMS ((bfd *));
152 static void som_print_symbol PARAMS ((bfd *, PTR,
153 asymbol *, bfd_print_symbol_type));
154 static boolean som_new_section_hook PARAMS ((bfd *, asection *));
155 static boolean som_bfd_copy_private_section_data PARAMS ((bfd *, asection *,
156 bfd *, asection *));
157 static boolean som_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *));
158 static boolean som_bfd_is_local_label PARAMS ((bfd *, asymbol *));
159 static boolean som_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
160 file_ptr, bfd_size_type));
161 static boolean som_get_section_contents PARAMS ((bfd *, sec_ptr, PTR,
162 file_ptr, bfd_size_type));
163 static boolean som_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
164 unsigned long));
165 static boolean som_find_nearest_line PARAMS ((bfd *, asection *,
166 asymbol **, bfd_vma,
167 CONST char **,
168 CONST char **,
169 unsigned int *));
170 static void som_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
171 static asection * bfd_section_from_som_symbol PARAMS ((bfd *,
172 struct symbol_dictionary_record *));
173 static int log2 PARAMS ((unsigned int));
174 static bfd_reloc_status_type hppa_som_reloc PARAMS ((bfd *, arelent *,
175 asymbol *, PTR,
176 asection *, bfd *,
177 char **));
178 static void som_initialize_reloc_queue PARAMS ((struct reloc_queue *));
179 static void som_reloc_queue_insert PARAMS ((unsigned char *, unsigned int,
180 struct reloc_queue *));
181 static void som_reloc_queue_fix PARAMS ((struct reloc_queue *, unsigned int));
182 static int som_reloc_queue_find PARAMS ((unsigned char *, unsigned int,
183 struct reloc_queue *));
184 static unsigned char * try_prev_fixup PARAMS ((bfd *, int *, unsigned char *,
185 unsigned int,
186 struct reloc_queue *));
187
188 static unsigned char * som_reloc_skip PARAMS ((bfd *, unsigned int,
189 unsigned char *, unsigned int *,
190 struct reloc_queue *));
191 static unsigned char * som_reloc_addend PARAMS ((bfd *, int, unsigned char *,
192 unsigned int *,
193 struct reloc_queue *));
194 static unsigned char * som_reloc_call PARAMS ((bfd *, unsigned char *,
195 unsigned int *,
196 arelent *, int,
197 struct reloc_queue *));
198 static unsigned long som_count_spaces PARAMS ((bfd *));
199 static unsigned long som_count_subspaces PARAMS ((bfd *));
200 static int compare_syms PARAMS ((asymbol **, asymbol **));
201 static unsigned long som_compute_checksum PARAMS ((bfd *));
202 static boolean som_prep_headers PARAMS ((bfd *));
203 static int som_sizeof_headers PARAMS ((bfd *, boolean));
204 static boolean som_write_headers PARAMS ((bfd *));
205 static boolean som_build_and_write_symbol_table PARAMS ((bfd *));
206 static void som_prep_for_fixups PARAMS ((bfd *, asymbol **, unsigned long));
207 static boolean som_write_fixups PARAMS ((bfd *, unsigned long, unsigned int *));
208 static boolean som_write_space_strings PARAMS ((bfd *, unsigned long,
209 unsigned int *));
210 static boolean som_write_symbol_strings PARAMS ((bfd *, unsigned long,
211 asymbol **, unsigned int,
212 unsigned *));
213 static boolean som_begin_writing PARAMS ((bfd *));
214 static const reloc_howto_type * som_bfd_reloc_type_lookup
215 PARAMS ((bfd_arch_info_type *, bfd_reloc_code_real_type));
216 static char som_section_type PARAMS ((const char *));
217 static int som_decode_symclass PARAMS ((asymbol *));
218 static boolean som_bfd_count_ar_symbols PARAMS ((bfd *, struct lst_header *,
219 symindex *));
220
221 static boolean som_bfd_fill_in_ar_symbols PARAMS ((bfd *, struct lst_header *,
222 carsym **syms));
223 static boolean som_slurp_armap PARAMS ((bfd *));
224 static boolean som_write_armap PARAMS ((bfd *));
225 static void som_bfd_derive_misc_symbol_info PARAMS ((bfd *, asymbol *,
226 struct som_misc_symbol_info *));
227 static boolean som_bfd_prep_for_ar_write PARAMS ((bfd *, unsigned int *,
228 unsigned int *));
229 static unsigned int som_bfd_ar_symbol_hash PARAMS ((asymbol *));
230 static boolean som_bfd_ar_write_symbol_stuff PARAMS ((bfd *, unsigned int,
231 unsigned int,
232 struct lst_header));
233 static CONST char *normalize PARAMS ((CONST char *file));
234 static boolean som_is_space PARAMS ((asection *));
235 static boolean som_is_subspace PARAMS ((asection *));
236 static boolean som_is_container PARAMS ((asection *, asection *));
237 static boolean som_bfd_free_cached_info PARAMS ((bfd *));
238
239 /* Map SOM section names to POSIX/BSD single-character symbol types.
240
241 This table includes all the standard subspaces as defined in the
242 current "PRO ABI for PA-RISC Systems", $UNWIND$ which for
243 some reason was left out, and sections specific to embedded stabs. */
244
245 static const struct section_to_type stt[] = {
246 {"$TEXT$", 't'},
247 {"$SHLIB_INFO$", 't'},
248 {"$MILLICODE$", 't'},
249 {"$LIT$", 't'},
250 {"$CODE$", 't'},
251 {"$UNWIND_START$", 't'},
252 {"$UNWIND$", 't'},
253 {"$PRIVATE$", 'd'},
254 {"$PLT$", 'd'},
255 {"$SHLIB_DATA$", 'd'},
256 {"$DATA$", 'd'},
257 {"$SHORTDATA$", 'g'},
258 {"$DLT$", 'd'},
259 {"$GLOBAL$", 'g'},
260 {"$SHORTBSS$", 's'},
261 {"$BSS$", 'b'},
262 {"$GDB_STRINGS$", 'N'},
263 {"$GDB_SYMBOLS$", 'N'},
264 {0, 0}
265 };
266
267 /* About the relocation formatting table...
268
269 There are 256 entries in the table, one for each possible
270 relocation opcode available in SOM. We index the table by
271 the relocation opcode. The names and operations are those
272 defined by a.out_800 (4).
273
274 Right now this table is only used to count and perform minimal
275 processing on relocation streams so that they can be internalized
276 into BFD and symbolically printed by utilities. To make actual use
277 of them would be much more difficult, BFD's concept of relocations
278 is far too simple to handle SOM relocations. The basic assumption
279 that a relocation can be completely processed independent of other
280 relocations before an object file is written is invalid for SOM.
281
282 The SOM relocations are meant to be processed as a stream, they
283 specify copying of data from the input section to the output section
284 while possibly modifying the data in some manner. They also can
285 specify that a variable number of zeros or uninitialized data be
286 inserted on in the output segment at the current offset. Some
287 relocations specify that some previous relocation be re-applied at
288 the current location in the input/output sections. And finally a number
289 of relocations have effects on other sections (R_ENTRY, R_EXIT,
290 R_UNWIND_AUX and a variety of others). There isn't even enough room
291 in the BFD relocation data structure to store enough information to
292 perform all the relocations.
293
294 Each entry in the table has three fields.
295
296 The first entry is an index into this "class" of relocations. This
297 index can then be used as a variable within the relocation itself.
298
299 The second field is a format string which actually controls processing
300 of the relocation. It uses a simple postfix machine to do calculations
301 based on variables/constants found in the string and the relocation
302 stream.
303
304 The third field specifys whether or not this relocation may use
305 a constant (V) from the previous R_DATA_OVERRIDE rather than a constant
306 stored in the instruction.
307
308 Variables:
309
310 L = input space byte count
311 D = index into class of relocations
312 M = output space byte count
313 N = statement number (unused?)
314 O = stack operation
315 R = parameter relocation bits
316 S = symbol index
317 U = 64 bits of stack unwind and frame size info (we only keep 32 bits)
318 V = a literal constant (usually used in the next relocation)
319 P = a previous relocation
320
321 Lower case letters (starting with 'b') refer to following
322 bytes in the relocation stream. 'b' is the next 1 byte,
323 c is the next 2 bytes, d is the next 3 bytes, etc...
324 This is the variable part of the relocation entries that
325 makes our life a living hell.
326
327 numerical constants are also used in the format string. Note
328 the constants are represented in decimal.
329
330 '+', "*" and "=" represents the obvious postfix operators.
331 '<' represents a left shift.
332
333 Stack Operations:
334
335 Parameter Relocation Bits:
336
337 Unwind Entries:
338
339 Previous Relocations: The index field represents which in the queue
340 of 4 previous fixups should be re-applied.
341
342 Literal Constants: These are generally used to represent addend
343 parts of relocations when these constants are not stored in the
344 fields of the instructions themselves. For example the instruction
345 addil foo-$global$-0x1234 would use an override for "0x1234" rather
346 than storing it into the addil itself. */
347
348 struct fixup_format
349 {
350 int D;
351 char *format;
352 };
353
354 static const struct fixup_format som_fixup_formats[256] =
355 {
356 /* R_NO_RELOCATION */
357 0, "LD1+4*=", /* 0x00 */
358 1, "LD1+4*=", /* 0x01 */
359 2, "LD1+4*=", /* 0x02 */
360 3, "LD1+4*=", /* 0x03 */
361 4, "LD1+4*=", /* 0x04 */
362 5, "LD1+4*=", /* 0x05 */
363 6, "LD1+4*=", /* 0x06 */
364 7, "LD1+4*=", /* 0x07 */
365 8, "LD1+4*=", /* 0x08 */
366 9, "LD1+4*=", /* 0x09 */
367 10, "LD1+4*=", /* 0x0a */
368 11, "LD1+4*=", /* 0x0b */
369 12, "LD1+4*=", /* 0x0c */
370 13, "LD1+4*=", /* 0x0d */
371 14, "LD1+4*=", /* 0x0e */
372 15, "LD1+4*=", /* 0x0f */
373 16, "LD1+4*=", /* 0x10 */
374 17, "LD1+4*=", /* 0x11 */
375 18, "LD1+4*=", /* 0x12 */
376 19, "LD1+4*=", /* 0x13 */
377 20, "LD1+4*=", /* 0x14 */
378 21, "LD1+4*=", /* 0x15 */
379 22, "LD1+4*=", /* 0x16 */
380 23, "LD1+4*=", /* 0x17 */
381 0, "LD8<b+1+4*=", /* 0x18 */
382 1, "LD8<b+1+4*=", /* 0x19 */
383 2, "LD8<b+1+4*=", /* 0x1a */
384 3, "LD8<b+1+4*=", /* 0x1b */
385 0, "LD16<c+1+4*=", /* 0x1c */
386 1, "LD16<c+1+4*=", /* 0x1d */
387 2, "LD16<c+1+4*=", /* 0x1e */
388 0, "Ld1+=", /* 0x1f */
389 /* R_ZEROES */
390 0, "Lb1+4*=", /* 0x20 */
391 1, "Ld1+=", /* 0x21 */
392 /* R_UNINIT */
393 0, "Lb1+4*=", /* 0x22 */
394 1, "Ld1+=", /* 0x23 */
395 /* R_RELOCATION */
396 0, "L4=", /* 0x24 */
397 /* R_DATA_ONE_SYMBOL */
398 0, "L4=Sb=", /* 0x25 */
399 1, "L4=Sd=", /* 0x26 */
400 /* R_DATA_PLEBEL */
401 0, "L4=Sb=", /* 0x27 */
402 1, "L4=Sd=", /* 0x28 */
403 /* R_SPACE_REF */
404 0, "L4=", /* 0x29 */
405 /* R_REPEATED_INIT */
406 0, "L4=Mb1+4*=", /* 0x2a */
407 1, "Lb4*=Mb1+L*=", /* 0x2b */
408 2, "Lb4*=Md1+4*=", /* 0x2c */
409 3, "Ld1+=Me1+=", /* 0x2d */
410 /* R_RESERVED */
411 0, "", /* 0x2e */
412 0, "", /* 0x2f */
413 /* R_PCREL_CALL */
414 0, "L4=RD=Sb=", /* 0x30 */
415 1, "L4=RD=Sb=", /* 0x31 */
416 2, "L4=RD=Sb=", /* 0x32 */
417 3, "L4=RD=Sb=", /* 0x33 */
418 4, "L4=RD=Sb=", /* 0x34 */
419 5, "L4=RD=Sb=", /* 0x35 */
420 6, "L4=RD=Sb=", /* 0x36 */
421 7, "L4=RD=Sb=", /* 0x37 */
422 8, "L4=RD=Sb=", /* 0x38 */
423 9, "L4=RD=Sb=", /* 0x39 */
424 0, "L4=RD8<b+=Sb=",/* 0x3a */
425 1, "L4=RD8<b+=Sb=",/* 0x3b */
426 0, "L4=RD8<b+=Sd=",/* 0x3c */
427 1, "L4=RD8<b+=Sd=",/* 0x3d */
428 /* R_RESERVED */
429 0, "", /* 0x3e */
430 0, "", /* 0x3f */
431 /* R_ABS_CALL */
432 0, "L4=RD=Sb=", /* 0x40 */
433 1, "L4=RD=Sb=", /* 0x41 */
434 2, "L4=RD=Sb=", /* 0x42 */
435 3, "L4=RD=Sb=", /* 0x43 */
436 4, "L4=RD=Sb=", /* 0x44 */
437 5, "L4=RD=Sb=", /* 0x45 */
438 6, "L4=RD=Sb=", /* 0x46 */
439 7, "L4=RD=Sb=", /* 0x47 */
440 8, "L4=RD=Sb=", /* 0x48 */
441 9, "L4=RD=Sb=", /* 0x49 */
442 0, "L4=RD8<b+=Sb=",/* 0x4a */
443 1, "L4=RD8<b+=Sb=",/* 0x4b */
444 0, "L4=RD8<b+=Sd=",/* 0x4c */
445 1, "L4=RD8<b+=Sd=",/* 0x4d */
446 /* R_RESERVED */
447 0, "", /* 0x4e */
448 0, "", /* 0x4f */
449 /* R_DP_RELATIVE */
450 0, "L4=SD=", /* 0x50 */
451 1, "L4=SD=", /* 0x51 */
452 2, "L4=SD=", /* 0x52 */
453 3, "L4=SD=", /* 0x53 */
454 4, "L4=SD=", /* 0x54 */
455 5, "L4=SD=", /* 0x55 */
456 6, "L4=SD=", /* 0x56 */
457 7, "L4=SD=", /* 0x57 */
458 8, "L4=SD=", /* 0x58 */
459 9, "L4=SD=", /* 0x59 */
460 10, "L4=SD=", /* 0x5a */
461 11, "L4=SD=", /* 0x5b */
462 12, "L4=SD=", /* 0x5c */
463 13, "L4=SD=", /* 0x5d */
464 14, "L4=SD=", /* 0x5e */
465 15, "L4=SD=", /* 0x5f */
466 16, "L4=SD=", /* 0x60 */
467 17, "L4=SD=", /* 0x61 */
468 18, "L4=SD=", /* 0x62 */
469 19, "L4=SD=", /* 0x63 */
470 20, "L4=SD=", /* 0x64 */
471 21, "L4=SD=", /* 0x65 */
472 22, "L4=SD=", /* 0x66 */
473 23, "L4=SD=", /* 0x67 */
474 24, "L4=SD=", /* 0x68 */
475 25, "L4=SD=", /* 0x69 */
476 26, "L4=SD=", /* 0x6a */
477 27, "L4=SD=", /* 0x6b */
478 28, "L4=SD=", /* 0x6c */
479 29, "L4=SD=", /* 0x6d */
480 30, "L4=SD=", /* 0x6e */
481 31, "L4=SD=", /* 0x6f */
482 32, "L4=Sb=", /* 0x70 */
483 33, "L4=Sd=", /* 0x71 */
484 /* R_RESERVED */
485 0, "", /* 0x72 */
486 0, "", /* 0x73 */
487 0, "", /* 0x74 */
488 0, "", /* 0x75 */
489 0, "", /* 0x76 */
490 0, "", /* 0x77 */
491 /* R_DLT_REL */
492 0, "L4=Sb=", /* 0x78 */
493 1, "L4=Sd=", /* 0x79 */
494 /* R_RESERVED */
495 0, "", /* 0x7a */
496 0, "", /* 0x7b */
497 0, "", /* 0x7c */
498 0, "", /* 0x7d */
499 0, "", /* 0x7e */
500 0, "", /* 0x7f */
501 /* R_CODE_ONE_SYMBOL */
502 0, "L4=SD=", /* 0x80 */
503 1, "L4=SD=", /* 0x81 */
504 2, "L4=SD=", /* 0x82 */
505 3, "L4=SD=", /* 0x83 */
506 4, "L4=SD=", /* 0x84 */
507 5, "L4=SD=", /* 0x85 */
508 6, "L4=SD=", /* 0x86 */
509 7, "L4=SD=", /* 0x87 */
510 8, "L4=SD=", /* 0x88 */
511 9, "L4=SD=", /* 0x89 */
512 10, "L4=SD=", /* 0x8q */
513 11, "L4=SD=", /* 0x8b */
514 12, "L4=SD=", /* 0x8c */
515 13, "L4=SD=", /* 0x8d */
516 14, "L4=SD=", /* 0x8e */
517 15, "L4=SD=", /* 0x8f */
518 16, "L4=SD=", /* 0x90 */
519 17, "L4=SD=", /* 0x91 */
520 18, "L4=SD=", /* 0x92 */
521 19, "L4=SD=", /* 0x93 */
522 20, "L4=SD=", /* 0x94 */
523 21, "L4=SD=", /* 0x95 */
524 22, "L4=SD=", /* 0x96 */
525 23, "L4=SD=", /* 0x97 */
526 24, "L4=SD=", /* 0x98 */
527 25, "L4=SD=", /* 0x99 */
528 26, "L4=SD=", /* 0x9a */
529 27, "L4=SD=", /* 0x9b */
530 28, "L4=SD=", /* 0x9c */
531 29, "L4=SD=", /* 0x9d */
532 30, "L4=SD=", /* 0x9e */
533 31, "L4=SD=", /* 0x9f */
534 32, "L4=Sb=", /* 0xa0 */
535 33, "L4=Sd=", /* 0xa1 */
536 /* R_RESERVED */
537 0, "", /* 0xa2 */
538 0, "", /* 0xa3 */
539 0, "", /* 0xa4 */
540 0, "", /* 0xa5 */
541 0, "", /* 0xa6 */
542 0, "", /* 0xa7 */
543 0, "", /* 0xa8 */
544 0, "", /* 0xa9 */
545 0, "", /* 0xaa */
546 0, "", /* 0xab */
547 0, "", /* 0xac */
548 0, "", /* 0xad */
549 /* R_MILLI_REL */
550 0, "L4=Sb=", /* 0xae */
551 1, "L4=Sd=", /* 0xaf */
552 /* R_CODE_PLABEL */
553 0, "L4=Sb=", /* 0xb0 */
554 1, "L4=Sd=", /* 0xb1 */
555 /* R_BREAKPOINT */
556 0, "L4=", /* 0xb2 */
557 /* R_ENTRY */
558 0, "Ui=", /* 0xb3 */
559 1, "Uf=", /* 0xb4 */
560 /* R_ALT_ENTRY */
561 0, "", /* 0xb5 */
562 /* R_EXIT */
563 0, "", /* 0xb6 */
564 /* R_BEGIN_TRY */
565 0, "", /* 0xb7 */
566 /* R_END_TRY */
567 0, "R0=", /* 0xb8 */
568 1, "Rb4*=", /* 0xb9 */
569 2, "Rd4*=", /* 0xba */
570 /* R_BEGIN_BRTAB */
571 0, "", /* 0xbb */
572 /* R_END_BRTAB */
573 0, "", /* 0xbc */
574 /* R_STATEMENT */
575 0, "Nb=", /* 0xbd */
576 1, "Nc=", /* 0xbe */
577 2, "Nd=", /* 0xbf */
578 /* R_DATA_EXPR */
579 0, "L4=", /* 0xc0 */
580 /* R_CODE_EXPR */
581 0, "L4=", /* 0xc1 */
582 /* R_FSEL */
583 0, "", /* 0xc2 */
584 /* R_LSEL */
585 0, "", /* 0xc3 */
586 /* R_RSEL */
587 0, "", /* 0xc4 */
588 /* R_N_MODE */
589 0, "", /* 0xc5 */
590 /* R_S_MODE */
591 0, "", /* 0xc6 */
592 /* R_D_MODE */
593 0, "", /* 0xc7 */
594 /* R_R_MODE */
595 0, "", /* 0xc8 */
596 /* R_DATA_OVERRIDE */
597 0, "V0=", /* 0xc9 */
598 1, "Vb=", /* 0xca */
599 2, "Vc=", /* 0xcb */
600 3, "Vd=", /* 0xcc */
601 4, "Ve=", /* 0xcd */
602 /* R_TRANSLATED */
603 0, "", /* 0xce */
604 /* R_RESERVED */
605 0, "", /* 0xcf */
606 /* R_COMP1 */
607 0, "Ob=", /* 0xd0 */
608 /* R_COMP2 */
609 0, "Ob=Sd=", /* 0xd1 */
610 /* R_COMP3 */
611 0, "Ob=Ve=", /* 0xd2 */
612 /* R_PREV_FIXUP */
613 0, "P", /* 0xd3 */
614 1, "P", /* 0xd4 */
615 2, "P", /* 0xd5 */
616 3, "P", /* 0xd6 */
617 /* R_RESERVED */
618 0, "", /* 0xd7 */
619 0, "", /* 0xd8 */
620 0, "", /* 0xd9 */
621 0, "", /* 0xda */
622 0, "", /* 0xdb */
623 0, "", /* 0xdc */
624 0, "", /* 0xdd */
625 0, "", /* 0xde */
626 0, "", /* 0xdf */
627 0, "", /* 0xe0 */
628 0, "", /* 0xe1 */
629 0, "", /* 0xe2 */
630 0, "", /* 0xe3 */
631 0, "", /* 0xe4 */
632 0, "", /* 0xe5 */
633 0, "", /* 0xe6 */
634 0, "", /* 0xe7 */
635 0, "", /* 0xe8 */
636 0, "", /* 0xe9 */
637 0, "", /* 0xea */
638 0, "", /* 0xeb */
639 0, "", /* 0xec */
640 0, "", /* 0xed */
641 0, "", /* 0xee */
642 0, "", /* 0xef */
643 0, "", /* 0xf0 */
644 0, "", /* 0xf1 */
645 0, "", /* 0xf2 */
646 0, "", /* 0xf3 */
647 0, "", /* 0xf4 */
648 0, "", /* 0xf5 */
649 0, "", /* 0xf6 */
650 0, "", /* 0xf7 */
651 0, "", /* 0xf8 */
652 0, "", /* 0xf9 */
653 0, "", /* 0xfa */
654 0, "", /* 0xfb */
655 0, "", /* 0xfc */
656 0, "", /* 0xfd */
657 0, "", /* 0xfe */
658 0, "", /* 0xff */
659 };
660
661 static const int comp1_opcodes[] =
662 {
663 0x00,
664 0x40,
665 0x41,
666 0x42,
667 0x43,
668 0x44,
669 0x45,
670 0x46,
671 0x47,
672 0x48,
673 0x49,
674 0x4a,
675 0x4b,
676 0x60,
677 0x80,
678 0xa0,
679 0xc0,
680 -1
681 };
682
683 static const int comp2_opcodes[] =
684 {
685 0x00,
686 0x80,
687 0x82,
688 0xc0,
689 -1
690 };
691
692 static const int comp3_opcodes[] =
693 {
694 0x00,
695 0x02,
696 -1
697 };
698
699 /* These apparently are not in older versions of hpux reloc.h. */
700 #ifndef R_DLT_REL
701 #define R_DLT_REL 0x78
702 #endif
703
704 #ifndef R_AUX_UNWIND
705 #define R_AUX_UNWIND 0xcf
706 #endif
707
708 #ifndef R_SEC_STMT
709 #define R_SEC_STMT 0xd7
710 #endif
711
712 static reloc_howto_type som_hppa_howto_table[] =
713 {
714 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
715 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
716 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
717 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
718 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
719 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
720 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
721 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
722 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
723 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
724 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
725 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
726 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
727 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
728 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
729 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
730 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
731 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
732 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
733 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
734 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
735 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
736 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
737 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
738 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
739 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
740 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
741 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
742 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
743 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
744 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
745 {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
746 {R_ZEROES, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ZEROES"},
747 {R_ZEROES, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ZEROES"},
748 {R_UNINIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_UNINIT"},
749 {R_UNINIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_UNINIT"},
750 {R_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RELOCATION"},
751 {R_DATA_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_ONE_SYMBOL"},
752 {R_DATA_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_ONE_SYMBOL"},
753 {R_DATA_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_PLABEL"},
754 {R_DATA_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_PLABEL"},
755 {R_SPACE_REF, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SPACE_REF"},
756 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
757 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
758 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
759 {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
760 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
761 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
762 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
763 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
764 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
765 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
766 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
767 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
768 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
769 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
770 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
771 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
772 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
773 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
774 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
775 {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
776 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
777 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
778 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
779 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
780 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
781 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
782 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
783 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
784 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
785 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
786 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
787 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
788 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
789 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
790 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
791 {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
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_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
795 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
796 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
797 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
798 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
799 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
800 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
801 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
802 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
803 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
804 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
805 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
806 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
807 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
808 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
809 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
810 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
811 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
812 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
813 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
814 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
815 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
816 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
817 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
818 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
819 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
820 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
821 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
822 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
823 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
824 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
825 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
826 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
827 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
828 {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
829 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
830 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
831 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
832 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
833 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
834 {R_DLT_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DLT_REL"},
835 {R_DLT_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DLT_REL"},
836 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
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_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
843 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
844 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
845 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
846 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
847 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
848 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
849 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
850 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
851 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
852 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
853 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
854 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
855 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
856 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
857 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
858 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
859 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
860 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
861 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
862 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
863 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
864 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
865 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
866 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
867 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
868 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
869 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
870 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
871 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
872 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
873 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
874 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
875 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
876 {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
877 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
878 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
879 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
880 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
881 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
882 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
883 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
884 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
885 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
886 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
887 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
888 {R_MILLI_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_MILLI_REL"},
889 {R_MILLI_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_MILLI_REL"},
890 {R_CODE_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_PLABEL"},
891 {R_CODE_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_PLABEL"},
892 {R_BREAKPOINT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BREAKPOINT"},
893 {R_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ENTRY"},
894 {R_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ENTRY"},
895 {R_ALT_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ALT_ENTRY"},
896 {R_EXIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_EXIT"},
897 {R_BEGIN_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BEGIN_TRY"},
898 {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
899 {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
900 {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
901 {R_BEGIN_BRTAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BEGIN_BRTAB"},
902 {R_END_BRTAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_BRTAB"},
903 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
904 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
905 {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
906 {R_DATA_EXPR, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_EXPR"},
907 {R_CODE_EXPR, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_EXPR"},
908 {R_FSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_FSEL"},
909 {R_LSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LSEL"},
910 {R_RSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RSEL"},
911 {R_N_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N_MODE"},
912 {R_S_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_S_MODE"},
913 {R_D_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_D_MODE"},
914 {R_R_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_R_MODE"},
915 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
916 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
917 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
918 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
919 {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
920 {R_TRANSLATED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_TRANSLATED"},
921 {R_AUX_UNWIND, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_AUX_UNWIND"},
922 {R_COMP1, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP1"},
923 {R_COMP2, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP2"},
924 {R_COMP3, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP3"},
925 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
926 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
927 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
928 {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
929 {R_SEC_STMT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SEC_STMT"},
930 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
931 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
932 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
933 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
934 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
935 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
936 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
937 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
938 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
939 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
940 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
941 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
942 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
943 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
944 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
945 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
946 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
947 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
948 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
949 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
950 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
951 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
952 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
953 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
954 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
955 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
956 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
957 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
958 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
959 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
960 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
961 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
962 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
963 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
964 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
965 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
966 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
967 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
968 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
969 {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"}};
970
971 /* Initialize the SOM relocation queue. By definition the queue holds
972 the last four multibyte fixups. */
973
974 static void
975 som_initialize_reloc_queue (queue)
976 struct reloc_queue *queue;
977 {
978 queue[0].reloc = NULL;
979 queue[0].size = 0;
980 queue[1].reloc = NULL;
981 queue[1].size = 0;
982 queue[2].reloc = NULL;
983 queue[2].size = 0;
984 queue[3].reloc = NULL;
985 queue[3].size = 0;
986 }
987
988 /* Insert a new relocation into the relocation queue. */
989
990 static void
991 som_reloc_queue_insert (p, size, queue)
992 unsigned char *p;
993 unsigned int size;
994 struct reloc_queue *queue;
995 {
996 queue[3].reloc = queue[2].reloc;
997 queue[3].size = queue[2].size;
998 queue[2].reloc = queue[1].reloc;
999 queue[2].size = queue[1].size;
1000 queue[1].reloc = queue[0].reloc;
1001 queue[1].size = queue[0].size;
1002 queue[0].reloc = p;
1003 queue[0].size = size;
1004 }
1005
1006 /* When an entry in the relocation queue is reused, the entry moves
1007 to the front of the queue. */
1008
1009 static void
1010 som_reloc_queue_fix (queue, index)
1011 struct reloc_queue *queue;
1012 unsigned int index;
1013 {
1014 if (index == 0)
1015 return;
1016
1017 if (index == 1)
1018 {
1019 unsigned char *tmp1 = queue[0].reloc;
1020 unsigned int tmp2 = queue[0].size;
1021 queue[0].reloc = queue[1].reloc;
1022 queue[0].size = queue[1].size;
1023 queue[1].reloc = tmp1;
1024 queue[1].size = tmp2;
1025 return;
1026 }
1027
1028 if (index == 2)
1029 {
1030 unsigned char *tmp1 = queue[0].reloc;
1031 unsigned int tmp2 = queue[0].size;
1032 queue[0].reloc = queue[2].reloc;
1033 queue[0].size = queue[2].size;
1034 queue[2].reloc = queue[1].reloc;
1035 queue[2].size = queue[1].size;
1036 queue[1].reloc = tmp1;
1037 queue[1].size = tmp2;
1038 return;
1039 }
1040
1041 if (index == 3)
1042 {
1043 unsigned char *tmp1 = queue[0].reloc;
1044 unsigned int tmp2 = queue[0].size;
1045 queue[0].reloc = queue[3].reloc;
1046 queue[0].size = queue[3].size;
1047 queue[3].reloc = queue[2].reloc;
1048 queue[3].size = queue[2].size;
1049 queue[2].reloc = queue[1].reloc;
1050 queue[2].size = queue[1].size;
1051 queue[1].reloc = tmp1;
1052 queue[1].size = tmp2;
1053 return;
1054 }
1055 abort();
1056 }
1057
1058 /* Search for a particular relocation in the relocation queue. */
1059
1060 static int
1061 som_reloc_queue_find (p, size, queue)
1062 unsigned char *p;
1063 unsigned int size;
1064 struct reloc_queue *queue;
1065 {
1066 if (queue[0].reloc && !bcmp (p, queue[0].reloc, size)
1067 && size == queue[0].size)
1068 return 0;
1069 if (queue[1].reloc && !bcmp (p, queue[1].reloc, size)
1070 && size == queue[1].size)
1071 return 1;
1072 if (queue[2].reloc && !bcmp (p, queue[2].reloc, size)
1073 && size == queue[2].size)
1074 return 2;
1075 if (queue[3].reloc && !bcmp (p, queue[3].reloc, size)
1076 && size == queue[3].size)
1077 return 3;
1078 return -1;
1079 }
1080
1081 static unsigned char *
1082 try_prev_fixup (abfd, subspace_reloc_sizep, p, size, queue)
1083 bfd *abfd;
1084 int *subspace_reloc_sizep;
1085 unsigned char *p;
1086 unsigned int size;
1087 struct reloc_queue *queue;
1088 {
1089 int queue_index = som_reloc_queue_find (p, size, queue);
1090
1091 if (queue_index != -1)
1092 {
1093 /* Found this in a previous fixup. Undo the fixup we
1094 just built and use R_PREV_FIXUP instead. We saved
1095 a total of size - 1 bytes in the fixup stream. */
1096 bfd_put_8 (abfd, R_PREV_FIXUP + queue_index, p);
1097 p += 1;
1098 *subspace_reloc_sizep += 1;
1099 som_reloc_queue_fix (queue, queue_index);
1100 }
1101 else
1102 {
1103 som_reloc_queue_insert (p, size, queue);
1104 *subspace_reloc_sizep += size;
1105 p += size;
1106 }
1107 return p;
1108 }
1109
1110 /* Emit the proper R_NO_RELOCATION fixups to map the next SKIP
1111 bytes without any relocation. Update the size of the subspace
1112 relocation stream via SUBSPACE_RELOC_SIZE_P; also return the
1113 current pointer into the relocation stream. */
1114
1115 static unsigned char *
1116 som_reloc_skip (abfd, skip, p, subspace_reloc_sizep, queue)
1117 bfd *abfd;
1118 unsigned int skip;
1119 unsigned char *p;
1120 unsigned int *subspace_reloc_sizep;
1121 struct reloc_queue *queue;
1122 {
1123 /* Use a 4 byte R_NO_RELOCATION entry with a maximal value
1124 then R_PREV_FIXUPs to get the difference down to a
1125 reasonable size. */
1126 if (skip >= 0x1000000)
1127 {
1128 skip -= 0x1000000;
1129 bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
1130 bfd_put_8 (abfd, 0xff, p + 1);
1131 bfd_put_16 (abfd, 0xffff, p + 2);
1132 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
1133 while (skip >= 0x1000000)
1134 {
1135 skip -= 0x1000000;
1136 bfd_put_8 (abfd, R_PREV_FIXUP, p);
1137 p++;
1138 *subspace_reloc_sizep += 1;
1139 /* No need to adjust queue here since we are repeating the
1140 most recent fixup. */
1141 }
1142 }
1143
1144 /* The difference must be less than 0x1000000. Use one
1145 more R_NO_RELOCATION entry to get to the right difference. */
1146 if ((skip & 3) == 0 && skip <= 0xc0000 && skip > 0)
1147 {
1148 /* Difference can be handled in a simple single-byte
1149 R_NO_RELOCATION entry. */
1150 if (skip <= 0x60)
1151 {
1152 bfd_put_8 (abfd, R_NO_RELOCATION + (skip >> 2) - 1, p);
1153 *subspace_reloc_sizep += 1;
1154 p++;
1155 }
1156 /* Handle it with a two byte R_NO_RELOCATION entry. */
1157 else if (skip <= 0x1000)
1158 {
1159 bfd_put_8 (abfd, R_NO_RELOCATION + 24 + (((skip >> 2) - 1) >> 8), p);
1160 bfd_put_8 (abfd, (skip >> 2) - 1, p + 1);
1161 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1162 }
1163 /* Handle it with a three byte R_NO_RELOCATION entry. */
1164 else
1165 {
1166 bfd_put_8 (abfd, R_NO_RELOCATION + 28 + (((skip >> 2) - 1) >> 16), p);
1167 bfd_put_16 (abfd, (skip >> 2) - 1, p + 1);
1168 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1169 }
1170 }
1171 /* Ugh. Punt and use a 4 byte entry. */
1172 else if (skip > 0)
1173 {
1174 bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
1175 bfd_put_8 (abfd, skip >> 16, p + 1);
1176 bfd_put_16 (abfd, skip, p + 2);
1177 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
1178 }
1179 return p;
1180 }
1181
1182 /* Emit the proper R_DATA_OVERRIDE fixups to handle a nonzero addend
1183 from a BFD relocation. Update the size of the subspace relocation
1184 stream via SUBSPACE_RELOC_SIZE_P; also return the current pointer
1185 into the relocation stream. */
1186
1187 static unsigned char *
1188 som_reloc_addend (abfd, addend, p, subspace_reloc_sizep, queue)
1189 bfd *abfd;
1190 int addend;
1191 unsigned char *p;
1192 unsigned int *subspace_reloc_sizep;
1193 struct reloc_queue *queue;
1194 {
1195 if ((unsigned)(addend) + 0x80 < 0x100)
1196 {
1197 bfd_put_8 (abfd, R_DATA_OVERRIDE + 1, p);
1198 bfd_put_8 (abfd, addend, p + 1);
1199 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1200 }
1201 else if ((unsigned) (addend) + 0x8000 < 0x10000)
1202 {
1203 bfd_put_8 (abfd, R_DATA_OVERRIDE + 2, p);
1204 bfd_put_16 (abfd, addend, p + 1);
1205 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1206 }
1207 else if ((unsigned) (addend) + 0x800000 < 0x1000000)
1208 {
1209 bfd_put_8 (abfd, R_DATA_OVERRIDE + 3, p);
1210 bfd_put_8 (abfd, addend >> 16, p + 1);
1211 bfd_put_16 (abfd, addend, p + 2);
1212 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
1213 }
1214 else
1215 {
1216 bfd_put_8 (abfd, R_DATA_OVERRIDE + 4, p);
1217 bfd_put_32 (abfd, addend, p + 1);
1218 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
1219 }
1220 return p;
1221 }
1222
1223 /* Handle a single function call relocation. */
1224
1225 static unsigned char *
1226 som_reloc_call (abfd, p, subspace_reloc_sizep, bfd_reloc, sym_num, queue)
1227 bfd *abfd;
1228 unsigned char *p;
1229 unsigned int *subspace_reloc_sizep;
1230 arelent *bfd_reloc;
1231 int sym_num;
1232 struct reloc_queue *queue;
1233 {
1234 int arg_bits = HPPA_R_ARG_RELOC (bfd_reloc->addend);
1235 int rtn_bits = arg_bits & 0x3;
1236 int type, done = 0;
1237
1238 /* You'll never believe all this is necessary to handle relocations
1239 for function calls. Having to compute and pack the argument
1240 relocation bits is the real nightmare.
1241
1242 If you're interested in how this works, just forget it. You really
1243 do not want to know about this braindamage. */
1244
1245 /* First see if this can be done with a "simple" relocation. Simple
1246 relocations have a symbol number < 0x100 and have simple encodings
1247 of argument relocations. */
1248
1249 if (sym_num < 0x100)
1250 {
1251 switch (arg_bits)
1252 {
1253 case 0:
1254 case 1:
1255 type = 0;
1256 break;
1257 case 1 << 8:
1258 case 1 << 8 | 1:
1259 type = 1;
1260 break;
1261 case 1 << 8 | 1 << 6:
1262 case 1 << 8 | 1 << 6 | 1:
1263 type = 2;
1264 break;
1265 case 1 << 8 | 1 << 6 | 1 << 4:
1266 case 1 << 8 | 1 << 6 | 1 << 4 | 1:
1267 type = 3;
1268 break;
1269 case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2:
1270 case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1:
1271 type = 4;
1272 break;
1273 default:
1274 /* Not one of the easy encodings. This will have to be
1275 handled by the more complex code below. */
1276 type = -1;
1277 break;
1278 }
1279 if (type != -1)
1280 {
1281 /* Account for the return value too. */
1282 if (rtn_bits)
1283 type += 5;
1284
1285 /* Emit a 2 byte relocation. Then see if it can be handled
1286 with a relocation which is already in the relocation queue. */
1287 bfd_put_8 (abfd, bfd_reloc->howto->type + type, p);
1288 bfd_put_8 (abfd, sym_num, p + 1);
1289 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1290 done = 1;
1291 }
1292 }
1293
1294 /* If this could not be handled with a simple relocation, then do a hard
1295 one. Hard relocations occur if the symbol number was too high or if
1296 the encoding of argument relocation bits is too complex. */
1297 if (! done)
1298 {
1299 /* Don't ask about these magic sequences. I took them straight
1300 from gas-1.36 which took them from the a.out man page. */
1301 type = rtn_bits;
1302 if ((arg_bits >> 6 & 0xf) == 0xe)
1303 type += 9 * 40;
1304 else
1305 type += (3 * (arg_bits >> 8 & 3) + (arg_bits >> 6 & 3)) * 40;
1306 if ((arg_bits >> 2 & 0xf) == 0xe)
1307 type += 9 * 4;
1308 else
1309 type += (3 * (arg_bits >> 4 & 3) + (arg_bits >> 2 & 3)) * 4;
1310
1311 /* Output the first two bytes of the relocation. These describe
1312 the length of the relocation and encoding style. */
1313 bfd_put_8 (abfd, bfd_reloc->howto->type + 10
1314 + 2 * (sym_num >= 0x100) + (type >= 0x100),
1315 p);
1316 bfd_put_8 (abfd, type, p + 1);
1317
1318 /* Now output the symbol index and see if this bizarre relocation
1319 just happened to be in the relocation queue. */
1320 if (sym_num < 0x100)
1321 {
1322 bfd_put_8 (abfd, sym_num, p + 2);
1323 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1324 }
1325 else
1326 {
1327 bfd_put_8 (abfd, sym_num >> 16, p + 2);
1328 bfd_put_16 (abfd, sym_num, p + 3);
1329 p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
1330 }
1331 }
1332 return p;
1333 }
1334
1335
1336 /* Return the logarithm of X, base 2, considering X unsigned.
1337 Abort -1 if X is not a power or two or is zero. */
1338
1339 static int
1340 log2 (x)
1341 unsigned int x;
1342 {
1343 int log = 0;
1344
1345 /* Test for 0 or a power of 2. */
1346 if (x == 0 || x != (x & -x))
1347 return -1;
1348
1349 while ((x >>= 1) != 0)
1350 log++;
1351 return log;
1352 }
1353
1354 static bfd_reloc_status_type
1355 hppa_som_reloc (abfd, reloc_entry, symbol_in, data,
1356 input_section, output_bfd, error_message)
1357 bfd *abfd;
1358 arelent *reloc_entry;
1359 asymbol *symbol_in;
1360 PTR data;
1361 asection *input_section;
1362 bfd *output_bfd;
1363 char **error_message;
1364 {
1365 if (output_bfd)
1366 {
1367 reloc_entry->address += input_section->output_offset;
1368 return bfd_reloc_ok;
1369 }
1370 return bfd_reloc_ok;
1371 }
1372
1373 /* Given a generic HPPA relocation type, the instruction format,
1374 and a field selector, return one or more appropriate SOM relocations. */
1375
1376 int **
1377 hppa_som_gen_reloc_type (abfd, base_type, format, field)
1378 bfd *abfd;
1379 int base_type;
1380 int format;
1381 enum hppa_reloc_field_selector_type_alt field;
1382 {
1383 int *final_type, **final_types;
1384
1385 final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 3);
1386 final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1387 if (!final_types || !final_type)
1388 {
1389 bfd_set_error (bfd_error_no_memory);
1390 return NULL;
1391 }
1392
1393 /* The field selector may require additional relocations to be
1394 generated. It's impossible to know at this moment if additional
1395 relocations will be needed, so we make them. The code to actually
1396 write the relocation/fixup stream is responsible for removing
1397 any redundant relocations. */
1398 switch (field)
1399 {
1400 case e_fsel:
1401 case e_psel:
1402 case e_lpsel:
1403 case e_rpsel:
1404 final_types[0] = final_type;
1405 final_types[1] = NULL;
1406 final_types[2] = NULL;
1407 *final_type = base_type;
1408 break;
1409
1410 case e_tsel:
1411 case e_ltsel:
1412 case e_rtsel:
1413 final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1414 if (!final_types[0])
1415 {
1416 bfd_set_error (bfd_error_no_memory);
1417 return NULL;
1418 }
1419 if (field == e_tsel)
1420 *final_types[0] = R_FSEL;
1421 else if (field == e_ltsel)
1422 *final_types[0] = R_LSEL;
1423 else
1424 *final_types[0] = R_RSEL;
1425 final_types[1] = final_type;
1426 final_types[2] = NULL;
1427 *final_type = base_type;
1428 break;
1429
1430 case e_lssel:
1431 case e_rssel:
1432 final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1433 if (!final_types[0])
1434 {
1435 bfd_set_error (bfd_error_no_memory);
1436 return NULL;
1437 }
1438 *final_types[0] = R_S_MODE;
1439 final_types[1] = final_type;
1440 final_types[2] = NULL;
1441 *final_type = base_type;
1442 break;
1443
1444 case e_lsel:
1445 case e_rsel:
1446 final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1447 if (!final_types[0])
1448 {
1449 bfd_set_error (bfd_error_no_memory);
1450 return NULL;
1451 }
1452 *final_types[0] = R_N_MODE;
1453 final_types[1] = final_type;
1454 final_types[2] = NULL;
1455 *final_type = base_type;
1456 break;
1457
1458 case e_ldsel:
1459 case e_rdsel:
1460 final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1461 if (!final_types[0])
1462 {
1463 bfd_set_error (bfd_error_no_memory);
1464 return NULL;
1465 }
1466 *final_types[0] = R_D_MODE;
1467 final_types[1] = final_type;
1468 final_types[2] = NULL;
1469 *final_type = base_type;
1470 break;
1471
1472 case e_lrsel:
1473 case e_rrsel:
1474 final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1475 if (!final_types[0])
1476 {
1477 bfd_set_error (bfd_error_no_memory);
1478 return NULL;
1479 }
1480 *final_types[0] = R_R_MODE;
1481 final_types[1] = final_type;
1482 final_types[2] = NULL;
1483 *final_type = base_type;
1484 break;
1485 }
1486
1487 switch (base_type)
1488 {
1489 case R_HPPA:
1490 /* PLABELs get their own relocation type. */
1491 if (field == e_psel
1492 || field == e_lpsel
1493 || field == e_rpsel)
1494 {
1495 /* A PLABEL relocation that has a size of 32 bits must
1496 be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */
1497 if (format == 32)
1498 *final_type = R_DATA_PLABEL;
1499 else
1500 *final_type = R_CODE_PLABEL;
1501 }
1502 /* PIC stuff. */
1503 else if (field == e_tsel
1504 || field == e_ltsel
1505 || field == e_rtsel)
1506 *final_type = R_DLT_REL;
1507 /* A relocation in the data space is always a full 32bits. */
1508 else if (format == 32)
1509 *final_type = R_DATA_ONE_SYMBOL;
1510
1511 break;
1512
1513 case R_HPPA_GOTOFF:
1514 /* More PLABEL special cases. */
1515 if (field == e_psel
1516 || field == e_lpsel
1517 || field == e_rpsel)
1518 *final_type = R_DATA_PLABEL;
1519 break;
1520
1521 case R_HPPA_NONE:
1522 case R_HPPA_ABS_CALL:
1523 case R_HPPA_PCREL_CALL:
1524 /* Right now we can default all these. */
1525 break;
1526 }
1527 return final_types;
1528 }
1529
1530 /* Return the address of the correct entry in the PA SOM relocation
1531 howto table. */
1532
1533 static const reloc_howto_type *
1534 som_bfd_reloc_type_lookup (arch, code)
1535 bfd_arch_info_type *arch;
1536 bfd_reloc_code_real_type code;
1537 {
1538 if ((int) code < (int) R_NO_RELOCATION + 255)
1539 {
1540 BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code);
1541 return &som_hppa_howto_table[(int) code];
1542 }
1543
1544 return (reloc_howto_type *) 0;
1545 }
1546
1547 /* Perform some initialization for an object. Save results of this
1548 initialization in the BFD. */
1549
1550 static bfd_target *
1551 som_object_setup (abfd, file_hdrp, aux_hdrp)
1552 bfd *abfd;
1553 struct header *file_hdrp;
1554 struct som_exec_auxhdr *aux_hdrp;
1555 {
1556 /* som_mkobject will set bfd_error if som_mkobject fails. */
1557 if (som_mkobject (abfd) != true)
1558 return 0;
1559
1560 /* Set BFD flags based on what information is available in the SOM. */
1561 abfd->flags = NO_FLAGS;
1562 if (file_hdrp->symbol_total)
1563 abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
1564
1565 switch (file_hdrp->a_magic)
1566 {
1567 case DEMAND_MAGIC:
1568 abfd->flags |= (D_PAGED | WP_TEXT | EXEC_P);
1569 break;
1570 case SHARE_MAGIC:
1571 abfd->flags |= (WP_TEXT | EXEC_P);
1572 break;
1573 case EXEC_MAGIC:
1574 abfd->flags |= (EXEC_P);
1575 break;
1576 case RELOC_MAGIC:
1577 abfd->flags |= HAS_RELOC;
1578 break;
1579 #ifdef SHL_MAGIC
1580 case SHL_MAGIC:
1581 #endif
1582 #ifdef DL_MAGIC
1583 case DL_MAGIC:
1584 #endif
1585 abfd->flags |= DYNAMIC;
1586 break;
1587
1588 default:
1589 break;
1590 }
1591
1592 bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
1593 bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
1594 bfd_get_symcount (abfd) = file_hdrp->symbol_total;
1595
1596 /* Initialize the saved symbol table and string table to NULL.
1597 Save important offsets and sizes from the SOM header into
1598 the BFD. */
1599 obj_som_stringtab (abfd) = (char *) NULL;
1600 obj_som_symtab (abfd) = (som_symbol_type *) NULL;
1601 obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
1602 obj_som_sym_filepos (abfd) = file_hdrp->symbol_location;
1603 obj_som_str_filepos (abfd) = file_hdrp->symbol_strings_location;
1604 obj_som_reloc_filepos (abfd) = file_hdrp->fixup_request_location;
1605
1606 obj_som_exec_data (abfd) = (struct som_exec_data *)
1607 bfd_zalloc (abfd, sizeof (struct som_exec_data ));
1608 if (obj_som_exec_data (abfd) == NULL)
1609 {
1610 bfd_set_error (bfd_error_no_memory);
1611 return NULL;
1612 }
1613
1614 obj_som_exec_data (abfd)->system_id = file_hdrp->system_id;
1615 obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags;
1616 return abfd->xvec;
1617 }
1618
1619 /* Convert all of the space and subspace info into BFD sections. Each space
1620 contains a number of subspaces, which in turn describe the mapping between
1621 regions of the exec file, and the address space that the program runs in.
1622 BFD sections which correspond to spaces will overlap the sections for the
1623 associated subspaces. */
1624
1625 static boolean
1626 setup_sections (abfd, file_hdr)
1627 bfd *abfd;
1628 struct header *file_hdr;
1629 {
1630 char *space_strings;
1631 int space_index;
1632 unsigned int total_subspaces = 0;
1633
1634 /* First, read in space names */
1635
1636 space_strings = malloc (file_hdr->space_strings_size);
1637 if (!space_strings && file_hdr->space_strings_size != 0)
1638 {
1639 bfd_set_error (bfd_error_no_memory);
1640 goto error_return;
1641 }
1642
1643 if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
1644 goto error_return;
1645 if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd)
1646 != file_hdr->space_strings_size)
1647 goto error_return;
1648
1649 /* Loop over all of the space dictionaries, building up sections */
1650 for (space_index = 0; space_index < file_hdr->space_total; space_index++)
1651 {
1652 struct space_dictionary_record space;
1653 struct subspace_dictionary_record subspace, save_subspace;
1654 int subspace_index;
1655 asection *space_asect;
1656 char *newname;
1657
1658 /* Read the space dictionary element */
1659 if (bfd_seek (abfd, file_hdr->space_location
1660 + space_index * sizeof space, SEEK_SET) < 0)
1661 goto error_return;
1662 if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space)
1663 goto error_return;
1664
1665 /* Setup the space name string */
1666 space.name.n_name = space.name.n_strx + space_strings;
1667
1668 /* Make a section out of it */
1669 newname = bfd_alloc (abfd, strlen (space.name.n_name) + 1);
1670 if (!newname)
1671 goto error_return;
1672 strcpy (newname, space.name.n_name);
1673
1674 space_asect = bfd_make_section_anyway (abfd, newname);
1675 if (!space_asect)
1676 goto error_return;
1677
1678 if (space.is_loadable == 0)
1679 space_asect->flags |= SEC_DEBUGGING;
1680
1681 /* Set up all the attributes for the space. */
1682 if (bfd_som_set_section_attributes (space_asect, space.is_defined,
1683 space.is_private, space.sort_key,
1684 space.space_number) == false)
1685 goto error_return;
1686
1687 /* Now, read in the first subspace for this space */
1688 if (bfd_seek (abfd, file_hdr->subspace_location
1689 + space.subspace_index * sizeof subspace,
1690 SEEK_SET) < 0)
1691 goto error_return;
1692 if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace)
1693 goto error_return;
1694 /* Seek back to the start of the subspaces for loop below */
1695 if (bfd_seek (abfd, file_hdr->subspace_location
1696 + space.subspace_index * sizeof subspace,
1697 SEEK_SET) < 0)
1698 goto error_return;
1699
1700 /* Setup the start address and file loc from the first subspace record */
1701 space_asect->vma = subspace.subspace_start;
1702 space_asect->filepos = subspace.file_loc_init_value;
1703 space_asect->alignment_power = log2 (subspace.alignment);
1704 if (space_asect->alignment_power == -1)
1705 goto error_return;
1706
1707 /* Initialize save_subspace so we can reliably determine if this
1708 loop placed any useful values into it. */
1709 memset (&save_subspace, 0, sizeof (struct subspace_dictionary_record));
1710
1711 /* Loop over the rest of the subspaces, building up more sections */
1712 for (subspace_index = 0; subspace_index < space.subspace_quantity;
1713 subspace_index++)
1714 {
1715 asection *subspace_asect;
1716
1717 /* Read in the next subspace */
1718 if (bfd_read (&subspace, 1, sizeof subspace, abfd)
1719 != sizeof subspace)
1720 goto error_return;
1721
1722 /* Setup the subspace name string */
1723 subspace.name.n_name = subspace.name.n_strx + space_strings;
1724
1725 newname = bfd_alloc (abfd, strlen (subspace.name.n_name) + 1);
1726 if (!newname)
1727 goto error_return;
1728 strcpy (newname, subspace.name.n_name);
1729
1730 /* Make a section out of this subspace */
1731 subspace_asect = bfd_make_section_anyway (abfd, newname);
1732 if (!subspace_asect)
1733 goto error_return;
1734
1735 /* Store private information about the section. */
1736 if (bfd_som_set_subsection_attributes (subspace_asect, space_asect,
1737 subspace.access_control_bits,
1738 subspace.sort_key,
1739 subspace.quadrant) == false)
1740 goto error_return;
1741
1742 /* Keep an easy mapping between subspaces and sections. */
1743 subspace_asect->target_index = total_subspaces++;
1744
1745 /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
1746 by the access_control_bits in the subspace header. */
1747 switch (subspace.access_control_bits >> 4)
1748 {
1749 /* Readonly data. */
1750 case 0x0:
1751 subspace_asect->flags |= SEC_DATA | SEC_READONLY;
1752 break;
1753
1754 /* Normal data. */
1755 case 0x1:
1756 subspace_asect->flags |= SEC_DATA;
1757 break;
1758
1759 /* Readonly code and the gateways.
1760 Gateways have other attributes which do not map
1761 into anything BFD knows about. */
1762 case 0x2:
1763 case 0x4:
1764 case 0x5:
1765 case 0x6:
1766 case 0x7:
1767 subspace_asect->flags |= SEC_CODE | SEC_READONLY;
1768 break;
1769
1770 /* dynamic (writable) code. */
1771 case 0x3:
1772 subspace_asect->flags |= SEC_CODE;
1773 break;
1774 }
1775
1776 if (subspace.dup_common || subspace.is_common)
1777 subspace_asect->flags |= SEC_IS_COMMON;
1778 else if (subspace.subspace_length > 0)
1779 subspace_asect->flags |= SEC_HAS_CONTENTS;
1780
1781 if (subspace.is_loadable)
1782 subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
1783 else
1784 subspace_asect->flags |= SEC_DEBUGGING;
1785
1786 if (subspace.code_only)
1787 subspace_asect->flags |= SEC_CODE;
1788
1789 /* Both file_loc_init_value and initialization_length will
1790 be zero for a BSS like subspace. */
1791 if (subspace.file_loc_init_value == 0
1792 && subspace.initialization_length == 0)
1793 subspace_asect->flags &= ~(SEC_DATA | SEC_LOAD);
1794
1795 /* This subspace has relocations.
1796 The fixup_request_quantity is a byte count for the number of
1797 entries in the relocation stream; it is not the actual number
1798 of relocations in the subspace. */
1799 if (subspace.fixup_request_quantity != 0)
1800 {
1801 subspace_asect->flags |= SEC_RELOC;
1802 subspace_asect->rel_filepos = subspace.fixup_request_index;
1803 som_section_data (subspace_asect)->reloc_size
1804 = subspace.fixup_request_quantity;
1805 /* We can not determine this yet. When we read in the
1806 relocation table the correct value will be filled in. */
1807 subspace_asect->reloc_count = -1;
1808 }
1809
1810 /* Update save_subspace if appropriate. */
1811 if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
1812 save_subspace = subspace;
1813
1814 subspace_asect->vma = subspace.subspace_start;
1815 subspace_asect->_cooked_size = subspace.subspace_length;
1816 subspace_asect->_raw_size = subspace.subspace_length;
1817 subspace_asect->filepos = subspace.file_loc_init_value;
1818 subspace_asect->alignment_power = log2 (subspace.alignment);
1819 if (subspace_asect->alignment_power == -1)
1820 goto error_return;
1821 }
1822
1823 /* Yow! there is no subspace within the space which actually
1824 has initialized information in it; this should never happen
1825 as far as I know. */
1826 if (!save_subspace.file_loc_init_value)
1827 goto error_return;
1828
1829 /* Setup the sizes for the space section based upon the info in the
1830 last subspace of the space. */
1831 space_asect->_cooked_size = save_subspace.subspace_start
1832 - space_asect->vma + save_subspace.subspace_length;
1833 space_asect->_raw_size = save_subspace.file_loc_init_value
1834 - space_asect->filepos + save_subspace.initialization_length;
1835 }
1836 if (space_strings != NULL)
1837 free (space_strings);
1838 return true;
1839
1840 error_return:
1841 if (space_strings != NULL)
1842 free (space_strings);
1843 return false;
1844 }
1845
1846 /* Read in a SOM object and make it into a BFD. */
1847
1848 static bfd_target *
1849 som_object_p (abfd)
1850 bfd *abfd;
1851 {
1852 struct header file_hdr;
1853 struct som_exec_auxhdr aux_hdr;
1854
1855 if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
1856 {
1857 if (bfd_get_error () != bfd_error_system_call)
1858 bfd_set_error (bfd_error_wrong_format);
1859 return 0;
1860 }
1861
1862 if (!_PA_RISC_ID (file_hdr.system_id))
1863 {
1864 bfd_set_error (bfd_error_wrong_format);
1865 return 0;
1866 }
1867
1868 switch (file_hdr.a_magic)
1869 {
1870 case RELOC_MAGIC:
1871 case EXEC_MAGIC:
1872 case SHARE_MAGIC:
1873 case DEMAND_MAGIC:
1874 #ifdef DL_MAGIC
1875 case DL_MAGIC:
1876 #endif
1877 #ifdef SHL_MAGIC
1878 case SHL_MAGIC:
1879 #endif
1880 #ifdef EXECLIBMAGIC
1881 case EXECLIBMAGIC:
1882 #endif
1883 #ifdef SHARED_MAGIC_CNX
1884 case SHARED_MAGIC_CNX:
1885 #endif
1886 break;
1887 default:
1888 bfd_set_error (bfd_error_wrong_format);
1889 return 0;
1890 }
1891
1892 if (file_hdr.version_id != VERSION_ID
1893 && file_hdr.version_id != NEW_VERSION_ID)
1894 {
1895 bfd_set_error (bfd_error_wrong_format);
1896 return 0;
1897 }
1898
1899 /* If the aux_header_size field in the file header is zero, then this
1900 object is an incomplete executable (a .o file). Do not try to read
1901 a non-existant auxiliary header. */
1902 memset (&aux_hdr, 0, sizeof (struct som_exec_auxhdr));
1903 if (file_hdr.aux_header_size != 0)
1904 {
1905 if (bfd_read ((PTR) & aux_hdr, 1, AUX_HDR_SIZE, abfd) != AUX_HDR_SIZE)
1906 {
1907 if (bfd_get_error () != bfd_error_system_call)
1908 bfd_set_error (bfd_error_wrong_format);
1909 return 0;
1910 }
1911 }
1912
1913 if (!setup_sections (abfd, &file_hdr))
1914 {
1915 /* setup_sections does not bubble up a bfd error code. */
1916 bfd_set_error (bfd_error_bad_value);
1917 return 0;
1918 }
1919
1920 /* This appears to be a valid SOM object. Do some initialization. */
1921 return som_object_setup (abfd, &file_hdr, &aux_hdr);
1922 }
1923
1924 /* Create a SOM object. */
1925
1926 static boolean
1927 som_mkobject (abfd)
1928 bfd *abfd;
1929 {
1930 /* Allocate memory to hold backend information. */
1931 abfd->tdata.som_data = (struct som_data_struct *)
1932 bfd_zalloc (abfd, sizeof (struct som_data_struct));
1933 if (abfd->tdata.som_data == NULL)
1934 {
1935 bfd_set_error (bfd_error_no_memory);
1936 return false;
1937 }
1938 return true;
1939 }
1940
1941 /* Initialize some information in the file header. This routine makes
1942 not attempt at doing the right thing for a full executable; it
1943 is only meant to handle relocatable objects. */
1944
1945 static boolean
1946 som_prep_headers (abfd)
1947 bfd *abfd;
1948 {
1949 struct header *file_hdr;
1950 asection *section;
1951
1952 /* Make and attach a file header to the BFD. */
1953 file_hdr = (struct header *) bfd_zalloc (abfd, sizeof (struct header));
1954 if (file_hdr == NULL)
1955
1956 {
1957 bfd_set_error (bfd_error_no_memory);
1958 return false;
1959 }
1960 obj_som_file_hdr (abfd) = file_hdr;
1961
1962 /* FIXME. This should really be conditional based on whether or not
1963 PA1.1 instructions/registers have been used. */
1964 if (abfd->flags & (EXEC_P | DYNAMIC))
1965 file_hdr->system_id = obj_som_exec_data (abfd)->system_id;
1966 else
1967 file_hdr->system_id = CPU_PA_RISC1_0;
1968
1969 if (abfd->flags & (EXEC_P | DYNAMIC))
1970 {
1971 if (abfd->flags & D_PAGED)
1972 file_hdr->a_magic = DEMAND_MAGIC;
1973 else if (abfd->flags & WP_TEXT)
1974 file_hdr->a_magic = SHARE_MAGIC;
1975 #ifdef SHL_MAGIC
1976 else if (abfd->flags & DYNAMIC)
1977 file_hdr->a_magic = SHL_MAGIC;
1978 #endif
1979 else
1980 file_hdr->a_magic = EXEC_MAGIC;
1981 }
1982 else
1983 file_hdr->a_magic = RELOC_MAGIC;
1984
1985 /* Only new format SOM is supported. */
1986 file_hdr->version_id = NEW_VERSION_ID;
1987
1988 /* These fields are optional, and embedding timestamps is not always
1989 a wise thing to do, it makes comparing objects during a multi-stage
1990 bootstrap difficult. */
1991 file_hdr->file_time.secs = 0;
1992 file_hdr->file_time.nanosecs = 0;
1993
1994 file_hdr->entry_space = 0;
1995 file_hdr->entry_subspace = 0;
1996 file_hdr->entry_offset = 0;
1997 file_hdr->presumed_dp = 0;
1998
1999 /* Now iterate over the sections translating information from
2000 BFD sections to SOM spaces/subspaces. */
2001
2002 for (section = abfd->sections; section != NULL; section = section->next)
2003 {
2004 /* Ignore anything which has not been marked as a space or
2005 subspace. */
2006 if (!som_is_space (section) && !som_is_subspace (section))
2007 continue;
2008
2009 if (som_is_space (section))
2010 {
2011 /* Allocate space for the space dictionary. */
2012 som_section_data (section)->space_dict
2013 = (struct space_dictionary_record *)
2014 bfd_zalloc (abfd, sizeof (struct space_dictionary_record));
2015 if (som_section_data (section)->space_dict == NULL)
2016 {
2017 bfd_set_error (bfd_error_no_memory);
2018 return false;
2019 }
2020 /* Set space attributes. Note most attributes of SOM spaces
2021 are set based on the subspaces it contains. */
2022 som_section_data (section)->space_dict->loader_fix_index = -1;
2023 som_section_data (section)->space_dict->init_pointer_index = -1;
2024
2025 /* Set more attributes that were stuffed away in private data. */
2026 som_section_data (section)->space_dict->sort_key =
2027 som_section_data (section)->copy_data->sort_key;
2028 som_section_data (section)->space_dict->is_defined =
2029 som_section_data (section)->copy_data->is_defined;
2030 som_section_data (section)->space_dict->is_private =
2031 som_section_data (section)->copy_data->is_private;
2032 som_section_data (section)->space_dict->space_number =
2033 som_section_data (section)->copy_data->space_number;
2034 }
2035 else
2036 {
2037 /* Allocate space for the subspace dictionary. */
2038 som_section_data (section)->subspace_dict
2039 = (struct subspace_dictionary_record *)
2040 bfd_zalloc (abfd, sizeof (struct subspace_dictionary_record));
2041 if (som_section_data (section)->subspace_dict == NULL)
2042 {
2043 bfd_set_error (bfd_error_no_memory);
2044 return false;
2045 }
2046
2047 /* Set subspace attributes. Basic stuff is done here, additional
2048 attributes are filled in later as more information becomes
2049 available. */
2050 if (section->flags & SEC_IS_COMMON)
2051 {
2052 som_section_data (section)->subspace_dict->dup_common = 1;
2053 som_section_data (section)->subspace_dict->is_common = 1;
2054 }
2055
2056 if (section->flags & SEC_ALLOC)
2057 som_section_data (section)->subspace_dict->is_loadable = 1;
2058
2059 if (section->flags & SEC_CODE)
2060 som_section_data (section)->subspace_dict->code_only = 1;
2061
2062 som_section_data (section)->subspace_dict->subspace_start =
2063 section->vma;
2064 som_section_data (section)->subspace_dict->subspace_length =
2065 bfd_section_size (abfd, section);
2066 som_section_data (section)->subspace_dict->initialization_length =
2067 bfd_section_size (abfd, section);
2068 som_section_data (section)->subspace_dict->alignment =
2069 1 << section->alignment_power;
2070
2071 /* Set more attributes that were stuffed away in private data. */
2072 som_section_data (section)->subspace_dict->sort_key =
2073 som_section_data (section)->copy_data->sort_key;
2074 som_section_data (section)->subspace_dict->access_control_bits =
2075 som_section_data (section)->copy_data->access_control_bits;
2076 som_section_data (section)->subspace_dict->quadrant =
2077 som_section_data (section)->copy_data->quadrant;
2078 }
2079 }
2080 return true;
2081 }
2082
2083 /* Return true if the given section is a SOM space, false otherwise. */
2084
2085 static boolean
2086 som_is_space (section)
2087 asection *section;
2088 {
2089 /* If no copy data is available, then it's neither a space nor a
2090 subspace. */
2091 if (som_section_data (section)->copy_data == NULL)
2092 return false;
2093
2094 /* If the containing space isn't the same as the given section,
2095 then this isn't a space. */
2096 if (som_section_data (section)->copy_data->container != section)
2097 return false;
2098
2099 /* OK. Must be a space. */
2100 return true;
2101 }
2102
2103 /* Return true if the given section is a SOM subspace, false otherwise. */
2104
2105 static boolean
2106 som_is_subspace (section)
2107 asection *section;
2108 {
2109 /* If no copy data is available, then it's neither a space nor a
2110 subspace. */
2111 if (som_section_data (section)->copy_data == NULL)
2112 return false;
2113
2114 /* If the containing space is the same as the given section,
2115 then this isn't a subspace. */
2116 if (som_section_data (section)->copy_data->container == section)
2117 return false;
2118
2119 /* OK. Must be a subspace. */
2120 return true;
2121 }
2122
2123 /* Return true if the given space containins the given subspace. It
2124 is safe to assume space really is a space, and subspace really
2125 is a subspace. */
2126
2127 static boolean
2128 som_is_container (space, subspace)
2129 asection *space, *subspace;
2130 {
2131 return som_section_data (subspace)->copy_data->container == space;
2132 }
2133
2134 /* Count and return the number of spaces attached to the given BFD. */
2135
2136 static unsigned long
2137 som_count_spaces (abfd)
2138 bfd *abfd;
2139 {
2140 int count = 0;
2141 asection *section;
2142
2143 for (section = abfd->sections; section != NULL; section = section->next)
2144 count += som_is_space (section);
2145
2146 return count;
2147 }
2148
2149 /* Count the number of subspaces attached to the given BFD. */
2150
2151 static unsigned long
2152 som_count_subspaces (abfd)
2153 bfd *abfd;
2154 {
2155 int count = 0;
2156 asection *section;
2157
2158 for (section = abfd->sections; section != NULL; section = section->next)
2159 count += som_is_subspace (section);
2160
2161 return count;
2162 }
2163
2164 /* Return -1, 0, 1 indicating the relative ordering of sym1 and sym2.
2165
2166 We desire symbols to be ordered starting with the symbol with the
2167 highest relocation count down to the symbol with the lowest relocation
2168 count. Doing so compacts the relocation stream. */
2169
2170 static int
2171 compare_syms (sym1, sym2)
2172 asymbol **sym1;
2173 asymbol **sym2;
2174
2175 {
2176 unsigned int count1, count2;
2177
2178 /* Get relocation count for each symbol. Note that the count
2179 is stored in the udata pointer for section symbols! */
2180 if ((*sym1)->flags & BSF_SECTION_SYM)
2181 count1 = (int)(*sym1)->udata;
2182 else
2183 count1 = som_symbol_data (*sym1)->reloc_count;
2184
2185 if ((*sym2)->flags & BSF_SECTION_SYM)
2186 count2 = (int)(*sym2)->udata;
2187 else
2188 count2 = som_symbol_data (*sym2)->reloc_count;
2189
2190 /* Return the appropriate value. */
2191 if (count1 < count2)
2192 return 1;
2193 else if (count1 > count2)
2194 return -1;
2195 return 0;
2196 }
2197
2198 /* Perform various work in preparation for emitting the fixup stream. */
2199
2200 static void
2201 som_prep_for_fixups (abfd, syms, num_syms)
2202 bfd *abfd;
2203 asymbol **syms;
2204 unsigned long num_syms;
2205 {
2206 int i;
2207 asection *section;
2208
2209 /* Most SOM relocations involving a symbol have a length which is
2210 dependent on the index of the symbol. So symbols which are
2211 used often in relocations should have a small index. */
2212
2213 /* First initialize the counters for each symbol. */
2214 for (i = 0; i < num_syms; i++)
2215 {
2216 /* Handle a section symbol; these have no pointers back to the
2217 SOM symbol info. So we just use the pointer field (udata)
2218 to hold the relocation count. */
2219 if (som_symbol_data (syms[i]) == NULL
2220 || syms[i]->flags & BSF_SECTION_SYM)
2221 {
2222 syms[i]->flags |= BSF_SECTION_SYM;
2223 syms[i]->udata = (PTR) 0;
2224 }
2225 else
2226 som_symbol_data (syms[i])->reloc_count = 0;
2227 }
2228
2229 /* Now that the counters are initialized, make a weighted count
2230 of how often a given symbol is used in a relocation. */
2231 for (section = abfd->sections; section != NULL; section = section->next)
2232 {
2233 int i;
2234
2235 /* Does this section have any relocations? */
2236 if (section->reloc_count <= 0)
2237 continue;
2238
2239 /* Walk through each relocation for this section. */
2240 for (i = 1; i < section->reloc_count; i++)
2241 {
2242 arelent *reloc = section->orelocation[i];
2243 int scale;
2244
2245 /* A relocation against a symbol in the *ABS* section really
2246 does not have a symbol. Likewise if the symbol isn't associated
2247 with any section. */
2248 if (reloc->sym_ptr_ptr == NULL
2249 || (*reloc->sym_ptr_ptr)->section == &bfd_abs_section)
2250 continue;
2251
2252 /* Scaling to encourage symbols involved in R_DP_RELATIVE
2253 and R_CODE_ONE_SYMBOL relocations to come first. These
2254 two relocations have single byte versions if the symbol
2255 index is very small. */
2256 if (reloc->howto->type == R_DP_RELATIVE
2257 || reloc->howto->type == R_CODE_ONE_SYMBOL)
2258 scale = 2;
2259 else
2260 scale = 1;
2261
2262 /* Handle section symbols by ramming the count in the udata
2263 field. It will not be used and the count is very important
2264 for these symbols. */
2265 if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2266 {
2267 (*reloc->sym_ptr_ptr)->udata =
2268 (PTR) ((int) (*reloc->sym_ptr_ptr)->udata + scale);
2269 continue;
2270 }
2271
2272 /* A normal symbol. Increment the count. */
2273 som_symbol_data (*reloc->sym_ptr_ptr)->reloc_count += scale;
2274 }
2275 }
2276
2277 /* Now sort the symbols. */
2278 qsort (syms, num_syms, sizeof (asymbol *), compare_syms);
2279
2280 /* Compute the symbol indexes, they will be needed by the relocation
2281 code. */
2282 for (i = 0; i < num_syms; i++)
2283 {
2284 /* A section symbol. Again, there is no pointer to backend symbol
2285 information, so we reuse (abuse) the udata field again. */
2286 if (syms[i]->flags & BSF_SECTION_SYM)
2287 syms[i]->udata = (PTR) i;
2288 else
2289 som_symbol_data (syms[i])->index = i;
2290 }
2291 }
2292
2293 static boolean
2294 som_write_fixups (abfd, current_offset, total_reloc_sizep)
2295 bfd *abfd;
2296 unsigned long current_offset;
2297 unsigned int *total_reloc_sizep;
2298 {
2299 unsigned int i, j;
2300 /* Chunk of memory that we can use as buffer space, then throw
2301 away. */
2302 unsigned char tmp_space[SOM_TMP_BUFSIZE];
2303 unsigned char *p;
2304 unsigned int total_reloc_size = 0;
2305 unsigned int subspace_reloc_size = 0;
2306 unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
2307 asection *section = abfd->sections;
2308
2309 memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2310 p = tmp_space;
2311
2312 /* All the fixups for a particular subspace are emitted in a single
2313 stream. All the subspaces for a particular space are emitted
2314 as a single stream.
2315
2316 So, to get all the locations correct one must iterate through all the
2317 spaces, for each space iterate through its subspaces and output a
2318 fixups stream. */
2319 for (i = 0; i < num_spaces; i++)
2320 {
2321 asection *subsection;
2322
2323 /* Find a space. */
2324 while (!som_is_space (section))
2325 section = section->next;
2326
2327 /* Now iterate through each of its subspaces. */
2328 for (subsection = abfd->sections;
2329 subsection != NULL;
2330 subsection = subsection->next)
2331 {
2332 int reloc_offset, current_rounding_mode;
2333
2334 /* Find a subspace of this space. */
2335 if (!som_is_subspace (subsection)
2336 || !som_is_container (section, subsection))
2337 continue;
2338
2339 /* If this subspace does not have real data, then we are
2340 finised with it. */
2341 if ((subsection->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0)
2342 {
2343 som_section_data (subsection)->subspace_dict->fixup_request_index
2344 = -1;
2345 continue;
2346 }
2347
2348 /* This subspace has some relocations. Put the relocation stream
2349 index into the subspace record. */
2350 som_section_data (subsection)->subspace_dict->fixup_request_index
2351 = total_reloc_size;
2352
2353 /* To make life easier start over with a clean slate for
2354 each subspace. Seek to the start of the relocation stream
2355 for this subspace in preparation for writing out its fixup
2356 stream. */
2357 if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) < 0)
2358 return false;
2359
2360 /* Buffer space has already been allocated. Just perform some
2361 initialization here. */
2362 p = tmp_space;
2363 subspace_reloc_size = 0;
2364 reloc_offset = 0;
2365 som_initialize_reloc_queue (reloc_queue);
2366 current_rounding_mode = R_N_MODE;
2367
2368 /* Translate each BFD relocation into one or more SOM
2369 relocations. */
2370 for (j = 0; j < subsection->reloc_count; j++)
2371 {
2372 arelent *bfd_reloc = subsection->orelocation[j];
2373 unsigned int skip;
2374 int sym_num;
2375
2376 /* Get the symbol number. Remember it's stored in a
2377 special place for section symbols. */
2378 if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2379 sym_num = (int) (*bfd_reloc->sym_ptr_ptr)->udata;
2380 else
2381 sym_num = som_symbol_data (*bfd_reloc->sym_ptr_ptr)->index;
2382
2383 /* If there is not enough room for the next couple relocations,
2384 then dump the current buffer contents now. Also reinitialize
2385 the relocation queue.
2386
2387 No single BFD relocation could ever translate into more
2388 than 100 bytes of SOM relocations (20bytes is probably the
2389 upper limit, but leave lots of space for growth). */
2390 if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
2391 {
2392 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2393 != p - tmp_space)
2394 return false;
2395
2396 p = tmp_space;
2397 som_initialize_reloc_queue (reloc_queue);
2398 }
2399
2400 /* Emit R_NO_RELOCATION fixups to map any bytes which were
2401 skipped. */
2402 skip = bfd_reloc->address - reloc_offset;
2403 p = som_reloc_skip (abfd, skip, p,
2404 &subspace_reloc_size, reloc_queue);
2405
2406 /* Update reloc_offset for the next iteration.
2407
2408 Many relocations do not consume input bytes. They
2409 are markers, or set state necessary to perform some
2410 later relocation. */
2411 switch (bfd_reloc->howto->type)
2412 {
2413 /* This only needs to handle relocations that may be
2414 made by hppa_som_gen_reloc. */
2415 case R_ENTRY:
2416 case R_EXIT:
2417 case R_N_MODE:
2418 case R_S_MODE:
2419 case R_D_MODE:
2420 case R_R_MODE:
2421 case R_FSEL:
2422 case R_LSEL:
2423 case R_RSEL:
2424 reloc_offset = bfd_reloc->address;
2425 break;
2426
2427 default:
2428 reloc_offset = bfd_reloc->address + 4;
2429 break;
2430 }
2431
2432 /* Now the actual relocation we care about. */
2433 switch (bfd_reloc->howto->type)
2434 {
2435 case R_PCREL_CALL:
2436 case R_ABS_CALL:
2437 p = som_reloc_call (abfd, p, &subspace_reloc_size,
2438 bfd_reloc, sym_num, reloc_queue);
2439 break;
2440
2441 case R_CODE_ONE_SYMBOL:
2442 case R_DP_RELATIVE:
2443 /* Account for any addend. */
2444 if (bfd_reloc->addend)
2445 p = som_reloc_addend (abfd, bfd_reloc->addend, p,
2446 &subspace_reloc_size, reloc_queue);
2447
2448 if (sym_num < 0x20)
2449 {
2450 bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
2451 subspace_reloc_size += 1;
2452 p += 1;
2453 }
2454 else if (sym_num < 0x100)
2455 {
2456 bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
2457 bfd_put_8 (abfd, sym_num, p + 1);
2458 p = try_prev_fixup (abfd, &subspace_reloc_size, p,
2459 2, reloc_queue);
2460 }
2461 else if (sym_num < 0x10000000)
2462 {
2463 bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
2464 bfd_put_8 (abfd, sym_num >> 16, p + 1);
2465 bfd_put_16 (abfd, sym_num, p + 2);
2466 p = try_prev_fixup (abfd, &subspace_reloc_size,
2467 p, 4, reloc_queue);
2468 }
2469 else
2470 abort ();
2471 break;
2472
2473 case R_DATA_ONE_SYMBOL:
2474 case R_DATA_PLABEL:
2475 case R_CODE_PLABEL:
2476 case R_DLT_REL:
2477 /* Account for any addend. */
2478 if (bfd_reloc->addend)
2479 p = som_reloc_addend (abfd, bfd_reloc->addend, p,
2480 &subspace_reloc_size, reloc_queue);
2481
2482 if (sym_num < 0x100)
2483 {
2484 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2485 bfd_put_8 (abfd, sym_num, p + 1);
2486 p = try_prev_fixup (abfd, &subspace_reloc_size, p,
2487 2, reloc_queue);
2488 }
2489 else if (sym_num < 0x10000000)
2490 {
2491 bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
2492 bfd_put_8 (abfd, sym_num >> 16, p + 1);
2493 bfd_put_16 (abfd, sym_num, p + 2);
2494 p = try_prev_fixup (abfd, &subspace_reloc_size,
2495 p, 4, reloc_queue);
2496 }
2497 else
2498 abort ();
2499 break;
2500
2501 case R_ENTRY:
2502 {
2503 int *descp
2504 = (int *) som_symbol_data (*bfd_reloc->sym_ptr_ptr)->unwind;
2505 bfd_put_8 (abfd, R_ENTRY, p);
2506 bfd_put_32 (abfd, descp[0], p + 1);
2507 bfd_put_32 (abfd, descp[1], p + 5);
2508 p = try_prev_fixup (abfd, &subspace_reloc_size,
2509 p, 9, reloc_queue);
2510 break;
2511 }
2512
2513 case R_EXIT:
2514 bfd_put_8 (abfd, R_EXIT, p);
2515 subspace_reloc_size += 1;
2516 p += 1;
2517 break;
2518
2519 case R_N_MODE:
2520 case R_S_MODE:
2521 case R_D_MODE:
2522 case R_R_MODE:
2523 /* If this relocation requests the current rounding
2524 mode, then it is redundant. */
2525 if (bfd_reloc->howto->type != current_rounding_mode)
2526 {
2527 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2528 subspace_reloc_size += 1;
2529 p += 1;
2530 current_rounding_mode = bfd_reloc->howto->type;
2531 }
2532 break;
2533
2534 case R_FSEL:
2535 case R_LSEL:
2536 case R_RSEL:
2537 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2538 subspace_reloc_size += 1;
2539 p += 1;
2540 break;
2541
2542 /* Put a "R_RESERVED" relocation in the stream if
2543 we hit something we do not understand. The linker
2544 will complain loudly if this ever happens. */
2545 default:
2546 bfd_put_8 (abfd, 0xff, p);
2547 subspace_reloc_size += 1;
2548 p += 1;
2549 break;
2550 }
2551 }
2552
2553 /* Last BFD relocation for a subspace has been processed.
2554 Map the rest of the subspace with R_NO_RELOCATION fixups. */
2555 p = som_reloc_skip (abfd, bfd_section_size (abfd, subsection)
2556 - reloc_offset,
2557 p, &subspace_reloc_size, reloc_queue);
2558
2559 /* Scribble out the relocations. */
2560 if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2561 != p - tmp_space)
2562 return false;
2563 p = tmp_space;
2564
2565 total_reloc_size += subspace_reloc_size;
2566 som_section_data (subsection)->subspace_dict->fixup_request_quantity
2567 = subspace_reloc_size;
2568 }
2569 section = section->next;
2570 }
2571 *total_reloc_sizep = total_reloc_size;
2572 return true;
2573 }
2574
2575 /* Write out the space/subspace string table. */
2576
2577 static boolean
2578 som_write_space_strings (abfd, current_offset, string_sizep)
2579 bfd *abfd;
2580 unsigned long current_offset;
2581 unsigned int *string_sizep;
2582 {
2583 /* Chunk of memory that we can use as buffer space, then throw
2584 away. */
2585 unsigned char tmp_space[SOM_TMP_BUFSIZE];
2586 unsigned char *p;
2587 unsigned int strings_size = 0;
2588 asection *section;
2589
2590 memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2591 p = tmp_space;
2592
2593 /* Seek to the start of the space strings in preparation for writing
2594 them out. */
2595 if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
2596 return false;
2597
2598 /* Walk through all the spaces and subspaces (order is not important)
2599 building up and writing string table entries for their names. */
2600 for (section = abfd->sections; section != NULL; section = section->next)
2601 {
2602 int length;
2603
2604 /* Only work with space/subspaces; avoid any other sections
2605 which might have been made (.text for example). */
2606 if (!som_is_space (section) && !som_is_subspace (section))
2607 continue;
2608
2609 /* Get the length of the space/subspace name. */
2610 length = strlen (section->name);
2611
2612 /* If there is not enough room for the next entry, then dump the
2613 current buffer contents now. Each entry will take 4 bytes to
2614 hold the string length + the string itself + null terminator. */
2615 if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
2616 {
2617 if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd)
2618 != p - tmp_space)
2619 return false;
2620 /* Reset to beginning of the buffer space. */
2621 p = tmp_space;
2622 }
2623
2624 /* First element in a string table entry is the length of the
2625 string. Alignment issues are already handled. */
2626 bfd_put_32 (abfd, length, p);
2627 p += 4;
2628 strings_size += 4;
2629
2630 /* Record the index in the space/subspace records. */
2631 if (som_is_space (section))
2632 som_section_data (section)->space_dict->name.n_strx = strings_size;
2633 else
2634 som_section_data (section)->subspace_dict->name.n_strx = strings_size;
2635
2636 /* Next comes the string itself + a null terminator. */
2637 strcpy (p, section->name);
2638 p += length + 1;
2639 strings_size += length + 1;
2640
2641 /* Always align up to the next word boundary. */
2642 while (strings_size % 4)
2643 {
2644 bfd_put_8 (abfd, 0, p);
2645 p++;
2646 strings_size++;
2647 }
2648 }
2649
2650 /* Done with the space/subspace strings. Write out any information
2651 contained in a partial block. */
2652 if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd) != p - tmp_space)
2653 return false;
2654 *string_sizep = strings_size;
2655 return true;
2656 }
2657
2658 /* Write out the symbol string table. */
2659
2660 static boolean
2661 som_write_symbol_strings (abfd, current_offset, syms, num_syms, string_sizep)
2662 bfd *abfd;
2663 unsigned long current_offset;
2664 asymbol **syms;
2665 unsigned int num_syms;
2666 unsigned int *string_sizep;
2667 {
2668 unsigned int i;
2669
2670 /* Chunk of memory that we can use as buffer space, then throw
2671 away. */
2672 unsigned char tmp_space[SOM_TMP_BUFSIZE];
2673 unsigned char *p;
2674 unsigned int strings_size = 0;
2675
2676 memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2677 p = tmp_space;
2678
2679 /* Seek to the start of the space strings in preparation for writing
2680 them out. */
2681 if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
2682 return false;
2683
2684 for (i = 0; i < num_syms; i++)
2685 {
2686 int length = strlen (syms[i]->name);
2687
2688 /* If there is not enough room for the next entry, then dump the
2689 current buffer contents now. */
2690 if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
2691 {
2692 if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd)
2693 != p - tmp_space)
2694 return false;
2695 /* Reset to beginning of the buffer space. */
2696 p = tmp_space;
2697 }
2698
2699 /* First element in a string table entry is the length of the
2700 string. This must always be 4 byte aligned. This is also
2701 an appropriate time to fill in the string index field in the
2702 symbol table entry. */
2703 bfd_put_32 (abfd, length, p);
2704 strings_size += 4;
2705 p += 4;
2706
2707 /* Next comes the string itself + a null terminator. */
2708 strcpy (p, syms[i]->name);
2709
2710 /* ACK. FIXME. */
2711 syms[i]->name = (char *)strings_size;
2712 p += length + 1;
2713 strings_size += length + 1;
2714
2715 /* Always align up to the next word boundary. */
2716 while (strings_size % 4)
2717 {
2718 bfd_put_8 (abfd, 0, p);
2719 strings_size++;
2720 p++;
2721 }
2722 }
2723
2724 /* Scribble out any partial block. */
2725 if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd) != p - tmp_space)
2726 return false;
2727
2728 *string_sizep = strings_size;
2729 return true;
2730 }
2731
2732 /* Compute variable information to be placed in the SOM headers,
2733 space/subspace dictionaries, relocation streams, etc. Begin
2734 writing parts of the object file. */
2735
2736 static boolean
2737 som_begin_writing (abfd)
2738 bfd *abfd;
2739 {
2740 unsigned long current_offset = 0;
2741 int strings_size = 0;
2742 unsigned int total_reloc_size = 0;
2743 unsigned long num_spaces, num_subspaces, num_syms, i;
2744 asection *section;
2745 asymbol **syms = bfd_get_outsymbols (abfd);
2746 unsigned int total_subspaces = 0;
2747 struct som_exec_auxhdr exec_header;
2748
2749 /* The file header will always be first in an object file,
2750 everything else can be in random locations. To keep things
2751 "simple" BFD will lay out the object file in the manner suggested
2752 by the PRO ABI for PA-RISC Systems. */
2753
2754 /* Before any output can really begin offsets for all the major
2755 portions of the object file must be computed. So, starting
2756 with the initial file header compute (and sometimes write)
2757 each portion of the object file. */
2758
2759 /* Make room for the file header, it's contents are not complete
2760 yet, so it can not be written at this time. */
2761 current_offset += sizeof (struct header);
2762
2763 /* Any auxiliary headers will follow the file header. Right now
2764 we support only the copyright and version headers. */
2765 obj_som_file_hdr (abfd)->aux_header_location = current_offset;
2766 obj_som_file_hdr (abfd)->aux_header_size = 0;
2767 if (abfd->flags & (EXEC_P | DYNAMIC))
2768 {
2769 /* Parts of the exec header will be filled in later, so
2770 delay writing the header itself. Fill in the defaults,
2771 and write it later. */
2772 current_offset += sizeof (exec_header);
2773 obj_som_file_hdr (abfd)->aux_header_size += sizeof (exec_header);
2774 memset (&exec_header, 0, sizeof (exec_header));
2775 exec_header.som_auxhdr.type = HPUX_AUX_ID;
2776 exec_header.som_auxhdr.length = 40;
2777 }
2778 if (obj_som_version_hdr (abfd) != NULL)
2779 {
2780 unsigned int len;
2781
2782 if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
2783 return false;
2784
2785 /* Write the aux_id structure and the string length. */
2786 len = sizeof (struct aux_id) + sizeof (unsigned int);
2787 obj_som_file_hdr (abfd)->aux_header_size += len;
2788 current_offset += len;
2789 if (bfd_write ((PTR) obj_som_version_hdr (abfd), len, 1, abfd) != len)
2790 return false;
2791
2792 /* Write the version string. */
2793 len = obj_som_version_hdr (abfd)->header_id.length - sizeof (int);
2794 obj_som_file_hdr (abfd)->aux_header_size += len;
2795 current_offset += len;
2796 if (bfd_write ((PTR) obj_som_version_hdr (abfd)->user_string,
2797 len, 1, abfd) != len)
2798 return false;
2799 }
2800
2801 if (obj_som_copyright_hdr (abfd) != NULL)
2802 {
2803 unsigned int len;
2804
2805 if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
2806 return false;
2807
2808 /* Write the aux_id structure and the string length. */
2809 len = sizeof (struct aux_id) + sizeof (unsigned int);
2810 obj_som_file_hdr (abfd)->aux_header_size += len;
2811 current_offset += len;
2812 if (bfd_write ((PTR) obj_som_copyright_hdr (abfd), len, 1, abfd) != len)
2813 return false;
2814
2815 /* Write the copyright string. */
2816 len = obj_som_copyright_hdr (abfd)->header_id.length - sizeof (int);
2817 obj_som_file_hdr (abfd)->aux_header_size += len;
2818 current_offset += len;
2819 if (bfd_write ((PTR) obj_som_copyright_hdr (abfd)->copyright,
2820 len, 1, abfd) != len)
2821 return false;
2822 }
2823
2824 /* Next comes the initialization pointers; we have no initialization
2825 pointers, so current offset does not change. */
2826 obj_som_file_hdr (abfd)->init_array_location = current_offset;
2827 obj_som_file_hdr (abfd)->init_array_total = 0;
2828
2829 /* Next are the space records. These are fixed length records.
2830
2831 Count the number of spaces to determine how much room is needed
2832 in the object file for the space records.
2833
2834 The names of the spaces are stored in a separate string table,
2835 and the index for each space into the string table is computed
2836 below. Therefore, it is not possible to write the space headers
2837 at this time. */
2838 num_spaces = som_count_spaces (abfd);
2839 obj_som_file_hdr (abfd)->space_location = current_offset;
2840 obj_som_file_hdr (abfd)->space_total = num_spaces;
2841 current_offset += num_spaces * sizeof (struct space_dictionary_record);
2842
2843 /* Next are the subspace records. These are fixed length records.
2844
2845 Count the number of subspaes to determine how much room is needed
2846 in the object file for the subspace records.
2847
2848 A variety if fields in the subspace record are still unknown at
2849 this time (index into string table, fixup stream location/size, etc). */
2850 num_subspaces = som_count_subspaces (abfd);
2851 obj_som_file_hdr (abfd)->subspace_location = current_offset;
2852 obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
2853 current_offset += num_subspaces * sizeof (struct subspace_dictionary_record);
2854
2855 /* Next is the string table for the space/subspace names. We will
2856 build and write the string table on the fly. At the same time
2857 we will fill in the space/subspace name index fields. */
2858
2859 /* The string table needs to be aligned on a word boundary. */
2860 if (current_offset % 4)
2861 current_offset += (4 - (current_offset % 4));
2862
2863 /* Mark the offset of the space/subspace string table in the
2864 file header. */
2865 obj_som_file_hdr (abfd)->space_strings_location = current_offset;
2866
2867 /* Scribble out the space strings. */
2868 if (som_write_space_strings (abfd, current_offset, &strings_size) == false)
2869 return false;
2870
2871 /* Record total string table size in the header and update the
2872 current offset. */
2873 obj_som_file_hdr (abfd)->space_strings_size = strings_size;
2874 current_offset += strings_size;
2875
2876 /* Next is the symbol table. These are fixed length records.
2877
2878 Count the number of symbols to determine how much room is needed
2879 in the object file for the symbol table.
2880
2881 The names of the symbols are stored in a separate string table,
2882 and the index for each symbol name into the string table is computed
2883 below. Therefore, it is not possible to write the symobl table
2884 at this time. */
2885 num_syms = bfd_get_symcount (abfd);
2886 obj_som_file_hdr (abfd)->symbol_location = current_offset;
2887 obj_som_file_hdr (abfd)->symbol_total = num_syms;
2888 current_offset += num_syms * sizeof (struct symbol_dictionary_record);
2889
2890 /* Do prep work before handling fixups. */
2891 som_prep_for_fixups (abfd, syms, num_syms);
2892
2893 /* Next comes the fixup stream which starts on a word boundary. */
2894 if (current_offset % 4)
2895 current_offset += (4 - (current_offset % 4));
2896 obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
2897
2898 /* Write the fixups and update fields in subspace headers which
2899 relate to the fixup stream. */
2900 if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
2901 return false;
2902
2903 /* Record the total size of the fixup stream in the file header. */
2904 obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
2905 current_offset += total_reloc_size;
2906
2907 /* Next are the symbol strings.
2908 Align them to a word boundary. */
2909 if (current_offset % 4)
2910 current_offset += (4 - (current_offset % 4));
2911 obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
2912
2913 /* Scribble out the symbol strings. */
2914 if (som_write_symbol_strings (abfd, current_offset, syms,
2915 num_syms, &strings_size)
2916 == false)
2917 return false;
2918
2919 /* Record total string table size in header and update the
2920 current offset. */
2921 obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
2922 current_offset += strings_size;
2923
2924 /* Next is the compiler records. We do not use these. */
2925 obj_som_file_hdr (abfd)->compiler_location = current_offset;
2926 obj_som_file_hdr (abfd)->compiler_total = 0;
2927
2928 /* Now compute the file positions for the loadable subspaces, taking
2929 care to make sure everything stays properly aligned. */
2930
2931 section = abfd->sections;
2932 for (i = 0; i < num_spaces; i++)
2933 {
2934 asection *subsection;
2935 int first_subspace;
2936 unsigned int subspace_offset = 0;
2937
2938 /* Find a space. */
2939 while (!som_is_space (section))
2940 section = section->next;
2941
2942 first_subspace = 1;
2943 /* Now look for all its subspaces. */
2944 for (subsection = abfd->sections;
2945 subsection != NULL;
2946 subsection = subsection->next)
2947 {
2948
2949 if (!som_is_subspace (subsection)
2950 || !som_is_container (section, subsection)
2951 || (subsection->flags & SEC_ALLOC) == 0)
2952 continue;
2953
2954 /* If this is the first subspace in the space, and we are
2955 building an executable, then take care to make sure all
2956 the alignments are correct and update the exec header. */
2957 if (first_subspace
2958 && (abfd->flags & (EXEC_P | DYNAMIC)))
2959 {
2960 /* Demand paged executables have each space aligned to a
2961 page boundary. Sharable executables (write-protected
2962 text) have just the private (aka data & bss) space aligned
2963 to a page boundary. Ugh. Not true for HPUX.
2964
2965 The HPUX kernel requires the text to always be page aligned
2966 within the file regardless of the executable's type. */
2967 if (abfd->flags & (D_PAGED | DYNAMIC)
2968 || (subsection->flags & SEC_CODE)
2969 || ((abfd->flags & WP_TEXT)
2970 && (subsection->flags & SEC_DATA)))
2971 current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
2972
2973 /* Update the exec header. */
2974 if (subsection->flags & SEC_CODE && exec_header.exec_tfile == 0)
2975 {
2976 exec_header.exec_tmem = section->vma;
2977 exec_header.exec_tfile = current_offset;
2978 }
2979 if (subsection->flags & SEC_DATA && exec_header.exec_dfile == 0)
2980 {
2981 exec_header.exec_dmem = section->vma;
2982 exec_header.exec_dfile = current_offset;
2983 }
2984
2985 /* Keep track of exactly where we are within a particular
2986 space. This is necessary as the braindamaged HPUX
2987 loader will create holes between subspaces *and*
2988 subspace alignments are *NOT* preserved. What a crock. */
2989 subspace_offset = subsection->vma;
2990
2991 /* Only do this for the first subspace within each space. */
2992 first_subspace = 0;
2993 }
2994 else if (abfd->flags & (EXEC_P | DYNAMIC))
2995 {
2996 /* The braindamaged HPUX loader may have created a hole
2997 between two subspaces. It is *not* sufficient to use
2998 the alignment specifications within the subspaces to
2999 account for these holes -- I've run into at least one
3000 case where the loader left one code subspace unaligned
3001 in a final executable.
3002
3003 To combat this we keep a current offset within each space,
3004 and use the subspace vma fields to detect and preserve
3005 holes. What a crock!
3006
3007 ps. This is not necessary for unloadable space/subspaces. */
3008 current_offset += subsection->vma - subspace_offset;
3009 if (subsection->flags & SEC_CODE)
3010 exec_header.exec_tsize += subsection->vma - subspace_offset;
3011 else
3012 exec_header.exec_dsize += subsection->vma - subspace_offset;
3013 subspace_offset += subsection->vma - subspace_offset;
3014 }
3015
3016
3017 subsection->target_index = total_subspaces++;
3018 /* This is real data to be loaded from the file. */
3019 if (subsection->flags & SEC_LOAD)
3020 {
3021 /* Update the size of the code & data. */
3022 if (abfd->flags & (EXEC_P | DYNAMIC)
3023 && subsection->flags & SEC_CODE)
3024 exec_header.exec_tsize += subsection->_cooked_size;
3025 else if (abfd->flags & (EXEC_P | DYNAMIC)
3026 && subsection->flags & SEC_DATA)
3027 exec_header.exec_dsize += subsection->_cooked_size;
3028 som_section_data (subsection)->subspace_dict->file_loc_init_value
3029 = current_offset;
3030 subsection->filepos = current_offset;
3031 current_offset += bfd_section_size (abfd, subsection);
3032 subspace_offset += bfd_section_size (abfd, subsection);
3033 }
3034 /* Looks like uninitialized data. */
3035 else
3036 {
3037 /* Update the size of the bss section. */
3038 if (abfd->flags & (EXEC_P | DYNAMIC))
3039 exec_header.exec_bsize += subsection->_cooked_size;
3040
3041 som_section_data (subsection)->subspace_dict->file_loc_init_value
3042 = 0;
3043 som_section_data (subsection)->subspace_dict->
3044 initialization_length = 0;
3045 }
3046 }
3047 /* Goto the next section. */
3048 section = section->next;
3049 }
3050
3051 /* Finally compute the file positions for unloadable subspaces.
3052 If building an executable, start the unloadable stuff on its
3053 own page. */
3054
3055 if (abfd->flags & (EXEC_P | DYNAMIC))
3056 current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3057
3058 obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
3059 section = abfd->sections;
3060 for (i = 0; i < num_spaces; i++)
3061 {
3062 asection *subsection;
3063
3064 /* Find a space. */
3065 while (!som_is_space (section))
3066 section = section->next;
3067
3068 if (abfd->flags & (EXEC_P | DYNAMIC))
3069 current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3070
3071 /* Now look for all its subspaces. */
3072 for (subsection = abfd->sections;
3073 subsection != NULL;
3074 subsection = subsection->next)
3075 {
3076
3077 if (!som_is_subspace (subsection)
3078 || !som_is_container (section, subsection)
3079 || (subsection->flags & SEC_ALLOC) != 0)
3080 continue;
3081
3082 subsection->target_index = total_subspaces;
3083 /* This is real data to be loaded from the file. */
3084 if ((subsection->flags & SEC_LOAD) == 0)
3085 {
3086 som_section_data (subsection)->subspace_dict->file_loc_init_value
3087 = current_offset;
3088 subsection->filepos = current_offset;
3089 current_offset += bfd_section_size (abfd, subsection);
3090 }
3091 /* Looks like uninitialized data. */
3092 else
3093 {
3094 som_section_data (subsection)->subspace_dict->file_loc_init_value
3095 = 0;
3096 som_section_data (subsection)->subspace_dict->
3097 initialization_length = bfd_section_size (abfd, subsection);
3098 }
3099 }
3100 /* Goto the next section. */
3101 section = section->next;
3102 }
3103
3104 /* If building an executable, then make sure to seek to and write
3105 one byte at the end of the file to make sure any necessary
3106 zeros are filled in. Ugh. */
3107 if (abfd->flags & (EXEC_P | DYNAMIC))
3108 current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3109 if (bfd_seek (abfd, current_offset - 1, SEEK_SET) < 0)
3110 return false;
3111 if (bfd_write ((PTR) "", 1, 1, abfd) != 1)
3112 return false;
3113
3114 obj_som_file_hdr (abfd)->unloadable_sp_size
3115 = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
3116
3117 /* Loader fixups are not supported in any way shape or form. */
3118 obj_som_file_hdr (abfd)->loader_fixup_location = 0;
3119 obj_som_file_hdr (abfd)->loader_fixup_total = 0;
3120
3121 /* Done. Store the total size of the SOM. */
3122 obj_som_file_hdr (abfd)->som_length = current_offset;
3123
3124 /* Now write the exec header. */
3125 if (abfd->flags & (EXEC_P | DYNAMIC))
3126 {
3127 long tmp;
3128
3129 exec_header.exec_entry = bfd_get_start_address (abfd);
3130 exec_header.exec_flags = obj_som_exec_data (abfd)->exec_flags;
3131
3132 /* Oh joys. Ram some of the BSS data into the DATA section
3133 to be compatable with how the hp linker makes objects
3134 (saves memory space). */
3135 tmp = exec_header.exec_dsize;
3136 tmp = SOM_ALIGN (tmp, PA_PAGESIZE);
3137 exec_header.exec_bsize -= (tmp - exec_header.exec_dsize);
3138 if (exec_header.exec_bsize < 0)
3139 exec_header.exec_bsize = 0;
3140 exec_header.exec_dsize = tmp;
3141
3142 if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location,
3143 SEEK_SET) < 0)
3144 return false;
3145
3146 if (bfd_write ((PTR) &exec_header, AUX_HDR_SIZE, 1, abfd)
3147 != AUX_HDR_SIZE)
3148 return false;
3149 }
3150 return true;
3151 }
3152
3153 /* Finally, scribble out the various headers to the disk. */
3154
3155 static boolean
3156 som_write_headers (abfd)
3157 bfd *abfd;
3158 {
3159 int num_spaces = som_count_spaces (abfd);
3160 int i;
3161 int subspace_index = 0;
3162 file_ptr location;
3163 asection *section;
3164
3165 /* Subspaces are written first so that we can set up information
3166 about them in their containing spaces as the subspace is written. */
3167
3168 /* Seek to the start of the subspace dictionary records. */
3169 location = obj_som_file_hdr (abfd)->subspace_location;
3170 if (bfd_seek (abfd, location, SEEK_SET) < 0)
3171 return false;
3172
3173 section = abfd->sections;
3174 /* Now for each loadable space write out records for its subspaces. */
3175 for (i = 0; i < num_spaces; i++)
3176 {
3177 asection *subsection;
3178
3179 /* Find a space. */
3180 while (!som_is_space (section))
3181 section = section->next;
3182
3183 /* Now look for all its subspaces. */
3184 for (subsection = abfd->sections;
3185 subsection != NULL;
3186 subsection = subsection->next)
3187 {
3188
3189 /* Skip any section which does not correspond to a space
3190 or subspace. Or does not have SEC_ALLOC set (and therefore
3191 has no real bits on the disk). */
3192 if (!som_is_subspace (subsection)
3193 || !som_is_container (section, subsection)
3194 || (subsection->flags & SEC_ALLOC) == 0)
3195 continue;
3196
3197 /* If this is the first subspace for this space, then save
3198 the index of the subspace in its containing space. Also
3199 set "is_loadable" in the containing space. */
3200
3201 if (som_section_data (section)->space_dict->subspace_quantity == 0)
3202 {
3203 som_section_data (section)->space_dict->is_loadable = 1;
3204 som_section_data (section)->space_dict->subspace_index
3205 = subspace_index;
3206 }
3207
3208 /* Increment the number of subspaces seen and the number of
3209 subspaces contained within the current space. */
3210 subspace_index++;
3211 som_section_data (section)->space_dict->subspace_quantity++;
3212
3213 /* Mark the index of the current space within the subspace's
3214 dictionary record. */
3215 som_section_data (subsection)->subspace_dict->space_index = i;
3216
3217 /* Dump the current subspace header. */
3218 if (bfd_write ((PTR) som_section_data (subsection)->subspace_dict,
3219 sizeof (struct subspace_dictionary_record), 1, abfd)
3220 != sizeof (struct subspace_dictionary_record))
3221 return false;
3222 }
3223 /* Goto the next section. */
3224 section = section->next;
3225 }
3226
3227 /* Now repeat the process for unloadable subspaces. */
3228 section = abfd->sections;
3229 /* Now for each space write out records for its subspaces. */
3230 for (i = 0; i < num_spaces; i++)
3231 {
3232 asection *subsection;
3233
3234 /* Find a space. */
3235 while (!som_is_space (section))
3236 section = section->next;
3237
3238 /* Now look for all its subspaces. */
3239 for (subsection = abfd->sections;
3240 subsection != NULL;
3241 subsection = subsection->next)
3242 {
3243
3244 /* Skip any section which does not correspond to a space or
3245 subspace, or which SEC_ALLOC set (and therefore handled
3246 in the loadable spaces/subspaces code above). */
3247
3248 if (!som_is_subspace (subsection)
3249 || !som_is_container (section, subsection)
3250 || (subsection->flags & SEC_ALLOC) != 0)
3251 continue;
3252
3253 /* If this is the first subspace for this space, then save
3254 the index of the subspace in its containing space. Clear
3255 "is_loadable". */
3256
3257 if (som_section_data (section)->space_dict->subspace_quantity == 0)
3258 {
3259 som_section_data (section)->space_dict->is_loadable = 0;
3260 som_section_data (section)->space_dict->subspace_index
3261 = subspace_index;
3262 }
3263
3264 /* Increment the number of subspaces seen and the number of
3265 subspaces contained within the current space. */
3266 som_section_data (section)->space_dict->subspace_quantity++;
3267 subspace_index++;
3268
3269 /* Mark the index of the current space within the subspace's
3270 dictionary record. */
3271 som_section_data (subsection)->subspace_dict->space_index = i;
3272
3273 /* Dump this subspace header. */
3274 if (bfd_write ((PTR) som_section_data (subsection)->subspace_dict,
3275 sizeof (struct subspace_dictionary_record), 1, abfd)
3276 != sizeof (struct subspace_dictionary_record))
3277 return false;
3278 }
3279 /* Goto the next section. */
3280 section = section->next;
3281 }
3282
3283 /* All the subspace dictiondary records are written, and all the
3284 fields are set up in the space dictionary records.
3285
3286 Seek to the right location and start writing the space
3287 dictionary records. */
3288 location = obj_som_file_hdr (abfd)->space_location;
3289 if (bfd_seek (abfd, location, SEEK_SET) < 0)
3290 return false;
3291
3292 section = abfd->sections;
3293 for (i = 0; i < num_spaces; i++)
3294 {
3295
3296 /* Find a space. */
3297 while (!som_is_space (section))
3298 section = section->next;
3299
3300 /* Dump its header */
3301 if (bfd_write ((PTR) som_section_data (section)->space_dict,
3302 sizeof (struct space_dictionary_record), 1, abfd)
3303 != sizeof (struct space_dictionary_record))
3304 return false;
3305
3306 /* Goto the next section. */
3307 section = section->next;
3308 }
3309
3310 /* Only thing left to do is write out the file header. It is always
3311 at location zero. Seek there and write it. */
3312 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) < 0)
3313 return false;
3314 if (bfd_write ((PTR) obj_som_file_hdr (abfd),
3315 sizeof (struct header), 1, abfd)
3316 != sizeof (struct header))
3317 return false;
3318 return true;
3319 }
3320
3321 /* Compute and return the checksum for a SOM file header. */
3322
3323 static unsigned long
3324 som_compute_checksum (abfd)
3325 bfd *abfd;
3326 {
3327 unsigned long checksum, count, i;
3328 unsigned long *buffer = (unsigned long *) obj_som_file_hdr (abfd);
3329
3330 checksum = 0;
3331 count = sizeof (struct header) / sizeof (unsigned long);
3332 for (i = 0; i < count; i++)
3333 checksum ^= *(buffer + i);
3334
3335 return checksum;
3336 }
3337
3338 static void
3339 som_bfd_derive_misc_symbol_info (abfd, sym, info)
3340 bfd *abfd;
3341 asymbol *sym;
3342 struct som_misc_symbol_info *info;
3343 {
3344 /* Initialize. */
3345 memset (info, 0, sizeof (struct som_misc_symbol_info));
3346
3347 /* The HP SOM linker requires detailed type information about
3348 all symbols (including undefined symbols!). Unfortunately,
3349 the type specified in an import/export statement does not
3350 always match what the linker wants. Severe braindamage. */
3351
3352 /* Section symbols will not have a SOM symbol type assigned to
3353 them yet. Assign all section symbols type ST_DATA. */
3354 if (sym->flags & BSF_SECTION_SYM)
3355 info->symbol_type = ST_DATA;
3356 else
3357 {
3358 /* Common symbols must have scope SS_UNSAT and type
3359 ST_STORAGE or the linker will choke. */
3360 if (sym->section == &bfd_com_section)
3361 {
3362 info->symbol_scope = SS_UNSAT;
3363 info->symbol_type = ST_STORAGE;
3364 }
3365
3366 /* It is possible to have a symbol without an associated
3367 type. This happens if the user imported the symbol
3368 without a type and the symbol was never defined
3369 locally. If BSF_FUNCTION is set for this symbol, then
3370 assign it type ST_CODE (the HP linker requires undefined
3371 external functions to have type ST_CODE rather than ST_ENTRY). */
3372 else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
3373 && sym->section == &bfd_und_section
3374 && sym->flags & BSF_FUNCTION)
3375 info->symbol_type = ST_CODE;
3376
3377 /* Handle function symbols which were defined in this file.
3378 They should have type ST_ENTRY. Also retrieve the argument
3379 relocation bits from the SOM backend information. */
3380 else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY
3381 || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
3382 && (sym->flags & BSF_FUNCTION))
3383 || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
3384 && (sym->flags & BSF_FUNCTION)))
3385 {
3386 info->symbol_type = ST_ENTRY;
3387 info->arg_reloc = som_symbol_data (sym)->tc_data.hppa_arg_reloc;
3388 }
3389
3390 /* If the type is unknown at this point, it should be
3391 ST_DATA (functions were handled as special cases above). */
3392 else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
3393 info->symbol_type = ST_DATA;
3394
3395 /* From now on it's a very simple mapping. */
3396 else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
3397 info->symbol_type = ST_ABSOLUTE;
3398 else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
3399 info->symbol_type = ST_CODE;
3400 else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
3401 info->symbol_type = ST_DATA;
3402 else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
3403 info->symbol_type = ST_MILLICODE;
3404 else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
3405 info->symbol_type = ST_PLABEL;
3406 else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
3407 info->symbol_type = ST_PRI_PROG;
3408 else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
3409 info->symbol_type = ST_SEC_PROG;
3410 }
3411
3412 /* Now handle the symbol's scope. Exported data which is not
3413 in the common section has scope SS_UNIVERSAL. Note scope
3414 of common symbols was handled earlier! */
3415 if (sym->flags & BSF_EXPORT && sym->section != &bfd_com_section)
3416 info->symbol_scope = SS_UNIVERSAL;
3417 /* Any undefined symbol at this point has a scope SS_UNSAT. */
3418 else if (sym->section == &bfd_und_section)
3419 info->symbol_scope = SS_UNSAT;
3420 /* Anything else which is not in the common section has scope
3421 SS_LOCAL. */
3422 else if (sym->section != &bfd_com_section)
3423 info->symbol_scope = SS_LOCAL;
3424
3425 /* Now set the symbol_info field. It has no real meaning
3426 for undefined or common symbols, but the HP linker will
3427 choke if it's not set to some "reasonable" value. We
3428 use zero as a reasonable value. */
3429 if (sym->section == &bfd_com_section || sym->section == &bfd_und_section
3430 || sym->section == &bfd_abs_section)
3431 info->symbol_info = 0;
3432 /* For all other symbols, the symbol_info field contains the
3433 subspace index of the space this symbol is contained in. */
3434 else
3435 info->symbol_info = sym->section->target_index;
3436
3437 /* Set the symbol's value. */
3438 info->symbol_value = sym->value + sym->section->vma;
3439 }
3440
3441 /* Build and write, in one big chunk, the entire symbol table for
3442 this BFD. */
3443
3444 static boolean
3445 som_build_and_write_symbol_table (abfd)
3446 bfd *abfd;
3447 {
3448 unsigned int num_syms = bfd_get_symcount (abfd);
3449 file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
3450 asymbol **bfd_syms = bfd_get_outsymbols (abfd);
3451 struct symbol_dictionary_record *som_symtab = NULL;
3452 int i, symtab_size;
3453
3454 /* Compute total symbol table size and allocate a chunk of memory
3455 to hold the symbol table as we build it. */
3456 symtab_size = num_syms * sizeof (struct symbol_dictionary_record);
3457 som_symtab = (struct symbol_dictionary_record *) malloc (symtab_size);
3458 if (som_symtab == NULL && symtab_size != 0)
3459 {
3460 bfd_set_error (bfd_error_no_memory);
3461 goto error_return;
3462 }
3463 memset (som_symtab, 0, symtab_size);
3464
3465 /* Walk over each symbol. */
3466 for (i = 0; i < num_syms; i++)
3467 {
3468 struct som_misc_symbol_info info;
3469
3470 /* This is really an index into the symbol strings table.
3471 By the time we get here, the index has already been
3472 computed and stored into the name field in the BFD symbol. */
3473 som_symtab[i].name.n_strx = (int) bfd_syms[i]->name;
3474
3475 /* Derive SOM information from the BFD symbol. */
3476 som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
3477
3478 /* Now use it. */
3479 som_symtab[i].symbol_type = info.symbol_type;
3480 som_symtab[i].symbol_scope = info.symbol_scope;
3481 som_symtab[i].arg_reloc = info.arg_reloc;
3482 som_symtab[i].symbol_info = info.symbol_info;
3483 som_symtab[i].symbol_value = info.symbol_value;
3484 }
3485
3486 /* Everything is ready, seek to the right location and
3487 scribble out the symbol table. */
3488 if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
3489 return false;
3490
3491 if (bfd_write ((PTR) som_symtab, symtab_size, 1, abfd) != symtab_size)
3492 goto error_return;
3493
3494 if (som_symtab != NULL)
3495 free (som_symtab);
3496 return true;
3497 error_return:
3498 if (som_symtab != NULL)
3499 free (som_symtab);
3500 return false;
3501 }
3502
3503 /* Write an object in SOM format. */
3504
3505 static boolean
3506 som_write_object_contents (abfd)
3507 bfd *abfd;
3508 {
3509 if (abfd->output_has_begun == false)
3510 {
3511 /* Set up fixed parts of the file, space, and subspace headers.
3512 Notify the world that output has begun. */
3513 som_prep_headers (abfd);
3514 abfd->output_has_begun = true;
3515 /* Start writing the object file. This include all the string
3516 tables, fixup streams, and other portions of the object file. */
3517 som_begin_writing (abfd);
3518 }
3519
3520 /* Now that the symbol table information is complete, build and
3521 write the symbol table. */
3522 if (som_build_and_write_symbol_table (abfd) == false)
3523 return false;
3524
3525 /* Compute the checksum for the file header just before writing
3526 the header to disk. */
3527 obj_som_file_hdr (abfd)->checksum = som_compute_checksum (abfd);
3528 return (som_write_headers (abfd));
3529 }
3530
3531 \f
3532 /* Read and save the string table associated with the given BFD. */
3533
3534 static boolean
3535 som_slurp_string_table (abfd)
3536 bfd *abfd;
3537 {
3538 char *stringtab;
3539
3540 /* Use the saved version if its available. */
3541 if (obj_som_stringtab (abfd) != NULL)
3542 return true;
3543
3544 /* I don't think this can currently happen, and I'm not sure it should
3545 really be an error, but it's better than getting unpredictable results
3546 from the host's malloc when passed a size of zero. */
3547 if (obj_som_stringtab_size (abfd) == 0)
3548 {
3549 bfd_set_error (bfd_error_no_symbols);
3550 return false;
3551 }
3552
3553 /* Allocate and read in the string table. */
3554 stringtab = malloc (obj_som_stringtab_size (abfd));
3555 if (stringtab == NULL)
3556 {
3557 bfd_set_error (bfd_error_no_memory);
3558 return false;
3559 }
3560
3561 if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
3562 return false;
3563
3564 if (bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd)
3565 != obj_som_stringtab_size (abfd))
3566 return false;
3567
3568 /* Save our results and return success. */
3569 obj_som_stringtab (abfd) = stringtab;
3570 return true;
3571 }
3572
3573 /* Return the amount of data (in bytes) required to hold the symbol
3574 table for this object. */
3575
3576 static long
3577 som_get_symtab_upper_bound (abfd)
3578 bfd *abfd;
3579 {
3580 if (!som_slurp_symbol_table (abfd))
3581 return -1;
3582
3583 return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *));
3584 }
3585
3586 /* Convert from a SOM subspace index to a BFD section. */
3587
3588 static asection *
3589 bfd_section_from_som_symbol (abfd, symbol)
3590 bfd *abfd;
3591 struct symbol_dictionary_record *symbol;
3592 {
3593 asection *section;
3594
3595 /* The meaning of the symbol_info field changes for functions
3596 within executables. So only use the quick symbol_info mapping for
3597 incomplete objects and non-function symbols in executables. */
3598 if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
3599 || (symbol->symbol_type != ST_ENTRY
3600 && symbol->symbol_type != ST_PRI_PROG
3601 && symbol->symbol_type != ST_SEC_PROG
3602 && symbol->symbol_type != ST_MILLICODE))
3603 {
3604 unsigned int index = symbol->symbol_info;
3605 for (section = abfd->sections; section != NULL; section = section->next)
3606 if (section->target_index == index)
3607 return section;
3608
3609 /* Should never happen. */
3610 abort();
3611 }
3612 else
3613 {
3614 unsigned int value = symbol->symbol_value;
3615 unsigned int found = 0;
3616
3617 /* For executables we will have to use the symbol's address and
3618 find out what section would contain that address. Yuk. */
3619 for (section = abfd->sections; section; section = section->next)
3620 {
3621 if (value >= section->vma
3622 && value <= section->vma + section->_cooked_size)
3623 return section;
3624 }
3625
3626 /* Should never happen. */
3627 abort ();
3628 }
3629 }
3630
3631 /* Read and save the symbol table associated with the given BFD. */
3632
3633 static unsigned int
3634 som_slurp_symbol_table (abfd)
3635 bfd *abfd;
3636 {
3637 int symbol_count = bfd_get_symcount (abfd);
3638 int symsize = sizeof (struct symbol_dictionary_record);
3639 char *stringtab;
3640 struct symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
3641 som_symbol_type *sym, *symbase;
3642
3643 /* Return saved value if it exists. */
3644 if (obj_som_symtab (abfd) != NULL)
3645 goto successful_return;
3646
3647 /* Special case. This is *not* an error. */
3648 if (symbol_count == 0)
3649 goto successful_return;
3650
3651 if (!som_slurp_string_table (abfd))
3652 goto error_return;
3653
3654 stringtab = obj_som_stringtab (abfd);
3655
3656 symbase = (som_symbol_type *)
3657 malloc (symbol_count * sizeof (som_symbol_type));
3658 if (symbase == NULL)
3659 {
3660 bfd_set_error (bfd_error_no_memory);
3661 goto error_return;
3662 }
3663
3664 /* Read in the external SOM representation. */
3665 buf = malloc (symbol_count * symsize);
3666 if (buf == NULL && symbol_count * symsize != 0)
3667 {
3668 bfd_set_error (bfd_error_no_memory);
3669 goto error_return;
3670 }
3671 if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
3672 goto error_return;
3673 if (bfd_read (buf, symbol_count * symsize, 1, abfd)
3674 != symbol_count * symsize)
3675 goto error_return;
3676
3677 /* Iterate over all the symbols and internalize them. */
3678 endbufp = buf + symbol_count;
3679 for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
3680 {
3681
3682 /* I don't think we care about these. */
3683 if (bufp->symbol_type == ST_SYM_EXT
3684 || bufp->symbol_type == ST_ARG_EXT)
3685 continue;
3686
3687 /* Set some private data we care about. */
3688 if (bufp->symbol_type == ST_NULL)
3689 som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
3690 else if (bufp->symbol_type == ST_ABSOLUTE)
3691 som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
3692 else if (bufp->symbol_type == ST_DATA)
3693 som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
3694 else if (bufp->symbol_type == ST_CODE)
3695 som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
3696 else if (bufp->symbol_type == ST_PRI_PROG)
3697 som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
3698 else if (bufp->symbol_type == ST_SEC_PROG)
3699 som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
3700 else if (bufp->symbol_type == ST_ENTRY)
3701 som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
3702 else if (bufp->symbol_type == ST_MILLICODE)
3703 som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
3704 else if (bufp->symbol_type == ST_PLABEL)
3705 som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
3706 else
3707 som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
3708 som_symbol_data (sym)->tc_data.hppa_arg_reloc = bufp->arg_reloc;
3709
3710 /* Some reasonable defaults. */
3711 sym->symbol.the_bfd = abfd;
3712 sym->symbol.name = bufp->name.n_strx + stringtab;
3713 sym->symbol.value = bufp->symbol_value;
3714 sym->symbol.section = 0;
3715 sym->symbol.flags = 0;
3716
3717 switch (bufp->symbol_type)
3718 {
3719 case ST_ENTRY:
3720 case ST_PRI_PROG:
3721 case ST_SEC_PROG:
3722 case ST_MILLICODE:
3723 sym->symbol.flags |= BSF_FUNCTION;
3724 sym->symbol.value &= ~0x3;
3725 break;
3726
3727 case ST_STUB:
3728 case ST_CODE:
3729 sym->symbol.value &= ~0x3;
3730
3731 default:
3732 break;
3733 }
3734
3735 /* Handle scoping and section information. */
3736 switch (bufp->symbol_scope)
3737 {
3738 /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
3739 so the section associated with this symbol can't be known. */
3740 case SS_EXTERNAL:
3741 if (bufp->symbol_type != ST_STORAGE)
3742 sym->symbol.section = &bfd_und_section;
3743 else
3744 sym->symbol.section = &bfd_com_section;
3745 sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3746 break;
3747
3748 case SS_UNSAT:
3749 if (bufp->symbol_type != ST_STORAGE)
3750 sym->symbol.section = &bfd_und_section;
3751 else
3752 sym->symbol.section = &bfd_com_section;
3753 break;
3754
3755 case SS_UNIVERSAL:
3756 sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3757 sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
3758 sym->symbol.value -= sym->symbol.section->vma;
3759 break;
3760
3761 #if 0
3762 /* SS_GLOBAL and SS_LOCAL are two names for the same thing.
3763 Sound dumb? It is. */
3764 case SS_GLOBAL:
3765 #endif
3766 case SS_LOCAL:
3767 sym->symbol.flags |= BSF_LOCAL;
3768 sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
3769 sym->symbol.value -= sym->symbol.section->vma;
3770 break;
3771 }
3772
3773 /* Mark section symbols and symbols used by the debugger. */
3774 if (sym->symbol.name[0] == '$'
3775 && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$')
3776 sym->symbol.flags |= BSF_SECTION_SYM;
3777 else if (!strncmp (sym->symbol.name, "L$0\002", 4))
3778 {
3779 sym->symbol.flags |= BSF_SECTION_SYM;
3780 sym->symbol.name = sym->symbol.section->name;
3781 }
3782 else if (!strncmp (sym->symbol.name, "L$0\001", 4))
3783 sym->symbol.flags |= BSF_DEBUGGING;
3784
3785 /* Note increment at bottom of loop, since we skip some symbols
3786 we can not include it as part of the for statement. */
3787 sym++;
3788 }
3789
3790 /* Save our results and return success. */
3791 obj_som_symtab (abfd) = symbase;
3792 successful_return:
3793 if (buf != NULL)
3794 free (buf);
3795 return (true);
3796
3797 error_return:
3798 if (buf != NULL)
3799 free (buf);
3800 return false;
3801 }
3802
3803 /* Canonicalize a SOM symbol table. Return the number of entries
3804 in the symbol table. */
3805
3806 static long
3807 som_get_symtab (abfd, location)
3808 bfd *abfd;
3809 asymbol **location;
3810 {
3811 int i;
3812 som_symbol_type *symbase;
3813
3814 if (!som_slurp_symbol_table (abfd))
3815 return -1;
3816
3817 i = bfd_get_symcount (abfd);
3818 symbase = obj_som_symtab (abfd);
3819
3820 for (; i > 0; i--, location++, symbase++)
3821 *location = &symbase->symbol;
3822
3823 /* Final null pointer. */
3824 *location = 0;
3825 return (bfd_get_symcount (abfd));
3826 }
3827
3828 /* Make a SOM symbol. There is nothing special to do here. */
3829
3830 static asymbol *
3831 som_make_empty_symbol (abfd)
3832 bfd *abfd;
3833 {
3834 som_symbol_type *new =
3835 (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
3836 if (new == NULL)
3837 {
3838 bfd_set_error (bfd_error_no_memory);
3839 return 0;
3840 }
3841 new->symbol.the_bfd = abfd;
3842
3843 return &new->symbol;
3844 }
3845
3846 /* Print symbol information. */
3847
3848 static void
3849 som_print_symbol (ignore_abfd, afile, symbol, how)
3850 bfd *ignore_abfd;
3851 PTR afile;
3852 asymbol *symbol;
3853 bfd_print_symbol_type how;
3854 {
3855 FILE *file = (FILE *) afile;
3856 switch (how)
3857 {
3858 case bfd_print_symbol_name:
3859 fprintf (file, "%s", symbol->name);
3860 break;
3861 case bfd_print_symbol_more:
3862 fprintf (file, "som ");
3863 fprintf_vma (file, symbol->value);
3864 fprintf (file, " %lx", (long) symbol->flags);
3865 break;
3866 case bfd_print_symbol_all:
3867 {
3868 CONST char *section_name;
3869 section_name = symbol->section ? symbol->section->name : "(*none*)";
3870 bfd_print_symbol_vandf ((PTR) file, symbol);
3871 fprintf (file, " %s\t%s", section_name, symbol->name);
3872 break;
3873 }
3874 }
3875 }
3876
3877 static boolean
3878 som_bfd_is_local_label (abfd, sym)
3879 bfd *abfd;
3880 asymbol *sym;
3881 {
3882 return (sym->name[0] == 'L' && sym->name[1] == '$');
3883 }
3884
3885 /* Count or process variable-length SOM fixup records.
3886
3887 To avoid code duplication we use this code both to compute the number
3888 of relocations requested by a stream, and to internalize the stream.
3889
3890 When computing the number of relocations requested by a stream the
3891 variables rptr, section, and symbols have no meaning.
3892
3893 Return the number of relocations requested by the fixup stream. When
3894 not just counting
3895
3896 This needs at least two or three more passes to get it cleaned up. */
3897
3898 static unsigned int
3899 som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
3900 unsigned char *fixup;
3901 unsigned int end;
3902 arelent *internal_relocs;
3903 asection *section;
3904 asymbol **symbols;
3905 boolean just_count;
3906 {
3907 unsigned int op, varname;
3908 unsigned char *end_fixups = &fixup[end];
3909 const struct fixup_format *fp;
3910 char *cp;
3911 unsigned char *save_fixup;
3912 int variables[26], stack[20], c, v, count, prev_fixup, *sp;
3913 const int *subop;
3914 arelent *rptr= internal_relocs;
3915 unsigned int offset = just_count ? 0 : section->vma;
3916
3917 #define var(c) variables[(c) - 'A']
3918 #define push(v) (*sp++ = (v))
3919 #define pop() (*--sp)
3920 #define emptystack() (sp == stack)
3921
3922 som_initialize_reloc_queue (reloc_queue);
3923 memset (variables, 0, sizeof (variables));
3924 memset (stack, 0, sizeof (stack));
3925 count = 0;
3926 prev_fixup = 0;
3927 sp = stack;
3928
3929 while (fixup < end_fixups)
3930 {
3931
3932 /* Save pointer to the start of this fixup. We'll use
3933 it later to determine if it is necessary to put this fixup
3934 on the queue. */
3935 save_fixup = fixup;
3936
3937 /* Get the fixup code and its associated format. */
3938 op = *fixup++;
3939 fp = &som_fixup_formats[op];
3940
3941 /* Handle a request for a previous fixup. */
3942 if (*fp->format == 'P')
3943 {
3944 /* Get pointer to the beginning of the prev fixup, move
3945 the repeated fixup to the head of the queue. */
3946 fixup = reloc_queue[fp->D].reloc;
3947 som_reloc_queue_fix (reloc_queue, fp->D);
3948 prev_fixup = 1;
3949
3950 /* Get the fixup code and its associated format. */
3951 op = *fixup++;
3952 fp = &som_fixup_formats[op];
3953 }
3954
3955 /* If we are not just counting, set some reasonable defaults. */
3956 if (! just_count)
3957 {
3958 rptr->address = offset;
3959 rptr->howto = &som_hppa_howto_table[op];
3960 rptr->addend = 0;
3961 rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
3962 }
3963
3964 /* Set default input length to 0. Get the opcode class index
3965 into D. */
3966 var ('L') = 0;
3967 var ('D') = fp->D;
3968
3969 /* Get the opcode format. */
3970 cp = fp->format;
3971
3972 /* Process the format string. Parsing happens in two phases,
3973 parse RHS, then assign to LHS. Repeat until no more
3974 characters in the format string. */
3975 while (*cp)
3976 {
3977 /* The variable this pass is going to compute a value for. */
3978 varname = *cp++;
3979
3980 /* Start processing RHS. Continue until a NULL or '=' is found. */
3981 do
3982 {
3983 c = *cp++;
3984
3985 /* If this is a variable, push it on the stack. */
3986 if (isupper (c))
3987 push (var (c));
3988
3989 /* If this is a lower case letter, then it represents
3990 additional data from the fixup stream to be pushed onto
3991 the stack. */
3992 else if (islower (c))
3993 {
3994 for (v = 0; c > 'a'; --c)
3995 v = (v << 8) | *fixup++;
3996 push (v);
3997 }
3998
3999 /* A decimal constant. Push it on the stack. */
4000 else if (isdigit (c))
4001 {
4002 v = c - '0';
4003 while (isdigit (*cp))
4004 v = (v * 10) + (*cp++ - '0');
4005 push (v);
4006 }
4007 else
4008
4009 /* An operator. Pop two two values from the stack and
4010 use them as operands to the given operation. Push
4011 the result of the operation back on the stack. */
4012 switch (c)
4013 {
4014 case '+':
4015 v = pop ();
4016 v += pop ();
4017 push (v);
4018 break;
4019 case '*':
4020 v = pop ();
4021 v *= pop ();
4022 push (v);
4023 break;
4024 case '<':
4025 v = pop ();
4026 v = pop () << v;
4027 push (v);
4028 break;
4029 default:
4030 abort ();
4031 }
4032 }
4033 while (*cp && *cp != '=');
4034
4035 /* Move over the equal operator. */
4036 cp++;
4037
4038 /* Pop the RHS off the stack. */
4039 c = pop ();
4040
4041 /* Perform the assignment. */
4042 var (varname) = c;
4043
4044 /* Handle side effects. and special 'O' stack cases. */
4045 switch (varname)
4046 {
4047 /* Consume some bytes from the input space. */
4048 case 'L':
4049 offset += c;
4050 break;
4051 /* A symbol to use in the relocation. Make a note
4052 of this if we are not just counting. */
4053 case 'S':
4054 if (! just_count)
4055 rptr->sym_ptr_ptr = &symbols[c];
4056 break;
4057 /* Handle the linker expression stack. */
4058 case 'O':
4059 switch (op)
4060 {
4061 case R_COMP1:
4062 subop = comp1_opcodes;
4063 break;
4064 case R_COMP2:
4065 subop = comp2_opcodes;
4066 break;
4067 case R_COMP3:
4068 subop = comp3_opcodes;
4069 break;
4070 default:
4071 abort ();
4072 }
4073 while (*subop <= (unsigned char) c)
4074 ++subop;
4075 --subop;
4076 break;
4077 default:
4078 break;
4079 }
4080 }
4081
4082 /* If we used a previous fixup, clean up after it. */
4083 if (prev_fixup)
4084 {
4085 fixup = save_fixup + 1;
4086 prev_fixup = 0;
4087 }
4088 /* Queue it. */
4089 else if (fixup > save_fixup + 1)
4090 som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
4091
4092 /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION
4093 fixups to BFD. */
4094 if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
4095 && som_hppa_howto_table[op].type != R_NO_RELOCATION)
4096 {
4097 /* Done with a single reloction. Loop back to the top. */
4098 if (! just_count)
4099 {
4100 rptr->addend = var ('V');
4101 rptr++;
4102 }
4103 count++;
4104 /* Now that we've handled a "full" relocation, reset
4105 some state. */
4106 memset (variables, 0, sizeof (variables));
4107 memset (stack, 0, sizeof (stack));
4108 }
4109 }
4110 return count;
4111
4112 #undef var
4113 #undef push
4114 #undef pop
4115 #undef emptystack
4116 }
4117
4118 /* Read in the relocs (aka fixups in SOM terms) for a section.
4119
4120 som_get_reloc_upper_bound calls this routine with JUST_COUNT
4121 set to true to indicate it only needs a count of the number
4122 of actual relocations. */
4123
4124 static boolean
4125 som_slurp_reloc_table (abfd, section, symbols, just_count)
4126 bfd *abfd;
4127 asection *section;
4128 asymbol **symbols;
4129 boolean just_count;
4130 {
4131 char *external_relocs;
4132 unsigned int fixup_stream_size;
4133 arelent *internal_relocs;
4134 unsigned int num_relocs;
4135
4136 fixup_stream_size = som_section_data (section)->reloc_size;
4137 /* If there were no relocations, then there is nothing to do. */
4138 if (section->reloc_count == 0)
4139 return true;
4140
4141 /* If reloc_count is -1, then the relocation stream has not been
4142 parsed. We must do so now to know how many relocations exist. */
4143 if (section->reloc_count == -1)
4144 {
4145 external_relocs = (char *) malloc (fixup_stream_size);
4146 if (external_relocs == (char *) NULL)
4147 {
4148 bfd_set_error (bfd_error_no_memory);
4149 return false;
4150 }
4151 /* Read in the external forms. */
4152 if (bfd_seek (abfd,
4153 obj_som_reloc_filepos (abfd) + section->rel_filepos,
4154 SEEK_SET)
4155 != 0)
4156 return false;
4157 if (bfd_read (external_relocs, 1, fixup_stream_size, abfd)
4158 != fixup_stream_size)
4159 return false;
4160
4161 /* Let callers know how many relocations found.
4162 also save the relocation stream as we will
4163 need it again. */
4164 section->reloc_count = som_set_reloc_info (external_relocs,
4165 fixup_stream_size,
4166 NULL, NULL, NULL, true);
4167
4168 som_section_data (section)->reloc_stream = external_relocs;
4169 }
4170
4171 /* If the caller only wanted a count, then return now. */
4172 if (just_count)
4173 return true;
4174
4175 num_relocs = section->reloc_count;
4176 external_relocs = som_section_data (section)->reloc_stream;
4177 /* Return saved information about the relocations if it is available. */
4178 if (section->relocation != (arelent *) NULL)
4179 return true;
4180
4181 internal_relocs = (arelent *) malloc (num_relocs * sizeof (arelent));
4182 if (internal_relocs == (arelent *) NULL)
4183 {
4184 bfd_set_error (bfd_error_no_memory);
4185 return false;
4186 }
4187
4188 /* Process and internalize the relocations. */
4189 som_set_reloc_info (external_relocs, fixup_stream_size,
4190 internal_relocs, section, symbols, false);
4191
4192 /* Save our results and return success. */
4193 section->relocation = internal_relocs;
4194 return (true);
4195 }
4196
4197 /* Return the number of bytes required to store the relocation
4198 information associated with the given section. */
4199
4200 static long
4201 som_get_reloc_upper_bound (abfd, asect)
4202 bfd *abfd;
4203 sec_ptr asect;
4204 {
4205 /* If section has relocations, then read in the relocation stream
4206 and parse it to determine how many relocations exist. */
4207 if (asect->flags & SEC_RELOC)
4208 {
4209 if (! som_slurp_reloc_table (abfd, asect, NULL, true))
4210 return false;
4211 return (asect->reloc_count + 1) * sizeof (arelent);
4212 }
4213 /* There are no relocations. */
4214 return 0;
4215 }
4216
4217 /* Convert relocations from SOM (external) form into BFD internal
4218 form. Return the number of relocations. */
4219
4220 static long
4221 som_canonicalize_reloc (abfd, section, relptr, symbols)
4222 bfd *abfd;
4223 sec_ptr section;
4224 arelent **relptr;
4225 asymbol **symbols;
4226 {
4227 arelent *tblptr;
4228 int count;
4229
4230 if (som_slurp_reloc_table (abfd, section, symbols, false) == false)
4231 return -1;
4232
4233 count = section->reloc_count;
4234 tblptr = section->relocation;
4235
4236 while (count--)
4237 *relptr++ = tblptr++;
4238
4239 *relptr = (arelent *) NULL;
4240 return section->reloc_count;
4241 }
4242
4243 extern bfd_target som_vec;
4244
4245 /* A hook to set up object file dependent section information. */
4246
4247 static boolean
4248 som_new_section_hook (abfd, newsect)
4249 bfd *abfd;
4250 asection *newsect;
4251 {
4252 newsect->used_by_bfd =
4253 (PTR) bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
4254 if (!newsect->used_by_bfd)
4255 {
4256 bfd_set_error (bfd_error_no_memory);
4257 return false;
4258 }
4259 newsect->alignment_power = 3;
4260
4261 /* We allow more than three sections internally */
4262 return true;
4263 }
4264
4265 /* Copy any private info we understand from the input section
4266 to the output section. */
4267 static boolean
4268 som_bfd_copy_private_section_data (ibfd, isection, obfd, osection)
4269 bfd *ibfd;
4270 asection *isection;
4271 bfd *obfd;
4272 asection *osection;
4273 {
4274 /* One day we may try to grok other private data. */
4275 if (ibfd->xvec->flavour != bfd_target_som_flavour
4276 || obfd->xvec->flavour != bfd_target_som_flavour
4277 || (!som_is_space (isection) && !som_is_subspace (isection)))
4278 return false;
4279
4280 som_section_data (osection)->copy_data
4281 = (struct som_copyable_section_data_struct *)
4282 bfd_zalloc (obfd, sizeof (struct som_copyable_section_data_struct));
4283 if (som_section_data (osection)->copy_data == NULL)
4284 {
4285 bfd_set_error (bfd_error_no_memory);
4286 return false;
4287 }
4288
4289 memcpy (som_section_data (osection)->copy_data,
4290 som_section_data (isection)->copy_data,
4291 sizeof (struct som_copyable_section_data_struct));
4292
4293 /* Reparent if necessary. */
4294 if (som_section_data (osection)->copy_data->container)
4295 som_section_data (osection)->copy_data->container =
4296 som_section_data (osection)->copy_data->container->output_section;
4297
4298 return true;
4299 }
4300
4301 /* Copy any private info we understand from the input bfd
4302 to the output bfd. */
4303
4304 static boolean
4305 som_bfd_copy_private_bfd_data (ibfd, obfd)
4306 bfd *ibfd, *obfd;
4307 {
4308 /* One day we may try to grok other private data. */
4309 if (ibfd->xvec->flavour != bfd_target_som_flavour
4310 || obfd->xvec->flavour != bfd_target_som_flavour)
4311 return false;
4312
4313 /* Allocate some memory to hold the data we need. */
4314 obj_som_exec_data (obfd) = (struct som_exec_data *)
4315 bfd_zalloc (obfd, sizeof (struct som_exec_data));
4316 if (obj_som_exec_data (obfd) == NULL)
4317 {
4318 bfd_set_error (bfd_error_no_memory);
4319 return false;
4320 }
4321
4322 /* Now copy the data. */
4323 memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
4324 sizeof (struct som_exec_data));
4325
4326 return true;
4327 }
4328
4329 /* Set backend info for sections which can not be described
4330 in the BFD data structures. */
4331
4332 boolean
4333 bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
4334 asection *section;
4335 int defined;
4336 int private;
4337 unsigned int sort_key;
4338 int spnum;
4339 {
4340 /* Allocate memory to hold the magic information. */
4341 if (som_section_data (section)->copy_data == NULL)
4342 {
4343 som_section_data (section)->copy_data
4344 = (struct som_copyable_section_data_struct *)
4345 bfd_zalloc (section->owner,
4346 sizeof (struct som_copyable_section_data_struct));
4347 if (som_section_data (section)->copy_data == NULL)
4348 {
4349 bfd_set_error (bfd_error_no_memory);
4350 return false;
4351 }
4352 }
4353 som_section_data (section)->copy_data->sort_key = sort_key;
4354 som_section_data (section)->copy_data->is_defined = defined;
4355 som_section_data (section)->copy_data->is_private = private;
4356 som_section_data (section)->copy_data->container = section;
4357 som_section_data (section)->copy_data->space_number = spnum;
4358 return true;
4359 }
4360
4361 /* Set backend info for subsections which can not be described
4362 in the BFD data structures. */
4363
4364 boolean
4365 bfd_som_set_subsection_attributes (section, container, access,
4366 sort_key, quadrant)
4367 asection *section;
4368 asection *container;
4369 int access;
4370 unsigned int sort_key;
4371 int quadrant;
4372 {
4373 /* Allocate memory to hold the magic information. */
4374 if (som_section_data (section)->copy_data == NULL)
4375 {
4376 som_section_data (section)->copy_data
4377 = (struct som_copyable_section_data_struct *)
4378 bfd_zalloc (section->owner,
4379 sizeof (struct som_copyable_section_data_struct));
4380 if (som_section_data (section)->copy_data == NULL)
4381 {
4382 bfd_set_error (bfd_error_no_memory);
4383 return false;
4384 }
4385 }
4386 som_section_data (section)->copy_data->sort_key = sort_key;
4387 som_section_data (section)->copy_data->access_control_bits = access;
4388 som_section_data (section)->copy_data->quadrant = quadrant;
4389 som_section_data (section)->copy_data->container = container;
4390 return true;
4391 }
4392
4393 /* Set the full SOM symbol type. SOM needs far more symbol information
4394 than any other object file format I'm aware of. It is mandatory
4395 to be able to know if a symbol is an entry point, millicode, data,
4396 code, absolute, storage request, or procedure label. If you get
4397 the symbol type wrong your program will not link. */
4398
4399 void
4400 bfd_som_set_symbol_type (symbol, type)
4401 asymbol *symbol;
4402 unsigned int type;
4403 {
4404 som_symbol_data (symbol)->som_type = type;
4405 }
4406
4407 /* Attach 64bits of unwind information to a symbol (which hopefully
4408 is a function of some kind!). It would be better to keep this
4409 in the R_ENTRY relocation, but there is not enough space. */
4410
4411 void
4412 bfd_som_attach_unwind_info (symbol, unwind_desc)
4413 asymbol *symbol;
4414 char *unwind_desc;
4415 {
4416 som_symbol_data (symbol)->unwind = unwind_desc;
4417 }
4418
4419 /* Attach an auxiliary header to the BFD backend so that it may be
4420 written into the object file. */
4421 boolean
4422 bfd_som_attach_aux_hdr (abfd, type, string)
4423 bfd *abfd;
4424 int type;
4425 char *string;
4426 {
4427 if (type == VERSION_AUX_ID)
4428 {
4429 int len = strlen (string);
4430 int pad = 0;
4431
4432 if (len % 4)
4433 pad = (4 - (len % 4));
4434 obj_som_version_hdr (abfd) = (struct user_string_aux_hdr *)
4435 bfd_zalloc (abfd, sizeof (struct aux_id)
4436 + sizeof (unsigned int) + len + pad);
4437 if (!obj_som_version_hdr (abfd))
4438 {
4439 bfd_set_error (bfd_error_no_memory);
4440 return false;
4441 }
4442 obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
4443 obj_som_version_hdr (abfd)->header_id.length = len + pad;
4444 obj_som_version_hdr (abfd)->header_id.length += sizeof (int);
4445 obj_som_version_hdr (abfd)->string_length = len;
4446 strncpy (obj_som_version_hdr (abfd)->user_string, string, len);
4447 }
4448 else if (type == COPYRIGHT_AUX_ID)
4449 {
4450 int len = strlen (string);
4451 int pad = 0;
4452
4453 if (len % 4)
4454 pad = (4 - (len % 4));
4455 obj_som_copyright_hdr (abfd) = (struct copyright_aux_hdr *)
4456 bfd_zalloc (abfd, sizeof (struct aux_id)
4457 + sizeof (unsigned int) + len + pad);
4458 if (!obj_som_copyright_hdr (abfd))
4459 {
4460 bfd_set_error (bfd_error_no_memory);
4461 return false;
4462 }
4463 obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
4464 obj_som_copyright_hdr (abfd)->header_id.length = len + pad;
4465 obj_som_copyright_hdr (abfd)->header_id.length += sizeof (int);
4466 obj_som_copyright_hdr (abfd)->string_length = len;
4467 strcpy (obj_som_copyright_hdr (abfd)->copyright, string);
4468 }
4469 return true;
4470 }
4471
4472 static boolean
4473 som_get_section_contents (abfd, section, location, offset, count)
4474 bfd *abfd;
4475 sec_ptr section;
4476 PTR location;
4477 file_ptr offset;
4478 bfd_size_type count;
4479 {
4480 if (count == 0 || ((section->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0))
4481 return true;
4482 if ((bfd_size_type)(offset+count) > section->_raw_size
4483 || bfd_seek (abfd, (file_ptr)(section->filepos + offset), SEEK_SET) == -1
4484 || bfd_read (location, (bfd_size_type)1, count, abfd) != count)
4485 return (false); /* on error */
4486 return (true);
4487 }
4488
4489 static boolean
4490 som_set_section_contents (abfd, section, location, offset, count)
4491 bfd *abfd;
4492 sec_ptr section;
4493 PTR location;
4494 file_ptr offset;
4495 bfd_size_type count;
4496 {
4497 if (abfd->output_has_begun == false)
4498 {
4499 /* Set up fixed parts of the file, space, and subspace headers.
4500 Notify the world that output has begun. */
4501 som_prep_headers (abfd);
4502 abfd->output_has_begun = true;
4503 /* Start writing the object file. This include all the string
4504 tables, fixup streams, and other portions of the object file. */
4505 som_begin_writing (abfd);
4506 }
4507
4508 /* Only write subspaces which have "real" contents (eg. the contents
4509 are not generated at run time by the OS). */
4510 if (!som_is_subspace (section)
4511 || ((section->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0))
4512 return true;
4513
4514 /* Seek to the proper offset within the object file and write the
4515 data. */
4516 offset += som_section_data (section)->subspace_dict->file_loc_init_value;
4517 if (bfd_seek (abfd, offset, SEEK_SET) == -1)
4518 return false;
4519
4520 if (bfd_write ((PTR) location, 1, count, abfd) != count)
4521 return false;
4522 return true;
4523 }
4524
4525 static boolean
4526 som_set_arch_mach (abfd, arch, machine)
4527 bfd *abfd;
4528 enum bfd_architecture arch;
4529 unsigned long machine;
4530 {
4531 /* Allow any architecture to be supported by the SOM backend */
4532 return bfd_default_set_arch_mach (abfd, arch, machine);
4533 }
4534
4535 static boolean
4536 som_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
4537 functionname_ptr, line_ptr)
4538 bfd *abfd;
4539 asection *section;
4540 asymbol **symbols;
4541 bfd_vma offset;
4542 CONST char **filename_ptr;
4543 CONST char **functionname_ptr;
4544 unsigned int *line_ptr;
4545 {
4546 fprintf (stderr, "som_find_nearest_line unimplemented\n");
4547 fflush (stderr);
4548 abort ();
4549 return (false);
4550 }
4551
4552 static int
4553 som_sizeof_headers (abfd, reloc)
4554 bfd *abfd;
4555 boolean reloc;
4556 {
4557 fprintf (stderr, "som_sizeof_headers unimplemented\n");
4558 fflush (stderr);
4559 abort ();
4560 return (0);
4561 }
4562
4563 /* Return the single-character symbol type corresponding to
4564 SOM section S, or '?' for an unknown SOM section. */
4565
4566 static char
4567 som_section_type (s)
4568 const char *s;
4569 {
4570 const struct section_to_type *t;
4571
4572 for (t = &stt[0]; t->section; t++)
4573 if (!strcmp (s, t->section))
4574 return t->type;
4575 return '?';
4576 }
4577
4578 static int
4579 som_decode_symclass (symbol)
4580 asymbol *symbol;
4581 {
4582 char c;
4583
4584 if (bfd_is_com_section (symbol->section))
4585 return 'C';
4586 if (symbol->section == &bfd_und_section)
4587 return 'U';
4588 if (symbol->section == &bfd_ind_section)
4589 return 'I';
4590 if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL)))
4591 return '?';
4592
4593 if (symbol->section == &bfd_abs_section)
4594 c = 'a';
4595 else if (symbol->section)
4596 c = som_section_type (symbol->section->name);
4597 else
4598 return '?';
4599 if (symbol->flags & BSF_GLOBAL)
4600 c = toupper (c);
4601 return c;
4602 }
4603
4604 /* Return information about SOM symbol SYMBOL in RET. */
4605
4606 static void
4607 som_get_symbol_info (ignore_abfd, symbol, ret)
4608 bfd *ignore_abfd;
4609 asymbol *symbol;
4610 symbol_info *ret;
4611 {
4612 ret->type = som_decode_symclass (symbol);
4613 if (ret->type != 'U')
4614 ret->value = symbol->value+symbol->section->vma;
4615 else
4616 ret->value = 0;
4617 ret->name = symbol->name;
4618 }
4619
4620 /* Count the number of symbols in the archive symbol table. Necessary
4621 so that we can allocate space for all the carsyms at once. */
4622
4623 static boolean
4624 som_bfd_count_ar_symbols (abfd, lst_header, count)
4625 bfd *abfd;
4626 struct lst_header *lst_header;
4627 symindex *count;
4628 {
4629 unsigned int i;
4630 unsigned int *hash_table = NULL;
4631 file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
4632
4633 hash_table =
4634 (unsigned int *) malloc (lst_header->hash_size * sizeof (unsigned int));
4635 if (hash_table == NULL && lst_header->hash_size != 0)
4636 {
4637 bfd_set_error (bfd_error_no_memory);
4638 goto error_return;
4639 }
4640
4641 /* Don't forget to initialize the counter! */
4642 *count = 0;
4643
4644 /* Read in the hash table. The has table is an array of 32bit file offsets
4645 which point to the hash chains. */
4646 if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
4647 != lst_header->hash_size * 4)
4648 goto error_return;
4649
4650 /* Walk each chain counting the number of symbols found on that particular
4651 chain. */
4652 for (i = 0; i < lst_header->hash_size; i++)
4653 {
4654 struct lst_symbol_record lst_symbol;
4655
4656 /* An empty chain has zero as it's file offset. */
4657 if (hash_table[i] == 0)
4658 continue;
4659
4660 /* Seek to the first symbol in this hash chain. */
4661 if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
4662 goto error_return;
4663
4664 /* Read in this symbol and update the counter. */
4665 if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4666 != sizeof (lst_symbol))
4667 goto error_return;
4668
4669 (*count)++;
4670
4671 /* Now iterate through the rest of the symbols on this chain. */
4672 while (lst_symbol.next_entry)
4673 {
4674
4675 /* Seek to the next symbol. */
4676 if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
4677 < 0)
4678 goto error_return;
4679
4680 /* Read the symbol in and update the counter. */
4681 if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4682 != sizeof (lst_symbol))
4683 goto error_return;
4684
4685 (*count)++;
4686 }
4687 }
4688 if (hash_table != NULL)
4689 free (hash_table);
4690 return true;
4691
4692 error_return:
4693 if (hash_table != NULL)
4694 free (hash_table);
4695 return false;
4696 }
4697
4698 /* Fill in the canonical archive symbols (SYMS) from the archive described
4699 by ABFD and LST_HEADER. */
4700
4701 static boolean
4702 som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
4703 bfd *abfd;
4704 struct lst_header *lst_header;
4705 carsym **syms;
4706 {
4707 unsigned int i, len;
4708 carsym *set = syms[0];
4709 unsigned int *hash_table = NULL;
4710 struct som_entry *som_dict = NULL;
4711 file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
4712
4713 hash_table =
4714 (unsigned int *) malloc (lst_header->hash_size * sizeof (unsigned int));
4715 if (hash_table == NULL && lst_header->hash_size != 0)
4716 {
4717 bfd_set_error (bfd_error_no_memory);
4718 goto error_return;
4719 }
4720
4721 som_dict =
4722 (struct som_entry *) malloc (lst_header->module_count
4723 * sizeof (struct som_entry));
4724 if (som_dict == NULL && lst_header->module_count != 0)
4725 {
4726 bfd_set_error (bfd_error_no_memory);
4727 goto error_return;
4728 }
4729
4730 /* Read in the hash table. The has table is an array of 32bit file offsets
4731 which point to the hash chains. */
4732 if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
4733 != lst_header->hash_size * 4)
4734 goto error_return;
4735
4736 /* Seek to and read in the SOM dictionary. We will need this to fill
4737 in the carsym's filepos field. */
4738 if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) < 0)
4739 goto error_return;
4740
4741 if (bfd_read ((PTR) som_dict, lst_header->module_count,
4742 sizeof (struct som_entry), abfd)
4743 != lst_header->module_count * sizeof (struct som_entry))
4744 goto error_return;
4745
4746 /* Walk each chain filling in the carsyms as we go along. */
4747 for (i = 0; i < lst_header->hash_size; i++)
4748 {
4749 struct lst_symbol_record lst_symbol;
4750
4751 /* An empty chain has zero as it's file offset. */
4752 if (hash_table[i] == 0)
4753 continue;
4754
4755 /* Seek to and read the first symbol on the chain. */
4756 if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
4757 goto error_return;
4758
4759 if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4760 != sizeof (lst_symbol))
4761 goto error_return;
4762
4763 /* Get the name of the symbol, first get the length which is stored
4764 as a 32bit integer just before the symbol.
4765
4766 One might ask why we don't just read in the entire string table
4767 and index into it. Well, according to the SOM ABI the string
4768 index can point *anywhere* in the archive to save space, so just
4769 using the string table would not be safe. */
4770 if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
4771 + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
4772 goto error_return;
4773
4774 if (bfd_read (&len, 1, 4, abfd) != 4)
4775 goto error_return;
4776
4777 /* Allocate space for the name and null terminate it too. */
4778 set->name = bfd_zalloc (abfd, len + 1);
4779 if (!set->name)
4780 {
4781 bfd_set_error (bfd_error_no_memory);
4782 goto error_return;
4783 }
4784 if (bfd_read (set->name, 1, len, abfd) != len)
4785 goto error_return;
4786
4787 set->name[len] = 0;
4788
4789 /* Fill in the file offset. Note that the "location" field points
4790 to the SOM itself, not the ar_hdr in front of it. */
4791 set->file_offset = som_dict[lst_symbol.som_index].location
4792 - sizeof (struct ar_hdr);
4793
4794 /* Go to the next symbol. */
4795 set++;
4796
4797 /* Iterate through the rest of the chain. */
4798 while (lst_symbol.next_entry)
4799 {
4800 /* Seek to the next symbol and read it in. */
4801 if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET) <0)
4802 goto error_return;
4803
4804 if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4805 != sizeof (lst_symbol))
4806 goto error_return;
4807
4808 /* Seek to the name length & string and read them in. */
4809 if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
4810 + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
4811 goto error_return;
4812
4813 if (bfd_read (&len, 1, 4, abfd) != 4)
4814 goto error_return;
4815
4816 /* Allocate space for the name and null terminate it too. */
4817 set->name = bfd_zalloc (abfd, len + 1);
4818 if (!set->name)
4819 {
4820 bfd_set_error (bfd_error_no_memory);
4821 goto error_return;
4822 }
4823
4824 if (bfd_read (set->name, 1, len, abfd) != len)
4825 goto error_return;
4826 set->name[len] = 0;
4827
4828 /* Fill in the file offset. Note that the "location" field points
4829 to the SOM itself, not the ar_hdr in front of it. */
4830 set->file_offset = som_dict[lst_symbol.som_index].location
4831 - sizeof (struct ar_hdr);
4832
4833 /* Go on to the next symbol. */
4834 set++;
4835 }
4836 }
4837 /* If we haven't died by now, then we successfully read the entire
4838 archive symbol table. */
4839 if (hash_table != NULL)
4840 free (hash_table);
4841 if (som_dict != NULL)
4842 free (som_dict);
4843 return true;
4844
4845 error_return:
4846 if (hash_table != NULL)
4847 free (hash_table);
4848 if (som_dict != NULL)
4849 free (som_dict);
4850 return false;
4851 }
4852
4853 /* Read in the LST from the archive. */
4854 static boolean
4855 som_slurp_armap (abfd)
4856 bfd *abfd;
4857 {
4858 struct lst_header lst_header;
4859 struct ar_hdr ar_header;
4860 unsigned int parsed_size;
4861 struct artdata *ardata = bfd_ardata (abfd);
4862 char nextname[17];
4863 int i = bfd_read ((PTR) nextname, 1, 16, abfd);
4864
4865 /* Special cases. */
4866 if (i == 0)
4867 return true;
4868 if (i != 16)
4869 return false;
4870
4871 if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) < 0)
4872 return false;
4873
4874 /* For archives without .o files there is no symbol table. */
4875 if (strncmp (nextname, "/ ", 16))
4876 {
4877 bfd_has_map (abfd) = false;
4878 return true;
4879 }
4880
4881 /* Read in and sanity check the archive header. */
4882 if (bfd_read ((PTR) &ar_header, 1, sizeof (struct ar_hdr), abfd)
4883 != sizeof (struct ar_hdr))
4884 return false;
4885
4886 if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
4887 {
4888 bfd_set_error (bfd_error_malformed_archive);
4889 return false;
4890 }
4891
4892 /* How big is the archive symbol table entry? */
4893 errno = 0;
4894 parsed_size = strtol (ar_header.ar_size, NULL, 10);
4895 if (errno != 0)
4896 {
4897 bfd_set_error (bfd_error_malformed_archive);
4898 return false;
4899 }
4900
4901 /* Save off the file offset of the first real user data. */
4902 ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
4903
4904 /* Read in the library symbol table. We'll make heavy use of this
4905 in just a minute. */
4906 if (bfd_read ((PTR) & lst_header, 1, sizeof (struct lst_header), abfd)
4907 != sizeof (struct lst_header))
4908 return false;
4909
4910 /* Sanity check. */
4911 if (lst_header.a_magic != LIBMAGIC)
4912 {
4913 bfd_set_error (bfd_error_malformed_archive);
4914 return false;
4915 }
4916
4917 /* Count the number of symbols in the library symbol table. */
4918 if (som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count)
4919 == false)
4920 return false;
4921
4922 /* Get back to the start of the library symbol table. */
4923 if (bfd_seek (abfd, ardata->first_file_filepos - parsed_size
4924 + sizeof (struct lst_header), SEEK_SET) < 0)
4925 return false;
4926
4927 /* Initializae the cache and allocate space for the library symbols. */
4928 ardata->cache = 0;
4929 ardata->symdefs = (carsym *) bfd_alloc (abfd,
4930 (ardata->symdef_count
4931 * sizeof (carsym)));
4932 if (!ardata->symdefs)
4933 {
4934 bfd_set_error (bfd_error_no_memory);
4935 return false;
4936 }
4937
4938 /* Now fill in the canonical archive symbols. */
4939 if (som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)
4940 == false)
4941 return false;
4942
4943 /* Seek back to the "first" file in the archive. Note the "first"
4944 file may be the extended name table. */
4945 if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) < 0)
4946 return false;
4947
4948 /* Notify the generic archive code that we have a symbol map. */
4949 bfd_has_map (abfd) = true;
4950 return true;
4951 }
4952
4953 /* Begin preparing to write a SOM library symbol table.
4954
4955 As part of the prep work we need to determine the number of symbols
4956 and the size of the associated string section. */
4957
4958 static boolean
4959 som_bfd_prep_for_ar_write (abfd, num_syms, stringsize)
4960 bfd *abfd;
4961 unsigned int *num_syms, *stringsize;
4962 {
4963 bfd *curr_bfd = abfd->archive_head;
4964
4965 /* Some initialization. */
4966 *num_syms = 0;
4967 *stringsize = 0;
4968
4969 /* Iterate over each BFD within this archive. */
4970 while (curr_bfd != NULL)
4971 {
4972 unsigned int curr_count, i;
4973 som_symbol_type *sym;
4974
4975 /* Don't bother for non-SOM objects. */
4976 if (curr_bfd->format != bfd_object
4977 || curr_bfd->xvec->flavour != bfd_target_som_flavour)
4978 {
4979 curr_bfd = curr_bfd->next;
4980 continue;
4981 }
4982
4983 /* Make sure the symbol table has been read, then snag a pointer
4984 to it. It's a little slimey to grab the symbols via obj_som_symtab,
4985 but doing so avoids allocating lots of extra memory. */
4986 if (som_slurp_symbol_table (curr_bfd) == false)
4987 return false;
4988
4989 sym = obj_som_symtab (curr_bfd);
4990 curr_count = bfd_get_symcount (curr_bfd);
4991
4992 /* Examine each symbol to determine if it belongs in the
4993 library symbol table. */
4994 for (i = 0; i < curr_count; i++, sym++)
4995 {
4996 struct som_misc_symbol_info info;
4997
4998 /* Derive SOM information from the BFD symbol. */
4999 som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
5000
5001 /* Should we include this symbol? */
5002 if (info.symbol_type == ST_NULL
5003 || info.symbol_type == ST_SYM_EXT
5004 || info.symbol_type == ST_ARG_EXT)
5005 continue;
5006
5007 /* Only global symbols and unsatisfied commons. */
5008 if (info.symbol_scope != SS_UNIVERSAL
5009 && info.symbol_type != ST_STORAGE)
5010 continue;
5011
5012 /* Do no include undefined symbols. */
5013 if (sym->symbol.section == &bfd_und_section)
5014 continue;
5015
5016 /* Bump the various counters, being careful to honor
5017 alignment considerations in the string table. */
5018 (*num_syms)++;
5019 *stringsize = *stringsize + strlen (sym->symbol.name) + 5;
5020 while (*stringsize % 4)
5021 (*stringsize)++;
5022 }
5023
5024 curr_bfd = curr_bfd->next;
5025 }
5026 return true;
5027 }
5028
5029 /* Hash a symbol name based on the hashing algorithm presented in the
5030 SOM ABI. */
5031 static unsigned int
5032 som_bfd_ar_symbol_hash (symbol)
5033 asymbol *symbol;
5034 {
5035 unsigned int len = strlen (symbol->name);
5036
5037 /* Names with length 1 are special. */
5038 if (len == 1)
5039 return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
5040
5041 return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
5042 | (symbol->name[len-2] << 8) | symbol->name[len-1];
5043 }
5044
5045 static CONST char *
5046 normalize (file)
5047 CONST char *file;
5048 {
5049 CONST char *filename = strrchr (file, '/');
5050
5051 if (filename != NULL)
5052 filename++;
5053 else
5054 filename = file;
5055 return filename;
5056 }
5057
5058 /* Do the bulk of the work required to write the SOM library
5059 symbol table. */
5060
5061 static boolean
5062 som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
5063 bfd *abfd;
5064 unsigned int nsyms, string_size;
5065 struct lst_header lst;
5066 {
5067 file_ptr lst_filepos;
5068 char *strings = NULL, *p;
5069 struct lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
5070 bfd *curr_bfd;
5071 unsigned int *hash_table = NULL;
5072 struct som_entry *som_dict = NULL;
5073 struct lst_symbol_record **last_hash_entry = NULL;
5074 unsigned int curr_som_offset, som_index, extended_name_length = 0;
5075 unsigned int maxname = abfd->xvec->ar_max_namelen;
5076
5077 hash_table =
5078 (unsigned int *) malloc (lst.hash_size * sizeof (unsigned int));
5079 if (hash_table == NULL && lst.hash_size != 0)
5080 {
5081 bfd_set_error (bfd_error_no_memory);
5082 goto error_return;
5083 }
5084 som_dict =
5085 (struct som_entry *) malloc (lst.module_count
5086 * sizeof (struct som_entry));
5087 if (som_dict == NULL && lst.module_count != 0)
5088 {
5089 bfd_set_error (bfd_error_no_memory);
5090 goto error_return;
5091 }
5092
5093 last_hash_entry =
5094 ((struct lst_symbol_record **)
5095 malloc (lst.hash_size * sizeof (struct lst_symbol_record *)));
5096 if (last_hash_entry == NULL && lst.hash_size != 0)
5097 {
5098 bfd_set_error (bfd_error_no_memory);
5099 goto error_return;
5100 }
5101
5102 /* Lots of fields are file positions relative to the start
5103 of the lst record. So save its location. */
5104 lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
5105
5106 /* Some initialization. */
5107 memset (hash_table, 0, 4 * lst.hash_size);
5108 memset (som_dict, 0, lst.module_count * sizeof (struct som_entry));
5109 memset (last_hash_entry, 0,
5110 lst.hash_size * sizeof (struct lst_symbol_record *));
5111
5112 /* Symbols have som_index fields, so we have to keep track of the
5113 index of each SOM in the archive.
5114
5115 The SOM dictionary has (among other things) the absolute file
5116 position for the SOM which a particular dictionary entry
5117 describes. We have to compute that information as we iterate
5118 through the SOMs/symbols. */
5119 som_index = 0;
5120 curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
5121
5122 /* Yow! We have to know the size of the extended name table
5123 too. */
5124 for (curr_bfd = abfd->archive_head;
5125 curr_bfd != NULL;
5126 curr_bfd = curr_bfd->next)
5127 {
5128 CONST char *normal = normalize (curr_bfd->filename);
5129 unsigned int thislen;
5130
5131 if (!normal)
5132 {
5133 bfd_set_error (bfd_error_no_memory);
5134 return false;
5135 }
5136 thislen = strlen (normal);
5137 if (thislen > maxname)
5138 extended_name_length += thislen + 1;
5139 }
5140
5141 /* Make room for the archive header and the contents of the
5142 extended string table. */
5143 if (extended_name_length)
5144 curr_som_offset += extended_name_length + sizeof (struct ar_hdr);
5145
5146 /* Make sure we're properly aligned. */
5147 curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
5148
5149 /* FIXME should be done with buffers just like everything else... */
5150 lst_syms = malloc (nsyms * sizeof (struct lst_symbol_record));
5151 if (lst_syms == NULL && nsyms != 0)
5152 {
5153 bfd_set_error (bfd_error_no_memory);
5154 goto error_return;
5155 }
5156 strings = malloc (string_size);
5157 if (strings == NULL && string_size != 0)
5158 {
5159 bfd_set_error (bfd_error_no_memory);
5160 goto error_return;
5161 }
5162
5163 p = strings;
5164 curr_lst_sym = lst_syms;
5165
5166 curr_bfd = abfd->archive_head;
5167 while (curr_bfd != NULL)
5168 {
5169 unsigned int curr_count, i;
5170 som_symbol_type *sym;
5171
5172 /* Don't bother for non-SOM objects. */
5173 if (curr_bfd->format != bfd_object
5174 || curr_bfd->xvec->flavour != bfd_target_som_flavour)
5175 {
5176 curr_bfd = curr_bfd->next;
5177 continue;
5178 }
5179
5180 /* Make sure the symbol table has been read, then snag a pointer
5181 to it. It's a little slimey to grab the symbols via obj_som_symtab,
5182 but doing so avoids allocating lots of extra memory. */
5183 if (som_slurp_symbol_table (curr_bfd) == false)
5184 goto error_return;
5185
5186 sym = obj_som_symtab (curr_bfd);
5187 curr_count = bfd_get_symcount (curr_bfd);
5188
5189 for (i = 0; i < curr_count; i++, sym++)
5190 {
5191 struct som_misc_symbol_info info;
5192
5193 /* Derive SOM information from the BFD symbol. */
5194 som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
5195
5196 /* Should we include this symbol? */
5197 if (info.symbol_type == ST_NULL
5198 || info.symbol_type == ST_SYM_EXT
5199 || info.symbol_type == ST_ARG_EXT)
5200 continue;
5201
5202 /* Only global symbols and unsatisfied commons. */
5203 if (info.symbol_scope != SS_UNIVERSAL
5204 && info.symbol_type != ST_STORAGE)
5205 continue;
5206
5207 /* Do no include undefined symbols. */
5208 if (sym->symbol.section == &bfd_und_section)
5209 continue;
5210
5211 /* If this is the first symbol from this SOM, then update
5212 the SOM dictionary too. */
5213 if (som_dict[som_index].location == 0)
5214 {
5215 som_dict[som_index].location = curr_som_offset;
5216 som_dict[som_index].length = arelt_size (curr_bfd);
5217 }
5218
5219 /* Fill in the lst symbol record. */
5220 curr_lst_sym->hidden = 0;
5221 curr_lst_sym->secondary_def = 0;
5222 curr_lst_sym->symbol_type = info.symbol_type;
5223 curr_lst_sym->symbol_scope = info.symbol_scope;
5224 curr_lst_sym->check_level = 0;
5225 curr_lst_sym->must_qualify = 0;
5226 curr_lst_sym->initially_frozen = 0;
5227 curr_lst_sym->memory_resident = 0;
5228 curr_lst_sym->is_common = (sym->symbol.section == &bfd_com_section);
5229 curr_lst_sym->dup_common = 0;
5230 curr_lst_sym->xleast = 0;
5231 curr_lst_sym->arg_reloc = info.arg_reloc;
5232 curr_lst_sym->name.n_strx = p - strings + 4;
5233 curr_lst_sym->qualifier_name.n_strx = 0;
5234 curr_lst_sym->symbol_info = info.symbol_info;
5235 curr_lst_sym->symbol_value = info.symbol_value;
5236 curr_lst_sym->symbol_descriptor = 0;
5237 curr_lst_sym->reserved = 0;
5238 curr_lst_sym->som_index = som_index;
5239 curr_lst_sym->symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
5240 curr_lst_sym->next_entry = 0;
5241
5242 /* Insert into the hash table. */
5243 if (hash_table[curr_lst_sym->symbol_key % lst.hash_size])
5244 {
5245 struct lst_symbol_record *tmp;
5246
5247 /* There is already something at the head of this hash chain,
5248 so tack this symbol onto the end of the chain. */
5249 tmp = last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size];
5250 tmp->next_entry
5251 = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
5252 + lst.hash_size * 4
5253 + lst.module_count * sizeof (struct som_entry)
5254 + sizeof (struct lst_header);
5255 }
5256 else
5257 {
5258 /* First entry in this hash chain. */
5259 hash_table[curr_lst_sym->symbol_key % lst.hash_size]
5260 = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
5261 + lst.hash_size * 4
5262 + lst.module_count * sizeof (struct som_entry)
5263 + sizeof (struct lst_header);
5264 }
5265
5266 /* Keep track of the last symbol we added to this chain so we can
5267 easily update its next_entry pointer. */
5268 last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size]
5269 = curr_lst_sym;
5270
5271
5272 /* Update the string table. */
5273 bfd_put_32 (abfd, strlen (sym->symbol.name), p);
5274 p += 4;
5275 strcpy (p, sym->symbol.name);
5276 p += strlen (sym->symbol.name) + 1;
5277 while ((int)p % 4)
5278 {
5279 bfd_put_8 (abfd, 0, p);
5280 p++;
5281 }
5282
5283 /* Head to the next symbol. */
5284 curr_lst_sym++;
5285 }
5286
5287 /* Keep track of where each SOM will finally reside; then look
5288 at the next BFD. */
5289 curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
5290 curr_bfd = curr_bfd->next;
5291 som_index++;
5292 }
5293
5294 /* Now scribble out the hash table. */
5295 if (bfd_write ((PTR) hash_table, lst.hash_size, 4, abfd)
5296 != lst.hash_size * 4)
5297 goto error_return;
5298
5299 /* Then the SOM dictionary. */
5300 if (bfd_write ((PTR) som_dict, lst.module_count,
5301 sizeof (struct som_entry), abfd)
5302 != lst.module_count * sizeof (struct som_entry))
5303 goto error_return;
5304
5305 /* The library symbols. */
5306 if (bfd_write ((PTR) lst_syms, nsyms, sizeof (struct lst_symbol_record), abfd)
5307 != nsyms * sizeof (struct lst_symbol_record))
5308 goto error_return;
5309
5310 /* And finally the strings. */
5311 if (bfd_write ((PTR) strings, string_size, 1, abfd) != string_size)
5312 goto error_return;
5313
5314 if (hash_table != NULL)
5315 free (hash_table);
5316 if (som_dict != NULL)
5317 free (som_dict);
5318 if (last_hash_entry != NULL)
5319 free (last_hash_entry);
5320 if (lst_syms != NULL)
5321 free (lst_syms);
5322 if (strings != NULL)
5323 free (strings);
5324 return true;
5325
5326 error_return:
5327 if (hash_table != NULL)
5328 free (hash_table);
5329 if (som_dict != NULL)
5330 free (som_dict);
5331 if (last_hash_entry != NULL)
5332 free (last_hash_entry);
5333 if (lst_syms != NULL)
5334 free (lst_syms);
5335 if (strings != NULL)
5336 free (strings);
5337
5338 return false;
5339 }
5340
5341 /* Write out the LST for the archive.
5342
5343 You'll never believe this is really how armaps are handled in SOM... */
5344
5345 static boolean
5346 som_write_armap (abfd)
5347 bfd *abfd;
5348 {
5349 bfd *curr_bfd;
5350 struct stat statbuf;
5351 unsigned int i, lst_size, nsyms, stringsize;
5352 struct ar_hdr hdr;
5353 struct lst_header lst;
5354 int *p;
5355
5356 /* We'll use this for the archive's date and mode later. */
5357 if (stat (abfd->filename, &statbuf) != 0)
5358 {
5359 bfd_set_error (bfd_error_system_call);
5360 return false;
5361 }
5362 /* Fudge factor. */
5363 bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
5364
5365 /* Account for the lst header first. */
5366 lst_size = sizeof (struct lst_header);
5367
5368 /* Start building the LST header. */
5369 lst.system_id = HP9000S800_ID;
5370 lst.a_magic = LIBMAGIC;
5371 lst.version_id = VERSION_ID;
5372 lst.file_time.secs = 0;
5373 lst.file_time.nanosecs = 0;
5374
5375 lst.hash_loc = lst_size;
5376 lst.hash_size = SOM_LST_HASH_SIZE;
5377
5378 /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets. */
5379 lst_size += 4 * SOM_LST_HASH_SIZE;
5380
5381 /* We need to count the number of SOMs in this archive. */
5382 curr_bfd = abfd->archive_head;
5383 lst.module_count = 0;
5384 while (curr_bfd != NULL)
5385 {
5386 /* Only true SOM objects count. */
5387 if (curr_bfd->format == bfd_object
5388 && curr_bfd->xvec->flavour == bfd_target_som_flavour)
5389 lst.module_count++;
5390 curr_bfd = curr_bfd->next;
5391 }
5392 lst.module_limit = lst.module_count;
5393 lst.dir_loc = lst_size;
5394 lst_size += sizeof (struct som_entry) * lst.module_count;
5395
5396 /* We don't support import/export tables, auxiliary headers,
5397 or free lists yet. Make the linker work a little harder
5398 to make our life easier. */
5399
5400 lst.export_loc = 0;
5401 lst.export_count = 0;
5402 lst.import_loc = 0;
5403 lst.aux_loc = 0;
5404 lst.aux_size = 0;
5405
5406 /* Count how many symbols we will have on the hash chains and the
5407 size of the associated string table. */
5408 if (som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize) == false)
5409 return false;
5410
5411 lst_size += sizeof (struct lst_symbol_record) * nsyms;
5412
5413 /* For the string table. One day we might actually use this info
5414 to avoid small seeks/reads when reading archives. */
5415 lst.string_loc = lst_size;
5416 lst.string_size = stringsize;
5417 lst_size += stringsize;
5418
5419 /* SOM ABI says this must be zero. */
5420 lst.free_list = 0;
5421 lst.file_end = lst_size;
5422
5423 /* Compute the checksum. Must happen after the entire lst header
5424 has filled in. */
5425 p = (int *)&lst;
5426 lst.checksum = 0;
5427 for (i = 0; i < sizeof (struct lst_header)/sizeof (int) - 1; i++)
5428 lst.checksum ^= *p++;
5429
5430 sprintf (hdr.ar_name, "/ ");
5431 sprintf (hdr.ar_date, "%ld", bfd_ardata (abfd)->armap_timestamp);
5432 sprintf (hdr.ar_uid, "%d", getuid ());
5433 sprintf (hdr.ar_gid, "%d", getgid ());
5434 sprintf (hdr.ar_mode, "%-8o", (unsigned int) statbuf.st_mode);
5435 sprintf (hdr.ar_size, "%-10d", (int) lst_size);
5436 hdr.ar_fmag[0] = '`';
5437 hdr.ar_fmag[1] = '\012';
5438
5439 /* Turn any nulls into spaces. */
5440 for (i = 0; i < sizeof (struct ar_hdr); i++)
5441 if (((char *) (&hdr))[i] == '\0')
5442 (((char *) (&hdr))[i]) = ' ';
5443
5444 /* Scribble out the ar header. */
5445 if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd)
5446 != sizeof (struct ar_hdr))
5447 return false;
5448
5449 /* Now scribble out the lst header. */
5450 if (bfd_write ((PTR) &lst, 1, sizeof (struct lst_header), abfd)
5451 != sizeof (struct lst_header))
5452 return false;
5453
5454 /* Build and write the armap. */
5455 if (som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst) == false)
5456 return false;
5457
5458 /* Done. */
5459 return true;
5460 }
5461
5462 /* Free all information we have cached for this BFD. We can always
5463 read it again later if we need it. */
5464
5465 static boolean
5466 som_bfd_free_cached_info (abfd)
5467 bfd *abfd;
5468 {
5469 asection *o;
5470
5471 if (bfd_get_format (abfd) != bfd_object)
5472 return true;
5473
5474 #define FREE(x) if (x != NULL) { free (x); x = NULL; }
5475 /* Free the native string and symbol tables. */
5476 FREE (obj_som_symtab (abfd));
5477 FREE (obj_som_stringtab (abfd));
5478 for (o = abfd->sections; o != (asection *) NULL; o = o->next)
5479 {
5480 /* Free the native relocations. */
5481 o->reloc_count = -1;
5482 FREE (som_section_data (o)->reloc_stream);
5483 /* Free the generic relocations. */
5484 FREE (o->relocation);
5485 }
5486 #undef FREE
5487
5488 return true;
5489 }
5490
5491 /* End of miscellaneous support functions. */
5492
5493 #define som_close_and_cleanup som_bfd_free_cached_info
5494
5495 #define som_openr_next_archived_file bfd_generic_openr_next_archived_file
5496 #define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
5497 #define som_truncate_arname bfd_bsd_truncate_arname
5498 #define som_slurp_extended_name_table _bfd_slurp_extended_name_table
5499
5500 #define som_get_lineno _bfd_nosymbols_get_lineno
5501 #define som_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
5502
5503 #define som_bfd_get_relocated_section_contents \
5504 bfd_generic_get_relocated_section_contents
5505 #define som_bfd_relax_section bfd_generic_relax_section
5506 #define som_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
5507 #define som_bfd_link_add_symbols _bfd_generic_link_add_symbols
5508 #define som_bfd_final_link _bfd_generic_final_link
5509
5510 bfd_target som_vec =
5511 {
5512 "som", /* name */
5513 bfd_target_som_flavour,
5514 true, /* target byte order */
5515 true, /* target headers byte order */
5516 (HAS_RELOC | EXEC_P | /* object flags */
5517 HAS_LINENO | HAS_DEBUG |
5518 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
5519 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
5520 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
5521
5522 /* leading_symbol_char: is the first char of a user symbol
5523 predictable, and if so what is it */
5524 0,
5525 '/', /* ar_pad_char */
5526 14, /* ar_max_namelen */
5527 3, /* minimum alignment */
5528 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
5529 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
5530 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
5531 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
5532 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
5533 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
5534 {_bfd_dummy_target,
5535 som_object_p, /* bfd_check_format */
5536 bfd_generic_archive_p,
5537 _bfd_dummy_target
5538 },
5539 {
5540 bfd_false,
5541 som_mkobject,
5542 _bfd_generic_mkarchive,
5543 bfd_false
5544 },
5545 {
5546 bfd_false,
5547 som_write_object_contents,
5548 _bfd_write_archive_contents,
5549 bfd_false,
5550 },
5551 #undef som
5552
5553 BFD_JUMP_TABLE_GENERIC (som),
5554 BFD_JUMP_TABLE_COPY (som),
5555 BFD_JUMP_TABLE_CORE (_bfd_nocore),
5556 BFD_JUMP_TABLE_ARCHIVE (som),
5557 BFD_JUMP_TABLE_SYMBOLS (som),
5558 BFD_JUMP_TABLE_RELOCS (som),
5559 BFD_JUMP_TABLE_WRITE (som),
5560 BFD_JUMP_TABLE_LINK (som),
5561 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
5562
5563 (PTR) 0
5564 };
5565
5566 #endif /* HOST_HPPAHPUX || HOST_HPPABSD || HOST_HPPAOSF */