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