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