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