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