xref: /netbsd-src/external/gpl3/gdb/dist/bfd/som.c (revision e670fd5c413e99c2f6a37901bb21c537fcd322d2)
1 /* bfd back-end for HP PA-RISC SOM objects.
2    Copyright (C) 1990-2020 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 "alloca-conf.h"
26 #include "bfd.h"
27 #include "libiberty.h"
28 #include "libbfd.h"
29 #include "som.h"
30 #include "safe-ctype.h"
31 #include "som/reloc.h"
32 #include "aout/ar.h"
33 
34 static bfd_reloc_status_type hppa_som_reloc
35   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
36 static bfd_boolean som_mkobject (bfd *);
37 static bfd_boolean som_is_space (asection *);
38 static bfd_boolean som_is_subspace (asection *);
39 static int compare_subspaces (const void *, const void *);
40 static uint32_t som_compute_checksum (struct som_external_header *);
41 static bfd_boolean som_build_and_write_symbol_table (bfd *);
42 static unsigned int som_slurp_symbol_table (bfd *);
43 
44 /* Magic not defined in standard HP-UX header files until 8.0.  */
45 
46 #ifndef CPU_PA_RISC1_0
47 #define CPU_PA_RISC1_0 0x20B
48 #endif /* CPU_PA_RISC1_0 */
49 
50 #ifndef CPU_PA_RISC1_1
51 #define CPU_PA_RISC1_1 0x210
52 #endif /* CPU_PA_RISC1_1 */
53 
54 #ifndef CPU_PA_RISC2_0
55 #define CPU_PA_RISC2_0 0x214
56 #endif /* CPU_PA_RISC2_0 */
57 
58 #ifndef _PA_RISC1_0_ID
59 #define _PA_RISC1_0_ID CPU_PA_RISC1_0
60 #endif /* _PA_RISC1_0_ID */
61 
62 #ifndef _PA_RISC1_1_ID
63 #define _PA_RISC1_1_ID CPU_PA_RISC1_1
64 #endif /* _PA_RISC1_1_ID */
65 
66 #ifndef _PA_RISC2_0_ID
67 #define _PA_RISC2_0_ID CPU_PA_RISC2_0
68 #endif /* _PA_RISC2_0_ID */
69 
70 #ifndef _PA_RISC_MAXID
71 #define _PA_RISC_MAXID	0x2FF
72 #endif /* _PA_RISC_MAXID */
73 
74 #ifndef _PA_RISC_ID
75 #define _PA_RISC_ID(__m_num)		\
76     (((__m_num) == _PA_RISC1_0_ID) ||	\
77      ((__m_num) >= _PA_RISC1_1_ID && (__m_num) <= _PA_RISC_MAXID))
78 #endif /* _PA_RISC_ID */
79 
80 /* HIUX in it's infinite stupidity changed the names for several "well
81    known" constants.  Work around such braindamage.  Try the HPUX version
82    first, then the HIUX version, and finally provide a default.  */
83 #ifdef HPUX_AUX_ID
84 #define EXEC_AUX_ID HPUX_AUX_ID
85 #endif
86 
87 #if !defined (EXEC_AUX_ID) && defined (HIUX_AUX_ID)
88 #define EXEC_AUX_ID HIUX_AUX_ID
89 #endif
90 
91 #ifndef EXEC_AUX_ID
92 #define EXEC_AUX_ID 0
93 #endif
94 
95 /* Size (in chars) of the temporary buffers used during fixup and string
96    table writes.   */
97 
98 #define SOM_TMP_BUFSIZE 8192
99 
100 /* Size of the hash table in archives.  */
101 #define SOM_LST_HASH_SIZE 31
102 
103 /* Max number of SOMs to be found in an archive.  */
104 #define SOM_LST_MODULE_LIMIT 1024
105 
106 /* Generic alignment macro.  */
107 #define SOM_ALIGN(val, alignment) \
108   (((val) + (alignment) - 1) &~ ((unsigned long) (alignment) - 1))
109 
110 /* SOM allows any one of the four previous relocations to be reused
111    with a "R_PREV_FIXUP" relocation entry.  Since R_PREV_FIXUP
112    relocations are always a single byte, using a R_PREV_FIXUP instead
113    of some multi-byte relocation makes object files smaller.
114 
115    Note one side effect of using a R_PREV_FIXUP is the relocation that
116    is being repeated moves to the front of the queue.  */
117 struct reloc_queue
118 {
119   unsigned char *reloc;
120   unsigned int size;
121 } reloc_queue[4];
122 
123 /* This fully describes the symbol types which may be attached to
124    an EXPORT or IMPORT directive.  Only SOM uses this formation
125    (ELF has no need for it).  */
126 typedef enum
127 {
128   SYMBOL_TYPE_UNKNOWN,
129   SYMBOL_TYPE_ABSOLUTE,
130   SYMBOL_TYPE_CODE,
131   SYMBOL_TYPE_DATA,
132   SYMBOL_TYPE_ENTRY,
133   SYMBOL_TYPE_MILLICODE,
134   SYMBOL_TYPE_PLABEL,
135   SYMBOL_TYPE_PRI_PROG,
136   SYMBOL_TYPE_SEC_PROG,
137 } pa_symbol_type;
138 
139 struct section_to_type
140 {
141   const char *section;
142   char type;
143 };
144 
145 /* Assorted symbol information that needs to be derived from the BFD symbol
146    and/or the BFD backend private symbol data.  */
147 struct som_misc_symbol_info
148 {
149   unsigned int symbol_type;
150   unsigned int symbol_scope;
151   unsigned int arg_reloc;
152   unsigned int symbol_info;
153   unsigned int symbol_value;
154   unsigned int priv_level;
155   unsigned int secondary_def;
156   unsigned int is_comdat;
157   unsigned int is_common;
158   unsigned int dup_common;
159 };
160 
161 /* Map SOM section names to POSIX/BSD single-character symbol types.
162 
163    This table includes all the standard subspaces as defined in the
164    current "PRO ABI for PA-RISC Systems", $UNWIND$ which for
165    some reason was left out, and sections specific to embedded stabs.  */
166 
167 static const struct section_to_type stt[] =
168 {
169   {"$TEXT$", 't'},
170   {"$SHLIB_INFO$", 't'},
171   {"$MILLICODE$", 't'},
172   {"$LIT$", 't'},
173   {"$CODE$", 't'},
174   {"$UNWIND_START$", 't'},
175   {"$UNWIND$", 't'},
176   {"$PRIVATE$", 'd'},
177   {"$PLT$", 'd'},
178   {"$SHLIB_DATA$", 'd'},
179   {"$DATA$", 'd'},
180   {"$SHORTDATA$", 'g'},
181   {"$DLT$", 'd'},
182   {"$GLOBAL$", 'g'},
183   {"$SHORTBSS$", 's'},
184   {"$BSS$", 'b'},
185   {"$GDB_STRINGS$", 'N'},
186   {"$GDB_SYMBOLS$", 'N'},
187   {0, 0}
188 };
189 
190 /* About the relocation formatting table...
191 
192    There are 256 entries in the table, one for each possible
193    relocation opcode available in SOM.  We index the table by
194    the relocation opcode.  The names and operations are those
195    defined by a.out_800 (4).
196 
197    Right now this table is only used to count and perform minimal
198    processing on relocation streams so that they can be internalized
199    into BFD and symbolically printed by utilities.  To make actual use
200    of them would be much more difficult, BFD's concept of relocations
201    is far too simple to handle SOM relocations.  The basic assumption
202    that a relocation can be completely processed independent of other
203    relocations before an object file is written is invalid for SOM.
204 
205    The SOM relocations are meant to be processed as a stream, they
206    specify copying of data from the input section to the output section
207    while possibly modifying the data in some manner.  They also can
208    specify that a variable number of zeros or uninitialized data be
209    inserted on in the output segment at the current offset.  Some
210    relocations specify that some previous relocation be re-applied at
211    the current location in the input/output sections.  And finally a number
212    of relocations have effects on other sections (R_ENTRY, R_EXIT,
213    R_UNWIND_AUX and a variety of others).  There isn't even enough room
214    in the BFD relocation data structure to store enough information to
215    perform all the relocations.
216 
217    Each entry in the table has three fields.
218 
219    The first entry is an index into this "class" of relocations.  This
220    index can then be used as a variable within the relocation itself.
221 
222    The second field is a format string which actually controls processing
223    of the relocation.  It uses a simple postfix machine to do calculations
224    based on variables/constants found in the string and the relocation
225    stream.
226 
227    The third field specifys whether or not this relocation may use
228    a constant (V) from the previous R_DATA_OVERRIDE rather than a constant
229    stored in the instruction.
230 
231    Variables:
232 
233    L = input space byte count
234    D = index into class of relocations
235    M = output space byte count
236    N = statement number (unused?)
237    O = stack operation
238    R = parameter relocation bits
239    S = symbol index
240    T = first 32 bits of stack unwind information
241    U = second 32 bits of stack unwind information
242    V = a literal constant (usually used in the next relocation)
243    P = a previous relocation
244 
245    Lower case letters (starting with 'b') refer to following
246    bytes in the relocation stream.  'b' is the next 1 byte,
247    c is the next 2 bytes, d is the next 3 bytes, etc...
248    This is the variable part of the relocation entries that
249    makes our life a living hell.
250 
251    numerical constants are also used in the format string.  Note
252    the constants are represented in decimal.
253 
254    '+', "*" and "=" represents the obvious postfix operators.
255    '<' represents a left shift.
256 
257    Stack Operations:
258 
259    Parameter Relocation Bits:
260 
261    Unwind Entries:
262 
263    Previous Relocations:  The index field represents which in the queue
264    of 4 previous fixups should be re-applied.
265 
266    Literal Constants:  These are generally used to represent addend
267    parts of relocations when these constants are not stored in the
268    fields of the instructions themselves.  For example the instruction
269    addil foo-$global$-0x1234 would use an override for "0x1234" rather
270    than storing it into the addil itself.  */
271 
272 struct fixup_format
273 {
274   int D;
275   const char *format;
276 };
277 
278 static const struct fixup_format som_fixup_formats[256] =
279 {
280   /* R_NO_RELOCATION.  */
281   {  0, "LD1+4*=" },		/* 0x00 */
282   {  1, "LD1+4*=" },		/* 0x01 */
283   {  2, "LD1+4*=" },		/* 0x02 */
284   {  3, "LD1+4*=" },		/* 0x03 */
285   {  4, "LD1+4*=" },		/* 0x04 */
286   {  5, "LD1+4*=" },		/* 0x05 */
287   {  6, "LD1+4*=" },		/* 0x06 */
288   {  7, "LD1+4*=" },		/* 0x07 */
289   {  8, "LD1+4*=" },		/* 0x08 */
290   {  9, "LD1+4*=" },		/* 0x09 */
291   { 10, "LD1+4*=" },		/* 0x0a */
292   { 11, "LD1+4*=" },		/* 0x0b */
293   { 12, "LD1+4*=" },		/* 0x0c */
294   { 13, "LD1+4*=" },		/* 0x0d */
295   { 14, "LD1+4*=" },		/* 0x0e */
296   { 15, "LD1+4*=" },		/* 0x0f */
297   { 16, "LD1+4*=" },		/* 0x10 */
298   { 17, "LD1+4*=" },		/* 0x11 */
299   { 18, "LD1+4*=" },		/* 0x12 */
300   { 19, "LD1+4*=" },		/* 0x13 */
301   { 20, "LD1+4*=" },		/* 0x14 */
302   { 21, "LD1+4*=" },		/* 0x15 */
303   { 22, "LD1+4*=" },		/* 0x16 */
304   { 23, "LD1+4*=" },		/* 0x17 */
305   {  0, "LD8<b+1+4*=" },	/* 0x18 */
306   {  1, "LD8<b+1+4*=" },	/* 0x19 */
307   {  2, "LD8<b+1+4*=" },	/* 0x1a */
308   {  3, "LD8<b+1+4*=" },	/* 0x1b */
309   {  0, "LD16<c+1+4*=" },	/* 0x1c */
310   {  1, "LD16<c+1+4*=" },	/* 0x1d */
311   {  2, "LD16<c+1+4*=" },	/* 0x1e */
312   {  0, "Ld1+=" },		/* 0x1f */
313   /* R_ZEROES.  */
314   {  0, "Lb1+4*=" },		/* 0x20 */
315   {  1, "Ld1+=" },		/* 0x21 */
316   /* R_UNINIT.  */
317   {  0, "Lb1+4*=" },		/* 0x22 */
318   {  1, "Ld1+=" },		/* 0x23 */
319   /* R_RELOCATION.  */
320   {  0, "L4=" },		/* 0x24 */
321   /* R_DATA_ONE_SYMBOL.  */
322   {  0, "L4=Sb=" },		/* 0x25 */
323   {  1, "L4=Sd=" },		/* 0x26 */
324   /* R_DATA_PLABEL.  */
325   {  0, "L4=Sb=" },		/* 0x27 */
326   {  1, "L4=Sd=" },		/* 0x28 */
327   /* R_SPACE_REF.  */
328   {  0, "L4=" },		/* 0x29 */
329   /* R_REPEATED_INIT.  */
330   {  0, "L4=Mb1+4*=" },		/* 0x2a */
331   {  1, "Lb4*=Mb1+L*=" },	/* 0x2b */
332   {  2, "Lb4*=Md1+4*=" },	/* 0x2c */
333   {  3, "Ld1+=Me1+=" },		/* 0x2d */
334   {  0, "" },			/* 0x2e */
335   {  0, "" },			/* 0x2f */
336   /* R_PCREL_CALL.  */
337   {  0, "L4=RD=Sb=" },		/* 0x30 */
338   {  1, "L4=RD=Sb=" },		/* 0x31 */
339   {  2, "L4=RD=Sb=" },		/* 0x32 */
340   {  3, "L4=RD=Sb=" },		/* 0x33 */
341   {  4, "L4=RD=Sb=" },		/* 0x34 */
342   {  5, "L4=RD=Sb=" },		/* 0x35 */
343   {  6, "L4=RD=Sb=" },		/* 0x36 */
344   {  7, "L4=RD=Sb=" },		/* 0x37 */
345   {  8, "L4=RD=Sb=" },		/* 0x38 */
346   {  9, "L4=RD=Sb=" },		/* 0x39 */
347   {  0, "L4=RD8<b+=Sb=" },	/* 0x3a */
348   {  1, "L4=RD8<b+=Sb=" },	/* 0x3b */
349   {  0, "L4=RD8<b+=Sd=" },	/* 0x3c */
350   {  1, "L4=RD8<b+=Sd=" },	/* 0x3d */
351   /* R_SHORT_PCREL_MODE.  */
352   {  0, "" },			/* 0x3e */
353   /* R_LONG_PCREL_MODE.  */
354   {  0, "" },			/* 0x3f */
355   /* R_ABS_CALL.  */
356   {  0, "L4=RD=Sb=" },		/* 0x40 */
357   {  1, "L4=RD=Sb=" },		/* 0x41 */
358   {  2, "L4=RD=Sb=" },		/* 0x42 */
359   {  3, "L4=RD=Sb=" },		/* 0x43 */
360   {  4, "L4=RD=Sb=" },		/* 0x44 */
361   {  5, "L4=RD=Sb=" },		/* 0x45 */
362   {  6, "L4=RD=Sb=" },		/* 0x46 */
363   {  7, "L4=RD=Sb=" },		/* 0x47 */
364   {  8, "L4=RD=Sb=" },		/* 0x48 */
365   {  9, "L4=RD=Sb=" },		/* 0x49 */
366   {  0, "L4=RD8<b+=Sb=" },	/* 0x4a */
367   {  1, "L4=RD8<b+=Sb=" },	/* 0x4b */
368   {  0, "L4=RD8<b+=Sd=" },	/* 0x4c */
369   {  1, "L4=RD8<b+=Sd=" },	/* 0x4d */
370   /* R_RESERVED.  */
371   {  0, "" },			/* 0x4e */
372   {  0, "" },			/* 0x4f */
373   /* R_DP_RELATIVE.  */
374   {  0, "L4=SD=" },		/* 0x50 */
375   {  1, "L4=SD=" },		/* 0x51 */
376   {  2, "L4=SD=" },		/* 0x52 */
377   {  3, "L4=SD=" },		/* 0x53 */
378   {  4, "L4=SD=" },		/* 0x54 */
379   {  5, "L4=SD=" },		/* 0x55 */
380   {  6, "L4=SD=" },		/* 0x56 */
381   {  7, "L4=SD=" },		/* 0x57 */
382   {  8, "L4=SD=" },		/* 0x58 */
383   {  9, "L4=SD=" },		/* 0x59 */
384   { 10, "L4=SD=" },		/* 0x5a */
385   { 11, "L4=SD=" },		/* 0x5b */
386   { 12, "L4=SD=" },		/* 0x5c */
387   { 13, "L4=SD=" },		/* 0x5d */
388   { 14, "L4=SD=" },		/* 0x5e */
389   { 15, "L4=SD=" },		/* 0x5f */
390   { 16, "L4=SD=" },		/* 0x60 */
391   { 17, "L4=SD=" },		/* 0x61 */
392   { 18, "L4=SD=" },		/* 0x62 */
393   { 19, "L4=SD=" },		/* 0x63 */
394   { 20, "L4=SD=" },		/* 0x64 */
395   { 21, "L4=SD=" },		/* 0x65 */
396   { 22, "L4=SD=" },		/* 0x66 */
397   { 23, "L4=SD=" },		/* 0x67 */
398   { 24, "L4=SD=" },		/* 0x68 */
399   { 25, "L4=SD=" },		/* 0x69 */
400   { 26, "L4=SD=" },		/* 0x6a */
401   { 27, "L4=SD=" },		/* 0x6b */
402   { 28, "L4=SD=" },		/* 0x6c */
403   { 29, "L4=SD=" },		/* 0x6d */
404   { 30, "L4=SD=" },		/* 0x6e */
405   { 31, "L4=SD=" },		/* 0x6f */
406   { 32, "L4=Sb=" },		/* 0x70 */
407   { 33, "L4=Sd=" },		/* 0x71 */
408   /* R_DATA_GPREL.  */
409   {  0, "L4=Sd=" },		/* 0x72 */
410   /* R_RESERVED.  */
411   {  0, "" },			/* 0x73 */
412   {  0, "" },			/* 0x74 */
413   {  0, "" },			/* 0x75 */
414   {  0, "" },			/* 0x76 */
415   {  0, "" },			/* 0x77 */
416   /* R_DLT_REL.  */
417   {  0, "L4=Sb=" },		/* 0x78 */
418   {  1, "L4=Sd=" },		/* 0x79 */
419   /* R_RESERVED.  */
420   {  0, "" },			/* 0x7a */
421   {  0, "" },			/* 0x7b */
422   {  0, "" },			/* 0x7c */
423   {  0, "" },			/* 0x7d */
424   {  0, "" },			/* 0x7e */
425   {  0, "" },			/* 0x7f */
426   /* R_CODE_ONE_SYMBOL.  */
427   {  0, "L4=SD=" },		/* 0x80 */
428   {  1, "L4=SD=" },		/* 0x81 */
429   {  2, "L4=SD=" },		/* 0x82 */
430   {  3, "L4=SD=" },		/* 0x83 */
431   {  4, "L4=SD=" },		/* 0x84 */
432   {  5, "L4=SD=" },		/* 0x85 */
433   {  6, "L4=SD=" },		/* 0x86 */
434   {  7, "L4=SD=" },		/* 0x87 */
435   {  8, "L4=SD=" },		/* 0x88 */
436   {  9, "L4=SD=" },		/* 0x89 */
437   { 10, "L4=SD=" },		/* 0x8q */
438   { 11, "L4=SD=" },		/* 0x8b */
439   { 12, "L4=SD=" },		/* 0x8c */
440   { 13, "L4=SD=" },		/* 0x8d */
441   { 14, "L4=SD=" },		/* 0x8e */
442   { 15, "L4=SD=" },		/* 0x8f */
443   { 16, "L4=SD=" },		/* 0x90 */
444   { 17, "L4=SD=" },		/* 0x91 */
445   { 18, "L4=SD=" },		/* 0x92 */
446   { 19, "L4=SD=" },		/* 0x93 */
447   { 20, "L4=SD=" },		/* 0x94 */
448   { 21, "L4=SD=" },		/* 0x95 */
449   { 22, "L4=SD=" },		/* 0x96 */
450   { 23, "L4=SD=" },		/* 0x97 */
451   { 24, "L4=SD=" },		/* 0x98 */
452   { 25, "L4=SD=" },		/* 0x99 */
453   { 26, "L4=SD=" },		/* 0x9a */
454   { 27, "L4=SD=" },		/* 0x9b */
455   { 28, "L4=SD=" },		/* 0x9c */
456   { 29, "L4=SD=" },		/* 0x9d */
457   { 30, "L4=SD=" },		/* 0x9e */
458   { 31, "L4=SD=" },		/* 0x9f */
459   { 32, "L4=Sb=" },		/* 0xa0 */
460   { 33, "L4=Sd=" },		/* 0xa1 */
461   /* R_RESERVED.  */
462   {  0, "" },			/* 0xa2 */
463   {  0, "" },			/* 0xa3 */
464   {  0, "" },			/* 0xa4 */
465   {  0, "" },			/* 0xa5 */
466   {  0, "" },			/* 0xa6 */
467   {  0, "" },			/* 0xa7 */
468   {  0, "" },			/* 0xa8 */
469   {  0, "" },			/* 0xa9 */
470   {  0, "" },			/* 0xaa */
471   {  0, "" },			/* 0xab */
472   {  0, "" },			/* 0xac */
473   {  0, "" },			/* 0xad */
474   /* R_MILLI_REL.  */
475   {  0, "L4=Sb=" },		/* 0xae */
476   {  1, "L4=Sd=" },		/* 0xaf */
477   /* R_CODE_PLABEL.  */
478   {  0, "L4=Sb=" },		/* 0xb0 */
479   {  1, "L4=Sd=" },		/* 0xb1 */
480   /* R_BREAKPOINT.  */
481   {  0, "L4=" },		/* 0xb2 */
482   /* R_ENTRY.  */
483   {  0, "Te=Ue=" },		/* 0xb3 */
484   {  1, "Uf=" },		/* 0xb4 */
485   /* R_ALT_ENTRY.  */
486   {  0, "" },			/* 0xb5 */
487   /* R_EXIT.  */
488   {  0, "" },			/* 0xb6 */
489   /* R_BEGIN_TRY.  */
490   {  0, "" },			/* 0xb7 */
491   /* R_END_TRY.  */
492   {  0, "R0=" },		/* 0xb8 */
493   {  1, "Rb4*=" },		/* 0xb9 */
494   {  2, "Rd4*=" },		/* 0xba */
495   /* R_BEGIN_BRTAB.  */
496   {  0, "" },			/* 0xbb */
497   /* R_END_BRTAB.  */
498   {  0, "" },			/* 0xbc */
499   /* R_STATEMENT.  */
500   {  0, "Nb=" },		/* 0xbd */
501   {  1, "Nc=" },		/* 0xbe */
502   {  2, "Nd=" },		/* 0xbf */
503   /* R_DATA_EXPR.  */
504   {  0, "L4=" },		/* 0xc0 */
505   /* R_CODE_EXPR.  */
506   {  0, "L4=" },		/* 0xc1 */
507   /* R_FSEL.  */
508   {  0, "" },			/* 0xc2 */
509   /* R_LSEL.  */
510   {  0, "" },			/* 0xc3 */
511   /* R_RSEL.  */
512   {  0, "" },			/* 0xc4 */
513   /* R_N_MODE.  */
514   {  0, "" },			/* 0xc5 */
515   /* R_S_MODE.  */
516   {  0, "" },			/* 0xc6 */
517   /* R_D_MODE.  */
518   {  0, "" },			/* 0xc7 */
519   /* R_R_MODE.  */
520   {  0, "" },			/* 0xc8 */
521   /* R_DATA_OVERRIDE.  */
522   {  0, "V0=" },		/* 0xc9 */
523   {  1, "Vb=" },		/* 0xca */
524   {  2, "Vc=" },		/* 0xcb */
525   {  3, "Vd=" },		/* 0xcc */
526   {  4, "Ve=" },		/* 0xcd */
527   /* R_TRANSLATED.  */
528   {  0, "" },			/* 0xce */
529   /* R_AUX_UNWIND.  */
530   {  0,"Sd=Ve=Ee=" },	       /* 0xcf */
531   /* R_COMP1.  */
532   {  0, "Ob=" },		/* 0xd0 */
533   /* R_COMP2.  */
534   {  0, "Ob=Sd=" },		/* 0xd1 */
535   /* R_COMP3.  */
536   {  0, "Ob=Ve=" },		/* 0xd2 */
537   /* R_PREV_FIXUP.  */
538   {  0, "P" },			/* 0xd3 */
539   {  1, "P" },			/* 0xd4 */
540   {  2, "P" },			/* 0xd5 */
541   {  3, "P" },			/* 0xd6 */
542   /* R_SEC_STMT.  */
543   {  0, "" },			/* 0xd7 */
544   /* R_N0SEL.  */
545   {  0, "" },			/* 0xd8 */
546   /* R_N1SEL.  */
547   {  0, "" },			/* 0xd9 */
548   /* R_LINETAB.  */
549   {  0, "Eb=Sd=Ve=" },		/* 0xda */
550   /* R_LINETAB_ESC.  */
551   {  0, "Eb=Mb=" },		/* 0xdb */
552   /* R_LTP_OVERRIDE.  */
553   {  0, "" },			/* 0xdc */
554   /* R_COMMENT.  */
555   {  0, "Ob=Vf=" },		/* 0xdd */
556   /* R_RESERVED.  */
557   {  0, "" },			/* 0xde */
558   {  0, "" },			/* 0xdf */
559   {  0, "" },			/* 0xe0 */
560   {  0, "" },			/* 0xe1 */
561   {  0, "" },			/* 0xe2 */
562   {  0, "" },			/* 0xe3 */
563   {  0, "" },			/* 0xe4 */
564   {  0, "" },			/* 0xe5 */
565   {  0, "" },			/* 0xe6 */
566   {  0, "" },			/* 0xe7 */
567   {  0, "" },			/* 0xe8 */
568   {  0, "" },			/* 0xe9 */
569   {  0, "" },			/* 0xea */
570   {  0, "" },			/* 0xeb */
571   {  0, "" },			/* 0xec */
572   {  0, "" },			/* 0xed */
573   {  0, "" },			/* 0xee */
574   {  0, "" },			/* 0xef */
575   {  0, "" },			/* 0xf0 */
576   {  0, "" },			/* 0xf1 */
577   {  0, "" },			/* 0xf2 */
578   {  0, "" },			/* 0xf3 */
579   {  0, "" },			/* 0xf4 */
580   {  0, "" },			/* 0xf5 */
581   {  0, "" },			/* 0xf6 */
582   {  0, "" },			/* 0xf7 */
583   {  0, "" },			/* 0xf8 */
584   {  0, "" },			/* 0xf9 */
585   {  0, "" },			/* 0xfa */
586   {  0, "" },			/* 0xfb */
587   {  0, "" },			/* 0xfc */
588   {  0, "" },			/* 0xfd */
589   {  0, "" },			/* 0xfe */
590   {  0, "" },			/* 0xff */
591 };
592 
593 static const int comp1_opcodes[] =
594 {
595   0x00,
596   0x40,
597   0x41,
598   0x42,
599   0x43,
600   0x44,
601   0x45,
602   0x46,
603   0x47,
604   0x48,
605   0x49,
606   0x4a,
607   0x4b,
608   0x60,
609   0x80,
610   0xa0,
611   0xc0,
612   -1
613 };
614 
615 static const int comp2_opcodes[] =
616 {
617   0x00,
618   0x80,
619   0x82,
620   0xc0,
621   -1
622 };
623 
624 static const int comp3_opcodes[] =
625 {
626   0x00,
627   0x02,
628   -1
629 };
630 
631 /* These apparently are not in older versions of hpux reloc.h (hpux7).  */
632 
633 /* And these first appeared in hpux10.  */
634 #ifndef R_SHORT_PCREL_MODE
635 #define NO_PCREL_MODES
636 #define R_SHORT_PCREL_MODE 0x3e
637 #endif
638 
639 #define SOM_HOWTO(TYPE, NAME)	\
640   HOWTO(TYPE, 0, 0, 32, FALSE, 0, 0, hppa_som_reloc, NAME, FALSE, 0, 0, FALSE)
641 
642 static reloc_howto_type som_hppa_howto_table[] =
643 {
644   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
645   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
646   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
647   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
648   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
649   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
650   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
651   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
652   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
653   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
654   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
655   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
656   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
657   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
658   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
659   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
660   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
661   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
662   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
663   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
664   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
665   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
666   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
667   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
668   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
669   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
670   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
671   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
672   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
673   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
674   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
675   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
676   SOM_HOWTO (R_ZEROES, "R_ZEROES"),
677   SOM_HOWTO (R_ZEROES, "R_ZEROES"),
678   SOM_HOWTO (R_UNINIT, "R_UNINIT"),
679   SOM_HOWTO (R_UNINIT, "R_UNINIT"),
680   SOM_HOWTO (R_RELOCATION, "R_RELOCATION"),
681   SOM_HOWTO (R_DATA_ONE_SYMBOL, "R_DATA_ONE_SYMBOL"),
682   SOM_HOWTO (R_DATA_ONE_SYMBOL, "R_DATA_ONE_SYMBOL"),
683   SOM_HOWTO (R_DATA_PLABEL, "R_DATA_PLABEL"),
684   SOM_HOWTO (R_DATA_PLABEL, "R_DATA_PLABEL"),
685   SOM_HOWTO (R_SPACE_REF, "R_SPACE_REF"),
686   SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
687   SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
688   SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
689   SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
690   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
691   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
692   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
693   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
694   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
695   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
696   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
697   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
698   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
699   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
700   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
701   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
702   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
703   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
704   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
705   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
706   SOM_HOWTO (R_SHORT_PCREL_MODE, "R_SHORT_PCREL_MODE"),
707   SOM_HOWTO (R_LONG_PCREL_MODE, "R_LONG_PCREL_MODE"),
708   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
709   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
710   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
711   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
712   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
713   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
714   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
715   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
716   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
717   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
718   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
719   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
720   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
721   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
722   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
723   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
724   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
725   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
726   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
727   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
728   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
729   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
730   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
731   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
732   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
733   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
734   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
735   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
736   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
737   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
738   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
739   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
740   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
741   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
742   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
743   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
744   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
745   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
746   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
747   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
748   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
749   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
750   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
751   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
752   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
753   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
754   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
755   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
756   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
757   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
758   SOM_HOWTO (R_DATA_GPREL, "R_DATA_GPREL"),
759   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
760   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
761   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
762   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
763   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
764   SOM_HOWTO (R_DLT_REL, "R_DLT_REL"),
765   SOM_HOWTO (R_DLT_REL, "R_DLT_REL"),
766   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
767   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
768   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
769   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
770   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
771   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
772   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
773   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
774   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
775   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
776   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
777   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
778   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
779   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
780   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
781   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
782   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
783   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
784   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
785   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
786   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
787   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
788   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
789   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
790   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
791   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
792   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
793   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
794   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
795   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
796   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
797   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
798   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
799   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
800   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
801   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
802   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
803   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
804   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
805   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
806   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
807   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
808   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
809   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
810   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
811   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
812   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
813   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
814   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
815   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
816   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
817   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
818   SOM_HOWTO (R_MILLI_REL, "R_MILLI_REL"),
819   SOM_HOWTO (R_MILLI_REL, "R_MILLI_REL"),
820   SOM_HOWTO (R_CODE_PLABEL, "R_CODE_PLABEL"),
821   SOM_HOWTO (R_CODE_PLABEL, "R_CODE_PLABEL"),
822   SOM_HOWTO (R_BREAKPOINT, "R_BREAKPOINT"),
823   SOM_HOWTO (R_ENTRY, "R_ENTRY"),
824   SOM_HOWTO (R_ENTRY, "R_ENTRY"),
825   SOM_HOWTO (R_ALT_ENTRY, "R_ALT_ENTRY"),
826   SOM_HOWTO (R_EXIT, "R_EXIT"),
827   SOM_HOWTO (R_BEGIN_TRY, "R_BEGIN_TRY"),
828   SOM_HOWTO (R_END_TRY, "R_END_TRY"),
829   SOM_HOWTO (R_END_TRY, "R_END_TRY"),
830   SOM_HOWTO (R_END_TRY, "R_END_TRY"),
831   SOM_HOWTO (R_BEGIN_BRTAB, "R_BEGIN_BRTAB"),
832   SOM_HOWTO (R_END_BRTAB, "R_END_BRTAB"),
833   SOM_HOWTO (R_STATEMENT, "R_STATEMENT"),
834   SOM_HOWTO (R_STATEMENT, "R_STATEMENT"),
835   SOM_HOWTO (R_STATEMENT, "R_STATEMENT"),
836   SOM_HOWTO (R_DATA_EXPR, "R_DATA_EXPR"),
837   SOM_HOWTO (R_CODE_EXPR, "R_CODE_EXPR"),
838   SOM_HOWTO (R_FSEL, "R_FSEL"),
839   SOM_HOWTO (R_LSEL, "R_LSEL"),
840   SOM_HOWTO (R_RSEL, "R_RSEL"),
841   SOM_HOWTO (R_N_MODE, "R_N_MODE"),
842   SOM_HOWTO (R_S_MODE, "R_S_MODE"),
843   SOM_HOWTO (R_D_MODE, "R_D_MODE"),
844   SOM_HOWTO (R_R_MODE, "R_R_MODE"),
845   SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
846   SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
847   SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
848   SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
849   SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
850   SOM_HOWTO (R_TRANSLATED, "R_TRANSLATED"),
851   SOM_HOWTO (R_AUX_UNWIND, "R_AUX_UNWIND"),
852   SOM_HOWTO (R_COMP1, "R_COMP1"),
853   SOM_HOWTO (R_COMP2, "R_COMP2"),
854   SOM_HOWTO (R_COMP3, "R_COMP3"),
855   SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
856   SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
857   SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
858   SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
859   SOM_HOWTO (R_SEC_STMT, "R_SEC_STMT"),
860   SOM_HOWTO (R_N0SEL, "R_N0SEL"),
861   SOM_HOWTO (R_N1SEL, "R_N1SEL"),
862   SOM_HOWTO (R_LINETAB, "R_LINETAB"),
863   SOM_HOWTO (R_LINETAB_ESC, "R_LINETAB_ESC"),
864   SOM_HOWTO (R_LTP_OVERRIDE, "R_LTP_OVERRIDE"),
865   SOM_HOWTO (R_COMMENT, "R_COMMENT"),
866   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
867   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
868   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
869   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
870   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
871   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
872   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
873   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
874   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
875   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
876   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
877   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
878   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
879   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
880   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
881   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
882   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
883   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
884   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
885   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
886   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
887   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
888   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
889   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
890   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
891   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
892   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
893   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
894   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
895   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
896   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
897   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
898   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
899   SOM_HOWTO (R_RESERVED, "R_RESERVED")
900 };
901 
902 /* Initialize the SOM relocation queue.  By definition the queue holds
903    the last four multibyte fixups.  */
904 
905 static void
906 som_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 
920 static void
921 som_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 
938 static void
939 som_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 
990 static int
991 som_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 
1010 static unsigned char *
1011 try_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 
1043 static unsigned char *
1044 som_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 
1114 static unsigned char *
1115 som_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 
1151 static unsigned char *
1152 som_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 
1263 static int
1264 exact_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 
1277 static bfd_reloc_status_type
1278 hppa_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 
1295 int **
1296 hppa_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 
1573 static reloc_howto_type *
1574 som_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 
1586 static reloc_howto_type *
1587 som_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 
1602 static void
1603 som_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 
1610 static void
1611 som_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 
1618 static void
1619 som_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 
1656 static void
1657 som_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 
1694 static void
1695 som_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 
1719 static void
1720 som_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 
1749 static void
1750 som_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 
1785 static void
1786 som_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 
1832 static void
1833 som_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 
1846 static void
1847 som_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 
1865 static void
1866 som_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 
1873 static void
1874 som_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 
1886 static void
1887 som_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 
1903 static void
1904 som_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 
1920 static void
1921 som_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 
1948 static bfd_cleanup
1949 som_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 
2072 static bfd_boolean
2073 setup_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 
2385 static bfd_cleanup
2386 som_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 
2530 static bfd_boolean
2531 som_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 
2544 static bfd_boolean
2545 som_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 
2667 static bfd_boolean
2668 som_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 
2688 static bfd_boolean
2689 som_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 
2711 static bfd_boolean
2712 som_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 
2721 static unsigned long
2722 som_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 
2735 static unsigned long
2736 som_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 
2753 static int
2754 compare_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 
2783 static int
2784 compare_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 
2799 static bfd_boolean
2800 som_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 
2906 static bfd_boolean
2907 som_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 (!som_is_space (section))
2938 	section = section->next;
2939 
2940       /* Now iterate through each of its subspaces.  */
2941       for (subsection = abfd->sections;
2942 	   subsection != NULL;
2943 	   subsection = subsection->next)
2944 	{
2945 	  int reloc_offset;
2946 	  unsigned int current_rounding_mode;
2947 #ifndef NO_PCREL_MODES
2948 	  unsigned int current_call_mode;
2949 #endif
2950 
2951 	  /* Find a subspace of this space.  */
2952 	  if (!som_is_subspace (subsection)
2953 	      || !som_is_container (section, subsection))
2954 	    continue;
2955 
2956 	  /* If this subspace does not have real data, then we are
2957 	     finished with it.  */
2958 	  if ((subsection->flags & SEC_HAS_CONTENTS) == 0)
2959 	    {
2960 	      som_section_data (subsection)->subspace_dict->fixup_request_index
2961 		= -1;
2962 	      continue;
2963 	    }
2964 
2965 	  /* This subspace has some relocations.  Put the relocation stream
2966 	     index into the subspace record.  */
2967 	  som_section_data (subsection)->subspace_dict->fixup_request_index
2968 	    = total_reloc_size;
2969 
2970 	  /* To make life easier start over with a clean slate for
2971 	     each subspace.  Seek to the start of the relocation stream
2972 	     for this subspace in preparation for writing out its fixup
2973 	     stream.  */
2974 	  if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) != 0)
2975 	    return FALSE;
2976 
2977 	  /* Buffer space has already been allocated.  Just perform some
2978 	     initialization here.  */
2979 	  p = tmp_space;
2980 	  subspace_reloc_size = 0;
2981 	  reloc_offset = 0;
2982 	  som_initialize_reloc_queue (reloc_queue);
2983 	  current_rounding_mode = R_N_MODE;
2984 #ifndef NO_PCREL_MODES
2985 	  current_call_mode = R_SHORT_PCREL_MODE;
2986 #endif
2987 
2988 	  /* Translate each BFD relocation into one or more SOM
2989 	     relocations.  */
2990 	  for (j = 0; j < subsection->reloc_count; j++)
2991 	    {
2992 	      arelent *bfd_reloc = subsection->orelocation[j];
2993 	      unsigned int skip;
2994 	      int sym_num;
2995 
2996 	      /* Get the symbol number.  Remember it's stored in a
2997 		 special place for section symbols.  */
2998 	      if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2999 		sym_num = (*bfd_reloc->sym_ptr_ptr)->udata.i;
3000 	      else
3001 		sym_num = som_symbol_data (*bfd_reloc->sym_ptr_ptr)->index;
3002 
3003 	      /* If there is not enough room for the next couple relocations,
3004 		 then dump the current buffer contents now.  Also reinitialize
3005 		 the relocation queue.
3006 
3007 		 No single BFD relocation could ever translate into more
3008 		 than 100 bytes of SOM relocations (20bytes is probably the
3009 		 upper limit, but leave lots of space for growth).  */
3010 	      if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
3011 		{
3012 		  amt = p - tmp_space;
3013 		  if (bfd_bwrite ((void *) tmp_space, amt, abfd) != amt)
3014 		    return FALSE;
3015 
3016 		  p = tmp_space;
3017 		  som_initialize_reloc_queue (reloc_queue);
3018 		}
3019 
3020 	      /* Emit R_NO_RELOCATION fixups to map any bytes which were
3021 		 skipped.  */
3022 	      skip = bfd_reloc->address - reloc_offset;
3023 	      p = som_reloc_skip (abfd, skip, p,
3024 				  &subspace_reloc_size, reloc_queue);
3025 
3026 	      /* Update reloc_offset for the next iteration.
3027 
3028 		 Many relocations do not consume input bytes.  They
3029 		 are markers, or set state necessary to perform some
3030 		 later relocation.  */
3031 	      switch (bfd_reloc->howto->type)
3032 		{
3033 		case R_ENTRY:
3034 		case R_ALT_ENTRY:
3035 		case R_EXIT:
3036 		case R_N_MODE:
3037 		case R_S_MODE:
3038 		case R_D_MODE:
3039 		case R_R_MODE:
3040 		case R_FSEL:
3041 		case R_LSEL:
3042 		case R_RSEL:
3043 		case R_COMP1:
3044 		case R_COMP2:
3045 		case R_BEGIN_BRTAB:
3046 		case R_END_BRTAB:
3047 		case R_BEGIN_TRY:
3048 		case R_END_TRY:
3049 		case R_N0SEL:
3050 		case R_N1SEL:
3051 #ifndef NO_PCREL_MODES
3052 		case R_SHORT_PCREL_MODE:
3053 		case R_LONG_PCREL_MODE:
3054 #endif
3055 		  reloc_offset = bfd_reloc->address;
3056 		  break;
3057 
3058 		default:
3059 		  reloc_offset = bfd_reloc->address + 4;
3060 		  break;
3061 		}
3062 
3063 	      /* Now the actual relocation we care about.  */
3064 	      switch (bfd_reloc->howto->type)
3065 		{
3066 		case R_PCREL_CALL:
3067 		case R_ABS_CALL:
3068 		  p = som_reloc_call (abfd, p, &subspace_reloc_size,
3069 				      bfd_reloc, sym_num, reloc_queue);
3070 		  break;
3071 
3072 		case R_CODE_ONE_SYMBOL:
3073 		case R_DP_RELATIVE:
3074 		  /* Account for any addend.  */
3075 		  if (bfd_reloc->addend)
3076 		    p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3077 					  &subspace_reloc_size, reloc_queue);
3078 
3079 		  if (sym_num < 0x20)
3080 		    {
3081 		      bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
3082 		      subspace_reloc_size += 1;
3083 		      p += 1;
3084 		    }
3085 		  else if (sym_num < 0x100)
3086 		    {
3087 		      bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
3088 		      bfd_put_8 (abfd, sym_num, p + 1);
3089 		      p = try_prev_fixup (abfd, &subspace_reloc_size, p,
3090 					  2, reloc_queue);
3091 		    }
3092 		  else if (sym_num < 0x10000000)
3093 		    {
3094 		      bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
3095 		      bfd_put_8 (abfd, sym_num >> 16, p + 1);
3096 		      bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
3097 		      p = try_prev_fixup (abfd, &subspace_reloc_size,
3098 					  p, 4, reloc_queue);
3099 		    }
3100 		  else
3101 		    abort ();
3102 		  break;
3103 
3104 		case R_DATA_GPREL:
3105 		  /* Account for any addend.  */
3106 		  if (bfd_reloc->addend)
3107 		    p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3108 					  &subspace_reloc_size, reloc_queue);
3109 
3110 		  if (sym_num < 0x10000000)
3111 		    {
3112 		      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3113 		      bfd_put_8 (abfd, sym_num >> 16, p + 1);
3114 		      bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
3115 		      p = try_prev_fixup (abfd, &subspace_reloc_size,
3116 					  p, 4, reloc_queue);
3117 		    }
3118 		  else
3119 		    abort ();
3120 		  break;
3121 
3122 		case R_DATA_ONE_SYMBOL:
3123 		case R_DATA_PLABEL:
3124 		case R_CODE_PLABEL:
3125 		case R_DLT_REL:
3126 		  /* Account for any addend using R_DATA_OVERRIDE.  */
3127 		  if (bfd_reloc->howto->type != R_DATA_ONE_SYMBOL
3128 		      && bfd_reloc->addend)
3129 		    p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3130 					  &subspace_reloc_size, reloc_queue);
3131 
3132 		  if (sym_num < 0x100)
3133 		    {
3134 		      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3135 		      bfd_put_8 (abfd, sym_num, p + 1);
3136 		      p = try_prev_fixup (abfd, &subspace_reloc_size, p,
3137 					  2, reloc_queue);
3138 		    }
3139 		  else if (sym_num < 0x10000000)
3140 		    {
3141 		      bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
3142 		      bfd_put_8 (abfd, sym_num >> 16, p + 1);
3143 		      bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
3144 		      p = try_prev_fixup (abfd, &subspace_reloc_size,
3145 					  p, 4, reloc_queue);
3146 		    }
3147 		  else
3148 		    abort ();
3149 		  break;
3150 
3151 		case R_ENTRY:
3152 		  {
3153 		    unsigned int tmp;
3154 		    arelent *tmp_reloc = NULL;
3155 		    bfd_put_8 (abfd, R_ENTRY, p);
3156 
3157 		    /* R_ENTRY relocations have 64 bits of associated
3158 		       data.  Unfortunately the addend field of a bfd
3159 		       relocation is only 32 bits.  So, we split up
3160 		       the 64bit unwind information and store part in
3161 		       the R_ENTRY relocation, and the rest in the R_EXIT
3162 		       relocation.  */
3163 		    bfd_put_32 (abfd, bfd_reloc->addend, p + 1);
3164 
3165 		    /* Find the next R_EXIT relocation.  */
3166 		    for (tmp = j; tmp < subsection->reloc_count; tmp++)
3167 		      {
3168 			tmp_reloc = subsection->orelocation[tmp];
3169 			if (tmp_reloc->howto->type == R_EXIT)
3170 			  break;
3171 		      }
3172 
3173 		    if (tmp == subsection->reloc_count)
3174 		      abort ();
3175 
3176 		    bfd_put_32 (abfd, tmp_reloc->addend, p + 5);
3177 		    p = try_prev_fixup (abfd, &subspace_reloc_size,
3178 					p, 9, reloc_queue);
3179 		    break;
3180 		  }
3181 
3182 		case R_N_MODE:
3183 		case R_S_MODE:
3184 		case R_D_MODE:
3185 		case R_R_MODE:
3186 		  /* If this relocation requests the current rounding
3187 		     mode, then it is redundant.  */
3188 		  if (bfd_reloc->howto->type != current_rounding_mode)
3189 		    {
3190 		      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3191 		      subspace_reloc_size += 1;
3192 		      p += 1;
3193 		      current_rounding_mode = bfd_reloc->howto->type;
3194 		    }
3195 		  break;
3196 
3197 #ifndef NO_PCREL_MODES
3198 		case R_LONG_PCREL_MODE:
3199 		case R_SHORT_PCREL_MODE:
3200 		  if (bfd_reloc->howto->type != current_call_mode)
3201 		    {
3202 		      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3203 		      subspace_reloc_size += 1;
3204 		      p += 1;
3205 		      current_call_mode = bfd_reloc->howto->type;
3206 		    }
3207 		  break;
3208 #endif
3209 
3210 		case R_EXIT:
3211 		case R_ALT_ENTRY:
3212 		case R_FSEL:
3213 		case R_LSEL:
3214 		case R_RSEL:
3215 		case R_BEGIN_BRTAB:
3216 		case R_END_BRTAB:
3217 		case R_BEGIN_TRY:
3218 		case R_N0SEL:
3219 		case R_N1SEL:
3220 		  bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3221 		  subspace_reloc_size += 1;
3222 		  p += 1;
3223 		  break;
3224 
3225 		case R_END_TRY:
3226 		  /* The end of an exception handling region.  The reloc's
3227 		     addend contains the offset of the exception handling
3228 		     code.  */
3229 		  if (bfd_reloc->addend == 0)
3230 		    bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3231 		  else if (bfd_reloc->addend < 1024)
3232 		    {
3233 		      bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
3234 		      bfd_put_8 (abfd, bfd_reloc->addend / 4, p + 1);
3235 		      p = try_prev_fixup (abfd, &subspace_reloc_size,
3236 					  p, 2, reloc_queue);
3237 		    }
3238 		  else
3239 		    {
3240 		      bfd_put_8 (abfd, bfd_reloc->howto->type + 2, p);
3241 		      bfd_put_8 (abfd, (bfd_reloc->addend / 4) >> 16, p + 1);
3242 		      bfd_put_16 (abfd, bfd_reloc->addend / 4, p + 2);
3243 		      p = try_prev_fixup (abfd, &subspace_reloc_size,
3244 					  p, 4, reloc_queue);
3245 		    }
3246 		  break;
3247 
3248 		case R_COMP1:
3249 		  /* The only time we generate R_COMP1, R_COMP2 and
3250 		     R_CODE_EXPR relocs is for the difference of two
3251 		     symbols.  Hence we can cheat here.  */
3252 		  bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3253 		  bfd_put_8 (abfd, 0x44, p + 1);
3254 		  p = try_prev_fixup (abfd, &subspace_reloc_size,
3255 				      p, 2, reloc_queue);
3256 		  break;
3257 
3258 		case R_COMP2:
3259 		  /* The only time we generate R_COMP1, R_COMP2 and
3260 		     R_CODE_EXPR relocs is for the difference of two
3261 		     symbols.  Hence we can cheat here.  */
3262 		  bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3263 		  bfd_put_8 (abfd, 0x80, p + 1);
3264 		  bfd_put_8 (abfd, sym_num >> 16, p + 2);
3265 		  bfd_put_16 (abfd, (bfd_vma) sym_num, p + 3);
3266 		  p = try_prev_fixup (abfd, &subspace_reloc_size,
3267 				      p, 5, reloc_queue);
3268 		  break;
3269 
3270 		case R_CODE_EXPR:
3271 		case R_DATA_EXPR:
3272 		  /* The only time we generate R_COMP1, R_COMP2 and
3273 		     R_CODE_EXPR relocs is for the difference of two
3274 		     symbols.  Hence we can cheat here.  */
3275 		  bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3276 		  subspace_reloc_size += 1;
3277 		  p += 1;
3278 		  break;
3279 
3280 		/* Put a "R_RESERVED" relocation in the stream if
3281 		   we hit something we do not understand.  The linker
3282 		   will complain loudly if this ever happens.  */
3283 		default:
3284 		  bfd_put_8 (abfd, 0xff, p);
3285 		  subspace_reloc_size += 1;
3286 		  p += 1;
3287 		  break;
3288 		}
3289 	    }
3290 
3291 	  /* Last BFD relocation for a subspace has been processed.
3292 	     Map the rest of the subspace with R_NO_RELOCATION fixups.  */
3293 	  p = som_reloc_skip (abfd, subsection->size - reloc_offset,
3294 			      p, &subspace_reloc_size, reloc_queue);
3295 
3296 	  /* Scribble out the relocations.  */
3297 	  amt = p - tmp_space;
3298 	  if (bfd_bwrite ((void *) tmp_space, amt, abfd) != amt)
3299 	    return FALSE;
3300 	  p = tmp_space;
3301 
3302 	  total_reloc_size += subspace_reloc_size;
3303 	  som_section_data (subsection)->subspace_dict->fixup_request_quantity
3304 	    = subspace_reloc_size;
3305 	}
3306       section = section->next;
3307     }
3308   *total_reloc_sizep = total_reloc_size;
3309   return TRUE;
3310 }
3311 
3312 /* Write out the space/subspace string table.  */
3313 
3314 static bfd_boolean
3315 som_write_space_strings (bfd *abfd,
3316 			 unsigned long current_offset,
3317 			 unsigned int *string_sizep)
3318 {
3319   /* Chunk of memory that we can use as buffer space, then throw
3320      away.  */
3321   size_t tmp_space_size = SOM_TMP_BUFSIZE;
3322   char *tmp_space = bfd_malloc (tmp_space_size);
3323   char *p = tmp_space;
3324   unsigned int strings_size = 0;
3325   asection *section;
3326   size_t amt;
3327   bfd_size_type res;
3328 
3329   if (tmp_space == NULL)
3330     return FALSE;
3331 
3332   /* Seek to the start of the space strings in preparation for writing
3333      them out.  */
3334   if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
3335     return FALSE;
3336 
3337   /* Walk through all the spaces and subspaces (order is not important)
3338      building up and writing string table entries for their names.  */
3339   for (section = abfd->sections; section != NULL; section = section->next)
3340     {
3341       size_t length;
3342 
3343       /* Only work with space/subspaces; avoid any other sections
3344 	 which might have been made (.text for example).  */
3345       if (!som_is_space (section) && !som_is_subspace (section))
3346 	continue;
3347 
3348       /* Get the length of the space/subspace name.  */
3349       length = strlen (section->name);
3350 
3351       /* If there is not enough room for the next entry, then dump the
3352 	 current buffer contents now and maybe allocate a larger
3353 	 buffer.  Each entry will take 4 bytes to hold the string
3354 	 length + the string itself + null terminator.  */
3355       if (p - tmp_space + 5 + length > tmp_space_size)
3356 	{
3357 	  /* Flush buffer before refilling or reallocating.  */
3358 	  amt = p - tmp_space;
3359 	  if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
3360 	    return FALSE;
3361 
3362 	  /* Reallocate if now empty buffer still too small.  */
3363 	  if (5 + length > tmp_space_size)
3364 	    {
3365 	      /* Ensure a minimum growth factor to avoid O(n**2) space
3366 		 consumption for n strings.  The optimal minimum
3367 		 factor seems to be 2, as no other value can guarantee
3368 		 wasting less than 50% space.  (Note that we cannot
3369 		 deallocate space allocated by `alloca' without
3370 		 returning from this function.)  The same technique is
3371 		 used a few more times below when a buffer is
3372 		 reallocated.  */
3373 	      if (2 * tmp_space_size < length + 5)
3374 		tmp_space_size = length + 5;
3375 	      else
3376 		tmp_space_size = 2 * tmp_space_size;
3377 	      tmp_space = xrealloc (tmp_space, tmp_space_size);
3378 	    }
3379 
3380 	  /* Reset to beginning of the (possibly new) buffer space.  */
3381 	  p = tmp_space;
3382 	}
3383 
3384       /* First element in a string table entry is the length of the
3385 	 string.  Alignment issues are already handled.  */
3386       bfd_put_32 (abfd, (bfd_vma) length, p);
3387       p += 4;
3388       strings_size += 4;
3389 
3390       /* Record the index in the space/subspace records.  */
3391       if (som_is_space (section))
3392 	som_section_data (section)->space_dict->name = strings_size;
3393       else
3394 	som_section_data (section)->subspace_dict->name = strings_size;
3395 
3396       /* Next comes the string itself + a null terminator.  */
3397       strcpy (p, section->name);
3398       p += length + 1;
3399       strings_size += length + 1;
3400 
3401       /* Always align up to the next word boundary.  */
3402       while (strings_size % 4)
3403 	{
3404 	  bfd_put_8 (abfd, 0, p);
3405 	  p++;
3406 	  strings_size++;
3407 	}
3408     }
3409 
3410   /* Done with the space/subspace strings.  Write out any information
3411      contained in a partial block.  */
3412   amt = p - tmp_space;
3413   res = bfd_bwrite ((void *) &tmp_space[0], amt, abfd);
3414   free (tmp_space);
3415   if (res != amt)
3416     return FALSE;
3417   *string_sizep = strings_size;
3418   return TRUE;
3419 }
3420 
3421 /* Write out the symbol string table.  */
3422 
3423 static bfd_boolean
3424 som_write_symbol_strings (bfd *abfd,
3425 			  unsigned long current_offset,
3426 			  asymbol **syms,
3427 			  unsigned int num_syms,
3428 			  unsigned int *string_sizep,
3429 			  struct som_compilation_unit *compilation_unit)
3430 {
3431   unsigned int i;
3432   /* Chunk of memory that we can use as buffer space, then throw
3433      away.  */
3434   size_t tmp_space_size = SOM_TMP_BUFSIZE;
3435   char *tmp_space = bfd_malloc (tmp_space_size);
3436   char *p = tmp_space;
3437   unsigned int strings_size = 0;
3438   size_t amt;
3439   bfd_size_type res;
3440 
3441   if (tmp_space == NULL)
3442     return FALSE;
3443 
3444   /* This gets a bit gruesome because of the compilation unit.  The
3445      strings within the compilation unit are part of the symbol
3446      strings, but don't have symbol_dictionary entries.  So, manually
3447      write them and update the compilation unit header.  On input, the
3448      compilation unit header contains local copies of the strings.
3449      Move them aside.  */
3450 
3451   /* Seek to the start of the space strings in preparation for writing
3452      them out.  */
3453   if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
3454     return FALSE;
3455 
3456   if (compilation_unit)
3457     {
3458       for (i = 0; i < 4; i++)
3459 	{
3460 	  struct som_name_pt *name;
3461 	  size_t length;
3462 
3463 	  switch (i)
3464 	    {
3465 	    case 0:
3466 	      name = &compilation_unit->name;
3467 	      break;
3468 	    case 1:
3469 	      name = &compilation_unit->language_name;
3470 	      break;
3471 	    case 2:
3472 	      name = &compilation_unit->product_id;
3473 	      break;
3474 	    case 3:
3475 	      name = &compilation_unit->version_id;
3476 	      break;
3477 	    default:
3478 	      abort ();
3479 	    }
3480 
3481 	  length = strlen (name->name);
3482 
3483 	  /* If there is not enough room for the next entry, then dump
3484 	     the current buffer contents now and maybe allocate a
3485 	     larger buffer.  */
3486 	  if (p - tmp_space + 5 + length > tmp_space_size)
3487 	    {
3488 	      /* Flush buffer before refilling or reallocating.  */
3489 	      amt = p - tmp_space;
3490 	      if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
3491 		return FALSE;
3492 
3493 	      /* Reallocate if now empty buffer still too small.  */
3494 	      if (5 + length > tmp_space_size)
3495 		{
3496 		  /* See alloca above for discussion of new size.  */
3497 		  if (2 * tmp_space_size < 5 + length)
3498 		    tmp_space_size = 5 + length;
3499 		  else
3500 		    tmp_space_size = 2 * tmp_space_size;
3501 		  tmp_space = xrealloc (tmp_space, tmp_space_size);
3502 		}
3503 
3504 	      /* Reset to beginning of the (possibly new) buffer
3505 		 space.  */
3506 	      p = tmp_space;
3507 	    }
3508 
3509 	  /* First element in a string table entry is the length of
3510 	     the string.  This must always be 4 byte aligned.  This is
3511 	     also an appropriate time to fill in the string index
3512 	     field in the symbol table entry.  */
3513 	  bfd_put_32 (abfd, (bfd_vma) length, p);
3514 	  strings_size += 4;
3515 	  p += 4;
3516 
3517 	  /* Next comes the string itself + a null terminator.  */
3518 	  strcpy (p, name->name);
3519 
3520 	  name->strx = strings_size;
3521 
3522 	  p += length + 1;
3523 	  strings_size += length + 1;
3524 
3525 	  /* Always align up to the next word boundary.  */
3526 	  while (strings_size % 4)
3527 	    {
3528 	      bfd_put_8 (abfd, 0, p);
3529 	      strings_size++;
3530 	      p++;
3531 	    }
3532 	}
3533     }
3534 
3535   for (i = 0; i < num_syms; i++)
3536     {
3537       size_t length = strlen (syms[i]->name);
3538 
3539       /* If there is not enough room for the next entry, then dump the
3540 	 current buffer contents now and maybe allocate a larger buffer.  */
3541      if (p - tmp_space + 5 + length > tmp_space_size)
3542 	{
3543 	  /* Flush buffer before refilling or reallocating.  */
3544 	  amt = p - tmp_space;
3545 	  if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
3546 	    return FALSE;
3547 
3548 	  /* Reallocate if now empty buffer still too small.  */
3549 	  if (5 + length > tmp_space_size)
3550 	    {
3551 	      /* See alloca above for discussion of new size.  */
3552 	      if (2 * tmp_space_size < 5 + length)
3553 		tmp_space_size = 5 + length;
3554 	      else
3555 		tmp_space_size = 2 * tmp_space_size;
3556 	      tmp_space = xrealloc (tmp_space, tmp_space_size);
3557 	    }
3558 
3559 	  /* Reset to beginning of the (possibly new) buffer space.  */
3560 	  p = tmp_space;
3561 	}
3562 
3563       /* First element in a string table entry is the length of the
3564 	 string.  This must always be 4 byte aligned.  This is also
3565 	 an appropriate time to fill in the string index field in the
3566 	 symbol table entry.  */
3567       bfd_put_32 (abfd, (bfd_vma) length, p);
3568       strings_size += 4;
3569       p += 4;
3570 
3571       /* Next comes the string itself + a null terminator.  */
3572       strcpy (p, syms[i]->name);
3573 
3574       som_symbol_data (syms[i])->stringtab_offset = strings_size;
3575       p += length + 1;
3576       strings_size += length + 1;
3577 
3578       /* Always align up to the next word boundary.  */
3579       while (strings_size % 4)
3580 	{
3581 	  bfd_put_8 (abfd, 0, p);
3582 	  strings_size++;
3583 	  p++;
3584 	}
3585     }
3586 
3587   /* Scribble out any partial block.  */
3588   amt = p - tmp_space;
3589   res = bfd_bwrite ((void *) &tmp_space[0], amt, abfd);
3590   free (tmp_space);
3591   if (res != amt)
3592     return FALSE;
3593 
3594   *string_sizep = strings_size;
3595   return TRUE;
3596 }
3597 
3598 /* Compute variable information to be placed in the SOM headers,
3599    space/subspace dictionaries, relocation streams, etc.  Begin
3600    writing parts of the object file.  */
3601 
3602 static bfd_boolean
3603 som_begin_writing (bfd *abfd)
3604 {
3605   unsigned long current_offset = 0;
3606   unsigned int strings_size = 0;
3607   unsigned long num_spaces, num_subspaces, i;
3608   asection *section;
3609   unsigned int total_subspaces = 0;
3610   struct som_exec_auxhdr *exec_header = NULL;
3611 
3612   /* The file header will always be first in an object file,
3613      everything else can be in random locations.  To keep things
3614      "simple" BFD will lay out the object file in the manner suggested
3615      by the PRO ABI for PA-RISC Systems.  */
3616 
3617   /* Before any output can really begin offsets for all the major
3618      portions of the object file must be computed.  So, starting
3619      with the initial file header compute (and sometimes write)
3620      each portion of the object file.  */
3621 
3622   /* Make room for the file header, it's contents are not complete
3623      yet, so it can not be written at this time.  */
3624   current_offset += sizeof (struct som_external_header);
3625 
3626   /* Any auxiliary headers will follow the file header.  Right now
3627      we support only the copyright and version headers.  */
3628   obj_som_file_hdr (abfd)->aux_header_location = current_offset;
3629   obj_som_file_hdr (abfd)->aux_header_size = 0;
3630   if (abfd->flags & (EXEC_P | DYNAMIC))
3631     {
3632       /* Parts of the exec header will be filled in later, so
3633 	 delay writing the header itself.  Fill in the defaults,
3634 	 and write it later.  */
3635       current_offset += sizeof (struct som_external_exec_auxhdr);
3636       obj_som_file_hdr (abfd)->aux_header_size
3637 	+= sizeof (struct som_external_exec_auxhdr);
3638       exec_header = obj_som_exec_hdr (abfd);
3639       exec_header->som_auxhdr.type = EXEC_AUX_ID;
3640       exec_header->som_auxhdr.length = 40;
3641     }
3642   if (obj_som_version_hdr (abfd) != NULL)
3643     {
3644       struct som_external_string_auxhdr ext_string_auxhdr;
3645       bfd_size_type len;
3646 
3647       if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
3648 	return FALSE;
3649 
3650       /* Write the aux_id structure and the string length.  */
3651       len = sizeof (struct som_external_string_auxhdr);
3652       obj_som_file_hdr (abfd)->aux_header_size += len;
3653       current_offset += len;
3654       som_swap_string_auxhdr_out
3655 	(obj_som_version_hdr (abfd), &ext_string_auxhdr);
3656       if (bfd_bwrite (&ext_string_auxhdr, len, abfd) != len)
3657 	return FALSE;
3658 
3659       /* Write the version string.  */
3660       len = obj_som_version_hdr (abfd)->header_id.length - 4;
3661       obj_som_file_hdr (abfd)->aux_header_size += len;
3662       current_offset += len;
3663       if (bfd_bwrite ((void *) obj_som_version_hdr (abfd)->string, len, abfd)
3664 	  != len)
3665 	return FALSE;
3666     }
3667 
3668   if (obj_som_copyright_hdr (abfd) != NULL)
3669     {
3670       struct som_external_string_auxhdr ext_string_auxhdr;
3671       bfd_size_type len;
3672 
3673       if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
3674 	return FALSE;
3675 
3676       /* Write the aux_id structure and the string length.  */
3677       len = sizeof (struct som_external_string_auxhdr);
3678       obj_som_file_hdr (abfd)->aux_header_size += len;
3679       current_offset += len;
3680       som_swap_string_auxhdr_out
3681 	(obj_som_copyright_hdr (abfd), &ext_string_auxhdr);
3682       if (bfd_bwrite (&ext_string_auxhdr, len, abfd) != len)
3683 	return FALSE;
3684 
3685       /* Write the copyright string.  */
3686       len = obj_som_copyright_hdr (abfd)->header_id.length - 4;
3687       obj_som_file_hdr (abfd)->aux_header_size += len;
3688       current_offset += len;
3689       if (bfd_bwrite ((void *) obj_som_copyright_hdr (abfd)->string, len, abfd)
3690 	  != len)
3691 	return FALSE;
3692     }
3693 
3694   /* Next comes the initialization pointers; we have no initialization
3695      pointers, so current offset does not change.  */
3696   obj_som_file_hdr (abfd)->init_array_location = current_offset;
3697   obj_som_file_hdr (abfd)->init_array_total = 0;
3698 
3699   /* Next are the space records.  These are fixed length records.
3700 
3701      Count the number of spaces to determine how much room is needed
3702      in the object file for the space records.
3703 
3704      The names of the spaces are stored in a separate string table,
3705      and the index for each space into the string table is computed
3706      below.  Therefore, it is not possible to write the space headers
3707      at this time.  */
3708   num_spaces = som_count_spaces (abfd);
3709   obj_som_file_hdr (abfd)->space_location = current_offset;
3710   obj_som_file_hdr (abfd)->space_total = num_spaces;
3711   current_offset +=
3712     num_spaces * sizeof (struct som_external_space_dictionary_record);
3713 
3714   /* Next are the subspace records.  These are fixed length records.
3715 
3716      Count the number of subspaes to determine how much room is needed
3717      in the object file for the subspace records.
3718 
3719      A variety if fields in the subspace record are still unknown at
3720      this time (index into string table, fixup stream location/size, etc).  */
3721   num_subspaces = som_count_subspaces (abfd);
3722   obj_som_file_hdr (abfd)->subspace_location = current_offset;
3723   obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
3724   current_offset
3725     += num_subspaces * sizeof (struct som_external_subspace_dictionary_record);
3726 
3727   /* Next is the string table for the space/subspace names.  We will
3728      build and write the string table on the fly.  At the same time
3729      we will fill in the space/subspace name index fields.  */
3730 
3731   /* The string table needs to be aligned on a word boundary.  */
3732   if (current_offset % 4)
3733     current_offset += (4 - (current_offset % 4));
3734 
3735   /* Mark the offset of the space/subspace string table in the
3736      file header.  */
3737   obj_som_file_hdr (abfd)->space_strings_location = current_offset;
3738 
3739   /* Scribble out the space strings.  */
3740   if (! som_write_space_strings (abfd, current_offset, &strings_size))
3741     return FALSE;
3742 
3743   /* Record total string table size in the header and update the
3744      current offset.  */
3745   obj_som_file_hdr (abfd)->space_strings_size = strings_size;
3746   current_offset += strings_size;
3747 
3748   /* Next is the compilation unit.  */
3749   obj_som_file_hdr (abfd)->compiler_location = current_offset;
3750   obj_som_file_hdr (abfd)->compiler_total = 0;
3751   if (obj_som_compilation_unit (abfd))
3752     {
3753       obj_som_file_hdr (abfd)->compiler_total = 1;
3754       current_offset += sizeof (struct som_external_compilation_unit);
3755     }
3756 
3757   /* Now compute the file positions for the loadable subspaces, taking
3758      care to make sure everything stays properly aligned.  */
3759 
3760   section = abfd->sections;
3761   for (i = 0; i < num_spaces; i++)
3762     {
3763       asection *subsection;
3764       int first_subspace;
3765       unsigned int subspace_offset = 0;
3766 
3767       /* Find a space.  */
3768       while (!som_is_space (section))
3769 	section = section->next;
3770 
3771       first_subspace = 1;
3772       /* Now look for all its subspaces.  */
3773       for (subsection = abfd->sections;
3774 	   subsection != NULL;
3775 	   subsection = subsection->next)
3776 	{
3777 
3778 	  if (!som_is_subspace (subsection)
3779 	      || !som_is_container (section, subsection)
3780 	      || (subsection->flags & SEC_ALLOC) == 0)
3781 	    continue;
3782 
3783 	  /* If this is the first subspace in the space, and we are
3784 	     building an executable, then take care to make sure all
3785 	     the alignments are correct and update the exec header.  */
3786 	  if (first_subspace
3787 	      && (abfd->flags & (EXEC_P | DYNAMIC)))
3788 	    {
3789 	      /* Demand paged executables have each space aligned to a
3790 		 page boundary.  Sharable executables (write-protected
3791 		 text) have just the private (aka data & bss) space aligned
3792 		 to a page boundary.  Ugh.  Not true for HPUX.
3793 
3794 		 The HPUX kernel requires the text to always be page aligned
3795 		 within the file regardless of the executable's type.  */
3796 	      if (abfd->flags & (D_PAGED | DYNAMIC)
3797 		  || (subsection->flags & SEC_CODE)
3798 		  || ((abfd->flags & WP_TEXT)
3799 		      && (subsection->flags & SEC_DATA)))
3800 		current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3801 
3802 	      /* Update the exec header.  */
3803 	      if (subsection->flags & SEC_CODE && exec_header->exec_tfile == 0)
3804 		{
3805 		  exec_header->exec_tmem = section->vma;
3806 		  exec_header->exec_tfile = current_offset;
3807 		}
3808 	      if (subsection->flags & SEC_DATA && exec_header->exec_dfile == 0)
3809 		{
3810 		  exec_header->exec_dmem = section->vma;
3811 		  exec_header->exec_dfile = current_offset;
3812 		}
3813 
3814 	      /* Keep track of exactly where we are within a particular
3815 		 space.  This is necessary as the braindamaged HPUX
3816 		 loader will create holes between subspaces *and*
3817 		 subspace alignments are *NOT* preserved.  What a crock.  */
3818 	      subspace_offset = subsection->vma;
3819 
3820 	      /* Only do this for the first subspace within each space.  */
3821 	      first_subspace = 0;
3822 	    }
3823 	  else if (abfd->flags & (EXEC_P | DYNAMIC))
3824 	    {
3825 	      /* The braindamaged HPUX loader may have created a hole
3826 		 between two subspaces.  It is *not* sufficient to use
3827 		 the alignment specifications within the subspaces to
3828 		 account for these holes -- I've run into at least one
3829 		 case where the loader left one code subspace unaligned
3830 		 in a final executable.
3831 
3832 		 To combat this we keep a current offset within each space,
3833 		 and use the subspace vma fields to detect and preserve
3834 		 holes.  What a crock!
3835 
3836 		 ps.  This is not necessary for unloadable space/subspaces.  */
3837 	      current_offset += subsection->vma - subspace_offset;
3838 	      if (subsection->flags & SEC_CODE)
3839 		exec_header->exec_tsize += subsection->vma - subspace_offset;
3840 	      else
3841 		exec_header->exec_dsize += subsection->vma - subspace_offset;
3842 	      subspace_offset += subsection->vma - subspace_offset;
3843 	    }
3844 
3845 	  subsection->target_index = total_subspaces++;
3846 	  /* This is real data to be loaded from the file.  */
3847 	  if (subsection->flags & SEC_LOAD)
3848 	    {
3849 	      /* Update the size of the code & data.  */
3850 	      if (abfd->flags & (EXEC_P | DYNAMIC)
3851 		  && subsection->flags & SEC_CODE)
3852 		exec_header->exec_tsize += subsection->size;
3853 	      else if (abfd->flags & (EXEC_P | DYNAMIC)
3854 		       && subsection->flags & SEC_DATA)
3855 		exec_header->exec_dsize += subsection->size;
3856 	      som_section_data (subsection)->subspace_dict->file_loc_init_value
3857 		= current_offset;
3858 	      subsection->filepos = current_offset;
3859 	      current_offset += subsection->size;
3860 	      subspace_offset += subsection->size;
3861 	    }
3862 	  /* Looks like uninitialized data.  */
3863 	  else
3864 	    {
3865 	      /* Update the size of the bss section.  */
3866 	      if (abfd->flags & (EXEC_P | DYNAMIC))
3867 		exec_header->exec_bsize += subsection->size;
3868 
3869 	      som_section_data (subsection)->subspace_dict->file_loc_init_value
3870 		= 0;
3871 	      som_section_data (subsection)->subspace_dict->
3872 		initialization_length = 0;
3873 	    }
3874 	}
3875       /* Goto the next section.  */
3876       section = section->next;
3877     }
3878 
3879   /* Finally compute the file positions for unloadable subspaces.
3880      If building an executable, start the unloadable stuff on its
3881      own page.  */
3882 
3883   if (abfd->flags & (EXEC_P | DYNAMIC))
3884     current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3885 
3886   obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
3887   section = abfd->sections;
3888   for (i = 0; i < num_spaces; i++)
3889     {
3890       asection *subsection;
3891 
3892       /* Find a space.  */
3893       while (!som_is_space (section))
3894 	section = section->next;
3895 
3896       if (abfd->flags & (EXEC_P | DYNAMIC))
3897 	current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3898 
3899       /* Now look for all its subspaces.  */
3900       for (subsection = abfd->sections;
3901 	   subsection != NULL;
3902 	   subsection = subsection->next)
3903 	{
3904 
3905 	  if (!som_is_subspace (subsection)
3906 	      || !som_is_container (section, subsection)
3907 	      || (subsection->flags & SEC_ALLOC) != 0)
3908 	    continue;
3909 
3910 	  subsection->target_index = total_subspaces++;
3911 	  /* This is real data to be loaded from the file.  */
3912 	  if ((subsection->flags & SEC_LOAD) == 0)
3913 	    {
3914 	      som_section_data (subsection)->subspace_dict->file_loc_init_value
3915 		= current_offset;
3916 	      subsection->filepos = current_offset;
3917 	      current_offset += subsection->size;
3918 	    }
3919 	  /* Looks like uninitialized data.  */
3920 	  else
3921 	    {
3922 	      som_section_data (subsection)->subspace_dict->file_loc_init_value
3923 		= 0;
3924 	      som_section_data (subsection)->subspace_dict->
3925 		initialization_length = subsection->size;
3926 	    }
3927 	}
3928       /* Goto the next section.  */
3929       section = section->next;
3930     }
3931 
3932   /* If building an executable, then make sure to seek to and write
3933      one byte at the end of the file to make sure any necessary
3934      zeros are filled in.  Ugh.  */
3935   if (abfd->flags & (EXEC_P | DYNAMIC))
3936     current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3937   if (bfd_seek (abfd, (file_ptr) current_offset - 1, SEEK_SET) != 0)
3938     return FALSE;
3939   if (bfd_bwrite ((void *) "", (bfd_size_type) 1, abfd) != 1)
3940     return FALSE;
3941 
3942   obj_som_file_hdr (abfd)->unloadable_sp_size
3943     = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
3944 
3945   /* Loader fixups are not supported in any way shape or form.  */
3946   obj_som_file_hdr (abfd)->loader_fixup_location = 0;
3947   obj_som_file_hdr (abfd)->loader_fixup_total = 0;
3948 
3949   /* Done.  Store the total size of the SOM so far.  */
3950   obj_som_file_hdr (abfd)->som_length = current_offset;
3951 
3952   return TRUE;
3953 }
3954 
3955 /* Finally, scribble out the various headers to the disk.  */
3956 
3957 static bfd_boolean
3958 som_finish_writing (bfd *abfd)
3959 {
3960   int num_spaces = som_count_spaces (abfd);
3961   asymbol **syms = bfd_get_outsymbols (abfd);
3962   int i, num_syms;
3963   int subspace_index = 0;
3964   file_ptr location;
3965   asection *section;
3966   unsigned long current_offset;
3967   unsigned int strings_size, total_reloc_size;
3968   size_t amt;
3969   struct som_external_header ext_header;
3970 
3971   /* We must set up the version identifier here as objcopy/strip copy
3972      private BFD data too late for us to handle this in som_begin_writing.  */
3973   if (obj_som_exec_data (abfd)
3974       && obj_som_exec_data (abfd)->version_id)
3975     obj_som_file_hdr (abfd)->version_id = obj_som_exec_data (abfd)->version_id;
3976   else
3977     obj_som_file_hdr (abfd)->version_id = NEW_VERSION_ID;
3978 
3979   /* Next is the symbol table.  These are fixed length records.
3980 
3981      Count the number of symbols to determine how much room is needed
3982      in the object file for the symbol table.
3983 
3984      The names of the symbols are stored in a separate string table,
3985      and the index for each symbol name into the string table is computed
3986      below.  Therefore, it is not possible to write the symbol table
3987      at this time.
3988 
3989      These used to be output before the subspace contents, but they
3990      were moved here to work around a stupid bug in the hpux linker
3991      (fixed in hpux10).  */
3992   current_offset = obj_som_file_hdr (abfd)->som_length;
3993 
3994   /* Make sure we're on a word boundary.  */
3995   if (current_offset % 4)
3996     current_offset += (4 - (current_offset % 4));
3997 
3998   num_syms = bfd_get_symcount (abfd);
3999   obj_som_file_hdr (abfd)->symbol_location = current_offset;
4000   obj_som_file_hdr (abfd)->symbol_total = num_syms;
4001   current_offset +=
4002     num_syms * sizeof (struct som_external_symbol_dictionary_record);
4003 
4004   /* Next are the symbol strings.
4005      Align them to a word boundary.  */
4006   if (current_offset % 4)
4007     current_offset += (4 - (current_offset % 4));
4008   obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
4009 
4010   /* Scribble out the symbol strings.  */
4011   if (! som_write_symbol_strings (abfd, current_offset, syms,
4012 				  num_syms, &strings_size,
4013 				  obj_som_compilation_unit (abfd)))
4014     return FALSE;
4015 
4016   /* Record total string table size in header and update the
4017      current offset.  */
4018   obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
4019   current_offset += strings_size;
4020 
4021   /* Do prep work before handling fixups.  */
4022   if (!som_prep_for_fixups (abfd,
4023 			    bfd_get_outsymbols (abfd),
4024 			    bfd_get_symcount (abfd)))
4025     return FALSE;
4026 
4027   /* At the end of the file is the fixup stream which starts on a
4028      word boundary.  */
4029   if (current_offset % 4)
4030     current_offset += (4 - (current_offset % 4));
4031   obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
4032 
4033   /* Write the fixups and update fields in subspace headers which
4034      relate to the fixup stream.  */
4035   if (! som_write_fixups (abfd, current_offset, &total_reloc_size))
4036     return FALSE;
4037 
4038   /* Record the total size of the fixup stream in the file header.  */
4039   obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
4040 
4041   /* Done.  Store the total size of the SOM.  */
4042   obj_som_file_hdr (abfd)->som_length = current_offset + total_reloc_size;
4043 
4044   /* Now that the symbol table information is complete, build and
4045      write the symbol table.  */
4046   if (! som_build_and_write_symbol_table (abfd))
4047     return FALSE;
4048 
4049   /* Subspaces are written first so that we can set up information
4050      about them in their containing spaces as the subspace is written.  */
4051 
4052   /* Seek to the start of the subspace dictionary records.  */
4053   location = obj_som_file_hdr (abfd)->subspace_location;
4054   if (bfd_seek (abfd, location, SEEK_SET) != 0)
4055     return FALSE;
4056 
4057   section = abfd->sections;
4058   /* Now for each loadable space write out records for its subspaces.  */
4059   for (i = 0; i < num_spaces; i++)
4060     {
4061       asection *subsection;
4062 
4063       /* Find a space.  */
4064       while (!som_is_space (section))
4065 	section = section->next;
4066 
4067       /* Now look for all its subspaces.  */
4068       for (subsection = abfd->sections;
4069 	   subsection != NULL;
4070 	   subsection = subsection->next)
4071 	{
4072 	  struct som_external_subspace_dictionary_record ext_subspace_dict;
4073 
4074 	  /* Skip any section which does not correspond to a space
4075 	     or subspace.  Or does not have SEC_ALLOC set (and therefore
4076 	     has no real bits on the disk).  */
4077 	  if (!som_is_subspace (subsection)
4078 	      || !som_is_container (section, subsection)
4079 	      || (subsection->flags & SEC_ALLOC) == 0)
4080 	    continue;
4081 
4082 	  /* If this is the first subspace for this space, then save
4083 	     the index of the subspace in its containing space.  Also
4084 	     set "is_loadable" in the containing space.  */
4085 
4086 	  if (som_section_data (section)->space_dict->subspace_quantity == 0)
4087 	    {
4088 	      som_section_data (section)->space_dict->is_loadable = 1;
4089 	      som_section_data (section)->space_dict->subspace_index
4090 		= subspace_index;
4091 	    }
4092 
4093 	  /* Increment the number of subspaces seen and the number of
4094 	     subspaces contained within the current space.  */
4095 	  subspace_index++;
4096 	  som_section_data (section)->space_dict->subspace_quantity++;
4097 
4098 	  /* Mark the index of the current space within the subspace's
4099 	     dictionary record.  */
4100 	  som_section_data (subsection)->subspace_dict->space_index = i;
4101 
4102 	  /* Dump the current subspace header.  */
4103 	  som_swap_subspace_dictionary_record_out
4104 	    (som_section_data (subsection)->subspace_dict, &ext_subspace_dict);
4105 	  amt = sizeof (struct som_subspace_dictionary_record);
4106 	  if (bfd_bwrite (&ext_subspace_dict, amt, abfd) != amt)
4107 	    return FALSE;
4108 	}
4109       /* Goto the next section.  */
4110       section = section->next;
4111     }
4112 
4113   /* Now repeat the process for unloadable subspaces.  */
4114   section = abfd->sections;
4115   /* Now for each space write out records for its subspaces.  */
4116   for (i = 0; i < num_spaces; i++)
4117     {
4118       asection *subsection;
4119 
4120       /* Find a space.  */
4121       while (!som_is_space (section))
4122 	section = section->next;
4123 
4124       /* Now look for all its subspaces.  */
4125       for (subsection = abfd->sections;
4126 	   subsection != NULL;
4127 	   subsection = subsection->next)
4128 	{
4129 	  struct som_external_subspace_dictionary_record ext_subspace_dict;
4130 
4131 	  /* Skip any section which does not correspond to a space or
4132 	     subspace, or which SEC_ALLOC set (and therefore handled
4133 	     in the loadable spaces/subspaces code above).  */
4134 
4135 	  if (!som_is_subspace (subsection)
4136 	      || !som_is_container (section, subsection)
4137 	      || (subsection->flags & SEC_ALLOC) != 0)
4138 	    continue;
4139 
4140 	  /* If this is the first subspace for this space, then save
4141 	     the index of the subspace in its containing space.  Clear
4142 	     "is_loadable".  */
4143 
4144 	  if (som_section_data (section)->space_dict->subspace_quantity == 0)
4145 	    {
4146 	      som_section_data (section)->space_dict->is_loadable = 0;
4147 	      som_section_data (section)->space_dict->subspace_index
4148 		= subspace_index;
4149 	    }
4150 
4151 	  /* Increment the number of subspaces seen and the number of
4152 	     subspaces contained within the current space.  */
4153 	  som_section_data (section)->space_dict->subspace_quantity++;
4154 	  subspace_index++;
4155 
4156 	  /* Mark the index of the current space within the subspace's
4157 	     dictionary record.  */
4158 	  som_section_data (subsection)->subspace_dict->space_index = i;
4159 
4160 	  /* Dump this subspace header.  */
4161 	  som_swap_subspace_dictionary_record_out
4162 	    (som_section_data (subsection)->subspace_dict, &ext_subspace_dict);
4163 	  amt = sizeof (struct som_subspace_dictionary_record);
4164 	  if (bfd_bwrite (&ext_subspace_dict, amt, abfd) != amt)
4165 	    return FALSE;
4166 	}
4167       /* Goto the next section.  */
4168       section = section->next;
4169     }
4170 
4171   /* All the subspace dictionary records are written, and all the
4172      fields are set up in the space dictionary records.
4173 
4174      Seek to the right location and start writing the space
4175      dictionary records.  */
4176   location = obj_som_file_hdr (abfd)->space_location;
4177   if (bfd_seek (abfd, location, SEEK_SET) != 0)
4178     return FALSE;
4179 
4180   section = abfd->sections;
4181   for (i = 0; i < num_spaces; i++)
4182     {
4183       struct som_external_space_dictionary_record ext_space_dict;
4184 
4185       /* Find a space.  */
4186       while (!som_is_space (section))
4187 	section = section->next;
4188 
4189       /* Dump its header.  */
4190       som_swap_space_dictionary_out (som_section_data (section)->space_dict,
4191 				     &ext_space_dict);
4192       amt = sizeof (struct som_external_space_dictionary_record);
4193       if (bfd_bwrite (&ext_space_dict, amt, abfd) != amt)
4194 	return FALSE;
4195 
4196       /* Goto the next section.  */
4197       section = section->next;
4198     }
4199 
4200   /* Write the compilation unit record if there is one.  */
4201   if (obj_som_compilation_unit (abfd))
4202     {
4203       struct som_external_compilation_unit ext_comp_unit;
4204 
4205       location = obj_som_file_hdr (abfd)->compiler_location;
4206       if (bfd_seek (abfd, location, SEEK_SET) != 0)
4207 	return FALSE;
4208 
4209       som_swap_compilation_unit_out
4210 	(obj_som_compilation_unit (abfd), &ext_comp_unit);
4211 
4212       amt = sizeof (struct som_external_compilation_unit);
4213       if (bfd_bwrite (&ext_comp_unit, amt, abfd) != amt)
4214 	return FALSE;
4215     }
4216 
4217   /* Setting of the system_id has to happen very late now that copying of
4218      BFD private data happens *after* section contents are set.  */
4219   if (abfd->flags & (EXEC_P | DYNAMIC))
4220     obj_som_file_hdr (abfd)->system_id = obj_som_exec_data (abfd)->system_id;
4221   else if (bfd_get_mach (abfd) == pa20)
4222     obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC2_0;
4223   else if (bfd_get_mach (abfd) == pa11)
4224     obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_1;
4225   else
4226     obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_0;
4227 
4228   /* Swap and compute the checksum for the file header just before writing
4229      the header to disk.  */
4230   som_swap_header_out (obj_som_file_hdr (abfd), &ext_header);
4231   bfd_putb32 (som_compute_checksum (&ext_header), ext_header.checksum);
4232 
4233   /* Only thing left to do is write out the file header.  It is always
4234      at location zero.  Seek there and write it.  */
4235   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
4236     return FALSE;
4237   amt = sizeof (struct som_external_header);
4238   if (bfd_bwrite (&ext_header, amt, abfd) != amt)
4239     return FALSE;
4240 
4241   /* Now write the exec header.  */
4242   if (abfd->flags & (EXEC_P | DYNAMIC))
4243     {
4244       long tmp, som_length;
4245       struct som_exec_auxhdr *exec_header;
4246       struct som_external_exec_auxhdr ext_exec_header;
4247 
4248       exec_header = obj_som_exec_hdr (abfd);
4249       exec_header->exec_entry = bfd_get_start_address (abfd);
4250       exec_header->exec_flags = obj_som_exec_data (abfd)->exec_flags;
4251 
4252       /* Oh joys.  Ram some of the BSS data into the DATA section
4253 	 to be compatible with how the hp linker makes objects
4254 	 (saves memory space).  */
4255       tmp = exec_header->exec_dsize;
4256       tmp = SOM_ALIGN (tmp, PA_PAGESIZE);
4257       exec_header->exec_bsize -= (tmp - exec_header->exec_dsize);
4258       if (exec_header->exec_bsize < 0)
4259 	exec_header->exec_bsize = 0;
4260       exec_header->exec_dsize = tmp;
4261 
4262       /* Now perform some sanity checks.  The idea is to catch bogons now and
4263 	 inform the user, instead of silently generating a bogus file.  */
4264       som_length = obj_som_file_hdr (abfd)->som_length;
4265       if (exec_header->exec_tfile + exec_header->exec_tsize > som_length
4266 	  || exec_header->exec_dfile + exec_header->exec_dsize > som_length)
4267 	{
4268 	  bfd_set_error (bfd_error_bad_value);
4269 	  return FALSE;
4270 	}
4271 
4272       som_swap_exec_auxhdr_out (exec_header, &ext_exec_header);
4273 
4274       if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location,
4275 		    SEEK_SET) != 0)
4276 	return FALSE;
4277 
4278       amt = sizeof (ext_exec_header);
4279       if (bfd_bwrite (&ext_exec_header, amt, abfd) != amt)
4280 	return FALSE;
4281     }
4282   return TRUE;
4283 }
4284 
4285 /* Compute and return the checksum for a SOM file header.  */
4286 
4287 static uint32_t
4288 som_compute_checksum (struct som_external_header *hdr)
4289 {
4290   size_t count, i;
4291   uint32_t checksum;
4292   uint32_t *buffer = (uint32_t *) hdr;
4293 
4294   checksum = 0;
4295   count = sizeof (*hdr) / sizeof (*buffer);
4296   for (i = 0; i < count; i++)
4297     checksum ^= *(buffer + i);
4298 
4299   return checksum;
4300 }
4301 
4302 static void
4303 som_bfd_derive_misc_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
4304 				 asymbol *sym,
4305 				 struct som_misc_symbol_info *info)
4306 {
4307   /* Initialize.  */
4308   memset (info, 0, sizeof (struct som_misc_symbol_info));
4309 
4310   /* The HP SOM linker requires detailed type information about
4311      all symbols (including undefined symbols!).  Unfortunately,
4312      the type specified in an import/export statement does not
4313      always match what the linker wants.  Severe braindamage.  */
4314 
4315   /* Section symbols will not have a SOM symbol type assigned to
4316      them yet.  Assign all section symbols type ST_DATA.  */
4317   if (sym->flags & BSF_SECTION_SYM)
4318     info->symbol_type = ST_DATA;
4319   else
4320     {
4321       /* For BFD style common, the linker will choke unless we set the
4322 	 type and scope to ST_STORAGE and SS_UNSAT, respectively.  */
4323       if (bfd_is_com_section (sym->section))
4324 	{
4325 	  info->symbol_type = ST_STORAGE;
4326 	  info->symbol_scope = SS_UNSAT;
4327 	}
4328 
4329       /* It is possible to have a symbol without an associated
4330 	 type.  This happens if the user imported the symbol
4331 	 without a type and the symbol was never defined
4332 	 locally.  If BSF_FUNCTION is set for this symbol, then
4333 	 assign it type ST_CODE (the HP linker requires undefined
4334 	 external functions to have type ST_CODE rather than ST_ENTRY).  */
4335       else if ((som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
4336 		|| som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
4337 	       && bfd_is_und_section (sym->section)
4338 	       && sym->flags & BSF_FUNCTION)
4339 	info->symbol_type = ST_CODE;
4340 
4341       /* Handle function symbols which were defined in this file.
4342 	 They should have type ST_ENTRY.  Also retrieve the argument
4343 	 relocation bits from the SOM backend information.  */
4344       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY
4345 	       || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
4346 		   && (sym->flags & BSF_FUNCTION))
4347 	       || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
4348 		   && (sym->flags & BSF_FUNCTION)))
4349 	{
4350 	  info->symbol_type = ST_ENTRY;
4351 	  info->arg_reloc = som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc;
4352 	  info->priv_level= som_symbol_data (sym)->tc_data.ap.hppa_priv_level;
4353 	}
4354 
4355       /* For unknown symbols set the symbol's type based on the symbol's
4356 	 section (ST_DATA for DATA sections, ST_CODE for CODE sections).  */
4357       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
4358 	{
4359 	  if (bfd_is_abs_section (sym->section))
4360 	    info->symbol_type = ST_ABSOLUTE;
4361 	  else if (sym->section->flags & SEC_CODE)
4362 	    info->symbol_type = ST_CODE;
4363 	  else
4364 	    info->symbol_type = ST_DATA;
4365 	}
4366 
4367       /* From now on it's a very simple mapping.  */
4368       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
4369 	info->symbol_type = ST_ABSOLUTE;
4370       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
4371 	info->symbol_type = ST_CODE;
4372       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
4373 	info->symbol_type = ST_DATA;
4374       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
4375 	info->symbol_type = ST_MILLICODE;
4376       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
4377 	info->symbol_type = ST_PLABEL;
4378       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
4379 	info->symbol_type = ST_PRI_PROG;
4380       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
4381 	info->symbol_type = ST_SEC_PROG;
4382     }
4383 
4384   /* Now handle the symbol's scope.  Exported data which is not
4385      in the common section has scope SS_UNIVERSAL.  Note scope
4386      of common symbols was handled earlier!  */
4387   if (bfd_is_com_section (sym->section))
4388     ;
4389   else if (bfd_is_und_section (sym->section))
4390     info->symbol_scope = SS_UNSAT;
4391   else if (sym->flags & (BSF_EXPORT | BSF_WEAK))
4392     info->symbol_scope = SS_UNIVERSAL;
4393   /* Anything else which is not in the common section has scope
4394      SS_LOCAL.  */
4395   else
4396     info->symbol_scope = SS_LOCAL;
4397 
4398   /* Now set the symbol_info field.  It has no real meaning
4399      for undefined or common symbols, but the HP linker will
4400      choke if it's not set to some "reasonable" value.  We
4401      use zero as a reasonable value.  */
4402   if (bfd_is_com_section (sym->section)
4403       || bfd_is_und_section (sym->section)
4404       || bfd_is_abs_section (sym->section))
4405     info->symbol_info = 0;
4406   /* For all other symbols, the symbol_info field contains the
4407      subspace index of the space this symbol is contained in.  */
4408   else
4409     info->symbol_info = sym->section->target_index;
4410 
4411   /* Set the symbol's value.  */
4412   info->symbol_value = sym->value + sym->section->vma;
4413 
4414   /* The secondary_def field is for "weak" symbols.  */
4415   if (sym->flags & BSF_WEAK)
4416     info->secondary_def = TRUE;
4417   else
4418     info->secondary_def = FALSE;
4419 
4420   /* The is_comdat, is_common and dup_common fields provide various
4421      flavors of common.
4422 
4423      For data symbols, setting IS_COMMON provides Fortran style common
4424      (duplicate definitions and overlapped initialization).  Setting both
4425      IS_COMMON and DUP_COMMON provides Cobol style common (duplicate
4426      definitions as long as they are all the same length).  In a shared
4427      link data symbols retain their IS_COMMON and DUP_COMMON flags.
4428      An IS_COMDAT data symbol is similar to a IS_COMMON | DUP_COMMON
4429      symbol except in that it loses its IS_COMDAT flag in a shared link.
4430 
4431      For code symbols, IS_COMDAT and DUP_COMMON have effect.  Universal
4432      DUP_COMMON code symbols are not exported from shared libraries.
4433      IS_COMDAT symbols are exported but they lose their IS_COMDAT flag.
4434 
4435      We take a simplified approach to setting the is_comdat, is_common
4436      and dup_common flags in symbols based on the flag settings of their
4437      subspace.  This avoids having to add directives like `.comdat' but
4438      the linker behavior is probably undefined if there is more than one
4439      universal symbol (comdat key sysmbol) in a subspace.
4440 
4441      The behavior of these flags is not well documentmented, so there
4442      may be bugs and some surprising interactions with other flags.  */
4443   if (som_section_data (sym->section)
4444       && som_section_data (sym->section)->subspace_dict
4445       && info->symbol_scope == SS_UNIVERSAL
4446       && (info->symbol_type == ST_ENTRY
4447 	  || info->symbol_type == ST_CODE
4448 	  || info->symbol_type == ST_DATA))
4449     {
4450       info->is_comdat
4451 	= som_section_data (sym->section)->subspace_dict->is_comdat;
4452       info->is_common
4453 	= som_section_data (sym->section)->subspace_dict->is_common;
4454       info->dup_common
4455 	= som_section_data (sym->section)->subspace_dict->dup_common;
4456     }
4457 }
4458 
4459 /* Build and write, in one big chunk, the entire symbol table for
4460    this BFD.  */
4461 
4462 static bfd_boolean
4463 som_build_and_write_symbol_table (bfd *abfd)
4464 {
4465   unsigned int num_syms = bfd_get_symcount (abfd);
4466   file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
4467   asymbol **bfd_syms = obj_som_sorted_syms (abfd);
4468   struct som_external_symbol_dictionary_record *som_symtab = NULL;
4469   unsigned int i;
4470   bfd_size_type symtab_size;
4471   size_t amt;
4472 
4473   /* Compute total symbol table size and allocate a chunk of memory
4474      to hold the symbol table as we build it.  */
4475   if (_bfd_mul_overflow (num_syms,
4476 			 sizeof (struct som_external_symbol_dictionary_record),
4477 			 &amt))
4478     {
4479       bfd_set_error (bfd_error_no_memory);
4480       return FALSE;
4481     }
4482   som_symtab = bfd_zmalloc (amt);
4483   if (som_symtab == NULL && num_syms != 0)
4484     goto error_return;
4485 
4486   /* Walk over each symbol.  */
4487   for (i = 0; i < num_syms; i++)
4488     {
4489       struct som_misc_symbol_info info;
4490       unsigned int flags;
4491 
4492       /* This is really an index into the symbol strings table.
4493 	 By the time we get here, the index has already been
4494 	 computed and stored into the name field in the BFD symbol.  */
4495       bfd_putb32 (som_symbol_data (bfd_syms[i])->stringtab_offset,
4496 		  som_symtab[i].name);
4497 
4498       /* Derive SOM information from the BFD symbol.  */
4499       som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
4500 
4501       /* Now use it.  */
4502       flags = (info.symbol_type << SOM_SYMBOL_TYPE_SH)
4503 	| (info.symbol_scope << SOM_SYMBOL_SCOPE_SH)
4504 	| (info.arg_reloc << SOM_SYMBOL_ARG_RELOC_SH)
4505 	| (3 << SOM_SYMBOL_XLEAST_SH)
4506 	| (info.secondary_def ? SOM_SYMBOL_SECONDARY_DEF : 0)
4507 	| (info.is_common ? SOM_SYMBOL_IS_COMMON : 0)
4508 	| (info.dup_common ? SOM_SYMBOL_DUP_COMMON : 0);
4509       bfd_putb32 (flags, som_symtab[i].flags);
4510 
4511       flags = (info.symbol_info << SOM_SYMBOL_SYMBOL_INFO_SH)
4512 	| (info.is_comdat ? SOM_SYMBOL_IS_COMDAT : 0);
4513       bfd_putb32 (flags, som_symtab[i].info);
4514       bfd_putb32 (info.symbol_value | info.priv_level,
4515 		  som_symtab[i].symbol_value);
4516     }
4517 
4518   /* Everything is ready, seek to the right location and
4519      scribble out the symbol table.  */
4520   if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
4521     goto error_return;
4522 
4523   symtab_size = num_syms;
4524   symtab_size *= sizeof (struct som_external_symbol_dictionary_record);
4525   if (bfd_bwrite ((void *) som_symtab, symtab_size, abfd) != symtab_size)
4526     goto error_return;
4527 
4528   free (som_symtab);
4529   return TRUE;
4530 
4531  error_return:
4532   free (som_symtab);
4533   return FALSE;
4534 }
4535 
4536 /* Write an object in SOM format.  */
4537 
4538 static bfd_boolean
4539 som_write_object_contents (bfd *abfd)
4540 {
4541   if (! abfd->output_has_begun)
4542     {
4543       /* Set up fixed parts of the file, space, and subspace headers.
4544 	 Notify the world that output has begun.  */
4545       som_prep_headers (abfd);
4546       abfd->output_has_begun = TRUE;
4547       /* Start writing the object file.  This include all the string
4548 	 tables, fixup streams, and other portions of the object file.  */
4549       som_begin_writing (abfd);
4550     }
4551 
4552   return som_finish_writing (abfd);
4553 }
4554 
4555 /* Read and save the string table associated with the given BFD.  */
4556 
4557 static bfd_boolean
4558 som_slurp_string_table (bfd *abfd)
4559 {
4560   char *stringtab;
4561   bfd_size_type amt;
4562 
4563   /* Use the saved version if its available.  */
4564   if (obj_som_stringtab (abfd) != NULL)
4565     return TRUE;
4566 
4567   /* I don't think this can currently happen, and I'm not sure it should
4568      really be an error, but it's better than getting unpredictable results
4569      from the host's malloc when passed a size of zero.  */
4570   if (obj_som_stringtab_size (abfd) == 0)
4571     {
4572       bfd_set_error (bfd_error_no_symbols);
4573       return FALSE;
4574     }
4575 
4576   /* Allocate and read in the string table.  */
4577   if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) != 0)
4578     return FALSE;
4579   amt = obj_som_stringtab_size (abfd);
4580   stringtab = (char *) _bfd_malloc_and_read (abfd, amt, amt);
4581   if (stringtab == NULL)
4582     return FALSE;
4583 
4584   /* Save our results and return success.  */
4585   obj_som_stringtab (abfd) = stringtab;
4586   return TRUE;
4587 }
4588 
4589 /* Return the amount of data (in bytes) required to hold the symbol
4590    table for this object.  */
4591 
4592 static long
4593 som_get_symtab_upper_bound (bfd *abfd)
4594 {
4595   if (!som_slurp_symbol_table (abfd))
4596     return -1;
4597 
4598   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
4599 }
4600 
4601 /* Convert from a SOM subspace index to a BFD section.  */
4602 
4603 asection *
4604 bfd_section_from_som_symbol
4605   (bfd *abfd, struct som_external_symbol_dictionary_record *symbol)
4606 {
4607   asection *section;
4608   unsigned int flags = bfd_getb32 (symbol->flags);
4609   unsigned int symbol_type = (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
4610 
4611   /* The meaning of the symbol_info field changes for functions
4612      within executables.  So only use the quick symbol_info mapping for
4613      incomplete objects and non-function symbols in executables.  */
4614   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
4615       || (symbol_type != ST_ENTRY
4616 	  && symbol_type != ST_PRI_PROG
4617 	  && symbol_type != ST_SEC_PROG
4618 	  && symbol_type != ST_MILLICODE))
4619     {
4620       int idx = (bfd_getb32 (symbol->info) >> SOM_SYMBOL_SYMBOL_INFO_SH)
4621 	& SOM_SYMBOL_SYMBOL_INFO_MASK;
4622 
4623       for (section = abfd->sections; section != NULL; section = section->next)
4624 	if (section->target_index == idx && som_is_subspace (section))
4625 	  return section;
4626     }
4627   else
4628     {
4629       unsigned int value = bfd_getb32 (symbol->symbol_value);
4630 
4631       /* For executables we will have to use the symbol's address and
4632 	 find out what section would contain that address.   Yuk.  */
4633       for (section = abfd->sections; section; section = section->next)
4634 	if (value >= section->vma
4635 	    && value <= section->vma + section->size
4636 	    && som_is_subspace (section))
4637 	  return section;
4638     }
4639 
4640   /* Could be a symbol from an external library (such as an OMOS
4641      shared library).  Don't abort.  */
4642   return bfd_abs_section_ptr;
4643 }
4644 
4645 /* Read and save the symbol table associated with the given BFD.  */
4646 
4647 static unsigned int
4648 som_slurp_symbol_table (bfd *abfd)
4649 {
4650   unsigned int symbol_count = bfd_get_symcount (abfd);
4651   size_t symsize = sizeof (struct som_external_symbol_dictionary_record);
4652   char *stringtab;
4653   struct som_external_symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
4654   som_symbol_type *sym, *symbase = NULL;
4655   size_t amt;
4656 
4657   /* Return saved value if it exists.  */
4658   if (obj_som_symtab (abfd) != NULL)
4659     goto successful_return;
4660 
4661   /* Special case.  This is *not* an error.  */
4662   if (symbol_count == 0)
4663     goto successful_return;
4664 
4665   if (!som_slurp_string_table (abfd))
4666     goto error_return;
4667 
4668   stringtab = obj_som_stringtab (abfd);
4669 
4670   /* Read in the external SOM representation.  */
4671   if (_bfd_mul_overflow (symbol_count, symsize, &amt))
4672     {
4673       bfd_set_error (bfd_error_file_too_big);
4674       goto error_return;
4675     }
4676   if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) != 0)
4677     goto error_return;
4678   buf = (struct som_external_symbol_dictionary_record *)
4679     _bfd_malloc_and_read (abfd, amt, amt);
4680   if (buf == NULL)
4681     goto error_return;
4682 
4683   if (_bfd_mul_overflow (symbol_count, sizeof (som_symbol_type), &amt))
4684     {
4685       bfd_set_error (bfd_error_file_too_big);
4686       goto error_return;
4687     }
4688   symbase = bfd_zmalloc (amt);
4689   if (symbase == NULL)
4690     goto error_return;
4691 
4692   /* Iterate over all the symbols and internalize them.  */
4693   endbufp = buf + symbol_count;
4694   for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
4695     {
4696       unsigned int flags = bfd_getb32 (bufp->flags);
4697       unsigned int symbol_type =
4698 	(flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
4699       unsigned int symbol_scope =
4700 	(flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK;
4701 
4702       /* I don't think we care about these.  */
4703       if (symbol_type == ST_SYM_EXT || symbol_type == ST_ARG_EXT)
4704 	continue;
4705 
4706       /* Set some private data we care about.  */
4707       if (symbol_type == ST_NULL)
4708 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
4709       else if (symbol_type == ST_ABSOLUTE)
4710 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
4711       else if (symbol_type == ST_DATA)
4712 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
4713       else if (symbol_type == ST_CODE)
4714 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
4715       else if (symbol_type == ST_PRI_PROG)
4716 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
4717       else if (symbol_type == ST_SEC_PROG)
4718 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
4719       else if (symbol_type == ST_ENTRY)
4720 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
4721       else if (symbol_type == ST_MILLICODE)
4722 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
4723       else if (symbol_type == ST_PLABEL)
4724 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
4725       else
4726 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
4727       som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc =
4728 	(flags >> SOM_SYMBOL_ARG_RELOC_SH) & SOM_SYMBOL_ARG_RELOC_MASK;
4729 
4730       /* Some reasonable defaults.  */
4731       sym->symbol.the_bfd = abfd;
4732       sym->symbol.name = bfd_getb32 (bufp->name) + stringtab;
4733       sym->symbol.value = bfd_getb32 (bufp->symbol_value);
4734       sym->symbol.section = 0;
4735       sym->symbol.flags = 0;
4736 
4737       switch (symbol_type)
4738 	{
4739 	case ST_ENTRY:
4740 	case ST_MILLICODE:
4741 	  sym->symbol.flags |= BSF_FUNCTION;
4742 	  som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
4743 	    sym->symbol.value & 0x3;
4744 	  sym->symbol.value &= ~0x3;
4745 	  break;
4746 
4747 	case ST_STUB:
4748 	case ST_CODE:
4749 	case ST_PRI_PROG:
4750 	case ST_SEC_PROG:
4751 	  som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
4752 	    sym->symbol.value & 0x3;
4753 	  sym->symbol.value &= ~0x3;
4754 	  /* If the symbol's scope is SS_UNSAT, then these are
4755 	     undefined function symbols.  */
4756 	  if (symbol_scope == SS_UNSAT)
4757 	    sym->symbol.flags |= BSF_FUNCTION;
4758 
4759 	default:
4760 	  break;
4761 	}
4762 
4763       /* Handle scoping and section information.  */
4764       switch (symbol_scope)
4765 	{
4766 	/* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
4767 	   so the section associated with this symbol can't be known.  */
4768 	case SS_EXTERNAL:
4769 	  if (symbol_type != ST_STORAGE)
4770 	    sym->symbol.section = bfd_und_section_ptr;
4771 	  else
4772 	    sym->symbol.section = bfd_com_section_ptr;
4773 	  sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
4774 	  break;
4775 
4776 	case SS_UNSAT:
4777 	  if (symbol_type != ST_STORAGE)
4778 	    sym->symbol.section = bfd_und_section_ptr;
4779 	  else
4780 	    sym->symbol.section = bfd_com_section_ptr;
4781 	  break;
4782 
4783 	case SS_UNIVERSAL:
4784 	  sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
4785 	  sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
4786 	  sym->symbol.value -= sym->symbol.section->vma;
4787 	  break;
4788 
4789 	case SS_LOCAL:
4790 	  sym->symbol.flags |= BSF_LOCAL;
4791 	  sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
4792 	  sym->symbol.value -= sym->symbol.section->vma;
4793 	  break;
4794 	}
4795 
4796       /* Check for a weak symbol.  */
4797       if (flags & SOM_SYMBOL_SECONDARY_DEF)
4798 	sym->symbol.flags |= BSF_WEAK;
4799 
4800       /* Mark section symbols and symbols used by the debugger.
4801 	 Note $START$ is a magic code symbol, NOT a section symbol.  */
4802       if (sym->symbol.name[0] == '$'
4803 	  && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$'
4804 	  && !strcmp (sym->symbol.name, sym->symbol.section->name))
4805 	sym->symbol.flags |= BSF_SECTION_SYM;
4806       else if (CONST_STRNEQ (sym->symbol.name, "L$0\002"))
4807 	{
4808 	  sym->symbol.flags |= BSF_SECTION_SYM;
4809 	  sym->symbol.name = sym->symbol.section->name;
4810 	}
4811       else if (CONST_STRNEQ (sym->symbol.name, "L$0\001"))
4812 	sym->symbol.flags |= BSF_DEBUGGING;
4813 
4814       /* Note increment at bottom of loop, since we skip some symbols
4815 	 we can not include it as part of the for statement.  */
4816       sym++;
4817     }
4818 
4819   /* We modify the symbol count to record the number of BFD symbols we
4820      created.  */
4821   abfd->symcount = sym - symbase;
4822 
4823   /* Save our results and return success.  */
4824   obj_som_symtab (abfd) = symbase;
4825  successful_return:
4826   free (buf);
4827   return (TRUE);
4828 
4829  error_return:
4830   free (symbase);
4831   free (buf);
4832   return FALSE;
4833 }
4834 
4835 /* Canonicalize a SOM symbol table.  Return the number of entries
4836    in the symbol table.  */
4837 
4838 static long
4839 som_canonicalize_symtab (bfd *abfd, asymbol **location)
4840 {
4841   int i;
4842   som_symbol_type *symbase;
4843 
4844   if (!som_slurp_symbol_table (abfd))
4845     return -1;
4846 
4847   i = bfd_get_symcount (abfd);
4848   symbase = obj_som_symtab (abfd);
4849 
4850   for (; i > 0; i--, location++, symbase++)
4851     *location = &symbase->symbol;
4852 
4853   /* Final null pointer.  */
4854   *location = 0;
4855   return (bfd_get_symcount (abfd));
4856 }
4857 
4858 /* Make a SOM symbol.  There is nothing special to do here.  */
4859 
4860 static asymbol *
4861 som_make_empty_symbol (bfd *abfd)
4862 {
4863   size_t amt = sizeof (som_symbol_type);
4864   som_symbol_type *new_symbol_type = bfd_zalloc (abfd, amt);
4865 
4866   if (new_symbol_type == NULL)
4867     return NULL;
4868   new_symbol_type->symbol.the_bfd = abfd;
4869 
4870   return &new_symbol_type->symbol;
4871 }
4872 
4873 /* Print symbol information.  */
4874 
4875 static void
4876 som_print_symbol (bfd *abfd,
4877 		  void *afile,
4878 		  asymbol *symbol,
4879 		  bfd_print_symbol_type how)
4880 {
4881   FILE *file = (FILE *) afile;
4882 
4883   switch (how)
4884     {
4885     case bfd_print_symbol_name:
4886       fprintf (file, "%s", symbol->name);
4887       break;
4888     case bfd_print_symbol_more:
4889       fprintf (file, "som ");
4890       fprintf_vma (file, symbol->value);
4891       fprintf (file, " %lx", (long) symbol->flags);
4892       break;
4893     case bfd_print_symbol_all:
4894       {
4895 	const char *section_name;
4896 
4897 	section_name = symbol->section ? symbol->section->name : "(*none*)";
4898 	bfd_print_symbol_vandf (abfd, (void *) file, symbol);
4899 	fprintf (file, " %s\t%s", section_name, symbol->name);
4900 	break;
4901       }
4902     }
4903 }
4904 
4905 static bfd_boolean
4906 som_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
4907 			     const char *name)
4908 {
4909   return name[0] == 'L' && name[1] == '$';
4910 }
4911 
4912 /* Count or process variable-length SOM fixup records.
4913 
4914    To avoid code duplication we use this code both to compute the number
4915    of relocations requested by a stream, and to internalize the stream.
4916 
4917    When computing the number of relocations requested by a stream the
4918    variables rptr, section, and symbols have no meaning.
4919 
4920    Return the number of relocations requested by the fixup stream.  When
4921    not just counting
4922 
4923    This needs at least two or three more passes to get it cleaned up.  */
4924 
4925 static unsigned int
4926 som_set_reloc_info (unsigned char *fixup,
4927 		    unsigned int end,
4928 		    arelent *internal_relocs,
4929 		    asection *section,
4930 		    asymbol **symbols,
4931 		    bfd_boolean just_count)
4932 {
4933   unsigned int op, varname, deallocate_contents = 0;
4934   unsigned char *end_fixups = &fixup[end];
4935   const struct fixup_format *fp;
4936   const char *cp;
4937   unsigned char *save_fixup;
4938   int variables[26], stack[20], c, v, count, prev_fixup, *sp, saved_unwind_bits;
4939   const int *subop;
4940   arelent *rptr = internal_relocs;
4941   unsigned int offset = 0;
4942 
4943 #define	var(c)		variables[(c) - 'A']
4944 #define	push(v)		(*sp++ = (v))
4945 #define	pop()		(*--sp)
4946 #define	emptystack()	(sp == stack)
4947 
4948   som_initialize_reloc_queue (reloc_queue);
4949   memset (variables, 0, sizeof (variables));
4950   memset (stack, 0, sizeof (stack));
4951   count = 0;
4952   prev_fixup = 0;
4953   saved_unwind_bits = 0;
4954   sp = stack;
4955 
4956   while (fixup < end_fixups)
4957     {
4958       /* Save pointer to the start of this fixup.  We'll use
4959 	 it later to determine if it is necessary to put this fixup
4960 	 on the queue.  */
4961       save_fixup = fixup;
4962 
4963       /* Get the fixup code and its associated format.  */
4964       op = *fixup++;
4965       fp = &som_fixup_formats[op];
4966 
4967       /* Handle a request for a previous fixup.  */
4968       if (*fp->format == 'P')
4969 	{
4970 	  /* Get pointer to the beginning of the prev fixup, move
4971 	     the repeated fixup to the head of the queue.  */
4972 	  fixup = reloc_queue[fp->D].reloc;
4973 	  som_reloc_queue_fix (reloc_queue, fp->D);
4974 	  prev_fixup = 1;
4975 
4976 	  /* Get the fixup code and its associated format.  */
4977 	  op = *fixup++;
4978 	  fp = &som_fixup_formats[op];
4979 	}
4980 
4981       /* If this fixup will be passed to BFD, set some reasonable defaults.  */
4982       if (! just_count
4983 	  && som_hppa_howto_table[op].type != R_NO_RELOCATION
4984 	  && som_hppa_howto_table[op].type != R_DATA_OVERRIDE)
4985 	{
4986 	  rptr->address = offset;
4987 	  rptr->howto = &som_hppa_howto_table[op];
4988 	  rptr->addend = 0;
4989 	  rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
4990 	}
4991 
4992       /* Set default input length to 0.  Get the opcode class index
4993 	 into D.  */
4994       var ('L') = 0;
4995       var ('D') = fp->D;
4996       var ('U') = saved_unwind_bits;
4997 
4998       /* Get the opcode format.  */
4999       cp = fp->format;
5000 
5001       /* Process the format string.  Parsing happens in two phases,
5002 	 parse RHS, then assign to LHS.  Repeat until no more
5003 	 characters in the format string.  */
5004       while (*cp)
5005 	{
5006 	  /* The variable this pass is going to compute a value for.  */
5007 	  varname = *cp++;
5008 
5009 	  /* Start processing RHS.  Continue until a NULL or '=' is found.  */
5010 	  do
5011 	    {
5012 	      c = *cp++;
5013 
5014 	      /* If this is a variable, push it on the stack.  */
5015 	      if (ISUPPER (c))
5016 		push (var (c));
5017 
5018 	      /* If this is a lower case letter, then it represents
5019 		 additional data from the fixup stream to be pushed onto
5020 		 the stack.  */
5021 	      else if (ISLOWER (c))
5022 		{
5023 		  int bits = (c - 'a') * 8;
5024 		  for (v = 0; c > 'a'; --c)
5025 		    v = (v << 8) | *fixup++;
5026 		  if (varname == 'V')
5027 		    v = sign_extend (v, bits);
5028 		  push (v);
5029 		}
5030 
5031 	      /* A decimal constant.  Push it on the stack.  */
5032 	      else if (ISDIGIT (c))
5033 		{
5034 		  v = c - '0';
5035 		  while (ISDIGIT (*cp))
5036 		    v = (v * 10) + (*cp++ - '0');
5037 		  push (v);
5038 		}
5039 	      else
5040 		/* An operator.  Pop two values from the stack and
5041 		   use them as operands to the given operation.  Push
5042 		   the result of the operation back on the stack.  */
5043 		switch (c)
5044 		  {
5045 		  case '+':
5046 		    v = pop ();
5047 		    v += pop ();
5048 		    push (v);
5049 		    break;
5050 		  case '*':
5051 		    v = pop ();
5052 		    v *= pop ();
5053 		    push (v);
5054 		    break;
5055 		  case '<':
5056 		    v = pop ();
5057 		    v = pop () << v;
5058 		    push (v);
5059 		    break;
5060 		  default:
5061 		    abort ();
5062 		  }
5063 	    }
5064 	  while (*cp && *cp != '=');
5065 
5066 	  /* Move over the equal operator.  */
5067 	  cp++;
5068 
5069 	  /* Pop the RHS off the stack.  */
5070 	  c = pop ();
5071 
5072 	  /* Perform the assignment.  */
5073 	  var (varname) = c;
5074 
5075 	  /* Handle side effects. and special 'O' stack cases.  */
5076 	  switch (varname)
5077 	    {
5078 	    /* Consume some bytes from the input space.  */
5079 	    case 'L':
5080 	      offset += c;
5081 	      break;
5082 	    /* A symbol to use in the relocation.  Make a note
5083 	       of this if we are not just counting.  */
5084 	    case 'S':
5085 	      if (! just_count)
5086 		rptr->sym_ptr_ptr = &symbols[c];
5087 	      break;
5088 	    /* Argument relocation bits for a function call.  */
5089 	    case 'R':
5090 	      if (! just_count)
5091 		{
5092 		  unsigned int tmp = var ('R');
5093 		  rptr->addend = 0;
5094 
5095 		  if ((som_hppa_howto_table[op].type == R_PCREL_CALL
5096 		       && R_PCREL_CALL + 10 > op)
5097 		      || (som_hppa_howto_table[op].type == R_ABS_CALL
5098 			  && R_ABS_CALL + 10 > op))
5099 		    {
5100 		      /* Simple encoding.  */
5101 		      if (tmp > 4)
5102 			{
5103 			  tmp -= 5;
5104 			  rptr->addend |= 1;
5105 			}
5106 		      if (tmp == 4)
5107 			rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2;
5108 		      else if (tmp == 3)
5109 			rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4;
5110 		      else if (tmp == 2)
5111 			rptr->addend |= 1 << 8 | 1 << 6;
5112 		      else if (tmp == 1)
5113 			rptr->addend |= 1 << 8;
5114 		    }
5115 		  else
5116 		    {
5117 		      unsigned int tmp1, tmp2;
5118 
5119 		      /* First part is easy -- low order two bits are
5120 			 directly copied, then shifted away.  */
5121 		      rptr->addend = tmp & 0x3;
5122 		      tmp >>= 2;
5123 
5124 		      /* Diving the result by 10 gives us the second
5125 			 part.  If it is 9, then the first two words
5126 			 are a double precision paramater, else it is
5127 			 3 * the first arg bits + the 2nd arg bits.  */
5128 		      tmp1 = tmp / 10;
5129 		      tmp -= tmp1 * 10;
5130 		      if (tmp1 == 9)
5131 			rptr->addend += (0xe << 6);
5132 		      else
5133 			{
5134 			  /* Get the two pieces.  */
5135 			  tmp2 = tmp1 / 3;
5136 			  tmp1 -= tmp2 * 3;
5137 			  /* Put them in the addend.  */
5138 			  rptr->addend += (tmp2 << 8) + (tmp1 << 6);
5139 			}
5140 
5141 		      /* What's left is the third part.  It's unpacked
5142 			 just like the second.  */
5143 		      if (tmp == 9)
5144 			rptr->addend += (0xe << 2);
5145 		      else
5146 			{
5147 			  tmp2 = tmp / 3;
5148 			  tmp -= tmp2 * 3;
5149 			  rptr->addend += (tmp2 << 4) + (tmp << 2);
5150 			}
5151 		    }
5152 		  rptr->addend = HPPA_R_ADDEND (rptr->addend, 0);
5153 		}
5154 	      break;
5155 	    /* Handle the linker expression stack.  */
5156 	    case 'O':
5157 	      switch (op)
5158 		{
5159 		case R_COMP1:
5160 		  subop = comp1_opcodes;
5161 		  break;
5162 		case R_COMP2:
5163 		  subop = comp2_opcodes;
5164 		  break;
5165 		case R_COMP3:
5166 		  subop = comp3_opcodes;
5167 		  break;
5168 		default:
5169 		  abort ();
5170 		}
5171 	      while (*subop <= (unsigned char) c)
5172 		++subop;
5173 	      --subop;
5174 	      break;
5175 	    /* The lower 32unwind bits must be persistent.  */
5176 	    case 'U':
5177 	      saved_unwind_bits = var ('U');
5178 	      break;
5179 
5180 	    default:
5181 	      break;
5182 	    }
5183 	}
5184 
5185       /* If we used a previous fixup, clean up after it.  */
5186       if (prev_fixup)
5187 	{
5188 	  fixup = save_fixup + 1;
5189 	  prev_fixup = 0;
5190 	}
5191       /* Queue it.  */
5192       else if (fixup > save_fixup + 1)
5193 	som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
5194 
5195       /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION
5196 	 fixups to BFD.  */
5197       if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
5198 	  && som_hppa_howto_table[op].type != R_NO_RELOCATION)
5199 	{
5200 	  /* Done with a single reloction. Loop back to the top.  */
5201 	  if (! just_count)
5202 	    {
5203 	      if (som_hppa_howto_table[op].type == R_ENTRY)
5204 		rptr->addend = var ('T');
5205 	      else if (som_hppa_howto_table[op].type == R_EXIT)
5206 		rptr->addend = var ('U');
5207 	      else if (som_hppa_howto_table[op].type == R_PCREL_CALL
5208 		       || som_hppa_howto_table[op].type == R_ABS_CALL)
5209 		;
5210 	      else if (som_hppa_howto_table[op].type == R_DATA_ONE_SYMBOL)
5211 		{
5212 		  /* Try what was specified in R_DATA_OVERRIDE first
5213 		     (if anything).  Then the hard way using the
5214 		     section contents.  */
5215 		  rptr->addend = var ('V');
5216 
5217 		  if (rptr->addend == 0 && !section->contents)
5218 		    {
5219 		      /* Got to read the damn contents first.  We don't
5220 			 bother saving the contents (yet).  Add it one
5221 			 day if the need arises.  */
5222 		      bfd_byte *contents;
5223 		      if (!bfd_malloc_and_get_section (section->owner, section,
5224 						       &contents))
5225 			{
5226 			  free (contents);
5227 			  return (unsigned) -1;
5228 			}
5229 		      section->contents = contents;
5230 		      deallocate_contents = 1;
5231 		    }
5232 		  else if (rptr->addend == 0)
5233 		    rptr->addend = bfd_get_32 (section->owner,
5234 					       (section->contents
5235 						+ offset - var ('L')));
5236 
5237 		}
5238 	      else
5239 		rptr->addend = var ('V');
5240 	      rptr++;
5241 	    }
5242 	  count++;
5243 	  /* Now that we've handled a "full" relocation, reset
5244 	     some state.  */
5245 	  memset (variables, 0, sizeof (variables));
5246 	  memset (stack, 0, sizeof (stack));
5247 	}
5248     }
5249   if (deallocate_contents)
5250     free (section->contents);
5251 
5252   return count;
5253 
5254 #undef var
5255 #undef push
5256 #undef pop
5257 #undef emptystack
5258 }
5259 
5260 /* Read in the relocs (aka fixups in SOM terms) for a section.
5261 
5262    som_get_reloc_upper_bound calls this routine with JUST_COUNT
5263    set to TRUE to indicate it only needs a count of the number
5264    of actual relocations.  */
5265 
5266 static bfd_boolean
5267 som_slurp_reloc_table (bfd *abfd,
5268 		       asection *section,
5269 		       asymbol **symbols,
5270 		       bfd_boolean just_count)
5271 {
5272   unsigned char *external_relocs;
5273   unsigned int fixup_stream_size;
5274   arelent *internal_relocs;
5275   unsigned int num_relocs;
5276   size_t amt;
5277 
5278   fixup_stream_size = som_section_data (section)->reloc_size;
5279   /* If there were no relocations, then there is nothing to do.  */
5280   if (section->reloc_count == 0)
5281     return TRUE;
5282 
5283   /* If reloc_count is -1, then the relocation stream has not been
5284      parsed.  We must do so now to know how many relocations exist.  */
5285   if (section->reloc_count == (unsigned) -1)
5286     {
5287       /* Read in the external forms.  */
5288       if (bfd_seek (abfd, obj_som_reloc_filepos (abfd) + section->rel_filepos,
5289 		    SEEK_SET) != 0)
5290 	return FALSE;
5291       amt = fixup_stream_size;
5292       external_relocs = _bfd_malloc_and_read (abfd, amt, amt);
5293       if (external_relocs == NULL)
5294 	return FALSE;
5295 
5296       /* Let callers know how many relocations found.
5297 	 also save the relocation stream as we will
5298 	 need it again.  */
5299       section->reloc_count = som_set_reloc_info (external_relocs,
5300 						 fixup_stream_size,
5301 						 NULL, NULL, NULL, TRUE);
5302 
5303       som_section_data (section)->reloc_stream = external_relocs;
5304     }
5305 
5306   /* If the caller only wanted a count, then return now.  */
5307   if (just_count)
5308     return TRUE;
5309 
5310   num_relocs = section->reloc_count;
5311   external_relocs = som_section_data (section)->reloc_stream;
5312   /* Return saved information about the relocations if it is available.  */
5313   if (section->relocation != NULL)
5314     return TRUE;
5315 
5316   if (_bfd_mul_overflow (num_relocs, sizeof (arelent), &amt))
5317     {
5318       bfd_set_error (bfd_error_file_too_big);
5319       return FALSE;
5320     }
5321   internal_relocs = bfd_zalloc (abfd, amt);
5322   if (internal_relocs == NULL)
5323     return FALSE;
5324 
5325   /* Process and internalize the relocations.  */
5326   som_set_reloc_info (external_relocs, fixup_stream_size,
5327 		      internal_relocs, section, symbols, FALSE);
5328 
5329   /* We're done with the external relocations.  Free them.  */
5330   free (external_relocs);
5331   som_section_data (section)->reloc_stream = NULL;
5332 
5333   /* Save our results and return success.  */
5334   section->relocation = internal_relocs;
5335   return TRUE;
5336 }
5337 
5338 /* Return the number of bytes required to store the relocation
5339    information associated with the given section.  */
5340 
5341 static long
5342 som_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
5343 {
5344   /* If section has relocations, then read in the relocation stream
5345      and parse it to determine how many relocations exist.  */
5346   if (asect->flags & SEC_RELOC)
5347     {
5348       if (! som_slurp_reloc_table (abfd, asect, NULL, TRUE))
5349 	return -1;
5350       return (asect->reloc_count + 1) * sizeof (arelent *);
5351     }
5352 
5353   /* There are no relocations.  Return enough space to hold the
5354      NULL pointer which will be installed if som_canonicalize_reloc
5355      is called.  */
5356   return sizeof (arelent *);
5357 }
5358 
5359 /* Convert relocations from SOM (external) form into BFD internal
5360    form.  Return the number of relocations.  */
5361 
5362 static long
5363 som_canonicalize_reloc (bfd *abfd,
5364 			sec_ptr section,
5365 			arelent **relptr,
5366 			asymbol **symbols)
5367 {
5368   arelent *tblptr;
5369   int count;
5370 
5371   if (! som_slurp_reloc_table (abfd, section, symbols, FALSE))
5372     return -1;
5373 
5374   count = section->reloc_count;
5375   tblptr = section->relocation;
5376 
5377   while (count--)
5378     *relptr++ = tblptr++;
5379 
5380   *relptr = NULL;
5381   return section->reloc_count;
5382 }
5383 
5384 extern const bfd_target hppa_som_vec;
5385 
5386 /* A hook to set up object file dependent section information.  */
5387 
5388 static bfd_boolean
5389 som_new_section_hook (bfd *abfd, asection *newsect)
5390 {
5391   if (!newsect->used_by_bfd)
5392     {
5393       size_t amt = sizeof (struct som_section_data_struct);
5394 
5395       newsect->used_by_bfd = bfd_zalloc (abfd, amt);
5396       if (!newsect->used_by_bfd)
5397 	return FALSE;
5398     }
5399   newsect->alignment_power = 3;
5400 
5401   /* We allow more than three sections internally.  */
5402   return _bfd_generic_new_section_hook (abfd, newsect);
5403 }
5404 
5405 /* Copy any private info we understand from the input symbol
5406    to the output symbol.  */
5407 
5408 static bfd_boolean
5409 som_bfd_copy_private_symbol_data (bfd *ibfd,
5410 				  asymbol *isymbol,
5411 				  bfd *obfd,
5412 				  asymbol *osymbol)
5413 {
5414   struct som_symbol *input_symbol = (struct som_symbol *) isymbol;
5415   struct som_symbol *output_symbol = (struct som_symbol *) osymbol;
5416 
5417   /* One day we may try to grok other private data.  */
5418   if (ibfd->xvec->flavour != bfd_target_som_flavour
5419       || obfd->xvec->flavour != bfd_target_som_flavour)
5420     return FALSE;
5421 
5422   /* The only private information we need to copy is the argument relocation
5423      bits.  */
5424   output_symbol->tc_data.ap.hppa_arg_reloc =
5425     input_symbol->tc_data.ap.hppa_arg_reloc;
5426 
5427   return TRUE;
5428 }
5429 
5430 /* Copy any private info we understand from the input section
5431    to the output section.  */
5432 
5433 static bfd_boolean
5434 som_bfd_copy_private_section_data (bfd *ibfd,
5435 				   asection *isection,
5436 				   bfd *obfd,
5437 				   asection *osection)
5438 {
5439   size_t amt;
5440 
5441   /* One day we may try to grok other private data.  */
5442   if (ibfd->xvec->flavour != bfd_target_som_flavour
5443       || obfd->xvec->flavour != bfd_target_som_flavour
5444       || (!som_is_space (isection) && !som_is_subspace (isection)))
5445     return TRUE;
5446 
5447   amt = sizeof (struct som_copyable_section_data_struct);
5448   som_section_data (osection)->copy_data = bfd_zalloc (obfd, amt);
5449   if (som_section_data (osection)->copy_data == NULL)
5450     return FALSE;
5451 
5452   memcpy (som_section_data (osection)->copy_data,
5453 	  som_section_data (isection)->copy_data,
5454 	  sizeof (struct som_copyable_section_data_struct));
5455 
5456   /* Reparent if necessary.  */
5457   if (som_section_data (osection)->copy_data->container)
5458     {
5459       if (som_section_data (osection)->copy_data->container->output_section)
5460 	som_section_data (osection)->copy_data->container =
5461 	  som_section_data (osection)->copy_data->container->output_section;
5462       else
5463 	{
5464 	  /* User has specified a subspace without its containing space.  */
5465 	  _bfd_error_handler (_("%pB[%pA]: no output section for space %pA"),
5466 	    obfd, osection, som_section_data (osection)->copy_data->container);
5467 	  return FALSE;
5468 	}
5469     }
5470 
5471   return TRUE;
5472 }
5473 
5474 /* Copy any private info we understand from the input bfd
5475    to the output bfd.  */
5476 
5477 static bfd_boolean
5478 som_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
5479 {
5480   /* One day we may try to grok other private data.  */
5481   if (ibfd->xvec->flavour != bfd_target_som_flavour
5482       || obfd->xvec->flavour != bfd_target_som_flavour)
5483     return TRUE;
5484 
5485   /* Allocate some memory to hold the data we need.  */
5486   obj_som_exec_data (obfd) = bfd_zalloc (obfd, (bfd_size_type) sizeof (struct som_exec_data));
5487   if (obj_som_exec_data (obfd) == NULL)
5488     return FALSE;
5489 
5490   /* Now copy the data.  */
5491   memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
5492 	  sizeof (struct som_exec_data));
5493 
5494   return TRUE;
5495 }
5496 
5497 /* Display the SOM header.  */
5498 
5499 static bfd_boolean
5500 som_bfd_print_private_bfd_data (bfd *abfd, void *farg)
5501 {
5502   struct som_exec_auxhdr *exec_header;
5503   struct som_aux_id* auxhdr;
5504   FILE *f;
5505 
5506   f = (FILE *) farg;
5507 
5508   exec_header = obj_som_exec_hdr (abfd);
5509   if (exec_header)
5510     {
5511       fprintf (f, _("\nExec Auxiliary Header\n"));
5512       fprintf (f, "  flags              ");
5513       auxhdr = &exec_header->som_auxhdr;
5514       if (auxhdr->mandatory)
5515 	fprintf (f, "mandatory ");
5516       if (auxhdr->copy)
5517 	fprintf (f, "copy ");
5518       if (auxhdr->append)
5519 	fprintf (f, "append ");
5520       if (auxhdr->ignore)
5521 	fprintf (f, "ignore ");
5522       fprintf (f, "\n");
5523       fprintf (f, "  type               %#x\n", auxhdr->type);
5524       fprintf (f, "  length             %#x\n", auxhdr->length);
5525 
5526       /* Note that, depending on the HP-UX version, the following fields can be
5527 	 either ints, or longs.  */
5528 
5529       fprintf (f, "  text size          %#lx\n", (long) exec_header->exec_tsize);
5530       fprintf (f, "  text memory offset %#lx\n", (long) exec_header->exec_tmem);
5531       fprintf (f, "  text file offset   %#lx\n", (long) exec_header->exec_tfile);
5532       fprintf (f, "  data size          %#lx\n", (long) exec_header->exec_dsize);
5533       fprintf (f, "  data memory offset %#lx\n", (long) exec_header->exec_dmem);
5534       fprintf (f, "  data file offset   %#lx\n", (long) exec_header->exec_dfile);
5535       fprintf (f, "  bss size           %#lx\n", (long) exec_header->exec_bsize);
5536       fprintf (f, "  entry point        %#lx\n", (long) exec_header->exec_entry);
5537       fprintf (f, "  loader flags       %#lx\n", (long) exec_header->exec_flags);
5538       fprintf (f, "  bss initializer    %#lx\n", (long) exec_header->exec_bfill);
5539     }
5540 
5541   return TRUE;
5542 }
5543 
5544 /* Set backend info for sections which can not be described
5545    in the BFD data structures.  */
5546 
5547 bfd_boolean
5548 bfd_som_set_section_attributes (asection *section,
5549 				int defined,
5550 				int private,
5551 				unsigned int sort_key,
5552 				int spnum)
5553 {
5554   /* Allocate memory to hold the magic information.  */
5555   if (som_section_data (section)->copy_data == NULL)
5556     {
5557       size_t amt = sizeof (struct som_copyable_section_data_struct);
5558 
5559       som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
5560       if (som_section_data (section)->copy_data == NULL)
5561 	return FALSE;
5562     }
5563   som_section_data (section)->copy_data->sort_key = sort_key;
5564   som_section_data (section)->copy_data->is_defined = defined;
5565   som_section_data (section)->copy_data->is_private = private;
5566   som_section_data (section)->copy_data->container = section;
5567   som_section_data (section)->copy_data->space_number = spnum;
5568   return TRUE;
5569 }
5570 
5571 /* Set backend info for subsections which can not be described
5572    in the BFD data structures.  */
5573 
5574 bfd_boolean
5575 bfd_som_set_subsection_attributes (asection *section,
5576 				   asection *container,
5577 				   int access_ctr,
5578 				   unsigned int sort_key,
5579 				   int quadrant,
5580 				   int comdat,
5581 				   int common,
5582 				   int dup_common)
5583 {
5584   /* Allocate memory to hold the magic information.  */
5585   if (som_section_data (section)->copy_data == NULL)
5586     {
5587       size_t amt = sizeof (struct som_copyable_section_data_struct);
5588 
5589       som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
5590       if (som_section_data (section)->copy_data == NULL)
5591 	return FALSE;
5592     }
5593   som_section_data (section)->copy_data->sort_key = sort_key;
5594   som_section_data (section)->copy_data->access_control_bits = access_ctr;
5595   som_section_data (section)->copy_data->quadrant = quadrant;
5596   som_section_data (section)->copy_data->container = container;
5597   som_section_data (section)->copy_data->is_comdat = comdat;
5598   som_section_data (section)->copy_data->is_common = common;
5599   som_section_data (section)->copy_data->dup_common = dup_common;
5600   return TRUE;
5601 }
5602 
5603 /* Set the full SOM symbol type.  SOM needs far more symbol information
5604    than any other object file format I'm aware of.  It is mandatory
5605    to be able to know if a symbol is an entry point, millicode, data,
5606    code, absolute, storage request, or procedure label.  If you get
5607    the symbol type wrong your program will not link.  */
5608 
5609 void
5610 bfd_som_set_symbol_type (asymbol *symbol, unsigned int type)
5611 {
5612   som_symbol_data (symbol)->som_type = type;
5613 }
5614 
5615 /* Attach an auxiliary header to the BFD backend so that it may be
5616    written into the object file.  */
5617 
5618 bfd_boolean
5619 bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string)
5620 {
5621   size_t amt;
5622 
5623   if (type == VERSION_AUX_ID)
5624     {
5625       size_t len = strlen (string);
5626       int pad = 0;
5627 
5628       if (len % 4)
5629 	pad = (4 - (len % 4));
5630       amt = sizeof (struct som_string_auxhdr) + len + pad;
5631       obj_som_version_hdr (abfd) = bfd_zalloc (abfd, amt);
5632       if (!obj_som_version_hdr (abfd))
5633 	return FALSE;
5634       obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
5635       obj_som_version_hdr (abfd)->header_id.length = 4 + len + pad;
5636       obj_som_version_hdr (abfd)->string_length = len;
5637       memcpy (obj_som_version_hdr (abfd)->string, string, len);
5638       memset (obj_som_version_hdr (abfd)->string + len, 0, pad);
5639     }
5640   else if (type == COPYRIGHT_AUX_ID)
5641     {
5642       size_t len = strlen (string);
5643       int pad = 0;
5644 
5645       if (len % 4)
5646 	pad = (4 - (len % 4));
5647       amt = sizeof (struct som_string_auxhdr) + len + pad;
5648       obj_som_copyright_hdr (abfd) = bfd_zalloc (abfd, amt);
5649       if (!obj_som_copyright_hdr (abfd))
5650 	return FALSE;
5651       obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
5652       obj_som_copyright_hdr (abfd)->header_id.length = len + pad + 4;
5653       obj_som_copyright_hdr (abfd)->string_length = len;
5654       memcpy (obj_som_copyright_hdr (abfd)->string, string, len);
5655       memset (obj_som_copyright_hdr (abfd)->string + len, 0, pad);
5656     }
5657   return TRUE;
5658 }
5659 
5660 /* Attach a compilation unit header to the BFD backend so that it may be
5661    written into the object file.  */
5662 
5663 bfd_boolean
5664 bfd_som_attach_compilation_unit (bfd *abfd,
5665 				 const char *name,
5666 				 const char *language_name,
5667 				 const char *product_id,
5668 				 const char *version_id)
5669 {
5670   struct som_compilation_unit *n;
5671 
5672   n = (struct som_compilation_unit *) bfd_zalloc
5673     (abfd, (bfd_size_type) sizeof (*n));
5674   if (n == NULL)
5675     return FALSE;
5676 
5677 #define STRDUP(f) \
5678   if (f != NULL) \
5679     { \
5680       n->f.name = bfd_alloc (abfd, (bfd_size_type) strlen (f) + 1); \
5681       if (n->f.name == NULL) \
5682 	return FALSE; \
5683       strcpy (n->f.name, f); \
5684     }
5685 
5686   STRDUP (name);
5687   STRDUP (language_name);
5688   STRDUP (product_id);
5689   STRDUP (version_id);
5690 
5691 #undef STRDUP
5692 
5693   obj_som_compilation_unit (abfd) = n;
5694 
5695   return TRUE;
5696 }
5697 
5698 static bfd_boolean
5699 som_get_section_contents (bfd *abfd,
5700 			  sec_ptr section,
5701 			  void *location,
5702 			  file_ptr offset,
5703 			  bfd_size_type count)
5704 {
5705   if (count == 0 || ((section->flags & SEC_HAS_CONTENTS) == 0))
5706     return TRUE;
5707   if ((bfd_size_type) (offset+count) > section->size
5708       || bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
5709       || bfd_bread (location, count, abfd) != count)
5710     return FALSE; /* On error.  */
5711   return TRUE;
5712 }
5713 
5714 static bfd_boolean
5715 som_set_section_contents (bfd *abfd,
5716 			  sec_ptr section,
5717 			  const void *location,
5718 			  file_ptr offset,
5719 			  bfd_size_type count)
5720 {
5721   if (! abfd->output_has_begun)
5722     {
5723       /* Set up fixed parts of the file, space, and subspace headers.
5724 	 Notify the world that output has begun.  */
5725       som_prep_headers (abfd);
5726       abfd->output_has_begun = TRUE;
5727       /* Start writing the object file.  This include all the string
5728 	 tables, fixup streams, and other portions of the object file.  */
5729       som_begin_writing (abfd);
5730     }
5731 
5732   /* Only write subspaces which have "real" contents (eg. the contents
5733      are not generated at run time by the OS).  */
5734   if (!som_is_subspace (section)
5735       || ((section->flags & SEC_HAS_CONTENTS) == 0))
5736     return TRUE;
5737 
5738   /* Seek to the proper offset within the object file and write the
5739      data.  */
5740   offset += som_section_data (section)->subspace_dict->file_loc_init_value;
5741   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
5742     return FALSE;
5743 
5744   if (bfd_bwrite (location, count, abfd) != count)
5745     return FALSE;
5746   return TRUE;
5747 }
5748 
5749 static bfd_boolean
5750 som_set_arch_mach (bfd *abfd,
5751 		   enum bfd_architecture arch,
5752 		   unsigned long machine)
5753 {
5754   /* Allow any architecture to be supported by the SOM backend.  */
5755   return bfd_default_set_arch_mach (abfd, arch, machine);
5756 }
5757 
5758 static bfd_boolean
5759 som_find_nearest_line (bfd *abfd,
5760 		       asymbol **symbols,
5761 		       asection *section,
5762 		       bfd_vma offset,
5763 		       const char **filename_ptr,
5764 		       const char **functionname_ptr,
5765 		       unsigned int *line_ptr,
5766 		       unsigned int *discriminator_ptr)
5767 {
5768   bfd_boolean found;
5769   asymbol *func;
5770   bfd_vma low_func;
5771   asymbol **p;
5772 
5773   if (discriminator_ptr)
5774     *discriminator_ptr = 0;
5775 
5776   if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
5777 					     & found, filename_ptr,
5778 					     functionname_ptr, line_ptr,
5779 					     & somdata (abfd).line_info))
5780     return FALSE;
5781 
5782   if (found)
5783     return TRUE;
5784 
5785   if (symbols == NULL)
5786     return FALSE;
5787 
5788   /* Fallback: find function name from symbols table.  */
5789   func = NULL;
5790   low_func = 0;
5791 
5792   for (p = symbols; *p != NULL; p++)
5793     {
5794       som_symbol_type *q = (som_symbol_type *) *p;
5795 
5796       if (q->som_type == SYMBOL_TYPE_ENTRY
5797 	  && q->symbol.section == section
5798 	  && q->symbol.value >= low_func
5799 	  && q->symbol.value <= offset)
5800 	{
5801 	  func = (asymbol *) q;
5802 	  low_func = q->symbol.value;
5803 	}
5804     }
5805 
5806   if (func == NULL)
5807     return FALSE;
5808 
5809   *filename_ptr = NULL;
5810   *functionname_ptr = bfd_asymbol_name (func);
5811   *line_ptr = 0;
5812 
5813   return TRUE;
5814 }
5815 
5816 static int
5817 som_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
5818 		    struct bfd_link_info *info ATTRIBUTE_UNUSED)
5819 {
5820   _bfd_error_handler (_("som_sizeof_headers unimplemented"));
5821   abort ();
5822   return 0;
5823 }
5824 
5825 /* Return the single-character symbol type corresponding to
5826    SOM section S, or '?' for an unknown SOM section.  */
5827 
5828 static char
5829 som_section_type (const char *s)
5830 {
5831   const struct section_to_type *t;
5832 
5833   for (t = &stt[0]; t->section; t++)
5834     if (!strcmp (s, t->section))
5835       return t->type;
5836   return '?';
5837 }
5838 
5839 static int
5840 som_decode_symclass (asymbol *symbol)
5841 {
5842   char c;
5843 
5844   if (bfd_is_com_section (symbol->section))
5845     return 'C';
5846   if (bfd_is_und_section (symbol->section))
5847     {
5848       if (symbol->flags & BSF_WEAK)
5849 	{
5850 	  /* If weak, determine if it's specifically an object
5851 	     or non-object weak.  */
5852 	  if (symbol->flags & BSF_OBJECT)
5853 	    return 'v';
5854 	  else
5855 	    return 'w';
5856 	}
5857       else
5858 	 return 'U';
5859     }
5860   if (bfd_is_ind_section (symbol->section))
5861     return 'I';
5862   if (symbol->flags & BSF_WEAK)
5863     {
5864       /* If weak, determine if it's specifically an object
5865 	 or non-object weak.  */
5866       if (symbol->flags & BSF_OBJECT)
5867 	return 'V';
5868       else
5869 	return 'W';
5870     }
5871   if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
5872     return '?';
5873 
5874   if (bfd_is_abs_section (symbol->section)
5875       || (som_symbol_data (symbol) != NULL
5876 	  && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE))
5877     c = 'a';
5878   else if (symbol->section)
5879     c = som_section_type (symbol->section->name);
5880   else
5881     return '?';
5882   if (symbol->flags & BSF_GLOBAL)
5883     c = TOUPPER (c);
5884   return c;
5885 }
5886 
5887 /* Return information about SOM symbol SYMBOL in RET.  */
5888 
5889 static void
5890 som_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
5891 		     asymbol *symbol,
5892 		     symbol_info *ret)
5893 {
5894   ret->type = som_decode_symclass (symbol);
5895   if (ret->type != 'U')
5896     ret->value = symbol->value + symbol->section->vma;
5897   else
5898     ret->value = 0;
5899   ret->name = symbol->name;
5900 }
5901 
5902 /* Count the number of symbols in the archive symbol table.  Necessary
5903    so that we can allocate space for all the carsyms at once.  */
5904 
5905 static bfd_boolean
5906 som_bfd_count_ar_symbols (bfd *abfd,
5907 			  struct som_lst_header *lst_header,
5908 			  symindex *count)
5909 {
5910   unsigned int i;
5911   unsigned char *hash_table;
5912   size_t amt;
5913   file_ptr lst_filepos;
5914 
5915   lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
5916 
5917   /* Read in the hash table.  The hash table is an array of 32-bit
5918      file offsets which point to the hash chains.  */
5919   if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt))
5920     {
5921       bfd_set_error (bfd_error_file_too_big);
5922       return FALSE;
5923     }
5924   hash_table = _bfd_malloc_and_read (abfd, amt, amt);
5925   if (hash_table == NULL && lst_header->hash_size != 0)
5926     goto error_return;
5927 
5928   /* Don't forget to initialize the counter!  */
5929   *count = 0;
5930 
5931   /* Walk each chain counting the number of symbols found on that particular
5932      chain.  */
5933   for (i = 0; i < lst_header->hash_size; i++)
5934     {
5935       struct som_external_lst_symbol_record ext_lst_symbol;
5936       unsigned int hash_val = bfd_getb32 (hash_table + 4 * i);
5937 
5938       /* An empty chain has zero as it's file offset.  */
5939       if (hash_val == 0)
5940 	continue;
5941 
5942       /* Seek to the first symbol in this hash chain.  */
5943       if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0)
5944 	goto error_return;
5945 
5946       /* Read in this symbol and update the counter.  */
5947       amt = sizeof (ext_lst_symbol);
5948       if (bfd_bread ((void *) &ext_lst_symbol, amt, abfd) != amt)
5949 	goto error_return;
5950 
5951       (*count)++;
5952 
5953       /* Now iterate through the rest of the symbols on this chain.  */
5954       while (1)
5955 	{
5956 	  unsigned int next_entry = bfd_getb32 (ext_lst_symbol.next_entry);
5957 
5958 	  if (next_entry == 0)
5959 	    break;
5960 
5961 	  /* Assume symbols on a chain are in increasing file offset
5962 	     order.  Otherwise we can loop here with fuzzed input.  */
5963 	  if (next_entry < hash_val + sizeof (ext_lst_symbol))
5964 	    {
5965 	      bfd_set_error (bfd_error_bad_value);
5966 	      goto error_return;
5967 	    }
5968 	  hash_val = next_entry;
5969 
5970 	  /* Seek to the next symbol.  */
5971 	  if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
5972 	    goto error_return;
5973 
5974 	  /* Read the symbol in 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     }
5982   free (hash_table);
5983   return TRUE;
5984 
5985  error_return:
5986   free (hash_table);
5987   return FALSE;
5988 }
5989 
5990 /* Fill in the canonical archive symbols (SYMS) from the archive described
5991    by ABFD and LST_HEADER.  */
5992 
5993 static bfd_boolean
5994 som_bfd_fill_in_ar_symbols (bfd *abfd,
5995 			    struct som_lst_header *lst_header,
5996 			    carsym **syms)
5997 {
5998   unsigned int i;
5999   carsym *set = syms[0];
6000   unsigned char *hash_table;
6001   struct som_external_som_entry *som_dict = NULL;
6002   size_t amt;
6003   file_ptr lst_filepos;
6004   unsigned int string_loc;
6005 
6006   lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
6007 
6008   /* Read in the hash table.  The has table is an array of 32bit file offsets
6009      which point to the hash chains.  */
6010   if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt))
6011     {
6012       bfd_set_error (bfd_error_file_too_big);
6013       return FALSE;
6014     }
6015   hash_table = _bfd_malloc_and_read (abfd, amt, amt);
6016   if (hash_table == NULL && lst_header->hash_size != 0)
6017     goto error_return;
6018 
6019   /* Seek to and read in the SOM dictionary.  We will need this to fill
6020      in the carsym's filepos field.  */
6021   if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0)
6022     goto error_return;
6023 
6024   if (_bfd_mul_overflow (lst_header->module_count,
6025 			 sizeof (struct som_external_som_entry), &amt))
6026     {
6027       bfd_set_error (bfd_error_file_too_big);
6028       goto error_return;
6029     }
6030   som_dict = (struct som_external_som_entry *)
6031     _bfd_malloc_and_read (abfd, amt, amt);
6032   if (som_dict == NULL && lst_header->module_count != 0)
6033     goto error_return;
6034 
6035   string_loc = lst_header->string_loc;
6036 
6037   /* Walk each chain filling in the carsyms as we go along.  */
6038   for (i = 0; i < lst_header->hash_size; i++)
6039     {
6040       struct som_external_lst_symbol_record lst_symbol;
6041       unsigned int hash_val;
6042       size_t len;
6043       unsigned char ext_len[4];
6044       char *name;
6045       unsigned int ndx;
6046 
6047       /* An empty chain has zero as it's file offset.  */
6048       hash_val = bfd_getb32 (hash_table + 4 * i);
6049       if (hash_val == 0)
6050 	continue;
6051 
6052       /* Seek to and read the first symbol on the chain.  */
6053       if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0)
6054 	goto error_return;
6055 
6056       amt = sizeof (lst_symbol);
6057       if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
6058 	goto error_return;
6059 
6060       /* Get the name of the symbol, first get the length which is stored
6061 	 as a 32bit integer just before the symbol.
6062 
6063 	 One might ask why we don't just read in the entire string table
6064 	 and index into it.  Well, according to the SOM ABI the string
6065 	 index can point *anywhere* in the archive to save space, so just
6066 	 using the string table would not be safe.  */
6067       if (bfd_seek (abfd, (lst_filepos + string_loc
6068 			   + bfd_getb32 (lst_symbol.name) - 4), SEEK_SET) != 0)
6069 	goto error_return;
6070 
6071       if (bfd_bread (&ext_len, (bfd_size_type) 4, abfd) != 4)
6072 	goto error_return;
6073       len = bfd_getb32 (ext_len);
6074 
6075       /* Allocate space for the name and null terminate it too.  */
6076       if (len == (size_t) -1)
6077 	{
6078 	  bfd_set_error (bfd_error_no_memory);
6079 	  goto error_return;
6080 	}
6081       name = (char *) _bfd_alloc_and_read (abfd, len + 1, len);
6082       if (!name)
6083 	goto error_return;
6084       name[len] = 0;
6085       set->name = name;
6086 
6087       /* Fill in the file offset.  Note that the "location" field points
6088 	 to the SOM itself, not the ar_hdr in front of it.  */
6089       ndx = bfd_getb32 (lst_symbol.som_index);
6090       if (ndx >= lst_header->module_count)
6091 	{
6092 	  bfd_set_error (bfd_error_bad_value);
6093 	  goto error_return;
6094 	}
6095       set->file_offset
6096 	= bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr);
6097 
6098       /* Go to the next symbol.  */
6099       set++;
6100 
6101       /* Iterate through the rest of the chain.  */
6102       while (1)
6103 	{
6104 	  unsigned int next_entry = bfd_getb32 (lst_symbol.next_entry);
6105 
6106 	  if (next_entry == 0)
6107 	    break;
6108 
6109 	  /* Seek to the next symbol and read it in.  */
6110 	  if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
6111 	    goto error_return;
6112 
6113 	  amt = sizeof (lst_symbol);
6114 	  if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
6115 	    goto error_return;
6116 
6117 	  /* Seek to the name length & string and read them in.  */
6118 	  if (bfd_seek (abfd, lst_filepos + string_loc
6119 			+ bfd_getb32 (lst_symbol.name) - 4, SEEK_SET) != 0)
6120 	    goto error_return;
6121 
6122 	  if (bfd_bread (&ext_len, (bfd_size_type) 4, abfd) != 4)
6123 	    goto error_return;
6124 	  len = bfd_getb32 (ext_len);
6125 
6126 	  /* Allocate space for the name and null terminate it too.  */
6127 	  if (len == (size_t) -1)
6128 	    {
6129 	      bfd_set_error (bfd_error_no_memory);
6130 	      goto error_return;
6131 	    }
6132 	  name = (char *) _bfd_alloc_and_read (abfd, len + 1, len);
6133 	  if (!name)
6134 	    goto error_return;
6135 	  name[len] = 0;
6136 	  set->name = name;
6137 
6138 	  /* Fill in the file offset.  Note that the "location" field points
6139 	     to the SOM itself, not the ar_hdr in front of it.  */
6140 	  ndx = bfd_getb32 (lst_symbol.som_index);
6141 	  if (ndx >= lst_header->module_count)
6142 	    {
6143 	      bfd_set_error (bfd_error_bad_value);
6144 	      goto error_return;
6145 	    }
6146 	  set->file_offset
6147 	    = bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr);
6148 
6149 	  /* Go on to the next symbol.  */
6150 	  set++;
6151 	}
6152     }
6153   /* If we haven't died by now, then we successfully read the entire
6154      archive symbol table.  */
6155   free (hash_table);
6156   free (som_dict);
6157   return TRUE;
6158 
6159  error_return:
6160   free (hash_table);
6161   free (som_dict);
6162   return FALSE;
6163 }
6164 
6165 /* Read in the LST from the archive.  */
6166 
6167 static bfd_boolean
6168 som_slurp_armap (bfd *abfd)
6169 {
6170   struct som_external_lst_header ext_lst_header;
6171   struct som_lst_header lst_header;
6172   struct ar_hdr ar_header;
6173   unsigned int parsed_size;
6174   struct artdata *ardata = bfd_ardata (abfd);
6175   char nextname[17];
6176   size_t amt = 16;
6177   int i = bfd_bread ((void *) nextname, amt, abfd);
6178 
6179   /* Special cases.  */
6180   if (i == 0)
6181     return TRUE;
6182   if (i != 16)
6183     return FALSE;
6184 
6185   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
6186     return FALSE;
6187 
6188   /* For archives without .o files there is no symbol table.  */
6189   if (! CONST_STRNEQ (nextname, "/               "))
6190     {
6191       abfd->has_armap = FALSE;
6192       return TRUE;
6193     }
6194 
6195   /* Read in and sanity check the archive header.  */
6196   amt = sizeof (struct ar_hdr);
6197   if (bfd_bread ((void *) &ar_header, amt, abfd) != amt)
6198     return FALSE;
6199 
6200   if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
6201     {
6202       bfd_set_error (bfd_error_malformed_archive);
6203       return FALSE;
6204     }
6205 
6206   /* How big is the archive symbol table entry?  */
6207   errno = 0;
6208   parsed_size = strtol (ar_header.ar_size, NULL, 10);
6209   if (errno != 0)
6210     {
6211       bfd_set_error (bfd_error_malformed_archive);
6212       return FALSE;
6213     }
6214 
6215   /* Save off the file offset of the first real user data.  */
6216   ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
6217 
6218   /* Read in the library symbol table.  We'll make heavy use of this
6219      in just a minute.  */
6220   amt = sizeof (struct som_external_lst_header);
6221   if (bfd_bread ((void *) &ext_lst_header, amt, abfd) != amt)
6222     return FALSE;
6223 
6224   som_swap_lst_header_in (&ext_lst_header, &lst_header);
6225 
6226   /* Sanity check.  */
6227   if (lst_header.a_magic != LIBMAGIC)
6228     {
6229       bfd_set_error (bfd_error_malformed_archive);
6230       return FALSE;
6231     }
6232 
6233   /* Count the number of symbols in the library symbol table.  */
6234   if (! som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count))
6235     return FALSE;
6236 
6237   /* Get back to the start of the library symbol table.  */
6238   if (bfd_seek (abfd, (ardata->first_file_filepos - parsed_size
6239 		       + sizeof (struct som_external_lst_header)),
6240 		SEEK_SET) != 0)
6241     return FALSE;
6242 
6243   /* Initialize the cache and allocate space for the library symbols.  */
6244   ardata->cache = 0;
6245   if (_bfd_mul_overflow (ardata->symdef_count, sizeof (carsym), &amt))
6246     {
6247       bfd_set_error (bfd_error_file_too_big);
6248       return FALSE;
6249     }
6250   ardata->symdefs = bfd_alloc (abfd, amt);
6251   if (!ardata->symdefs)
6252     return FALSE;
6253 
6254   /* Now fill in the canonical archive symbols.  */
6255   if (! som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs))
6256     return FALSE;
6257 
6258   /* Seek back to the "first" file in the archive.  Note the "first"
6259      file may be the extended name table.  */
6260   if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) != 0)
6261     return FALSE;
6262 
6263   /* Notify the generic archive code that we have a symbol map.  */
6264   abfd->has_armap = TRUE;
6265   return TRUE;
6266 }
6267 
6268 /* Begin preparing to write a SOM library symbol table.
6269 
6270    As part of the prep work we need to determine the number of symbols
6271    and the size of the associated string section.  */
6272 
6273 static bfd_boolean
6274 som_bfd_prep_for_ar_write (bfd *abfd,
6275 			   unsigned int *num_syms,
6276 			   unsigned int *stringsize)
6277 {
6278   bfd *curr_bfd = abfd->archive_head;
6279 
6280   /* Some initialization.  */
6281   *num_syms = 0;
6282   *stringsize = 0;
6283 
6284   /* Iterate over each BFD within this archive.  */
6285   while (curr_bfd != NULL)
6286     {
6287       unsigned int curr_count, i;
6288       som_symbol_type *sym;
6289 
6290       /* Don't bother for non-SOM objects.  */
6291       if (curr_bfd->format != bfd_object
6292 	  || curr_bfd->xvec->flavour != bfd_target_som_flavour)
6293 	{
6294 	  curr_bfd = curr_bfd->archive_next;
6295 	  continue;
6296 	}
6297 
6298       /* Make sure the symbol table has been read, then snag a pointer
6299 	 to it.  It's a little slimey to grab the symbols via obj_som_symtab,
6300 	 but doing so avoids allocating lots of extra memory.  */
6301       if (! som_slurp_symbol_table (curr_bfd))
6302 	return FALSE;
6303 
6304       sym = obj_som_symtab (curr_bfd);
6305       curr_count = bfd_get_symcount (curr_bfd);
6306 
6307       /* Examine each symbol to determine if it belongs in the
6308 	 library symbol table.  */
6309       for (i = 0; i < curr_count; i++, sym++)
6310 	{
6311 	  struct som_misc_symbol_info info;
6312 
6313 	  /* Derive SOM information from the BFD symbol.  */
6314 	  som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
6315 
6316 	  /* Should we include this symbol?  */
6317 	  if (info.symbol_type == ST_NULL
6318 	      || info.symbol_type == ST_SYM_EXT
6319 	      || info.symbol_type == ST_ARG_EXT)
6320 	    continue;
6321 
6322 	  /* Only global symbols and unsatisfied commons.  */
6323 	  if (info.symbol_scope != SS_UNIVERSAL
6324 	      && info.symbol_type != ST_STORAGE)
6325 	    continue;
6326 
6327 	  /* Do no include undefined symbols.  */
6328 	  if (bfd_is_und_section (sym->symbol.section))
6329 	    continue;
6330 
6331 	  /* Bump the various counters, being careful to honor
6332 	     alignment considerations in the string table.  */
6333 	  (*num_syms)++;
6334 	  *stringsize += strlen (sym->symbol.name) + 5;
6335 	  while (*stringsize % 4)
6336 	    (*stringsize)++;
6337 	}
6338 
6339       curr_bfd = curr_bfd->archive_next;
6340     }
6341   return TRUE;
6342 }
6343 
6344 /* Hash a symbol name based on the hashing algorithm presented in the
6345    SOM ABI.  */
6346 
6347 static unsigned int
6348 som_bfd_ar_symbol_hash (asymbol *symbol)
6349 {
6350   unsigned int len = strlen (symbol->name);
6351 
6352   /* Names with length 1 are special.  */
6353   if (len == 1)
6354     return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
6355 
6356   return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
6357 	  | (symbol->name[len - 2] << 8) | symbol->name[len - 1];
6358 }
6359 
6360 /* Do the bulk of the work required to write the SOM library
6361    symbol table.  */
6362 
6363 static bfd_boolean
6364 som_bfd_ar_write_symbol_stuff (bfd *abfd,
6365 			       unsigned int nsyms,
6366 			       unsigned int string_size,
6367 			       struct som_external_lst_header lst,
6368 			       unsigned elength)
6369 {
6370   char *strings = NULL, *p;
6371   struct som_external_lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
6372   bfd *curr_bfd;
6373   unsigned char *hash_table = NULL;
6374   struct som_external_som_entry *som_dict = NULL;
6375   struct som_external_lst_symbol_record **last_hash_entry = NULL;
6376   unsigned int curr_som_offset, som_index = 0;
6377   size_t amt;
6378   unsigned int module_count;
6379   unsigned int hash_size;
6380 
6381   hash_size = bfd_getb32 (lst.hash_size);
6382   if (_bfd_mul_overflow (hash_size, 4, &amt))
6383     {
6384       bfd_set_error (bfd_error_no_memory);
6385       return FALSE;
6386     }
6387   hash_table = bfd_zmalloc (amt);
6388   if (hash_table == NULL && hash_size != 0)
6389     goto error_return;
6390 
6391   module_count = bfd_getb32 (lst.module_count);
6392   if (_bfd_mul_overflow (module_count,
6393 			 sizeof (struct som_external_som_entry), &amt))
6394     {
6395       bfd_set_error (bfd_error_no_memory);
6396       goto error_return;
6397     }
6398   som_dict = bfd_zmalloc (amt);
6399   if (som_dict == NULL && module_count != 0)
6400     goto error_return;
6401 
6402   if (_bfd_mul_overflow (hash_size,
6403 			 sizeof (struct som_external_lst_symbol_record *),
6404 			 &amt))
6405     {
6406       bfd_set_error (bfd_error_no_memory);
6407       goto error_return;
6408     }
6409   last_hash_entry = bfd_zmalloc (amt);
6410   if (last_hash_entry == NULL && hash_size != 0)
6411     goto error_return;
6412 
6413   /* Symbols have som_index fields, so we have to keep track of the
6414      index of each SOM in the archive.
6415 
6416      The SOM dictionary has (among other things) the absolute file
6417      position for the SOM which a particular dictionary entry
6418      describes.  We have to compute that information as we iterate
6419      through the SOMs/symbols.  */
6420   som_index = 0;
6421 
6422   /* We add in the size of the archive header twice as the location
6423      in the SOM dictionary is the actual offset of the SOM, not the
6424      archive header before the SOM.  */
6425   curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + bfd_getb32 (lst.file_end);
6426 
6427   /* Make room for the archive header and the contents of the
6428      extended string table.  Note that elength includes the size
6429      of the archive header for the extended name table!  */
6430   if (elength)
6431     curr_som_offset += elength;
6432 
6433   /* Make sure we're properly aligned.  */
6434   curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
6435 
6436   /* FIXME should be done with buffers just like everything else...  */
6437   if (_bfd_mul_overflow (nsyms,
6438 			 sizeof (struct som_external_lst_symbol_record), &amt))
6439     {
6440       bfd_set_error (bfd_error_no_memory);
6441       goto error_return;
6442     }
6443   lst_syms = bfd_malloc (amt);
6444   if (lst_syms == NULL && nsyms != 0)
6445     goto error_return;
6446   strings = bfd_malloc (string_size);
6447   if (strings == NULL && string_size != 0)
6448     goto error_return;
6449 
6450   p = strings;
6451   curr_lst_sym = lst_syms;
6452 
6453   curr_bfd = abfd->archive_head;
6454   while (curr_bfd != NULL)
6455     {
6456       unsigned int curr_count, i;
6457       som_symbol_type *sym;
6458 
6459       /* Don't bother for non-SOM objects.  */
6460       if (curr_bfd->format != bfd_object
6461 	  || curr_bfd->xvec->flavour != bfd_target_som_flavour)
6462 	{
6463 	  curr_bfd = curr_bfd->archive_next;
6464 	  continue;
6465 	}
6466 
6467       /* Make sure the symbol table has been read, then snag a pointer
6468 	 to it.  It's a little slimey to grab the symbols via obj_som_symtab,
6469 	 but doing so avoids allocating lots of extra memory.  */
6470       if (! som_slurp_symbol_table (curr_bfd))
6471 	goto error_return;
6472 
6473       sym = obj_som_symtab (curr_bfd);
6474       curr_count = bfd_get_symcount (curr_bfd);
6475 
6476       for (i = 0; i < curr_count; i++, sym++)
6477 	{
6478 	  struct som_misc_symbol_info info;
6479 	  struct som_external_lst_symbol_record *last;
6480 	  unsigned int symbol_pos;
6481 	  unsigned int slen;
6482 	  unsigned int symbol_key;
6483 	  unsigned int flags;
6484 
6485 	  /* Derive SOM information from the BFD symbol.  */
6486 	  som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
6487 
6488 	  /* Should we include this symbol?  */
6489 	  if (info.symbol_type == ST_NULL
6490 	      || info.symbol_type == ST_SYM_EXT
6491 	      || info.symbol_type == ST_ARG_EXT)
6492 	    continue;
6493 
6494 	  /* Only global symbols and unsatisfied commons.  */
6495 	  if (info.symbol_scope != SS_UNIVERSAL
6496 	      && info.symbol_type != ST_STORAGE)
6497 	    continue;
6498 
6499 	  /* Do no include undefined symbols.  */
6500 	  if (bfd_is_und_section (sym->symbol.section))
6501 	    continue;
6502 
6503 	  /* If this is the first symbol from this SOM, then update
6504 	     the SOM dictionary too.  */
6505 	  if (bfd_getb32 (som_dict[som_index].location) == 0)
6506 	    {
6507 	      bfd_putb32 (curr_som_offset, som_dict[som_index].location);
6508 	      bfd_putb32 (arelt_size (curr_bfd), som_dict[som_index].length);
6509 	    }
6510 
6511 	  symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
6512 
6513 	  /* Fill in the lst symbol record.  */
6514 	  flags = 0;
6515 	  if (info.secondary_def)
6516 	    flags |= LST_SYMBOL_SECONDARY_DEF;
6517 	  flags |= info.symbol_type << LST_SYMBOL_SYMBOL_TYPE_SH;
6518 	  flags |= info.symbol_scope << LST_SYMBOL_SYMBOL_SCOPE_SH;
6519 	  if (bfd_is_com_section (sym->symbol.section))
6520 	    flags |= LST_SYMBOL_IS_COMMON;
6521 	  if (info.dup_common)
6522 	    flags |= LST_SYMBOL_DUP_COMMON;
6523 	  flags |= 3 << LST_SYMBOL_XLEAST_SH;
6524 	  flags |= info.arg_reloc << LST_SYMBOL_ARG_RELOC_SH;
6525 	  bfd_putb32 (flags, curr_lst_sym->flags);
6526 	  bfd_putb32 (p - strings + 4, curr_lst_sym->name);
6527 	  bfd_putb32 (0, curr_lst_sym->qualifier_name);
6528 	  bfd_putb32 (info.symbol_info, curr_lst_sym->symbol_info);
6529 	  bfd_putb32 (info.symbol_value | info.priv_level,
6530 		      curr_lst_sym->symbol_value);
6531 	  bfd_putb32 (0, curr_lst_sym->symbol_descriptor);
6532 	  curr_lst_sym->reserved = 0;
6533 	  bfd_putb32 (som_index, curr_lst_sym->som_index);
6534 	  bfd_putb32 (symbol_key, curr_lst_sym->symbol_key);
6535 	  bfd_putb32 (0, curr_lst_sym->next_entry);
6536 
6537 	  /* Insert into the hash table.  */
6538 	  symbol_pos =
6539 	    (curr_lst_sym - lst_syms)
6540 	    * sizeof (struct som_external_lst_symbol_record)
6541 	    + hash_size * 4
6542 	    + module_count * sizeof (struct som_external_som_entry)
6543 	    + sizeof (struct som_external_lst_header);
6544 	  last = last_hash_entry[symbol_key % hash_size];
6545 	  if (last != NULL)
6546 	    {
6547 	      /* There is already something at the head of this hash chain,
6548 		 so tack this symbol onto the end of the chain.  */
6549 	      bfd_putb32 (symbol_pos, last->next_entry);
6550 	    }
6551 	  else
6552 	    /* First entry in this hash chain.  */
6553 	    bfd_putb32 (symbol_pos, hash_table + 4 * (symbol_key % hash_size));
6554 
6555 	  /* Keep track of the last symbol we added to this chain so we can
6556 	     easily update its next_entry pointer.  */
6557 	  last_hash_entry[symbol_key % hash_size] = curr_lst_sym;
6558 
6559 	  /* Update the string table.  */
6560 	  slen = strlen (sym->symbol.name);
6561 	  bfd_put_32 (abfd, slen, p);
6562 	  p += 4;
6563 	  slen++; /* Nul terminator.  */
6564 	  memcpy (p, sym->symbol.name, slen);
6565 	  p += slen;
6566 	  while (slen % 4)
6567 	    {
6568 	      bfd_put_8 (abfd, 0, p);
6569 	      p++;
6570 	      slen++;
6571 	    }
6572 	  BFD_ASSERT (p <= strings + string_size);
6573 
6574 	  /* Head to the next symbol.  */
6575 	  curr_lst_sym++;
6576 	}
6577 
6578       /* Keep track of where each SOM will finally reside; then look
6579 	 at the next BFD.  */
6580       curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
6581 
6582       /* A particular object in the archive may have an odd length; the
6583 	 linker requires objects begin on an even boundary.  So round
6584 	 up the current offset as necessary.  */
6585       curr_som_offset = (curr_som_offset + 0x1) &~ (unsigned) 1;
6586       curr_bfd = curr_bfd->archive_next;
6587       som_index++;
6588     }
6589 
6590   /* Now scribble out the hash table.  */
6591   amt = (size_t) hash_size * 4;
6592   if (bfd_bwrite ((void *) hash_table, amt, abfd) != amt)
6593     goto error_return;
6594 
6595   /* Then the SOM dictionary.  */
6596   amt = (size_t) module_count * sizeof (struct som_external_som_entry);
6597   if (bfd_bwrite ((void *) som_dict, amt, abfd) != amt)
6598     goto error_return;
6599 
6600   /* The library symbols.  */
6601   amt = (size_t) nsyms * sizeof (struct som_external_lst_symbol_record);
6602   if (bfd_bwrite ((void *) lst_syms, amt, abfd) != amt)
6603     goto error_return;
6604 
6605   /* And finally the strings.  */
6606   amt = string_size;
6607   if (bfd_bwrite ((void *) strings, amt, abfd) != amt)
6608     goto error_return;
6609 
6610   free (hash_table);
6611   free (som_dict);
6612   free (last_hash_entry);
6613   free (lst_syms);
6614   free (strings);
6615   return TRUE;
6616 
6617  error_return:
6618   free (hash_table);
6619   free (som_dict);
6620   free (last_hash_entry);
6621   free (lst_syms);
6622   free (strings);
6623 
6624   return FALSE;
6625 }
6626 
6627 /* Write out the LST for the archive.
6628 
6629    You'll never believe this is really how armaps are handled in SOM...  */
6630 
6631 static bfd_boolean
6632 som_write_armap (bfd *abfd,
6633 		 unsigned int elength,
6634 		 struct orl *map ATTRIBUTE_UNUSED,
6635 		 unsigned int orl_count ATTRIBUTE_UNUSED,
6636 		 int stridx ATTRIBUTE_UNUSED)
6637 {
6638   bfd *curr_bfd;
6639   struct stat statbuf;
6640   unsigned int i, lst_size, nsyms, stringsize;
6641   struct ar_hdr hdr;
6642   struct som_external_lst_header lst;
6643   unsigned char *p;
6644   size_t amt;
6645   unsigned int csum;
6646   unsigned int module_count;
6647 
6648   /* We'll use this for the archive's date and mode later.  */
6649   if (stat (bfd_get_filename (abfd), &statbuf) != 0)
6650     {
6651       bfd_set_error (bfd_error_system_call);
6652       return FALSE;
6653     }
6654   /* Fudge factor.  */
6655   bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
6656 
6657   /* Account for the lst header first.  */
6658   lst_size = sizeof (struct som_external_lst_header);
6659 
6660   /* Start building the LST header.  */
6661   /* FIXME:  Do we need to examine each element to determine the
6662      largest id number?  */
6663   bfd_putb16 (CPU_PA_RISC1_0, &lst.system_id);
6664   bfd_putb16 (LIBMAGIC, &lst.a_magic);
6665   bfd_putb32 (VERSION_ID, &lst.version_id);
6666   bfd_putb32 (0, &lst.file_time.secs);
6667   bfd_putb32 (0, &lst.file_time.nanosecs);
6668 
6669   bfd_putb32 (lst_size, &lst.hash_loc);
6670   bfd_putb32 (SOM_LST_HASH_SIZE, &lst.hash_size);
6671 
6672   /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets.  */
6673   lst_size += 4 * SOM_LST_HASH_SIZE;
6674 
6675   /* We need to count the number of SOMs in this archive.  */
6676   curr_bfd = abfd->archive_head;
6677   module_count = 0;
6678   while (curr_bfd != NULL)
6679     {
6680       /* Only true SOM objects count.  */
6681       if (curr_bfd->format == bfd_object
6682 	  && curr_bfd->xvec->flavour == bfd_target_som_flavour)
6683 	module_count++;
6684       curr_bfd = curr_bfd->archive_next;
6685     }
6686   bfd_putb32 (module_count, &lst.module_count);
6687   bfd_putb32 (module_count, &lst.module_limit);
6688   bfd_putb32 (lst_size, &lst.dir_loc);
6689   lst_size += sizeof (struct som_external_som_entry) * module_count;
6690 
6691   /* We don't support import/export tables, auxiliary headers,
6692      or free lists yet.  Make the linker work a little harder
6693      to make our life easier.  */
6694 
6695   bfd_putb32 (0, &lst.export_loc);
6696   bfd_putb32 (0, &lst.export_count);
6697   bfd_putb32 (0, &lst.import_loc);
6698   bfd_putb32 (0, &lst.aux_loc);
6699   bfd_putb32 (0, &lst.aux_size);
6700 
6701   /* Count how many symbols we will have on the hash chains and the
6702      size of the associated string table.  */
6703   if (! som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize))
6704     return FALSE;
6705 
6706   lst_size += sizeof (struct som_external_lst_symbol_record) * nsyms;
6707 
6708   /* For the string table.  One day we might actually use this info
6709      to avoid small seeks/reads when reading archives.  */
6710   bfd_putb32 (lst_size, &lst.string_loc);
6711   bfd_putb32 (stringsize, &lst.string_size);
6712   lst_size += stringsize;
6713 
6714   /* SOM ABI says this must be zero.  */
6715   bfd_putb32 (0, &lst.free_list);
6716   bfd_putb32 (lst_size, &lst.file_end);
6717 
6718   /* Compute the checksum.  Must happen after the entire lst header
6719      has filled in.  */
6720   p = (unsigned char *) &lst;
6721   csum = 0;
6722   for (i = 0; i < sizeof (struct som_external_lst_header) - sizeof (int);
6723        i += 4)
6724     csum ^= bfd_getb32 (&p[i]);
6725   bfd_putb32 (csum, &lst.checksum);
6726 
6727   sprintf (hdr.ar_name, "/              ");
6728   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%-12ld",
6729 		    bfd_ardata (abfd)->armap_timestamp);
6730   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld",
6731 		    statbuf.st_uid);
6732   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld",
6733 		    statbuf.st_gid);
6734   _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-8o",
6735 		    (unsigned int)statbuf.st_mode);
6736   _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10d",
6737 		    (int) lst_size);
6738   hdr.ar_fmag[0] = '`';
6739   hdr.ar_fmag[1] = '\012';
6740 
6741   /* Turn any nulls into spaces.  */
6742   for (i = 0; i < sizeof (struct ar_hdr); i++)
6743     if (((char *) (&hdr))[i] == '\0')
6744       (((char *) (&hdr))[i]) = ' ';
6745 
6746   /* Scribble out the ar header.  */
6747   amt = sizeof (struct ar_hdr);
6748   if (bfd_bwrite ((void *) &hdr, amt, abfd) != amt)
6749     return FALSE;
6750 
6751   /* Now scribble out the lst header.  */
6752   amt = sizeof (struct som_external_lst_header);
6753   if (bfd_bwrite ((void *) &lst, amt, abfd) != amt)
6754     return FALSE;
6755 
6756   /* Build and write the armap.  */
6757   if (!som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength))
6758     return FALSE;
6759 
6760   /* Done.  */
6761   return TRUE;
6762 }
6763 
6764 /* Free all information we have cached for this BFD.  We can always
6765    read it again later if we need it.  */
6766 
6767 static bfd_boolean
6768 som_bfd_free_cached_info (bfd *abfd)
6769 {
6770   if (bfd_get_format (abfd) == bfd_object)
6771     {
6772       asection *o;
6773 
6774 #define FREE(x) do { free (x); x = NULL; } while (0)
6775       /* Free the native string and symbol tables.  */
6776       FREE (obj_som_symtab (abfd));
6777       FREE (obj_som_stringtab (abfd));
6778       for (o = abfd->sections; o != NULL; o = o->next)
6779 	{
6780 	  /* Free the native relocations.  */
6781 	  o->reloc_count = (unsigned) -1;
6782 	  FREE (som_section_data (o)->reloc_stream);
6783 	  /* Do not free the generic relocations as they are objalloc'ed.  */
6784 	}
6785 #undef FREE
6786     }
6787 
6788   return _bfd_generic_close_and_cleanup (abfd);
6789 }
6790 
6791 /* End of miscellaneous support functions.  */
6792 
6793 /* Linker support functions.  */
6794 
6795 static bfd_boolean
6796 som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
6797 {
6798   return som_is_subspace (sec) && sec->size > 240000;
6799 }
6800 
6801 #define som_find_line				_bfd_nosymbols_find_line
6802 #define som_get_symbol_version_string		_bfd_nosymbols_get_symbol_version_string
6803 #define	som_close_and_cleanup			som_bfd_free_cached_info
6804 #define som_read_ar_hdr				_bfd_generic_read_ar_hdr
6805 #define som_write_ar_hdr			_bfd_generic_write_ar_hdr
6806 #define som_openr_next_archived_file		bfd_generic_openr_next_archived_file
6807 #define som_get_elt_at_index			_bfd_generic_get_elt_at_index
6808 #define som_generic_stat_arch_elt		bfd_generic_stat_arch_elt
6809 #define som_truncate_arname			bfd_bsd_truncate_arname
6810 #define som_slurp_extended_name_table		_bfd_slurp_extended_name_table
6811 #define som_construct_extended_name_table	_bfd_archive_coff_construct_extended_name_table
6812 #define som_update_armap_timestamp		_bfd_bool_bfd_true
6813 #define som_bfd_is_target_special_symbol        _bfd_bool_bfd_asymbol_false
6814 #define som_get_lineno				_bfd_nosymbols_get_lineno
6815 #define som_bfd_make_debug_symbol		_bfd_nosymbols_bfd_make_debug_symbol
6816 #define som_read_minisymbols			_bfd_generic_read_minisymbols
6817 #define som_minisymbol_to_symbol		_bfd_generic_minisymbol_to_symbol
6818 #define som_get_section_contents_in_window	_bfd_generic_get_section_contents_in_window
6819 #define som_bfd_get_relocated_section_contents	bfd_generic_get_relocated_section_contents
6820 #define som_bfd_relax_section			bfd_generic_relax_section
6821 #define som_bfd_link_hash_table_create		_bfd_generic_link_hash_table_create
6822 #define som_bfd_link_add_symbols		_bfd_generic_link_add_symbols
6823 #define som_bfd_link_just_syms			_bfd_generic_link_just_syms
6824 #define som_bfd_copy_link_hash_symbol_type \
6825   _bfd_generic_copy_link_hash_symbol_type
6826 #define som_bfd_final_link			_bfd_generic_final_link
6827 #define som_bfd_gc_sections			bfd_generic_gc_sections
6828 #define som_bfd_lookup_section_flags		bfd_generic_lookup_section_flags
6829 #define som_bfd_merge_sections			bfd_generic_merge_sections
6830 #define som_bfd_is_group_section		bfd_generic_is_group_section
6831 #define som_bfd_group_name			bfd_generic_group_name
6832 #define som_bfd_discard_group			bfd_generic_discard_group
6833 #define som_section_already_linked		_bfd_generic_section_already_linked
6834 #define som_bfd_define_common_symbol		bfd_generic_define_common_symbol
6835 #define som_bfd_link_hide_symbol		_bfd_generic_link_hide_symbol
6836 #define som_bfd_define_start_stop		bfd_generic_define_start_stop
6837 #define som_bfd_merge_private_bfd_data		_bfd_generic_bfd_merge_private_bfd_data
6838 #define som_bfd_copy_private_header_data	_bfd_generic_bfd_copy_private_header_data
6839 #define som_bfd_set_private_flags		_bfd_generic_bfd_set_private_flags
6840 #define som_find_inliner_info			_bfd_nosymbols_find_inliner_info
6841 #define som_bfd_link_check_relocs		_bfd_generic_link_check_relocs
6842 #define som_set_reloc				_bfd_generic_set_reloc
6843 
6844 const bfd_target hppa_som_vec =
6845 {
6846   "som",			/* Name.  */
6847   bfd_target_som_flavour,
6848   BFD_ENDIAN_BIG,		/* Target byte order.  */
6849   BFD_ENDIAN_BIG,		/* Target headers byte order.  */
6850   (HAS_RELOC | EXEC_P |		/* Object flags.  */
6851    HAS_LINENO | HAS_DEBUG |
6852    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
6853   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS | SEC_LINK_ONCE
6854    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),		/* Section flags.  */
6855 
6856   /* Leading_symbol_char: is the first char of a user symbol
6857      predictable, and if so what is it.  */
6858   0,
6859   '/',				/* AR_pad_char.  */
6860   14,				/* AR_max_namelen.  */
6861   0,				/* match priority.  */
6862   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6863   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
6864   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
6865   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6866   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
6867   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
6868   {_bfd_dummy_target,
6869    som_object_p,		/* bfd_check_format.  */
6870    bfd_generic_archive_p,
6871    _bfd_dummy_target
6872   },
6873   {
6874     _bfd_bool_bfd_false_error,
6875     som_mkobject,
6876     _bfd_generic_mkarchive,
6877     _bfd_bool_bfd_false_error
6878   },
6879   {
6880     _bfd_bool_bfd_false_error,
6881     som_write_object_contents,
6882     _bfd_write_archive_contents,
6883     _bfd_bool_bfd_false_error,
6884   },
6885 #undef som
6886 
6887   BFD_JUMP_TABLE_GENERIC (som),
6888   BFD_JUMP_TABLE_COPY (som),
6889   BFD_JUMP_TABLE_CORE (_bfd_nocore),
6890   BFD_JUMP_TABLE_ARCHIVE (som),
6891   BFD_JUMP_TABLE_SYMBOLS (som),
6892   BFD_JUMP_TABLE_RELOCS (som),
6893   BFD_JUMP_TABLE_WRITE (som),
6894   BFD_JUMP_TABLE_LINK (som),
6895   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6896 
6897   NULL,
6898 
6899   NULL
6900 };
6901 
6902